Previous 199869 Revisions Next

r20947 Monday 11th February, 2013 at 15:41:23 UTC by smf
Moved some of the saturn code from mame/ into emu/ and made saturn.c & stv.c separately compilable. Still needs work before saturn.c can be moved to mess/ [smf]
[src/emu]emu.mak
[src/emu/machine]scudsp.c* scudsp.h* smpc.c* smpc.h* stvcd.c*
[src/emu/video]stvvdp1.c* stvvdp2.c*
[src/mame]mame.mak
[src/mame/drivers]saturn.c stv.c
[src/mame/includes]stv.h
[src/mame/machine]scudsp.c scudsp.h smpc.c smpc.h stvcd.c
[src/mame/video]stvvdp1.c stvvdp2.c
[src/mess]mess.mak

trunk/src/emu/video/stvvdp1.c
r0r20947
1/*
2
3STV - VDP1
4
5the vdp1 draws to the FRAMEBUFFER which is mapped in memory
6
7Framebuffer todo:
8- finish manual erase
9- add proper framebuffer erase
10- 8 bpp support - now we always draw as 16 bpp, but this is not a problem since
11  VDP2 interprets framebuffer as 8 bpp in these cases
12
13*/
14
15
16#include "emu.h"
17#include "includes/stv.h"
18
19#define VDP1_LOG 0
20
21
22enum { FRAC_SHIFT = 16 };
23
24struct spoint {
25   INT32 x, y;
26   INT32 u, v;
27};
28
29struct shaded_point
30{
31   INT32 x,y;
32   INT32 r,g,b;
33};
34
35#define RGB_R(_color)   (_color & 0x1f)
36#define RGB_G(_color)   ((_color >> 5) & 0x1f)
37#define RGB_B(_color)   ((_color >> 10) & 0x1f)
38
39#define SWAP_INT32(_a,_b) \
40   { \
41      INT32 t; \
42      t = _a; \
43      _a = _b; \
44      _b = t; \
45   }
46
47#define SWAP_INT32PTR(_p1, _p2) \
48   { \
49      INT32 *p; \
50      p = _p1; \
51      _p1 = _p2; \
52      _p2 = p; \
53   }
54
55/*TV Mode Selection Register */
56/*
57   xxxx xxxx xxxx ---- | UNUSED
58   ---- ---- ---- x--- | VBlank Erase/Write (VBE)
59   ---- ---- ---- -xxx | TV Mode (TVM)
60   TV-Mode:
61   This sets the Frame Buffer size,the rotation of the Frame Buffer & the bit width.
62   bit 2 HDTV disable(0)/enable(1)
63   bit 1 non-rotation/rotation(1)
64   bit 0 16(0)/8(1) bits per pixel
65   Size of the Frame Buffer:
66   7 invalid
67   6 invalid
68   5 invalid
69   4 512x256
70   3 512x512
71   2 512x256
72   1 1024x256
73   0 512x256
74*/
75
76/*Frame Buffer Change Mode Register*/
77/*
78   xxxx xxxx xxx- ---- | UNUSED
79   ---- ---- ---x ---- | Even/Odd Coordinate Select Bit (EOS)
80   ---- ---- ---- x--- | Double Interlace Mode (DIE)
81   ---- ---- ---- -x-- | Double Interlace Draw Line (DIL)
82   ---- ---- ---- --x- | Frame Buffer Change Trigger (FCM)
83   ---- ---- ---- ---x | Frame Buffer Change Mode (FCT)
84*/
85#define STV_VDP1_FBCR ((m_vdp1_regs[0x002/2] >> 0)&0xffff)
86#define STV_VDP1_EOS ((STV_VDP1_FBCR & 0x0010) >> 4)
87#define STV_VDP1_DIE ((STV_VDP1_FBCR & 0x0008) >> 3)
88#define STV_VDP1_DIL ((STV_VDP1_FBCR & 0x0004) >> 2)
89#define STV_VDP1_FCM ((STV_VDP1_FBCR & 0x0002) >> 1)
90#define STV_VDP1_FCT ((STV_VDP1_FBCR & 0x0001) >> 0)
91
92/*Plot Trigger Register*/
93/*
94   xxxx xxxx xxxx xx-- | UNUSED
95   ---- ---- ---- --xx | Plot Trigger Mode (PTM)
96
97   Plot Trigger Mode:
98   3 Invalid
99   2 Automatic draw
100   1 VDP1 draw by request
101   0 VDP1 Idle (no access)
102*/
103#define STV_VDP1_PTMR ((m_vdp1_regs[0x004/2])&0xffff)
104#define STV_VDP1_PTM  ((STV_VDP1_PTMR & 0x0003) >> 0)
105#define PTM_0         m_vdp1_regs[0x004/2]&=~0x0001
106
107/*
108    Erase/Write Data Register
109    16 bpp = data
110    8 bpp = erase/write data for even/odd X coordinates
111*/
112#define STV_VDP1_EWDR ((m_vdp1_regs[0x006/2])&0xffff)
113
114/*Erase/Write Upper-Left register*/
115/*
116   x--- ---- ---- ---- | UNUSED
117   -xxx xxx- ---- ---- | X1 register
118   ---- ---x xxxx xxxx | Y1 register
119
120*/
121#define STV_VDP1_EWLR ((m_vdp1_regs[0x008/2])&0xffff)
122#define STV_VDP1_EWLR_X1 ((STV_VDP1_EWLR & 0x7e00) >> 9)
123#define STV_VDP1_EWLR_Y1 ((STV_VDP1_EWLR & 0x01ff) >> 0)
124/*Erase/Write Lower-Right register*/
125/*
126   xxxx xxx- ---- ---- | X3 register
127   ---- ---x xxxx xxxx | Y3 register
128
129*/
130#define STV_VDP1_EWRR ((m_vdp1_regs[0x00a/2])&0xffff)
131#define STV_VDP1_EWRR_X3 ((STV_VDP1_EWRR & 0xfe00) >> 9)
132#define STV_VDP1_EWRR_Y3 ((STV_VDP1_EWRR & 0x01ff) >> 0)
133/*Transfer End Status Register*/
134/*
135   xxxx xxxx xxxx xx-- | UNUSED
136   ---- ---- ---- --x- | CEF
137   ---- ---- ---- ---x | BEF
138
139*/
140#define STV_VDP1_EDSR ((m_vdp1_regs[0x010/2])&0xffff)
141#define STV_VDP1_CEF  (STV_VDP1_EDSR & 2)
142#define STV_VDP1_BEF  (STV_VDP1_EDSR & 1)
143/**/
144
145
146
147READ16_MEMBER( saturn_state::saturn_vdp1_regs_r )
148{
149   //logerror ("cpu %s (PC=%08X) VDP1: Read from Registers, Offset %04x\n", space.device().tag(), space.device().safe_pc(), offset);
150
151   switch(offset)
152   {
153      case 0x02/2:
154         return 0;
155      case 0x10/2:
156         break;
157      case 0x12/2: return m_vdp1.lopr;
158      case 0x14/2: return m_vdp1.copr;
159      /* MODR register, read register for the other VDP1 regs
160         (Shienryu SS version abuses of this during intro) */
161      case 0x16/2:
162         UINT16 modr;
163
164         modr = 0x1000; //vdp1 VER
165         modr |= (STV_VDP1_PTM >> 1) << 8; // PTM1
166         modr |= STV_VDP1_EOS << 7; // EOS
167         modr |= STV_VDP1_DIE << 6; // DIE
168         modr |= STV_VDP1_DIL << 5; // DIL
169         modr |= STV_VDP1_FCM << 4; //FCM
170         modr |= STV_VDP1_VBE << 3; //VBE
171         modr |= STV_VDP1_TVM & 7; //TVM
172
173         return modr;
174      default:
175         if(!space.debugger_access())
176            printf ("cpu %s (PC=%08X) VDP1: Read from Registers, Offset %04x\n", space.device().tag(), space.device().safe_pc(), offset*2);
177         break;
178   }
179
180   return m_vdp1_regs[offset]; //TODO: write-only regs should return open bus or zero
181}
182
183void saturn_state::stv_clear_framebuffer( int which_framebuffer )
184{
185   if ( VDP1_LOG ) logerror( "Clearing %d framebuffer\n", m_vdp1.framebuffer_current_draw );
186   memset( m_vdp1.framebuffer[ which_framebuffer ], m_vdp1.ewdr, 1024 * 256 * sizeof(UINT16) * 2 );
187}
188
189
190void saturn_state::stv_prepare_framebuffers( void )
191{
192   int i,rowsize;
193
194   rowsize = m_vdp1.framebuffer_width;
195   if ( m_vdp1.framebuffer_current_draw == 0 )
196   {
197      for ( i = 0; i < m_vdp1.framebuffer_height; i++ )
198      {
199         m_vdp1.framebuffer_draw_lines[i] = &m_vdp1.framebuffer[0][ i * rowsize ];
200         m_vdp1.framebuffer_display_lines[i] = &m_vdp1.framebuffer[1][ i * rowsize ];
201      }
202      for ( ; i < 512; i++ )
203      {
204         m_vdp1.framebuffer_draw_lines[i] = &m_vdp1.framebuffer[0][0];
205         m_vdp1.framebuffer_display_lines[i] = &m_vdp1.framebuffer[1][0];
206      }
207   }
208   else
209   {
210      for ( i = 0; i < m_vdp1.framebuffer_height; i++ )
211      {
212         m_vdp1.framebuffer_draw_lines[i] = &m_vdp1.framebuffer[1][ i * rowsize ];
213         m_vdp1.framebuffer_display_lines[i] = &m_vdp1.framebuffer[0][ i * rowsize ];
214      }
215      for ( ; i < 512; i++ )
216      {
217         m_vdp1.framebuffer_draw_lines[i] = &m_vdp1.framebuffer[1][0];
218         m_vdp1.framebuffer_display_lines[i] = &m_vdp1.framebuffer[0][0];
219      }
220
221   }
222
223   for ( ; i < 512; i++ )
224   {
225      m_vdp1.framebuffer_draw_lines[i] = &m_vdp1.framebuffer[0][0];
226      m_vdp1.framebuffer_display_lines[i] = &m_vdp1.framebuffer[1][0];
227   }
228
229}
230
231void saturn_state::stv_vdp1_change_framebuffers( void )
232{
233   m_vdp1.framebuffer_current_display ^= 1;
234   m_vdp1.framebuffer_current_draw ^= 1;
235   if ( VDP1_LOG ) logerror( "Changing framebuffers: %d - draw, %d - display\n", m_vdp1.framebuffer_current_draw, m_vdp1.framebuffer_current_display );
236   stv_prepare_framebuffers();
237}
238
239void saturn_state::stv_set_framebuffer_config( void )
240{
241   if ( m_vdp1.framebuffer_mode == STV_VDP1_TVM &&
242         m_vdp1.framebuffer_double_interlace == STV_VDP1_DIE ) return;
243
244   if ( VDP1_LOG ) logerror( "Setting framebuffer config\n" );
245   m_vdp1.framebuffer_mode = STV_VDP1_TVM;
246   m_vdp1.framebuffer_double_interlace = STV_VDP1_DIE;
247   switch( m_vdp1.framebuffer_mode )
248   {
249      case 0: m_vdp1.framebuffer_width = 512; m_vdp1.framebuffer_height = 256; break;
250      case 1: m_vdp1.framebuffer_width = 1024; m_vdp1.framebuffer_height = 256; break;
251      case 2: m_vdp1.framebuffer_width = 512; m_vdp1.framebuffer_height = 256; break;
252      case 3: m_vdp1.framebuffer_width = 512; m_vdp1.framebuffer_height = 512; break;
253      case 4: m_vdp1.framebuffer_width = 512; m_vdp1.framebuffer_height = 256; break;
254      default: logerror( "Invalid framebuffer config %x\n", STV_VDP1_TVM ); m_vdp1.framebuffer_width = 512; m_vdp1.framebuffer_height = 256; break;
255   }
256   if ( STV_VDP1_DIE ) m_vdp1.framebuffer_height *= 2; /* double interlace */
257
258   m_vdp1.framebuffer_current_draw = 0;
259   m_vdp1.framebuffer_current_display = 1;
260   stv_prepare_framebuffers();
261}
262
263WRITE16_MEMBER( saturn_state::saturn_vdp1_regs_w )
264{
265   COMBINE_DATA(&m_vdp1_regs[offset]);
266
267   switch(offset)
268   {
269      case 0x00/2:
270         stv_set_framebuffer_config();
271         if ( VDP1_LOG ) logerror( "VDP1: Access to register TVMR = %1X\n", STV_VDP1_TVMR );
272
273         break;
274      case 0x02/2:
275         stv_set_framebuffer_config();
276         if ( VDP1_LOG ) logerror( "VDP1: Access to register FBCR = %1X\n", STV_VDP1_FBCR );
277         m_vdp1.fbcr_accessed = 1;
278         break;
279      case 0x04/2:
280         if ( VDP1_LOG ) logerror( "VDP1: Access to register PTMR = %1X\n", STV_VDP1_PTM );
281         if ( STV_VDP1_PTMR == 1 )
282            stv_vdp1_process_list();
283
284         break;
285      case 0x06/2:
286         if ( VDP1_LOG ) logerror( "VDP1: Erase data set %08X\n", data );
287
288         m_vdp1.ewdr = STV_VDP1_EWDR;
289         break;
290      case 0x08/2:
291         if ( VDP1_LOG ) logerror( "VDP1: Erase upper-left coord set: %08X\n", data );
292         break;
293      case 0x0a/2:
294         if ( VDP1_LOG ) logerror( "VDP1: Erase lower-right coord set: %08X\n", data );
295         break;
296      case 0x0c/2:
297         if ( VDP1_LOG ) logerror( "VDP1: Draw forced termination register write: %08X\n", data );
298         break;
299      default:
300         printf("Warning: write to unknown VDP1 reg %08x %08x\n",offset*2,data);
301         break;
302   }
303
304}
305
306READ32_MEMBER ( saturn_state::saturn_vdp1_vram_r )
307{
308   return m_vdp1_vram[offset];
309}
310
311
312WRITE32_MEMBER ( saturn_state::saturn_vdp1_vram_w )
313{
314   UINT8 *vdp1 = m_vdp1.gfx_decode;
315
316   COMBINE_DATA (&m_vdp1_vram[offset]);
317
318//  if (((offset * 4) > 0xdf) && ((offset * 4) < 0x140))
319//  {
320//      logerror("cpu %s (PC=%08X): VRAM dword write to %08X = %08X & %08X\n", space.device().tag(), space.device().safe_pc(), offset*4, data, mem_mask);
321//  }
322
323   data = m_vdp1_vram[offset];
324   /* put in gfx region for easy decoding */
325   vdp1[offset*4+0] = (data & 0xff000000) >> 24;
326   vdp1[offset*4+1] = (data & 0x00ff0000) >> 16;
327   vdp1[offset*4+2] = (data & 0x0000ff00) >> 8;
328   vdp1[offset*4+3] = (data & 0x000000ff) >> 0;
329}
330
331WRITE32_MEMBER ( saturn_state::saturn_vdp1_framebuffer0_w )
332{
333   //popmessage ("STV VDP1 Framebuffer 0 WRITE offset %08x data %08x",offset, data);
334   if ( STV_VDP1_TVM & 1 )
335   {
336      /* 8-bit mode */
337      //printf("VDP1 8-bit mode %08x %02x\n",offset,data);
338      if ( ACCESSING_BITS_24_31 )
339      {
340         m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2] &= 0x00ff;
341         m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2] |= data & 0xff00;
342      }
343      if ( ACCESSING_BITS_16_23 )
344      {
345         m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2] &= 0xff00;
346         m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2] |= data & 0x00ff;
347      }
348      if ( ACCESSING_BITS_8_15 )
349      {
350         m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2+1] &= 0x00ff;
351         m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2+1] |= data & 0xff00;
352      }
353      if ( ACCESSING_BITS_0_7 )
354      {
355         m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2+1] &= 0xff00;
356         m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2+1] |= data & 0x00ff;
357      }
358   }
359   else
360   {
361      /* 16-bit mode */
362      if ( ACCESSING_BITS_16_31 )
363      {
364         m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2] = (data >> 16) & 0xffff;
365      }
366      if ( ACCESSING_BITS_0_15 )
367      {
368         m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2+1] = data & 0xffff;
369      }
370   }
371}
372
373READ32_MEMBER ( saturn_state::saturn_vdp1_framebuffer0_r )
374{
375   UINT32 result = 0;
376   //popmessage ("STV VDP1 Framebuffer 0 READ offset %08x",offset);
377   if ( STV_VDP1_TVM & 1 )
378   {
379      /* 8-bit mode */
380      //printf("VDP1 8-bit mode %08x\n",offset);
381      if ( ACCESSING_BITS_24_31 )
382         result |= ((m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2] & 0xff00) << 16);
383      if ( ACCESSING_BITS_16_23 )
384         result |= ((m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2] & 0x00ff) << 16);
385      if ( ACCESSING_BITS_8_15 )
386         result |= ((m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2+1] & 0xff00));
387      if ( ACCESSING_BITS_0_7 )
388         result |= ((m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2+1] & 0x00ff));
389   }
390   else
391   {
392      /* 16-bit mode */
393      if ( ACCESSING_BITS_16_31 )
394      {
395         result |= (m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2] << 16);
396      }
397      if ( ACCESSING_BITS_0_15 )
398      {
399         result |= (m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2+1]);
400      }
401
402   }
403
404   return result;
405}
406
407#ifdef UNUSED_FUNCTION
408WRITE32_HANDLER ( saturn_vdp1_framebuffer1_w )
409{
410   //popmessage ("STV VDP1 Framebuffer 1 WRITE offset %08x data %08x",offset, data);
411}
412
413READ32_HANDLER ( saturn_vdp1_framebuffer1_r )
414{
415   //popmessage ("STV VDP1 Framebuffer 1 READ offset %08x",offset);
416   return 0xffff;
417}
418#endif
419
420
421/*
422
423there is a command every 0x20 bytes
424the first word is the control word
425the rest are data used by it
426
427---
42800 CMDCTRL
429   e--- ---- ---- ---- | end bit (15)
430   -jjj ---- ---- ---- | jump select bits (12-14)
431   ---- zzzz ---- ---- | zoom point / hotspot (8-11)
432   ---- ---- 00-- ---- | UNUSED
433   ---- ---- --dd ---- | character read direction (4,5)
434   ---- ---- ---- cccc | command bits (0-3)
435
43602 CMDLINK
437   llll llll llll ll-- | link
438   ---- ---- ---- --00 | UNUSED
439
44004 CMDPMOD
441   m--- ---- ---- ---- | MON (looks at MSB and apply shadows etc.)
442   -00- ---- ---- ---- | UNUSED
443   ---h ---- ---- ---- | HSS (High Speed Shrink)
444   ---- p--- ---- ---- | PCLIP (Pre Clipping Disable)
445   ---- -c-- ---- ---- | CLIP (Clipping Mode Bit)
446   ---- --m- ---- ---- | CMOD (User Clipping Enable Bit)
447   ---- ---M ---- ---- | MESH (Mesh Enable Bit)
448   ---- ---- e--- ---- | ECD (End Code Disable)
449   ---- ---- -S-- ---- | SPD (Transparent Pixel Disable)
450   ---- ---- --cc c--- | Colour Mode
451   ---- ---- ---- -CCC | Colour Calculation bits
452
45306 CMDCOLR
454   mmmm mmmm mmmm mmmm | Colour Bank, Colour Lookup /8
455
45608 CMDSRCA (Character Address)
457   aaaa aaaa aaaa aa-- | Character Address
458   ---- ---- ---- --00 | UNUSED
459
4600a CMDSIZE (Character Size)
461   00-- ---- ---- ---- | UNUSED
462   --xx xxxx ---- ---- | Character Size (X)
463   ---- ---- yyyy yyyy | Character Size (Y)
464
4650c CMDXA (used for normal sprite)
466   eeee ee-- ---- ---- | extension bits
467   ---- --xx xxxx xxxx | x position
468
4690e CMDYA (used for normal sprite)
470   eeee ee-- ---- ---- | extension bits
471   ---- --yy yyyy yyyy | y position
472
47310 CMDXB
47412 CMDYB
47514 CMDXC
47616 CMDYC
47718 CMDXD
4781a CMDYD
4791c CMDGRDA (Gouraud Shading Table)
4801e UNUSED
481---
482
483
484*/
485
486void saturn_state::stv_clear_gouraud_shading(void)
487{
488   memset( &stv_gouraud_shading, 0, sizeof( stv_gouraud_shading ) );
489}
490
491UINT8 saturn_state::stv_read_gouraud_table( void )
492{
493   int gaddr;
494
495   if ( (stv2_current_sprite.CMDPMOD & 0x7) == 4 )
496   {
497      gaddr = stv2_current_sprite.CMDGRDA * 8;
498      stv_gouraud_shading.GA = (m_vdp1_vram[gaddr/4] >> 16) & 0xffff;
499      stv_gouraud_shading.GB = (m_vdp1_vram[gaddr/4] >> 0) & 0xffff;
500      stv_gouraud_shading.GC = (m_vdp1_vram[gaddr/4 + 1] >> 16) & 0xffff;
501      stv_gouraud_shading.GD = (m_vdp1_vram[gaddr/4 + 1] >> 0) & 0xffff;
502      return 1;
503   }
504   else
505   {
506      return 0;
507   }
508}
509
510INLINE INT32 _shading( INT32 color, INT32 correction )
511{
512   correction = (correction >> 16) & 0x1f;
513   color += (correction - 16);
514
515   if ( color < 0 ) color = 0;
516   if ( color > 0x1f ) color = 0x1f;
517
518   return color;
519}
520
521UINT16 saturn_state::stv_vdp1_apply_gouraud_shading( int x, int y, UINT16 pix )
522{
523   INT32 r,g,b, msb;
524
525   msb = pix & 0x8000;
526
527#ifdef MAME_DEBUG
528   if ( (stv_vdp1_shading_data->scanline[y].x[0] >> 16) != x )
529   {
530      logerror( "ERROR in computing x coordinates (line %d, x = %x, %d, xc = %x, %d)\n", y, x, x, stv_vdp1_shading_data->scanline[y].x[0], stv_vdp1_shading_data->scanline[y].x[0] >> 16 );
531   };
532#endif
533
534   b = RGB_B(pix);
535   g = RGB_G(pix);
536   r = RGB_R(pix);
537
538   b = _shading( b, stv_vdp1_shading_data->scanline[y].b[0] );
539   g = _shading( g, stv_vdp1_shading_data->scanline[y].g[0] );
540   r = _shading( r, stv_vdp1_shading_data->scanline[y].r[0] );
541
542   stv_vdp1_shading_data->scanline[y].b[0] += stv_vdp1_shading_data->scanline[y].db;
543   stv_vdp1_shading_data->scanline[y].g[0] += stv_vdp1_shading_data->scanline[y].dg;
544   stv_vdp1_shading_data->scanline[y].r[0] += stv_vdp1_shading_data->scanline[y].dr;
545
546   stv_vdp1_shading_data->scanline[y].x[0] += 1 << FRAC_SHIFT;
547
548   return msb | b << 10 | g << 5 | r;
549}
550
551void saturn_state::stv_vdp1_setup_shading_for_line(INT32 y, INT32 x1, INT32 x2,
552                                 INT32 r1, INT32 g1, INT32 b1,
553                                 INT32 r2, INT32 g2, INT32 b2)
554{
555   int xx1 = x1>>FRAC_SHIFT;
556   int xx2 = x2>>FRAC_SHIFT;
557
558
559   if ( xx1 > xx2 )
560   {
561      SWAP_INT32(xx1, xx2);
562      SWAP_INT32(r1, r2);
563      SWAP_INT32(g1, g2);
564      SWAP_INT32(b1, b2);
565   }
566
567   if ( (y >= 0) && (y < 512) )
568   {
569      INT32  dx;
570      INT32   gbd, ggd, grd;
571
572      dx = xx2 - xx1;
573
574      if ( dx == 0 )
575      {
576         gbd = ggd = grd = 0;
577      }
578      else
579      {
580         gbd = abs(b2 - b1) / dx;
581         if (b2 < b1) gbd = -gbd;
582         ggd = abs(g2 - g1) / dx;
583         if (g2 < g1) ggd = -ggd;
584         grd = abs(r2 - r1) / dx;
585         if (r2 < r1) grd = -grd;
586      }
587
588      stv_vdp1_shading_data->scanline[y].x[0] = x1;
589      stv_vdp1_shading_data->scanline[y].x[1] = x2;
590
591      stv_vdp1_shading_data->scanline[y].b[0] = b1;
592      stv_vdp1_shading_data->scanline[y].g[0] = g1;
593      stv_vdp1_shading_data->scanline[y].r[0] = r1;
594      stv_vdp1_shading_data->scanline[y].b[1] = b2;
595      stv_vdp1_shading_data->scanline[y].g[1] = g2;
596      stv_vdp1_shading_data->scanline[y].r[1] = r2;
597
598      stv_vdp1_shading_data->scanline[y].db = gbd;
599      stv_vdp1_shading_data->scanline[y].dg = ggd;
600      stv_vdp1_shading_data->scanline[y].dr = grd;
601
602   }
603}
604
605void saturn_state::stv_vdp1_setup_shading_for_slope(
606                     INT32 x1, INT32 x2, INT32 sl1, INT32 sl2, INT32 *nx1, INT32 *nx2,
607                     INT32 r1, INT32 r2, INT32 slr1, INT32 slr2, INT32 *nr1, INT32 *nr2,
608                     INT32 g1, INT32 g2, INT32 slg1, INT32 slg2, INT32 *ng1, INT32 *ng2,
609                     INT32 b1, INT32 b2, INT32 slb1, INT32 slb2, INT32 *nb1, INT32 *nb2,
610                     INT32 _y1, INT32 y2)
611{
612   if(x1 > x2 || (x1==x2 && sl1 > sl2)) {
613      SWAP_INT32(x1,x2);
614      SWAP_INT32(sl1,sl2);
615      SWAP_INT32PTR(nx1, nx2);
616      SWAP_INT32(r1,r2);
617      SWAP_INT32(slr1, slr2);
618      SWAP_INT32PTR(nr1, nr2);
619      SWAP_INT32(g1, g2);
620      SWAP_INT32(slg1, slg2);
621      SWAP_INT32PTR(ng1, ng2);
622      SWAP_INT32(b1, b2);
623      SWAP_INT32(slb1, slb2);
624      SWAP_INT32PTR(nb1, nb2);
625   }
626
627   while(_y1 < y2)
628   {
629      stv_vdp1_setup_shading_for_line(_y1, x1, x2, r1, g1, b1, r2, g2, b2);
630      x1 += sl1;
631      r1 += slr1;
632      g1 += slg1;
633      b1 += slb1;
634
635      x2 += sl2;
636      r2 += slr2;
637      g2 += slg2;
638      b2 += slb2;
639      _y1++;
640   }
641   *nx1 = x1;
642   *nr1 = r1;
643   *ng1 = g1;
644   *nb1 = b1;
645
646   *nx2 = x2;
647   *nr2 = r2;
648   *nb2 = b2;
649   *ng2 = g2;
650}
651
652void saturn_state::stv_vdp1_setup_shading(const struct spoint* q, const rectangle &cliprect)
653{
654   INT32 x1, x2, delta, cury, limy;
655   INT32 r1, g1, b1, r2, g2, b2;
656   INT32 sl1, slg1, slb1, slr1;
657   INT32 sl2, slg2, slb2, slr2;
658   int pmin, pmax, i, ps1, ps2;
659   struct shaded_point p[8];
660   UINT16 gd[4];
661
662   if ( stv_read_gouraud_table() == 0 ) return;
663
664   gd[0] = stv_gouraud_shading.GA;
665   gd[1] = stv_gouraud_shading.GB;
666   gd[2] = stv_gouraud_shading.GC;
667   gd[3] = stv_gouraud_shading.GD;
668
669   for(i=0; i<4; i++) {
670      p[i].x = p[i+4].x = q[i].x << FRAC_SHIFT;
671      p[i].y = p[i+4].y = q[i].y;
672      p[i].r = p[i+4].r = RGB_R(gd[i]) << FRAC_SHIFT;
673      p[i].g = p[i+4].g = RGB_G(gd[i]) << FRAC_SHIFT;
674      p[i].b = p[i+4].b = RGB_B(gd[i]) << FRAC_SHIFT;
675   }
676
677   pmin = pmax = 0;
678   for(i=1; i<4; i++) {
679      if(p[i].y < p[pmin].y)
680         pmin = i;
681      if(p[i].y > p[pmax].y)
682         pmax = i;
683   }
684
685   cury = p[pmin].y;
686   limy = p[pmax].y;
687
688   stv_vdp1_shading_data->sy = cury;
689   stv_vdp1_shading_data->ey = limy;
690
691   if(cury == limy) {
692      x1 = x2 = p[0].x;
693      ps1 = ps2 = 0;
694      for(i=1; i<4; i++) {
695         if(p[i].x < x1) {
696            x1 = p[i].x;
697            ps1 = i;
698         }
699         if(p[i].x > x2) {
700            x2 = p[i].x;
701            ps2 = i;
702         }
703      }
704      stv_vdp1_setup_shading_for_line(cury, x1, x2, p[ps1].r, p[ps1].g, p[ps1].b, p[ps2].r, p[ps2].g, p[ps2].b);
705      goto finish;
706   }
707
708   ps1 = pmin+4;
709   ps2 = pmin;
710
711   goto startup;
712
713   for(;;) {
714      if(p[ps1-1].y == p[ps2+1].y) {
715         stv_vdp1_setup_shading_for_slope(
716                     x1, x2, sl1, sl2, &x1, &x2,
717                     r1, r2, slr1, slr2, &r1, &r2,
718                     g1, g2, slg1, slg2, &g1, &g2,
719                     b1, b2, slb1, slb2, &b1, &b2,
720                     cury, p[ps1-1].y);
721         cury = p[ps1-1].y;
722         if(cury >= limy)
723            break;
724         ps1--;
725         ps2++;
726
727      startup:
728         while(p[ps1-1].y == cury)
729            ps1--;
730         while(p[ps2+1].y == cury)
731            ps2++;
732         x1 = p[ps1].x;
733         r1 = p[ps1].r;
734         g1 = p[ps1].g;
735         b1 = p[ps1].b;
736         x2 = p[ps2].x;
737         r2 = p[ps2].r;
738         g2 = p[ps2].g;
739         b2 = p[ps2].b;
740
741         delta = cury-p[ps1-1].y;
742         sl1 = (x1-p[ps1-1].x)/delta;
743         slr1 = (r1-p[ps1-1].r)/delta;
744         slg1 = (g1-p[ps1-1].g)/delta;
745         slb1 = (b1-p[ps1-1].b)/delta;
746
747         delta = cury-p[ps2+1].y;
748         sl2 = (x2-p[ps2+1].x)/delta;
749         slr2 = (r2-p[ps2+1].r)/delta;
750         slg2 = (g2-p[ps2+1].g)/delta;
751         slb2 = (b2-p[ps2+1].b)/delta;
752      } else if(p[ps1-1].y < p[ps2+1].y) {
753         stv_vdp1_setup_shading_for_slope(
754                     x1, x2, sl1, sl2, &x1, &x2,
755                     r1, r2, slr1, slr2, &r1, &r2,
756                     g1, g2, slg1, slg2, &g1, &g2,
757                     b1, b2, slb1, slb2, &b1, &b2,
758                     cury, p[ps1-1].y);
759         cury = p[ps1-1].y;
760         if(cury >= limy)
761            break;
762         ps1--;
763         while(p[ps1-1].y == cury)
764            ps1--;
765         x1 = p[ps1].x;
766         r1 = p[ps1].r;
767         g1 = p[ps1].g;
768         b1 = p[ps1].b;
769
770         delta = cury-p[ps1-1].y;
771         sl1 = (x1-p[ps1-1].x)/delta;
772         slr1 = (r1-p[ps1-1].r)/delta;
773         slg1 = (g1-p[ps1-1].g)/delta;
774         slb1 = (b1-p[ps1-1].b)/delta;
775      } else {
776         stv_vdp1_setup_shading_for_slope(
777                     x1, x2, sl1, sl2, &x1, &x2,
778                     r1, r2, slr1, slr2, &r1, &r2,
779                     g1, g2, slg1, slg2, &g1, &g2,
780                     b1, b2, slb1, slb2, &b1, &b2,
781                     cury, p[ps2+1].y);
782         cury = p[ps2+1].y;
783         if(cury >= limy)
784            break;
785         ps2++;
786         while(p[ps2+1].y == cury)
787            ps2++;
788         x2 = p[ps2].x;
789         r2 = p[ps2].r;
790         g2 = p[ps2].g;
791         b2 = p[ps2].b;
792
793         delta = cury-p[ps2+1].y;
794         sl2 = (x2-p[ps2+1].x)/delta;
795         slr2 = (r2-p[ps2+1].r)/delta;
796         slg2 = (g2-p[ps2+1].g)/delta;
797         slb2 = (b2-p[ps2+1].b)/delta;
798      }
799   }
800   if(cury == limy)
801      stv_vdp1_setup_shading_for_line(cury, x1, x2, r1, g1, b1, r2, g2, b2 );
802
803finish:
804
805   if ( stv_vdp1_shading_data->sy < 0 ) stv_vdp1_shading_data->sy = 0;
806   if ( stv_vdp1_shading_data->sy >= 512 ) return;
807   if ( stv_vdp1_shading_data->ey < 0 ) return;
808   if ( stv_vdp1_shading_data->ey >= 512 ) stv_vdp1_shading_data->ey = 511;
809
810   for ( cury = stv_vdp1_shading_data->sy; cury <= stv_vdp1_shading_data->ey; cury++ )
811   {
812      while( (stv_vdp1_shading_data->scanline[cury].x[0] >> 16) < cliprect.min_x )
813      {
814         stv_vdp1_shading_data->scanline[cury].x[0] += (1 << FRAC_SHIFT);
815         stv_vdp1_shading_data->scanline[cury].b[0] += stv_vdp1_shading_data->scanline[cury].db;
816         stv_vdp1_shading_data->scanline[cury].g[0] += stv_vdp1_shading_data->scanline[cury].dg;
817         stv_vdp1_shading_data->scanline[cury].r[0] += stv_vdp1_shading_data->scanline[cury].dr;
818      }
819   }
820
821}
822
823/* note that if we're drawing
824to the framebuffer we CAN'T frameskip the vdp1 drawing as the hardware can READ the framebuffer
825and if we skip the drawing the content could be incorrect when it reads it, although i have no idea
826why they would want to */
827
828
829
830void saturn_state::drawpixel_poly(int x, int y, int patterndata, int offsetcnt)
831{
832   /* Capcom Collection Dai 4 uses a dummy polygon to clear VDP1 framebuffer that goes over our current max size ... */
833   if(x >= 1024 || y >= 512)
834      return;
835
836   m_vdp1.framebuffer_draw_lines[y][x] = stv2_current_sprite.CMDCOLR;
837}
838
839void saturn_state::drawpixel_8bpp_trans(int x, int y, int patterndata, int offsetcnt)
840{
841   UINT16 pix;
842
843   pix = m_vdp1.gfx_decode[patterndata+offsetcnt];
844   if ( pix & 0xff )
845   {
846      m_vdp1.framebuffer_draw_lines[y][x] = pix | m_sprite_colorbank;
847   }
848}
849
850void saturn_state::drawpixel_4bpp_notrans(int x, int y, int patterndata, int offsetcnt)
851{
852   UINT16 pix;
853
854   pix = m_vdp1.gfx_decode[patterndata+offsetcnt/2];
855   pix = offsetcnt&1 ? (pix & 0x0f) : ((pix & 0xf0)>>4);
856   m_vdp1.framebuffer_draw_lines[y][x] = pix | m_sprite_colorbank;
857}
858
859void saturn_state::drawpixel_4bpp_trans(int x, int y, int patterndata, int offsetcnt)
860{
861   UINT16 pix;
862
863   pix = m_vdp1.gfx_decode[patterndata+offsetcnt/2];
864   pix = offsetcnt&1 ? (pix & 0x0f) : ((pix & 0xf0)>>4);
865   if ( pix )
866      m_vdp1.framebuffer_draw_lines[y][x] = pix | m_sprite_colorbank;
867}
868
869void saturn_state::drawpixel_generic(int x, int y, int patterndata, int offsetcnt)
870{
871   int pix,mode,transmask, spd = stv2_current_sprite.CMDPMOD & 0x40;
872   int mesh = stv2_current_sprite.CMDPMOD & 0x100;
873   int pix2;
874
875   if ( mesh && !((x ^ y) & 1) )
876   {
877      return;
878   }
879
880   if ( stv2_current_sprite.ispoly )
881   {
882      pix = stv2_current_sprite.CMDCOLR&0xffff;
883
884      transmask = 0xffff;
885      if ( pix & 0x8000 )
886      {
887         mode = 5;
888      }
889      else
890      {
891         mode = 1;
892      }
893   }
894   else
895   {
896      switch (stv2_current_sprite.CMDPMOD&0x0038)
897      {
898         case 0x0000: // mode 0 16 colour bank mode (4bits) (hanagumi blocks)
899            // most of the shienryu sprites use this mode
900            pix = m_vdp1.gfx_decode[(patterndata+offsetcnt/2) & 0xfffff];
901            pix = offsetcnt&1 ? (pix & 0x0f) : ((pix & 0xf0)>>4);
902            pix = pix+((stv2_current_sprite.CMDCOLR&0xfff0));
903            mode = 0;
904            transmask = 0xf;
905            break;
906         case 0x0008: // mode 1 16 colour lookup table mode (4bits)
907            // shienryu explosisons (and some enemies) use this mode
908            pix2 = m_vdp1.gfx_decode[(patterndata+offsetcnt/2) & 0xfffff];
909            pix2 = offsetcnt&1 ? (pix2 & 0x0f) : ((pix2 & 0xf0)>>4);
910            pix = pix2&1 ?
911            ((((m_vdp1_vram[(((stv2_current_sprite.CMDCOLR&0xffff)*8)>>2)+((pix2&0xfffe)/2)])) & 0x0000ffff) >> 0):
912            ((((m_vdp1_vram[(((stv2_current_sprite.CMDCOLR&0xffff)*8)>>2)+((pix2&0xfffe)/2)])) & 0xffff0000) >> 16);
913
914            mode = 5;
915            transmask = 0xffff;
916
917            if ( !spd )
918            {
919               if ( (pix2 & 0xf) == 0 )
920               {
921                  return;
922               }
923               else
924               {
925                  spd = 1;
926               }
927            }
928            break;
929         case 0x0010: // mode 2 64 colour bank mode (8bits) (character select portraits on hanagumi)
930            pix = m_vdp1.gfx_decode[(patterndata+offsetcnt) & 0xfffff];
931            mode = 2;
932            pix = pix+(stv2_current_sprite.CMDCOLR&0xffc0);
933            transmask = 0x3f;
934            break;
935         case 0x0018: // mode 3 128 colour bank mode (8bits) (little characters on hanagumi use this mode)
936            pix = m_vdp1.gfx_decode[(patterndata+offsetcnt) & 0xfffff];
937            pix = pix+(stv2_current_sprite.CMDCOLR&0xff80);
938            transmask = 0x7f;
939            mode = 3;
940            break;
941         case 0x0020: // mode 4 256 colour bank mode (8bits) (hanagumi title)
942            pix = m_vdp1.gfx_decode[(patterndata+offsetcnt) & 0xfffff];
943            pix = pix+(stv2_current_sprite.CMDCOLR&0xff00);
944            transmask = 0xff;
945            mode = 4;
946            break;
947         case 0x0028: // mode 5 32,768 colour RGB mode (16bits)
948            pix = m_vdp1.gfx_decode[(patterndata+offsetcnt*2+1) & 0xfffff] | (m_vdp1.gfx_decode[(patterndata+offsetcnt*2) & 0xfffff]<<8) ;
949            mode = 5;
950            transmask = -1; /* TODO: check me */
951            break;
952         default: // other settings illegal
953            pix = machine().rand();
954            mode = 0;
955            transmask = 0xff;
956            popmessage("Illegal Sprite Mode, contact MAMEdev");
957      }
958
959
960      // preliminary end code disable support
961      if ( ((stv2_current_sprite.CMDPMOD & 0x80) == 0) &&
962         ((pix & transmask) == transmask) )
963      {
964         return;
965      }
966   }
967
968   /* MSBON */
969   pix |= stv2_current_sprite.CMDPMOD & 0x8000;
970   if ( mode != 5 )
971   {
972      if ( (pix & transmask) || spd )
973      {
974         m_vdp1.framebuffer_draw_lines[y][x] = pix;
975      }
976   }
977   else
978   {
979      if ( (pix & transmask) || spd )
980      {
981         switch( stv2_current_sprite.CMDPMOD & 0x7 )
982         {
983            case 0: /* replace */
984               m_vdp1.framebuffer_draw_lines[y][x] = pix;
985               break;
986            case 1: /* shadow */
987               if ( m_vdp1.framebuffer_draw_lines[y][x] & 0x8000 )
988               {
989                  m_vdp1.framebuffer_draw_lines[y][x] = ((m_vdp1.framebuffer_draw_lines[y][x] & ~0x8421) >> 1) | 0x8000;
990               }
991               break;
992            case 2: /* half luminance */
993               m_vdp1.framebuffer_draw_lines[y][x] = ((pix & ~0x8421) >> 1) | 0x8000;
994               break;
995            case 3: /* half transparent */
996               if ( m_vdp1.framebuffer_draw_lines[y][x] & 0x8000 )
997               {
998                  m_vdp1.framebuffer_draw_lines[y][x] = alpha_blend_r16( m_vdp1.framebuffer_draw_lines[y][x], pix, 0x80 ) | 0x8000;
999               }
1000               else
1001               {
1002                  m_vdp1.framebuffer_draw_lines[y][x] = pix;
1003               }
1004               break;
1005            case 4: /* Gouraud shading */
1006               m_vdp1.framebuffer_draw_lines[y][x] = stv_vdp1_apply_gouraud_shading( x, y, pix );
1007               break;
1008            default:
1009               m_vdp1.framebuffer_draw_lines[y][x] = pix;
1010               break;
1011         }
1012      }
1013   }
1014}
1015
1016
1017void saturn_state::stv_vdp1_set_drawpixel( void )
1018{
1019   int sprite_type = stv2_current_sprite.CMDCTRL & 0x000f;
1020   int sprite_mode = stv2_current_sprite.CMDPMOD&0x0038;
1021   int spd = stv2_current_sprite.CMDPMOD & 0x40;
1022   int mesh = stv2_current_sprite.CMDPMOD & 0x100;
1023   int ecd = stv2_current_sprite.CMDPMOD & 0x80;
1024
1025   if ( mesh || !ecd || ((stv2_current_sprite.CMDPMOD & 0x7) != 0) )
1026   {
1027      drawpixel = &saturn_state::drawpixel_generic;
1028      return;
1029   }
1030
1031   if (sprite_type == 4 && ((stv2_current_sprite.CMDPMOD & 0x7) == 0))
1032   {
1033      drawpixel = &saturn_state::drawpixel_poly;
1034   }
1035   else if ( (sprite_mode == 0x20) && !spd )
1036   {
1037      m_sprite_colorbank = (stv2_current_sprite.CMDCOLR&0xff00);
1038      drawpixel = &saturn_state::drawpixel_8bpp_trans;
1039   }
1040   else if ((sprite_mode == 0x00) && spd)
1041   {
1042      m_sprite_colorbank = (stv2_current_sprite.CMDCOLR&0xfff0);
1043      drawpixel = &saturn_state::drawpixel_4bpp_notrans;
1044   }
1045   else if (sprite_mode == 0x00 && !spd )
1046   {
1047      m_sprite_colorbank = (stv2_current_sprite.CMDCOLR&0xfff0);
1048      drawpixel = &saturn_state::drawpixel_4bpp_trans;
1049   }
1050   else
1051   {
1052      drawpixel = &saturn_state::drawpixel_generic;
1053   }
1054}
1055
1056
1057void saturn_state::vdp1_fill_slope(const rectangle &cliprect, int patterndata, int xsize,
1058                     INT32 x1, INT32 x2, INT32 sl1, INT32 sl2, INT32 *nx1, INT32 *nx2,
1059                     INT32 u1, INT32 u2, INT32 slu1, INT32 slu2, INT32 *nu1, INT32 *nu2,
1060                     INT32 v1, INT32 v2, INT32 slv1, INT32 slv2, INT32 *nv1, INT32 *nv2,
1061                     INT32 _y1, INT32 y2)
1062{
1063   if(_y1 > cliprect.max_y)
1064      return;
1065
1066   if(y2 <= cliprect.min_y) {
1067      int delta = y2-_y1;
1068      *nx1 = x1+delta*sl1;
1069      *nu1 = u1+delta*slu1;
1070      *nv1 = v1+delta*slv1;
1071      *nx2 = x2+delta*sl2;
1072      *nu2 = u2+delta*slu2;
1073      *nv2 = v2+delta*slv2;
1074      return;
1075   }
1076
1077   if(y2 > cliprect.max_y)
1078      y2 = cliprect.max_y+1;
1079
1080   if(_y1 < cliprect.min_y) {
1081      int delta = cliprect.min_y - _y1;
1082      x1 += delta*sl1;
1083      u1 += delta*slu1;
1084      v1 += delta*slv1;
1085      x2 += delta*sl2;
1086      u2 += delta*slu2;
1087      v2 += delta*slv2;
1088      _y1 = cliprect.min_y;
1089   }
1090
1091   if(x1 > x2 || (x1==x2 && sl1 > sl2)) {
1092      INT32 t, *tp;
1093      t = x1;
1094      x1 = x2;
1095      x2 = t;
1096      t = sl1;
1097      sl1 = sl2;
1098      sl2 = t;
1099      tp = nx1;
1100      nx1 = nx2;
1101      nx2 = tp;
1102
1103      t = u1;
1104      u1 = u2;
1105      u2 = t;
1106      t = slu1;
1107      slu1 = slu2;
1108      slu2 = t;
1109      tp = nu1;
1110      nu1 = nu2;
1111      nu2 = tp;
1112
1113      t = v1;
1114      v1 = v2;
1115      v2 = t;
1116      t = slv1;
1117      slv1 = slv2;
1118      slv2 = t;
1119      tp = nv1;
1120      nv1 = nv2;
1121      nv2 = tp;
1122   }
1123
1124   while(_y1 < y2) {
1125      if(_y1 >= cliprect.min_y) {
1126         INT32 slux = 0, slvx = 0;
1127         int xx1 = x1>>FRAC_SHIFT;
1128         int xx2 = x2>>FRAC_SHIFT;
1129         INT32 u = u1;
1130         INT32 v = v1;
1131         if(xx1 != xx2) {
1132            int delta = xx2-xx1;
1133            slux = (u2-u1)/delta;
1134            slvx = (v2-v1)/delta;
1135         }
1136         if(xx1 <= cliprect.max_x || xx2 >= cliprect.min_x) {
1137            if(xx1 < cliprect.min_x) {
1138               int delta = cliprect.min_x-xx1;
1139               u += slux*delta;
1140               v += slvx*delta;
1141               xx1 = cliprect.min_x;
1142            }
1143            if(xx2 > cliprect.max_x)
1144               xx2 = cliprect.max_x;
1145
1146            while(xx1 <= xx2) {
1147               (this->*drawpixel)(xx1,_y1, patterndata, (v>>FRAC_SHIFT)*xsize+(u>>FRAC_SHIFT));
1148               xx1++;
1149               u += slux;
1150               v += slvx;
1151            }
1152         }
1153      }
1154
1155      x1 += sl1;
1156      u1 += slu1;
1157      v1 += slv1;
1158      x2 += sl2;
1159      u2 += slu2;
1160      v2 += slv2;
1161      _y1++;
1162   }
1163   *nx1 = x1;
1164   *nu1 = u1;
1165   *nv1 = v1;
1166   *nx2 = x2;
1167   *nu2 = u2;
1168   *nv2 = v2;
1169}
1170
1171void saturn_state::vdp1_fill_line(const rectangle &cliprect, int patterndata, int xsize, INT32 y,
1172                     INT32 x1, INT32 x2, INT32 u1, INT32 u2, INT32 v1, INT32 v2)
1173{
1174   int xx1 = x1>>FRAC_SHIFT;
1175   int xx2 = x2>>FRAC_SHIFT;
1176
1177   if(y > cliprect.max_y || y < cliprect.min_y)
1178      return;
1179
1180   if(xx1 <= cliprect.max_x || xx2 >= cliprect.min_x) {
1181      INT32 slux = 0, slvx = 0;
1182      INT32 u = u1;
1183      INT32 v = v1;
1184      if(xx1 != xx2) {
1185         int delta = xx2-xx1;
1186         slux = (u2-u1)/delta;
1187         slvx = (v2-v1)/delta;
1188      }
1189      if(xx1 < cliprect.min_x) {
1190         int delta = cliprect.min_x-xx1;
1191         u += slux*delta;
1192         v += slvx*delta;
1193         xx1 = cliprect.min_x;
1194      }
1195      if(xx2 > cliprect.max_x)
1196         xx2 = cliprect.max_x;
1197
1198      while(xx1 <= xx2) {
1199         (this->*drawpixel)(xx1,y,patterndata,(v>>FRAC_SHIFT)*xsize+(u>>FRAC_SHIFT));
1200         xx1++;
1201         u += slux;
1202         v += slvx;
1203      }
1204   }
1205}
1206
1207void saturn_state::vdp1_fill_quad(const rectangle &cliprect, int patterndata, int xsize, const struct spoint *q)
1208{
1209   INT32 sl1, sl2, slu1, slu2, slv1, slv2, cury, limy, x1, x2, u1, u2, v1, v2, delta;
1210   int pmin, pmax, i, ps1, ps2;
1211   struct spoint p[8];
1212
1213   for(i=0; i<4; i++) {
1214      p[i].x = p[i+4].x = q[i].x << FRAC_SHIFT;
1215      p[i].y = p[i+4].y = q[i].y;
1216      p[i].u = p[i+4].u = q[i].u << FRAC_SHIFT;
1217      p[i].v = p[i+4].v = q[i].v << FRAC_SHIFT;
1218   }
1219
1220   pmin = pmax = 0;
1221   for(i=1; i<4; i++) {
1222      if(p[i].y < p[pmin].y)
1223         pmin = i;
1224      if(p[i].y > p[pmax].y)
1225         pmax = i;
1226   }
1227
1228   cury = p[pmin].y;
1229   limy = p[pmax].y;
1230
1231   if(cury == limy) {
1232      x1 = x2 = p[0].x;
1233      u1 = u2 = p[0].u;
1234      v1 = v2 = p[0].v;
1235      for(i=1; i<4; i++) {
1236         if(p[i].x < x1) {
1237            x1 = p[i].x;
1238            u1 = p[i].u;
1239            v1 = p[i].v;
1240         }
1241         if(p[i].x > x2) {
1242            x2 = p[i].x;
1243            u2 = p[i].u;
1244            v2 = p[i].v;
1245         }
1246      }
1247      vdp1_fill_line(cliprect, patterndata, xsize, cury, x1, x2, u1, u2, v1, v2);
1248      return;
1249   }
1250
1251   if(cury > cliprect.max_y)
1252      return;
1253   if(limy <= cliprect.min_y)
1254      return;
1255
1256   if(limy > cliprect.max_y)
1257      limy = cliprect.max_y;
1258
1259   ps1 = pmin+4;
1260   ps2 = pmin;
1261
1262   goto startup;
1263
1264   for(;;) {
1265      if(p[ps1-1].y == p[ps2+1].y) {
1266         vdp1_fill_slope(cliprect, patterndata, xsize,
1267                     x1, x2, sl1, sl2, &x1, &x2,
1268                     u1, u2, slu1, slu2, &u1, &u2,
1269                     v1, v2, slv1, slv2, &v1, &v2,
1270                     cury, p[ps1-1].y);
1271         cury = p[ps1-1].y;
1272         if(cury >= limy)
1273            break;
1274         ps1--;
1275         ps2++;
1276
1277      startup:
1278         while(p[ps1-1].y == cury)
1279            ps1--;
1280         while(p[ps2+1].y == cury)
1281            ps2++;
1282         x1 = p[ps1].x;
1283         u1 = p[ps1].u;
1284         v1 = p[ps1].v;
1285         x2 = p[ps2].x;
1286         u2 = p[ps2].u;
1287         v2 = p[ps2].v;
1288
1289         delta = cury-p[ps1-1].y;
1290         sl1 = (x1-p[ps1-1].x)/delta;
1291         slu1 = (u1-p[ps1-1].u)/delta;
1292         slv1 = (v1-p[ps1-1].v)/delta;
1293
1294         delta = cury-p[ps2+1].y;
1295         sl2 = (x2-p[ps2+1].x)/delta;
1296         slu2 = (u2-p[ps2+1].u)/delta;
1297         slv2 = (v2-p[ps2+1].v)/delta;
1298      } else if(p[ps1-1].y < p[ps2+1].y) {
1299         vdp1_fill_slope(cliprect, patterndata, xsize,
1300                     x1, x2, sl1, sl2, &x1, &x2,
1301                     u1, u2, slu1, slu2, &u1, &u2,
1302                     v1, v2, slv1, slv2, &v1, &v2,
1303                     cury, p[ps1-1].y);
1304         cury = p[ps1-1].y;
1305         if(cury >= limy)
1306            break;
1307         ps1--;
1308         while(p[ps1-1].y == cury)
1309            ps1--;
1310         x1 = p[ps1].x;
1311         u1 = p[ps1].u;
1312         v1 = p[ps1].v;
1313
1314         delta = cury-p[ps1-1].y;
1315         sl1 = (x1-p[ps1-1].x)/delta;
1316         slu1 = (u1-p[ps1-1].u)/delta;
1317         slv1 = (v1-p[ps1-1].v)/delta;
1318      } else {
1319         vdp1_fill_slope(cliprect, patterndata, xsize,
1320                     x1, x2, sl1, sl2, &x1, &x2,
1321                     u1, u2, slu1, slu2, &u1, &u2,
1322                     v1, v2, slv1, slv2, &v1, &v2,
1323                     cury, p[ps2+1].y);
1324         cury = p[ps2+1].y;
1325         if(cury >= limy)
1326            break;
1327         ps2++;
1328         while(p[ps2+1].y == cury)
1329            ps2++;
1330         x2 = p[ps2].x;
1331         u2 = p[ps2].u;
1332         v2 = p[ps2].v;
1333
1334         delta = cury-p[ps2+1].y;
1335         sl2 = (x2-p[ps2+1].x)/delta;
1336         slu2 = (u2-p[ps2+1].u)/delta;
1337         slv2 = (v2-p[ps2+1].v)/delta;
1338      }
1339   }
1340   if(cury == limy)
1341      vdp1_fill_line(cliprect, patterndata, xsize, cury, x1, x2, u1, u2, v1, v2);
1342}
1343
1344int saturn_state::x2s(int v)
1345{
1346   return (INT32)(INT16)v + m_vdp1.local_x;
1347}
1348
1349int saturn_state::y2s(int v)
1350{
1351   return (INT32)(INT16)v + m_vdp1.local_y;
1352}
1353
1354void saturn_state::stv_vdp1_draw_line(const rectangle &cliprect)
1355{
1356   struct spoint q[4];
1357
1358   q[0].x = x2s(stv2_current_sprite.CMDXA);
1359   q[0].y = y2s(stv2_current_sprite.CMDYA);
1360   q[1].x = x2s(stv2_current_sprite.CMDXB);
1361   q[1].y = y2s(stv2_current_sprite.CMDYB);
1362   q[2].x = x2s(stv2_current_sprite.CMDXA);
1363   q[2].y = y2s(stv2_current_sprite.CMDYA);
1364   q[3].x = x2s(stv2_current_sprite.CMDXB);
1365   q[3].y = y2s(stv2_current_sprite.CMDYB);
1366
1367   q[0].u = q[3].u = q[1].u = q[2].u = 0;
1368   q[0].v = q[1].v = q[2].v = q[3].v = 0;
1369
1370   vdp1_fill_quad(cliprect, 0, 1, q);
1371}
1372
1373void saturn_state::stv_vdp1_draw_poly_line(const rectangle &cliprect)
1374{
1375   struct spoint q[4];
1376
1377   q[0].x = x2s(stv2_current_sprite.CMDXA);
1378   q[0].y = y2s(stv2_current_sprite.CMDYA);
1379   q[1].x = x2s(stv2_current_sprite.CMDXB);
1380   q[1].y = y2s(stv2_current_sprite.CMDYB);
1381   q[2].x = x2s(stv2_current_sprite.CMDXA);
1382   q[2].y = y2s(stv2_current_sprite.CMDYA);
1383   q[3].x = x2s(stv2_current_sprite.CMDXB);
1384   q[3].y = y2s(stv2_current_sprite.CMDYB);
1385
1386   q[0].u = q[3].u = q[1].u = q[2].u = 0;
1387   q[0].v = q[1].v = q[2].v = q[3].v = 0;
1388
1389   vdp1_fill_quad(cliprect, 0, 1, q);
1390
1391   q[0].x = x2s(stv2_current_sprite.CMDXB);
1392   q[0].y = y2s(stv2_current_sprite.CMDYB);
1393   q[1].x = x2s(stv2_current_sprite.CMDXC);
1394   q[1].y = y2s(stv2_current_sprite.CMDYC);
1395   q[2].x = x2s(stv2_current_sprite.CMDXB);
1396   q[2].y = y2s(stv2_current_sprite.CMDYB);
1397   q[3].x = x2s(stv2_current_sprite.CMDXC);
1398   q[3].y = y2s(stv2_current_sprite.CMDYC);
1399
1400   q[0].u = q[3].u = q[1].u = q[2].u = 0;
1401   q[0].v = q[1].v = q[2].v = q[3].v = 0;
1402
1403   vdp1_fill_quad(cliprect, 0, 1, q);
1404
1405   q[0].x = x2s(stv2_current_sprite.CMDXC);
1406   q[0].y = y2s(stv2_current_sprite.CMDYC);
1407   q[1].x = x2s(stv2_current_sprite.CMDXD);
1408   q[1].y = y2s(stv2_current_sprite.CMDYD);
1409   q[2].x = x2s(stv2_current_sprite.CMDXC);
1410   q[2].y = y2s(stv2_current_sprite.CMDYC);
1411   q[3].x = x2s(stv2_current_sprite.CMDXD);
1412   q[3].y = y2s(stv2_current_sprite.CMDYD);
1413
1414   q[0].u = q[3].u = q[1].u = q[2].u = 0;
1415   q[0].v = q[1].v = q[2].v = q[3].v = 0;
1416
1417   vdp1_fill_quad(cliprect, 0, 1, q);
1418
1419   q[0].x = x2s(stv2_current_sprite.CMDXD);
1420   q[0].y = y2s(stv2_current_sprite.CMDYD);
1421   q[1].x = x2s(stv2_current_sprite.CMDXA);
1422   q[1].y = y2s(stv2_current_sprite.CMDYA);
1423   q[2].x = x2s(stv2_current_sprite.CMDXD);
1424   q[2].y = y2s(stv2_current_sprite.CMDYD);
1425   q[3].x = x2s(stv2_current_sprite.CMDXA);
1426   q[3].y = y2s(stv2_current_sprite.CMDYA);
1427
1428   q[0].u = q[3].u = q[1].u = q[2].u = 0;
1429   q[0].v = q[1].v = q[2].v = q[3].v = 0;
1430
1431   stv_vdp1_setup_shading(q, cliprect);
1432   vdp1_fill_quad(cliprect, 0, 1, q);
1433
1434}
1435
1436void saturn_state::stv_vdp1_draw_distorted_sprite(const rectangle &cliprect)
1437{
1438   struct spoint q[4];
1439
1440   int xsize, ysize;
1441   int direction;
1442   int patterndata;
1443
1444   direction = (stv2_current_sprite.CMDCTRL & 0x0030)>>4;
1445
1446   if ( stv2_current_sprite.ispoly )
1447   {
1448      xsize = ysize = 1;
1449      patterndata = 0;
1450   }
1451   else
1452   {
1453      xsize = (stv2_current_sprite.CMDSIZE & 0x3f00) >> 8;
1454      xsize = xsize * 8;
1455      if (xsize == 0) return; /* setting prohibited */
1456
1457      ysize = (stv2_current_sprite.CMDSIZE & 0x00ff);
1458      if (ysize == 0) return; /* setting prohibited */
1459
1460      patterndata = (stv2_current_sprite.CMDSRCA) & 0xffff;
1461      patterndata = patterndata * 0x8;
1462
1463   }
1464
1465
1466   q[0].x = x2s(stv2_current_sprite.CMDXA);
1467   q[0].y = y2s(stv2_current_sprite.CMDYA);
1468   q[1].x = x2s(stv2_current_sprite.CMDXB);
1469   q[1].y = y2s(stv2_current_sprite.CMDYB);
1470   q[2].x = x2s(stv2_current_sprite.CMDXC);
1471   q[2].y = y2s(stv2_current_sprite.CMDYC);
1472   q[3].x = x2s(stv2_current_sprite.CMDXD);
1473   q[3].y = y2s(stv2_current_sprite.CMDYD);
1474
1475   if(direction & 1) { // xflip
1476      q[0].u = q[3].u = xsize-1;
1477      q[1].u = q[2].u = 0;
1478   } else {
1479      q[0].u = q[3].u = 0;
1480      q[1].u = q[2].u = xsize-1;
1481   }
1482   if(direction & 2) { // yflip
1483      q[0].v = q[1].v = ysize-1;
1484      q[2].v = q[3].v = 0;
1485   } else {
1486      q[0].v = q[1].v = 0;
1487      q[2].v = q[3].v = ysize-1;
1488   }
1489
1490   stv_vdp1_setup_shading(q, cliprect);
1491   vdp1_fill_quad(cliprect, patterndata, xsize, q);
1492}
1493
1494void saturn_state::stv_vdp1_draw_scaled_sprite(const rectangle &cliprect)
1495{
1496   struct spoint q[4];
1497
1498   int xsize, ysize;
1499   int direction;
1500   int patterndata;
1501   int zoompoint;
1502   int x,y;
1503   int x2,y2;
1504   int screen_width,screen_height,screen_height_negative = 0;
1505
1506   direction = (stv2_current_sprite.CMDCTRL & 0x0030)>>4;
1507
1508   xsize = (stv2_current_sprite.CMDSIZE & 0x3f00) >> 8;
1509   xsize = xsize * 8;
1510
1511   ysize = (stv2_current_sprite.CMDSIZE & 0x00ff);
1512
1513   patterndata = (stv2_current_sprite.CMDSRCA) & 0xffff;
1514   patterndata = patterndata * 0x8;
1515
1516   zoompoint = (stv2_current_sprite.CMDCTRL & 0x0f00)>>8;
1517
1518   x = stv2_current_sprite.CMDXA;
1519   y = stv2_current_sprite.CMDYA;
1520
1521   screen_width = (INT16)stv2_current_sprite.CMDXB;
1522   if ( (screen_width < 0) && zoompoint)
1523   {
1524      screen_width = -screen_width;
1525      direction |= 1;
1526   }
1527
1528   screen_height = (INT16)stv2_current_sprite.CMDYB;
1529   if ( (screen_height < 0) && zoompoint )
1530   {
1531      screen_height_negative = 1;
1532      screen_height = -screen_height;
1533      direction |= 2;
1534   }
1535
1536   x2 = stv2_current_sprite.CMDXC; // second co-ordinate set x
1537   y2 = stv2_current_sprite.CMDYC; // second co-ordinate set y
1538
1539   switch (zoompoint)
1540   {
1541      case 0x0: // specified co-ordinates
1542         break;
1543      case 0x5: // up left
1544         break;
1545      case 0x6: // up center
1546         x -= screen_width/2 ;
1547         break;
1548      case 0x7: // up right
1549         x -= screen_width;
1550         break;
1551
1552      case 0x9: // center left
1553         y -= screen_height/2 ;
1554         break;
1555      case 0xa: // center center
1556         y -= screen_height/2 ;
1557         x -= screen_width/2 ;
1558
1559         break;
1560
1561      case 0xb: // center right
1562         y -= screen_height/2 ;
1563         x -= screen_width;
1564         break;
1565
1566      case 0xd: // center left
1567         y -= screen_height;
1568         break;
1569
1570      case 0xe: // center center
1571         y -= screen_height;
1572         x -= screen_width/2 ;
1573         break;
1574
1575      case 0xf: // center right
1576         y -= screen_height;
1577         x -= screen_width;
1578         break;
1579
1580      default: // illegal
1581         break;
1582
1583   }
1584
1585   /*  0----1
1586       |    |
1587       |    |
1588       3----2   */
1589
1590   if (zoompoint)
1591   {
1592      q[0].x = x2s(x);
1593      q[0].y = y2s(y);
1594      q[1].x = x2s(x)+screen_width;
1595      q[1].y = y2s(y);
1596      q[2].x = x2s(x)+screen_width;
1597      q[2].y = y2s(y)+screen_height;
1598      q[3].x = x2s(x);
1599      q[3].y = y2s(y)+screen_height;
1600
1601      if ( screen_height_negative )
1602      {
1603         q[0].y += screen_height;
1604         q[1].y += screen_height;
1605         q[2].y += screen_height;
1606         q[3].y += screen_height;
1607      }
1608   }
1609   else
1610   {
1611      q[0].x = x2s(x);
1612      q[0].y = y2s(y);
1613      q[1].x = x2s(x2);
1614      q[1].y = y2s(y);
1615      q[2].x = x2s(x2);
1616      q[2].y = y2s(y2);
1617      q[3].x = x2s(x);
1618      q[3].y = y2s(y2);
1619   }
1620
1621
1622   if(direction & 1) { // xflip
1623      q[0].u = q[3].u = xsize-1;
1624      q[1].u = q[2].u = 0;
1625   } else {
1626      q[0].u = q[3].u = 0;
1627      q[1].u = q[2].u = xsize-1;
1628   }
1629   if(direction & 2) { // yflip
1630      q[0].v = q[1].v = ysize-1;
1631      q[2].v = q[3].v = 0;
1632   } else {
1633      q[0].v = q[1].v = 0;
1634      q[2].v = q[3].v = ysize-1;
1635   }
1636
1637   stv_vdp1_setup_shading(q, cliprect);
1638   vdp1_fill_quad(cliprect, patterndata, xsize, q);
1639}
1640
1641
1642void saturn_state::stv_vdp1_draw_normal_sprite(const rectangle &cliprect, int sprite_type)
1643{
1644   //UINT16 *destline;
1645   //saturn_state *state = machine.driver_data<saturn_state>();
1646   int y, ysize, drawypos;
1647   int x, xsize, drawxpos;
1648   int direction;
1649   int patterndata;
1650   UINT8 shading;
1651   int su, u, dux, duy;
1652   int maxdrawypos, maxdrawxpos;
1653
1654   x = x2s(stv2_current_sprite.CMDXA);
1655   y = y2s(stv2_current_sprite.CMDYA);
1656
1657   direction = (stv2_current_sprite.CMDCTRL & 0x0030)>>4;
1658
1659   xsize = (stv2_current_sprite.CMDSIZE & 0x3f00) >> 8;
1660   xsize = xsize * 8;
1661
1662   ysize = (stv2_current_sprite.CMDSIZE & 0x00ff);
1663
1664   patterndata = (stv2_current_sprite.CMDSRCA) & 0xffff;
1665   patterndata = patterndata * 0x8;
1666
1667   if (VDP1_LOG) logerror ("Drawing Normal Sprite x %04x y %04x xsize %04x ysize %04x patterndata %06x\n",x,y,xsize,ysize,patterndata);
1668
1669   if ( x > cliprect.max_x ) return;
1670   if ( y > cliprect.max_y ) return;
1671
1672   shading = stv_read_gouraud_table();
1673   if ( shading )
1674   {
1675      struct spoint q[4];
1676      q[0].x = x; q[0].y = y;
1677      q[1].x = x + xsize; q[1].y = y;
1678      q[2].x = x + xsize; q[2].y = y + ysize;
1679      q[3].x = x; q[3].y = y + ysize;
1680
1681      stv_vdp1_setup_shading( q, cliprect );
1682   }
1683
1684   u = 0;
1685   dux = 1;
1686   duy = xsize;
1687   if ( direction & 0x1 ) //xflip
1688   {
1689      dux = -1;
1690      u = xsize - 1;
1691   }
1692   if ( direction & 0x2 ) //yflip
1693   {
1694      duy = -xsize;
1695      u += xsize*(ysize-1);
1696   }
1697   if ( y < cliprect.min_y ) //clip y
1698   {
1699      u += xsize*(cliprect.min_y - y);
1700      ysize -= (cliprect.min_y - y);
1701      y = cliprect.min_y;
1702   }
1703   if ( x < cliprect.min_x ) //clip x
1704   {
1705      u += dux*(cliprect.min_x - x);
1706      xsize -= (cliprect.min_x - x);
1707      x = cliprect.min_x;
1708   }
1709   maxdrawypos = MIN(y+ysize-1,cliprect.max_y);
1710   maxdrawxpos = MIN(x+xsize-1,cliprect.max_x);
1711   for (drawypos = y; drawypos <= maxdrawypos; drawypos++ )
1712   {
1713      //destline = m_vdp1.framebuffer_draw_lines[drawypos];
1714      su = u;
1715      for (drawxpos = x; drawxpos <= maxdrawxpos; drawxpos++ )
1716      {
1717         (this->*drawpixel)( drawxpos, drawypos, patterndata, u );
1718         u += dux;
1719      }
1720      u = su + duy;
1721   }
1722}
1723
1724void saturn_state::stv_vdp1_process_list( void )
1725{
1726   int position;
1727   int spritecount;
1728   int vdp1_nest;
1729   rectangle *cliprect;
1730
1731   spritecount = 0;
1732   position = 0;
1733
1734   if (VDP1_LOG) logerror ("Sprite List Process START\n");
1735
1736   vdp1_nest = -1;
1737
1738   stv_clear_gouraud_shading();
1739
1740   /*Set CEF bit to 0*/
1741   CEF_0;
1742
1743   while (spritecount<10000) // if its drawn this many sprites something is probably wrong or sega were crazy ;-)
1744   {
1745      int draw_this_sprite;
1746
1747      draw_this_sprite = 1;
1748
1749   //  if (position >= ((0x80000/0x20)/4)) // safety check
1750   //  {
1751   //      if (VDP1_LOG) logerror ("Sprite List Position Too High!\n");
1752   //      position = 0;
1753   //  }
1754
1755      stv2_current_sprite.CMDCTRL = (m_vdp1_vram[position * (0x20/4)+0] & 0xffff0000) >> 16;
1756
1757      if (stv2_current_sprite.CMDCTRL == 0x8000)
1758      {
1759         if (VDP1_LOG) logerror ("List Terminator (0x8000) Encountered, Sprite List Process END\n");
1760         goto end; // end of list
1761      }
1762
1763      stv2_current_sprite.CMDLINK = (m_vdp1_vram[position * (0x20/4)+0] & 0x0000ffff) >> 0;
1764      stv2_current_sprite.CMDPMOD = (m_vdp1_vram[position * (0x20/4)+1] & 0xffff0000) >> 16;
1765      stv2_current_sprite.CMDCOLR = (m_vdp1_vram[position * (0x20/4)+1] & 0x0000ffff) >> 0;
1766      stv2_current_sprite.CMDSRCA = (m_vdp1_vram[position * (0x20/4)+2] & 0xffff0000) >> 16;
1767      stv2_current_sprite.CMDSIZE = (m_vdp1_vram[position * (0x20/4)+2] & 0x0000ffff) >> 0;
1768      stv2_current_sprite.CMDXA   = (m_vdp1_vram[position * (0x20/4)+3] & 0xffff0000) >> 16;
1769      stv2_current_sprite.CMDYA   = (m_vdp1_vram[position * (0x20/4)+3] & 0x0000ffff) >> 0;
1770      stv2_current_sprite.CMDXB   = (m_vdp1_vram[position * (0x20/4)+4] & 0xffff0000) >> 16;
1771      stv2_current_sprite.CMDYB   = (m_vdp1_vram[position * (0x20/4)+4] & 0x0000ffff) >> 0;
1772      stv2_current_sprite.CMDXC   = (m_vdp1_vram[position * (0x20/4)+5] & 0xffff0000) >> 16;
1773      stv2_current_sprite.CMDYC   = (m_vdp1_vram[position * (0x20/4)+5] & 0x0000ffff) >> 0;
1774      stv2_current_sprite.CMDXD   = (m_vdp1_vram[position * (0x20/4)+6] & 0xffff0000) >> 16;
1775      stv2_current_sprite.CMDYD   = (m_vdp1_vram[position * (0x20/4)+6] & 0x0000ffff) >> 0;
1776      stv2_current_sprite.CMDGRDA = (m_vdp1_vram[position * (0x20/4)+7] & 0xffff0000) >> 16;
1777//      stv2_current_sprite.UNUSED  = (m_vdp1_vram[position * (0x20/4)+7] & 0x0000ffff) >> 0;
1778
1779      /* proecess jump / skip commands, set position for next sprite */
1780      switch (stv2_current_sprite.CMDCTRL & 0x7000)
1781      {
1782         case 0x0000: // jump next
1783            if (VDP1_LOG) logerror ("Sprite List Process + Next (Normal)\n");
1784            position++;
1785            break;
1786         case 0x1000: // jump assign
1787            if (VDP1_LOG) logerror ("Sprite List Process + Jump Old %06x New %06x\n", position, (stv2_current_sprite.CMDLINK>>2));
1788            position= (stv2_current_sprite.CMDLINK>>2);
1789            break;
1790         case 0x2000: // jump call
1791            if (vdp1_nest == -1)
1792            {
1793               if (VDP1_LOG) logerror ("Sprite List Process + Call Old %06x New %06x\n",position, (stv2_current_sprite.CMDLINK>>2));
1794               vdp1_nest = position+1;
1795               position = (stv2_current_sprite.CMDLINK>>2);
1796            }
1797            else
1798            {
1799               if (VDP1_LOG) logerror ("Sprite List Nested Call, ignoring\n");
1800               position++;
1801            }
1802            break;
1803         case 0x3000:
1804            if (vdp1_nest != -1)
1805            {
1806               if (VDP1_LOG) logerror ("Sprite List Process + Return\n");
1807               position = vdp1_nest;
1808               vdp1_nest = -1;
1809            }
1810            else
1811            {
1812               if (VDP1_LOG) logerror ("Attempted return from no subroutine, aborting\n");
1813               position++;
1814               goto end; // end of list
1815            }
1816            break;
1817         case 0x4000:
1818            draw_this_sprite = 0;
1819            position++;
1820            break;
1821         case 0x5000:
1822            if (VDP1_LOG) logerror ("Sprite List Skip + Jump Old %06x New %06x\n", position, (stv2_current_sprite.CMDLINK>>2));
1823            draw_this_sprite = 0;
1824            position= (stv2_current_sprite.CMDLINK>>2);
1825
1826            break;
1827         case 0x6000:
1828            draw_this_sprite = 0;
1829            if (vdp1_nest == -1)
1830            {
1831               if (VDP1_LOG) logerror ("Sprite List Skip + Call To Subroutine Old %06x New %06x\n",position, (stv2_current_sprite.CMDLINK>>2));
1832
1833               vdp1_nest = position+1;
1834               position = (stv2_current_sprite.CMDLINK>>2);
1835            }
1836            else
1837            {
1838               if (VDP1_LOG) logerror ("Sprite List Nested Call, ignoring\n");
1839               position++;
1840            }
1841            break;
1842         case 0x7000:
1843            draw_this_sprite = 0;
1844            if (vdp1_nest != -1)
1845            {
1846               if (VDP1_LOG) logerror ("Sprite List Skip + Return from Subroutine\n");
1847
1848               position = vdp1_nest;
1849               vdp1_nest = -1;
1850            }
1851            else
1852            {
1853               if (VDP1_LOG) logerror ("Attempted return from no subroutine, aborting\n");
1854               position++;
1855               goto end; // end of list
1856            }
1857            break;
1858      }
1859
1860      /* continue to draw this sprite only if the command wasn't to skip it */
1861      if (draw_this_sprite ==1)
1862      {
1863         if ( stv2_current_sprite.CMDPMOD & 0x0400 )
1864         {
1865            //if(stv2_current_sprite.CMDPMOD & 0x0200) /* TODO: Bio Hazard inventory screen uses outside cliprect */
1866            //  cliprect = &m_vdp1.system_cliprect;
1867            //else
1868               cliprect = &m_vdp1.user_cliprect;
1869         }
1870         else
1871         {
1872            cliprect = &m_vdp1.system_cliprect;
1873         }
1874
1875         stv_vdp1_set_drawpixel();
1876
1877         switch (stv2_current_sprite.CMDCTRL & 0x000f)
1878         {
1879            case 0x0000:
1880               if (VDP1_LOG) logerror ("Sprite List Normal Sprite (%d %d)\n",stv2_current_sprite.CMDXA,stv2_current_sprite.CMDYA);
1881               stv2_current_sprite.ispoly = 0;
1882               stv_vdp1_draw_normal_sprite(*cliprect, 0);
1883               break;
1884
1885            case 0x0001:
1886               if (VDP1_LOG) logerror ("Sprite List Scaled Sprite (%d %d)\n",stv2_current_sprite.CMDXA,stv2_current_sprite.CMDYA);
1887               stv2_current_sprite.ispoly = 0;
1888               stv_vdp1_draw_scaled_sprite(*cliprect);
1889               break;
1890
1891            case 0x0002:
1892            case 0x0003: // used by Hardcore 4x4
1893               if (VDP1_LOG) logerror ("Sprite List Distorted Sprite\n");
1894               if (VDP1_LOG) logerror ("(A: %d %d)\n",stv2_current_sprite.CMDXA,stv2_current_sprite.CMDYA);
1895               if (VDP1_LOG) logerror ("(B: %d %d)\n",stv2_current_sprite.CMDXB,stv2_current_sprite.CMDYB);
1896               if (VDP1_LOG) logerror ("(C: %d %d)\n",stv2_current_sprite.CMDXC,stv2_current_sprite.CMDYC);
1897               if (VDP1_LOG) logerror ("(D: %d %d)\n",stv2_current_sprite.CMDXD,stv2_current_sprite.CMDYD);
1898               if (VDP1_LOG) logerror ("CMDPMOD = %04x\n",stv2_current_sprite.CMDPMOD);
1899
1900               stv2_current_sprite.ispoly = 0;
1901               stv_vdp1_draw_distorted_sprite(*cliprect);
1902               break;
1903
1904            case 0x0004:
1905               if (VDP1_LOG) logerror ("Sprite List Polygon\n");
1906               stv2_current_sprite.ispoly = 1;
1907               stv_vdp1_draw_distorted_sprite(*cliprect);
1908               break;
1909
1910            case 0x0005:
1911//              case 0x0007: // mirror? Baroque uses it, crashes for whatever reason
1912               if (VDP1_LOG) logerror ("Sprite List Polyline\n");
1913               stv2_current_sprite.ispoly = 1;
1914               stv_vdp1_draw_poly_line(*cliprect);
1915               break;
1916
1917            case 0x0006:
1918               if (VDP1_LOG) logerror ("Sprite List Line\n");
1919               stv2_current_sprite.ispoly = 1;
1920               stv_vdp1_draw_line(*cliprect);
1921               break;
1922
1923            case 0x0008:
1924//              case 0x000b: // mirror? Bug 2
1925               if (VDP1_LOG) logerror ("Sprite List Set Command for User Clipping (%d,%d),(%d,%d)\n", stv2_current_sprite.CMDXA, stv2_current_sprite.CMDYA, stv2_current_sprite.CMDXC, stv2_current_sprite.CMDYC);
1926               m_vdp1.user_cliprect.set(stv2_current_sprite.CMDXA, stv2_current_sprite.CMDXC, stv2_current_sprite.CMDYA, stv2_current_sprite.CMDYC);
1927               break;
1928
1929            case 0x0009:
1930               if (VDP1_LOG) logerror ("Sprite List Set Command for System Clipping (0,0),(%d,%d)\n", stv2_current_sprite.CMDXC, stv2_current_sprite.CMDYC);
1931               m_vdp1.system_cliprect.set(0, stv2_current_sprite.CMDXC, 0, stv2_current_sprite.CMDYC);
1932               break;
1933
1934            case 0x000a:
1935               if (VDP1_LOG) logerror ("Sprite List Local Co-Ordinate Set (%d %d)\n",(INT16)stv2_current_sprite.CMDXA,(INT16)stv2_current_sprite.CMDYA);
1936               m_vdp1.local_x = (INT16)stv2_current_sprite.CMDXA;
1937               m_vdp1.local_y = (INT16)stv2_current_sprite.CMDYA;
1938               break;
1939
1940            default:
1941               popmessage ("VDP1: Sprite List Illegal %02x, contact MAMEdev",stv2_current_sprite.CMDCTRL & 0xf);
1942               m_vdp1.lopr = (position * 0x20) >> 3;
1943               m_vdp1.copr = (position * 0x20) >> 3;
1944               return;
1945         }
1946      }
1947
1948      spritecount++;
1949
1950   }
1951
1952
1953   end:
1954   /* set CEF to 1*/
1955   CEF_1;
1956   m_vdp1.copr = (position * 0x20) >> 3;
1957
1958   if (VDP1_LOG) logerror ("End of list processing!\n");
1959}
1960
1961void saturn_state::video_update_vdp1( void )
1962{
1963   int framebuffer_changed = 0;
1964
1965//  int enable;
1966//  if (machine.input().code_pressed (KEYCODE_R)) VDP1_LOG = 1;
1967//  if (machine.input().code_pressed (KEYCODE_T)) VDP1_LOG = 0;
1968
1969//  if (machine.input().code_pressed (KEYCODE_Y)) VDP1_LOG = 0;
1970//  {
1971//      FILE *fp;
1972//
1973//      fp=fopen("vdp1_ram.dmp", "w+b");
1974//      if (fp)
1975//      {
1976//          fwrite(stv_vdp1, 0x00100000, 1, fp);
1977//          fclose(fp);
1978//      }
1979//  }
1980   if (VDP1_LOG) logerror("video_update_vdp1 called\n");
1981   if (VDP1_LOG) logerror( "FBCR = %0x, accessed = %d\n", STV_VDP1_FBCR, m_vdp1.fbcr_accessed );
1982
1983   if(STV_VDP1_CEF)
1984      BEF_1;
1985   else
1986      BEF_0;
1987
1988   if ( m_vdp1.framebuffer_clear_on_next_frame )
1989   {
1990      if ( ((STV_VDP1_FBCR & 0x3) == 3) &&
1991         m_vdp1.fbcr_accessed )
1992      {
1993         stv_clear_framebuffer(m_vdp1.framebuffer_current_display);
1994         m_vdp1.framebuffer_clear_on_next_frame = 0;
1995      }
1996   }
1997
1998   switch( STV_VDP1_FBCR & 0x3 )
1999   {
2000      case 0: /* Automatic mode */
2001         stv_vdp1_change_framebuffers();
2002         stv_clear_framebuffer(m_vdp1.framebuffer_current_draw);
2003         framebuffer_changed = 1;
2004         break;
2005      case 1: /* Setting prohibited */
2006         break;
2007      case 2: /* Manual mode - erase */
2008         if ( m_vdp1.fbcr_accessed )
2009         {
2010            m_vdp1.framebuffer_clear_on_next_frame = 1;
2011         }
2012         break;
2013      case 3: /* Manual mode - change */
2014         if ( m_vdp1.fbcr_accessed )
2015         {
2016            stv_vdp1_change_framebuffers();
2017            if ( STV_VDP1_VBE )
2018            {
2019               stv_clear_framebuffer(m_vdp1.framebuffer_current_draw);
2020            }
2021            /* TODO: Slam n Jam 96 & Cross Romance doesn't like this, investigate. */
2022            framebuffer_changed = 1;
2023         }
2024   //      framebuffer_changed = 1;
2025         break;
2026   }
2027   m_vdp1.fbcr_accessed = 0;
2028
2029   if (VDP1_LOG) logerror( "PTM = %0x, TVM = %x\n", STV_VDP1_PTM, STV_VDP1_TVM );
2030   switch(STV_VDP1_PTM & 3)
2031   {
2032      case 0:/*Idle Mode*/
2033         break;
2034      case 1:/*Draw by request*/
2035         break;
2036      case 2:/*Automatic Draw*/
2037         if ( framebuffer_changed || VDP1_LOG )
2038         {
2039            /*set CEF to 1*/
2040            stv_vdp1_process_list();
2041         }
2042         break;
2043      case 3: /*<invalid>*/
2044         logerror("Warning: Invalid PTM mode set for VDP1!\n");
2045         break;
2046   }
2047   //popmessage("%04x %04x",STV_VDP1_EWRR_X3,STV_VDP1_EWRR_Y3);
2048}
2049
2050void saturn_state::stv_vdp1_state_save_postload( void )
2051{
2052   UINT8 *vdp1 = m_vdp1.gfx_decode;
2053   int offset;
2054   UINT32 data;
2055
2056   m_vdp1.framebuffer_mode = -1;
2057   m_vdp1.framebuffer_double_interlace = -1;
2058
2059   stv_set_framebuffer_config();
2060
2061   for (offset = 0; offset < 0x80000/4; offset++ )
2062   {
2063      data = m_vdp1_vram[offset];
2064      /* put in gfx region for easy decoding */
2065      vdp1[offset*4+0] = (data & 0xff000000) >> 24;
2066      vdp1[offset*4+1] = (data & 0x00ff0000) >> 16;
2067      vdp1[offset*4+2] = (data & 0x0000ff00) >> 8;
2068      vdp1[offset*4+3] = (data & 0x000000ff) >> 0;
2069   }
2070}
2071
2072int saturn_state::stv_vdp1_start ( void )
2073{
2074   m_vdp1_regs = auto_alloc_array_clear(machine(), UINT16, 0x020/2 );
2075   m_vdp1_vram = auto_alloc_array_clear(machine(), UINT32, 0x100000/4 );
2076   m_vdp1.gfx_decode = auto_alloc_array(machine(), UINT8, 0x100000 );
2077
2078   stv_vdp1_shading_data = auto_alloc(machine(), struct stv_vdp1_poly_scanline_data);
2079
2080   m_vdp1.framebuffer[0] = auto_alloc_array(machine(), UINT16, 1024 * 256 * 2 ); /* *2 is for double interlace */
2081   m_vdp1.framebuffer[1] = auto_alloc_array(machine(), UINT16, 1024 * 256 * 2 );
2082
2083   m_vdp1.framebuffer_display_lines = auto_alloc_array(machine(), UINT16 *, 512);
2084   m_vdp1.framebuffer_draw_lines = auto_alloc_array(machine(), UINT16 *, 512);
2085
2086   m_vdp1.framebuffer_width = m_vdp1.framebuffer_height = 0;
2087   m_vdp1.framebuffer_mode = -1;
2088   m_vdp1.framebuffer_double_interlace = -1;
2089   m_vdp1.fbcr_accessed = 0;
2090   m_vdp1.framebuffer_current_display = 0;
2091   m_vdp1.framebuffer_current_draw = 1;
2092   stv_clear_framebuffer(m_vdp1.framebuffer_current_draw);
2093   m_vdp1.framebuffer_clear_on_next_frame = 0;
2094
2095   m_vdp1.system_cliprect.set(0, 0, 0, 0);
2096   /* Kidou Senshi Z Gundam - Zenpen Zeta no Kodou loves to use the user cliprect vars in an undefined state ... */
2097   m_vdp1.user_cliprect.set(0, 512, 0, 256);
2098
2099   // save state
2100   state_save_register_global_pointer(machine(), m_vdp1_regs, 0x020/2);
2101   state_save_register_global_pointer(machine(), m_vdp1_vram, 0x100000/4);
2102   state_save_register_global(machine(), m_vdp1.fbcr_accessed);
2103   state_save_register_global(machine(), m_vdp1.framebuffer_current_display);
2104   state_save_register_global(machine(), m_vdp1.framebuffer_current_draw);
2105   state_save_register_global(machine(), m_vdp1.framebuffer_clear_on_next_frame);
2106   state_save_register_global(machine(), m_vdp1.local_x);
2107   state_save_register_global(machine(), m_vdp1.local_y);
2108   machine().save().register_postload(save_prepost_delegate(FUNC(saturn_state::stv_vdp1_state_save_postload), this));
2109   return 0;
2110}
Property changes on: trunk/src/emu/video/stvvdp1.c
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/emu/video/stvvdp2.c
r0r20947
1/* Sega Saturn VDP2 */
2
3#define DEBUG_MODE 0
4#define TEST_FUNCTIONS 0
5
6/*
7
8the dirty marking stuff and tile decoding will probably be removed in the end anyway as we'll need custom
9rendering code since mame's drawgfx / tilesytem don't offer everything st-v needs
10
11this system seems far too complex to use Mame's tilemap system
12
134 'scroll' planes (scroll screens)
14
15the scroll planes have slightly different capabilities
16
17NBG0
18NBG1
19NBG2
20NBG3
21
222 'rotate' planes
23
24RBG0
25RBG1
26
27-- other crap
28EXBG (external)
29
30-----------------------------------------------------------------------------------------------------------
31
32Video emulation TODO:
33-all games:
34 \-priorities (check myfairld,thunt)
35 \-complete windows effects
36 \-mosaic effect
37 \-ODD bit/H/V Counter not yet emulated properly
38 \-Reduction enable bits
39 \-Check if there are any remaining video registers that are yet to be macroized & added to the rumble.
40-batmanfr:
41 \-If you reset the game after the character selection screen,when you get again to it there's garbage
42   floating behind Batman.
43-elandore:
44 \-(BTANB) priorities at the VS. screen apparently is wrong,but it's like this on the Saturn version too.
45-hanagumi:
46 \-ending screens have corrupt graphics. (*untested*)
47-kiwames:
48 \-incorrect color emulation for the alpha blended flames on the title screen,it's caused by a schizoid
49   linescroll emulation quirk.
50 \-the VDP1 sprites refresh is too slow,causing the "Draw by request" mode to
51   flicker.Moved back to default ATM.
52-pblbeach:
53 \-Sprites are offset, because it doesn't clear vdp1 local coordinates set by bios,
54   I guess that they are cleared when some vdp1 register is written (kludged for now)
55-prikura:
56 \-Attract mode presentation has corrupted graphics in various places,probably caused by incomplete
57   framebuffer data delete.
58-seabass:
59 \-Player sprite is corrupt/missing during movements,caused by incomplete framebuffer switching.
60
61Notes of Interest & Unclear features:
62
63-the test mode / bios is drawn with layer NBG3;
64-hanagumi puts a 'RED' dragon logo in tileram (base 0x64000, 4bpp, 8x8 tiles) but
65its not displayed because its priority value is 0.Left-over?
66
67-scrolling is screen display wise,meaning that a scrolling value is masked with the
68screen resolution size values;
69
70-H-Blank bit is INDIPENDENT of the V-Blank bit...trying to fix enable/disable it during V-Blank period
71 causes wrong gameplay speed in Golden Axe:The Duel.
72
73-Bitmaps uses transparency pens,examples are:
74\-elandore's energy bars;
75\-mausuke's foreground(the one used on the playfield)
76\-shanhigw's tile-based sprites;
77The transparency pen table is like this:
78
79|------------------|---------------------|
80| Character count  | Transparency code   |
81|------------------|---------------------|
82| 16 colors        |=0x0 (4 bits)        |
83| 256 colors       |=0x00 (8 bits)       |
84| 2048 colors      |=0x000 (11 bits)     |
85| 32,768 colors    |MSB=0 (bit 15)       |
86| 16,770,000 colors|MSB=0 (bit 31)       |
87|------------------|---------------------|
88In other words,the first three types uses the offset and not the color allocated.
89
90-double density interlace setting (LSMD == 3) apparently does a lot of fancy stuff in the graphics sizes.
91
92-Debug key list(only if you enable the debug mode on top of this file):
93    \-T: NBG3 layer toggle
94    \-Y: NBG2 layer toggle
95    \-U: NBG1 layer toggle
96    \-I: NBG0 layer toggle
97    \-O: SPRITE toggle
98    \-K: RBG0 layer toggle
99    \-W Decodes the graphics for F4 menu.
100    \-M Stores VDP1 ram contents from a file.
101    \-N Stores VDP1 ram contents into a file.
102*/
103
104#include "emu.h"
105#include "includes/stv.h"
106
107enum
108{
109   STV_TRANSPARENCY_NONE,
110   STV_TRANSPARENCY_PEN,
111   STV_TRANSPARENCY_ADD_BLEND,
112   STV_TRANSPARENCY_ALPHA
113};
114
115#if DEBUG_MODE
116#define LOG_VDP2 1
117#define LOG_ROZ 0
118#else
119#define LOG_VDP2 0
120#define LOG_ROZ 0
121#endif
122
123/*
124
125-------------------------------------------------|-----------------------------|------------------------------
126|  Function        |  Normal Scroll Screen                                     |  Rotation Scroll Screen     |
127|                  |-----------------------------|-----------------------------|------------------------------
128|                  | NBG0         | NBG1         | NBG2         | NBG3         | RBG0         | RBG1         |
129-------------------------------------------------|-----------------------------|------------------------------
130| Character Colour | 16 colours   | 16 colours   | 16 colours   | 16 colours   | 16 colours   | 16 colours   |
131| Count            | 256 " "      | 256 " "      | 256 " "      | 256 " "      | 256 " "      | 256 " "      |
132|                  | 2048 " "     | 2048 " "     |              |              | 2048 " "     | 2048 " "     |
133|                  | 32768 " "    | 32768 " "    |              |              | 32768 " "    | 32768 " "    |
134|                  | 16770000 " " |              |              |              | 16770000 " " | 16770000 " " |
135-------------------------------------------------|-----------------------------|------------------------------
136| Character Size   | 1x1 Cells , 2x2 Cells                                                                   |
137-------------------------------------------------|-----------------------------|------------------------------
138| Pattern Name     | 1 word , 2 words                                                                        |
139| Data Size        |                                                                                         |
140-------------------------------------------------|-----------------------------|------------------------------
141| Plane Size       | 1 H x 1 V 1 Pages ; 2 H x 1 V 1 Pages ; 2 H x 2 V Pages                                 |
142-------------------------------------------------|-----------------------------|------------------------------
143| Plane Count      | 4                                                         | 16                          |
144-------------------------------------------------|-----------------------------|------------------------------
145| Bitmap Possible  | Yes                         | No                          | Yes          | No           |
146-------------------------------------------------|-----------------------------|------------------------------
147| Bitmap Size      | 512 x 256                   | N/A                         | 512x256      | N/A          |
148|                  | 512 x 512                   |                             | 512x512      |              |
149|                  | 1024 x 256                  |                             |              |              |
150|                  | 1024 x 512                  |                             |              |              |
151-------------------------------------------------|-----------------------------|------------------------------
152| Scale            | 0.25 x - 256 x              | None                        | Any ?                       |
153-------------------------------------------------|-----------------------------|------------------------------
154| Rotation         | No                                                        | Yes                         |
155-------------------------------------------------|-----------------------------|-----------------------------|
156| Linescroll       | Yes                         | No                                                        |
157-------------------------------------------------|-----------------------------|------------------------------
158| Column Scroll    | Yes                         | No                                                        |
159-------------------------------------------------|-----------------------------|------------------------------
160| Mosaic           | Yes                                                       | Horizontal Only             |
161-------------------------------------------------|-----------------------------|------------------------------
162
163*/
164
165/* 180000 - r/w - TVMD - TV Screen Mode
166 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
167       | DISP     |    --    |    --    |    --    |    --    |    --    |    --    | BDCLMD   |
168       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
169       | LSMD1    | LSMD0    | VRESO1   | VRESO0   |    --    | HRESO2   | HRESO1   | HRESO0   |
170       \----------|----------|----------|----------|----------|----------|----------|---------*/
171
172   #define STV_VDP2_TVMD   (m_vdp2_regs[0x000/2])
173
174   #define STV_VDP2_DISP   ((STV_VDP2_TVMD & 0x8000) >> 15)
175   #define STV_VDP2_BDCLMD ((STV_VDP2_TVMD & 0x0100) >> 8)
176   #define STV_VDP2_LSMD   ((STV_VDP2_TVMD & 0x00c0) >> 6)
177   #define STV_VDP2_VRES   ((STV_VDP2_TVMD & 0x0030) >> 4)
178   #define STV_VDP2_HRES   ((STV_VDP2_TVMD & 0x0007) >> 0)
179
180/* 180002 - r/w - EXTEN - External Signal Enable Register
181 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
182       |    --    |    --    |    --    |    --    |    --    |    --    | EXLTEN   | EXSYEN   |
183       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
184       |    --    |    --    |    --    |    --    |    --    |    --    | DASEL    | EXBGEN   |
185       \----------|----------|----------|----------|----------|----------|----------|---------*/
186
187   #define STV_VDP2_EXTEN  (m_vdp2_regs[0x002/2])
188
189   #define STV_VDP2_EXLTEN ((STV_VDP2_EXTEN & 0x0200) >> 9)
190
191/* 180004 - r/o - TVSTAT - Screen Status
192 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
193       |    --    |    --    |    --    |    --    |    --    |    --    | EXLTFG   | EXSYFG   |
194       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
195       |    --    |    --    |    --    |    --    | VBLANK   | HBLANK   | ODD      | EVEN     |
196       \----------|----------|----------|----------|----------|----------|----------|---------*/
197
198/* 180006 - r/w - VRSIZE - VRAM Size
199 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
200       | VRAMSZ   |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
201       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
202       |    --    |    --    |    --    |    --    | VER3     | VER2     | VER1     | VER0     |
203       \----------|----------|----------|----------|----------|----------|----------|---------*/
204
205   #define STV_VDP2_VRSIZE (m_vdp2_regs[0x006/2])
206
207   #define STV_VDP2_VRAMSZ ((STV_VDP2_VRSIZE & 0x8000) >> 15)
208
209/* 180008 - r/o - HCNT - H-Counter
210 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
211       |    --    |    --    |    --    |    --    |    --    |    --    | HCT9     | HCT8     |
212       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
213       | HCT7     | HCT6     | HCT5     | HCT4     | HCT3     | HCT2     | HCT1     | HCT0     |
214       \----------|----------|----------|----------|----------|----------|----------|---------*/
215
216   #define STV_VDP2_HCNT (m_vdp2_regs[0x008/2])
217
218/* 18000A - r/o - VCNT - V-Counter
219 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
220       |    --    |    --    |    --    |    --    |    --    |    --    | VCT9     | VCT8     |
221       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
222       | VCT7     | VCT6     | VCT5     | VCT4     | VCT3     | VCT2     | VCT1     | VCT0     |
223       \----------|----------|----------|----------|----------|----------|----------|---------*/
224
225   #define STV_VDP2_VCNT (m_vdp2_regs[0x00a/2])
226
227/* 18000C - RESERVED
228 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
229       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
230       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
231       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
232       \----------|----------|----------|----------|----------|----------|----------|---------*/
233
234/* 18000E - r/w - RAMCTL - RAM Control
235 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
236       |  CRKTE   |    --    | CRMD1    | CRMD0    |    --    |    --    | VRBMD    | VRAMD    |
237       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
238       | RDBSB11  | RDBSB10  | RDBSB01  | RDBSB00  | RDBSA11  | RDBSA10  | RDBSA01  | RDBSA00  |
239       \----------|----------|----------|----------|----------|----------|----------|---------*/
240
241   #define STV_VDP2_RAMCTL (m_vdp2_regs[0x00e/2])
242
243   #define STV_VDP2_CRKTE ((STV_VDP2_RAMCTL & 0x8000) >> 15)
244   #define STV_VDP2_CRMD  ((STV_VDP2_RAMCTL & 0x3000) >> 12)
245   #define STV_VDP2_RDBSB1 ((STV_VDP2_RAMCTL & 0x00c0) >> 6)
246   #define STV_VDP2_RDBSB0 ((STV_VDP2_RAMCTL & 0x0030) >> 4)
247   #define STV_VDP2_RDBSA1 ((STV_VDP2_RAMCTL & 0x000c) >> 2)
248   #define STV_VDP2_RDBSA0 ((STV_VDP2_RAMCTL & 0x0003) >> 0)
249
250
251/* 180010 - r/w - -CYCA0L - VRAM CYCLE PATTERN (BANK A0)
252 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
253       | VCP0A03  | VCP0A02  | VCP0A01  | VCP0A00  | VCP1A03  | VCP1A02  | VCP1A01  | VCP1A00  |
254       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
255       | VCP2A03  | VCP2A02  | VCP2A01  | VCP2A00  | VCP3A03  | VCP3A02  | VCP3A01  | VCP3A00  |
256       \----------|----------|----------|----------|----------|----------|----------|---------*/
257
258   #define STV_VDP2_CYCA0L (m_vdp2_regs[0x010/2])
259
260/* 180012 - r/w - -CYCA0U - VRAM CYCLE PATTERN (BANK A0)
261 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
262       | VCP4A03  | VCP4A02  | VCP4A01  | VCP4A00  | VCP5A03  | VCP5A02  | VCP5A01  | VCP5A00  |
263       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
264       | VCP6A03  | VCP6A02  | VCP6A01  | VCP6A00  | VCP7A03  | VCP7A02  | VCP7A01  | VCP7A00  |
265       \----------|----------|----------|----------|----------|----------|----------|---------*/
266
267   #define STV_VDP2_CYCA0U (m_vdp2_regs[0x012/2])
268
269/* 180014 - r/w - -CYCA1L - VRAM CYCLE PATTERN (BANK A1)
270 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
271       | VCP0A13  | VCP0A12  | VCP0A11  | VCP0A10  | VCP1A13  | VCP1A12  | VCP1A11  | VCP1A10  |
272       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
273       | VCP2A13  | VCP2A12  | VCP2A11  | VCP2A10  | VCP3A13  | VCP3A12  | VCP3A11  | VCP3A10  |
274       \----------|----------|----------|----------|----------|----------|----------|---------*/
275
276   #define STV_VDP2_CYCA1L (m_vdp2_regs[0x014/2])
277
278/* 180016 - r/w - -CYCA1U - VRAM CYCLE PATTERN (BANK A1)
279 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
280       | VCP4A13  | VCP4A12  | VCP4A11  | VCP4A10  | VCP5A13  | VCP5A12  | VCP5A11  | VCP5A10  |
281       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
282       | VCP6A13  | VCP6A12  | VCP6A11  | VCP6A10  | VCP7A13  | VCP7A12  | VCP7A11  | VCP7A10  |
283       \----------|----------|----------|----------|----------|----------|----------|---------*/
284
285   #define STV_VDP2_CYCA1U (m_vdp2_regs[0x016/2])
286
287/* 180018 - r/w - -CYCB0L - VRAM CYCLE PATTERN (BANK B0)
288 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
289       | VCP0B03  | VCP0B02  | VCP0B01  | VCP0B00  | VCP1B03  | VCP1B02  | VCP1B01  | VCP1B00  |
290       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
291       | VCP2B03  | VCP2B02  | VCP2B01  | VCP2B00  | VCP3B03  | VCP3B02  | VCP3B01  | VCP3B00  |
292       \----------|----------|----------|----------|----------|----------|----------|---------*/
293
294   #define STV_VDP2_CYCA2L (m_vdp2_regs[0x018/2])
295
296/* 18001A - r/w - -CYCB0U - VRAM CYCLE PATTERN (BANK B0)
297 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
298       | VCP4B03  | VCP4B02  | VCP4B01  | VCP4B00  | VCP5B03  | VCP5B02  | VCP5B01  | VCP5B00  |
299       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
300       | VCP6B03  | VCP6B02  | VCP6B01  | VCP6B00  | VCP7B03  | VCP7B02  | VCP7B01  | VCP7B00  |
301       \----------|----------|----------|----------|----------|----------|----------|---------*/
302
303   #define STV_VDP2_CYCA2U (m_vdp2_regs[0x01a/2])
304
305/* 18001C - r/w - -CYCB1L - VRAM CYCLE PATTERN (BANK B1)
306 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
307       | VCP0B13  | VCP0B12  | VCP0B11  | VCP0B10  | VCP1B13  | VCP1B12  | VCP1B11  | VCP1B10  |
308       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
309       | VCP2B13  | VCP2B12  | VCP2B11  | VCP2B10  | VCP3B13  | VCP3B12  | VCP3B11  | VCP3B10  |
310       \----------|----------|----------|----------|----------|----------|----------|---------*/
311
312   #define STV_VDP2_CYCA3L (m_vdp2_regs[0x01c/2])
313
314/* 18001E - r/w - -CYCB1U - VRAM CYCLE PATTERN (BANK B1)
315 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
316       | VCP4B13  | VCP4B12  | VCP4B11  | VCP4B10  | VCP5B13  | VCP5B12  | VCP5B11  | VCP5B10  |
317       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
318       | VCP6B13  | VCP6B12  | VCP6B11  | VCP6B10  | VCP7B13  | VCP7B12  | VCP7B11  | VCP7B10  |
319       \----------|----------|----------|----------|----------|----------|----------|---------*/
320
321   #define STV_VDP2_CYCA3U (m_vdp2_regs[0x01e/2])
322
323/* 180020 - r/w - BGON - SCREEN DISPLAY ENABLE
324
325 this register allows each tilemap to be enabled or disabled and also which layers are solid
326
327 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
328       |    --    |    --    |    --    | R0TPON   | N3TPON   | N2TPON   | N1TPON   | N0TPON   |
329       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
330       |    --    |    --    | R1ON     | R0ON     | N3ON     | N2ON     | N1ON     | N0ON     |
331       \----------|----------|----------|----------|----------|----------|----------|---------*/
332
333   #define STV_VDP2_BGON (m_vdp2_regs[0x020/2])
334
335   // NxOn - Layer Enable Register
336   #define STV_VDP2_xxON ((STV_VDP2_BGON & 0x001f) >> 0) /* to see if anything is enabled */
337
338   #define STV_VDP2_N0ON ((STV_VDP2_BGON & 0x0001) >> 0) /* N0On = NBG0 Enable */
339   #define STV_VDP2_N1ON ((STV_VDP2_BGON & 0x0002) >> 1) /* N1On = NBG1 Enable */
340   #define STV_VDP2_N2ON ((STV_VDP2_BGON & 0x0004) >> 2) /* N2On = NBG2 Enable */
341   #define STV_VDP2_N3ON ((STV_VDP2_BGON & 0x0008) >> 3) /* N3On = NBG3 Enable */
342   #define STV_VDP2_R0ON ((STV_VDP2_BGON & 0x0010) >> 4) /* R0On = RBG0 Enable */
343   #define STV_VDP2_R1ON ((STV_VDP2_BGON & 0x0020) >> 5) /* R1On = RBG1 Enable */
344
345   // NxTPON - Transparency Pen Enable Registers
346   #define STV_VDP2_N0TPON ((STV_VDP2_BGON & 0x0100) >> 8) /*  N0TPON = NBG0 Draw Transparent Pen (as solid) /or/ RBG1 Draw Transparent Pen */
347   #define STV_VDP2_N1TPON ((STV_VDP2_BGON & 0x0200) >> 9) /*  N1TPON = NBG1 Draw Transparent Pen (as solid) /or/ EXBG Draw Transparent Pen */
348   #define STV_VDP2_N2TPON ((STV_VDP2_BGON & 0x0400) >> 10)/*  N2TPON = NBG2 Draw Transparent Pen (as solid) */
349   #define STV_VDP2_N3TPON ((STV_VDP2_BGON & 0x0800) >> 11)/*  N3TPON = NBG3 Draw Transparent Pen (as solid) */
350   #define STV_VDP2_R0TPON ((STV_VDP2_BGON & 0x1000) >> 12)/*  R0TPON = RBG0 Draw Transparent Pen (as solid) */
351
352/*
353180022 - MZCTL - Mosaic Control
354bit->  /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
355       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
356       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
357       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
358       \----------|----------|----------|----------|----------|----------|----------|---------*/
359
360   #define STV_VDP2_MZCTL (m_vdp2_regs[0x022/2])
361
362   #define STV_VDP2_MZSZV ((STV_VDP2_MZCTL & 0xf000) >> 12)
363   #define STV_VDP2_MZSZH ((STV_VDP2_MZCTL & 0x0f00) >> 8)
364   #define STV_VDP2_R0MZE ((STV_VDP2_MZCTL & 0x0010) >> 4)
365   #define STV_VDP2_N3MZE ((STV_VDP2_MZCTL & 0x0008) >> 3)
366   #define STV_VDP2_N2MZE ((STV_VDP2_MZCTL & 0x0004) >> 2)
367   #define STV_VDP2_N1MZE ((STV_VDP2_MZCTL & 0x0002) >> 1)
368   #define STV_VDP2_N0MZE ((STV_VDP2_MZCTL & 0x0001) >> 0)
369
370/*180024 - Special Function Code Select
371
372*/
373
374   #define STV_VDP2_SFSEL (m_vdp2_regs[0x024/2])
375
376/*180026 - Special Function Code
377
378*/
379
380   #define STV_VDP2_SFCODE (m_vdp2_regs[0x026/2])
381
382
383/*
384180028 - CHCTLA - Character Control (NBG0, NBG1)
385 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
386       |    --    |    --    | N1CHCN1  | N1CHCN0  | N1BMSZ1  | N1BMSZ0  | N1BMEN   | N1CHSZ   |
387       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
388       |    --    | N0CHCN2  | N0CHCN1  | N0CHCN0  | N0BMSZ1  | N0BMSZ0  | N0BMEN   | N0CHSZ   |
389       \----------|----------|----------|----------|----------|----------|----------|---------*/
390
391   #define STV_VDP2_CHCTLA (m_vdp2_regs[0x028/2])
392
393/* -------------------------- NBG0 Character Control Registers -------------------------- */
394
395/*  N0CHCNx  NBG0 (or RGB1) Colour Depth
396    000 - 16 Colours
397    001 - 256 Colours
398    010 - 2048 Colours
399    011 - 32768 Colours (RGB5)
400    100 - 16770000 Colours (RGB8)
401    101 - invalid
402    110 - invalid
403    111 - invalid   */
404   #define STV_VDP2_N0CHCN ((STV_VDP2_CHCTLA & 0x0070) >> 4)
405
406/*  N0BMSZx - NBG0 Bitmap Size *guessed*
407    00 - 512 x 256
408    01 - 512 x 512
409    10 - 1024 x 256
410    11 - 1024 x 512   */
411   #define STV_VDP2_N0BMSZ ((STV_VDP2_CHCTLA & 0x000c) >> 2)
412
413/*  N0BMEN - NBG0 Bitmap Enable
414    0 - use cell mode
415    1 - use bitmap mode   */
416   #define STV_VDP2_N0BMEN ((STV_VDP2_CHCTLA & 0x0002) >> 1)
417
418/*  N0CHSZ - NBG0 Character (Tile) Size
419    0 - 1 cell  x 1 cell  (8x8)
420    1 - 2 cells x 2 cells (16x16)  */
421   #define STV_VDP2_N0CHSZ ((STV_VDP2_CHCTLA & 0x0001) >> 0)
422
423/* -------------------------- NBG1 Character Control Registers -------------------------- */
424
425/*  N1CHCNx - NBG1 (or EXB1) Colour Depth
426    00 - 16 Colours
427    01 - 256 Colours
428    10 - 2048 Colours
429    11 - 32768 Colours (RGB5)  */
430   #define STV_VDP2_N1CHCN ((STV_VDP2_CHCTLA & 0x3000) >> 12)
431
432/*  N1BMSZx - NBG1 Bitmap Size *guessed*
433    00 - 512 x 256
434    01 - 512 x 512
435    10 - 1024 x 256
436    11 - 1024 x 512   */
437   #define STV_VDP2_N1BMSZ ((STV_VDP2_CHCTLA & 0x0c00) >> 10)
438
439/*  N1BMEN - NBG1 Bitmap Enable
440    0 - use cell mode
441    1 - use bitmap mode   */
442   #define STV_VDP2_N1BMEN ((STV_VDP2_CHCTLA & 0x0200) >> 9)
443
444/*  N1CHSZ - NBG1 Character (Tile) Size
445    0 - 1 cell  x 1 cell  (8x8)
446    1 - 2 cells x 2 cells (16x16)  */
447   #define STV_VDP2_N1CHSZ ((STV_VDP2_CHCTLA & 0x0100) >> 8)
448
449/*
45018002A - CHCTLB - Character Control (NBG2, NBG1, RBG0)
451 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
452       |    --    | R0CHCN2  | R0CHCN1  | R0CHCN0  |    --    | R0BMSZ   | R0BMEN   | R0CHSZ   |
453       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
454       |    --    |    --    | N3CHCN   | N3CHSZ   |    --    |    --    | N2CHCN   | N2CHSZ   |
455       \----------|----------|----------|----------|----------|----------|----------|---------*/
456
457   #define STV_VDP2_CHCTLB (m_vdp2_regs[0x02a/2])
458
459/* -------------------------- RBG0 Character Control Registers -------------------------- */
460
461
462/*  R0CHCNx  RBG0  Colour Depth
463    000 - 16 Colours
464    001 - 256 Colours
465    010 - 2048 Colours
466    011 - 32768 Colours (RGB5)
467    100 - 16770000 Colours (RGB8)
468    101 - invalid
469    110 - invalid
470    111 - invalid   */
471   #define STV_VDP2_R0CHCN ((STV_VDP2_CHCTLB & 0x7000) >> 12)
472
473/*  R0BMSZx - RBG0 Bitmap Size *guessed*
474    00 - 512 x 256
475    01 - 512 x 512  */
476   #define STV_VDP2_R0BMSZ ((STV_VDP2_CHCTLB & 0x0400) >> 10)
477
478/*  R0BMEN - RBG0 Bitmap Enable
479    0 - use cell mode
480    1 - use bitmap mode   */
481   #define STV_VDP2_R0BMEN ((STV_VDP2_CHCTLB & 0x0200) >> 9)
482
483/*  R0CHSZ - RBG0 Character (Tile) Size
484    0 - 1 cell  x 1 cell  (8x8)
485    1 - 2 cells x 2 cells (16x16)  */
486   #define STV_VDP2_R0CHSZ ((STV_VDP2_CHCTLB & 0x0100) >> 8)
487
488   #define STV_VDP2_N3CHCN ((STV_VDP2_CHCTLB & 0x0020) >> 5)
489   #define STV_VDP2_N3CHSZ ((STV_VDP2_CHCTLB & 0x0010) >> 4)
490   #define STV_VDP2_N2CHCN ((STV_VDP2_CHCTLB & 0x0002) >> 1)
491   #define STV_VDP2_N2CHSZ ((STV_VDP2_CHCTLB & 0x0001) >> 0)
492
493
494/*
49518002C - BMPNA - Bitmap Palette Number (NBG0, NBG1)
496 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
497       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
498       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
499       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
500       \----------|----------|----------|----------|----------|----------|----------|---------*/
501
502   #define STV_VDP2_BMPNA (m_vdp2_regs[0x02c/2])
503
504   #define STV_VDP2_N1BMP ((STV_VDP2_BMPNA & 0x0700) >> 8)
505   #define STV_VDP2_N0BMP ((STV_VDP2_BMPNA & 0x0007) >> 0)
506
507/* 18002E - Bitmap Palette Number (RBG0)
508 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
509       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
510       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
511       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
512       \----------|----------|----------|----------|----------|----------|----------|---------*/
513
514   #define STV_VDP2_BMPNB (m_vdp2_regs[0x02e/2])
515
516   #define STV_VDP2_R0BMP ((STV_VDP2_BMPNB & 0x0007) >> 0)
517
518/* 180030 - PNCN0 - Pattern Name Control (NBG0)
519 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
520       | N0PNB    | N0CNSM   |    --    |    --    |    --    |    --    | N0SPR    | N0SCC    |
521       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
522       | N0SPLT6  | N0SPLT5  | N0SPLT4  | N0SPCN4  | N0SPCN3  | N0SPCN2  | N0SPCN1  | N0SPCN0  |
523       \----------|----------|----------|----------|----------|----------|----------|---------*/
524
525   #define STV_VDP2_PNCN0 (m_vdp2_regs[0x030/2])
526
527/*  Pattern Data Size
528    0 = 2 bytes
529    1 = 1 byte */
530   #define STV_VDP2_N0PNB  ((STV_VDP2_PNCN0 & 0x8000) >> 15)
531
532/*  Character Number Supplement (in 1 byte mode)
533    0 = Character Number = 10bits + 2bits for flip
534    1 = Character Number = 12 bits, no flip  */
535   #define STV_VDP2_N0CNSM ((STV_VDP2_PNCN0 & 0x4000) >> 14)
536
537/*  NBG0 Special Priority Register (in 1 byte mode) */
538   #define STV_VDP2_N0SPR ((STV_VDP2_PNCN0 & 0x0200) >> 9)
539
540/*  NBG0 Special Colour Control Register (in 1 byte mode) */
541   #define STV_VDP2_N0SCC ((STV_VDP2_PNCN0 & 0x0100) >> 8)
542
543/*  Supplementary Palette Bits (in 1 byte mode) */
544   #define STV_VDP2_N0SPLT ((STV_VDP2_PNCN0 & 0x00e0) >> 5)
545
546/*  Supplementary Character Bits (in 1 byte mode) */
547   #define STV_VDP2_N0SPCN ((STV_VDP2_PNCN0 & 0x001f) >> 0)
548
549/* 180032 - Pattern Name Control (NBG1)
550 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
551       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
552       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
553       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
554       \----------|----------|----------|----------|----------|----------|----------|---------*/
555
556   #define STV_VDP2_PNCN1 (m_vdp2_regs[0x032/2])
557
558/*  Pattern Data Size
559    0 = 2 bytes
560    1 = 1 byte */
561   #define STV_VDP2_N1PNB  ((STV_VDP2_PNCN1 & 0x8000) >> 15)
562
563/*  Character Number Supplement (in 1 byte mode)
564    0 = Character Number = 10bits + 2bits for flip
565    1 = Character Number = 12 bits, no flip  */
566   #define STV_VDP2_N1CNSM ((STV_VDP2_PNCN1 & 0x4000) >> 14)
567
568/*  NBG0 Special Priority Register (in 1 byte mode) */
569   #define STV_VDP2_N1SPR ((STV_VDP2_PNCN1 & 0x0200) >> 9)
570
571/*  NBG0 Special Colour Control Register (in 1 byte mode) */
572   #define STV_VDP2_N1SCC ((STV_VDP2_PNCN1 & 0x0100) >> 8)
573
574/*  Supplementary Palette Bits (in 1 byte mode) */
575   #define STV_VDP2_N1SPLT ((STV_VDP2_PNCN1 & 0x00e0) >> 5)
576
577/*  Supplementary Character Bits (in 1 byte mode) */
578   #define STV_VDP2_N1SPCN ((STV_VDP2_PNCN1 & 0x001f) >> 0)
579
580
581/* 180034 - Pattern Name Control (NBG2)
582 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
583       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
584       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
585       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
586       \----------|----------|----------|----------|----------|----------|----------|---------*/
587
588   #define STV_VDP2_PNCN2 (m_vdp2_regs[0x034/2])
589
590/*  Pattern Data Size
591    0 = 2 bytes
592    1 = 1 byte */
593   #define STV_VDP2_N2PNB  ((STV_VDP2_PNCN2 & 0x8000) >> 15)
594
595/*  Character Number Supplement (in 1 byte mode)
596    0 = Character Number = 10bits + 2bits for flip
597    1 = Character Number = 12 bits, no flip  */
598   #define STV_VDP2_N2CNSM ((STV_VDP2_PNCN2 & 0x4000) >> 14)
599
600/*  NBG0 Special Priority Register (in 1 byte mode) */
601   #define STV_VDP2_N2SPR ((STV_VDP2_PNCN2 & 0x0200) >> 9)
602
603/*  NBG0 Special Colour Control Register (in 1 byte mode) */
604   #define STV_VDP2_N2SCC ((STV_VDP2_PNCN2 & 0x0100) >> 8)
605
606/*  Supplementary Palette Bits (in 1 byte mode) */
607   #define STV_VDP2_N2SPLT ((STV_VDP2_PNCN2 & 0x00e0) >> 5)
608
609/*  Supplementary Character Bits (in 1 byte mode) */
610   #define STV_VDP2_N2SPCN ((STV_VDP2_PNCN2 & 0x001f) >> 0)
611
612
613/* 180036 - Pattern Name Control (NBG3)
614 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
615       | N3PNB    | N3CNSM   |    --    |    --    |    --    |    --    | N3SPR    | N3SCC    |
616       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
617       | N3SPLT6  | N3SPLT5  | N3SPLT4  | N3SPCN4  | N3SPCN3  | N3SPCN2  | N3SPCN1  | N3SPCN0  |
618       \----------|----------|----------|----------|----------|----------|----------|---------*/
619
620   #define STV_VDP2_PNCN3 (m_vdp2_regs[0x036/2])
621
622/*  Pattern Data Size
623    0 = 2 bytes
624    1 = 1 byte */
625   #define STV_VDP2_N3PNB  ((STV_VDP2_PNCN3 & 0x8000) >> 15)
626
627/*  Character Number Supplement (in 1 byte mode)
628    0 = Character Number = 10bits + 2bits for flip
629    1 = Character Number = 12 bits, no flip  */
630   #define STV_VDP2_N3CNSM ((STV_VDP2_PNCN3 & 0x4000) >> 14)
631
632/*  NBG0 Special Priority Register (in 1 byte mode) */
633   #define STV_VDP2_N3SPR ((STV_VDP2_PNCN3 & 0x0200) >> 9)
634
635/*  NBG0 Special Colour Control Register (in 1 byte mode) */
636   #define STV_VDP2_N3SCC ((STV_VDP2_PNCN3 & 0x0100) >> 8)
637
638/*  Supplementary Palette Bits (in 1 byte mode) */
639   #define STV_VDP2_N3SPLT ((STV_VDP2_PNCN3 & 0x00e0) >> 5)
640
641/*  Supplementary Character Bits (in 1 byte mode) */
642   #define STV_VDP2_N3SPCN ((STV_VDP2_PNCN3 & 0x001f) >> 0)
643
644
645/* 180038 - Pattern Name Control (RBG0)
646 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
647       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
648       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
649       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
650       \----------|----------|----------|----------|----------|----------|----------|---------*/
651
652   #define STV_VDP2_PNCR (m_vdp2_regs[0x038/2])
653
654/*  Pattern Data Size
655    0 = 2 bytes
656    1 = 1 byte */
657   #define STV_VDP2_R0PNB  ((STV_VDP2_PNCR & 0x8000) >> 15)
658
659/*  Character Number Supplement (in 1 byte mode)
660    0 = Character Number = 10bits + 2bits for flip
661    1 = Character Number = 12 bits, no flip  */
662   #define STV_VDP2_R0CNSM ((STV_VDP2_PNCR & 0x4000) >> 14)
663
664/*  NBG0 Special Priority Register (in 1 byte mode) */
665   #define STV_VDP2_R0SPR ((STV_VDP2_PNCR & 0x0200) >> 9)
666
667/*  NBG0 Special Colour Control Register (in 1 byte mode) */
668   #define STV_VDP2_R0SCC ((STV_VDP2_PNCR & 0x0100) >> 8)
669
670/*  Supplementary Palette Bits (in 1 byte mode) */
671   #define STV_VDP2_R0SPLT ((STV_VDP2_PNCR & 0x00e0) >> 5)
672
673/*  Supplementary Character Bits (in 1 byte mode) */
674   #define STV_VDP2_R0SPCN ((STV_VDP2_PNCR & 0x001f) >> 0)
675
676/* 18003A - PLSZ - Plane Size
677 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
678       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
679       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
680       | N3PLSZ1  | N3PLSZ0  |    --    |    --    | N1PLSZ1  | N1PLSZ0  | N0PLSZ1  | N0PLSZ0  |
681       \----------|----------|----------|----------|----------|----------|----------|---------*/
682
683   #define STV_VDP2_PLSZ (m_vdp2_regs[0x03a/2])
684
685   /* NBG0 Plane Size
686   00 1H Page x 1V Page
687   01 2H Pages x 1V Page
688   10 invalid
689   11 2H Pages x 2V Pages  */
690   #define STV_VDP2_RBOVR  ((STV_VDP2_PLSZ & 0xc000) >> 14)
691   #define STV_VDP2_RBPLSZ ((STV_VDP2_PLSZ & 0x3000) >> 12)
692   #define STV_VDP2_RAOVR  ((STV_VDP2_PLSZ & 0x0c00) >> 10)
693   #define STV_VDP2_RAPLSZ ((STV_VDP2_PLSZ & 0x0300) >> 8)
694   #define STV_VDP2_N3PLSZ ((STV_VDP2_PLSZ & 0x00c0) >> 6)
695   #define STV_VDP2_N2PLSZ ((STV_VDP2_PLSZ & 0x0030) >> 4)
696   #define STV_VDP2_N1PLSZ ((STV_VDP2_PLSZ & 0x000c) >> 2)
697   #define STV_VDP2_N0PLSZ ((STV_VDP2_PLSZ & 0x0003) >> 0)
698
699/* 18003C - MPOFN - Map Offset (NBG0, NBG1, NBG2, NBG3)
700 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
701       |    --    | N3MP8    | N3MP7    | N3MP6    |    --    | N2MP8    | N2MP7    | N2MP6    |
702       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
703       |    --    | N1MP8    | N1MP7    | N1MP6    |    --    | N0MP8    | N0MP7    | N0MP6    |
704       \----------|----------|----------|----------|----------|----------|----------|---------*/
705
706   #define STV_VDP2_MPOFN_ (m_vdp2_regs[0x03c/2])
707
708   /* Higher 3 bits of the map offset for each layer */
709   #define STV_VDP2_N3MP_ ((STV_VDP2_MPOFN_ & 0x3000) >> 12)
710   #define STV_VDP2_N2MP_ ((STV_VDP2_MPOFN_ & 0x0300) >> 8)
711   #define STV_VDP2_N1MP_ ((STV_VDP2_MPOFN_ & 0x0030) >> 4)
712   #define STV_VDP2_N0MP_ ((STV_VDP2_MPOFN_ & 0x0003) >> 0)
713
714
715
716
717/* 18003E - Map Offset (Rotation Parameter A,B)
718 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
719       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
720       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
721       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
722       \----------|----------|----------|----------|----------|----------|----------|---------*/
723
724   #define STV_VDP2_MPOFR_ (m_vdp2_regs[0x03e/2])
725
726   #define STV_VDP2_RBMP_ ((STV_VDP2_MPOFR_ & 0x0030) >> 4)
727   #define STV_VDP2_RAMP_ ((STV_VDP2_MPOFR_ & 0x0003) >> 0)
728
729/* 180040 - MPABN0 - Map (NBG0, Plane A,B)
730 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
731       |    --    |    --    | N0MPB5   | N0MPB4   | N0MPB3   | N0MPB2   | N0MPB1   | N0MPB0   |
732       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
733       |    --    |    --    | N0MPA5   | N0MPA4   | N0MPA3   | N0MPA2   | N0MPA1   | N0MPA0   |
734       \----------|----------|----------|----------|----------|----------|----------|---------*/
735
736   #define STV_VDP2_MPABN0 (m_vdp2_regs[0x040/2])
737
738   /* N0MPB5 = lower 6 bits of Map Address of Plane B of Tilemap NBG0 */
739   #define STV_VDP2_N0MPB ((STV_VDP2_MPABN0 & 0x3f00) >> 8)
740
741   /* N0MPA5 = lower 6 bits of Map Address of Plane A of Tilemap NBG0 */
742   #define STV_VDP2_N0MPA ((STV_VDP2_MPABN0 & 0x003f) >> 0)
743
744
745/* 180042 - MPCDN0 - (NBG0, Plane C,D)
746 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
747       |    --    |    --    | N0MPD5   | N0MPD4   | N0MPD3   | N0MPD2   | N0MPD1   | N0MPD0   |
748       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
749       |    --    |    --    | N0MPC5   | N0MPC4   | N0MPC3   | N0MPC2   | N0MPC1   | N0MPC0   |
750       \----------|----------|----------|----------|----------|----------|----------|---------*/
751
752   #define STV_VDP2_MPCDN0 (m_vdp2_regs[0x042/2])
753
754   /* N0MPB5 = lower 6 bits of Map Address of Plane D of Tilemap NBG0 */
755   #define STV_VDP2_N0MPD ((STV_VDP2_MPCDN0 & 0x3f00) >> 8)
756
757   /* N0MPA5 = lower 6 bits of Map Address of Plane C of Tilemap NBG0 */
758   #define STV_VDP2_N0MPC ((STV_VDP2_MPCDN0 & 0x003f) >> 0)
759
760
761/* 180044 - Map (NBG1, Plane A,B)
762 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
763       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
764       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
765       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
766       \----------|----------|----------|----------|----------|----------|----------|---------*/
767
768   #define STV_VDP2_MPABN1 (m_vdp2_regs[0x044/2])
769
770   /* N0MPB5 = lower 6 bits of Map Address of Plane B of Tilemap NBG1 */
771   #define STV_VDP2_N1MPB ((STV_VDP2_MPABN1 & 0x3f00) >> 8)
772
773   /* N0MPA5 = lower 6 bits of Map Address of Plane A of Tilemap NBG1 */
774   #define STV_VDP2_N1MPA ((STV_VDP2_MPABN1 & 0x003f) >> 0)
775
776/* 180046 - Map (NBG1, Plane C,D)
777 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
778       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
779       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
780       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
781       \----------|----------|----------|----------|----------|----------|----------|---------*/
782
783   #define STV_VDP2_MPCDN1 (m_vdp2_regs[0x046/2])
784
785   /* N0MPB5 = lower 6 bits of Map Address of Plane D of Tilemap NBG0 */
786   #define STV_VDP2_N1MPD ((STV_VDP2_MPCDN1 & 0x3f00) >> 8)
787
788   /* N0MPA5 = lower 6 bits of Map Address of Plane C of Tilemap NBG0 */
789   #define STV_VDP2_N1MPC ((STV_VDP2_MPCDN1 & 0x003f) >> 0)
790
791
792/* 180048 - Map (NBG2, Plane A,B)
793 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
794       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
795       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
796       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
797       \----------|----------|----------|----------|----------|----------|----------|---------*/
798
799   #define STV_VDP2_MPABN2 (m_vdp2_regs[0x048/2])
800
801   /* N0MPB5 = lower 6 bits of Map Address of Plane B of Tilemap NBG2 */
802   #define STV_VDP2_N2MPB ((STV_VDP2_MPABN2 & 0x3f00) >> 8)
803
804   /* N0MPA5 = lower 6 bits of Map Address of Plane A of Tilemap NBG2 */
805   #define STV_VDP2_N2MPA ((STV_VDP2_MPABN2 & 0x003f) >> 0)
806
807/* 18004a - Map (NBG2, Plane C,D)
808 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
809       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
810       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
811       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
812       \----------|----------|----------|----------|----------|----------|----------|---------*/
813
814   #define STV_VDP2_MPCDN2 (m_vdp2_regs[0x04a/2])
815
816   /* N0MPB5 = lower 6 bits of Map Address of Plane D of Tilemap NBG2 */
817   #define STV_VDP2_N2MPD ((STV_VDP2_MPCDN2 & 0x3f00) >> 8)
818
819   /* N0MPA5 = lower 6 bits of Map Address of Plane C of Tilemap NBG2 */
820   #define STV_VDP2_N2MPC ((STV_VDP2_MPCDN2 & 0x003f) >> 0)
821
822/* 18004c - Map (NBG3, Plane A,B)
823 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
824       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
825       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
826       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
827       \----------|----------|----------|----------|----------|----------|----------|---------*/
828
829   #define STV_VDP2_MPABN3 (m_vdp2_regs[0x04c/2])
830
831   /* N0MPB5 = lower 6 bits of Map Address of Plane B of Tilemap NBG1 */
832   #define STV_VDP2_N3MPB ((STV_VDP2_MPABN3 & 0x3f00) >> 8)
833
834   /* N0MPA5 = lower 6 bits of Map Address of Plane A of Tilemap NBG1 */
835   #define STV_VDP2_N3MPA ((STV_VDP2_MPABN3 & 0x003f) >> 0)
836
837
838/* 18004e - Map (NBG3, Plane C,D)
839 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
840       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
841       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
842       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
843       \----------|----------|----------|----------|----------|----------|----------|---------*/
844
845   #define STV_VDP2_MPCDN3 (m_vdp2_regs[0x04e/2])
846
847   /* N0MPB5 = lower 6 bits of Map Address of Plane B of Tilemap NBG0 */
848   #define STV_VDP2_N3MPD ((STV_VDP2_MPCDN3 & 0x3f00) >> 8)
849
850   /* N0MPA5 = lower 6 bits of Map Address of Plane A of Tilemap NBG0 */
851   #define STV_VDP2_N3MPC ((STV_VDP2_MPCDN3 & 0x003f) >> 0)
852
853/* 180050 - Map (Rotation Parameter A, Plane A,B)
854 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
855       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
856       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
857       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
858       \----------|----------|----------|----------|----------|----------|----------|---------*/
859
860   #define STV_VDP2_MPABRA (m_vdp2_regs[0x050/2])
861
862   /* R0MPB5 = lower 6 bits of Map Address of Plane B of Tilemap RBG0 */
863   #define STV_VDP2_RAMPB ((STV_VDP2_MPABRA & 0x3f00) >> 8)
864
865   /* R0MPA5 = lower 6 bits of Map Address of Plane A of Tilemap RBG0 */
866   #define STV_VDP2_RAMPA ((STV_VDP2_MPABRA & 0x003f) >> 0)
867
868
869
870/* 180052 - Map (Rotation Parameter A, Plane C,D)
871 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
872       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
873       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
874       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
875       \----------|----------|----------|----------|----------|----------|----------|---------*/
876   #define STV_VDP2_MPCDRA (m_vdp2_regs[0x052/2])
877
878   /* R0MPB5 = lower 6 bits of Map Address of Plane D of Tilemap RBG0 */
879   #define STV_VDP2_RAMPD ((STV_VDP2_MPCDRA & 0x3f00) >> 8)
880
881   /* R0MPA5 = lower 6 bits of Map Address of Plane C of Tilemap RBG0 */
882   #define STV_VDP2_RAMPC ((STV_VDP2_MPCDRA & 0x003f) >> 0)
883
884/* 180054 - Map (Rotation Parameter A, Plane E,F)
885 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
886       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
887       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
888       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
889       \----------|----------|----------|----------|----------|----------|----------|---------*/
890   #define STV_VDP2_MPEFRA (m_vdp2_regs[0x054/2])
891
892   /* R0MPB5 = lower 6 bits of Map Address of Plane F of Tilemap RBG0 */
893   #define STV_VDP2_RAMPF ((STV_VDP2_MPEFRA & 0x3f00) >> 8)
894
895   /* R0MPA5 = lower 6 bits of Map Address of Plane E of Tilemap RBG0 */
896   #define STV_VDP2_RAMPE ((STV_VDP2_MPEFRA & 0x003f) >> 0)
897
898/* 180056 - Map (Rotation Parameter A, Plane G,H)
899 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
900       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
901       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
902       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
903       \----------|----------|----------|----------|----------|----------|----------|---------*/
904   #define STV_VDP2_MPGHRA (m_vdp2_regs[0x056/2])
905
906   /* R0MPB5 = lower 6 bits of Map Address of Plane H of Tilemap RBG0 */
907   #define STV_VDP2_RAMPH ((STV_VDP2_MPGHRA & 0x3f00) >> 8)
908
909   /* R0MPA5 = lower 6 bits of Map Address of Plane G of Tilemap RBG0 */
910   #define STV_VDP2_RAMPG ((STV_VDP2_MPGHRA & 0x003f) >> 0)
911
912/* 180058 - Map (Rotation Parameter A, Plane I,J)
913 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
914       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
915       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
916       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
917       \----------|----------|----------|----------|----------|----------|----------|---------*/
918   #define STV_VDP2_MPIJRA (m_vdp2_regs[0x058/2])
919
920   /* R0MPB5 = lower 6 bits of Map Address of Plane J of Tilemap RBG0 */
921   #define STV_VDP2_RAMPJ ((STV_VDP2_MPIJRA & 0x3f00) >> 8)
922
923   /* R0MPA5 = lower 6 bits of Map Address of Plane I of Tilemap RBG0 */
924   #define STV_VDP2_RAMPI ((STV_VDP2_MPIJRA & 0x003f) >> 0)
925
926/* 18005a - Map (Rotation Parameter A, Plane K,L)
927 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
928       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
929       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
930       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
931       \----------|----------|----------|----------|----------|----------|----------|---------*/
932   #define STV_VDP2_MPKLRA (m_vdp2_regs[0x05a/2])
933
934   /* R0MPB5 = lower 6 bits of Map Address of Plane L of Tilemap RBG0 */
935   #define STV_VDP2_RAMPL ((STV_VDP2_MPKLRA & 0x3f00) >> 8)
936
937   /* R0MPA5 = lower 6 bits of Map Address of Plane K of Tilemap RBG0 */
938   #define STV_VDP2_RAMPK ((STV_VDP2_MPKLRA & 0x003f) >> 0)
939
940/* 18005c - Map (Rotation Parameter A, Plane M,N)
941 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
942       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
943       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
944       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
945       \----------|----------|----------|----------|----------|----------|----------|---------*/
946   #define STV_VDP2_MPMNRA (m_vdp2_regs[0x05c/2])
947
948   /* R0MPB5 = lower 6 bits of Map Address of Plane N of Tilemap RBG0 */
949   #define STV_VDP2_RAMPN ((STV_VDP2_MPMNRA & 0x3f00) >> 8)
950
951   /* R0MPA5 = lower 6 bits of Map Address of Plane M of Tilemap RBG0 */
952   #define STV_VDP2_RAMPM ((STV_VDP2_MPMNRA & 0x003f) >> 0)
953
954/* 18005e - Map (Rotation Parameter A, Plane O,P)
955 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
956       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
957       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
958       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
959       \----------|----------|----------|----------|----------|----------|----------|---------*/
960   #define STV_VDP2_MPOPRA (m_vdp2_regs[0x05e/2])
961
962   /* R0MPB5 = lower 6 bits of Map Address of Plane P of Tilemap RBG0 */
963   #define STV_VDP2_RAMPP ((STV_VDP2_MPOPRA & 0x3f00) >> 8)
964
965   /* R0MPA5 = lower 6 bits of Map Address of Plane O of Tilemap RBG0 */
966   #define STV_VDP2_RAMPO ((STV_VDP2_MPOPRA & 0x003f) >> 0)
967
968/* 180060 - Map (Rotation Parameter B, Plane A,B)
969 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
970       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
971       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
972       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
973       \----------|----------|----------|----------|----------|----------|----------|---------*/
974
975   #define STV_VDP2_MPABRB (m_vdp2_regs[0x060/2])
976
977   /* R0MPB5 = lower 6 bits of Map Address of Plane B of Tilemap RBG0 */
978   #define STV_VDP2_RBMPB ((STV_VDP2_MPABRB & 0x3f00) >> 8)
979
980   /* R0MPA5 = lower 6 bits of Map Address of Plane A of Tilemap RBG0 */
981   #define STV_VDP2_RBMPA ((STV_VDP2_MPABRB & 0x003f) >> 0)
982
983
984/* 180062 - Map (Rotation Parameter B, Plane C,D)
985 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
986       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
987       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
988       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
989       \----------|----------|----------|----------|----------|----------|----------|---------*/
990
991   #define STV_VDP2_MPCDRB (m_vdp2_regs[0x062/2])
992
993   /* R0MPD5 = lower 6 bits of Map Address of Plane D of Tilemap RBG0 */
994   #define STV_VDP2_RBMPD ((STV_VDP2_MPCDRB & 0x3f00) >> 8)
995
996   /* R0MPc5 = lower 6 bits of Map Address of Plane C of Tilemap RBG0 */
997   #define STV_VDP2_RBMPC ((STV_VDP2_MPCDRB & 0x003f) >> 0)
998
999/* 180064 - Map (Rotation Parameter B, Plane E,F)
1000 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1001       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1002       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1003       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1004       \----------|----------|----------|----------|----------|----------|----------|---------*/
1005
1006   #define STV_VDP2_MPEFRB (m_vdp2_regs[0x064/2])
1007
1008   /* R0MPF5 = lower 6 bits of Map Address of Plane F of Tilemap RBG0 */
1009   #define STV_VDP2_RBMPF ((STV_VDP2_MPEFRB & 0x3f00) >> 8)
1010
1011   /* R0MPE5 = lower 6 bits of Map Address of Plane E of Tilemap RBG0 */
1012   #define STV_VDP2_RBMPE ((STV_VDP2_MPEFRB & 0x003f) >> 0)
1013
1014/* 180066 - Map (Rotation Parameter B, Plane G,H)
1015 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1016       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1017       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1018       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1019       \----------|----------|----------|----------|----------|----------|----------|---------*/
1020
1021   #define STV_VDP2_MPGHRB (m_vdp2_regs[0x066/2])
1022
1023   /* R0MPH5 = lower 6 bits of Map Address of Plane H of Tilemap RBG0 */
1024   #define STV_VDP2_RBMPH ((STV_VDP2_MPGHRB & 0x3f00) >> 8)
1025
1026   /* R0MPG5 = lower 6 bits of Map Address of Plane G of Tilemap RBG0 */
1027   #define STV_VDP2_RBMPG ((STV_VDP2_MPGHRB & 0x003f) >> 0)
1028
1029/* 180068 - Map (Rotation Parameter B, Plane I,J)
1030 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1031       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1032       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1033       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1034       \----------|----------|----------|----------|----------|----------|----------|---------*/
1035
1036   #define STV_VDP2_MPIJRB (m_vdp2_regs[0x068/2])
1037
1038   /* R0MPJ5 = lower 6 bits of Map Address of Plane J of Tilemap RBG0 */
1039   #define STV_VDP2_RBMPJ ((STV_VDP2_MPIJRB & 0x3f00) >> 8)
1040
1041   /* R0MPI5 = lower 6 bits of Map Address of Plane E of Tilemap RBG0 */
1042   #define STV_VDP2_RBMPI ((STV_VDP2_MPIJRB & 0x003f) >> 0)
1043
1044/* 18006a - Map (Rotation Parameter B, Plane K,L)
1045 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1046       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1047       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1048       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1049       \----------|----------|----------|----------|----------|----------|----------|---------*/
1050
1051   #define STV_VDP2_MPKLRB (m_vdp2_regs[0x06a/2])
1052
1053   /* R0MPL5 = lower 6 bits of Map Address of Plane L of Tilemap RBG0 */
1054   #define STV_VDP2_RBMPL ((STV_VDP2_MPKLRB & 0x3f00) >> 8)
1055
1056   /* R0MPK5 = lower 6 bits of Map Address of Plane K of Tilemap RBG0 */
1057   #define STV_VDP2_RBMPK ((STV_VDP2_MPKLRB & 0x003f) >> 0)
1058
1059/* 18006c - Map (Rotation Parameter B, Plane M,N)
1060 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1061       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1062       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1063       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1064       \----------|----------|----------|----------|----------|----------|----------|---------*/
1065
1066   #define STV_VDP2_MPMNRB (m_vdp2_regs[0x06c/2])
1067
1068   /* R0MPN5 = lower 6 bits of Map Address of Plane N of Tilemap RBG0 */
1069   #define STV_VDP2_RBMPN ((STV_VDP2_MPMNRB & 0x3f00) >> 8)
1070
1071   /* R0MPM5 = lower 6 bits of Map Address of Plane M of Tilemap RBG0 */
1072   #define STV_VDP2_RBMPM ((STV_VDP2_MPMNRB & 0x003f) >> 0)
1073
1074/* 18006e - Map (Rotation Parameter B, Plane O,P)
1075 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1076       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1077       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1078       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1079       \----------|----------|----------|----------|----------|----------|----------|---------*/
1080
1081   #define STV_VDP2_MPOPRB (m_vdp2_regs[0x06e/2])
1082
1083   /* R0MPP5 = lower 6 bits of Map Address of Plane P of Tilemap RBG0 */
1084   #define STV_VDP2_RBMPP ((STV_VDP2_MPOPRB & 0x3f00) >> 8)
1085
1086   /* R0MPO5 = lower 6 bits of Map Address of Plane O of Tilemap RBG0 */
1087   #define STV_VDP2_RBMPO ((STV_VDP2_MPOPRB & 0x003f) >> 0)
1088
1089/* 180070 - SCXIN0 - Screen Scroll (NBG0, Horizontal Integer Part)
1090 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1091       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1092       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1093       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1094       \----------|----------|----------|----------|----------|----------|----------|---------*/
1095
1096   #define STV_VDP2_SCXIN0 (m_vdp2_regs[0x070/2])
1097
1098
1099/* 180072 - Screen Scroll (NBG0, Horizontal Fractional Part)
1100 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1101       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1102       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1103       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1104       \----------|----------|----------|----------|----------|----------|----------|---------*/
1105
1106   #define STV_VDP2_SCXDN0 (m_vdp2_regs[0x072/2])
1107
1108/* 180074 - SCYIN0 - Screen Scroll (NBG0, Vertical Integer Part)
1109 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1110       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1111       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1112       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1113       \----------|----------|----------|----------|----------|----------|----------|---------*/
1114   #define STV_VDP2_SCYIN0 (m_vdp2_regs[0x074/2])
1115
1116
1117/* 180076 - Screen Scroll (NBG0, Vertical Fractional Part)
1118 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1119       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1120       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1121       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1122       \----------|----------|----------|----------|----------|----------|----------|---------*/
1123
1124   #define STV_VDP2_SCYDN0 (m_vdp2_regs[0x076/2])
1125
1126/* 180078 - Coordinate Inc (NBG0, Horizontal Integer Part)
1127 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1128       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1129       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1130       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1131       \----------|----------|----------|----------|----------|----------|----------|---------*/
1132
1133   #define STV_VDP2_ZMXIN0 (m_vdp2_regs[0x078/2])
1134
1135   #define STV_VDP2_N0ZMXI ((STV_VDP2_ZMXIN0 & 0x0007) >> 0)
1136
1137/* 18007a - Coordinate Inc (NBG0, Horizontal Fractional Part)
1138 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1139       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1140       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1141       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1142       \----------|----------|----------|----------|----------|----------|----------|---------*/
1143
1144   #define STV_VDP2_ZMXDN0 (m_vdp2_regs[0x07a/2])
1145
1146   #define STV_VDP2_N0ZMXD ((STV_VDP2_ZMXDN0 >> 8)& 0xff)
1147   #define STV_VDP2_ZMXN0  (((STV_VDP2_N0ZMXI<<16) | (STV_VDP2_N0ZMXD<<8))  & 0x0007ff00)
1148
1149
1150/* 18007c - Coordinate Inc (NBG0, Vertical Integer Part)
1151 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1152       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1153       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1154       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1155       \----------|----------|----------|----------|----------|----------|----------|---------*/
1156
1157   #define STV_VDP2_ZMYIN0 (m_vdp2_regs[0x07c/2])
1158
1159   #define STV_VDP2_N0ZMYI ((STV_VDP2_ZMYIN0 & 0x0007) >> 0)
1160
1161/* 18007e - Coordinate Inc (NBG0, Vertical Fractional Part)
1162 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1163       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1164       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1165       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1166       \----------|----------|----------|----------|----------|----------|----------|---------*/
1167
1168   #define STV_VDP2_ZMYDN0 (m_vdp2_regs[0x07e/2])
1169
1170   #define STV_VDP2_N0ZMYD ((STV_VDP2_ZMYDN0 >> 8)& 0xff)
1171   #define STV_VDP2_ZMYN0  (((STV_VDP2_N0ZMYI<<16) | (STV_VDP2_N0ZMYD<<8))  & 0x0007ff00)
1172
1173/* 180080 - SCXIN1 - Screen Scroll (NBG1, Horizontal Integer Part)
1174 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1175       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1176       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1177       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1178       \----------|----------|----------|----------|----------|----------|----------|---------*/
1179
1180   #define STV_VDP2_SCXIN1 (m_vdp2_regs[0x080/2])
1181
1182/* 180082 - Screen Scroll (NBG1, Horizontal Fractional Part)
1183 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1184       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1185       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1186       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1187       \----------|----------|----------|----------|----------|----------|----------|---------*/
1188
1189   #define STV_VDP2_SCXDN1 (m_vdp2_regs[0x082/2])
1190
1191/* 180084 - SCYIN1 - Screen Scroll (NBG1, Vertical Integer Part)
1192 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1193       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1194       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1195       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1196       \----------|----------|----------|----------|----------|----------|----------|---------*/
1197
1198   #define STV_VDP2_SCYIN1 (m_vdp2_regs[0x084/2])
1199
1200/* 180086 - Screen Scroll (NBG1, Vertical Fractional Part)
1201 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1202       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1203       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1204       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1205       \----------|----------|----------|----------|----------|----------|----------|---------*/
1206
1207   #define STV_VDP2_SCYDN1 (m_vdp2_regs[0x086/2])
1208
1209/* 180088 - Coordinate Inc (NBG1, Horizontal Integer Part)
1210 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1211       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1212       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1213       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1214       \----------|----------|----------|----------|----------|----------|----------|---------*/
1215
1216   #define STV_VDP2_ZMXIN1 (m_vdp2_regs[0x088/2])
1217
1218   #define STV_VDP2_N1ZMXI ((STV_VDP2_ZMXIN1 & 0x0007) >> 0)
1219
1220/* 18008a - Coordinate Inc (NBG1, Horizontal Fractional Part)
1221 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1222       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1223       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1224       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1225       \----------|----------|----------|----------|----------|----------|----------|---------*/
1226
1227   #define STV_VDP2_ZMXDN1 (m_vdp2_regs[0x08a/2])
1228
1229   #define STV_VDP2_N1ZMXD ((STV_VDP2_ZMXDN1 >> 8)& 0xff)
1230   #define STV_VDP2_ZMXN1  (((STV_VDP2_N1ZMXI<<16) | (STV_VDP2_N1ZMXD<<8)) & 0x0007ff00)
1231
1232/* 18008c - Coordinate Inc (NBG1, Vertical Integer Part)
1233 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1234       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1235       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1236       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1237       \----------|----------|----------|----------|----------|----------|----------|---------*/
1238
1239   #define STV_VDP2_ZMYIN1 (m_vdp2_regs[0x08c/2])
1240
1241   #define STV_VDP2_N1ZMYI ((STV_VDP2_ZMYIN1 & 0x0007) >> 0)
1242
1243/* 18008e - Coordinate Inc (NBG1, Vertical Fractional Part)
1244 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1245       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1246       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1247       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1248       \----------|----------|----------|----------|----------|----------|----------|---------*/
1249
1250   #define STV_VDP2_ZMYDN1 (m_vdp2_regs[0x08e/2])
1251
1252   #define STV_VDP2_N1ZMYD ((STV_VDP2_ZMYDN1 >> 8)& 0xff)
1253   #define STV_VDP2_ZMYN1  (((STV_VDP2_N1ZMYI<<16) | (STV_VDP2_N1ZMYD<<8)) & 0x007ff00)
1254
1255/* 180090 - SCXN2 - Screen Scroll (NBG2, Horizontal)
1256 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1257       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1258       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1259       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1260       \----------|----------|----------|----------|----------|----------|----------|---------*/
1261
1262   #define STV_VDP2_SCXN2 (m_vdp2_regs[0x090/2])
1263
1264/* 180092 - SCYN2 - Screen Scroll (NBG2, Vertical)
1265 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1266       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1267       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1268       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1269       \----------|----------|----------|----------|----------|----------|----------|---------*/
1270
1271   #define STV_VDP2_SCYN2 (m_vdp2_regs[0x092/2])
1272
1273/* 180094 - SCXN3 - Screen Scroll (NBG3, Horizontal)
1274 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1275       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1276       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1277       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1278       \----------|----------|----------|----------|----------|----------|----------|---------*/
1279
1280   #define STV_VDP2_SCXN3 (m_vdp2_regs[0x094/2])
1281
1282/* 180096 - SCYN3 - Screen Scroll (NBG3, Vertical)
1283 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1284       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1285       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1286       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1287       \----------|----------|----------|----------|----------|----------|----------|---------*/
1288
1289   #define STV_VDP2_SCYN3 (m_vdp2_regs[0x096/2])
1290
1291/* 180098 - Reduction Enable
1292 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1293       |    --    |    --    |    --    |    --    |    --    |    --    | N1ZMQT   | N1ZMHF   |
1294       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1295       |    --    |    --    |    --    |    --    |    --    |    --    | N0ZMQT   | N0ZMHF   |
1296       \----------|----------|----------|----------|----------|----------|----------|---------*/
1297
1298   #define STV_VDP2_ZMCTL (m_vdp2_regs[0x098/2])
1299
1300   #define STV_VDP2_N1ZMQT  ((STV_VDP2_ZMCTL & 0x0200) >> 9)
1301   #define STV_VDP2_N1ZMHF  ((STV_VDP2_ZMCTL & 0x0100) >> 8)
1302   #define STV_VDP2_N0ZMQT  ((STV_VDP2_ZMCTL & 0x0002) >> 1)
1303   #define STV_VDP2_N0ZMHF  ((STV_VDP2_ZMCTL & 0x0001) >> 0)
1304
1305/* 18009a - Line and Vertical Cell Scroll Control (NBG0, NBG1)
1306 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1307       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1308       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1309       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1310       \----------|----------|----------|----------|----------|----------|----------|---------*/
1311
1312   #define STV_VDP2_SCRCTL (m_vdp2_regs[0x09a/2])
1313
1314   #define STV_VDP2_N1LSS  ((STV_VDP2_SCRCTL & 0x3000) >> 12)
1315   #define STV_VDP2_N1LZMX ((STV_VDP2_SCRCTL & 0x0800) >> 11)
1316   #define STV_VDP2_N1LSCY ((STV_VDP2_SCRCTL & 0x0400) >> 10)
1317   #define STV_VDP2_N1LSCX ((STV_VDP2_SCRCTL & 0x0200) >> 9)
1318   #define STV_VDP2_N1VCSC ((STV_VDP2_SCRCTL & 0x0100) >> 8)
1319   #define STV_VDP2_N0LSS  ((STV_VDP2_SCRCTL & 0x0030) >> 4)
1320   #define STV_VDP2_N0LZMX ((STV_VDP2_SCRCTL & 0x0008) >> 3)
1321   #define STV_VDP2_N0LSCY ((STV_VDP2_SCRCTL & 0x0004) >> 2)
1322   #define STV_VDP2_N0LSCX ((STV_VDP2_SCRCTL & 0x0002) >> 1)
1323   #define STV_VDP2_N0VCSC ((STV_VDP2_SCRCTL & 0x0001) >> 0)
1324
1325/* 18009c - Vertical Cell Table Address (NBG0, NBG1)
1326 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1327       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1328       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1329       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1330       \----------|----------|----------|----------|----------|----------|----------|---------*/
1331
1332   #define STV_VDP2_VCSTAU (m_vdp2_regs[0x09c/2] & 7)
1333
1334
1335/* 18009e - Vertical Cell Table Address (NBG0, NBG1)
1336 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1337       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1338       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1339       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1340       \----------|----------|----------|----------|----------|----------|----------|---------*/
1341
1342   #define STV_VDP2_VCSTAL (m_vdp2_regs[0x09e/2])
1343
1344
1345/* 1800a0 - LSTA0U - Line Scroll Table Address (NBG0)
1346 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1347       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1348       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1349       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1350       \----------|----------|----------|----------|----------|----------|----------|---------*/
1351
1352   /*bit 2 unused when VRAM = 4 Mbits*/
1353   #define STV_VDP2_LSTA0U (m_vdp2_regs[0x0a0/2] & 7)
1354
1355/* 1800a2 - LSTA0L - Line Scroll Table Address (NBG0)
1356 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1357       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1358       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1359       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1360       \----------|----------|----------|----------|----------|----------|----------|---------*/
1361
1362   #define STV_VDP2_LSTA0L (m_vdp2_regs[0x0a2/2])
1363
1364/* 1800a4 - LSTA1U - Line Scroll Table Address (NBG1)
1365 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1366       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1367       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1368       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1369       \----------|----------|----------|----------|----------|----------|----------|---------*/
1370
1371   /*bit 2 unused when VRAM = 4 Mbits*/
1372   #define STV_VDP2_LSTA1U (m_vdp2_regs[0x0a4/2] & 7)
1373
1374/* 1800a6 - LSTA1L - Line Scroll Table Address (NBG1)
1375 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1376       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1377       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1378       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1379       \----------|----------|----------|----------|----------|----------|----------|---------*/
1380
1381   #define STV_VDP2_LSTA1L (m_vdp2_regs[0x0a6/2])
1382
1383/* 1800a8 - LCTAU - Line Colour Screen Table Address
1384 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1385       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1386       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1387       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1388       \----------|----------|----------|----------|----------|----------|----------|---------*/
1389
1390   #define STV_VDP2_LCTAU  (m_vdp2_regs[0x0a8/2])
1391   #define STV_VDP2_LCCLMD ((STV_VDP2_LCTAU & 0x8000) >> 15)
1392
1393/* 1800aa - LCTAL - Line Colour Screen Table Address
1394 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1395       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1396       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1397       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1398       \----------|----------|----------|----------|----------|----------|----------|---------*/
1399   #define STV_VDP2_LCTAL  (m_vdp2_regs[0x0aa/2])
1400
1401   #define STV_VDP2_LCTA   (((STV_VDP2_LCTAU & 0x0007) << 16) | (STV_VDP2_LCTAL & 0xffff))
1402
1403/* 1800ac - Back Screen Table Address
1404 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1405       |  BKCLMD  |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1406       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1407       |    --    |    --    |    --    |    --    |    --    |  BKTA18  |  BKTA17  |  BKTA16  |
1408       \----------|----------|----------|----------|----------|----------|----------|---------*/
1409
1410   #define STV_VDP2_BKTAU  (m_vdp2_regs[0x0ac/2])
1411
1412   #define STV_VDP2_BKCLMD ((STV_VDP2_BKTAU & 0x8000) >> 15)
1413
1414
1415/* 1800ae - Back Screen Table Address
1416 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1417       |  BKTA15  |  BKTA14  |  BKTA13  |  BKTA12  |  BKTA11  |  BKTA10  |  BKTA9   |  BKTA8   |
1418       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1419       |  BKTA7   |  BKTA7   |  BKTA6   |  BKTA5   |  BKTA4   |  BKTA3   |  BKTA2   |  BKTA0   |
1420       \----------|----------|----------|----------|----------|----------|----------|---------*/
1421
1422   #define STV_VDP2_BKTAL  (m_vdp2_regs[0x0ae/2])
1423
1424   #define STV_VDP2_BKTA   (((STV_VDP2_BKTAU & 0x0007) << 16) | (STV_VDP2_BKTAL & 0xffff))
1425
1426/* 1800b0 - RPMD - Rotation Parameter Mode
1427 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1428       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1429       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1430       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1431       \----------|----------|----------|----------|----------|----------|----------|---------*/
1432
1433   #define STV_VDP2_RPMD   ((m_vdp2_regs[0x0b0/2]) & 0x0003)
1434
1435/* 1800b2 - RPRCTL - Rotation Parameter Read Control
1436 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1437       |    --    |    --    |    --    |    --    |    --    | RBKASTRE | RBYSTRE  | RBXSTRE  |
1438       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1439       |    --    |    --    |    --    |    --    |    --    | RAKASTRE | RAYSTRE  | RBXSTRE  |
1440       \----------|----------|----------|----------|----------|----------|----------|---------*/
1441
1442   #define STV_VDP2_RPRCTL     (m_vdp2_regs[0x0b2/2])
1443   #define STV_VDP2_RBKASTRE   ((STV_VDP2_RPRCTL & 0x0400) >> 10)
1444   #define STV_VDP2_RBYSTRE    ((STV_VDP2_RPRCTL & 0x0200) >> 9)
1445   #define STV_VDP2_RBXSTRE    ((STV_VDP2_RPRCTL & 0x0100) >> 8)
1446   #define STV_VDP2_RAKASTRE   ((STV_VDP2_RPRCTL & 0x0004) >> 2)
1447   #define STV_VDP2_RAYSTRE    ((STV_VDP2_RPRCTL & 0x0002) >> 1)
1448   #define STV_VDP2_RAXSTRE    ((STV_VDP2_RPRCTL & 0x0001) >> 0)
1449
1450/* 1800b4 - KTCTL - Coefficient Table Control
1451 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1452       |    --    |    --    |    --    |  RBKLCE  |  RBKMD1  |  RBKMD0  |  RBKDBS  |   RBKTE  |
1453       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1454       |    --    |    --    |    --    |  RAKLCE  |  RAKMD1  |  RAKMD0  |  RAKDBS  |   RAKTE  |
1455       \----------|----------|----------|----------|----------|----------|----------|---------*/
1456
1457   #define STV_VDP2_KTCTL  (m_vdp2_regs[0x0b4/2])
1458   #define STV_VDP2_RBKLCE ((STV_VDP2_KTCTL & 0x1000) >> 12)
1459   #define STV_VDP2_RBKMD  ((STV_VDP2_KTCTL & 0x0c00) >> 10)
1460   #define STV_VDP2_RBKDBS ((STV_VDP2_KTCTL & 0x0200) >> 9)
1461   #define STV_VDP2_RBKTE  ((STV_VDP2_KTCTL & 0x0100) >> 8)
1462   #define STV_VDP2_RAKLCE ((STV_VDP2_KTCTL & 0x0010) >> 4)
1463   #define STV_VDP2_RAKMD  ((STV_VDP2_KTCTL & 0x000c) >> 2)
1464   #define STV_VDP2_RAKDBS ((STV_VDP2_KTCTL & 0x0002) >> 1)
1465   #define STV_VDP2_RAKTE  ((STV_VDP2_KTCTL & 0x0001) >> 0)
1466
1467/* 1800b6 - KTAOF - Coefficient Table Address Offset (Rotation Parameter A,B)
1468 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1469       |    --    |    --    |    --    |    --    |    --    | RBKTAOS2 | RBKTAOS1 | RBKTAOS0 |
1470       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1471       |    --    |    --    |    --    |    --    |    --    | RAKTAOS2 | RAKTAOS1 | RAKTAOS0 |
1472       \----------|----------|----------|----------|----------|----------|----------|---------*/
1473
1474   #define STV_VDP2_KTAOF  (m_vdp2_regs[0x0b6/2])
1475   #define STV_VDP2_RBKTAOS ((STV_VDP2_KTAOF & 0x0700) >> 8)
1476   #define STV_VDP2_RAKTAOS ((STV_VDP2_KTAOF & 0x0007) >> 0)
1477
1478/* 1800b8 - OVPNRA - Screen Over Pattern Name (Rotation Parameter A)
1479 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1480       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1481       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1482       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1483       \----------|----------|----------|----------|----------|----------|----------|---------*/
1484
1485   #define STV_VDP2_OVPNRA (m_vdp2_regs[0x0b8/2])
1486
1487/* 1800ba - Screen Over Pattern Name (Rotation Parameter B)
1488 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1489       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1490       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1491       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1492       \----------|----------|----------|----------|----------|----------|----------|---------*/
1493
1494   #define STV_VDP2_OVPNRB (m_vdp2_regs[0x0ba/2])
1495
1496/* 1800bc - RPTAU - Rotation Parameter Table Address (Rotation Parameter A,B)
1497 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1498       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1499       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1500       |    --    |    --    |    --    |    --    |    --    |  RPTA18  |  RPTA17  |  RPTA16  |
1501       \----------|----------|----------|----------|----------|----------|----------|---------*/
1502   #define STV_VDP2_RPTAU  (m_vdp2_regs[0x0bc/2] & 7)
1503
1504/* 1800be - RPTAL - Rotation Parameter Table Address (Rotation Parameter A,B)
1505 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1506       |  RPTA15  |  RPTA14  |  RPTA13  |  RPTA12  |  RPTA11  |  RPTA10  |   RPTA9  |   RPTA8  |
1507       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1508       |   RPTA7  |   RPTA6  |   RPTA5  |   RPTA4  |   RPTA3  |   RPTA2  |   RPTA1  |    --    |
1509       \----------|----------|----------|----------|----------|----------|----------|---------*/
1510
1511   #define STV_VDP2_RPTAL  (m_vdp2_regs[0x0be/2] & 0x0000ffff)
1512
1513/* 1800c0 - Window Position (W0, Horizontal Start Point)
1514 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1515       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1516       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1517       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1518       \----------|----------|----------|----------|----------|----------|----------|---------*/
1519
1520   #define STV_VDP2_WPSX0 (m_vdp2_regs[0x0c0/2])
1521
1522   #define STV_VDP2_W0SX ((STV_VDP2_WPSX0 & 0x03ff) >> 0)
1523
1524/* 1800c2 - Window Position (W0, Vertical Start Point)
1525 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1526       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1527       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1528       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1529       \----------|----------|----------|----------|----------|----------|----------|---------*/
1530
1531   #define STV_VDP2_WPSY0 (m_vdp2_regs[0x0c2/2])
1532
1533   #define STV_VDP2_W0SY ((STV_VDP2_WPSY0 & 0x03ff) >> 0)
1534
1535/* 1800c4 - Window Position (W0, Horizontal End Point)
1536 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1537       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1538       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1539       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1540       \----------|----------|----------|----------|----------|----------|----------|---------*/
1541
1542   #define STV_VDP2_WPEX0 (m_vdp2_regs[0x0c4/2])
1543
1544   #define STV_VDP2_W0EX ((STV_VDP2_WPEX0 & 0x03ff) >> 0)
1545
1546/* 1800c6 - Window Position (W0, Vertical End Point)
1547 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1548       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1549       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1550       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1551       \----------|----------|----------|----------|----------|----------|----------|---------*/
1552
1553   #define STV_VDP2_WPEY0 (m_vdp2_regs[0x0c6/2])
1554
1555   #define STV_VDP2_W0EY ((STV_VDP2_WPEY0 & 0x03ff) >> 0)
1556
1557/* 1800c8 - Window Position (W1, Horizontal Start Point)
1558 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1559       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1560       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1561       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1562       \----------|----------|----------|----------|----------|----------|----------|---------*/
1563
1564   #define STV_VDP2_WPSX1 (m_vdp2_regs[0x0c8/2])
1565
1566   #define STV_VDP2_W1SX ((STV_VDP2_WPSX1 & 0x03ff) >> 0)
1567
1568/* 1800ca - Window Position (W1, Vertical Start Point)
1569 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1570       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1571       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1572       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1573       \----------|----------|----------|----------|----------|----------|----------|---------*/
1574
1575   #define STV_VDP2_WPSY1 (m_vdp2_regs[0x0ca/2])
1576
1577   #define STV_VDP2_W1SY ((STV_VDP2_WPSY1 & 0x03ff) >> 0)
1578
1579/* 1800cc - Window Position (W1, Horizontal End Point)
1580 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1581       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1582       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1583       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1584       \----------|----------|----------|----------|----------|----------|----------|---------*/
1585
1586   #define STV_VDP2_WPEX1 (m_vdp2_regs[0x0cc/2])
1587
1588   #define STV_VDP2_W1EX ((STV_VDP2_WPEX1 & 0x03ff) >> 0)
1589
1590/* 1800ce - Window Position (W1, Vertical End Point)
1591 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1592       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1593       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1594       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1595       \----------|----------|----------|----------|----------|----------|----------|---------*/
1596
1597   #define STV_VDP2_WPEY1 (m_vdp2_regs[0x0ce/2])
1598
1599   #define STV_VDP2_W1EY ((STV_VDP2_WPEY1 & 0x03ff) >> 0)
1600
1601/* 1800d0 - Window Control (NBG0, NBG1)
1602 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1603       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1604       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1605       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1606       \----------|----------|----------|----------|----------|----------|----------|---------*/
1607
1608   #define STV_VDP2_WCTLA (m_vdp2_regs[0x0d0/2])
1609   #define STV_VDP2_N1LOG ((STV_VDP2_WCTLA & 0x8000) >> 15)
1610   #define STV_VDP2_N1SWE ((STV_VDP2_WCTLA & 0x2000) >> 13)
1611   #define STV_VDP2_N1SWA ((STV_VDP2_WCTLA & 0x1000) >> 12)
1612   #define STV_VDP2_N1W1E ((STV_VDP2_WCTLA & 0x0800) >> 11)
1613   #define STV_VDP2_N1W1A ((STV_VDP2_WCTLA & 0x0400) >> 10)
1614   #define STV_VDP2_N1W0E ((STV_VDP2_WCTLA & 0x0200) >> 9)
1615   #define STV_VDP2_N1W0A ((STV_VDP2_WCTLA & 0x0100) >> 8)
1616   #define STV_VDP2_N0LOG ((STV_VDP2_WCTLA & 0x0080) >> 7)
1617   #define STV_VDP2_N0SWE ((STV_VDP2_WCTLA & 0x0020) >> 5)
1618   #define STV_VDP2_N0SWA ((STV_VDP2_WCTLA & 0x0010) >> 4)
1619   #define STV_VDP2_N0W1E ((STV_VDP2_WCTLA & 0x0008) >> 3)
1620   #define STV_VDP2_N0W1A ((STV_VDP2_WCTLA & 0x0004) >> 2)
1621   #define STV_VDP2_N0W0E ((STV_VDP2_WCTLA & 0x0002) >> 1)
1622   #define STV_VDP2_N0W0A ((STV_VDP2_WCTLA & 0x0001) >> 0)
1623
1624/* 1800d2 - Window Control (NBG2, NBG3)
1625 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1626       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1627       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1628       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1629       \----------|----------|----------|----------|----------|----------|----------|---------*/
1630
1631   #define STV_VDP2_WCTLB (m_vdp2_regs[0x0d2/2])
1632   #define STV_VDP2_N3LOG ((STV_VDP2_WCTLB & 0x8000) >> 15)
1633   #define STV_VDP2_N3SWE ((STV_VDP2_WCTLB & 0x2000) >> 13)
1634   #define STV_VDP2_N3SWA ((STV_VDP2_WCTLB & 0x1000) >> 12)
1635   #define STV_VDP2_N3W1E ((STV_VDP2_WCTLB & 0x0800) >> 11)
1636   #define STV_VDP2_N3W1A ((STV_VDP2_WCTLB & 0x0400) >> 10)
1637   #define STV_VDP2_N3W0E ((STV_VDP2_WCTLB & 0x0200) >> 9)
1638   #define STV_VDP2_N3W0A ((STV_VDP2_WCTLB & 0x0100) >> 8)
1639   #define STV_VDP2_N2LOG ((STV_VDP2_WCTLB & 0x0080) >> 7)
1640   #define STV_VDP2_N2SWE ((STV_VDP2_WCTLB & 0x0020) >> 5)
1641   #define STV_VDP2_N2SWA ((STV_VDP2_WCTLB & 0x0010) >> 4)
1642   #define STV_VDP2_N2W1E ((STV_VDP2_WCTLB & 0x0008) >> 3)
1643   #define STV_VDP2_N2W1A ((STV_VDP2_WCTLB & 0x0004) >> 2)
1644   #define STV_VDP2_N2W0E ((STV_VDP2_WCTLB & 0x0002) >> 1)
1645   #define STV_VDP2_N2W0A ((STV_VDP2_WCTLB & 0x0001) >> 0)
1646
1647/* 1800d4 - Window Control (RBG0, Sprite)
1648 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1649       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1650       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1651       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1652       \----------|----------|----------|----------|----------|----------|----------|---------*/
1653
1654   #define STV_VDP2_WCTLC (m_vdp2_regs[0x0d4/2])
1655   #define STV_VDP2_SPLOG ((STV_VDP2_WCTLC & 0x8000) >> 15)
1656   #define STV_VDP2_SPSWE ((STV_VDP2_WCTLC & 0x2000) >> 13)
1657   #define STV_VDP2_SPSWA ((STV_VDP2_WCTLC & 0x1000) >> 12)
1658   #define STV_VDP2_SPW1E ((STV_VDP2_WCTLC & 0x0800) >> 11)
1659   #define STV_VDP2_SPW1A ((STV_VDP2_WCTLC & 0x0400) >> 10)
1660   #define STV_VDP2_SPW0E ((STV_VDP2_WCTLC & 0x0200) >> 9)
1661   #define STV_VDP2_SPW0A ((STV_VDP2_WCTLC & 0x0100) >> 8)
1662   #define STV_VDP2_R0LOG ((STV_VDP2_WCTLC & 0x0080) >> 7)
1663   #define STV_VDP2_R0SWE ((STV_VDP2_WCTLC & 0x0020) >> 5)
1664   #define STV_VDP2_R0SWA ((STV_VDP2_WCTLC & 0x0010) >> 4)
1665   #define STV_VDP2_R0W1E ((STV_VDP2_WCTLC & 0x0008) >> 3)
1666   #define STV_VDP2_R0W1A ((STV_VDP2_WCTLC & 0x0004) >> 2)
1667   #define STV_VDP2_R0W0E ((STV_VDP2_WCTLC & 0x0002) >> 1)
1668   #define STV_VDP2_R0W0A ((STV_VDP2_WCTLC & 0x0001) >> 0)
1669
1670/* 1800d6 - Window Control (Parameter Window, Colour Calc. Window)
1671 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1672       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1673       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1674       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1675       \----------|----------|----------|----------|----------|----------|----------|---------*/
1676
1677   #define STV_VDP2_WCTLD (m_vdp2_regs[0x0d6/2])
1678   #define STV_VDP2_CCLOG ((STV_VDP2_WCTLD & 0x8000) >> 15)
1679   #define STV_VDP2_CCSWE ((STV_VDP2_WCTLD & 0x2000) >> 13)
1680   #define STV_VDP2_CCSWA ((STV_VDP2_WCTLD & 0x1000) >> 12)
1681   #define STV_VDP2_CCW1E ((STV_VDP2_WCTLD & 0x0800) >> 11)
1682   #define STV_VDP2_CCW1A ((STV_VDP2_WCTLD & 0x0400) >> 10)
1683   #define STV_VDP2_CCW0E ((STV_VDP2_WCTLD & 0x0200) >> 9)
1684   #define STV_VDP2_CCW0A ((STV_VDP2_WCTLD & 0x0100) >> 8)
1685   #define STV_VDP2_RPLOG ((STV_VDP2_WCTLD & 0x0080) >> 7)
1686   #define STV_VDP2_RPW1E ((STV_VDP2_WCTLD & 0x0008) >> 3)
1687   #define STV_VDP2_RPW1A ((STV_VDP2_WCTLD & 0x0004) >> 2)
1688   #define STV_VDP2_RPW0E ((STV_VDP2_WCTLD & 0x0002) >> 1)
1689   #define STV_VDP2_RPW0A ((STV_VDP2_WCTLD & 0x0001) >> 0)
1690
1691/* 1800d8 - Line Window Table Address (W0)
1692 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1693       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1694       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1695       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1696       \----------|----------|----------|----------|----------|----------|----------|---------*/
1697
1698   #define STV_VDP2_LWTA0U (m_vdp2_regs[0x0d8/2])
1699
1700   #define STV_VDP2_W0LWE  ((STV_VDP2_LWTA0U & 0x8000) >> 15)
1701
1702/* 1800da - Line Window Table Address (W0)
1703 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1704       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1705       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1706       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1707       \----------|----------|----------|----------|----------|----------|----------|---------*/
1708
1709   #define STV_VDP2_LWTA0L (m_vdp2_regs[0x0da/2])
1710
1711   /* bit 19 isn't used when VRAM = 4 Mbit */
1712   #define STV_VDP2_W0LWTA (((STV_VDP2_LWTA0U & 0x0007) << 16) | (STV_VDP2_LWTA0L & 0xfffe))
1713
1714
1715/* 1800dc - Line Window Table Address (W1)
1716 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1717       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1718       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1719       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1720       \----------|----------|----------|----------|----------|----------|----------|---------*/
1721
1722   #define STV_VDP2_LWTA1U (m_vdp2_regs[0x0dc/2])
1723
1724   #define STV_VDP2_W1LWE  ((STV_VDP2_LWTA0U & 0x8000) >> 15)
1725
1726
1727/* 1800de - Line Window Table Address (W1)
1728 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1729       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1730       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1731       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1732       \----------|----------|----------|----------|----------|----------|----------|---------*/
1733
1734   #define STV_VDP2_LWTA1L (m_vdp2_regs[0x0de/2])
1735
1736   /* bit 19 isn't used when VRAM = 4 Mbit */
1737   #define STV_VDP2_W1LWTA (((STV_VDP2_LWTA1U & 0x0007) << 16) | (STV_VDP2_LWTA1L & 0xfffe))
1738
1739
1740/* 1800e0 - Sprite Control
1741 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1742       |    --    |    --    | SPCCCS1  | SPCCCS0  |    --    |  SPCCN2  |  SPCCN1  |  SPCCN0  |
1743       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1744       |    --    |    --    |  SPCLMD  | SPWINEN  |  SPTYPE3 |  SPTYPE2 |  SPTYPE1 |  SPTYPE0 |
1745       \----------|----------|----------|----------|----------|----------|----------|---------*/
1746
1747   #define STV_VDP2_SPCTL  (m_vdp2_regs[0xe0/2])
1748   #define STV_VDP2_SPCCCS     ((STV_VDP2_SPCTL & 0x3000) >> 12)
1749   #define STV_VDP2_SPCCN      ((STV_VDP2_SPCTL & 0x700) >> 8)
1750   #define STV_VDP2_SPCLMD     ((STV_VDP2_SPCTL & 0x20) >> 5)
1751   #define STV_VDP2_SPWINEN    ((STV_VDP2_SPCTL & 0x10) >> 4)
1752   #define STV_VDP2_SPTYPE     (STV_VDP2_SPCTL & 0xf)
1753
1754/* 1800e2 - Shadow Control
1755 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1756       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1757       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1758       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1759       \----------|----------|----------|----------|----------|----------|----------|---------*/
1760
1761   #define STV_VDP2_SDCTL  (m_vdp2_regs[0x0e2/2])
1762
1763/* 1800e4 - CRAOFA - Colour Ram Address Offset (NBG0 - NBG3)
1764 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1765       |    --    | N0CAOS2  | N3CAOS1  | N3CAOS0  |    --    | N2CAOS2  | N2CAOS1  | N2CAOS0  |
1766       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1767       |    --    | N1CAOS2  | N1CAOS1  | N1CAOS0  |    --    | N0CAOS2  | N0CAOS1  | N0CAOS0  |
1768       \----------|----------|----------|----------|----------|----------|----------|---------*/
1769
1770   #define STV_VDP2_CRAOFA (m_vdp2_regs[0x0e4/2])
1771
1772   /* NxCAOS =  */
1773   #define STV_VDP2_N0CAOS ((STV_VDP2_CRAOFA & 0x0007) >> 0)
1774   #define STV_VDP2_N1CAOS ((STV_VDP2_CRAOFA & 0x0070) >> 4)
1775   #define STV_VDP2_N2CAOS ((STV_VDP2_CRAOFA & 0x0700) >> 8)
1776   #define STV_VDP2_N3CAOS ((STV_VDP2_CRAOFA & 0x7000) >> 12)
1777
1778
1779/* 1800e6 - Colour Ram Address Offset (RBG0, SPRITE)
1780 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1781       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1782       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1783       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1784       \----------|----------|----------|----------|----------|----------|----------|---------*/
1785   #define STV_VDP2_CRAOFB (m_vdp2_regs[0x0e6/2])
1786   #define STV_VDP2_R0CAOS ((STV_VDP2_CRAOFB & 0x0007) >> 0)
1787   #define STV_VDP2_SPCAOS ((STV_VDP2_CRAOFB & 0x0070) >> 4)
1788
1789/* 1800e8 - LNCLEN - Line Colour Screen Enable
1790 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1791       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1792       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1793       |    --    |    --    |  SPLCEN  |  R0LCEN  |  N3LCEN  |  N2LCEN  |  N1LCEN  | N0LCEN   |
1794       \----------|----------|----------|----------|----------|----------|----------|---------*/
1795
1796   #define STV_VDP2_LNCLEN (m_vdp2_regs[0x0e8/2])
1797   #define STV_VDP2_SPLCEN ((STV_VDP2_LNCLEN & 0x0020) >> 5)
1798   #define STV_VDP2_R0LCEN ((STV_VDP2_LNCLEN & 0x0010) >> 4)
1799   #define STV_VDP2_N3LCEN ((STV_VDP2_LNCLEN & 0x0008) >> 3)
1800   #define STV_VDP2_N2LCEN ((STV_VDP2_LNCLEN & 0x0004) >> 2)
1801   #define STV_VDP2_N1LCEN ((STV_VDP2_LNCLEN & 0x0002) >> 1)
1802   #define STV_VDP2_N0LCEN ((STV_VDP2_LNCLEN & 0x0001) >> 0)
1803
1804/* 1800ea - Special Priority Mode
1805 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1806       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1807       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1808       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1809       \----------|----------|----------|----------|----------|----------|----------|---------*/
1810
1811   #define STV_VDP2_SFPRMD (m_vdp2_regs[0x0ea/2])
1812
1813
1814/* 1800ec - Colour Calculation Control
1815 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1816       |  BOKEN   |  BOKN2   |  BOKN1   |   BOKN0  |    --    |  EXCCEN  |  CCRTMD  |  CCMD    |
1817       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1818       |    --    |  SPCCEN  |  LCCCEN  |  R0CCEN  |  N3CCEN  |  N2CCEN  |  N1CCEN  |  N0CCEN  |
1819       \----------|----------|----------|----------|----------|----------|----------|---------*/
1820
1821   #define STV_VDP2_CCCR       (m_vdp2_regs[0x0ec/2])
1822   #define STV_VDP2_CCMD       ((STV_VDP2_CCCR & 0x100) >> 8)
1823   #define STV_VDP2_SPCCEN     ((STV_VDP2_CCCR & 0x40) >> 6)
1824   #define STV_VDP2_LCCCEN     ((STV_VDP2_CCCR & 0x20) >> 5)
1825   #define STV_VDP2_R0CCEN     ((STV_VDP2_CCCR & 0x10) >> 4)
1826   #define STV_VDP2_N3CCEN     ((STV_VDP2_CCCR & 0x8) >> 3)
1827   #define STV_VDP2_N2CCEN     ((STV_VDP2_CCCR & 0x4) >> 2)
1828   #define STV_VDP2_N1CCEN     ((STV_VDP2_CCCR & 0x2) >> 1)
1829   #define STV_VDP2_N0CCEN     ((STV_VDP2_CCCR & 0x1) >> 0)
1830
1831
1832/* 1800ee - Special Colour Calculation Mode
1833 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1834       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1835       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1836       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1837       \----------|----------|----------|----------|----------|----------|----------|---------*/
1838
1839   #define STV_VDP2_SFCCMD     (m_vdp2_regs[0x0ee/2])
1840
1841/* 1800f0 - Priority Number (Sprite 0,1)
1842 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1843       |    --    |    --    |    --    |    --    |    --    |  S1PRIN2 |  S1PRIN1 |  S1PRIN0 |
1844       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1845       |    --    |    --    |    --    |    --    |    --    |  S0PRIN2 |  S0PRIN1 |  S0PRIN0 |
1846       \----------|----------|----------|----------|----------|----------|----------|---------*/
1847
1848   #define STV_VDP2_PRISA      (m_vdp2_regs[0x0f0/2])
1849   #define STV_VDP2_S1PRIN     ((STV_VDP2_PRISA & 0x0700) >> 8)
1850   #define STV_VDP2_S0PRIN     ((STV_VDP2_PRISA & 0x0007) >> 0)
1851
1852/* 1800f2 - Priority Number (Sprite 2,3)
1853 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1854       |    --    |    --    |    --    |    --    |    --    |  S3PRIN2 |  S3PRIN1 |  S3PRIN0 |
1855       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1856       |    --    |    --    |    --    |    --    |    --    |  S2PRIN2 |  S2PRIN1 |  S2PRIN0 |
1857       \----------|----------|----------|----------|----------|----------|----------|---------*/
1858
1859   #define STV_VDP2_PRISB      (m_vdp2_regs[0x0f2/2])
1860   #define STV_VDP2_S3PRIN     ((STV_VDP2_PRISB & 0x0700) >> 8)
1861   #define STV_VDP2_S2PRIN     ((STV_VDP2_PRISB & 0x0007) >> 0)
1862
1863/* 1800f4 - Priority Number (Sprite 4,5)
1864 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1865       |    --    |    --    |    --    |    --    |    --    |  S5PRIN2 |  S5PRIN1 |  S5PRIN0 |
1866       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1867       |    --    |    --    |    --    |    --    |    --    |  S4PRIN2 |  S4PRIN1 |  S4PRIN0 |
1868       \----------|----------|----------|----------|----------|----------|----------|---------*/
1869
1870   #define STV_VDP2_PRISC      (m_vdp2_regs[0x0f4/2])
1871   #define STV_VDP2_S5PRIN     ((STV_VDP2_PRISC & 0x0700) >> 8)
1872   #define STV_VDP2_S4PRIN     ((STV_VDP2_PRISC & 0x0007) >> 0)
1873
1874/* 1800f6 - Priority Number (Sprite 6,7)
1875 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1876       |    --    |    --    |    --    |    --    |    --    |  S7PRIN2 |  S7PRIN1 |  S7PRIN0 |
1877       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1878       |    --    |    --    |    --    |    --    |    --    |  S6PRIN2 |  S6PRIN1 |  S6PRIN0 |
1879       \----------|----------|----------|----------|----------|----------|----------|---------*/
1880
1881   #define STV_VDP2_PRISD      (m_vdp2_regs[0x0f6/2])
1882   #define STV_VDP2_S7PRIN     ((STV_VDP2_PRISD & 0x0700) >> 8)
1883   #define STV_VDP2_S6PRIN     ((STV_VDP2_PRISD & 0x0007) >> 0)
1884
1885
1886/* 1800f8 - PRINA - Priority Number (NBG 0,1)
1887 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1888       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1889       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1890       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1891       \----------|----------|----------|----------|----------|----------|----------|---------*/
1892
1893   #define STV_VDP2_PRINA (m_vdp2_regs[0x0f8/2])
1894
1895   #define STV_VDP2_N1PRIN ((STV_VDP2_PRINA & 0x0700) >> 8)
1896   #define STV_VDP2_N0PRIN ((STV_VDP2_PRINA & 0x0007) >> 0)
1897
1898/* 1800fa - PRINB - Priority Number (NBG 2,3)
1899 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1900       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1901       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1902       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1903       \----------|----------|----------|----------|----------|----------|----------|---------*/
1904
1905   #define STV_VDP2_PRINB (m_vdp2_regs[0x0fa/2])
1906
1907   #define STV_VDP2_N3PRIN ((STV_VDP2_PRINB & 0x0700) >> 8)
1908   #define STV_VDP2_N2PRIN ((STV_VDP2_PRINB & 0x0007) >> 0)
1909
1910/* 1800fc - Priority Number (RBG0)
1911 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1912       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1913       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1914       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1915       \----------|----------|----------|----------|----------|----------|----------|---------*/
1916   #define STV_VDP2_PRIR (m_vdp2_regs[0x0fc/2])
1917
1918   #define STV_VDP2_R0PRIN ((STV_VDP2_PRIR & 0x0007) >> 0)
1919
1920/* 1800fe - Reserved
1921 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1922       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1923       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1924       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1925       \----------|----------|----------|----------|----------|----------|----------|---------*/
1926
1927/* 180100 - Colour Calculation Ratio (Sprite 0,1)
1928 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1929       |    --    |    --    |    --    |  S1CCRT4 |  S1CCRT3 |  S1CCRT2 |  S1CCRT1 |  S1CCRT0 |
1930       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1931       |    --    |    --    |    --    |  S0CCRT4 |  S0CCRT3 |  S0CCRT2 |  S0CCRT1 |  S0CCRT0 |
1932       \----------|----------|----------|----------|----------|----------|----------|---------*/
1933
1934   #define STV_VDP2_CCRSA      (m_vdp2_regs[0x100/2])
1935   #define STV_VDP2_S1CCRT     ((STV_VDP2_CCRSA & 0x1f00) >> 8)
1936   #define STV_VDP2_S0CCRT     ((STV_VDP2_CCRSA & 0x001f) >> 0)
1937
1938/* 180102 - Colour Calculation Ratio (Sprite 2,3)
1939 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1940       |    --    |    --    |    --    |  S3CCRT4 |  S3CCRT3 |  S3CCRT2 |  S3CCRT1 |  S3CCRT0 |
1941       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1942       |    --    |    --    |    --    |  S2CCRT4 |  S2CCRT3 |  S2CCRT2 |  S2CCRT1 |  S2CCRT0 |
1943       \----------|----------|----------|----------|----------|----------|----------|---------*/
1944
1945   #define STV_VDP2_CCRSB      (m_vdp2_regs[0x102/2])
1946   #define STV_VDP2_S3CCRT     ((STV_VDP2_CCRSB & 0x1f00) >> 8)
1947   #define STV_VDP2_S2CCRT     ((STV_VDP2_CCRSB & 0x001f) >> 0)
1948
1949/* 180104 - Colour Calculation Ratio (Sprite 4,5)
1950 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1951       |    --    |    --    |    --    |  S5CCRT4 |  S5CCRT3 |  S5CCRT2 |  S5CCRT1 |  S5CCRT0 |
1952       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1953       |    --    |    --    |    --    |  S4CCRT4 |  S4CCRT3 |  S4CCRT2 |  S4CCRT1 |  S4CCRT0 |
1954       \----------|----------|----------|----------|----------|----------|----------|---------*/
1955
1956   #define STV_VDP2_CCRSC      (m_vdp2_regs[0x104/2])
1957   #define STV_VDP2_S5CCRT     ((STV_VDP2_CCRSC & 0x1f00) >> 8)
1958   #define STV_VDP2_S4CCRT     ((STV_VDP2_CCRSC & 0x001f) >> 0)
1959
1960/* 180106 - Colour Calculation Ratio (Sprite 6,7)
1961 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1962       |    --    |    --    |    --    |  S7CCRT4 |  S7CCRT3 |  S7CCRT2 |  S7CCRT1 |  S7CCRT0 |
1963       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1964       |    --    |    --    |    --    |  S6CCRT4 |  S6CCRT3 |  S6CCRT2 |  S6CCRT1 |  S6CCRT0 |
1965       \----------|----------|----------|----------|----------|----------|----------|---------*/
1966
1967   #define STV_VDP2_CCRSD      (m_vdp2_regs[0x106/2])
1968   #define STV_VDP2_S7CCRT     ((STV_VDP2_CCRSD & 0x1f00) >> 8)
1969   #define STV_VDP2_S6CCRT     ((STV_VDP2_CCRSD & 0x001f) >> 0)
1970
1971/* 180108 - Colour Calculation Ratio (NBG 0,1)
1972 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1973       |    --    |    --    |    --    | N1CCRT4  | N1CCRT3  | N1CCRT2  | N1CCRT1  | N1CCRT0  |
1974       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1975       |    --    |    --    |    --    | N0CCRT4  | N0CCRT3  | N0CCRT2  | N0CCRT1  | N0CCRT0  |
1976       \----------|----------|----------|----------|----------|----------|----------|---------*/
1977
1978   #define STV_VDP2_CCRNA  (m_vdp2_regs[0x108/2])
1979   #define STV_VDP2_N1CCRT ((STV_VDP2_CCRNA & 0x1f00) >> 8)
1980   #define STV_VDP2_N0CCRT (STV_VDP2_CCRNA & 0x1f)
1981
1982/* 18010a - Colour Calculation Ratio (NBG 2,3)
1983 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1984       |    --    |    --    |    --    | N3CCRT4  | N3CCRT3  | N3CCRT2  | N3CCRT1  | N3CCRT0  |
1985       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1986       |    --    |    --    |    --    | N2CCRT4  | N2CCRT3  | N2CCRT2  | N2CCRT1  | N2CCRT0  |
1987       \----------|----------|----------|----------|----------|----------|----------|---------*/
1988
1989   #define STV_VDP2_CCRNB  (m_vdp2_regs[0x10a/2])
1990   #define STV_VDP2_N3CCRT ((STV_VDP2_CCRNB & 0x1f00) >> 8)
1991   #define STV_VDP2_N2CCRT (STV_VDP2_CCRNB & 0x1f)
1992
1993/* 18010c - Colour Calculation Ratio (RBG 0)
1994 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1995       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1996       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1997       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1998       \----------|----------|----------|----------|----------|----------|----------|---------*/
1999
2000   #define STV_VDP2_CCRR   (m_vdp2_regs[0x10c/2])
2001   #define STV_VDP2_R0CCRT (STV_VDP2_CCRR & 0x1f)
2002
2003/* 18010e - Colour Calculation Ratio (Line Colour Screen, Back Colour Screen)
2004 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
2005       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
2006       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
2007       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
2008       \----------|----------|----------|----------|----------|----------|----------|---------*/
2009
2010/* 180110 - Colour Offset Enable
2011 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
2012       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
2013       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
2014       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
2015       \----------|----------|----------|----------|----------|----------|----------|---------*/
2016
2017   #define STV_VDP2_CLOFEN (m_vdp2_regs[0x110/2])
2018   #define STV_VDP2_N0COEN ((STV_VDP2_CLOFEN & 0x01) >> 0)
2019   #define STV_VDP2_N1COEN ((STV_VDP2_CLOFEN & 0x02) >> 1)
2020   #define STV_VDP2_N2COEN ((STV_VDP2_CLOFEN & 0x04) >> 2)
2021   #define STV_VDP2_N3COEN ((STV_VDP2_CLOFEN & 0x08) >> 3)
2022   #define STV_VDP2_R0COEN ((STV_VDP2_CLOFEN & 0x10) >> 4)
2023   #define STV_VDP2_BKCOEN ((STV_VDP2_CLOFEN & 0x20) >> 5)
2024   #define STV_VDP2_SPCOEN ((STV_VDP2_CLOFEN & 0x40) >> 6)
2025
2026/* 180112 - Colour Offset Select
2027 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
2028       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
2029       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
2030       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
2031       \----------|----------|----------|----------|----------|----------|----------|---------*/
2032
2033   #define STV_VDP2_CLOFSL (m_vdp2_regs[0x112/2])
2034   #define STV_VDP2_N0COSL ((STV_VDP2_CLOFSL & 0x01) >> 0)
2035   #define STV_VDP2_N1COSL ((STV_VDP2_CLOFSL & 0x02) >> 1)
2036   #define STV_VDP2_N2COSL ((STV_VDP2_CLOFSL & 0x04) >> 2)
2037   #define STV_VDP2_N3COSL ((STV_VDP2_CLOFSL & 0x08) >> 3)
2038   #define STV_VDP2_R0COSL ((STV_VDP2_CLOFSL & 0x10) >> 4)
2039   #define STV_VDP2_BKCOSL ((STV_VDP2_CLOFSL & 0x20) >> 5)
2040   #define STV_VDP2_SPCOSL ((STV_VDP2_CLOFSL & 0x40) >> 6)
2041
2042/* 180114 - Colour Offset A (Red)
2043 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
2044       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
2045       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
2046       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
2047       \----------|----------|----------|----------|----------|----------|----------|---------*/
2048
2049   #define STV_VDP2_COAR (m_vdp2_regs[0x114/2])
2050
2051/* 180116 - Colour Offset A (Green)
2052 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
2053       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
2054       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
2055       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
2056       \----------|----------|----------|----------|----------|----------|----------|---------*/
2057   #define STV_VDP2_COAG (m_vdp2_regs[0x116/2])
2058
2059/* 180118 - Colour Offset A (Blue)
2060 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
2061       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
2062       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
2063       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
2064       \----------|----------|----------|----------|----------|----------|----------|---------*/
2065
2066   #define STV_VDP2_COAB (m_vdp2_regs[0x118/2])
2067
2068/* 18011a - Colour Offset B (Red)
2069 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
2070       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
2071       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
2072       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
2073       \----------|----------|----------|----------|----------|----------|----------|---------*/
2074   #define STV_VDP2_COBR (m_vdp2_regs[0x11a/2])
2075
2076/* 18011c - Colour Offset B (Green)
2077 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
2078       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
2079       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
2080       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
2081       \----------|----------|----------|----------|----------|----------|----------|---------*/
2082   #define STV_VDP2_COBG (m_vdp2_regs[0x11c/2])
2083
2084/* 18011e - Colour Offset B (Blue)
2085 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
2086       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
2087       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
2088       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
2089       \----------|----------|----------|----------|----------|----------|----------|---------*/
2090   #define STV_VDP2_COBB (m_vdp2_regs[0x11e/2])
2091
2092
2093#define STV_VDP2_RBG_ROTATION_PARAMETER_A   1
2094#define STV_VDP2_RBG_ROTATION_PARAMETER_B   2
2095
2096
2097#define mul_fixed32( a, b ) mul_32x32_shift( a, b, 16 )
2098
2099void saturn_state::stv_vdp2_fill_rotation_parameter_table( UINT8 rot_parameter )
2100{
2101   UINT32 address = 0;
2102
2103   address = (((STV_VDP2_RPTAU << 16) | STV_VDP2_RPTAL) << 1);
2104   if ( rot_parameter == 1 )
2105   {
2106      address &= ~0x00000080;
2107   }
2108   else if ( rot_parameter == 2 )
2109   {
2110      address |= 0x00000080;
2111   }
2112
2113   stv_current_rotation_parameter_table.xst  = (m_vdp2_vram[address/4] & 0x1fffffc0) | ((m_vdp2_vram[address/4] & 0x10000000) ? 0xe0000000 : 0x00000000 );
2114   stv_current_rotation_parameter_table.yst  = (m_vdp2_vram[address/4 + 1] & 0x1fffffc0) | ((m_vdp2_vram[address/4 + 1] & 0x10000000) ? 0xe0000000 : 0x00000000 );
2115   stv_current_rotation_parameter_table.zst  = (m_vdp2_vram[address/4 + 2] & 0x1fffffc0) | ((m_vdp2_vram[address/4 + 2] & 0x10000000) ? 0xe0000000 : 0x00000000 );
2116   stv_current_rotation_parameter_table.dxst = (m_vdp2_vram[address/4 + 3] & 0x0007ffc0) | ((m_vdp2_vram[address/4 + 3] & 0x00040000) ? 0xfff80000 : 0x00000000 );
2117   stv_current_rotation_parameter_table.dyst = (m_vdp2_vram[address/4 + 4] & 0x0007ffc0) | ((m_vdp2_vram[address/4 + 4] & 0x00040000) ? 0xfff80000 : 0x00000000 );
2118   stv_current_rotation_parameter_table.dx   = (m_vdp2_vram[address/4 + 5] & 0x0007ffc0) | ((m_vdp2_vram[address/4 + 5] & 0x00040000) ? 0xfff80000 : 0x00000000 );
2119   stv_current_rotation_parameter_table.dy   = (m_vdp2_vram[address/4 + 6] & 0x0007ffc0) | ((m_vdp2_vram[address/4 + 6] & 0x00040000) ? 0xfff80000 : 0x00000000 );
2120   stv_current_rotation_parameter_table.A    = (m_vdp2_vram[address/4 + 7] & 0x000fffc0) | ((m_vdp2_vram[address/4 + 7] & 0x00080000) ? 0xfff00000 : 0x00000000 );
2121   stv_current_rotation_parameter_table.B    = (m_vdp2_vram[address/4 + 8] & 0x000fffc0) | ((m_vdp2_vram[address/4 + 8] & 0x00080000) ? 0xfff00000 : 0x00000000 );
2122   stv_current_rotation_parameter_table.C    = (m_vdp2_vram[address/4 + 9] & 0x000fffc0) | ((m_vdp2_vram[address/4 + 9] & 0x00080000) ? 0xfff00000 : 0x00000000 );
2123   stv_current_rotation_parameter_table.D    = (m_vdp2_vram[address/4 + 10] & 0x000fffc0) | ((m_vdp2_vram[address/4 + 10] & 0x00080000) ? 0xfff00000 : 0x00000000 );
2124   stv_current_rotation_parameter_table.E    = (m_vdp2_vram[address/4 + 11] & 0x000fffc0) | ((m_vdp2_vram[address/4 + 11] & 0x00080000) ? 0xfff00000 : 0x00000000 );
2125   stv_current_rotation_parameter_table.F    = (m_vdp2_vram[address/4 + 12] & 0x000fffc0) | ((m_vdp2_vram[address/4 + 12] & 0x00080000) ? 0xfff00000 : 0x00000000 );
2126   stv_current_rotation_parameter_table.px   = (m_vdp2_vram[address/4 + 13] & 0x3fff0000) | ((m_vdp2_vram[address/4 + 13] & 0x30000000) ? 0xc0000000 : 0x00000000 );
2127   stv_current_rotation_parameter_table.py   = (m_vdp2_vram[address/4 + 13] & 0x00003fff) << 16;
2128   if ( stv_current_rotation_parameter_table.py & 0x20000000 ) stv_current_rotation_parameter_table.py |= 0xc0000000;
2129   stv_current_rotation_parameter_table.pz   = (m_vdp2_vram[address/4 + 14] & 0x3fff0000) | ((m_vdp2_vram[address/4 + 14] & 0x20000000) ? 0xc0000000 : 0x00000000 );
2130   stv_current_rotation_parameter_table.cx   = (m_vdp2_vram[address/4 + 15] & 0x3fff0000) | ((m_vdp2_vram[address/4 + 15] & 0x20000000) ? 0xc0000000 : 0x00000000 );
2131   stv_current_rotation_parameter_table.cy   = (m_vdp2_vram[address/4 + 15] & 0x00003fff) << 16;
2132   if ( stv_current_rotation_parameter_table.cy & 0x20000000 ) stv_current_rotation_parameter_table.cy |= 0xc0000000;
2133   stv_current_rotation_parameter_table.cz   = (m_vdp2_vram[address/4 + 16] & 0x3fff0000) | ((m_vdp2_vram[address/4 + 16] & 0x20000000) ? 0xc0000000 : 0x00000000 );
2134   stv_current_rotation_parameter_table.mx   = (m_vdp2_vram[address/4 + 17] & 0x3fffffc0) | ((m_vdp2_vram[address/4 + 17] & 0x20000000) ? 0xc0000000 : 0x00000000 );
2135   stv_current_rotation_parameter_table.my   = (m_vdp2_vram[address/4 + 18] & 0x3fffffc0) | ((m_vdp2_vram[address/4 + 18] & 0x20000000) ? 0xc0000000 : 0x00000000 );
2136   stv_current_rotation_parameter_table.kx   = (m_vdp2_vram[address/4 + 19] & 0x00ffffff) | ((m_vdp2_vram[address/4 + 19] & 0x00800000) ? 0xff000000 : 0x00000000 );
2137   stv_current_rotation_parameter_table.ky   = (m_vdp2_vram[address/4 + 20] & 0x00ffffff) | ((m_vdp2_vram[address/4 + 20] & 0x00800000) ? 0xff000000 : 0x00000000 );
2138   stv_current_rotation_parameter_table.kast = (m_vdp2_vram[address/4 + 21] & 0xffffffc0);
2139   stv_current_rotation_parameter_table.dkast= (m_vdp2_vram[address/4 + 22] & 0x03ffffc0) | ((m_vdp2_vram[address/4 + 22] & 0x02000000) ? 0xfc000000 : 0x00000000 );
2140   stv_current_rotation_parameter_table.dkax = (m_vdp2_vram[address/4 + 23] & 0x03ffffc0) | ((m_vdp2_vram[address/4 + 23] & 0x02000000) ? 0xfc000000 : 0x00000000 );
2141
2142#define RP  stv_current_rotation_parameter_table
2143
2144   if(LOG_ROZ == 1) logerror( "Rotation parameter table (%d)\n", rot_parameter );
2145   if(LOG_ROZ == 1) logerror( "xst = %x, yst = %x, zst = %x\n", RP.xst, RP.yst, RP.zst );
2146   if(LOG_ROZ == 1) logerror( "dxst = %x, dyst = %x\n", RP.dxst, RP.dyst );
2147   if(LOG_ROZ == 1) logerror( "dx = %x, dy = %x\n", RP.dx, RP.dy );
2148   if(LOG_ROZ == 1) logerror( "A = %x, B = %x, C = %x, D = %x, E = %x, F = %x\n", RP.A, RP.B, RP.C, RP.D, RP.E, RP.F );
2149   if(LOG_ROZ == 1) logerror( "px = %x, py = %x, pz = %x\n", RP.px, RP.py, RP.pz );
2150   if(LOG_ROZ == 1) logerror( "cx = %x, cy = %x, cz = %x\n", RP.cx, RP.cy, RP.cz );
2151   if(LOG_ROZ == 1) logerror( "mx = %x, my = %x\n", RP.mx, RP.my );
2152   if(LOG_ROZ == 1) logerror( "kx = %x, ky = %x\n", RP.kx, RP.ky );
2153   if(LOG_ROZ == 1) logerror( "kast = %x, dkast = %x, dkax = %x\n", RP.kast, RP.dkast, RP.dkax );
2154
2155   /*Attempt to show on screen the rotation table*/
2156   #if 0
2157   if(LOG_ROZ == 2)
2158   {
2159      if(machine().input().code_pressed_once(JOYCODE_Y_UP_SWITCH))
2160         m_vdpdebug_roz++;
2161
2162      if(machine().input().code_pressed_once(JOYCODE_Y_DOWN_SWITCH))
2163         m_vdpdebug_roz--;
2164
2165      if(m_vdpdebug_roz > 10)
2166         m_vdpdebug_roz = 10;
2167
2168      switch(m_vdpdebug_roz)
2169      {
2170         case 0: popmessage( "Rotation parameter Table (%d)", rot_parameter ); break;
2171         case 1: popmessage( "xst = %x, yst = %x, zst = %x", RP.xst, RP.yst, RP.zst ); break;
2172         case 2: popmessage( "dxst = %x, dyst = %x", RP.dxst, RP.dyst ); break;
2173         case 3: popmessage( "dx = %x, dy = %x", RP.dx, RP.dy ); break;
2174         case 4: popmessage( "A = %x, B = %x, C = %x, D = %x, E = %x, F = %x", RP.A, RP.B, RP.C, RP.D, RP.E, RP.F ); break;
2175         case 5: popmessage( "px = %x, py = %x, pz = %x", RP.px, RP.py, RP.pz ); break;
2176         case 6: popmessage( "cx = %x, cy = %x, cz = %x", RP.cx, RP.cy, RP.cz ); break;
2177         case 7: popmessage( "mx = %x, my = %x", RP.mx, RP.my ); break;
2178         case 8: popmessage( "kx = %x, ky = %x", RP.kx, RP.ky ); break;
2179         case 9: popmessage( "kast = %x, dkast = %x, dkax = %x", RP.kast, RP.dkast, RP.dkax ); break;
2180         case 10: break;
2181      }
2182   }
2183   #endif
2184}
2185
2186/* check if RGB layer has rotation applied */
2187UINT8 saturn_state::stv_vdp2_is_rotation_applied(void)
2188{
2189#define _FIXED_1    (0x00010000)
2190#define _FIXED_0    (0x00000000)
2191
2192   if ( RP.A == _FIXED_1 &&
2193         RP.B == _FIXED_0 &&
2194         RP.C == _FIXED_0 &&
2195         RP.D == _FIXED_0 &&
2196         RP.E == _FIXED_1 &&
2197         RP.F == _FIXED_0 &&
2198         RP.dxst == _FIXED_0 &&
2199         RP.dyst == _FIXED_1 &&
2200         RP.dx == _FIXED_1 &&
2201         RP.dy == _FIXED_0 &&
2202         RP.kx == _FIXED_1 &&
2203         RP.ky == _FIXED_1 )
2204   {
2205      return 0;
2206   }
2207   else
2208   {
2209      return 1;
2210   }
2211}
2212
2213UINT8 saturn_state::stv_vdp2_are_map_registers_equal(void)
2214{
2215   int i;
2216
2217   for ( i = 1; i < stv2_current_tilemap.map_count; i++ )
2218   {
2219      if ( stv2_current_tilemap.map_offset[i] != stv2_current_tilemap.map_offset[0] )
2220      {
2221         return 0;
2222      }
2223   }
2224   return 1;
2225}
2226
2227void saturn_state::stv_vdp2_check_fade_control_for_layer( void )
2228{
2229   if ( stv2_current_tilemap.fade_control & 1 )
2230   {
2231      if ( stv2_current_tilemap.fade_control & 2 )
2232      {
2233         if ((STV_VDP2_COBR & 0x1ff) == 0 &&
2234            (STV_VDP2_COBG & 0x1ff) == 0 &&
2235            (STV_VDP2_COBB & 0x1ff) == 0 )
2236         {
2237            stv2_current_tilemap.fade_control = 0;
2238         }
2239      }
2240      else
2241      {
2242         if ((STV_VDP2_COAR & 0x1ff) == 0 &&
2243            (STV_VDP2_COAG & 0x1ff) == 0 &&
2244            (STV_VDP2_COAB & 0x1ff) == 0 )
2245         {
2246            stv2_current_tilemap.fade_control = 0;
2247         }
2248      }
2249   }
2250}
2251
2252#define STV_VDP2_CP_NBG0_PNMDR      0x0
2253#define STV_VDP2_CP_NBG1_PNMDR      0x1
2254#define STV_VDP2_CP_NBG2_PNMDR      0x2
2255#define STV_VDP2_CP_NBG3_PNMDR      0x3
2256#define STV_VDP2_CP_NBG0_CPDR       0x4
2257#define STV_VDP2_CP_NBG1_CPDR       0x5
2258#define STV_VDP2_CP_NBG2_CPDR       0x6
2259#define STV_VDP2_CP_NBG3_CPDR       0x7
2260
2261UINT8 saturn_state::stv_vdp2_check_vram_cycle_pattern_registers( UINT8 access_command_pnmdr, UINT8 access_command_cpdr, UINT8 bitmap_enable )
2262{
2263   int i;
2264   UINT8  access_command_ok = 0;
2265   UINT16 cp_regs[8];
2266   cp_regs[0] = STV_VDP2_CYCA0L;
2267   cp_regs[1] = STV_VDP2_CYCA0U;
2268   cp_regs[2] = STV_VDP2_CYCA1L;
2269   cp_regs[3] = STV_VDP2_CYCA1U;
2270   cp_regs[4] = STV_VDP2_CYCA2L;
2271   cp_regs[5] = STV_VDP2_CYCA2U;
2272   cp_regs[6] = STV_VDP2_CYCA3L;
2273   cp_regs[7] = STV_VDP2_CYCA3U;
2274
2275   if ( bitmap_enable ) access_command_ok = 1;
2276
2277   for ( i = 0; i < 8; i++ )
2278   {
2279      if ( ((cp_regs[i] >> 12) & 0xf) == access_command_pnmdr )
2280      {
2281         access_command_ok |= 1;
2282      }
2283      if ( ((cp_regs[i] >> 12) & 0xf) == access_command_cpdr )
2284      {
2285         access_command_ok |= 2;
2286      }
2287      if ( ((cp_regs[i] >> 8) & 0xf) == access_command_pnmdr )
2288      {
2289         access_command_ok |= 1;
2290      }
2291      if ( ((cp_regs[i] >> 8) & 0xf) == access_command_cpdr )
2292      {
2293         access_command_ok |= 2;
2294      }
2295      if ( ((cp_regs[i] >> 4) & 0xf) == access_command_pnmdr )
2296      {
2297         access_command_ok |= 1;
2298      }
2299      if ( ((cp_regs[i] >> 4) & 0xf) == access_command_cpdr )
2300      {
2301         access_command_ok |= 2;
2302      }
2303      if ( ((cp_regs[i] >> 0) & 0xf) == access_command_pnmdr )
2304      {
2305         access_command_ok |= 1;
2306      }
2307      if ( ((cp_regs[i] >> 0) & 0xf) == access_command_cpdr )
2308      {
2309         access_command_ok |= 2;
2310      }
2311   }
2312   return access_command_ok == 3 ? 1 : 0;
2313}
2314
2315INLINE UINT32 stv_add_blend(UINT32 a, UINT32 b)
2316{
2317   UINT32 rb = (a & 0xff00ff) + (b & 0xff00ff);
2318   UINT32 g = (a & 0x00ff00) + (b & 0x00ff00);
2319   return MAKE_RGB((rb & 0x1000000) ? 0xff : RGB_RED(rb),
2320      (g & 0x0010000) ? 0xff : RGB_GREEN(g),
2321      (rb & 0x0000100) ? 0xff : RGB_BLUE(rb)
2322   );
2323}
2324
2325
2326void saturn_state::stv_vdp2_compute_color_offset( int *r, int *g, int *b, int cor )
2327{
2328   if ( cor == 0 )
2329   {
2330      *r = (STV_VDP2_COAR & 0x100) ? (*r - (0x100 - (STV_VDP2_COAR & 0xff))) : ((STV_VDP2_COAR & 0xff) + *r);
2331      *g = (STV_VDP2_COAG & 0x100) ? (*g - (0x100 - (STV_VDP2_COAG & 0xff))) : ((STV_VDP2_COAG & 0xff) + *g);
2332      *b = (STV_VDP2_COAB & 0x100) ? (*b - (0x100 - (STV_VDP2_COAB & 0xff))) : ((STV_VDP2_COAB & 0xff) + *b);
2333   }
2334   else
2335   {
2336      *r = (STV_VDP2_COBR & 0x100) ? (*r - (0xff - (STV_VDP2_COBR & 0xff))) : ((STV_VDP2_COBR & 0xff) + *r);
2337      *g = (STV_VDP2_COBG & 0x100) ? (*g - (0xff - (STV_VDP2_COBG & 0xff))) : ((STV_VDP2_COBG & 0xff) + *g);
2338      *b = (STV_VDP2_COBB & 0x100) ? (*b - (0xff - (STV_VDP2_COBB & 0xff))) : ((STV_VDP2_COBB & 0xff) + *b);
2339   }
2340   if(*r < 0)      { *r = 0; }
2341   if(*r > 0xff)   { *r = 0xff; }
2342   if(*g < 0)      { *g = 0; }
2343   if(*g > 0xff)   { *g = 0xff; }
2344   if(*b < 0)      { *b = 0; }
2345   if(*b > 0xff)   { *b = 0xff; }
2346}
2347
2348void saturn_state::stv_vdp2_compute_color_offset_UINT32(UINT32 *rgb, int cor)
2349{
2350   int _r = RGB_RED(*rgb);
2351   int _g = RGB_GREEN(*rgb);
2352   int _b = RGB_BLUE(*rgb);
2353   if ( cor == 0 )
2354   {
2355      _r = (STV_VDP2_COAR & 0x100) ? (_r - (0x100 - (STV_VDP2_COAR & 0xff))) : ((STV_VDP2_COAR & 0xff) + _r);
2356      _g = (STV_VDP2_COAG & 0x100) ? (_g - (0x100 - (STV_VDP2_COAG & 0xff))) : ((STV_VDP2_COAG & 0xff) + _g);
2357      _b = (STV_VDP2_COAB & 0x100) ? (_b - (0x100 - (STV_VDP2_COAB & 0xff))) : ((STV_VDP2_COAB & 0xff) + _b);
2358   }
2359   else
2360   {
2361      _r = (STV_VDP2_COBR & 0x100) ? (_r - (0xff - (STV_VDP2_COBR & 0xff))) : ((STV_VDP2_COBR & 0xff) + _r);
2362      _g = (STV_VDP2_COBG & 0x100) ? (_g - (0xff - (STV_VDP2_COBG & 0xff))) : ((STV_VDP2_COBG & 0xff) + _g);
2363      _b = (STV_VDP2_COBB & 0x100) ? (_b - (0xff - (STV_VDP2_COBB & 0xff))) : ((STV_VDP2_COBB & 0xff) + _b);
2364   }
2365   if(_r < 0)      { _r = 0; }
2366   if(_r > 0xff)   { _r = 0xff; }
2367   if(_g < 0)      { _g = 0; }
2368   if(_g > 0xff)   { _g = 0xff; }
2369   if(_b < 0)      { _b = 0; }
2370   if(_b > 0xff)   { _b = 0xff; }
2371
2372   *rgb = MAKE_RGB(_r, _g, _b);
2373}
2374
2375void saturn_state::stv_vdp2_drawgfxzoom(
2376      bitmap_rgb32 &dest_bmp,const rectangle &clip,gfx_element *gfx,
2377      UINT32 code,UINT32 color,int flipx,int flipy,int sx,int sy,
2378      int transparency,int transparent_color,int scalex, int scaley,
2379      int sprite_screen_width, int sprite_screen_height, int alpha)
2380{
2381   rectangle myclip;
2382
2383   if (!scalex || !scaley) return;
2384
2385   if (gfx->has_pen_usage() && transparency == STV_TRANSPARENCY_PEN)
2386   {
2387      int transmask = 0;
2388
2389      transmask = 1 << (transparent_color & 0xff);
2390
2391      if ((gfx->pen_usage(code) & ~transmask) == 0)
2392         /* character is totally transparent, no need to draw */
2393         return;
2394      else if ((gfx->pen_usage(code) & transmask) == 0)
2395         /* character is totally opaque, can disable transparency */
2396         transparency = STV_TRANSPARENCY_NONE;
2397   }
2398
2399   /*
2400   scalex and scaley are 16.16 fixed point numbers
2401   1<<15 : shrink to 50%
2402   1<<16 : uniform scale
2403   1<<17 : double to 200%
2404   */
2405
2406
2407   /* KW 991012 -- Added code to force clip to bitmap boundary */
2408   myclip = clip;
2409   myclip &= dest_bmp.cliprect();
2410
2411   if( gfx )
2412   {
2413      const pen_t *pal = &gfx->machine().pens[gfx->colorbase() + gfx->granularity() * (color % gfx->colors())];
2414      const UINT8 *source_base = gfx->get_data(code % gfx->elements());
2415
2416      //int sprite_screen_height = (scaley*gfx->height()+0x8000)>>16;
2417      //int sprite_screen_width = (scalex*gfx->width()+0x8000)>>16;
2418
2419      if (sprite_screen_width && sprite_screen_height)
2420      {
2421         /* compute sprite increment per screen pixel */
2422         //int dx = (gfx->width()<<16)/sprite_screen_width;
2423         //int dy = (gfx->height()<<16)/sprite_screen_height;
2424         int dx = stv2_current_tilemap.incx;
2425         int dy = stv2_current_tilemap.incy;
2426
2427         int ex = sx+sprite_screen_width;
2428         int ey = sy+sprite_screen_height;
2429
2430         int x_index_base;
2431         int y_index;
2432
2433         if( flipx )
2434         {
2435            x_index_base = (sprite_screen_width-1)*dx;
2436            dx = -dx;
2437         }
2438         else
2439         {
2440            x_index_base = 0;
2441         }
2442
2443         if( flipy )
2444         {
2445            y_index = (sprite_screen_height-1)*dy;
2446            dy = -dy;
2447         }
2448         else
2449         {
2450            y_index = 0;
2451         }
2452
2453         if( sx < myclip.min_x)
2454         { /* clip left */
2455            int pixels = myclip.min_x-sx;
2456            sx += pixels;
2457            x_index_base += pixels*dx;
2458         }
2459         if( sy < myclip.min_y )
2460         { /* clip top */
2461            int pixels = myclip.min_y-sy;
2462            sy += pixels;
2463            y_index += pixels*dy;
2464         }
2465         /* NS 980211 - fixed incorrect clipping */
2466         if( ex > myclip.max_x+1 )
2467         { /* clip right */
2468            int pixels = ex-myclip.max_x-1;
2469            ex -= pixels;
2470         }
2471         if( ey > myclip.max_y+1 )
2472         { /* clip bottom */
2473            int pixels = ey-myclip.max_y-1;
2474            ey -= pixels;
2475         }
2476
2477         if( ex>sx )
2478         { /* skip if inner loop doesn't draw anything */
2479            int y;
2480
2481            /* case 0: STV_TRANSPARENCY_NONE */
2482            if (transparency == STV_TRANSPARENCY_NONE)
2483            {
2484               for( y=sy; y<ey; y++ )
2485               {
2486                  const UINT8 *source = source_base + (y_index>>16) * gfx->rowbytes();
2487                  UINT32 *dest = &dest_bmp.pix32(y);
2488
2489                  int x, x_index = x_index_base;
2490                  for( x=sx; x<ex; x++ )
2491                  {
2492                     dest[x] = pal[source[x_index>>16]];
2493                     x_index += dx;
2494                  }
2495
2496                  y_index += dy;
2497               }
2498            }
2499
2500            /* case 1: STV_TRANSPARENCY_PEN */
2501            if (transparency == STV_TRANSPARENCY_PEN)
2502            {
2503               for( y=sy; y<ey; y++ )
2504               {
2505                  const UINT8 *source = source_base + (y_index>>16) * gfx->rowbytes();
2506                  UINT32 *dest = &dest_bmp.pix32(y);
2507
2508                  int x, x_index = x_index_base;
2509                  for( x=sx; x<ex; x++ )
2510                  {
2511                     int c = source[x_index>>16];
2512                     if( c != transparent_color ) dest[x] = pal[c];
2513                     x_index += dx;
2514                  }
2515
2516                  y_index += dy;
2517               }
2518            }
2519
2520            /* case 6: STV_TRANSPARENCY_ALPHA */
2521            if (transparency == STV_TRANSPARENCY_ALPHA)
2522            {
2523               for( y=sy; y<ey; y++ )
2524               {
2525                  const UINT8 *source = source_base + (y_index>>16) * gfx->rowbytes();
2526                  UINT32 *dest = &dest_bmp.pix32(y);
2527
2528                  int x, x_index = x_index_base;
2529                  for( x=sx; x<ex; x++ )
2530                  {
2531                     int c = source[x_index>>16];
2532                     if( c != transparent_color ) dest[x] = alpha_blend_r32(dest[x], pal[c], alpha);
2533                     x_index += dx;
2534                  }
2535
2536                  y_index += dy;
2537               }
2538            }
2539
2540            /* case : STV_TRANSPARENCY_ADD_BLEND */
2541            if (transparency == STV_TRANSPARENCY_ADD_BLEND )
2542            {
2543               for( y=sy; y<ey; y++ )
2544               {
2545                  const UINT8 *source = source_base + (y_index>>16) * gfx->rowbytes();
2546                  UINT32 *dest = &dest_bmp.pix32(y);
2547
2548                  int x, x_index = x_index_base;
2549                  for( x=sx; x<ex; x++ )
2550                  {
2551                     int c = source[x_index>>16];
2552                     if( c != transparent_color ) dest[x] = stv_add_blend(dest[x],pal[c]);
2553                     x_index += dx;
2554                  }
2555
2556                  y_index += dy;
2557               }
2558            }
2559
2560         }
2561      }
2562   }
2563
2564}
2565
2566void saturn_state::stv_vdp2_drawgfxzoom_rgb555(
2567      bitmap_rgb32 &dest_bmp,const rectangle &clip,
2568      UINT32 code,UINT32 color,int flipx,int flipy,int sx,int sy,
2569      int transparency,int transparent_color,int scalex, int scaley,
2570      int sprite_screen_width, int sprite_screen_height, int alpha)
2571{
2572   rectangle myclip;
2573   UINT8* gfxdata;
2574
2575   gfxdata = m_vdp2.gfx_decode + code * 0x20;
2576
2577   if (!scalex || !scaley) return;
2578
2579   #if 0
2580   if (gfx->has_pen_usage() && transparency == STV_TRANSPARENCY_PEN)
2581   {
2582      int transmask = 0;
2583
2584      transmask = 1 << (transparent_color & 0xff);
2585
2586      if ((gfx->pen_usage(code) & ~transmask) == 0)
2587         /* character is totally transparent, no need to draw */
2588         return;
2589      else if ((gfx->pen_usage(code) & transmask) == 0)
2590         /* character is totally opaque, can disable transparency */
2591         transparency = STV_TRANSPARENCY_NONE;
2592   }
2593   #endif
2594
2595   /*
2596   scalex and scaley are 16.16 fixed point numbers
2597   1<<15 : shrink to 50%
2598   1<<16 : uniform scale
2599   1<<17 : double to 200%
2600   */
2601
2602
2603   /* KW 991012 -- Added code to force clip to bitmap boundary */
2604   myclip = clip;
2605   myclip &= dest_bmp.cliprect();
2606
2607//  if( gfx )
2608   {
2609//      const UINT8 *source_base = gfx->get_data(code % gfx->elements());
2610
2611      //int sprite_screen_height = (scaley*gfx->height()+0x8000)>>16;
2612      //int sprite_screen_width = (scalex*gfx->width()+0x8000)>>16;
2613
2614      if (sprite_screen_width && sprite_screen_height)
2615      {
2616         /* compute sprite increment per screen pixel */
2617         //int dx = (gfx->width()<<16)/sprite_screen_width;
2618         //int dy = (gfx->height()<<16)/sprite_screen_height;
2619         int dx = stv2_current_tilemap.incx;
2620         int dy = stv2_current_tilemap.incy;
2621
2622         int ex = sx+sprite_screen_width;
2623         int ey = sy+sprite_screen_height;
2624
2625         int x_index_base;
2626         int y_index;
2627
2628         if( flipx )
2629         {
2630            x_index_base = (sprite_screen_width-1)*dx;
2631            dx = -dx;
2632         }
2633         else
2634         {
2635            x_index_base = 0;
2636         }
2637
2638         if( flipy )
2639         {
2640            y_index = (sprite_screen_height-1)*dy;
2641            dy = -dy;
2642         }
2643         else
2644         {
2645            y_index = 0;
2646         }
2647
2648         if( sx < myclip.min_x)
2649         { /* clip left */
2650            int pixels = myclip.min_x-sx;
2651            sx += pixels;
2652            x_index_base += pixels*dx;
2653         }
2654         if( sy < myclip.min_y )
2655         { /* clip top */
2656            int pixels = myclip.min_y-sy;
2657            sy += pixels;
2658            y_index += pixels*dy;
2659         }
2660         /* NS 980211 - fixed incorrect clipping */
2661         if( ex > myclip.max_x+1 )
2662         { /* clip right */
2663            int pixels = ex-myclip.max_x-1;
2664            ex -= pixels;
2665         }
2666         if( ey > myclip.max_y+1 )
2667         { /* clip bottom */
2668            int pixels = ey-myclip.max_y-1;
2669            ey -= pixels;
2670         }
2671
2672         if( ex>sx )
2673         { /* skip if inner loop doesn't draw anything */
2674            int y;
2675
2676            /* case 0: STV_TRANSPARENCY_NONE */
2677            if (transparency == STV_TRANSPARENCY_NONE)
2678            {
2679               for( y=sy; y<ey; y++ )
2680               {
2681                  const UINT8 *source = gfxdata + (y_index>>16)*16;
2682                  UINT32 *dest = &dest_bmp.pix32(y);
2683                  int r,g,b,data;
2684
2685                  int x, x_index = x_index_base;
2686                  for( x=sx; x<ex; x++ )
2687                  {
2688                     data = (source[(x_index>>16)*2] << 8) | source[(x_index>>16)*2+1];
2689                     b = pal5bit((data & 0x7c00) >> 10);
2690                     g = pal5bit((data & 0x03e0) >> 5);
2691                     r = pal5bit( data & 0x001f);
2692                     if(stv2_current_tilemap.fade_control & 1)
2693                        stv_vdp2_compute_color_offset(&r,&g,&b,stv2_current_tilemap.fade_control & 2);
2694
2695                     dest[x] = MAKE_RGB(r, g, b);
2696                     x_index += dx;
2697                  }
2698
2699                  y_index += dy;
2700               }
2701            }
2702
2703            /* case 1: STV_TRANSPARENCY_PEN */
2704            if (transparency == STV_TRANSPARENCY_PEN)
2705            {
2706               for( y=sy; y<ey; y++ )
2707               {
2708                  const UINT8 *source = gfxdata + (y_index>>16)*16;
2709                  UINT32 *dest = &dest_bmp.pix32(y);
2710                  int r,g,b,data;
2711
2712                  int x, x_index = x_index_base;
2713                  for( x=sx; x<ex; x++ )
2714                  {
2715                     data = (source[(x_index>>16)*2] << 8) | source[(x_index>>16)*2+1];
2716                     b = pal5bit((data & 0x7c00) >> 10);
2717                     g = pal5bit((data & 0x03e0) >> 5);
2718                     r = pal5bit( data & 0x001f);
2719                     if(stv2_current_tilemap.fade_control & 1)
2720                        stv_vdp2_compute_color_offset(&r,&g,&b,stv2_current_tilemap.fade_control & 2);
2721
2722                     if( data ) dest[x] = MAKE_RGB(r, g, b);
2723                     x_index += dx;
2724                  }
2725
2726                  y_index += dy;
2727               }
2728            }
2729
2730            /* case 6: STV_TRANSPARENCY_ALPHA */
2731            if (transparency == STV_TRANSPARENCY_ALPHA)
2732            {
2733               for( y=sy; y<ey; y++ )
2734               {
2735                  const UINT8 *source = gfxdata + (y_index>>16)*16;
2736                  UINT32 *dest = &dest_bmp.pix32(y);
2737                  int r,g,b,data;
2738
2739                  int x, x_index = x_index_base;
2740                  for( x=sx; x<ex; x++ )
2741                  {
2742                     data = (source[(x_index>>16)*2] << 8) | source[(x_index>>16)*2+1];
2743                     b = pal5bit((data & 0x7c00) >> 10);
2744                     g = pal5bit((data & 0x03e0) >> 5);
2745                     r = pal5bit( data & 0x001f);
2746                     if(stv2_current_tilemap.fade_control & 1)
2747                        stv_vdp2_compute_color_offset(&r,&g,&b,stv2_current_tilemap.fade_control & 2);
2748
2749                     if( data ) dest[x] = alpha_blend_r32(dest[x], MAKE_RGB(r, g, b), alpha);
2750                     x_index += dx;
2751                  }
2752
2753                  y_index += dy;
2754               }
2755            }
2756
2757            /* case : STV_TRANSPARENCY_ADD_BLEND */
2758            if (transparency == STV_TRANSPARENCY_ADD_BLEND )
2759            {
2760               for( y=sy; y<ey; y++ )
2761               {
2762                  const UINT8 *source = gfxdata + (y_index>>16)*16;
2763                  UINT32 *dest = &dest_bmp.pix32(y);
2764                  int r,g,b,data;
2765
2766                  int x, x_index = x_index_base;
2767                  for( x=sx; x<ex; x++ )
2768                  {
2769                     data = (source[(x_index*2+0)>>16]<<0)|(source[(x_index*2+1)>>16]<<8);
2770                     b = pal5bit((data & 0x7c00) >> 10);
2771                     g = pal5bit((data & 0x03e0) >> 5);
2772                     r = pal5bit( data & 0x001f);
2773                     if(stv2_current_tilemap.fade_control & 1)
2774                        stv_vdp2_compute_color_offset(&r,&g,&b,stv2_current_tilemap.fade_control & 2);
2775
2776                     if( data ) dest[x] = stv_add_blend(dest[x], MAKE_RGB(r, g, b));
2777                     x_index += dx;
2778                  }
2779
2780                  y_index += dy;
2781               }
2782            }
2783
2784         }
2785      }
2786   }
2787
2788}
2789
2790
2791void saturn_state::stv_vdp2_drawgfx_rgb555( bitmap_rgb32 &dest_bmp, const rectangle &clip, UINT32 code, int flipx, int flipy, int sx, int sy, int transparency, int alpha)
2792{
2793   rectangle myclip;
2794   UINT8* gfxdata;
2795   int sprite_screen_width, sprite_screen_height;
2796
2797   gfxdata = m_vdp2.gfx_decode + code * 0x20;
2798   sprite_screen_width = sprite_screen_height = 8;
2799
2800   /* KW 991012 -- Added code to force clip to bitmap boundary */
2801   myclip = clip;
2802   myclip &= dest_bmp.cliprect();
2803
2804   {
2805      int dx = stv2_current_tilemap.incx;
2806      int dy = stv2_current_tilemap.incy;
2807
2808      int ex = sx+sprite_screen_width;
2809      int ey = sy+sprite_screen_height;
2810
2811      int x_index_base;
2812      int y_index;
2813
2814      if( flipx )
2815      {
2816         x_index_base = (sprite_screen_width-1)*dx;
2817         dx = -dx;
2818      }
2819      else
2820      {
2821         x_index_base = 0;
2822      }
2823
2824      if( flipy )
2825      {
2826         y_index = (sprite_screen_height-1)*dy;
2827         dy = -dy;
2828      }
2829      else
2830      {
2831         y_index = 0;
2832      }
2833
2834      if( sx < myclip.min_x)
2835      { /* clip left */
2836         int pixels = myclip.min_x-sx;
2837         sx += pixels;
2838         x_index_base += pixels*dx;
2839      }
2840      if( sy < myclip.min_y )
2841      { /* clip top */
2842         int pixels = myclip.min_y-sy;
2843         sy += pixels;
2844         y_index += pixels*dy;
2845      }
2846      /* NS 980211 - fixed incorrect clipping */
2847      if( ex > myclip.max_x+1 )
2848      { /* clip right */
2849         int pixels = ex-myclip.max_x-1;
2850         ex -= pixels;
2851      }
2852      if( ey > myclip.max_y+1 )
2853      { /* clip bottom */
2854         int pixels = ey-myclip.max_y-1;
2855         ey -= pixels;
2856      }
2857
2858      if( ex>sx )
2859      { /* skip if inner loop doesn't draw anything */
2860         int y;
2861
2862         for( y=sy; y<ey; y++ )
2863         {
2864            const UINT8 *source = gfxdata + (y_index>>16)*16;
2865            UINT32 *dest = &dest_bmp.pix32(y);
2866            UINT16 data;
2867
2868            int x, x_index = x_index_base;
2869            for( x=sx; x<ex; x++ )
2870            {
2871               int r,g,b;
2872
2873               data = (source[(x_index>>16)*2] << 8) | source[(x_index>>16)*2+1];
2874               if ((data & 0x8000) || (transparency == STV_TRANSPARENCY_NONE))
2875               {
2876                  b = pal5bit((data & 0x7c00) >> 10);
2877                  g = pal5bit((data & 0x03e0) >> 5);
2878                  r = pal5bit( data & 0x001f);
2879                  if(stv2_current_tilemap.fade_control & 1)
2880                     stv_vdp2_compute_color_offset(&r,&g,&b,stv2_current_tilemap.fade_control & 2);
2881
2882                  if ( transparency == STV_TRANSPARENCY_ALPHA )
2883                     dest[x] = alpha_blend_r32( dest[x], MAKE_RGB(r, g, b), alpha );
2884                  else
2885                     dest[x] = MAKE_RGB(r, g, b);
2886               }
2887               x_index += dx;
2888            }
2889
2890            y_index += dy;
2891         }
2892
2893      }
2894
2895   }
2896
2897}
2898
2899
2900void saturn_state::stv_vdp2_drawgfx_rgb888( bitmap_rgb32 &dest_bmp, const rectangle &clip, UINT32 code, int flipx, int flipy,
2901                              int sx, int sy, int transparency, int alpha)
2902{
2903   rectangle myclip;
2904   UINT8* gfxdata;
2905   int sprite_screen_width, sprite_screen_height;
2906
2907   gfxdata = m_vdp2.gfx_decode + code * 0x20;
2908   sprite_screen_width = sprite_screen_height = 8;
2909
2910   /* KW 991012 -- Added code to force clip to bitmap boundary */
2911   myclip = clip;
2912   myclip &= dest_bmp.cliprect();
2913   {
2914      int dx = stv2_current_tilemap.incx;
2915      int dy = stv2_current_tilemap.incy;
2916
2917      int ex = sx+sprite_screen_width;
2918      int ey = sy+sprite_screen_height;
2919
2920      int x_index_base;
2921      int y_index;
2922
2923      if( flipx )
2924      {
2925         x_index_base = (sprite_screen_width-1)*dx;
2926         dx = -dx;
2927      }
2928      else
2929      {
2930         x_index_base = 0;
2931      }
2932
2933      if( flipy )
2934      {
2935         y_index = (sprite_screen_height-1)*dy;
2936         dy = -dy;
2937      }
2938      else
2939      {
2940         y_index = 0;
2941      }
2942
2943      if( sx < myclip.min_x)
2944      { /* clip left */
2945         int pixels = myclip.min_x-sx;
2946         sx += pixels;
2947         x_index_base += pixels*dx;
2948      }
2949      if( sy < myclip.min_y )
2950      { /* clip top */
2951         int pixels = myclip.min_y-sy;
2952         sy += pixels;
2953         y_index += pixels*dy;
2954      }
2955      /* NS 980211 - fixed incorrect clipping */
2956      if( ex > myclip.max_x+1 )
2957      { /* clip right */
2958         int pixels = ex-myclip.max_x-1;
2959         ex -= pixels;
2960      }
2961      if( ey > myclip.max_y+1 )
2962      { /* clip bottom */
2963         int pixels = ey-myclip.max_y-1;
2964         ey -= pixels;
2965      }
2966
2967      if( ex>sx )
2968      { /* skip if inner loop doesn't draw anything */
2969         int y;
2970
2971         for( y=sy; y<ey; y++ )
2972         {
2973            const UINT8 *source = gfxdata + (y_index>>16)*32;
2974            UINT32 *dest = &dest_bmp.pix32(y);
2975            UINT32 data;
2976
2977            int x, x_index = x_index_base;
2978
2979            for( x=sx; x<ex; x++ )
2980            {
2981               int r,g,b;
2982
2983               data = (source[(x_index>>16)*4+0] << 24) | (source[(x_index>>16)*4+1] << 16) | (source[(x_index>>16)*4+2] << 8) | (source[(x_index>>16)*4+3] << 0);
2984               if ((data & 0x80000000) || (transparency == STV_TRANSPARENCY_NONE))
2985               {
2986                  b = (data & 0xff0000) >> 16;
2987                  g = (data & 0x00ff00) >> 8;
2988                  r = (data & 0x0000ff);
2989
2990                  if(stv2_current_tilemap.fade_control & 1)
2991                     stv_vdp2_compute_color_offset(&r,&g,&b,stv2_current_tilemap.fade_control & 2);
2992
2993                  if ( transparency == STV_TRANSPARENCY_ALPHA )
2994                     dest[x] = alpha_blend_r32( dest[x], MAKE_RGB(r, g, b), alpha );
2995                  else
2996                     dest[x] = MAKE_RGB(r, g, b);
2997               }
2998               x_index += dx;
2999            }
3000
3001            y_index += dy;
3002         }
3003
3004      }
3005
3006   }
3007
3008}
3009
3010void saturn_state::draw_4bpp_bitmap(bitmap_rgb32 &bitmap, const rectangle &cliprect)
3011{
3012   int xsize, ysize, xsize_mask, ysize_mask;
3013   int xsrc,ysrc,xdst,ydst;
3014   int src_offs;
3015   UINT8* vram = m_vdp2.gfx_decode;
3016   UINT32 map_offset = stv2_current_tilemap.bitmap_map * 0x20000;
3017   int scrollx = stv2_current_tilemap.scrollx;
3018   int scrolly = stv2_current_tilemap.scrolly;
3019   UINT16 dot_data;
3020   UINT16 pal_bank;
3021
3022   xsize = (stv2_current_tilemap.bitmap_size & 2) ? 1024 : 512;
3023   ysize = (stv2_current_tilemap.bitmap_size & 1) ? 512 : 256;
3024
3025   xsize_mask = (stv2_current_tilemap.linescroll_enable) ? 1024 : xsize;
3026   ysize_mask = (stv2_current_tilemap.vertical_linescroll_enable) ? 512 : ysize;
3027
3028   pal_bank = stv2_current_tilemap.bitmap_palette_number;
3029   pal_bank+= stv2_current_tilemap.colour_ram_address_offset;
3030   pal_bank&= 7;
3031   pal_bank<<=8;
3032   if(stv2_current_tilemap.fade_control & 1)
3033      pal_bank += ((stv2_current_tilemap.fade_control & 2) ? (2*2048) : (2048));
3034
3035   for(ydst=cliprect.min_y;ydst<=cliprect.max_y;ydst++)
3036   {
3037      for(xdst=cliprect.min_x;xdst<=cliprect.max_x;xdst++)
3038      {
3039         if(stv_vdp2_window_process(xdst,ydst))
3040            continue;
3041
3042         xsrc = (xdst + scrollx) & (xsize_mask-1);
3043         ysrc = (ydst + scrolly) & (ysize_mask-1);
3044         src_offs = (xsrc + (ysrc*xsize));
3045         src_offs/= 2;
3046         src_offs += map_offset;
3047         src_offs &= 0x7ffff;
3048
3049         dot_data = vram[src_offs] >> ((xsrc & 1) ? 0 : 4);
3050         dot_data&= 0xf;
3051
3052         if ((dot_data != 0) || (stv2_current_tilemap.transparency == STV_TRANSPARENCY_NONE))
3053         {
3054            dot_data += pal_bank;
3055
3056            if ( stv2_current_tilemap.colour_calculation_enabled == 0 )
3057               bitmap.pix32(ydst, xdst) = machine().pens[dot_data];
3058            else
3059               bitmap.pix32(ydst, xdst) = alpha_blend_r32(bitmap.pix32(ydst, xdst), machine().pens[dot_data], stv2_current_tilemap.alpha);
3060         }
3061      }
3062   }
3063}
3064
3065
3066void saturn_state::draw_8bpp_bitmap(bitmap_rgb32 &bitmap, const rectangle &cliprect)
3067{
3068   int xsize, ysize, xsize_mask, ysize_mask;
3069   int xsrc,ysrc,xdst,ydst;
3070   int src_offs;
3071   UINT8* vram = m_vdp2.gfx_decode;
3072   UINT32 map_offset = stv2_current_tilemap.bitmap_map * 0x20000;
3073   int scrollx = stv2_current_tilemap.scrollx;
3074   int scrolly = stv2_current_tilemap.scrolly;
3075   UINT16 dot_data;
3076   UINT16 pal_bank;
3077   int xf, yf;
3078
3079   xsize = (stv2_current_tilemap.bitmap_size & 2) ? 1024 : 512;
3080   ysize = (stv2_current_tilemap.bitmap_size & 1) ? 512 : 256;
3081
3082   xsize_mask = (stv2_current_tilemap.linescroll_enable) ? 1024 : xsize;
3083   ysize_mask = (stv2_current_tilemap.vertical_linescroll_enable) ? 512 : ysize;
3084
3085   pal_bank = stv2_current_tilemap.bitmap_palette_number;
3086   pal_bank+= stv2_current_tilemap.colour_ram_address_offset;
3087   pal_bank&= 7;
3088   pal_bank<<=8;
3089   if(stv2_current_tilemap.fade_control & 1)
3090      pal_bank += ((stv2_current_tilemap.fade_control & 2) ? (2*2048) : (2048));
3091
3092   for(ydst=cliprect.min_y;ydst<=cliprect.max_y;ydst++)
3093   {
3094      for(xdst=cliprect.min_x;xdst<=cliprect.max_x;xdst++)
3095      {
3096         if(stv_vdp2_window_process(xdst,ydst))
3097            continue;
3098
3099         xf = stv2_current_tilemap.incx * xdst;
3100         xf>>=16;
3101         yf = stv2_current_tilemap.incy * ydst;
3102         yf>>=16;
3103
3104         xsrc = (xf + scrollx) & (xsize_mask-1);
3105         ysrc = (yf + scrolly) & (ysize_mask-1);
3106         src_offs = (xsrc + (ysrc*xsize));
3107         src_offs += map_offset;
3108         src_offs &= 0x7ffff;
3109
3110         dot_data = vram[src_offs];
3111
3112         if ((dot_data != 0) || (stv2_current_tilemap.transparency == STV_TRANSPARENCY_NONE))
3113         {
3114            dot_data += pal_bank;
3115
3116            if ( stv2_current_tilemap.colour_calculation_enabled == 0 )
3117               bitmap.pix32(ydst, xdst) = machine().pens[dot_data];
3118            else
3119               bitmap.pix32(ydst, xdst) = alpha_blend_r32(bitmap.pix32(ydst, xdst), machine().pens[dot_data], stv2_current_tilemap.alpha);
3120         }
3121      }
3122   }
3123}
3124
3125void saturn_state::draw_rgb15_bitmap(bitmap_rgb32 &bitmap, const rectangle &cliprect)
3126{
3127   int xsize, ysize, xsize_mask, ysize_mask;
3128   int xsrc,ysrc,xdst,ydst;
3129   int src_offs;
3130   UINT8* vram = m_vdp2.gfx_decode;
3131   UINT32 map_offset = stv2_current_tilemap.bitmap_map * 0x20000;
3132   int scrollx = stv2_current_tilemap.scrollx;
3133   int scrolly = stv2_current_tilemap.scrolly;
3134   int r,g,b;
3135   UINT16 dot_data;
3136   int xf, yf;
3137
3138   xsize = (stv2_current_tilemap.bitmap_size & 2) ? 1024 : 512;
3139   ysize = (stv2_current_tilemap.bitmap_size & 1) ? 512 : 256;
3140
3141   xsize_mask = (stv2_current_tilemap.linescroll_enable) ? 1024 : xsize;
3142   ysize_mask = (stv2_current_tilemap.vertical_linescroll_enable) ? 512 : ysize;
3143
3144   for(ydst=cliprect.min_y;ydst<=cliprect.max_y;ydst++)
3145   {
3146      for(xdst=cliprect.min_x;xdst<=cliprect.max_x;xdst++)
3147      {
3148         if(stv_vdp2_window_process(xdst,ydst))
3149            continue;
3150
3151         xf = stv2_current_tilemap.incx * xdst;
3152         xf>>=16;
3153         yf = stv2_current_tilemap.incy * ydst;
3154         yf>>=16;
3155
3156         xsrc = (xf + scrollx) & (xsize_mask-1);
3157         ysrc = (yf + scrolly) & (ysize_mask-1);
3158         src_offs = (xsrc + (ysrc*xsize));
3159         src_offs *= 2;
3160         src_offs += map_offset;
3161         src_offs &= 0x7ffff;
3162
3163         dot_data =(vram[src_offs]<<8)|(vram[src_offs+1]<<0);
3164
3165         if ((dot_data & 0x8000) || (stv2_current_tilemap.transparency == STV_TRANSPARENCY_NONE))
3166         {
3167            b = pal5bit((dot_data & 0x7c00) >> 10);
3168            g = pal5bit((dot_data & 0x03e0) >> 5);
3169            r = pal5bit((dot_data & 0x001f) >> 0);
3170
3171            if(stv2_current_tilemap.fade_control & 1)
3172               stv_vdp2_compute_color_offset(&r,&g,&b,stv2_current_tilemap.fade_control & 2);
3173
3174            if ( stv2_current_tilemap.colour_calculation_enabled == 0 )
3175               bitmap.pix32(ydst, xdst) = MAKE_RGB(r, g, b);
3176            else
3177               bitmap.pix32(ydst, xdst) = alpha_blend_r32( bitmap.pix32(ydst, xdst), MAKE_RGB(r, g, b), stv2_current_tilemap.alpha );
3178         }
3179      }
3180   }
3181}
3182
3183void saturn_state::draw_rgb32_bitmap(bitmap_rgb32 &bitmap, const rectangle &cliprect)
3184{
3185   int xsize, ysize, xsize_mask, ysize_mask;
3186   int xsrc,ysrc,xdst,ydst;
3187   int src_offs;
3188   UINT8* vram = m_vdp2.gfx_decode;
3189   UINT32 map_offset = stv2_current_tilemap.bitmap_map * 0x20000;
3190   int scrollx = stv2_current_tilemap.scrollx;
3191   int scrolly = stv2_current_tilemap.scrolly;
3192   int r,g,b;
3193   UINT32 dot_data;
3194
3195   xsize = (stv2_current_tilemap.bitmap_size & 2) ? 1024 : 512;
3196   ysize = (stv2_current_tilemap.bitmap_size & 1) ? 512 : 256;
3197
3198   xsize_mask = (stv2_current_tilemap.linescroll_enable) ? 1024 : xsize;
3199   ysize_mask = (stv2_current_tilemap.vertical_linescroll_enable) ? 512 : ysize;
3200
3201   for(ydst=cliprect.min_y;ydst<=cliprect.max_y;ydst++)
3202   {
3203      for(xdst=cliprect.min_x;xdst<=cliprect.max_x;xdst++)
3204      {
3205         if(stv_vdp2_window_process(xdst,ydst))
3206            continue;
3207
3208         xsrc = (xdst + scrollx) & (xsize_mask-1);
3209         ysrc = (ydst + scrolly) & (ysize_mask-1);
3210         src_offs = (xsrc + (ysrc*xsize));
3211         src_offs *= 4;
3212         src_offs += map_offset;
3213         src_offs &= 0x7ffff;
3214
3215         dot_data = (vram[src_offs+0]<<24)|(vram[src_offs+1]<<16)|(vram[src_offs+2]<<8)|(vram[src_offs+3]<<0);
3216
3217         if ((dot_data & 0x80000000) || (stv2_current_tilemap.transparency == STV_TRANSPARENCY_NONE))
3218         {
3219            b = ((dot_data & 0x00ff0000) >> 16);
3220            g = ((dot_data & 0x0000ff00) >> 8);
3221            r = ((dot_data & 0x000000ff) >> 0);
3222
3223            if(stv2_current_tilemap.fade_control & 1)
3224               stv_vdp2_compute_color_offset(&r,&g,&b,stv2_current_tilemap.fade_control & 2);
3225
3226            if ( stv2_current_tilemap.colour_calculation_enabled == 0 )
3227               bitmap.pix32(ydst, xdst) = MAKE_RGB(r, g, b);
3228            else
3229               bitmap.pix32(ydst, xdst) = alpha_blend_r32( bitmap.pix32(ydst, xdst), MAKE_RGB(r, g, b), stv2_current_tilemap.alpha );
3230         }
3231      }
3232   }
3233}
3234
3235
3236void saturn_state::stv_vdp2_draw_basic_bitmap(bitmap_rgb32 &bitmap, const rectangle &cliprect)
3237{
3238//  if(LOG_VDP2) logerror ("bitmap enable %02x size %08x depth %08x\n", stv2_current_tilemap.layer_name, stv2_current_tilemap.bitmap_size, stv2_current_tilemap.colour_depth);
3239//  popmessage ("bitmap enable %02x size %08x depth %08x number %02x", stv2_current_tilemap.layer_name, stv2_current_tilemap.bitmap_size, stv2_current_tilemap.colour_depth,stv2_current_tilemap.bitmap_palette_number);
3240   //popmessage("%04x",STV_VDP2_SCRCTL);
3241
3242   int xsize = 0, xsizemask = 0;
3243   int ysize = 0/*, ysizemask = 0*/;
3244   int xlinesize = 0/*, xpixelsize = 0*/;
3245   int xcnt,ycnt;
3246   UINT8* gfxdata = m_vdp2.gfx_decode;
3247   UINT32 *destline;
3248   UINT16 pal_color_offset = 0;
3249   UINT8* gfxdatalow, *gfxdatahigh;
3250   int screen_x,screen_y;
3251
3252   if (!stv2_current_tilemap.enabled) return;
3253
3254   /* new bitmap code, supposed to rewrite the old one. Not supposed to be clean, but EFFICIENT! */
3255   if(stv2_current_tilemap.incx == 0x10000 && stv2_current_tilemap.incy == 0x10000)
3256   {
3257      switch(stv2_current_tilemap.colour_depth)
3258      {
3259         case 0: draw_4bpp_bitmap(bitmap,cliprect); return;
3260         case 1: draw_8bpp_bitmap(bitmap,cliprect); return;
3261         case 3: draw_rgb15_bitmap(bitmap,cliprect); return;
3262         case 4: draw_rgb32_bitmap(bitmap,cliprect); return;
3263      }
3264
3265      /* intentional fall-through*/
3266      popmessage("%d %s %s %s %s",stv2_current_tilemap.colour_depth,
3267                           stv2_current_tilemap.transparency == STV_TRANSPARENCY_NONE ? "no trans" : "trans",
3268                           stv2_current_tilemap.window_control & 6 ? "window" : "no window",
3269                           stv2_current_tilemap.colour_calculation_enabled ? "cc" : "no cc",
3270                           (stv2_current_tilemap.incx == 0x10000 && stv2_current_tilemap.incy == 0x10000) ? "no zoom" : "zoom");
3271   }
3272   else
3273   {
3274      switch(stv2_current_tilemap.colour_depth)
3275      {
3276      //  case 0: draw_4bpp_bitmap(bitmap,cliprect); return;
3277         case 1: draw_8bpp_bitmap(bitmap,cliprect); return;
3278         case 3: draw_rgb15_bitmap(bitmap,cliprect); return;
3279      //  case 4: draw_rgb32_bitmap(bitmap,cliprect); return;
3280      }
3281
3282      /* intentional fall-through*/
3283      popmessage("%d %s %s %s %s",stv2_current_tilemap.colour_depth,
3284                           stv2_current_tilemap.transparency == STV_TRANSPARENCY_NONE ? "no trans" : "trans",
3285                           stv2_current_tilemap.window_control & 6 ? "window" : "no window",
3286                           stv2_current_tilemap.colour_calculation_enabled ? "cc" : "no cc",
3287                           (stv2_current_tilemap.incx == 0x10000 && stv2_current_tilemap.incy == 0x10000) ? "no zoom" : "zoom");
3288   }
3289
3290   /* size for n0 / n1 */
3291   switch (stv2_current_tilemap.bitmap_size)
3292   {
3293      case 0: xsize=512; ysize=256; break;
3294      case 1: xsize=512; ysize=512; break;
3295      case 2: xsize=1024; ysize=256; break;
3296      case 3: xsize=1024; ysize=512; break;
3297   }
3298   xsizemask = xsize - 1;
3299   /*ysizemask = ysize - 1;*/
3300
3301   switch( stv2_current_tilemap.colour_depth )
3302   {
3303      case 0: xlinesize = xsize / 2; /*xpixelsize = 0;*/ break;
3304      case 1: xlinesize = xsize; /*xpixelsize = 1;*/ break;
3305      case 2: case 3: xlinesize = xsize * 2; /*xpixelsize = 2;*/ break;
3306      case 4: xlinesize = xsize * 4; /*xpixelsize = 4;*/ break;
3307   }
3308
3309   if(stv2_current_tilemap.colour_depth == 0)
3310      stv2_current_tilemap.scrollx /= 2;
3311   if(stv2_current_tilemap.colour_depth == 2 || stv2_current_tilemap.colour_depth == 3)
3312      stv2_current_tilemap.scrollx*=2;
3313   if(stv2_current_tilemap.colour_depth == 4)
3314      stv2_current_tilemap.scrollx*=4;
3315
3316   gfxdatalow = gfxdata + stv2_current_tilemap.bitmap_map * 0x20000;
3317   gfxdata+=(
3318   (stv2_current_tilemap.scrollx & (xlinesize-1)) +
3319   ((stv2_current_tilemap.scrolly & (ysize-1)) * (xlinesize)) + /* TODO: mask ysize, check me! */
3320   (stv2_current_tilemap.bitmap_map * 0x20000)
3321   );
3322   gfxdatahigh = gfxdatalow + xlinesize*ysize;
3323
3324//  popmessage("%04x %04x",stv2_current_tilemap.scrollx,stv2_current_tilemap.scrolly);
3325
3326   /*Enable fading bit*/
3327   if(stv2_current_tilemap.fade_control & 1)
3328   {
3329      /*Select fading bit*/
3330      pal_color_offset += ((stv2_current_tilemap.fade_control & 2) ? (2*2048) : (2048));
3331   }
3332
3333   stv2_current_tilemap.bitmap_palette_number+=stv2_current_tilemap.colour_ram_address_offset;
3334   stv2_current_tilemap.bitmap_palette_number&=7;//safety check
3335
3336   screen_x = machine().primary_screen->visible_area().max_x;
3337   screen_y = machine().primary_screen->visible_area().max_y;
3338
3339   switch(stv2_current_tilemap.colour_depth)
3340   {
3341      /*Palette Format*/
3342      case 0:
3343         for (ycnt = 0; ycnt <ysize;ycnt++)
3344         {
3345            for (xcnt = 0; xcnt <xsize;xcnt+=2)
3346            {
3347               if (!stv_vdp2_window_process(xcnt+1,ycnt))
3348               {
3349                  if ((gfxdata[0] & 0x0f) || (stv2_current_tilemap.transparency == STV_TRANSPARENCY_NONE))
3350                  {
3351                     if (((xcnt + 1) <= screen_x) && (ycnt <= screen_y))
3352                     {
3353                        if ( stv2_current_tilemap.colour_calculation_enabled == 0 )
3354                           bitmap.pix32(ycnt, xcnt+1) = machine().pens[((gfxdata[0] & 0x0f) >> 0) | (stv2_current_tilemap.bitmap_palette_number * 0x100) | pal_color_offset];
3355                        else
3356                           bitmap.pix32(ycnt, xcnt+1) = alpha_blend_r32(bitmap.pix32(ycnt, xcnt+1), machine().pens[((gfxdata[0] & 0x0f) >> 0) | (stv2_current_tilemap.bitmap_palette_number * 0x100) | pal_color_offset], stv2_current_tilemap.alpha);
3357                     }
3358                  }
3359               }
3360               if (!stv_vdp2_window_process(xcnt,ycnt))
3361               {
3362                  if ((gfxdata[0] & 0xf0) || (stv2_current_tilemap.transparency == STV_TRANSPARENCY_NONE))
3363                  {
3364                     if (((xcnt + 0) <= screen_x) && (ycnt <= screen_y))
3365                     {
3366                        if ( stv2_current_tilemap.colour_calculation_enabled == 0 )
3367                           bitmap.pix32(ycnt, xcnt) = machine().pens[((gfxdata[0] & 0xf0) >> 4) | (stv2_current_tilemap.bitmap_palette_number * 0x100) | pal_color_offset];
3368                        else
3369                           bitmap.pix32(ycnt, xcnt) = alpha_blend_r32(bitmap.pix32(ycnt, xcnt), machine().pens[((gfxdata[0] & 0xf0) >> 4) | (stv2_current_tilemap.bitmap_palette_number * 0x100) | pal_color_offset], stv2_current_tilemap.alpha);
3370                     }
3371                  }
3372               }
3373               gfxdata++;
3374               if ( gfxdata >= gfxdatahigh ) gfxdata = gfxdatalow;
3375            }
3376         }
3377         break;
3378      case 1:
3379         if ( stv2_current_tilemap.incx == 0x10000 && stv2_current_tilemap.incy == 0x10000 )
3380         {
3381            //int gfx_wraparound = -1;
3382
3383            gfxdata += xlinesize*cliprect.min_y;
3384
3385            for (ycnt = cliprect.min_y; ycnt <= cliprect.max_y; ycnt++)
3386            {
3387               for (xcnt = cliprect.min_x; xcnt <= cliprect.max_x; xcnt++)
3388               {
3389                  int xs = xcnt & xsizemask;
3390
3391                  if (!stv_vdp2_window_process(xcnt,ycnt))
3392                  {
3393                     //60aee2c = $0013 at @605d838
3394                     if ((gfxdata[xs] & 0xff) || (stv2_current_tilemap.transparency == STV_TRANSPARENCY_NONE))
3395                     {
3396                        if (((xcnt + 0) <= screen_x) && (ycnt <= screen_y))
3397                        {
3398                           if ( stv2_current_tilemap.colour_calculation_enabled == 0 )
3399                              bitmap.pix32(ycnt, xcnt) = machine().pens[(gfxdata[xs] & 0xff) | (stv2_current_tilemap.bitmap_palette_number * 0x100) | pal_color_offset];
3400                           else
3401                              bitmap.pix32(ycnt, xcnt) = alpha_blend_r32(bitmap.pix32(ycnt, xcnt), machine().pens[(gfxdata[xs] & 0xff) | (stv2_current_tilemap.bitmap_palette_number * 0x100) | pal_color_offset], stv2_current_tilemap.alpha);
3402                        }
3403                     }
3404                  }
3405                  if ( (gfxdata + xs) >= gfxdatahigh )
3406                  {
3407                     //gfx_wraparound = (ycnt << 16) | xcnt;
3408                     gfxdata = gfxdatalow - xs;
3409                  }
3410               }
3411               if ( (gfxdata + xlinesize) < gfxdatahigh )
3412               {
3413                  gfxdata += xlinesize;
3414               }
3415               else
3416               {
3417                  gfxdata = gfxdatalow + ((gfxdata + xlinesize) - gfxdatahigh);
3418               }
3419            }
3420
3421         }
3422         else
3423         {
3424            int xx, xs, yy=0;
3425            for (ycnt = cliprect.min_y; ycnt <= cliprect.max_y; yy+=stv2_current_tilemap.incy, ycnt++ )
3426            {
3427               gfxdata += xlinesize*(yy>>16);
3428               yy &= 0xffff;
3429
3430               xx = 0;
3431               for (xcnt = cliprect.min_x; xcnt <= cliprect.max_x; xx+=stv2_current_tilemap.incx, xcnt++)
3432               {
3433                  xs = xx >> 16;
3434                  if (!stv_vdp2_window_process(xcnt,ycnt))
3435                  {
3436                     if ((gfxdata[xs] & 0xff) || (stv2_current_tilemap.transparency == STV_TRANSPARENCY_NONE))
3437                     {
3438                        if (((xcnt + 0) <= screen_x) && (ycnt <= screen_y))
3439                        {
3440                           if ( stv2_current_tilemap.colour_calculation_enabled == 0 )
3441                              bitmap.pix32(ycnt, xcnt) = machine().pens[(gfxdata[xs] & 0xff) | (stv2_current_tilemap.bitmap_palette_number * 0x100) | pal_color_offset];
3442                           else
3443                              bitmap.pix32(ycnt, xcnt) = alpha_blend_r32(bitmap.pix32(ycnt, xcnt), machine().pens[(gfxdata[xs] & 0xff) | (stv2_current_tilemap.bitmap_palette_number * 0x100) | pal_color_offset], stv2_current_tilemap.alpha);
3444                        }
3445                     }
3446                  }
3447
3448                  if ( (gfxdata + xs) >= gfxdatahigh ) gfxdata = gfxdatalow;
3449
3450               }
3451            }
3452         }
3453         break;
3454      case 2:
3455         for (ycnt = 0; ycnt <ysize;ycnt++)
3456         {
3457            for (xcnt = 0; xcnt <xsize;xcnt++)
3458            {
3459               if (!stv_vdp2_window_process(xcnt,ycnt))
3460               {
3461                  if (((gfxdata[0] & 0x07) | (gfxdata[1] & 0xff)) || (stv2_current_tilemap.transparency == STV_TRANSPARENCY_NONE))
3462                  {
3463                     if (((xcnt + 0) <= screen_x) && (ycnt <= screen_y))
3464                     {
3465                        if ( stv2_current_tilemap.colour_calculation_enabled == 0 )
3466                           bitmap.pix32(ycnt, xcnt) = machine().pens[((gfxdata[0] & 0x07) * 0x100) | (gfxdata[1] & 0xff) | pal_color_offset];
3467                        else
3468                           bitmap.pix32(ycnt, xcnt) = alpha_blend_r32(bitmap.pix32(ycnt, xcnt), machine().pens[((gfxdata[0] & 0x07) * 0x100) | (gfxdata[1] & 0xff) | pal_color_offset], stv2_current_tilemap.alpha);
3469                     }
3470                  }
3471               }
3472
3473               gfxdata+=2;
3474               if ( gfxdata >= gfxdatahigh ) gfxdata = gfxdatalow;
3475            }
3476         }
3477         break;
3478      /*RGB format*/
3479      /*
3480      M                     L
3481      S                     S
3482      B                     B
3483      --------BBBBBGGGGGRRRRR
3484      */
3485      case 3:
3486         if ( stv2_current_tilemap.incx == 0x10000 && stv2_current_tilemap.incy == 0x10000 )
3487         {
3488            /* adjust for cliprect */
3489            gfxdata += xlinesize*cliprect.min_y;
3490
3491            for (ycnt = cliprect.min_y; ycnt <= cliprect.max_y; ycnt++)
3492            {
3493               destline = &bitmap.pix32(ycnt);
3494
3495               for (xcnt = cliprect.min_x; xcnt <= cliprect.max_x; xcnt++)
3496               {
3497                  int r,g,b;
3498                  int xs = xcnt & xsizemask;
3499
3500                  if ((gfxdata[2*xs] & 0x80) || (stv2_current_tilemap.transparency == STV_TRANSPARENCY_NONE))
3501                  {
3502                     b = pal5bit(((gfxdata[2*xs] & 0x7c) >> 2));
3503                     g = pal5bit(((gfxdata[2*xs] & 0x03) << 3) | ((gfxdata[2*xs+1] & 0xe0) >> 5));
3504                     r = pal5bit(gfxdata[2*xs+1] & 0x1f);
3505                     if(stv2_current_tilemap.fade_control & 1)
3506                        stv_vdp2_compute_color_offset(&r,&g,&b,stv2_current_tilemap.fade_control & 2);
3507
3508                     if (!stv_vdp2_window_process(xcnt,ycnt))
3509                     {
3510                        if (((xcnt + 0) <= screen_x) && (ycnt <= screen_y))
3511                        {
3512                           if ( stv2_current_tilemap.colour_calculation_enabled == 0 )
3513                              destline[xcnt] = MAKE_RGB(r, g, b);
3514                           else
3515                              destline[xcnt] = alpha_blend_r32( destline[xcnt], MAKE_RGB(r, g, b), stv2_current_tilemap.alpha );
3516                        }
3517                     }
3518                  }
3519
3520                  if ( (gfxdata + 2*xs) >= gfxdatahigh ) gfxdata = gfxdatalow;
3521               }
3522
3523               gfxdata += xlinesize;
3524               if ( gfxdata >= gfxdatahigh ) gfxdata = gfxdatalow + (gfxdata - gfxdatahigh);
3525            }
3526
3527         }
3528         else
3529         {
3530            int xx, xs, yy=0;
3531
3532            for (ycnt = cliprect.min_y; ycnt <= cliprect.max_y; yy+=stv2_current_tilemap.incy, ycnt++ )
3533            {
3534               gfxdata += xlinesize*(yy>>16);
3535               yy &= 0xffff;
3536
3537               destline = &bitmap.pix32(ycnt);
3538               xx = 0;
3539               for (xcnt = cliprect.min_x; xcnt <= cliprect.max_x; xx+=stv2_current_tilemap.incx, xcnt++)
3540               {
3541                  int r,g,b;
3542
3543                  xs = xx >> 16;
3544                  b = pal5bit(((gfxdata[2*xs] & 0x7c) >> 2));
3545                  g = pal5bit(((gfxdata[2*xs] & 0x03) << 3) | ((gfxdata[2*xs+1] & 0xe0) >> 5));
3546                  r = pal5bit(gfxdata[2*xs+1] & 0x1f);
3547                  if(stv2_current_tilemap.fade_control & 1)
3548                     stv_vdp2_compute_color_offset( &r,&g,&b,stv2_current_tilemap.fade_control & 2);
3549
3550                  if (!stv_vdp2_window_process(xcnt,ycnt))
3551                  {
3552                     if ((gfxdata[2*xs] & 0x80) || (stv2_current_tilemap.transparency == STV_TRANSPARENCY_NONE))
3553                     {
3554                        if (((xcnt + 0) <= screen_x) && (ycnt <= screen_y))
3555                        {
3556                        if ( stv2_current_tilemap.colour_calculation_enabled == 1 )
3557                           destline[xcnt] = alpha_blend_r32( destline[xcnt], MAKE_RGB(r, g, b), stv2_current_tilemap.alpha );
3558                        else
3559                           destline[xcnt] = MAKE_RGB(r, g, b);
3560                        }
3561                     }
3562                  }
3563
3564                  if ( (gfxdata + 2*xs) >= gfxdatahigh ) gfxdata = gfxdatalow;
3565               }
3566               /*Guess: myfairlady needs that the vertical resolution is doubled because it's using the double density mode.*/
3567               if(STV_VDP2_LSMD == 3) { gfxdata += xlinesize*(yy>>16); }
3568               else                   { gfxdata += xlinesize; }
3569               if ( gfxdata >= gfxdatahigh ) gfxdata = gfxdatalow + (gfxdata - gfxdatahigh);
3570            }
3571         }
3572         break;
3573      /*
3574      M                              L
3575      S                              S
3576      B                              B
3577      --------BBBBBBBBGGGGGGGGRRRRRRRR
3578      */
3579      case 4:
3580         /* adjust for cliprect */
3581         gfxdata += xlinesize*(cliprect.min_y);
3582
3583         for (ycnt = cliprect.min_y; ycnt <= cliprect.max_y; ycnt++)
3584         {
3585            destline = &bitmap.pix32(ycnt);
3586
3587            for (xcnt = cliprect.min_x; xcnt <= cliprect.max_x; xcnt++)
3588            {
3589               int r,g,b;
3590               int xs = xcnt & xsizemask;
3591               UINT32 dot_data;
3592
3593               dot_data = (gfxdata[4*xs+0]<<24)|(gfxdata[4*xs+1]<<16)|(gfxdata[4*xs+2]<<8)|(gfxdata[4*xs+3]<<0);
3594               if ((dot_data & 0x80000000) || (stv2_current_tilemap.transparency == STV_TRANSPARENCY_NONE))
3595               {
3596                  b = ((dot_data & 0x00ff0000) >> 16);
3597                  g = ((dot_data & 0x0000ff00) >> 8);
3598                  r = ((dot_data & 0x000000ff) >> 0);
3599
3600                  if(stv2_current_tilemap.fade_control & 1)
3601                     stv_vdp2_compute_color_offset(&r,&g,&b,stv2_current_tilemap.fade_control & 2);
3602
3603                  if (!stv_vdp2_window_process(xcnt,ycnt))
3604                  {
3605                     if (((xcnt + 0) <= screen_x) && (ycnt <= screen_y))
3606                     {
3607                        if ( stv2_current_tilemap.colour_calculation_enabled == 0 )
3608                           destline[xcnt] = MAKE_RGB(r, g, b);
3609                        else
3610                           destline[xcnt] = alpha_blend_r32( destline[xcnt], MAKE_RGB(r, g, b), stv2_current_tilemap.alpha );
3611                     }
3612                  }
3613               }
3614
3615               if ( (gfxdata + 4*xs) >= gfxdatahigh ) gfxdata = gfxdatalow;
3616            }
3617
3618            gfxdata += xlinesize;
3619            if ( gfxdata >= gfxdatahigh ) gfxdata = gfxdatalow + (gfxdata - gfxdatahigh);
3620         }
3621
3622         break;
3623   }
3624}
3625
3626   /*---------------------------------------------------------------------------
3627   | Plane Size | Pattern Name Data Size | Character Size | Map Bits / Address |
3628   ----------------------------------------------------------------------------|
3629   |            |                        | 1 H x 1 V      | bits 6-0 * 0x02000 |
3630   |            | 1 word                 |-------------------------------------|
3631   |            |                        | 2 H x 2 V      | bits 8-0 * 0x00800 |
3632   | 1 H x 1 V  ---------------------------------------------------------------|
3633   |            |                        | 1 H x 1 V      | bits 5-0 * 0x04000 |
3634   |            | 2 words                |-------------------------------------|
3635   |            |                        | 2 H x 2 V      | bits 7-0 * 0x01000 |
3636   -----------------------------------------------------------------------------
3637   |            |                        | 1 H x 1 V      | bits 6-1 * 0x04000 |
3638   |            | 1 word                 |-------------------------------------|
3639   |            |                        | 2 H x 2 V      | bits 8-1 * 0x01000 |
3640   | 2 H x 1 V  ---------------------------------------------------------------|
3641   |            |                        | 1 H x 1 V      | bits 5-1 * 0x08000 |
3642   |            | 2 words                |-------------------------------------|
3643   |            |                        | 2 H x 2 V      | bits 7-1 * 0x02000 |
3644   -----------------------------------------------------------------------------
3645   |            |                        | 1 H x 1 V      | bits 6-2 * 0x08000 |
3646   |            | 1 word                 |-------------------------------------|
3647   |            |                        | 2 H x 2 V      | bits 8-2 * 0x02000 |
3648   | 2 H x 2 V  ---------------------------------------------------------------|
3649   |            |                        | 1 H x 1 V      | bits 5-2 * 0x10000 |
3650   |            | 2 words                |-------------------------------------|
3651   |            |                        | 2 H x 2 V      | bits 7-2 * 0x04000 |
3652   --the-highest-bit-is-ignored-if-vram-is-only-4mbits------------------------*/
3653
3654
3655/*
36564.2 Sega's Cell / Character Pattern / Page / Plane / Map system, aka a rather annoying thing that makes optimizations hard
3657 (this is only for the normal tilemaps at the moment, i haven't even thought about the ROZ ones)
3658
3659Tiles:
3660
3661Cells are 8x8 gfx stored in video ram, they can be of various colour depths
3662
3663Character Patterns can be 8x8 or 16x16 (1 hcell x 1 vcell or 2 hcell x 2 vcell)
3664  (a 16x16 character pattern is 4 8x8 cells put together)
3665
3666A page is made up of 64x64 cells, thats 64x64 character patterns in 8x8 mode or 32x32 character patterns in 16x16 mode.
3667  64 * 8  = 512 (0x200)
3668  32 * 16 = 512 (0x200)
3669A page is _always_ 512 (0x200) pixels in each direction
3670
3671in 1 word mode a 32*16 x 32*16 page is 0x0800 bytes
3672in 1 word mode a 64*8  x 64*8  page is 0x2000 bytes
3673in 2 word mode a 32*16 x 32*16 page is 0x1000 bytes
3674in 2 word mode a 64*8  x 64*8  page is 0x4000 bytes
3675
3676either 1, 2 or 4 pages make each plane depending on the plane size register (per tilemap)
3677  therefore each plane is either
3678  64 * 8 * 1 x 64 * 8 * 1 (512 x 512)
3679  64 * 8 * 2 x 64 * 8 * 1 (1024 x 512)
3680  64 * 8 * 2 x 64 * 8 * 2 (1024 x 1024)
3681
3682  32 * 16 * 1 x 32 * 16 * 1 (512 x 512)
3683  32 * 16 * 2 x 32 * 16 * 1 (1024 x 512)
3684  32 * 16 * 2 x 32 * 16 * 2 (1024 x 1024)
3685
3686map is always enabled?
3687  map is a 2x2 arrangement of planes, all 4 of the planes can be the same.
3688
3689*/
3690
3691void saturn_state::stv_vdp2_get_map_page( int x, int y, int *_map, int *_page )
3692{
3693   int page = 0;
3694   int map = 0;
3695
3696   if ( stv2_current_tilemap.map_count == 4 )
3697   {
3698      if ( stv2_current_tilemap.tile_size == 0 )
3699      {
3700         if ( stv2_current_tilemap.plane_size & 1 )
3701         {
3702            page = ((x >> 6) & 1);
3703            map = (x >> 7) & 1;
3704         }
3705         else
3706         {
3707            map = (x >> 6) & 1;
3708         }
3709
3710         if ( stv2_current_tilemap.plane_size & 2 )
3711         {
3712            page |= ((y >> (6-1)) & 2);
3713            map |= ((y >> (7-1)) & 2);
3714         }
3715         else
3716         {
3717            map |= ((y >> (6-1)) & 2);
3718         }
3719      }
3720      else
3721      {
3722         if ( stv2_current_tilemap.plane_size & 1 )
3723         {
3724            page = ((x >> 5) & 1);
3725            map = (x >> 6) & 1;
3726         }
3727         else
3728         {
3729            map = (x >> 5) & 1;
3730         }
3731
3732         if ( stv2_current_tilemap.plane_size & 2 )
3733         {
3734            page |= ((y >> (5 - 1)) & 2);
3735            map |= ((y >> (6-1)) & 2);
3736         }
3737         else
3738         {
3739            map |= ((y >> (5-1)) & 2);
3740         }
3741      }
3742   }
3743   else //16
3744   {
3745      if ( stv2_current_tilemap.tile_size == 0 )
3746      {
3747         if ( stv2_current_tilemap.plane_size & 1 )
3748         {
3749            page = ((x >> 6) & 1);
3750            map = (x >> 7) & 3;
3751         }
3752         else
3753         {
3754            map = (x >> 6) & 3;
3755         }
3756
3757         if ( stv2_current_tilemap.plane_size & 2 )
3758         {
3759            page |= ((y >> (6-1)) & 2);
3760            map |= ((y >> (7-2)) & 12);
3761         }
3762         else
3763         {
3764            map |= ((y >> (6-2)) & 12);
3765         }
3766      }
3767      else
3768      {
3769         if ( stv2_current_tilemap.plane_size & 1 )
3770         {
3771            page = ((x >> 5) & 1);
3772            map = (x >> 6) & 3;
3773         }
3774         else
3775         {
3776            map = (x >> 5) & 3;
3777         }
3778
3779         if ( stv2_current_tilemap.plane_size & 2 )
3780         {
3781            page |= ((y >> (5 - 1)) & 2);
3782            map |= ((y >> (6-2)) & 12);
3783         }
3784         else
3785         {
3786            map |= ((y >> (5-2)) & 12);
3787         }
3788      }
3789   }
3790   *_page = page;
3791   *_map = map;
3792}
3793
3794void saturn_state::stv_vdp2_draw_basic_tilemap(bitmap_rgb32 &bitmap, const rectangle &cliprect)
3795{
3796   /* hopefully this is easier to follow than it is efficient .. */
3797
3798   /* I call character patterns tiles .. even if they represent up to 4 tiles */
3799
3800   /* Page variables */
3801   int pgtiles_x, pgpixels_x;
3802   int pgtiles_y, pgpixels_y;
3803   int pgsize_bytes, pgsize_dwords;
3804
3805   /* Plane Variables */
3806   int pltiles_x, plpixels_x;
3807   int pltiles_y, plpixels_y;
3808   int plsize_bytes/*, plsize_dwords*/;
3809
3810   /* Map Variables */
3811   int mptiles_x, mppixels_x;
3812   int mptiles_y, mppixels_y;
3813   int mpsize_bytes, mpsize_dwords;
3814
3815   /* work Variables */
3816   int i, x, y;
3817   int base[16];
3818
3819   int scalex,scaley;
3820   int tilesizex, tilesizey;
3821   int drawypos, drawxpos;
3822
3823   int tilecodemin = 0x10000000, tilecodemax = 0;
3824
3825   if ( stv2_current_tilemap.incx == 0 || stv2_current_tilemap.incy == 0 ) return;
3826
3827   if ( stv2_current_tilemap.colour_calculation_enabled == 1 )
3828   {
3829      if ( STV_VDP2_CCMD )
3830      {
3831         stv2_current_tilemap.transparency = STV_TRANSPARENCY_ADD_BLEND;
3832      }
3833      else
3834      {
3835         stv2_current_tilemap.transparency = STV_TRANSPARENCY_ALPHA;
3836      }
3837   }
3838
3839   scalex = (INT32)((INT64)S64(0x100000000) / (INT64)stv2_current_tilemap.incx);
3840   scaley = (INT32)((INT64)S64(0x100000000) / (INT64)stv2_current_tilemap.incy);
3841   tilesizex = scalex * 8;
3842   tilesizey = scaley * 8;
3843   drawypos = drawxpos = 0;
3844
3845   /* Calculate the Number of tiles for x / y directions of each page (actually these will be the same */
3846   /* (2-stv2_current_tilemap.tile_size) << 5) */
3847   pgtiles_x = ((2-stv2_current_tilemap.tile_size) << 5); // 64 (8x8 mode) or 32 (16x16 mode)
3848   pgtiles_y = ((2-stv2_current_tilemap.tile_size) << 5); // 64 (8x8 mode) or 32 (16x16 mode)
3849
3850   /* Calculate the Page Size in BYTES */
3851   /* 64 * 64 * (1 * 2) = 0x2000 bytes
3852      32 * 32 * (1 * 2) = 0x0800 bytes
3853      64 * 64 * (2 * 2) = 0x4000 bytes
3854      32 * 32 * (2 * 2) = 0x1000 bytes */
3855
3856   pgsize_bytes = (pgtiles_x * pgtiles_y) * ((2-stv2_current_tilemap.pattern_data_size)*2);
3857
3858   /*---------------------------------------------------------------------------
3859   | Plane Size | Pattern Name Data Size | Character Size | Map Bits / Address |
3860   ----------------------------------------------------------------------------|
3861   |            |                        | 1 H x 1 V      | bits 6-0 * 0x02000 |
3862   |            | 1 word                 |-------------------------------------|
3863   |            |                        | 2 H x 2 V      | bits 8-0 * 0x00800 |
3864   | 1 H x 1 V  ---------------------------------------------------------------|
3865   |            |                        | 1 H x 1 V      | bits 5-0 * 0x04000 |
3866   |            | 2 words                |-------------------------------------|
3867   |            |                        | 2 H x 2 V      | bits 7-0 * 0x01000 |
3868   ---------------------------------------------------------------------------*/
3869
3870
3871   /* Page Dimensions are always 0x200 pixes (512x512) */
3872   pgpixels_x = 0x200;
3873   pgpixels_y = 0x200;
3874
3875   /* Work out the Plane Size in tiles and Plane Dimensions (pixels) */
3876   switch (stv2_current_tilemap.plane_size & 3)
3877   {
3878      case 0: // 1 page * 1 page
3879         pltiles_x  = pgtiles_x;
3880         plpixels_x = pgpixels_x;
3881         pltiles_y  = pgtiles_y;
3882         plpixels_y = pgpixels_y;
3883         break;
3884
3885      case 1: // 2 pages * 1 page
3886         pltiles_x  = pgtiles_x * 2;
3887         plpixels_x = pgpixels_x * 2;
3888         pltiles_y  = pgtiles_y;
3889         plpixels_y = pgpixels_y;
3890         break;
3891
3892      case 3: // 2 pages * 2 pages
3893         pltiles_x  = pgtiles_x * 2;
3894         plpixels_x = pgpixels_x * 2;
3895         pltiles_y  = pgtiles_y * 2;
3896         plpixels_y = pgpixels_y * 2;
3897         break;
3898
3899      default:
3900         // illegal
3901         pltiles_x  = pgtiles_x;
3902         plpixels_x = pgpixels_x;
3903         pltiles_y  = pgtiles_y * 2;
3904         plpixels_y = pgpixels_y * 2;
3905      break;
3906   }
3907
3908   /* Plane Size in BYTES */
3909   /* still the same as before
3910      (64 * 1) * (64 * 1) * (1 * 2) = 0x02000 bytes
3911      (32 * 1) * (32 * 1) * (1 * 2) = 0x00800 bytes
3912      (64 * 1) * (64 * 1) * (2 * 2) = 0x04000 bytes
3913      (32 * 1) * (32 * 1) * (2 * 2) = 0x01000 bytes
3914      changed
3915      (64 * 2) * (64 * 1) * (1 * 2) = 0x04000 bytes
3916      (32 * 2) * (32 * 1) * (1 * 2) = 0x01000 bytes
3917      (64 * 2) * (64 * 1) * (2 * 2) = 0x08000 bytes
3918      (32 * 2) * (32 * 1) * (2 * 2) = 0x02000 bytes
3919      changed
3920      (64 * 2) * (64 * 1) * (1 * 2) = 0x08000 bytes
3921      (32 * 2) * (32 * 1) * (1 * 2) = 0x02000 bytes
3922      (64 * 2) * (64 * 1) * (2 * 2) = 0x10000 bytes
3923      (32 * 2) * (32 * 1) * (2 * 2) = 0x04000 bytes
3924   */
3925
3926   plsize_bytes = (pltiles_x * pltiles_y) * ((2-stv2_current_tilemap.pattern_data_size)*2);
3927
3928   /*---------------------------------------------------------------------------
3929   | Plane Size | Pattern Name Data Size | Character Size | Map Bits / Address |
3930   -----------------------------------------------------------------------------
3931   | 1 H x 1 V   see above, nothing has changed                                |
3932   -----------------------------------------------------------------------------
3933   |            |                        | 1 H x 1 V      | bits 6-1 * 0x04000 |
3934   |            | 1 word                 |-------------------------------------|
3935   |            |                        | 2 H x 2 V      | bits 8-1 * 0x01000 |
3936   | 2 H x 1 V  ---------------------------------------------------------------|
3937   |            |                        | 1 H x 1 V      | bits 5-1 * 0x08000 |
3938   |            | 2 words                |-------------------------------------|
3939   |            |                        | 2 H x 2 V      | bits 7-1 * 0x02000 |
3940   -----------------------------------------------------------------------------
3941   |            |                        | 1 H x 1 V      | bits 6-2 * 0x08000 |
3942   |            | 1 word                 |-------------------------------------|
3943   |            |                        | 2 H x 2 V      | bits 8-2 * 0x02000 |
3944   | 2 H x 2 V  ---------------------------------------------------------------|
3945   |            |                        | 1 H x 1 V      | bits 5-2 * 0x10000 |
3946   |            | 2 words                |-------------------------------------|
3947   |            |                        | 2 H x 2 V      | bits 7-2 * 0x04000 |
3948   --the-highest-bit-is-ignored-if-vram-is-only-4mbits------------------------*/
3949
3950
3951   /* Work out the Map Sizes in tiles, Map Dimensions */
3952   /* maps are always enabled? */
3953   if ( stv2_current_tilemap.map_count == 4 )
3954   {
3955      mptiles_x = pltiles_x * 2;
3956      mptiles_y = pltiles_y * 2;
3957      mppixels_x = plpixels_x * 2;
3958      mppixels_y = plpixels_y * 2;
3959   }
3960   else
3961   {
3962      mptiles_x = pltiles_x * 4;
3963      mptiles_y = pltiles_y * 4;
3964      mppixels_x = plpixels_x * 4;
3965      mppixels_y = plpixels_y * 4;
3966   }
3967
3968   /* Map Size in BYTES */
3969   mpsize_bytes = (mptiles_x * mptiles_y) * ((2-stv2_current_tilemap.pattern_data_size)*2);
3970
3971
3972   /*-----------------------------------------------------------------------------------------------------------
3973   |            |                        | 1 H x 1 V      | bits 6-1 (upper mask 0x07f) (0x1ff >> 2) * 0x04000 |
3974   |            | 1 word                 |---------------------------------------------------------------------|
3975   |            |                        | 2 H x 2 V      | bits 8-1 (upper mask 0x1ff) (0x1ff >> 0) * 0x01000 |
3976   | 2 H x 1 V  -----------------------------------------------------------------------------------------------|
3977   |            |                        | 1 H x 1 V      | bits 5-1 (upper mask 0x03f) (0x1ff >> 3) * 0x08000 |
3978   |            | 2 words                |---------------------------------------------------------------------|
3979   |            |                        | 2 H x 2 V      | bits 7-1 (upper mask 0x0ff) (0x1ff >> 1) * 0x02000 |
3980   -------------------------------------------------------------------------------------------------------------
3981   lower mask = ~stv2_current_tilemap.plane_size
3982   -----------------------------------------------------------------------------------------------------------*/
3983
3984   /* Precalculate bases from MAP registers */
3985   for (i = 0; i < stv2_current_tilemap.map_count; i++)
3986   {
3987      static const int shifttable[4] = {0,1,2,2};
3988
3989      int uppermask, uppermaskshift;
3990
3991      uppermaskshift = (1-stv2_current_tilemap.pattern_data_size) | ((1-stv2_current_tilemap.tile_size)<<1);
3992      uppermask = 0x1ff >> uppermaskshift;
3993
3994      base[i] = ((stv2_current_tilemap.map_offset[i] & uppermask) >> shifttable[stv2_current_tilemap.plane_size]) * plsize_bytes;
3995
3996      base[i] &= 0x7ffff; /* shienryu needs this for the text layer, is there a problem elsewhere or is it just right without the ram cart */
3997
3998      base[i] = base[i] / 4; // convert bytes to DWORDS
3999   }
4000
4001   /* other bits */
4002   //stv2_current_tilemap.trans_enabled = stv2_current_tilemap.trans_enabled ? STV_TRANSPARENCY_NONE : STV_TRANSPARENCY_PEN;
4003   stv2_current_tilemap.scrollx &= mppixels_x-1;
4004   stv2_current_tilemap.scrolly &= mppixels_y-1;
4005
4006   pgsize_dwords = pgsize_bytes /4;
4007   //plsize_dwords = plsize_bytes /4;
4008   mpsize_dwords = mpsize_bytes /4;
4009
4010//  if (stv2_current_tilemap.layer_name==3) popmessage ("well this is a bit  %08x", stv2_current_tilemap.map_offset[0]);
4011//  if (stv2_current_tilemap.layer_name==3) popmessage ("well this is a bit  %08x %08x %08x %08x", stv2_current_tilemap.plane_size, pgtiles_x, pltiles_x, mptiles_x);
4012
4013   if (!stv2_current_tilemap.enabled) return; // stop right now if its disabled ...
4014
4015   /* most things we need (or don't need) to work out are now worked out */
4016
4017   for (y = 0; y<mptiles_y; y++) {
4018      int ypageoffs;
4019      int page, map, newbase, offs, data;
4020      int tilecode, flipyx, pal, gfx = 0;
4021
4022      map = 0 ; page = 0 ;
4023      if ( y == 0 )
4024      {
4025         int drawyposinc = tilesizey*(stv2_current_tilemap.tile_size ? 2 : 1);
4026         drawypos = -(stv2_current_tilemap.scrolly*scaley);
4027         while( ((drawypos + drawyposinc) >> 16) < cliprect.min_y )
4028         {
4029            drawypos += drawyposinc;
4030            y++;
4031         }
4032         mptiles_y += y;
4033      }
4034      else
4035      {
4036         drawypos += tilesizey*(stv2_current_tilemap.tile_size ? 2 : 1);
4037      }
4038      if ((drawypos >> 16) > cliprect.max_y) break;
4039
4040      ypageoffs = y & (pgtiles_y-1);
4041
4042      for (x = 0; x<mptiles_x; x++) {
4043         int xpageoffs;
4044         int tilecodespacing = 1;
4045
4046         if ( x == 0 )
4047         {
4048            int drawxposinc = tilesizex*(stv2_current_tilemap.tile_size ? 2 : 1);
4049            drawxpos = -(stv2_current_tilemap.scrollx*scalex);
4050            while( ((drawxpos + drawxposinc) >> 16) < cliprect.min_x )
4051            {
4052               drawxpos += drawxposinc;
4053               x++;
4054            }
4055            mptiles_x += x;
4056         }
4057         else
4058         {
4059            drawxpos+=tilesizex*(stv2_current_tilemap.tile_size ? 2 : 1);
4060         }
4061         if ( (drawxpos >> 16) > cliprect.max_x ) break;
4062
4063         xpageoffs = x & (pgtiles_x-1);
4064
4065         stv_vdp2_get_map_page(x,y,&map,&page);
4066
4067         newbase = base[map] + page * pgsize_dwords;
4068         offs = (ypageoffs * pgtiles_x) + xpageoffs;
4069
4070/* GET THE TILE INFO ... */
4071         /* 1 word per tile mode with supplement bits */
4072         if (stv2_current_tilemap.pattern_data_size ==1)
4073         {
4074            data = m_vdp2_vram[newbase + offs/2];
4075            data = (offs&1) ? (data & 0x0000ffff) : ((data & 0xffff0000) >> 16);
4076
4077            /* Supplement Mode 12 bits, no flip */
4078            if (stv2_current_tilemap.character_number_supplement == 1)
4079            {
4080/* no flip */       flipyx   = 0;
4081/* 8x8 */           if (stv2_current_tilemap.tile_size==0) tilecode = (data & 0x0fff) + ( (stv2_current_tilemap.supplementary_character_bits&0x1c) << 10);
4082/* 16x16 */         else tilecode = ((data & 0x0fff) << 2) + (stv2_current_tilemap.supplementary_character_bits&0x03) + ((stv2_current_tilemap.supplementary_character_bits&0x10) << 10);
4083            }
4084            /* Supplement Mode 10 bits, with flip */
4085            else
4086            {
4087/* flip bits */     flipyx   = (data & 0x0c00) >> 10;
4088/* 8x8 */           if (stv2_current_tilemap.tile_size==0) tilecode = (data & 0x03ff) +  ( (stv2_current_tilemap.supplementary_character_bits) << 10);
4089/* 16x16 */         else tilecode = ((data & 0x03ff) <<2) +  (stv2_current_tilemap.supplementary_character_bits&0x03) + ((stv2_current_tilemap.supplementary_character_bits&0x1c) << 10);
4090            }
4091
4092/*>16cols*/     if (stv2_current_tilemap.colour_depth != 0) pal = ((data & 0x7000)>>8);
4093/*16 cols*/     else pal = ((data & 0xf000)>>12) +( (stv2_current_tilemap.supplementary_palette_bits) << 4);
4094
4095         }
4096         /* 2 words per tile, no supplement bits */
4097         else
4098         {
4099            data = m_vdp2_vram[newbase + offs];
4100            tilecode = (data & 0x00007fff);
4101            pal   = (data &    0x007f0000)>>16;
4102   //          specialc = (data & 0x10000000)>>28;
4103            flipyx   = (data & 0xc0000000)>>30;
4104         }
4105/* WE'VE GOT THE TILE INFO ... */
4106
4107         if ( tilecode < tilecodemin ) tilecodemin = tilecode;
4108         if ( tilecode > tilecodemax ) tilecodemax = tilecode;
4109
4110/* DECODE ANY TILES WE NEED TO DECODE */
4111
4112         pal += stv2_current_tilemap.colour_ram_address_offset<< 4; // bios uses this ..
4113
4114         /*Enable fading bit*/
4115         if(stv2_current_tilemap.fade_control & 1)
4116         {
4117            /*Select fading bit*/
4118            pal += ((stv2_current_tilemap.fade_control & 2) ? (0x100) : (0x80));
4119         }
4120
4121         if (stv2_current_tilemap.colour_depth == 1)
4122         {
4123            gfx = 2;
4124            pal = pal >>4;
4125            tilecode &=0x7fff;
4126            if (tilecode == 0x7fff) tilecode--; /* prevents crash but unsure what should happen; wrapping? */
4127            tilecodespacing = 2;
4128         }
4129         else if (stv2_current_tilemap.colour_depth == 0)
4130         {
4131            gfx = 0;
4132            tilecode &=0x7fff;
4133            tilecodespacing = 1;
4134         }
4135/* TILES ARE NOW DECODED */
4136
4137         if(!STV_VDP2_VRAMSZ)
4138            tilecode &= 0x3fff;
4139
4140/* DRAW! */
4141         if(stv2_current_tilemap.incx != 0x10000 ||
4142            stv2_current_tilemap.incy != 0x10000 ||
4143            stv2_current_tilemap.transparency == STV_TRANSPARENCY_ADD_BLEND )
4144         {
4145#define SCR_TILESIZE_X          (((drawxpos + tilesizex) >> 16) - (drawxpos >> 16))
4146#define SCR_TILESIZE_X1(startx) (((drawxpos + (startx) + tilesizex) >> 16) - ((drawxpos + (startx))>>16))
4147#define SCR_TILESIZE_Y          (((drawypos + tilesizey) >> 16) - (drawypos >> 16))
4148#define SCR_TILESIZE_Y1(starty) (((drawypos + (starty) + tilesizey) >> 16) - ((drawypos + (starty))>>16))
4149            if (stv2_current_tilemap.tile_size==1)
4150            {
4151               if ( stv2_current_tilemap.colour_depth == 4 )
4152               {
4153                  popmessage("Unsupported tilemap gfx zoom color depth = 4, tile size = 1, contact MAMEdev");
4154               }
4155               else if ( stv2_current_tilemap.colour_depth == 3 )
4156               {
4157                  /* RGB555 */
4158                  stv_vdp2_drawgfxzoom_rgb555(bitmap,cliprect,tilecode+(0+(flipyx&1)+(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos >> 16, drawypos >> 16,stv2_current_tilemap.transparency,0,scalex,scaley,SCR_TILESIZE_X, SCR_TILESIZE_Y,stv2_current_tilemap.alpha);
4159                  stv_vdp2_drawgfxzoom_rgb555(bitmap,cliprect,tilecode+(1-(flipyx&1)+(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,(drawxpos+tilesizex) >> 16,drawypos >> 16,stv2_current_tilemap.transparency,0,scalex,scaley,SCR_TILESIZE_X1(tilesizex), SCR_TILESIZE_Y,stv2_current_tilemap.alpha);
4160                  stv_vdp2_drawgfxzoom_rgb555(bitmap,cliprect,tilecode+(2+(flipyx&1)-(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos >> 16,(drawypos+tilesizey) >> 16,stv2_current_tilemap.transparency,0,scalex,scaley,SCR_TILESIZE_X, SCR_TILESIZE_Y1(tilesizey),stv2_current_tilemap.alpha);
4161                  stv_vdp2_drawgfxzoom_rgb555(bitmap,cliprect,tilecode+(3-(flipyx&1)-(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,(drawxpos+tilesizex)>> 16,(drawypos+tilesizey) >> 16,stv2_current_tilemap.transparency,0,scalex,scaley,SCR_TILESIZE_X1(tilesizex), SCR_TILESIZE_Y1(tilesizey),stv2_current_tilemap.alpha);
4162               }
4163               else
4164               {
4165                  /* normal */
4166                  stv_vdp2_drawgfxzoom(bitmap,cliprect,machine().gfx[gfx],tilecode+(0+(flipyx&1)+(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos >> 16, drawypos >> 16,stv2_current_tilemap.transparency,0,scalex,scaley,SCR_TILESIZE_X, SCR_TILESIZE_Y,stv2_current_tilemap.alpha);
4167                  stv_vdp2_drawgfxzoom(bitmap,cliprect,machine().gfx[gfx],tilecode+(1-(flipyx&1)+(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,(drawxpos+tilesizex) >> 16,drawypos >> 16,stv2_current_tilemap.transparency,0,scalex,scaley,SCR_TILESIZE_X1(tilesizex), SCR_TILESIZE_Y,stv2_current_tilemap.alpha);
4168                  stv_vdp2_drawgfxzoom(bitmap,cliprect,machine().gfx[gfx],tilecode+(2+(flipyx&1)-(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos >> 16,(drawypos+tilesizey) >> 16,stv2_current_tilemap.transparency,0,scalex,scaley,SCR_TILESIZE_X, SCR_TILESIZE_Y1(tilesizey),stv2_current_tilemap.alpha);
4169                  stv_vdp2_drawgfxzoom(bitmap,cliprect,machine().gfx[gfx],tilecode+(3-(flipyx&1)-(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,(drawxpos+tilesizex)>> 16,(drawypos+tilesizey) >> 16,stv2_current_tilemap.transparency,0,scalex,scaley,SCR_TILESIZE_X1(tilesizex), SCR_TILESIZE_Y1(tilesizey),stv2_current_tilemap.alpha);
4170               }
4171            }
4172            else
4173            {
4174               if ( stv2_current_tilemap.colour_depth == 4 )
4175                  popmessage("Unsupported tilemap gfx zoom color depth = 4, tile size = 0, contact MAMEdev");
4176               else if ( stv2_current_tilemap.colour_depth == 3)
4177               {
4178                  stv_vdp2_drawgfxzoom_rgb555(bitmap,cliprect,tilecode,pal,flipyx&1,flipyx&2, drawxpos >> 16, drawypos >> 16,stv2_current_tilemap.transparency,0,scalex,scaley,SCR_TILESIZE_X,SCR_TILESIZE_Y,stv2_current_tilemap.alpha);
4179               }
4180               else
4181                  stv_vdp2_drawgfxzoom(bitmap,cliprect,machine().gfx[gfx],tilecode,pal,flipyx&1,flipyx&2, drawxpos >> 16, drawypos >> 16,stv2_current_tilemap.transparency,0,scalex,scaley,SCR_TILESIZE_X,SCR_TILESIZE_Y,stv2_current_tilemap.alpha);
4182            }
4183         }
4184         else
4185         {
4186            int olddrawxpos, olddrawypos;
4187            olddrawxpos = drawxpos; drawxpos >>= 16;
4188            olddrawypos = drawypos; drawypos >>= 16;
4189            if (stv2_current_tilemap.tile_size==1)
4190            {
4191               if ( stv2_current_tilemap.colour_depth == 4 )
4192               {
4193                  /* normal */
4194                  stv_vdp2_drawgfx_rgb888(bitmap,cliprect,tilecode+(0+(flipyx&1)+(flipyx&2))*4,flipyx&1,flipyx&2,drawxpos, drawypos,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha);
4195                  stv_vdp2_drawgfx_rgb888(bitmap,cliprect,tilecode+(1-(flipyx&1)+(flipyx&2))*4,flipyx&1,flipyx&2,drawxpos+8,drawypos,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha);
4196                  stv_vdp2_drawgfx_rgb888(bitmap,cliprect,tilecode+(2+(flipyx&1)-(flipyx&2))*4,flipyx&1,flipyx&2,drawxpos,drawypos+8,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha);
4197                  stv_vdp2_drawgfx_rgb888(bitmap,cliprect,tilecode+(3-(flipyx&1)-(flipyx&2))*4,flipyx&1,flipyx&2,drawxpos+8,drawypos+8,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha);
4198               }
4199               else if ( stv2_current_tilemap.colour_depth == 3 )
4200               {
4201                  /* normal */
4202                  stv_vdp2_drawgfx_rgb555(bitmap,cliprect,tilecode+(0+(flipyx&1)+(flipyx&2))*4,flipyx&1,flipyx&2,drawxpos, drawypos,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha);
4203                  stv_vdp2_drawgfx_rgb555(bitmap,cliprect,tilecode+(1-(flipyx&1)+(flipyx&2))*4,flipyx&1,flipyx&2,drawxpos+8,drawypos,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha);
4204                  stv_vdp2_drawgfx_rgb555(bitmap,cliprect,tilecode+(2+(flipyx&1)-(flipyx&2))*4,flipyx&1,flipyx&2,drawxpos,drawypos+8,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha);
4205                  stv_vdp2_drawgfx_rgb555(bitmap,cliprect,tilecode+(3-(flipyx&1)-(flipyx&2))*4,flipyx&1,flipyx&2,drawxpos+8,drawypos+8,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha);
4206               }
4207               else if (stv2_current_tilemap.transparency == STV_TRANSPARENCY_ALPHA)
4208               {
4209                  /* alpha */
4210                  drawgfx_alpha(bitmap,cliprect,machine().gfx[gfx],tilecode+(0+(flipyx&1)+(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos, drawypos,0,stv2_current_tilemap.alpha);
4211                  drawgfx_alpha(bitmap,cliprect,machine().gfx[gfx],tilecode+(1-(flipyx&1)+(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos+8,drawypos,0,stv2_current_tilemap.alpha);
4212                  drawgfx_alpha(bitmap,cliprect,machine().gfx[gfx],tilecode+(2+(flipyx&1)-(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos,drawypos+8,0,stv2_current_tilemap.alpha);
4213                  drawgfx_alpha(bitmap,cliprect,machine().gfx[gfx],tilecode+(3-(flipyx&1)-(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos+8,drawypos+8,0,stv2_current_tilemap.alpha);
4214               }
4215               else
4216               {
4217                  /* normal */
4218                  drawgfx_transpen(bitmap,cliprect,machine().gfx[gfx],tilecode+(0+(flipyx&1)+(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos, drawypos,(stv2_current_tilemap.transparency==STV_TRANSPARENCY_PEN)?0:-1);
4219                  drawgfx_transpen(bitmap,cliprect,machine().gfx[gfx],tilecode+(1-(flipyx&1)+(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos+8,drawypos,(stv2_current_tilemap.transparency==STV_TRANSPARENCY_PEN)?0:-1);
4220                  drawgfx_transpen(bitmap,cliprect,machine().gfx[gfx],tilecode+(2+(flipyx&1)-(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos,drawypos+8,(stv2_current_tilemap.transparency==STV_TRANSPARENCY_PEN)?0:-1);
4221                  drawgfx_transpen(bitmap,cliprect,machine().gfx[gfx],tilecode+(3-(flipyx&1)-(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos+8,drawypos+8,(stv2_current_tilemap.transparency==STV_TRANSPARENCY_PEN)?0:-1);
4222               }
4223            }
4224            else
4225            {
4226               if ( stv2_current_tilemap.colour_depth == 4)
4227               {
4228                  stv_vdp2_drawgfx_rgb888(bitmap,cliprect,tilecode,flipyx&1,flipyx&2,drawxpos,drawypos,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha);
4229               }
4230               else if ( stv2_current_tilemap.colour_depth == 3)
4231               {
4232                  stv_vdp2_drawgfx_rgb555(bitmap,cliprect,tilecode,flipyx&1,flipyx&2,drawxpos,drawypos,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha);
4233               }
4234               else
4235               {
4236                  if (stv2_current_tilemap.transparency == STV_TRANSPARENCY_ALPHA)
4237                     drawgfx_alpha(bitmap,cliprect,machine().gfx[gfx],tilecode,pal,flipyx&1,flipyx&2, drawxpos, drawypos,0,stv2_current_tilemap.alpha);
4238                  else
4239                     drawgfx_transpen(bitmap,cliprect,machine().gfx[gfx],tilecode,pal,flipyx&1,flipyx&2, drawxpos, drawypos,(stv2_current_tilemap.transparency==STV_TRANSPARENCY_PEN)?0:-1);
4240               }
4241            }
4242            drawxpos = olddrawxpos;
4243            drawypos = olddrawypos;
4244         }
4245/* DRAWN?! */
4246
4247      }
4248   }
4249   if ( stv2_current_tilemap.layer_name & 0x80 )
4250   {
4251      static const int shifttable[4] = {0,1,2,2};
4252      int uppermask, uppermaskshift;
4253      int mapsize;
4254      uppermaskshift = (1-stv2_current_tilemap.pattern_data_size) | ((1-stv2_current_tilemap.tile_size)<<1);
4255      uppermask = 0x1ff >> uppermaskshift;
4256
4257      if ( LOG_VDP2 )
4258      {
4259         logerror( "Layer RBG%d, size %d x %d\n", stv2_current_tilemap.layer_name & 0x7f, cliprect.max_x + 1, cliprect.max_y + 1 );
4260         logerror( "Tiles: min %08X, max %08X\n", tilecodemin, tilecodemax );
4261         logerror( "MAP size in dwords %08X\n", mpsize_dwords );
4262         for (i = 0; i < stv2_current_tilemap.map_count; i++)
4263         {
4264            logerror( "Map register %d: base %08X\n", stv2_current_tilemap.map_offset[i], base[i] );
4265         }
4266      }
4267
4268      // store map information
4269      stv_vdp2_layer_data_placement.map_offset_min = 0x7fffffff;
4270      stv_vdp2_layer_data_placement.map_offset_max = 0x00000000;
4271      for (i = 0; i < stv2_current_tilemap.map_count; i++)
4272      {
4273         if ( base[i] < stv_vdp2_layer_data_placement.map_offset_min )
4274            stv_vdp2_layer_data_placement.map_offset_min = base[i];
4275         if ( base[i] > stv_vdp2_layer_data_placement.map_offset_max )
4276            stv_vdp2_layer_data_placement.map_offset_max = base[i];
4277      }
4278
4279
4280      mapsize = ((1 & uppermask) >> shifttable[stv2_current_tilemap.plane_size]) * plsize_bytes -
4281               ((0 & uppermask) >> shifttable[stv2_current_tilemap.plane_size]) * plsize_bytes;
4282      mapsize /= 4;
4283
4284      stv_vdp2_layer_data_placement.map_offset_max += mapsize;
4285
4286      stv_vdp2_layer_data_placement.tile_offset_min = tilecodemin * 0x20 / 4;
4287      stv_vdp2_layer_data_placement.tile_offset_max = (tilecodemax + 1) * 0x20 / 4;
4288   }
4289
4290}
4291
4292#define STV_VDP2_READ_VERTICAL_LINESCROLL( _val, _address ) \
4293   { \
4294      _val = m_vdp2_vram[ _address ]; \
4295      _val &= 0x07ffff00; \
4296      if ( _val & 0x04000000 ) _val |= 0xf8000000; \
4297   }
4298
4299
4300void saturn_state::stv_vdp2_check_tilemap_with_linescroll(bitmap_rgb32 &bitmap, const rectangle &cliprect)
4301{
4302   rectangle mycliprect;
4303   int cur_line = cliprect.min_y;
4304   int address;
4305   int active_functions = 0;
4306   INT32 scroll_values[3], prev_scroll_values[3];
4307   int i;
4308   int scroll_values_equal;
4309   int lines;
4310   INT16 main_scrollx, main_scrolly;
4311//  INT32 incx;
4312   int linescroll_enable, vertical_linescroll_enable, linezoom_enable;
4313   int vertical_linescroll_index = -1;
4314
4315   // read original scroll values
4316   main_scrollx = stv2_current_tilemap.scrollx;
4317   main_scrolly = stv2_current_tilemap.scrolly;
4318//  incx = stv2_current_tilemap.incx;
4319
4320   // prepare linescroll flags
4321   linescroll_enable = stv2_current_tilemap.linescroll_enable;
4322//  stv2_current_tilemap.linescroll_enable = 0;
4323   vertical_linescroll_enable = stv2_current_tilemap.vertical_linescroll_enable;
4324//  stv2_current_tilemap.vertical_linescroll_enable = 0;
4325   linezoom_enable = stv2_current_tilemap.linezoom_enable;
4326//  stv2_current_tilemap.linezoom_enable = 0;
4327
4328   // prepare working clipping rectangle
4329   memcpy( &mycliprect, &cliprect, sizeof(rectangle) );
4330
4331   // calculate the number of active functions
4332   if ( linescroll_enable ) active_functions++;
4333   if ( vertical_linescroll_enable )
4334   {
4335      vertical_linescroll_index = active_functions;
4336      active_functions++;
4337   }
4338   if ( linezoom_enable ) active_functions++;
4339
4340   // address of data table
4341   address = stv2_current_tilemap.linescroll_table_address + active_functions*4*cliprect.min_y;
4342
4343   // get the first scroll values
4344   for ( i = 0; i < active_functions; i++ )
4345   {
4346      if ( i == vertical_linescroll_index )
4347      {
4348         STV_VDP2_READ_VERTICAL_LINESCROLL( prev_scroll_values[i], (address / 4) + i );
4349         prev_scroll_values[i] -= (cur_line * stv2_current_tilemap.incy);
4350      }
4351      else
4352      {
4353         prev_scroll_values[i] = m_vdp2_vram[ (address / 4) + i ];
4354      }
4355   }
4356
4357   while( cur_line <= cliprect.max_y )
4358   {
4359      lines = 0;
4360      do
4361      {
4362         // update address
4363         address += active_functions*4;
4364
4365         // update lines count
4366         lines += stv2_current_tilemap.linescroll_interval;
4367
4368         // get scroll values
4369         for ( i = 0; i < active_functions; i++ )
4370         {
4371            if ( i == vertical_linescroll_index )
4372            {
4373               STV_VDP2_READ_VERTICAL_LINESCROLL( scroll_values[i], (address/4) + i );
4374               scroll_values[i] -= (cur_line + lines) * stv2_current_tilemap.incy;
4375            }
4376            else
4377            {
4378               scroll_values[i] = m_vdp2_vram[ (address / 4) + i ];
4379            }
4380         }
4381
4382         // compare scroll values
4383         scroll_values_equal = 1;
4384         for ( i = 0; i < active_functions; i++ )
4385         {
4386            scroll_values_equal &= (scroll_values[i] == prev_scroll_values[i]);
4387         }
4388      } while( scroll_values_equal && ((cur_line + lines) <= cliprect.max_y) );
4389
4390      // determined how many lines can be drawn
4391      // prepare clipping rectangle
4392      mycliprect.min_y = cur_line;
4393      mycliprect.max_y = cur_line + lines - 1;
4394
4395      // prepare scroll values
4396      i = 0;
4397      // linescroll
4398      if ( linescroll_enable )
4399      {
4400         prev_scroll_values[i] &= 0x07ffff00;
4401         if ( prev_scroll_values[i] & 0x04000000 ) prev_scroll_values[i] |= 0xf8000000;
4402         stv2_current_tilemap.scrollx = main_scrollx + (prev_scroll_values[i] >> 16);
4403         i++;
4404      }
4405      // vertical line scroll
4406      if ( vertical_linescroll_enable )
4407      {
4408         stv2_current_tilemap.scrolly = main_scrolly + (prev_scroll_values[i] >> 16);
4409         i++;
4410      }
4411
4412      // linezooom
4413      if ( linezoom_enable )
4414      {
4415         prev_scroll_values[i] &= 0x0007ff00;
4416         if ( prev_scroll_values[i] & 0x00040000 ) prev_scroll_values[i] |= 0xfff80000;
4417         stv2_current_tilemap.incx = prev_scroll_values[i];
4418         i++;
4419      }
4420
4421//      if ( LOG_VDP2 ) logerror( "Linescroll: y < %d, %d >, scrollx = %d, scrolly = %d, incx = %f\n", mycliprect.min_y, mycliprect.max_y, stv2_current_tilemap.scrollx, stv2_current_tilemap.scrolly, (float)stv2_current_tilemap.incx/65536.0 );
4422      // render current tilemap portion
4423      if (stv2_current_tilemap.bitmap_enable) // this layer is a bitmap
4424      {
4425         stv_vdp2_draw_basic_bitmap(bitmap, mycliprect);
4426      }
4427      else
4428      {
4429         stv_vdp2_apply_window_on_layer(mycliprect);
4430         stv_vdp2_draw_basic_tilemap(bitmap, mycliprect);
4431      }
4432
4433      // update parameters for next iteration
4434      memcpy( prev_scroll_values, scroll_values, sizeof(scroll_values));
4435      cur_line += lines;
4436   }
4437}
4438
4439void saturn_state::stv_vdp2_draw_line(bitmap_rgb32 &bitmap, const rectangle &cliprect)
4440{
4441   int x,y;
4442   UINT8* gfxdata = m_vdp2.gfx_decode;
4443   UINT32 base_offs,base_mask;
4444   UINT32 pix;
4445   UINT8 interlace;
4446
4447   interlace = (STV_VDP2_LSMD == 3)+1;
4448
4449   {
4450      base_mask = STV_VDP2_VRAMSZ ? 0x7ffff : 0x3ffff;
4451
4452      for(y=cliprect.min_y;y<=cliprect.max_y;y++)
4453      {
4454         base_offs = (STV_VDP2_LCTA & base_mask) << 1;
4455
4456         if(STV_VDP2_LCCLMD)
4457            base_offs += (y / interlace) << 1;
4458
4459         for(x=cliprect.min_x;x<=cliprect.max_x;x++)
4460         {
4461            UINT16 pen;
4462
4463            pen = (gfxdata[base_offs+0]<<8)|gfxdata[base_offs+1];
4464            pix = bitmap.pix32(y, x);
4465
4466            bitmap.pix32(y, x) = stv_add_blend(machine().pens[pen & 0x7ff],pix);
4467         }
4468      }
4469   }
4470}
4471
4472void saturn_state::stv_vdp2_draw_mosaic(bitmap_rgb32 &bitmap, const rectangle &cliprect, UINT8 is_roz)
4473{
4474   int x,y,xi,yi;
4475   UINT8 h_size,v_size;
4476   UINT32 pix;
4477
4478   h_size = STV_VDP2_MZSZH+1;
4479   v_size = STV_VDP2_MZSZV+1;
4480
4481   if(is_roz)
4482      v_size = 1;
4483
4484   if(h_size == 1 && v_size == 1)
4485      return; // don't bother
4486
4487   if(STV_VDP2_LSMD == 3)
4488      v_size <<= 1;
4489
4490   for(y=cliprect.min_y;y<=cliprect.max_y;y+=v_size)
4491   {
4492      for(x=cliprect.min_x;x<=cliprect.max_x;x+=h_size)
4493      {
4494         pix = bitmap.pix32(y, x);
4495
4496         for(yi=0;yi<v_size;yi++)
4497            for(xi=0;xi<h_size;xi++)
4498               bitmap.pix32(y+yi, x+xi) = pix;
4499      }
4500   }
4501}
4502
4503void saturn_state::stv_vdp2_check_tilemap(bitmap_rgb32 &bitmap, const rectangle &cliprect)
4504{
4505   /* the idea is here we check the tilemap capabilities / whats enabled and call an appropriate tilemap drawing routine, or
4506     at the very list throw up a few errors if the tilemaps want to do something we don't support yet */
4507//  int window_applied = 0;
4508   rectangle mycliprect = cliprect;
4509
4510   if ( stv2_current_tilemap.linescroll_enable ||
4511         stv2_current_tilemap.vertical_linescroll_enable ||
4512         stv2_current_tilemap.linezoom_enable )
4513   {
4514      stv_vdp2_check_tilemap_with_linescroll(bitmap, cliprect);
4515      return;
4516   }
4517
4518
4519   if (stv2_current_tilemap.bitmap_enable) // this layer is a bitmap
4520   {
4521      /*elandore doesn't like current cliprect code,will be worked on...*/
4522      //if ( window_applied && stv2_current_tilemap.colour_depth != 4)
4523      //  stv2_current_tilemap.window_control = 0;
4524
4525      stv_vdp2_draw_basic_bitmap(bitmap, mycliprect);
4526   }
4527   else
4528   {
4529      stv_vdp2_apply_window_on_layer(mycliprect);
4530      stv_vdp2_draw_basic_tilemap(bitmap, mycliprect);
4531   }
4532
4533   /* post-processing functions (TODO: needs layer bitmaps to be individual planes to work correctly) */
4534   if(stv2_current_tilemap.line_screen_enabled && TEST_FUNCTIONS)
4535      stv_vdp2_draw_line(bitmap,cliprect);
4536
4537   if(stv2_current_tilemap.mosaic_screen_enabled && TEST_FUNCTIONS)
4538      stv_vdp2_draw_mosaic(bitmap,cliprect,stv2_current_tilemap.layer_name & 0x80);
4539
4540
4541   {
4542      if(stv2_current_tilemap.colour_depth == 2 && !stv2_current_tilemap.bitmap_enable)
4543         popmessage("2048 color mode used on a non-bitmap plane");
4544
4545//      if(STV_VDP2_SCXDN0 || STV_VDP2_SCXDN1 || STV_VDP2_SCYDN0 || STV_VDP2_SCYDN1)
4546//          popmessage("Fractional part scrolling write, contact MAMEdev");
4547
4548      /* Pukunpa */
4549      //if(STV_VDP2_SPWINEN)
4550      //  popmessage("Sprite Window enabled");
4551
4552      /* Capcom Collection Dai 2 - Choh Makaimura (Duh!) */
4553      if(STV_VDP2_MZCTL & 0x1f && 0)
4554         popmessage("Mosaic control enabled = %04x\n",STV_VDP2_MZCTL);
4555
4556      /* Bio Hazard bit 1 */
4557      /* Airs Adventure 0x3e */
4558      /* Bakuretsu Hunter */
4559      if(STV_VDP2_LNCLEN & ~2 && 0)
4560         popmessage("Line Colour screen enabled %04x %08x, contact MAMEdev",STV_VDP2_LNCLEN,STV_VDP2_LCTAU<<16|STV_VDP2_LCTAL);
4561
4562      /* Bio Hazard 0x400 = extended color calculation enabled */
4563      /* Advanced World War 0x200 = color calculation ratio mode */
4564      //if(STV_VDP2_CCCR & 0xf600)
4565      if(STV_VDP2_CCCR & 0xf000)
4566         popmessage("Gradation enabled %04x, contact MAMEdev",STV_VDP2_CCCR);
4567
4568      /* Advanced VG, Shining Force III */
4569      if(STV_VDP2_SFCCMD && 0)
4570         popmessage("Special Color Calculation enable %04x, contact MAMEdev",STV_VDP2_SFCCMD);
4571
4572      /* Cleopatra Fortune Transparent Shadow */
4573      /* Pretty Fighter X Back & Transparent Shadow*/
4574      //if(STV_VDP2_SDCTL & 0x0120)
4575      //  popmessage("%s shadow select bit enabled, contact MAMEdev",STV_VDP2_SDCTL & 0x100 ? "Transparent" : "Back");
4576
4577      /* Langrisser III bit 3 normal, bit 1 during battle field */
4578      /* Metal Slug bit 0 during gameplay */
4579      if(STV_VDP2_SFSEL & ~0xb)
4580         popmessage("Special Function Code Select enable %04x %04x, contact MAMEdev",STV_VDP2_SFSEL,STV_VDP2_SFCODE);
4581
4582      /* Albert Odyssey Gaiden 0x0001 */
4583      /* Asuka 120% (doesn't make sense?) 0x0101 */
4584      /* Slam n Jam 96 0x0003 */
4585      if(STV_VDP2_ZMCTL & 0x0200)
4586         popmessage("Reduction enable %04x, contact MAMEdev",STV_VDP2_ZMCTL);
4587
4588      /* Burning Rangers and friends FMV, J.League Pro Soccer Club Wo Tsukurou!! backgrounds */
4589      if(STV_VDP2_SCRCTL & 0x0101 && 0)
4590         popmessage("Vertical cell scroll enable %04x, contact MAMEdev",STV_VDP2_SCRCTL);
4591
4592      /* Magical Drop III 0x200 -> color calculation window */
4593      /* Ide Yousuke Meijin No Shin Jissen Mahjong 0x0303 */
4594      /* Decathlete 0x088 */
4595      if(STV_VDP2_WCTLD & 0x2000)
4596         popmessage("Special window enabled %04x, contact MAMEdev",STV_VDP2_WCTLD);
4597
4598      /* Shining Force III, After Burner 2 (doesn't make a proper use tho?) */
4599      /* Layer Section */
4600      //if(STV_VDP2_W0LWE || STV_VDP2_W1LWE)
4601      //  popmessage("Line Window %s %08x enabled, contact MAMEdev",STV_VDP2_W0LWE ? "0" : "1",STV_VDP2_W0LWTA);
4602
4603      /* Akumajou Dracula, bits 2-4 */
4604      /* Arcana Strikes bit 5 */
4605      /* Choh Makai Mura 0x0055 */
4606      /* Sega Rally 0x0155 */
4607      /* Find Love  0x4400 */
4608      /* Dragon Ball Z 0x3800 - 0x2c00 */
4609      /* Assault Suit Leynos 2 0x0200*/
4610      if(STV_VDP2_SFPRMD & ~0x7f75)
4611         popmessage("Special Priority Mode enabled %04x, contact MAMEdev",STV_VDP2_SFPRMD);
4612   }
4613}
4614
4615
4616void saturn_state::stv_vdp2_copy_roz_bitmap(bitmap_rgb32 &bitmap,
4617                              bitmap_rgb32 &roz_bitmap,
4618                              const rectangle &cliprect,
4619                              int iRP,
4620                              int planesizex,
4621                              int planesizey,
4622                              int planerenderedsizex,
4623                              int planerenderedsizey)
4624{
4625   INT32 xsp, ysp, xp, yp, dx, dy, x, y, xs, ys, dxs, dys;
4626   INT32 vcnt, hcnt;
4627   INT32 kx, ky;
4628   INT8  use_coeff_table, coeff_table_mode, coeff_table_size, coeff_table_shift;
4629   INT8  screen_over_process;
4630   UINT8 vcnt_shift, hcnt_shift;
4631   UINT8 coeff_msb;
4632   UINT32 *coeff_table_base, coeff_table_offset;
4633   INT32 coeff_table_val;
4634   UINT32 address;
4635   UINT32 *line;
4636   UINT32 pix;
4637   //UINT32 coeff_line_color_screen_data;
4638   INT32 clipxmask = 0, clipymask = 0;
4639
4640
4641   vcnt_shift = ((STV_VDP2_LSMD & 3) == 3);
4642   hcnt_shift = ((STV_VDP2_HRES & 2) == 2);
4643
4644   planesizex--;
4645   planesizey--;
4646   planerenderedsizex--;
4647   planerenderedsizey--;
4648
4649   kx = RP.kx;
4650   ky = RP.ky;
4651
4652   use_coeff_table = coeff_table_mode = coeff_table_size = coeff_table_shift = 0;
4653   coeff_table_offset = 0;
4654   coeff_table_val = 0;
4655   coeff_table_base = NULL;
4656
4657   if ( LOG_ROZ == 1 ) logerror( "Rendering RBG with parameter %s\n", iRP == 1 ? "A" : "B" );
4658   if ( LOG_ROZ == 1 ) logerror( "RPMD (parameter mode) = %x\n", STV_VDP2_RPMD );
4659   if ( LOG_ROZ == 1 ) logerror( "RPRCTL (parameter read control) = %04x\n", STV_VDP2_RPRCTL );
4660   if ( LOG_ROZ == 1 ) logerror( "KTCTL (coefficient table control) = %04x\n", STV_VDP2_KTCTL );
4661   if ( LOG_ROZ == 1 ) logerror( "KTAOF (coefficient table address offset) = %04x\n", STV_VDP2_KTAOF );
4662   if ( LOG_ROZ == 1 ) logerror( "RAOVR (screen-over process) = %x\n", STV_VDP2_RAOVR );
4663   if ( iRP == 1 )
4664   {
4665      use_coeff_table = STV_VDP2_RAKTE;
4666      if ( use_coeff_table == 1 )
4667      {
4668         coeff_table_mode = STV_VDP2_RAKMD;
4669         coeff_table_size = STV_VDP2_RAKDBS;
4670         coeff_table_offset = STV_VDP2_RAKTAOS;
4671      }
4672      screen_over_process = STV_VDP2_RAOVR;
4673   }
4674   else
4675   {
4676      use_coeff_table = STV_VDP2_RBKTE;
4677      if ( use_coeff_table == 1 )
4678      {
4679         coeff_table_mode = STV_VDP2_RBKMD;
4680         coeff_table_size = STV_VDP2_RBKDBS;
4681         coeff_table_offset = STV_VDP2_RBKTAOS;
4682      }
4683      screen_over_process = STV_VDP2_RBOVR;
4684   }
4685   if ( use_coeff_table )
4686   {
4687      if ( STV_VDP2_CRKTE == 0 )
4688      {
4689         coeff_table_base = m_vdp2_vram;
4690      }
4691      else
4692      {
4693         coeff_table_base = m_vdp2_cram;
4694      }
4695      if ( coeff_table_size == 0 )
4696      {
4697         coeff_table_offset = (coeff_table_offset & 0x0003) * 0x40000;
4698         coeff_table_shift = 2;
4699      }
4700      else
4701      {
4702         coeff_table_offset = (coeff_table_offset & 0x0007) * 0x20000;
4703         coeff_table_shift = 1;
4704      }
4705   }
4706
4707   if ( stv2_current_tilemap.colour_calculation_enabled == 1 )
4708   {
4709      if ( STV_VDP2_CCMD )
4710      {
4711         stv2_current_tilemap.transparency = STV_TRANSPARENCY_ADD_BLEND;
4712      }
4713      else
4714      {
4715         stv2_current_tilemap.transparency = STV_TRANSPARENCY_ALPHA;
4716      }
4717   }
4718
4719   /* clipping */
4720   switch( screen_over_process )
4721   {
4722      case 0:
4723         /* repeated */
4724         clipxmask = clipymask = 0;
4725         break;
4726      case 1:
4727         /* screen over pattern, not supported */
4728         clipxmask = clipymask = 0;
4729         break;
4730      case 2:
4731         /* outside display area, scroll screen is transparent */
4732         clipxmask = ~planesizex;
4733         clipymask = ~planesizey;
4734         break;
4735      case 3:
4736         /* display area is 512x512, outside is transparent */
4737         clipxmask = ~511;
4738         clipymask = ~511;
4739         break;
4740   }
4741
4742   //dx  = (RP.A * RP.dx) + (RP.B * RP.dy);
4743   //dy  = (RP.D * RP.dx) + (RP.E * RP.dy);
4744   dx = mul_fixed32( RP.A, RP.dx ) + mul_fixed32( RP.B, RP.dy );
4745   dy = mul_fixed32( RP.D, RP.dx ) + mul_fixed32( RP.E, RP.dy );
4746
4747   //xp  = RP.A * ( RP.px - RP.cx ) + RP.B * ( RP.py - RP.cy ) + RP.C * ( RP.pz - RP.cz ) + RP.cx + RP.mx;
4748   //yp  = RP.D * ( RP.px - RP.cx ) + RP.E * ( RP.py - RP.cy ) + RP.F * ( RP.pz - RP.cz ) + RP.cy + RP.my;
4749   xp = mul_fixed32( RP.A, RP.px - RP.cx ) + mul_fixed32( RP.B, RP.py - RP.cy ) + mul_fixed32( RP.C, RP.pz - RP.cz ) + RP.cx + RP.mx;
4750   yp = mul_fixed32( RP.D, RP.px - RP.cx ) + mul_fixed32( RP.E, RP.py - RP.cy ) + mul_fixed32( RP.F, RP.pz - RP.cz ) + RP.cy + RP.my;
4751
4752   for (vcnt = cliprect.min_y; vcnt <= cliprect.max_y; vcnt++ )
4753   {
4754      /*xsp = RP.A * ( ( RP.xst + RP.dxst * (vcnt << 16) ) - RP.px ) +
4755            RP.B * ( ( RP.yst + RP.dyst * (vcnt << 16) ) - RP.py ) +
4756            RP.C * ( RP.zst - RP.pz);
4757      ysp = RP.D * ( ( RP.xst + RP.dxst * (vcnt << 16) ) - RP.px ) +
4758            RP.E * ( ( RP.yst + RP.dyst * (vcnt << 16) ) - RP.py ) +
4759            RP.F * ( RP.zst - RP.pz );*/
4760      xsp = mul_fixed32( RP.A, RP.xst + mul_fixed32( RP.dxst, vcnt << (16 - vcnt_shift)) - RP.px ) +
4761            mul_fixed32( RP.B, RP.yst + mul_fixed32( RP.dyst, vcnt << (16 - vcnt_shift)) - RP.py ) +
4762            mul_fixed32( RP.C, RP.zst - RP.pz );
4763      ysp = mul_fixed32( RP.D, RP.xst + mul_fixed32( RP.dxst, vcnt << (16 - vcnt_shift)) - RP.px ) +
4764            mul_fixed32( RP.E, RP.yst + mul_fixed32( RP.dyst, vcnt << (16 - vcnt_shift)) - RP.py ) +
4765            mul_fixed32( RP.F, RP.zst - RP.pz );
4766      //xp  = RP.A * ( RP.px - RP.cx ) + RP.B * ( RP.py - RP.cy ) + RP.C * ( RP.pz - RP.cz ) + RP.cx + RP.mx;
4767      //yp  = RP.D * ( RP.px - RP.cx ) + RP.E * ( RP.py - RP.cy ) + RP.F * ( RP.pz - RP.cz ) + RP.cy + RP.my;
4768      //dx  = (RP.A * RP.dx) + (RP.B * RP.dy);
4769      //dy  = (RP.D * RP.dx) + (RP.E * RP.dy);
4770
4771      line = &bitmap.pix32(vcnt);
4772
4773      if ( !use_coeff_table || RP.dkax == 0 )
4774      {
4775         if ( use_coeff_table )
4776         {
4777            switch( coeff_table_size )
4778            {
4779               case 0:
4780                  address = coeff_table_offset + ((RP.kast + RP.dkast*(vcnt>>vcnt_shift)) >> 16) * 4;
4781                  coeff_table_val = coeff_table_base[ address / 4 ];
4782                  //coeff_line_color_screen_data = (coeff_table_val & 0x7f000000) >> 24;
4783                  coeff_msb = (coeff_table_val & 0x80000000) > 0;
4784                  if ( coeff_table_val & 0x00800000 )
4785                  {
4786                     coeff_table_val |= 0xff000000;
4787                  }
4788                  else
4789                  {
4790                     coeff_table_val &= 0x007fffff;
4791                  }
4792                  break;
4793               case 1:
4794                  address = coeff_table_offset + ((RP.kast + RP.dkast*(vcnt>>vcnt_shift)) >> 16) * 2;
4795                  coeff_table_val = coeff_table_base[ address / 4 ];
4796                  if ( (address & 2) == 0 )
4797                  {
4798                     coeff_table_val >>= 16;
4799                  }
4800                  coeff_table_val &= 0xffff;
4801                  //coeff_line_color_screen_data = 0;
4802                  coeff_msb = (coeff_table_val & 0x8000) > 0;
4803                  if ( coeff_table_val & 0x4000 )
4804                  {
4805                     coeff_table_val |= 0xffff8000;
4806                  }
4807                  else
4808                  {
4809                     coeff_table_val &= 0x3fff;
4810                  }
4811                  coeff_table_val <<= 6; /* to form 16.16 fixed point val */
4812                  break;
4813               default:
4814                  coeff_msb = 1;
4815                  break;
4816            }
4817            if ( coeff_msb ) continue;
4818
4819            switch( coeff_table_mode )
4820            {
4821               case 0:
4822                  kx = ky = coeff_table_val;
4823                  break;
4824               case 1:
4825                  kx = coeff_table_val;
4826                  break;
4827               case 2:
4828                  ky = coeff_table_val;
4829                  break;
4830               case 3:
4831                  xp = coeff_table_val;
4832                  break;
4833            }
4834         }
4835
4836         //x = RP.kx * ( xsp + dx * (hcnt << 16)) + xp;
4837         //y = RP.ky * ( ysp + dy * (hcnt << 16)) + yp;
4838         xs = mul_fixed32( kx, xsp ) + xp;
4839         ys = mul_fixed32( ky, ysp ) + yp;
4840         dxs = mul_fixed32( kx, mul_fixed32( dx, 1 << (16-hcnt_shift)));
4841         dys = mul_fixed32( ky, mul_fixed32( dy, 1 << (16-hcnt_shift)));
4842
4843         for (hcnt = cliprect.min_x; hcnt <= cliprect.max_x; xs+=dxs, ys+=dys, hcnt++ )
4844         {
4845            x = xs >> 16;
4846            y = ys >> 16;
4847
4848            if ( x & clipxmask || y & clipymask ) continue;
4849            pix = roz_bitmap.pix32(y & planerenderedsizey, x & planerenderedsizex);
4850            switch( stv2_current_tilemap.transparency )
4851            {
4852               case STV_TRANSPARENCY_PEN:
4853                  if (pix & 0xffffff)
4854                  {
4855                     if(stv2_current_tilemap.fade_control & 1)
4856                        stv_vdp2_compute_color_offset_UINT32(&pix,stv2_current_tilemap.fade_control & 2);
4857
4858                     line[hcnt] = pix;
4859                  }
4860                  break;
4861               case STV_TRANSPARENCY_NONE:
4862                  if(stv2_current_tilemap.fade_control & 1)
4863                     stv_vdp2_compute_color_offset_UINT32(&pix,stv2_current_tilemap.fade_control & 2);
4864
4865                  line[hcnt] = pix;
4866                  break;
4867               case STV_TRANSPARENCY_ALPHA:
4868                  if (pix & 0xffffff)
4869                  {
4870                     if(stv2_current_tilemap.fade_control & 1)
4871                        stv_vdp2_compute_color_offset_UINT32(&pix,stv2_current_tilemap.fade_control & 2);
4872
4873                     line[hcnt] = alpha_blend_r32( line[hcnt], pix, stv2_current_tilemap.alpha );
4874                  }
4875                  break;
4876               case STV_TRANSPARENCY_ADD_BLEND:
4877                  if (pix & 0xffffff)
4878                  {
4879                     if(stv2_current_tilemap.fade_control & 1)
4880                        stv_vdp2_compute_color_offset_UINT32(&pix,stv2_current_tilemap.fade_control & 2);
4881
4882                     line[hcnt] = stv_add_blend( line[hcnt], pix );
4883                  }
4884                  break;
4885            }
4886
4887         }
4888      }
4889      else
4890      {
4891         for (hcnt = cliprect.min_x; hcnt <= cliprect.max_x; hcnt++ )
4892         {
4893            switch( coeff_table_size )
4894            {
4895               case 0:
4896                  address = coeff_table_offset + ((RP.kast + RP.dkast*(vcnt>>vcnt_shift) + RP.dkax*hcnt) >> 16) * 4;
4897                  coeff_table_val = coeff_table_base[ address / 4 ];
4898                  //coeff_line_color_screen_data = (coeff_table_val & 0x7f000000) >> 24;
4899                  coeff_msb = (coeff_table_val & 0x80000000) > 0;
4900                  if ( coeff_table_val & 0x00800000 )
4901                  {
4902                     coeff_table_val |= 0xff000000;
4903                  }
4904                  else
4905                  {
4906                     coeff_table_val &= 0x007fffff;
4907                  }
4908                  break;
4909               case 1:
4910                  address = coeff_table_offset + ((RP.kast + RP.dkast*(vcnt>>vcnt_shift) + RP.dkax*hcnt) >> 16) * 2;
4911                  coeff_table_val = coeff_table_base[ address / 4 ];
4912                  if ( (address & 2) == 0 )
4913                  {
4914                     coeff_table_val >>= 16;
4915                  }
4916                  coeff_table_val &= 0xffff;
4917                  //coeff_line_color_screen_data = 0;
4918                  coeff_msb = (coeff_table_val & 0x8000) > 0;
4919                  if ( coeff_table_val & 0x4000 )
4920                  {
4921                     coeff_table_val |= 0xffff8000;
4922                  }
4923                  else
4924                  {
4925                     coeff_table_val &= 0x3fff;
4926                  }
4927                  coeff_table_val <<= 6; /* to form 16.16 fixed point val */
4928                  break;
4929               default:
4930                  coeff_msb = 1;
4931                  break;
4932            }
4933            if ( coeff_msb ) continue;
4934            switch( coeff_table_mode )
4935            {
4936               case 0:
4937                  kx = ky = coeff_table_val;
4938                  break;
4939               case 1:
4940                  kx = coeff_table_val;
4941                  break;
4942               case 2:
4943                  ky = coeff_table_val;
4944                  break;
4945               case 3:
4946                  xp = coeff_table_val;
4947                  break;
4948            }
4949
4950            //x = RP.kx * ( xsp + dx * (hcnt << 16)) + xp;
4951            //y = RP.ky * ( ysp + dy * (hcnt << 16)) + yp;
4952            x = mul_fixed32( kx, xsp + mul_fixed32( dx, (hcnt>>hcnt_shift) << 16 ) ) + xp;
4953            y = mul_fixed32( ky, ysp + mul_fixed32( dy, (hcnt>>hcnt_shift) << 16 ) ) + yp;
4954
4955            x >>= 16;
4956            y >>= 16;
4957
4958            if ( x & clipxmask || y & clipymask ) continue;
4959
4960            pix = roz_bitmap.pix32(y & planerenderedsizey, x & planerenderedsizex);
4961            switch( stv2_current_tilemap.transparency )
4962            {
4963               case STV_TRANSPARENCY_PEN:
4964                  if (pix & 0xffffff)
4965                  {
4966                     if(stv2_current_tilemap.fade_control & 1)
4967                        stv_vdp2_compute_color_offset_UINT32(&pix,stv2_current_tilemap.fade_control & 2);
4968
4969                     line[hcnt] = pix;
4970                  }
4971                  break;
4972               case STV_TRANSPARENCY_NONE:
4973                  if(stv2_current_tilemap.fade_control & 1)
4974                     stv_vdp2_compute_color_offset_UINT32(&pix,stv2_current_tilemap.fade_control & 2);
4975
4976                  line[hcnt] = pix;
4977                  break;
4978               case STV_TRANSPARENCY_ALPHA:
4979                  if (pix & 0xffffff)
4980                  {
4981                     if(stv2_current_tilemap.fade_control & 1)
4982                        stv_vdp2_compute_color_offset_UINT32(&pix,stv2_current_tilemap.fade_control & 2);
4983
4984                     line[hcnt] = alpha_blend_r32( line[hcnt], pix, stv2_current_tilemap.alpha );
4985                  }
4986                  break;
4987               case STV_TRANSPARENCY_ADD_BLEND:
4988                  if (pix & 0xffffff)
4989                  {
4990                     if(stv2_current_tilemap.fade_control & 1)
4991                        stv_vdp2_compute_color_offset_UINT32(&pix,stv2_current_tilemap.fade_control & 2);
4992
4993                     line[hcnt] = stv_add_blend( line[hcnt], pix );
4994                  }
4995                  break;
4996            }
4997         }
4998      }
4999   }
5000}
5001
5002void saturn_state::stv_vdp2_draw_NBG0(bitmap_rgb32 &bitmap, const rectangle &cliprect)
5003{
5004   UINT32 base_mask;
5005
5006   base_mask = STV_VDP2_VRAMSZ ? 0x7ffff : 0x3ffff;
5007
5008   /*
5009      Colours           : 16, 256, 2048, 32768, 16770000
5010      Char Size         : 1x1 cells, 2x2 cells
5011      Pattern Data Size : 1 word, 2 words
5012      Plane Layouts     : 1 x 1, 2 x 1, 2 x 2
5013      Planes            : 4
5014      Bitmap            : Possible
5015      Bitmap Sizes      : 512 x 256, 512 x 512, 1024 x 256, 1024 x 512
5016      Scale             : 0.25 x - 256 x
5017      Rotation          : No
5018      Linescroll        : Yes
5019      Column Scroll     : Yes
5020      Mosaic            : Yes
5021   */
5022
5023   stv2_current_tilemap.enabled = STV_VDP2_N0ON | STV_VDP2_R1ON;
5024
5025//  if (!stv2_current_tilemap.enabled) return; // stop right now if its disabled ...
5026
5027   //stv2_current_tilemap.trans_enabled = STV_VDP2_N0TPON;
5028   if ( STV_VDP2_N0CCEN )
5029   {
5030      stv2_current_tilemap.colour_calculation_enabled = 1;
5031      stv2_current_tilemap.alpha = ((UINT16)(0x1f-STV_VDP2_N0CCRT)*0xff)/0x1f;
5032   }
5033   else
5034   {
5035      stv2_current_tilemap.colour_calculation_enabled = 0;
5036   }
5037   if ( STV_VDP2_N0TPON == 0 )
5038   {
5039      stv2_current_tilemap.transparency = STV_TRANSPARENCY_PEN;
5040   }
5041   else
5042   {
5043      stv2_current_tilemap.transparency = STV_TRANSPARENCY_NONE;
5044   }
5045   stv2_current_tilemap.colour_depth = STV_VDP2_N0CHCN;
5046   stv2_current_tilemap.tile_size = STV_VDP2_N0CHSZ;
5047   stv2_current_tilemap.bitmap_enable = STV_VDP2_N0BMEN;
5048   stv2_current_tilemap.bitmap_size = STV_VDP2_N0BMSZ;
5049   stv2_current_tilemap.bitmap_palette_number = STV_VDP2_N0BMP;
5050   stv2_current_tilemap.bitmap_map = STV_VDP2_N0MP_;
5051   stv2_current_tilemap.map_offset[0] = STV_VDP2_N0MPA | (STV_VDP2_N0MP_ << 6);
5052   stv2_current_tilemap.map_offset[1] = STV_VDP2_N0MPB | (STV_VDP2_N0MP_ << 6);
5053   stv2_current_tilemap.map_offset[2] = STV_VDP2_N0MPC | (STV_VDP2_N0MP_ << 6);
5054   stv2_current_tilemap.map_offset[3] = STV_VDP2_N0MPD | (STV_VDP2_N0MP_ << 6);
5055   stv2_current_tilemap.map_count = 4;
5056
5057   stv2_current_tilemap.pattern_data_size = STV_VDP2_N0PNB;
5058   stv2_current_tilemap.character_number_supplement = STV_VDP2_N0CNSM;
5059   stv2_current_tilemap.special_priority_register = STV_VDP2_N0SPR;
5060   stv2_current_tilemap.special_colour_control_register = STV_VDP2_PNCN0;
5061   stv2_current_tilemap.supplementary_palette_bits = STV_VDP2_N0SPLT;
5062   stv2_current_tilemap.supplementary_character_bits = STV_VDP2_N0SPCN;
5063
5064   stv2_current_tilemap.scrollx = STV_VDP2_SCXIN0;
5065   stv2_current_tilemap.scrolly = STV_VDP2_SCYIN0;
5066   stv2_current_tilemap.incx = STV_VDP2_ZMXN0;
5067   stv2_current_tilemap.incy = STV_VDP2_ZMYN0;
5068
5069   stv2_current_tilemap.linescroll_enable = STV_VDP2_N0LSCX;
5070   stv2_current_tilemap.linescroll_interval = (((STV_VDP2_LSMD & 3) == 2) ? (2) : (1)) << (STV_VDP2_N0LSS);
5071   stv2_current_tilemap.linescroll_table_address = (((STV_VDP2_LSTA0U << 16) | STV_VDP2_LSTA0L) & base_mask) * 2;
5072   stv2_current_tilemap.vertical_linescroll_enable = STV_VDP2_N0LSCY;
5073   stv2_current_tilemap.linezoom_enable = STV_VDP2_N0LZMX;
5074
5075   stv2_current_tilemap.plane_size = (STV_VDP2_R1ON) ? STV_VDP2_RBPLSZ : STV_VDP2_N0PLSZ;
5076   stv2_current_tilemap.colour_ram_address_offset = STV_VDP2_N0CAOS;
5077   stv2_current_tilemap.fade_control = (STV_VDP2_N0COEN * 1) | (STV_VDP2_N0COSL * 2);
5078   stv_vdp2_check_fade_control_for_layer();
5079   stv2_current_tilemap.window_control = (STV_VDP2_N0LOG << 0) |
5080                                 (STV_VDP2_N0W0E << 1) |
5081                                 (STV_VDP2_N0W1E << 2) |
5082                                 (STV_VDP2_N0SWE << 3) |
5083                                 (STV_VDP2_N0W0A << 4) |
5084                                 (STV_VDP2_N0W1A << 5) |
5085                                 (STV_VDP2_N0SWA << 6);
5086
5087   stv2_current_tilemap.line_screen_enabled = STV_VDP2_N0LCEN;
5088   stv2_current_tilemap.mosaic_screen_enabled = STV_VDP2_N0MZE;
5089
5090   stv2_current_tilemap.layer_name=(STV_VDP2_R1ON) ? 0x81 : 0;
5091
5092   if ( stv2_current_tilemap.enabled && (!(STV_VDP2_R1ON))) /* TODO: check cycle pattern for RBG1 */
5093   {
5094      stv2_current_tilemap.enabled = stv_vdp2_check_vram_cycle_pattern_registers( STV_VDP2_CP_NBG0_PNMDR, STV_VDP2_CP_NBG0_CPDR, stv2_current_tilemap.bitmap_enable );
5095   }
5096
5097   if(STV_VDP2_R1ON)
5098      stv_vdp2_draw_rotation_screen(bitmap, cliprect, 2 );
5099   else
5100      stv_vdp2_check_tilemap(bitmap, cliprect);
5101}
5102
5103void saturn_state::stv_vdp2_draw_NBG1(bitmap_rgb32 &bitmap, const rectangle &cliprect)
5104{
5105   UINT32 base_mask;
5106
5107   base_mask = STV_VDP2_VRAMSZ ? 0x7ffff : 0x3ffff;
5108
5109   /*
5110      Colours           : 16, 256, 2048, 32768
5111      Char Size         : 1x1 cells, 2x2 cells
5112      Pattern Data Size : 1 word, 2 words
5113      Plane Layouts     : 1 x 1, 2 x 1, 2 x 2
5114      Planes            : 4
5115      Bitmap            : Possible
5116      Bitmap Sizes      : 512 x 256, 512 x 512, 1024 x 256, 1024 x 512
5117      Scale             : 0.25 x - 256 x
5118      Rotation          : No
5119      Linescroll        : Yes
5120      Column Scroll     : Yes
5121      Mosaic            : Yes
5122   */
5123   stv2_current_tilemap.enabled = STV_VDP2_N1ON;
5124
5125//  if (!stv2_current_tilemap.enabled) return; // stop right now if its disabled ...
5126
5127   //stv2_current_tilemap.trans_enabled = STV_VDP2_N1TPON;
5128   if ( STV_VDP2_N1CCEN )
5129   {
5130      stv2_current_tilemap.colour_calculation_enabled = 1;
5131      stv2_current_tilemap.alpha = ((UINT16)(0x1f-STV_VDP2_N1CCRT)*0xff)/0x1f;
5132   }
5133   else
5134   {
5135      stv2_current_tilemap.colour_calculation_enabled = 0;
5136   }
5137   if ( STV_VDP2_N1TPON == 0 )
5138   {
5139      stv2_current_tilemap.transparency = STV_TRANSPARENCY_PEN;
5140   }
5141   else
5142   {
5143      stv2_current_tilemap.transparency = STV_TRANSPARENCY_NONE;
5144   }
5145   stv2_current_tilemap.colour_depth = STV_VDP2_N1CHCN;
5146   stv2_current_tilemap.tile_size = STV_VDP2_N1CHSZ;
5147   stv2_current_tilemap.bitmap_enable = STV_VDP2_N1BMEN;
5148   stv2_current_tilemap.bitmap_size = STV_VDP2_N1BMSZ;
5149   stv2_current_tilemap.bitmap_palette_number = STV_VDP2_N1BMP;
5150   stv2_current_tilemap.bitmap_map = STV_VDP2_N1MP_;
5151   stv2_current_tilemap.map_offset[0] = STV_VDP2_N1MPA | (STV_VDP2_N1MP_ << 6);
5152   stv2_current_tilemap.map_offset[1] = STV_VDP2_N1MPB | (STV_VDP2_N1MP_ << 6);
5153   stv2_current_tilemap.map_offset[2] = STV_VDP2_N1MPC | (STV_VDP2_N1MP_ << 6);
5154   stv2_current_tilemap.map_offset[3] = STV_VDP2_N1MPD | (STV_VDP2_N1MP_ << 6);
5155   stv2_current_tilemap.map_count = 4;
5156
5157   stv2_current_tilemap.pattern_data_size = STV_VDP2_N1PNB;
5158   stv2_current_tilemap.character_number_supplement = STV_VDP2_N1CNSM;
5159   stv2_current_tilemap.special_priority_register = STV_VDP2_N1SPR;
5160   stv2_current_tilemap.special_colour_control_register = STV_VDP2_PNCN1;
5161   stv2_current_tilemap.supplementary_palette_bits = STV_VDP2_N1SPLT;
5162   stv2_current_tilemap.supplementary_character_bits = STV_VDP2_N1SPCN;
5163
5164   stv2_current_tilemap.scrollx = STV_VDP2_SCXIN1;
5165   stv2_current_tilemap.scrolly = STV_VDP2_SCYIN1;
5166   stv2_current_tilemap.incx = STV_VDP2_ZMXN1;
5167   stv2_current_tilemap.incy = STV_VDP2_ZMYN1;
5168
5169   stv2_current_tilemap.linescroll_enable = STV_VDP2_N1LSCX;
5170   stv2_current_tilemap.linescroll_interval = (((STV_VDP2_LSMD & 3) == 2) ? (2) : (1)) << (STV_VDP2_N1LSS);
5171   stv2_current_tilemap.linescroll_table_address = (((STV_VDP2_LSTA1U << 16) | STV_VDP2_LSTA1L) & base_mask) * 2;
5172   stv2_current_tilemap.vertical_linescroll_enable = STV_VDP2_N1LSCY;
5173   stv2_current_tilemap.linezoom_enable = STV_VDP2_N1LZMX;
5174
5175   stv2_current_tilemap.plane_size = STV_VDP2_N1PLSZ;
5176   stv2_current_tilemap.colour_ram_address_offset = STV_VDP2_N1CAOS;
5177   stv2_current_tilemap.fade_control = (STV_VDP2_N1COEN * 1) | (STV_VDP2_N1COSL * 2);
5178   stv_vdp2_check_fade_control_for_layer();
5179   stv2_current_tilemap.window_control = (STV_VDP2_N1LOG << 0) |
5180                                 (STV_VDP2_N1W0E << 1) |
5181                                 (STV_VDP2_N1W1E << 2) |
5182                                 (STV_VDP2_N1SWE << 3) |
5183                                 (STV_VDP2_N1W0A << 4) |
5184                                 (STV_VDP2_N1W1A << 5) |
5185                                 (STV_VDP2_N1SWA << 6);
5186
5187   stv2_current_tilemap.line_screen_enabled = STV_VDP2_N1LCEN;
5188   stv2_current_tilemap.mosaic_screen_enabled = STV_VDP2_N1MZE;
5189
5190   stv2_current_tilemap.layer_name=1;
5191
5192   if ( stv2_current_tilemap.enabled )
5193   {
5194      stv2_current_tilemap.enabled = stv_vdp2_check_vram_cycle_pattern_registers( STV_VDP2_CP_NBG1_PNMDR, STV_VDP2_CP_NBG1_CPDR, stv2_current_tilemap.bitmap_enable );
5195   }
5196
5197   stv_vdp2_check_tilemap(bitmap, cliprect);
5198}
5199
5200void saturn_state::stv_vdp2_draw_NBG2(bitmap_rgb32 &bitmap, const rectangle &cliprect)
5201{
5202   /*
5203      NBG2 is the first of the 2 more basic tilemaps, it has exactly the same capabilities as NBG3
5204
5205      Colours           : 16, 256
5206      Char Size         : 1x1 cells, 2x2 cells
5207      Pattern Data Size : 1 word, 2 words
5208      Plane Layouts     : 1 x 1, 2 x 1, 2 x 2
5209      Planes            : 4
5210      Bitmap            : No
5211      Bitmap Sizes      : N/A
5212      Scale             : No
5213      Rotation          : No
5214      Linescroll        : No
5215      Column Scroll     : No
5216      Mosaic            : Yes
5217   */
5218
5219   stv2_current_tilemap.enabled = STV_VDP2_N2ON;
5220
5221   /* these modes for N0 disable this layer */
5222   if (STV_VDP2_N0CHCN == 0x03) stv2_current_tilemap.enabled = 0;
5223   if (STV_VDP2_N0CHCN == 0x04) stv2_current_tilemap.enabled = 0;
5224
5225//  if (!stv2_current_tilemap.enabled) return; // stop right now if its disabled ...
5226
5227   //stv2_current_tilemap.trans_enabled = STV_VDP2_N2TPON;
5228   if ( STV_VDP2_N2CCEN )
5229   {
5230      stv2_current_tilemap.colour_calculation_enabled = 1;
5231      stv2_current_tilemap.alpha = ((UINT16)(0x1f-STV_VDP2_N2CCRT)*0xff)/0x1f;
5232   }
5233   else
5234   {
5235      stv2_current_tilemap.colour_calculation_enabled = 0;
5236   }
5237   if ( STV_VDP2_N2TPON == 0 )
5238   {
5239      stv2_current_tilemap.transparency = STV_TRANSPARENCY_PEN;
5240   }
5241   else
5242   {
5243      stv2_current_tilemap.transparency = STV_TRANSPARENCY_NONE;
5244   }
5245   stv2_current_tilemap.colour_depth = STV_VDP2_N2CHCN;
5246   stv2_current_tilemap.tile_size = STV_VDP2_N2CHSZ;
5247   /* this layer can't be a bitmap,so ignore these registers*/
5248   stv2_current_tilemap.bitmap_enable = 0;
5249   stv2_current_tilemap.bitmap_size = 0;
5250   stv2_current_tilemap.bitmap_palette_number = 0;
5251   stv2_current_tilemap.bitmap_map = 0;
5252   stv2_current_tilemap.map_offset[0] = STV_VDP2_N2MPA | (STV_VDP2_N2MP_ << 6);
5253   stv2_current_tilemap.map_offset[1] = STV_VDP2_N2MPB | (STV_VDP2_N2MP_ << 6);
5254   stv2_current_tilemap.map_offset[2] = STV_VDP2_N2MPC | (STV_VDP2_N2MP_ << 6);
5255   stv2_current_tilemap.map_offset[3] = STV_VDP2_N2MPD | (STV_VDP2_N2MP_ << 6);
5256   stv2_current_tilemap.map_count = 4;
5257
5258   stv2_current_tilemap.pattern_data_size = STV_VDP2_N2PNB;
5259   stv2_current_tilemap.character_number_supplement = STV_VDP2_N2CNSM;
5260   stv2_current_tilemap.special_priority_register = STV_VDP2_N2SPR;
5261   stv2_current_tilemap.special_colour_control_register = STV_VDP2_PNCN2;
5262   stv2_current_tilemap.supplementary_palette_bits = STV_VDP2_N2SPLT;
5263   stv2_current_tilemap.supplementary_character_bits = STV_VDP2_N2SPCN;
5264
5265   stv2_current_tilemap.scrollx = STV_VDP2_SCXN2;
5266   stv2_current_tilemap.scrolly = STV_VDP2_SCYN2;
5267   /*This layer can't be scaled*/
5268   stv2_current_tilemap.incx = 0x10000;
5269   stv2_current_tilemap.incy = 0x10000;
5270
5271   stv2_current_tilemap.linescroll_enable = 0;
5272   stv2_current_tilemap.linescroll_interval = 0;
5273   stv2_current_tilemap.linescroll_table_address = 0;
5274   stv2_current_tilemap.vertical_linescroll_enable = 0;
5275   stv2_current_tilemap.linezoom_enable = 0;
5276
5277   stv2_current_tilemap.colour_ram_address_offset = STV_VDP2_N2CAOS;
5278   stv2_current_tilemap.fade_control = (STV_VDP2_N2COEN * 1) | (STV_VDP2_N2COSL * 2);
5279   stv_vdp2_check_fade_control_for_layer();
5280   stv2_current_tilemap.window_control = (STV_VDP2_N2LOG << 0) |
5281                                 (STV_VDP2_N2W0E << 1) |
5282                                 (STV_VDP2_N2W1E << 2) |
5283                                 (STV_VDP2_N2SWE << 3) |
5284                                 (STV_VDP2_N2W0A << 4) |
5285                                 (STV_VDP2_N2W1A << 5) |
5286                                 (STV_VDP2_N2SWA << 6);
5287
5288   stv2_current_tilemap.line_screen_enabled = STV_VDP2_N2LCEN;
5289   stv2_current_tilemap.mosaic_screen_enabled = STV_VDP2_N2MZE;
5290
5291   stv2_current_tilemap.layer_name=2;
5292
5293   stv2_current_tilemap.plane_size = STV_VDP2_N2PLSZ;
5294
5295   if ( stv2_current_tilemap.enabled )
5296   {
5297      stv2_current_tilemap.enabled = stv_vdp2_check_vram_cycle_pattern_registers( STV_VDP2_CP_NBG2_PNMDR, STV_VDP2_CP_NBG2_CPDR, stv2_current_tilemap.bitmap_enable );
5298   }
5299
5300   stv_vdp2_check_tilemap(bitmap, cliprect);
5301}
5302
5303void saturn_state::stv_vdp2_draw_NBG3(bitmap_rgb32 &bitmap, const rectangle &cliprect)
5304{
5305   /*
5306      NBG3 is the second of the 2 more basic tilemaps, it has exactly the same capabilities as NBG2
5307
5308      Colours           : 16, 256
5309      Char Size         : 1x1 cells, 2x2 cells
5310      Pattern Data Size : 1 word, 2 words
5311      Plane Layouts     : 1 x 1, 2 x 1, 2 x 2
5312      Planes            : 4
5313      Bitmap            : No
5314      Bitmap Sizes      : N/A
5315      Scale             : No
5316      Rotation          : No
5317      Linescroll        : No
5318      Column Scroll     : No
5319      Mosaic            : Yes
5320   */
5321
5322   stv2_current_tilemap.enabled = STV_VDP2_N3ON;
5323
5324//  if (!stv2_current_tilemap.enabled) return; // stop right now if its disabled ...
5325
5326   /* these modes for N1 disable this layer */
5327   if (STV_VDP2_N1CHCN == 0x03) stv2_current_tilemap.enabled = 0;
5328   if (STV_VDP2_N1CHCN == 0x04) stv2_current_tilemap.enabled = 0;
5329
5330   //stv2_current_tilemap.trans_enabled = STV_VDP2_N3TPON;
5331   if ( STV_VDP2_N3CCEN )
5332   {
5333      stv2_current_tilemap.colour_calculation_enabled = 1;
5334      stv2_current_tilemap.alpha = ((UINT16)(0x1f-STV_VDP2_N3CCRT)*0xff)/0x1f;
5335   }
5336   else
5337   {
5338      stv2_current_tilemap.colour_calculation_enabled = 0;
5339   }
5340   if ( STV_VDP2_N3TPON == 0 )
5341   {
5342      stv2_current_tilemap.transparency = STV_TRANSPARENCY_PEN;
5343   }
5344   else
5345   {
5346      stv2_current_tilemap.transparency = STV_TRANSPARENCY_NONE;
5347   }
5348   stv2_current_tilemap.colour_depth = STV_VDP2_N3CHCN;
5349   stv2_current_tilemap.tile_size = STV_VDP2_N3CHSZ;
5350   /* this layer can't be a bitmap,so ignore these registers*/
5351   stv2_current_tilemap.bitmap_enable = 0;
5352   stv2_current_tilemap.bitmap_size = 0;
5353   stv2_current_tilemap.bitmap_palette_number = 0;
5354   stv2_current_tilemap.bitmap_map = 0;
5355   stv2_current_tilemap.map_offset[0] = STV_VDP2_N3MPA | (STV_VDP2_N3MP_ << 6);
5356   stv2_current_tilemap.map_offset[1] = STV_VDP2_N3MPB | (STV_VDP2_N3MP_ << 6);
5357   stv2_current_tilemap.map_offset[2] = STV_VDP2_N3MPC | (STV_VDP2_N3MP_ << 6);
5358   stv2_current_tilemap.map_offset[3] = STV_VDP2_N3MPD | (STV_VDP2_N3MP_ << 6);
5359   stv2_current_tilemap.map_count = 4;
5360
5361   stv2_current_tilemap.pattern_data_size = STV_VDP2_N3PNB;
5362   stv2_current_tilemap.character_number_supplement = STV_VDP2_N3CNSM;
5363   stv2_current_tilemap.special_priority_register = STV_VDP2_N3SPR;
5364   stv2_current_tilemap.special_colour_control_register = STV_VDP2_N3SCC;
5365   stv2_current_tilemap.supplementary_palette_bits = STV_VDP2_N3SPLT;
5366   stv2_current_tilemap.supplementary_character_bits = STV_VDP2_N3SPCN;
5367
5368   stv2_current_tilemap.scrollx = STV_VDP2_SCXN3;
5369   stv2_current_tilemap.scrolly = STV_VDP2_SCYN3;
5370   /*This layer can't be scaled*/
5371   stv2_current_tilemap.incx = 0x10000;
5372   stv2_current_tilemap.incy = 0x10000;
5373
5374   stv2_current_tilemap.linescroll_enable = 0;
5375   stv2_current_tilemap.linescroll_interval = 0;
5376   stv2_current_tilemap.linescroll_table_address = 0;
5377   stv2_current_tilemap.vertical_linescroll_enable = 0;
5378   stv2_current_tilemap.linezoom_enable = 0;
5379
5380   stv2_current_tilemap.colour_ram_address_offset = STV_VDP2_N3CAOS;
5381   stv2_current_tilemap.fade_control = (STV_VDP2_N3COEN * 1) | (STV_VDP2_N3COSL * 2);
5382   stv_vdp2_check_fade_control_for_layer();
5383   stv2_current_tilemap.window_control = (STV_VDP2_N3LOG << 0) |
5384                                 (STV_VDP2_N3W0E << 1) |
5385                                 (STV_VDP2_N3W1E << 2) |
5386                                 (STV_VDP2_N3SWE << 3) |
5387                                 (STV_VDP2_N3W0A << 4) |
5388                                 (STV_VDP2_N3W1A << 5) |
5389                                 (STV_VDP2_N3SWA << 6);
5390
5391   stv2_current_tilemap.line_screen_enabled = STV_VDP2_N3LCEN;
5392   stv2_current_tilemap.mosaic_screen_enabled = STV_VDP2_N3MZE;
5393
5394   stv2_current_tilemap.layer_name=3;
5395
5396   stv2_current_tilemap.plane_size = STV_VDP2_N3PLSZ;
5397
5398   if ( stv2_current_tilemap.enabled )
5399   {
5400      stv2_current_tilemap.enabled = stv_vdp2_check_vram_cycle_pattern_registers( STV_VDP2_CP_NBG3_PNMDR, STV_VDP2_CP_NBG3_CPDR, stv2_current_tilemap.bitmap_enable );
5401   }
5402
5403   stv_vdp2_check_tilemap(bitmap, cliprect);
5404}
5405
5406
5407void saturn_state::stv_vdp2_draw_rotation_screen(bitmap_rgb32 &bitmap, const rectangle &cliprect, int iRP)
5408{
5409   rectangle roz_clip_rect, mycliprect;
5410   int planesizex = 0, planesizey = 0;
5411   int planerenderedsizex, planerenderedsizey;
5412   UINT8 colour_calculation_enabled;
5413   UINT8 window_control;
5414   UINT8 fade_control;
5415
5416   if ( iRP == 1)
5417   {
5418      stv2_current_tilemap.bitmap_map = STV_VDP2_RAMP_;
5419      stv2_current_tilemap.map_offset[0] = STV_VDP2_RAMPA | (STV_VDP2_RAMP_ << 6);
5420      stv2_current_tilemap.map_offset[1] = STV_VDP2_RAMPB | (STV_VDP2_RAMP_ << 6);
5421      stv2_current_tilemap.map_offset[2] = STV_VDP2_RAMPC | (STV_VDP2_RAMP_ << 6);
5422      stv2_current_tilemap.map_offset[3] = STV_VDP2_RAMPD | (STV_VDP2_RAMP_ << 6);
5423      stv2_current_tilemap.map_offset[4] = STV_VDP2_RAMPE | (STV_VDP2_RAMP_ << 6);
5424      stv2_current_tilemap.map_offset[5] = STV_VDP2_RAMPF | (STV_VDP2_RAMP_ << 6);
5425      stv2_current_tilemap.map_offset[6] = STV_VDP2_RAMPG | (STV_VDP2_RAMP_ << 6);
5426      stv2_current_tilemap.map_offset[7] = STV_VDP2_RAMPH | (STV_VDP2_RAMP_ << 6);
5427      stv2_current_tilemap.map_offset[8] = STV_VDP2_RAMPI | (STV_VDP2_RAMP_ << 6);
5428      stv2_current_tilemap.map_offset[9] = STV_VDP2_RAMPJ | (STV_VDP2_RAMP_ << 6);
5429      stv2_current_tilemap.map_offset[10] = STV_VDP2_RAMPK | (STV_VDP2_RAMP_ << 6);
5430      stv2_current_tilemap.map_offset[11] = STV_VDP2_RAMPL | (STV_VDP2_RAMP_ << 6);
5431      stv2_current_tilemap.map_offset[12] = STV_VDP2_RAMPM | (STV_VDP2_RAMP_ << 6);
5432      stv2_current_tilemap.map_offset[13] = STV_VDP2_RAMPN | (STV_VDP2_RAMP_ << 6);
5433      stv2_current_tilemap.map_offset[14] = STV_VDP2_RAMPO | (STV_VDP2_RAMP_ << 6);
5434      stv2_current_tilemap.map_offset[15] = STV_VDP2_RAMPP | (STV_VDP2_RAMP_ << 6);
5435      stv2_current_tilemap.map_count = 16;
5436   }
5437   else
5438   {
5439      stv2_current_tilemap.bitmap_map = STV_VDP2_RBMP_;
5440      stv2_current_tilemap.map_offset[0] = STV_VDP2_RBMPA | (STV_VDP2_RBMP_ << 6);
5441      stv2_current_tilemap.map_offset[1] = STV_VDP2_RBMPB | (STV_VDP2_RBMP_ << 6);
5442      stv2_current_tilemap.map_offset[2] = STV_VDP2_RBMPC | (STV_VDP2_RBMP_ << 6);
5443      stv2_current_tilemap.map_offset[3] = STV_VDP2_RBMPD | (STV_VDP2_RBMP_ << 6);
5444      stv2_current_tilemap.map_offset[4] = STV_VDP2_RBMPE | (STV_VDP2_RBMP_ << 6);
5445      stv2_current_tilemap.map_offset[5] = STV_VDP2_RBMPF | (STV_VDP2_RBMP_ << 6);
5446      stv2_current_tilemap.map_offset[6] = STV_VDP2_RBMPG | (STV_VDP2_RBMP_ << 6);
5447      stv2_current_tilemap.map_offset[7] = STV_VDP2_RBMPH | (STV_VDP2_RBMP_ << 6);
5448      stv2_current_tilemap.map_offset[8] = STV_VDP2_RBMPI | (STV_VDP2_RBMP_ << 6);
5449      stv2_current_tilemap.map_offset[9] = STV_VDP2_RBMPJ | (STV_VDP2_RBMP_ << 6);
5450      stv2_current_tilemap.map_offset[10] = STV_VDP2_RBMPK | (STV_VDP2_RBMP_ << 6);
5451      stv2_current_tilemap.map_offset[11] = STV_VDP2_RBMPL | (STV_VDP2_RBMP_ << 6);
5452      stv2_current_tilemap.map_offset[12] = STV_VDP2_RBMPM | (STV_VDP2_RBMP_ << 6);
5453      stv2_current_tilemap.map_offset[13] = STV_VDP2_RBMPN | (STV_VDP2_RBMP_ << 6);
5454      stv2_current_tilemap.map_offset[14] = STV_VDP2_RBMPO | (STV_VDP2_RBMP_ << 6);
5455      stv2_current_tilemap.map_offset[15] = STV_VDP2_RBMPP | (STV_VDP2_RBMP_ << 6);
5456      stv2_current_tilemap.map_count = 16;
5457   }
5458
5459   stv_vdp2_fill_rotation_parameter_table(iRP);
5460
5461   if ( iRP == 1 )
5462   {
5463      stv2_current_tilemap.plane_size = STV_VDP2_RAPLSZ;
5464   }
5465   else
5466   {
5467      stv2_current_tilemap.plane_size = STV_VDP2_RBPLSZ;
5468   }
5469
5470   if (stv2_current_tilemap.bitmap_enable)
5471   {
5472      switch (stv2_current_tilemap.bitmap_size)
5473      {
5474         case 0: planesizex=512; planesizey=256; break;
5475         case 1: planesizex=512; planesizey=512; break;
5476         case 2: planesizex=1024; planesizey=256; break;
5477         case 3: planesizex=1024; planesizey=512; break;
5478      }
5479   }
5480   else
5481   {
5482      switch( stv2_current_tilemap.plane_size )
5483      {
5484      case 0:
5485         planesizex = planesizey = 2048;
5486         break;
5487      case 1:
5488         planesizex = 4096;
5489         planesizey = 2048;
5490         break;
5491      case 2:
5492         planesizex = 0;
5493         planesizey = 0;
5494         break;
5495      case 3:
5496         planesizex = planesizey = 4096;
5497         break;
5498      }
5499   }
5500
5501   if ( stv_vdp2_is_rotation_applied() == 0 )
5502   {
5503      stv2_current_tilemap.scrollx = stv_current_rotation_parameter_table.mx >> 16;
5504      stv2_current_tilemap.scrolly = stv_current_rotation_parameter_table.my >> 16;
5505
5506      stv_vdp2_check_tilemap(bitmap,cliprect);
5507   }
5508   else
5509   {
5510      if ( !m_vdp2.roz_bitmap[iRP-1].valid() )
5511         m_vdp2.roz_bitmap[iRP-1].allocate(4096, 4096);
5512
5513      roz_clip_rect.min_x = roz_clip_rect.min_y = 0;
5514      if ( (iRP == 1 && STV_VDP2_RAOVR == 3) ||
5515            (iRP == 2 && STV_VDP2_RBOVR == 3) )
5516      {
5517         roz_clip_rect.max_x = roz_clip_rect.max_y = 511;
5518         planerenderedsizex = planerenderedsizey = 512;
5519      }
5520      else if (stv_vdp2_are_map_registers_equal() &&
5521               !stv2_current_tilemap.bitmap_enable)
5522      {
5523         roz_clip_rect.max_x = (planesizex / 4) - 1;
5524         roz_clip_rect.max_y = (planesizey / 4) - 1;
5525         planerenderedsizex = planesizex / 4;
5526         planerenderedsizey = planesizey / 4;
5527      }
5528      else
5529      {
5530         roz_clip_rect.max_x = planesizex - 1;
5531         roz_clip_rect.max_y = planesizey - 1;
5532         planerenderedsizex = planesizex;
5533         planerenderedsizey = planesizey;
5534      }
5535
5536
5537      colour_calculation_enabled = stv2_current_tilemap.colour_calculation_enabled;
5538      stv2_current_tilemap.colour_calculation_enabled = 0;
5539      window_control = stv2_current_tilemap.window_control;
5540      stv2_current_tilemap.window_control = 0;
5541      fade_control = stv2_current_tilemap.fade_control;
5542      stv2_current_tilemap.fade_control = 0;
5543      g_profiler.start(PROFILER_USER1);
5544      if ( LOG_VDP2 ) logerror( "Checking for cached RBG bitmap, cache_dirty = %d, memcmp() = %d\n", stv_rbg_cache_data.is_cache_dirty, memcmp(&stv_rbg_cache_data.layer_data[iRP-1],&stv2_current_tilemap,sizeof(stv2_current_tilemap)));
5545      if ( (stv_rbg_cache_data.is_cache_dirty & iRP) ||
5546         memcmp(&stv_rbg_cache_data.layer_data[iRP-1],&stv2_current_tilemap,sizeof(stv2_current_tilemap)) != 0 )
5547      {
5548         m_vdp2.roz_bitmap[iRP-1].fill(get_black_pen(machine()), roz_clip_rect );
5549         stv_vdp2_check_tilemap(m_vdp2.roz_bitmap[iRP-1], roz_clip_rect);
5550         // prepare cache data
5551         stv_rbg_cache_data.watch_vdp2_vram_writes |= iRP;
5552         stv_rbg_cache_data.is_cache_dirty &= ~iRP;
5553         memcpy(&stv_rbg_cache_data.layer_data[iRP-1], &stv2_current_tilemap, sizeof(stv2_current_tilemap));
5554         stv_rbg_cache_data.map_offset_min[iRP-1] = stv_vdp2_layer_data_placement.map_offset_min;
5555         stv_rbg_cache_data.map_offset_max[iRP-1] = stv_vdp2_layer_data_placement.map_offset_max;
5556         stv_rbg_cache_data.tile_offset_min[iRP-1] = stv_vdp2_layer_data_placement.tile_offset_min;
5557         stv_rbg_cache_data.tile_offset_max[iRP-1] = stv_vdp2_layer_data_placement.tile_offset_max;
5558         if ( LOG_VDP2 ) logerror( "Cache watch: map = %06X - %06X, tile = %06X - %06X\n", stv_rbg_cache_data.map_offset_min[iRP-1],
5559            stv_rbg_cache_data.map_offset_max[iRP-1], stv_rbg_cache_data.tile_offset_min[iRP-1], stv_rbg_cache_data.tile_offset_max[iRP-1] );
5560      }
5561
5562      g_profiler.stop();
5563
5564      stv2_current_tilemap.colour_calculation_enabled = colour_calculation_enabled;
5565      if ( colour_calculation_enabled )
5566      {
5567         stv2_current_tilemap.transparency = STV_TRANSPARENCY_ALPHA;
5568      }
5569
5570      mycliprect = cliprect;
5571
5572      if ( window_control )
5573      {
5574         stv2_current_tilemap.window_control = window_control;
5575         stv_vdp2_apply_window_on_layer(mycliprect);
5576      }
5577
5578      stv2_current_tilemap.fade_control = fade_control;
5579
5580      g_profiler.start(PROFILER_USER2);
5581      stv_vdp2_copy_roz_bitmap(bitmap, m_vdp2.roz_bitmap[iRP-1], mycliprect, iRP, planesizex, planesizey, planerenderedsizex, planerenderedsizey );
5582      g_profiler.stop();
5583   }
5584
5585}
5586
5587void saturn_state::stv_vdp2_draw_RBG0(bitmap_rgb32 &bitmap, const rectangle &cliprect)
5588{
5589   /*
5590      Colours           : 16, 256, 2048, 32768, 16770000
5591      Char Size         : 1x1 cells, 2x2 cells
5592      Pattern Data Size : 1 word, 2 words
5593      Plane Layouts     : 1 x 1, 2 x 1, 2 x 2
5594      Planes            : 4
5595      Bitmap            : Possible
5596      Bitmap Sizes      : 512 x 256, 512 x 512, 1024 x 256, 1024 x 512
5597      Scale             : 0.25 x - 256 x
5598      Rotation          : Yes
5599      Linescroll        : Yes
5600      Column Scroll     : Yes
5601      Mosaic            : Yes
5602   */
5603
5604   stv2_current_tilemap.enabled = STV_VDP2_R0ON;
5605
5606//  if (!stv2_current_tilemap.enabled) return; // stop right now if its disabled ...
5607
5608   //stv2_current_tilemap.trans_enabled = STV_VDP2_R0TPON;
5609   if ( STV_VDP2_R0CCEN )
5610   {
5611      stv2_current_tilemap.colour_calculation_enabled = 1;
5612      stv2_current_tilemap.alpha = ((UINT16)(0x1f-STV_VDP2_R0CCRT)*0xff)/0x1f;
5613   }
5614   else
5615   {
5616      stv2_current_tilemap.colour_calculation_enabled = 0;
5617   }
5618   if ( STV_VDP2_R0TPON == 0 )
5619   {
5620      stv2_current_tilemap.transparency = STV_TRANSPARENCY_PEN;
5621   }
5622   else
5623   {
5624      stv2_current_tilemap.transparency = STV_TRANSPARENCY_NONE;
5625   }
5626   stv2_current_tilemap.colour_depth = STV_VDP2_R0CHCN;
5627   stv2_current_tilemap.tile_size = STV_VDP2_R0CHSZ;
5628   stv2_current_tilemap.bitmap_enable = STV_VDP2_R0BMEN;
5629   stv2_current_tilemap.bitmap_size = STV_VDP2_R0BMSZ;
5630   stv2_current_tilemap.bitmap_palette_number = STV_VDP2_R0BMP;
5631
5632   stv2_current_tilemap.pattern_data_size = STV_VDP2_R0PNB;
5633   stv2_current_tilemap.character_number_supplement = STV_VDP2_R0CNSM;
5634   stv2_current_tilemap.special_priority_register = STV_VDP2_R0SPR;
5635   stv2_current_tilemap.special_colour_control_register = STV_VDP2_R0SCC;
5636   stv2_current_tilemap.supplementary_palette_bits = STV_VDP2_R0SPLT;
5637   stv2_current_tilemap.supplementary_character_bits = STV_VDP2_R0SPCN;
5638
5639   stv2_current_tilemap.colour_ram_address_offset = STV_VDP2_R0CAOS;
5640   stv2_current_tilemap.fade_control = (STV_VDP2_R0COEN * 1) | (STV_VDP2_R0COSL * 2);
5641   stv_vdp2_check_fade_control_for_layer();
5642   stv2_current_tilemap.window_control = (STV_VDP2_R0LOG << 0) |
5643                                 (STV_VDP2_R0W0E << 1) |
5644                                 (STV_VDP2_R0W1E << 2) |
5645                                 (STV_VDP2_R0SWE << 3) |
5646                                 (STV_VDP2_R0W0A << 4) |
5647                                 (STV_VDP2_R0W1A << 5) |
5648                                 (STV_VDP2_R0SWA << 6);
5649
5650   stv2_current_tilemap.scrollx = 0;
5651   stv2_current_tilemap.scrolly = 0;
5652   stv2_current_tilemap.incx = 0x10000;
5653   stv2_current_tilemap.incy = 0x10000;
5654
5655   stv2_current_tilemap.linescroll_enable = 0;
5656   stv2_current_tilemap.linescroll_interval = 0;
5657   stv2_current_tilemap.linescroll_table_address = 0;
5658   stv2_current_tilemap.vertical_linescroll_enable = 0;
5659   stv2_current_tilemap.linezoom_enable = 0;
5660
5661   stv2_current_tilemap.line_screen_enabled = STV_VDP2_R0LCEN;
5662   stv2_current_tilemap.mosaic_screen_enabled = STV_VDP2_R0MZE;
5663
5664   /*Use 0x80 as a normal/rotate switch*/
5665   stv2_current_tilemap.layer_name=0x80;
5666
5667   if ( !stv2_current_tilemap.enabled ) return;
5668
5669   switch(STV_VDP2_RPMD)
5670   {
5671      case 0://Rotation Parameter A
5672         stv_vdp2_draw_rotation_screen(bitmap, cliprect, 1 );
5673         break;
5674      case 1://Rotation Parameter B
5675      //case 2:
5676         stv_vdp2_draw_rotation_screen(bitmap, cliprect, 2 );
5677         break;
5678      case 2://Rotation Parameter A & B CKTE
5679         stv_vdp2_draw_rotation_screen(bitmap, cliprect, 2 );
5680         stv_vdp2_draw_rotation_screen(bitmap, cliprect, 1 );
5681         break;
5682      case 3://Rotation Parameter A & B Window (wrong)
5683         stv_vdp2_draw_rotation_screen(bitmap, cliprect, 1 );
5684         break;
5685   }
5686
5687}
5688
5689void saturn_state::stv_vdp2_draw_back(bitmap_rgb32 &bitmap, const rectangle &cliprect)
5690{
5691   int x,y;
5692   UINT8* gfxdata = m_vdp2.gfx_decode;
5693   UINT32 base_offs,base_mask;
5694   UINT8 interlace;
5695
5696   interlace = (STV_VDP2_LSMD == 3)+1;
5697
5698//  popmessage("Back screen %08x %08x %08x",STV_VDP2_BDCLMD,STV_VDP2_BKCLMD,STV_VDP2_BKTA);
5699
5700   /* draw black if BDCLMD and DISP are cleared */
5701   if(!(STV_VDP2_BDCLMD) && !(STV_VDP2_DISP))
5702      bitmap.fill(get_black_pen(machine()), cliprect);
5703   else
5704   {
5705      base_mask = STV_VDP2_VRAMSZ ? 0x7ffff : 0x3ffff;
5706
5707      for(y=cliprect.min_y;y<=cliprect.max_y;y++)
5708      {
5709         base_offs = ((STV_VDP2_BKTA ) & base_mask) << 1;
5710         if(STV_VDP2_BKCLMD)
5711            base_offs += ((y / interlace) << 1);
5712
5713         for(x=cliprect.min_x;x<=cliprect.max_x;x++)
5714         {
5715            int r,g,b;
5716            UINT16 dot;
5717
5718            dot = (gfxdata[base_offs+0]<<8)|gfxdata[base_offs+1];
5719            b = pal5bit((dot & 0x7c00) >> 10);
5720            g = pal5bit((dot & 0x03e0) >> 5);
5721            r = pal5bit( dot & 0x001f);
5722            if(STV_VDP2_BKCOEN)
5723               stv_vdp2_compute_color_offset( &r, &g, &b, STV_VDP2_BKCOSL );
5724
5725            bitmap.pix32(y, x) = MAKE_RGB(r, g, b);
5726         }
5727      }
5728   }
5729}
5730
5731READ32_MEMBER ( saturn_state::saturn_vdp2_vram_r )
5732{
5733   return m_vdp2_vram[offset];
5734}
5735
5736WRITE32_MEMBER ( saturn_state::saturn_vdp2_vram_w )
5737{
5738   UINT8* gfxdata = m_vdp2.gfx_decode;
5739
5740   COMBINE_DATA(&m_vdp2_vram[offset]);
5741
5742   data = m_vdp2_vram[offset];
5743   /* put in gfx region for easy decoding */
5744   gfxdata[offset*4+0] = (data & 0xff000000) >> 24;
5745   gfxdata[offset*4+1] = (data & 0x00ff0000) >> 16;
5746   gfxdata[offset*4+2] = (data & 0x0000ff00) >> 8;
5747   gfxdata[offset*4+3] = (data & 0x000000ff) >> 0;
5748
5749   space.machine().gfx[0]->mark_dirty(offset/8);
5750   space.machine().gfx[1]->mark_dirty(offset/8);
5751   space.machine().gfx[2]->mark_dirty(offset/8);
5752   space.machine().gfx[3]->mark_dirty(offset/8);
5753
5754   /* 8-bit tiles overlap, so this affects the previous one as well */
5755   if (offset/8 != 0)
5756   {
5757      space.machine().gfx[2]->mark_dirty(offset/8 - 1);
5758      space.machine().gfx[3]->mark_dirty(offset/8 - 1);
5759   }
5760
5761   if ( stv_rbg_cache_data.watch_vdp2_vram_writes )
5762   {
5763      if ( stv_rbg_cache_data.watch_vdp2_vram_writes & STV_VDP2_RBG_ROTATION_PARAMETER_A )
5764      {
5765         if ( (offset >= stv_rbg_cache_data.map_offset_min[0] &&
5766               offset < stv_rbg_cache_data.map_offset_max[0]) ||
5767               (offset >= stv_rbg_cache_data.tile_offset_min[0] &&
5768               offset < stv_rbg_cache_data.tile_offset_max[0]) )
5769         {
5770            if ( LOG_VDP2 ) logerror( "RBG Cache: dirtying for RP = 1, write at offset = %06X\n", offset );
5771            stv_rbg_cache_data.is_cache_dirty |= STV_VDP2_RBG_ROTATION_PARAMETER_A;
5772            stv_rbg_cache_data.watch_vdp2_vram_writes &= ~STV_VDP2_RBG_ROTATION_PARAMETER_A;
5773         }
5774      }
5775      if ( stv_rbg_cache_data.watch_vdp2_vram_writes & STV_VDP2_RBG_ROTATION_PARAMETER_B )
5776      {
5777         if ( (offset >= stv_rbg_cache_data.map_offset_min[1] &&
5778               offset < stv_rbg_cache_data.map_offset_max[1]) ||
5779               (offset >= stv_rbg_cache_data.tile_offset_min[1] &&
5780               offset < stv_rbg_cache_data.tile_offset_max[1]) )
5781         {
5782            if ( LOG_VDP2 ) logerror( "RBG Cache: dirtying for RP = 2, write at offset = %06X\n", offset );
5783            stv_rbg_cache_data.is_cache_dirty |= STV_VDP2_RBG_ROTATION_PARAMETER_B;
5784            stv_rbg_cache_data.watch_vdp2_vram_writes &= ~STV_VDP2_RBG_ROTATION_PARAMETER_B;
5785         }
5786      }
5787
5788   }
5789
5790}
5791
5792READ16_MEMBER ( saturn_state::saturn_vdp2_regs_r )
5793{
5794   switch(offset)
5795   {
5796      case 0x002/2:
5797      {
5798         /* latch h/v signals through HV latch*/
5799         if(!STV_VDP2_EXLTEN)
5800         {
5801            /* TODO: handle various h/v settings. */
5802            if(!space.debugger_access())
5803            {
5804               m_vdp2.h_count = space.machine().primary_screen->hpos() & 0x3ff;
5805               m_vdp2.v_count = space.machine().primary_screen->vpos() & (STV_VDP2_LSMD == 3 ? 0x7ff : 0x3ff);
5806               /* latch flag */
5807               m_vdp2.exltfg |= 1;
5808            }
5809         }
5810
5811         break;
5812      }
5813      case 0x004/2:
5814      {
5815         /*Screen Status Register*/
5816                              /*VBLANK              HBLANK            ODD               PAL    */
5817         m_vdp2_regs[offset] = (m_vdp2.exltfg<<9) |
5818                                 (m_vdp2.exsyfg<<8) |
5819                                 (get_vblank() << 3) |
5820                                 (get_hblank() << 2) |
5821                                 (get_odd_bit() << 1) |
5822                                 (m_vdp2.pal << 0);
5823
5824         /* vblank bit is always 1 if DISP bit is disabled */
5825         if(!STV_VDP2_DISP)
5826            m_vdp2_regs[offset] |= 1 << 3;
5827
5828         /* HV latches clears if this register is read */
5829         if(!space.debugger_access())
5830         {
5831            m_vdp2.exltfg &= ~1;
5832            m_vdp2.exsyfg &= ~1;
5833         }
5834         break;
5835      }
5836      case 0x006/2:
5837      {
5838         m_vdp2_regs[offset] = (STV_VDP2_VRAMSZ << 15) |
5839                                 ((0 << 0) & 0xf); // VDP2 version
5840
5841         if(!space.debugger_access())
5842            printf("Warning: VDP2 version read\n");
5843         break;
5844      }
5845
5846      /* HCNT */
5847      case 0x008/2:
5848      {
5849         m_vdp2_regs[offset] = (m_vdp2.h_count);
5850         break;
5851      }
5852
5853      /* VCNT */
5854      case 0x00a/2:
5855      {
5856         m_vdp2_regs[offset] = (m_vdp2.v_count);
5857         break;
5858      }
5859
5860      default:
5861         //if(!space.debugger_access())
5862         //  printf("VDP2: read from register %08x %08x\n",offset*4,mem_mask);
5863         break;
5864   }
5865
5866   return m_vdp2_regs[offset];
5867}
5868
5869READ32_MEMBER ( saturn_state::saturn_vdp2_cram_r )
5870{
5871   offset &= (0xfff) >> (2);
5872   return m_vdp2_cram[offset];
5873}
5874
5875
5876
5877
5878WRITE32_MEMBER ( saturn_state::saturn_vdp2_cram_w )
5879{
5880   int r,g,b;
5881   UINT8 cmode0;
5882
5883   cmode0 = (STV_VDP2_CRMD & 3) == 0;
5884
5885   offset &= (0xfff) >> (2);
5886   COMBINE_DATA(&m_vdp2_cram[offset]);
5887
5888   switch( STV_VDP2_CRMD )
5889   {
5890      /*Mode 2/3*/
5891      case 2:
5892      case 3:
5893      {
5894         //offset &= (0xfff) >> 2;
5895
5896         b = ((m_vdp2_cram[offset] & 0x00ff0000) >> 16);
5897         g = ((m_vdp2_cram[offset] & 0x0000ff00) >> 8);
5898         r = ((m_vdp2_cram[offset] & 0x000000ff) >> 0);
5899         palette_set_color(space.machine(),offset,MAKE_RGB(r,g,b));
5900         palette_set_color(space.machine(),offset^0x400,MAKE_RGB(r,g,b));
5901      }
5902      break;
5903      /*Mode 0*/
5904      case 0:
5905      case 1:
5906      {
5907         offset &= (0xfff) >> (cmode0+2);
5908
5909         b = ((m_vdp2_cram[offset] & 0x00007c00) >> 10);
5910         g = ((m_vdp2_cram[offset] & 0x000003e0) >> 5);
5911         r = ((m_vdp2_cram[offset] & 0x0000001f) >> 0);
5912         palette_set_color_rgb(space.machine(),(offset*2)+1,pal5bit(r),pal5bit(g),pal5bit(b));
5913         if(cmode0)
5914            palette_set_color_rgb(space.machine(),((offset*2)+1)^0x400,pal5bit(r),pal5bit(g),pal5bit(b));
5915
5916         b = ((m_vdp2_cram[offset] & 0x7c000000) >> 26);
5917         g = ((m_vdp2_cram[offset] & 0x03e00000) >> 21);
5918         r = ((m_vdp2_cram[offset] & 0x001f0000) >> 16);
5919         palette_set_color_rgb(space.machine(),offset*2,pal5bit(r),pal5bit(g),pal5bit(b));
5920         if(cmode0)
5921            palette_set_color_rgb(space.machine(),(offset*2)^0x400,pal5bit(r),pal5bit(g),pal5bit(b));
5922      }
5923      break;
5924   }
5925}
5926
5927void saturn_state::refresh_palette_data( void )
5928{
5929   int r,g,b;
5930   int c_i;
5931   UINT8 bank;
5932
5933   switch( STV_VDP2_CRMD )
5934   {
5935      case 2:
5936      case 3:
5937      {
5938         for(c_i=0;c_i<0x400;c_i++)
5939         {
5940            b = ((m_vdp2_cram[c_i] & 0x00ff0000) >> 16);
5941            g = ((m_vdp2_cram[c_i] & 0x0000ff00) >> 8);
5942            r = ((m_vdp2_cram[c_i] & 0x000000ff) >> 0);
5943            palette_set_color(machine(),c_i,MAKE_RGB(r,g,b));
5944            palette_set_color(machine(),c_i+0x400,MAKE_RGB(r,g,b));
5945         }
5946      }
5947      break;
5948      case 0:
5949      {
5950         for(bank=0;bank<2;bank++)
5951         {
5952            for(c_i=0;c_i<0x400;c_i++)
5953            {
5954               b = ((m_vdp2_cram[c_i] & 0x00007c00) >> 10);
5955               g = ((m_vdp2_cram[c_i] & 0x000003e0) >> 5);
5956               r = ((m_vdp2_cram[c_i] & 0x0000001f) >> 0);
5957               palette_set_color_rgb(machine(),(c_i*2)+1+bank*0x400,pal5bit(r),pal5bit(g),pal5bit(b));
5958               b = ((m_vdp2_cram[c_i] & 0x7c000000) >> 26);
5959               g = ((m_vdp2_cram[c_i] & 0x03e00000) >> 21);
5960               r = ((m_vdp2_cram[c_i] & 0x001f0000) >> 16);
5961               palette_set_color_rgb(machine(),c_i*2+bank*0x400,pal5bit(r),pal5bit(g),pal5bit(b));
5962            }
5963         }
5964      }
5965      break;
5966      case 1:
5967      {
5968         for(c_i=0;c_i<0x800;c_i++)
5969         {
5970            b = ((m_vdp2_cram[c_i] & 0x00007c00) >> 10);
5971            g = ((m_vdp2_cram[c_i] & 0x000003e0) >> 5);
5972            r = ((m_vdp2_cram[c_i] & 0x0000001f) >> 0);
5973            palette_set_color_rgb(machine(),(c_i*2)+1,pal5bit(r),pal5bit(g),pal5bit(b));
5974            b = ((m_vdp2_cram[c_i] & 0x7c000000) >> 26);
5975            g = ((m_vdp2_cram[c_i] & 0x03e00000) >> 21);
5976            r = ((m_vdp2_cram[c_i] & 0x001f0000) >> 16);
5977            palette_set_color_rgb(machine(),c_i*2,pal5bit(r),pal5bit(g),pal5bit(b));
5978         }
5979      }
5980      break;
5981   }
5982}
5983
5984WRITE16_MEMBER ( saturn_state::saturn_vdp2_regs_w )
5985{
5986   COMBINE_DATA(&m_vdp2_regs[offset]);
5987
5988   if(m_vdp2.old_crmd != STV_VDP2_CRMD)
5989   {
5990      m_vdp2.old_crmd = STV_VDP2_CRMD;
5991      refresh_palette_data();
5992   }
5993   if(m_vdp2.old_tvmd != STV_VDP2_TVMD)
5994   {
5995      m_vdp2.old_tvmd = STV_VDP2_TVMD;
5996      stv_vdp2_dynamic_res_change();
5997   }
5998
5999   if(STV_VDP2_VRAMSZ)
6000      printf("VDP2 sets up 8 Mbit VRAM!\n");
6001}
6002
6003int saturn_state::get_hblank_duration( void )
6004{
6005   int res;
6006
6007   res = (STV_VDP2_HRES & 1) ? 455 : 427;
6008
6009   /* double pump horizontal max res */
6010   if(STV_VDP2_HRES & 2)
6011      res<<=1;
6012
6013   return res;
6014}
6015
6016/*some vblank lines measurements (according to Charles MacDonald)*/
6017/* TODO: interlace mode "eats" one line, should be 262.5 */
6018int saturn_state::get_vblank_duration( void )
6019{
6020   int res;
6021
6022   res = (m_vdp2.pal) ? 313 : 263;
6023
6024   /* compensate for interlacing */
6025   if((STV_VDP2_LSMD & 3) == 3)
6026      res<<=1;
6027
6028   if(STV_VDP2_HRES & 4)
6029      res = (STV_VDP2_HRES & 1) ? 561 : 525;  //Hi-Vision / 31kHz Monitor
6030
6031   return res;
6032}
6033
6034int saturn_state::get_pixel_clock( void )
6035{
6036   int res,divider;
6037
6038   res = m_vdp2.dotsel ? MASTER_CLOCK_352 : MASTER_CLOCK_320;
6039   /* TODO: divider is ALWAYS 8, this thing is just to over-compensate for MAME framework faults ... */
6040   divider = 8;
6041
6042   if(STV_VDP2_HRES & 2)
6043      divider>>=1;
6044
6045   if((STV_VDP2_LSMD & 3) == 3)
6046      divider>>=1;
6047
6048   if(STV_VDP2_HRES & 4) //TODO
6049      divider>>=1;
6050
6051   return res/divider;
6052}
6053
6054UINT8 saturn_state::get_hblank( void )
6055{
6056   const rectangle &visarea = machine().primary_screen->visible_area();
6057   int cur_h = machine().primary_screen->hpos();
6058
6059   if (cur_h > visarea.max_x) //TODO
6060      return 1;
6061
6062   return 0;
6063}
6064
6065UINT8 saturn_state::get_vblank( void )
6066{
6067   int cur_v,vblank;
6068   cur_v = machine().primary_screen->vpos();
6069
6070   vblank = (m_vdp2.pal) ? 288 : 240;
6071
6072   if((STV_VDP2_LSMD & 3) == 3)
6073      vblank<<=1;
6074
6075   if (cur_v >= vblank)
6076      return 1;
6077
6078   return 0;
6079}
6080
6081UINT8 saturn_state::get_odd_bit( void )
6082{
6083   int cur_v;
6084   cur_v = machine().primary_screen->vpos();
6085
6086   if(STV_VDP2_HRES & 4) //exclusive monitor mode makes this bit to be always 1
6087      return 1;
6088
6089   if(STV_VDP2_LSMD == 0) // same for non-interlace mode
6090      return 1;
6091
6092   if(cur_v % 2)
6093      return 1;
6094
6095   return 0;
6096}
6097
6098void saturn_state::stv_vdp2_state_save_postload( void )
6099{
6100   UINT8 *gfxdata = m_vdp2.gfx_decode;
6101   int offset;
6102   UINT32 data;
6103
6104   for ( offset = 0; offset < 0x100000/4; offset++ )
6105   {
6106      data = m_vdp2_vram[offset];
6107      /* put in gfx region for easy decoding */
6108      gfxdata[offset*4+0] = (data & 0xff000000) >> 24;
6109      gfxdata[offset*4+1] = (data & 0x00ff0000) >> 16;
6110      gfxdata[offset*4+2] = (data & 0x0000ff00) >> 8;
6111      gfxdata[offset*4+3] = (data & 0x000000ff) >> 0;
6112
6113      machine().gfx[0]->mark_dirty(offset/8);
6114      machine().gfx[1]->mark_dirty(offset/8);
6115      machine().gfx[2]->mark_dirty(offset/8);
6116      machine().gfx[3]->mark_dirty(offset/8);
6117
6118      /* 8-bit tiles overlap, so this affects the previous one as well */
6119      if (offset/8 != 0)
6120      {
6121         machine().gfx[2]->mark_dirty(offset/8 - 1);
6122         machine().gfx[3]->mark_dirty(offset/8 - 1);
6123      }
6124
6125   }
6126
6127   memset( &stv_rbg_cache_data, 0, sizeof(stv_rbg_cache_data));
6128   stv_rbg_cache_data.is_cache_dirty = 3;
6129   memset( &stv_vdp2_layer_data_placement, 0, sizeof(stv_vdp2_layer_data_placement));
6130
6131   refresh_palette_data();
6132}
6133
6134void saturn_state::stv_vdp2_exit ( void )
6135{
6136   m_vdp2.roz_bitmap[0].reset();
6137   m_vdp2.roz_bitmap[1].reset();
6138}
6139
6140int saturn_state::stv_vdp2_start ( void )
6141{
6142   machine().add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(saturn_state::stv_vdp2_exit), this));
6143
6144   m_vdp2_regs = auto_alloc_array_clear(machine(), UINT16, 0x040000/2 );
6145   m_vdp2_vram = auto_alloc_array_clear(machine(), UINT32, 0x100000/4 );
6146   m_vdp2_cram = auto_alloc_array_clear(machine(), UINT32, 0x080000/4 );
6147   m_vdp2.gfx_decode = auto_alloc_array(machine(), UINT8, 0x100000 );
6148
6149//  machine().gfx[0]->granularity()=4;
6150//  machine().gfx[1]->granularity()=4;
6151
6152   memset( &stv_rbg_cache_data, 0, sizeof(stv_rbg_cache_data));
6153   stv_rbg_cache_data.is_cache_dirty = 3;
6154   memset( &stv_vdp2_layer_data_placement, 0, sizeof(stv_vdp2_layer_data_placement));
6155
6156   state_save_register_global_pointer(machine(), m_vdp2_regs, 0x040000/2);
6157   state_save_register_global_pointer(machine(), m_vdp2_vram, 0x100000/4);
6158   state_save_register_global_pointer(machine(), m_vdp2_cram, 0x080000/4);
6159   machine().save().register_postload(save_prepost_delegate(FUNC(saturn_state::stv_vdp2_state_save_postload), this));
6160
6161   return 0;
6162}
6163
6164/* maybe we should move this to video/stv.c */
6165VIDEO_START_MEMBER(saturn_state,stv_vdp2)
6166{
6167   machine().primary_screen->register_screen_bitmap(m_tmpbitmap);
6168   stv_vdp2_start();
6169   stv_vdp1_start();
6170   m_vdpdebug_roz = 0;
6171   machine().gfx[0]->set_source(m_vdp2.gfx_decode);
6172   machine().gfx[1]->set_source(m_vdp2.gfx_decode);
6173   machine().gfx[2]->set_source(m_vdp2.gfx_decode);
6174   machine().gfx[3]->set_source(m_vdp2.gfx_decode);
6175}
6176
6177void saturn_state::stv_vdp2_dynamic_res_change( void )
6178{
6179   const int d_vres[4] = { 224, 240, 256, 256 };
6180   const int d_hres[4] = { 320, 352, 640, 704 };
6181   int horz_res,vert_res;
6182   int vres_mask;
6183
6184   vres_mask = (m_vdp2.pal << 1)|1; //PAL uses mask 3, NTSC uses mask 1
6185   vert_res = d_vres[STV_VDP2_VRES & vres_mask];
6186
6187   if((STV_VDP2_VRES & 3) == 3)
6188      popmessage("Illegal VRES MODE, contact MAMEdev");
6189
6190   /*Double-density interlace mode,doubles the vertical res*/
6191   if((STV_VDP2_LSMD & 3) == 3) { vert_res*=2;  }
6192
6193   horz_res = d_hres[STV_VDP2_HRES & 3];
6194   /*Exclusive modes,they sets the Vertical Resolution without considering the
6195     VRES register.*/
6196   if(STV_VDP2_HRES & 4)
6197      vert_res = 480;
6198
6199   {
6200      int vblank_period,hblank_period;
6201      attoseconds_t refresh;;
6202      rectangle visarea(0, horz_res-1, 0, vert_res-1);
6203
6204      vblank_period = get_vblank_duration();
6205      hblank_period = get_hblank_duration();
6206      refresh  = HZ_TO_ATTOSECONDS(get_pixel_clock()) * (hblank_period) * vblank_period;
6207      //printf("%d %d %d %d\n",horz_res,vert_res,horz_res+hblank_period,vblank_period);
6208
6209      machine().primary_screen->configure((hblank_period), (vblank_period), visarea, refresh );
6210   }
6211//  machine().primary_screen->set_visible_area(0*8, horz_res-1,0*8, vert_res-1);
6212}
6213
6214/*This is for calculating the rgb brightness*/
6215/*TODO: Optimize this...*/
6216void saturn_state::stv_vdp2_fade_effects( void )
6217{
6218   /*
6219   Note:We have to use temporary storages because palette_get_color must use
6220   variables setted with unsigned int8
6221   */
6222   INT16 t_r,t_g,t_b;
6223   UINT8 r,g,b;
6224   rgb_t color;
6225   int i;
6226   //popmessage("%04x %04x",STV_VDP2_CLOFEN,STV_VDP2_CLOFSL);
6227   for(i=0;i<2048;i++)
6228   {
6229      /*Fade A*/
6230      color = palette_get_color(machine(), i);
6231      t_r = (STV_VDP2_COAR & 0x100) ? (RGB_RED(color) - (0x100 - (STV_VDP2_COAR & 0xff))) : ((STV_VDP2_COAR & 0xff) + RGB_RED(color));
6232      t_g = (STV_VDP2_COAG & 0x100) ? (RGB_GREEN(color) - (0x100 - (STV_VDP2_COAG & 0xff))) : ((STV_VDP2_COAG & 0xff) + RGB_GREEN(color));
6233      t_b = (STV_VDP2_COAB & 0x100) ? (RGB_BLUE(color) - (0x100 - (STV_VDP2_COAB & 0xff))) : ((STV_VDP2_COAB & 0xff) + RGB_BLUE(color));
6234      if(t_r < 0)     { t_r = 0; }
6235      if(t_r > 0xff)  { t_r = 0xff; }
6236      if(t_g < 0)     { t_g = 0; }
6237      if(t_g > 0xff)  { t_g = 0xff; }
6238      if(t_b < 0)     { t_b = 0; }
6239      if(t_b > 0xff)  { t_b = 0xff; }
6240      r = t_r;
6241      g = t_g;
6242      b = t_b;
6243      palette_set_color(machine(),i+(2048*1),MAKE_RGB(r,g,b));
6244
6245      /*Fade B*/
6246      color = palette_get_color(machine(), i);
6247      t_r = (STV_VDP2_COBR & 0x100) ? (RGB_RED(color) - (0xff - (STV_VDP2_COBR & 0xff))) : ((STV_VDP2_COBR & 0xff) + RGB_RED(color));
6248      t_g = (STV_VDP2_COBG & 0x100) ? (RGB_GREEN(color) - (0xff - (STV_VDP2_COBG & 0xff))) : ((STV_VDP2_COBG & 0xff) + RGB_GREEN(color));
6249      t_b = (STV_VDP2_COBB & 0x100) ? (RGB_BLUE(color) - (0xff - (STV_VDP2_COBB & 0xff))) : ((STV_VDP2_COBB & 0xff) + RGB_BLUE(color));
6250      if(t_r < 0)     { t_r = 0; }
6251      if(t_r > 0xff)  { t_r = 0xff; }
6252      if(t_g < 0)     { t_g = 0; }
6253      if(t_g > 0xff)  { t_g = 0xff; }
6254      if(t_b < 0)     { t_b = 0; }
6255      if(t_b > 0xff)  { t_b = 0xff; }
6256      r = t_r;
6257      g = t_g;
6258      b = t_b;
6259      palette_set_color(machine(),i+(2048*2),MAKE_RGB(r,g,b));
6260   }
6261   //popmessage("%04x %04x %04x %04x %04x %04x",STV_VDP2_COAR,STV_VDP2_COAG,STV_VDP2_COAB,STV_VDP2_COBR,STV_VDP2_COBG,STV_VDP2_COBB);
6262}
6263
6264/******************************************************************************************
6265
6266ST-V VDP2 window effect function version 0.04
6267
6268How it works: returns 0 if the requested pixel is drawnable,1 if it isn't.
6269For tilemap and sprite layer, clipping rectangle is changed.
6270
6271Done:
6272-Basic support(w0 or w1),bitmaps only.
6273-W0 (outside) for tilemaps and sprite layer.
6274-Window logic.
6275
6276Not Done:
6277-Complete Windows on cells.A split between cells and bitmaps is in progress...
6278-w0 & w1 at the same time.
6279-Line window.
6280-Color Calculation.
6281-Rotation parameter Window (already done?).
6282
6283Window Registers are hooked up like this ATM:
6284    x--- ---- UNUSED
6285    -x-- ---- Sprite Window Area
6286    --x- ---- Window 1 Area
6287    ---x ---- Window 0 Area
6288                  (0 = Inside,1 = Outside)
6289    ---- x--- Sprite Window Enable
6290    ---- -x-- Window 1 Enable
6291    ---- --x- Window 0 Enable
6292                  (0 = Disabled,1 = Enabled)
6293    ---- ---x Window Logic
6294                  (0 = OR,1 = AND)
6295******************************************************************************************/
6296
6297void saturn_state::stv_vdp2_get_window0_coordinates(UINT16 *s_x, UINT16 *e_x, UINT16 *s_y, UINT16 *e_y)
6298{
6299   /*W0*/
6300   switch(STV_VDP2_LSMD & 3)
6301   {
6302      case 0:
6303      case 1:
6304      case 2:
6305         *s_y = ((STV_VDP2_W0SY & 0x3ff) >> 0);
6306         *e_y = ((STV_VDP2_W0EY & 0x3ff) >> 0);
6307         break;
6308      case 3:
6309         *s_y = ((STV_VDP2_W0SY & 0x7ff) >> 0);
6310         *e_y = ((STV_VDP2_W0EY & 0x7ff) >> 0);
6311         break;
6312   }
6313   switch(STV_VDP2_HRES & 6)
6314   {
6315      /*Normal*/
6316      case 0:
6317         *s_x = ((STV_VDP2_W0SX & 0x3fe) >> 1);
6318         *e_x = ((STV_VDP2_W0EX & 0x3fe) >> 1);
6319         break;
6320      /*Hi-Res*/
6321      case 2:
6322         *s_x = ((STV_VDP2_W0SX & 0x3ff) >> 0);
6323         *e_x = ((STV_VDP2_W0EX & 0x3ff) >> 0);
6324         break;
6325      /*Exclusive Normal*/
6326      case 4:
6327         *s_x = ((STV_VDP2_W0SX & 0x1ff) >> 0);
6328         *e_x = ((STV_VDP2_W0EX & 0x1ff) >> 0);
6329         *s_y = ((STV_VDP2_W0SY & 0x3ff) >> 0);
6330         *e_y = ((STV_VDP2_W0EY & 0x3ff) >> 0);
6331         break;
6332      /*Exclusive Hi-Res*/
6333      case 6:
6334         *s_x = ((STV_VDP2_W0SX & 0x1ff) << 1);
6335         *e_x = ((STV_VDP2_W0EX & 0x1ff) << 1);
6336         *s_y = ((STV_VDP2_W0SY & 0x3ff) >> 0);
6337         *e_y = ((STV_VDP2_W0EY & 0x3ff) >> 0);
6338         break;
6339   }
6340}
6341
6342void saturn_state::stv_vdp2_get_window1_coordinates(UINT16 *s_x, UINT16 *e_x, UINT16 *s_y, UINT16 *e_y)
6343{
6344   /*W1*/
6345   switch(STV_VDP2_LSMD & 3)
6346   {
6347      case 0:
6348      case 1:
6349      case 2:
6350         *s_y = ((STV_VDP2_W1SY & 0x3ff) >> 0);
6351         *e_y = ((STV_VDP2_W1EY & 0x3ff) >> 0);
6352         break;
6353      case 3:
6354         *s_y = ((STV_VDP2_W1SY & 0x7ff) >> 0);
6355         *e_y = ((STV_VDP2_W1EY & 0x7ff) >> 0);
6356         break;
6357   }
6358   switch(STV_VDP2_HRES & 6)
6359   {
6360      /*Normal*/
6361      case 0:
6362         *s_x = ((STV_VDP2_W1SX & 0x3fe) >> 1);
6363         *e_x = ((STV_VDP2_W1EX & 0x3fe) >> 1);
6364         break;
6365      /*Hi-Res*/
6366      case 2:
6367         *s_x = ((STV_VDP2_W1SX & 0x3ff) >> 0);
6368         *e_x = ((STV_VDP2_W1EX & 0x3ff) >> 0);
6369         break;
6370      /*Exclusive Normal*/
6371      case 4:
6372         *s_x = ((STV_VDP2_W1SX & 0x1ff) >> 0);
6373         *e_x = ((STV_VDP2_W1EX & 0x1ff) >> 0);
6374         *s_y = ((STV_VDP2_W1SY & 0x3ff) >> 0);
6375         *e_y = ((STV_VDP2_W1EY & 0x3ff) >> 0);
6376         break;
6377      /*Exclusive Hi-Res*/
6378      case 6:
6379         *s_x = ((STV_VDP2_W1SX & 0x1ff) << 1);
6380         *e_x = ((STV_VDP2_W1EX & 0x1ff) << 1);
6381         *s_y = ((STV_VDP2_W1SY & 0x3ff) >> 0);
6382         *e_y = ((STV_VDP2_W1EY & 0x3ff) >> 0);
6383         break;
6384   }
6385
6386}
6387
6388int saturn_state::get_window_pixel(UINT16 s_x,UINT16 e_x,UINT16 s_y,UINT16 e_y,int x, int y,UINT8 win_num)
6389{
6390   if(stv2_current_tilemap.window_control & (2 << win_num))
6391   {
6392      /*Outside Area*/
6393      if(stv2_current_tilemap.window_control & (0x10 << win_num))
6394      {
6395         if(y < s_y || y > e_y)
6396            return 1;
6397         else
6398         {
6399            if(x < s_x || x > e_x)
6400               return 1;
6401            //else
6402            //  return 0;
6403         }
6404      }
6405      /*Inside Area*/
6406      else
6407      {
6408         if(y > s_y && y < e_y)
6409         {
6410            if(x > s_x && x < e_x)
6411               return 1;
6412         }
6413         //else
6414         //  return 0;
6415      }
6416   }
6417
6418   return 0;
6419}
6420
6421int saturn_state::stv_vdp2_window_process(int x,int y)
6422{
6423   UINT16 s_x=0,e_x=0,s_y=0,e_y=0;
6424   UINT8 w0_pix, w1_pix;
6425
6426   if ((stv2_current_tilemap.window_control & 6) == 0)
6427      return 0;
6428
6429   stv_vdp2_get_window0_coordinates(&s_x, &e_x, &s_y, &e_y);
6430   w0_pix = get_window_pixel(s_x,e_x,s_y,e_y,x,y,0);
6431
6432   stv_vdp2_get_window1_coordinates(&s_x, &e_x, &s_y, &e_y);
6433   w1_pix = get_window_pixel(s_x,e_x,s_y,e_y,x,y,1);
6434
6435   return stv2_current_tilemap.window_control & 1 ? (w0_pix & w1_pix) : (w0_pix | w1_pix);
6436}
6437
6438int saturn_state::stv_vdp2_apply_window_on_layer(rectangle &cliprect)
6439{
6440   UINT16 s_x=0,e_x=0,s_y=0,e_y=0;
6441
6442   if ( stv2_current_tilemap.window_control == 0x12 )
6443   {
6444      /* w0, transparent outside supported */
6445      stv_vdp2_get_window0_coordinates(&s_x, &e_x, &s_y, &e_y);
6446
6447      if ( s_x > cliprect.min_x ) cliprect.min_x = s_x;
6448      if ( e_x < cliprect.max_x ) cliprect.max_x = e_x;
6449      if ( s_y > cliprect.min_y ) cliprect.min_y = s_y;
6450      if ( e_y < cliprect.max_y ) cliprect.max_y = e_y;
6451
6452      return 1;
6453   }
6454   else if ( stv2_current_tilemap.window_control == 0x24 )
6455   {
6456      /* w1, transparent outside supported */
6457      stv_vdp2_get_window1_coordinates(&s_x, &e_x, &s_y, &e_y);
6458
6459      if ( s_x > cliprect.min_x ) cliprect.min_x = s_x;
6460      if ( e_x < cliprect.max_x ) cliprect.max_x = e_x;
6461      if ( s_y > cliprect.min_y ) cliprect.min_y = s_y;
6462      if ( e_y < cliprect.max_y ) cliprect.max_y = e_y;
6463
6464      return 1;
6465   }
6466   else
6467   {
6468      return 0;
6469   }
6470}
6471
6472void saturn_state::draw_sprites(bitmap_rgb32 &bitmap, const rectangle &cliprect, UINT8 pri)
6473{
6474   int x,y,r,g,b;
6475   int i;
6476   UINT16 pix;
6477   UINT16 *framebuffer_line;
6478   UINT32 *bitmap_line, *bitmap_line2 = NULL;
6479   UINT8  interlace_framebuffer;
6480   UINT8  double_x;
6481   static const UINT16 sprite_colormask_table[] = {
6482      0x07ff, 0x07ff, 0x07ff, 0x07ff, 0x03ff, 0x07ff, 0x03ff, 0x01ff,
6483      0x007f, 0x003f, 0x003f, 0x003f, 0x00ff, 0x00ff, 0x00ff, 0x00ff
6484   };
6485   static const UINT16 priority_shift_table[] = { 14, 13, 14, 13, 13, 12, 12, 12, 7, 7, 6, 0, 7, 7, 6, 0 };
6486   static const UINT16 priority_mask_table[]  = {  3,  7,  1,  3,  3,  7,  7,  7, 1, 1, 3, 0, 1, 1, 3, 0 };
6487   static const UINT16 ccrr_shift_table[] =     { 11, 11, 11, 11, 10, 11, 10,  9, 0, 6, 0, 6, 0, 6, 0, 6 };
6488   static const UINT16 ccrr_mask_table[] =      {  7,  3,  7,  3,  7,  1,  3,  7, 0, 1, 0, 3, 0, 1, 0, 3 };
6489   static const UINT16 shadow_mask_table[] = { 0, 0, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0, 0, 0, 0, 0, 0, 0, 0 };
6490   UINT16 alpha_enabled;
6491
6492   int sprite_type;
6493   int sprite_colormask;
6494   int color_offset_pal;
6495   int sprite_shadow;
6496   UINT16 sprite_priority_shift, sprite_priority_mask, sprite_ccrr_shift, sprite_ccrr_mask;
6497   UINT8   priority;
6498   UINT8   ccr = 0;
6499   UINT8 sprite_priorities[8];
6500   UINT8 sprite_ccr[8];
6501   int sprite_color_mode = STV_VDP2_SPCLMD;
6502   rectangle mycliprect;
6503
6504   if ( (stv_sprite_priorities_usage_valid == 1) && (stv_sprite_priorities_used[pri] == 0) )
6505      return;
6506
6507   sprite_priorities[0] = STV_VDP2_S0PRIN;
6508   sprite_priorities[1] = STV_VDP2_S1PRIN;
6509   sprite_priorities[2] = STV_VDP2_S2PRIN;
6510   sprite_priorities[3] = STV_VDP2_S3PRIN;
6511   sprite_priorities[4] = STV_VDP2_S4PRIN;
6512   sprite_priorities[5] = STV_VDP2_S5PRIN;
6513   sprite_priorities[6] = STV_VDP2_S6PRIN;
6514   sprite_priorities[7] = STV_VDP2_S7PRIN;
6515
6516   sprite_ccr[0] = STV_VDP2_S0CCRT;
6517   sprite_ccr[1] = STV_VDP2_S1CCRT;
6518   sprite_ccr[2] = STV_VDP2_S2CCRT;
6519   sprite_ccr[3] = STV_VDP2_S3CCRT;
6520   sprite_ccr[4] = STV_VDP2_S4CCRT;
6521   sprite_ccr[5] = STV_VDP2_S5CCRT;
6522   sprite_ccr[6] = STV_VDP2_S6CCRT;
6523   sprite_ccr[7] = STV_VDP2_S7CCRT;
6524
6525   sprite_type = STV_VDP2_SPTYPE;
6526   sprite_colormask = sprite_colormask_table[sprite_type];
6527   sprite_priority_shift = priority_shift_table[sprite_type];
6528   sprite_priority_mask = priority_mask_table[sprite_type];
6529   sprite_ccrr_shift = ccrr_shift_table[sprite_type];
6530   sprite_ccrr_mask = ccrr_mask_table[sprite_type];
6531   sprite_shadow = shadow_mask_table[sprite_type];
6532
6533   for ( i = 0; i < (sprite_priority_mask+1); i++ ) if ( sprite_priorities[i] == pri ) break;
6534   if ( i == (sprite_priority_mask+1) ) return;
6535
6536   /* color offset (RGB brightness) */
6537   color_offset_pal = 0;
6538   if ( STV_VDP2_SPCOEN )
6539   {
6540      if ( STV_VDP2_SPCOSL == 0 )
6541      { color_offset_pal = 2048; }
6542      else
6543      { color_offset_pal = 2048*2; }
6544   }
6545
6546   /* color calculation (alpha blending)*/
6547   if ( STV_VDP2_SPCCEN )
6548   {
6549      alpha_enabled = 0;
6550      switch( STV_VDP2_SPCCCS )
6551      {
6552         case 0x0: if ( pri <= STV_VDP2_SPCCN ) alpha_enabled = 1; break;
6553         case 0x1: if ( pri == STV_VDP2_SPCCN ) alpha_enabled = 1; break;
6554         case 0x2: if ( pri >= STV_VDP2_SPCCN ) alpha_enabled = 1; break;
6555         case 0x3: alpha_enabled = 2; sprite_shadow = 0; break;
6556      }
6557   }
6558   else
6559   {
6560      alpha_enabled = 0;
6561   }
6562
6563   /* framebuffer interlace */
6564   if ( (STV_VDP2_LSMD == 3) && m_vdp1.framebuffer_double_interlace == 0 )
6565      interlace_framebuffer = 1;
6566   else
6567      interlace_framebuffer = 0;
6568
6569   /*Guess:Some games needs that the horizontal sprite size to be doubled
6570     (TODO: understand the proper settings,it might not work like this)*/
6571   if(STV_VDP1_TVM == 0 && STV_VDP2_HRES & 2) // astrass & findlove
6572      double_x = 1;
6573   else
6574      double_x = 0;
6575
6576   /* window control */
6577   stv2_current_tilemap.window_control = (STV_VDP2_SPLOG * 0x01) |
6578                                 (STV_VDP2_SPW0E * 0x02) |
6579                                 (STV_VDP2_SPW1E * 0x04) |
6580                                 (STV_VDP2_SPSWE * 0x08) |
6581                                 (STV_VDP2_SPW0A * 0x10) |
6582                                 (STV_VDP2_SPW1A * 0x20) |
6583                                 (STV_VDP2_SPSWA * 0x40);
6584   mycliprect = cliprect;
6585
6586   stv_vdp2_apply_window_on_layer(mycliprect);
6587
6588   if (interlace_framebuffer == 0 && double_x == 0 )
6589   {
6590      if ( alpha_enabled == 0 )
6591      {
6592         for ( y = mycliprect.min_y; y <= mycliprect.max_y; y++ )
6593         {
6594            if ( stv_sprite_priorities_usage_valid )
6595               if (stv_sprite_priorities_in_fb_line[y][pri] == 0)
6596                  continue;
6597
6598            framebuffer_line = m_vdp1.framebuffer_display_lines[y];
6599            bitmap_line = &bitmap.pix32(y);
6600
6601            for ( x = mycliprect.min_x; x <= mycliprect.max_x; x++ )
6602            {
6603               pix = framebuffer_line[x];
6604               if ( (pix & 0x8000) && sprite_color_mode)
6605               {
6606                  if ( sprite_priorities[0] != pri )
6607                  {
6608                     stv_sprite_priorities_used[sprite_priorities[0]] = 1;
6609                     stv_sprite_priorities_in_fb_line[y][sprite_priorities[0]] = 1;
6610                     continue;
6611                  };
6612
6613                  if(STV_VDP2_SPWINEN && pix == 0x8000) /* Pukunpa */
6614                     continue;
6615
6616                  b = pal5bit((pix & 0x7c00) >> 10);
6617                  g = pal5bit((pix & 0x03e0) >> 5);
6618                  r = pal5bit( pix & 0x001f);
6619                  if ( color_offset_pal )
6620                  {
6621                     stv_vdp2_compute_color_offset( &r, &g, &b, STV_VDP2_SPCOSL );
6622                  }
6623
6624                  bitmap_line[x] = MAKE_RGB(r, g, b);
6625               }
6626               else
6627               {
6628                  priority = sprite_priorities[(pix >> sprite_priority_shift) & sprite_priority_mask];
6629                  if ( priority != pri )
6630                  {
6631                     stv_sprite_priorities_used[priority] = 1;
6632                     stv_sprite_priorities_in_fb_line[y][priority] = 1;
6633                     continue;
6634                  };
6635
6636                  {
6637                     pix &= sprite_colormask;
6638                     if ( pix == (sprite_colormask - 1) )
6639                     {
6640                        /*shadow - in reality, we should check from what layer pixel beneath comes...*/
6641                        if ( STV_VDP2_SDCTL & 0x3f )
6642                        {
6643                           UINT32 p = bitmap_line[x];
6644                           bitmap_line[x] = MAKE_RGB(RGB_RED(p) >> 1, RGB_GREEN(p) >> 1, RGB_BLUE(p) >> 1);
6645                        }
6646                        /* note that when shadows are disabled, "shadow" palette entries are not drawn */
6647                     }
6648                     else if ( pix )
6649                     {
6650                        pix += (STV_VDP2_SPCAOS << 8);
6651                        pix &= 0x7ff;
6652                        pix += color_offset_pal;
6653                        bitmap_line[x] = machine().pens[ pix ];
6654                     }
6655                  }
6656
6657                  /* TODO: I don't think this one makes much logic ... (1) */
6658                  if ( pix & sprite_shadow )
6659                  {
6660                     if ( pix & ~sprite_shadow )
6661                     {
6662                        UINT32 p = bitmap_line[x];
6663                        bitmap_line[x] = MAKE_RGB(RGB_RED(p) >> 1, RGB_GREEN(p) >> 1, RGB_BLUE(p) >> 1);
6664                     }
6665                  }
6666               }
6667            }
6668         }
6669      }
6670      else //alpha_enabled == 1
6671      {
6672         for ( y = mycliprect.min_y; y <= mycliprect.max_y; y++ )
6673         {
6674            if ( stv_sprite_priorities_usage_valid )
6675               if (stv_sprite_priorities_in_fb_line[y][pri] == 0)
6676                  continue;
6677
6678            framebuffer_line = m_vdp1.framebuffer_display_lines[y];
6679            bitmap_line = &bitmap.pix32(y);
6680
6681            for ( x = mycliprect.min_x; x <= mycliprect.max_x; x++ )
6682            {
6683               pix = framebuffer_line[x];
6684               if ( (pix & 0x8000) && sprite_color_mode)
6685               {
6686                  if ( sprite_priorities[0] != pri )
6687                  {
6688                     stv_sprite_priorities_used[sprite_priorities[0]] = 1;
6689                     stv_sprite_priorities_in_fb_line[y][sprite_priorities[0]] = 1;
6690                     continue;
6691                  };
6692
6693                  b = pal5bit((pix & 0x7c00) >> 10);
6694                  g = pal5bit((pix & 0x03e0) >> 5);
6695                  r = pal5bit( pix & 0x001f);
6696                  if ( color_offset_pal )
6697                  {
6698                     stv_vdp2_compute_color_offset( &r, &g, &b, STV_VDP2_SPCOSL );
6699                  }
6700                  ccr = sprite_ccr[0];
6701                  if ( STV_VDP2_CCMD )
6702                  {
6703                     bitmap_line[x] = stv_add_blend( bitmap_line[x], MAKE_RGB(r, g, b));
6704                  }
6705                  else
6706                  {
6707                     bitmap_line[x] = alpha_blend_r32( bitmap_line[x], MAKE_RGB(r, g ,b), ((UINT16)(0x1f-ccr)*0xff)/0x1f);
6708                  }
6709               }
6710               else
6711               {
6712                  priority = sprite_priorities[(pix >> sprite_priority_shift) & sprite_priority_mask];
6713                  if ( priority != pri )
6714                  {
6715                     stv_sprite_priorities_used[priority] = 1;
6716                     stv_sprite_priorities_in_fb_line[y][priority] = 1;
6717                     continue;
6718                  };
6719
6720                  ccr = sprite_ccr[ (pix >> sprite_ccrr_shift) & sprite_ccrr_mask ];
6721                  if ( alpha_enabled == 2 )
6722                  {
6723                     if ( ( pix & 0x8000 ) == 0 )
6724                     {
6725                        ccr = 0;
6726                     }
6727                  }
6728
6729
6730                  {
6731                     pix &= sprite_colormask;
6732                     if ( pix == (sprite_colormask - 1) )
6733                     {
6734                        /*shadow - in reality, we should check from what layer pixel beneath comes...*/
6735                        if ( STV_VDP2_SDCTL & 0x3f )
6736                        {
6737                           UINT32 p = bitmap_line[x];
6738                           bitmap_line[x] = MAKE_RGB(RGB_RED(p) >> 1, RGB_GREEN(p) >> 1, RGB_BLUE(p) >> 1);
6739                        }
6740                        /* note that when shadows are disabled, "shadow" palette entries are not drawn */
6741                     } else if ( pix )
6742                     {
6743                        pix += (STV_VDP2_SPCAOS << 8);
6744                        pix &= 0x7ff;
6745                        pix += color_offset_pal;
6746                        if ( ccr > 0 )
6747                        {
6748                           if ( STV_VDP2_CCMD )
6749                           {
6750                              bitmap_line[x] = stv_add_blend( bitmap_line[x], machine().pens[pix] );
6751                           }
6752                           else
6753                           {
6754                              bitmap_line[x] = alpha_blend_r32( bitmap_line[x], machine().pens[pix], ((UINT16)(0x1f-ccr)*0xff)/0x1f );
6755                           }
6756                        }
6757                        else
6758                           bitmap_line[x] = machine().pens[pix];
6759                     }
6760                  }
6761
6762                  /* TODO: (1) */
6763                  if ( pix & sprite_shadow )
6764                  {
6765                     if ( pix & ~sprite_shadow )
6766                     {
6767                        UINT32 p = bitmap_line[x];
6768                        bitmap_line[x] = MAKE_RGB(RGB_RED(p) >> 1, RGB_GREEN(p) >> 1, RGB_BLUE(p) >> 1);
6769                     }
6770                  }
6771               }
6772            }
6773         }
6774      }
6775   }
6776   else
6777   {
6778      for ( y = mycliprect.min_y; y <= mycliprect.max_y / (interlace_framebuffer+1); y++ )
6779      {
6780         if ( stv_sprite_priorities_usage_valid )
6781            if (stv_sprite_priorities_in_fb_line[y][pri] == 0)
6782               continue;
6783
6784         framebuffer_line = m_vdp1.framebuffer_display_lines[y];
6785         if ( interlace_framebuffer == 0 )
6786         {
6787            bitmap_line = &bitmap.pix32(y);
6788         }
6789         else
6790         {
6791            bitmap_line = &bitmap.pix32(2*y);
6792            bitmap_line2 = &bitmap.pix32(2*y + 1);
6793         }
6794
6795         for ( x = mycliprect.min_x; x <= mycliprect.max_x /(double_x+1) ; x++ )
6796         {
6797            pix = framebuffer_line[x];
6798            if ( (pix & 0x8000) && sprite_color_mode)
6799            {
6800               if ( sprite_priorities[0] != pri )
6801               {
6802                  stv_sprite_priorities_used[sprite_priorities[0]] = 1;
6803                  stv_sprite_priorities_in_fb_line[y][sprite_priorities[0]] = 1;
6804                  continue;
6805               };
6806
6807               b = pal5bit((pix & 0x7c00) >> 10);
6808               g = pal5bit((pix & 0x03e0) >> 5);
6809               r = pal5bit( pix & 0x001f);
6810               if ( color_offset_pal )
6811               {
6812                  stv_vdp2_compute_color_offset( &r, &g, &b, STV_VDP2_SPCOSL );
6813               }
6814               if ( alpha_enabled == 0 )
6815               {
6816                  if(double_x)
6817                  {
6818                     bitmap_line[x*2] = MAKE_RGB(r, g, b);
6819                     if ( interlace_framebuffer == 1 ) bitmap_line2[x*2] = MAKE_RGB(r, g, b);
6820                     bitmap_line[x*2+1] = MAKE_RGB(r, g, b);
6821                     if ( interlace_framebuffer == 1 ) bitmap_line2[x*2+1] = MAKE_RGB(r, g, b);
6822                  }
6823                  else
6824                  {
6825                     bitmap_line[x] = MAKE_RGB(r, g, b);
6826                     if ( interlace_framebuffer == 1 ) bitmap_line2[x] = MAKE_RGB(r, g, b);
6827                  }
6828               }
6829               else // alpha_blend == 1
6830               {
6831                  ccr = sprite_ccr[0];
6832
6833                  if ( STV_VDP2_CCMD )
6834                  {
6835                     if(double_x)
6836                     {
6837                        bitmap_line[x*2] = stv_add_blend( bitmap_line[x*2], MAKE_RGB(r, g, b) );
6838                        if ( interlace_framebuffer == 1 ) bitmap_line2[x*2] = stv_add_blend( bitmap_line2[x*2], MAKE_RGB(r, g, b) );
6839                        bitmap_line[x*2+1] = stv_add_blend( bitmap_line[x*2+1], MAKE_RGB(r, g, b) );
6840                        if ( interlace_framebuffer == 1 ) bitmap_line2[x*2+1] = stv_add_blend( bitmap_line2[x*2+1], MAKE_RGB(r, g, b) );
6841                     }
6842                     else
6843                     {
6844                        bitmap_line[x] = stv_add_blend( bitmap_line[x], MAKE_RGB(r, g, b) );
6845                        if ( interlace_framebuffer == 1 ) bitmap_line2[x] = stv_add_blend( bitmap_line2[x], MAKE_RGB(r, g, b) );
6846                     }
6847                  }
6848                  else
6849                  {
6850                     if(double_x)
6851                     {
6852                        bitmap_line[x*2] = alpha_blend_r32( bitmap_line[x*2], MAKE_RGB(r, g, b), ((UINT16)(0x1f-ccr)*0xff)/0x1f );
6853                        if ( interlace_framebuffer == 1 ) bitmap_line2[x*2] = alpha_blend_r32( bitmap_line2[x*2], MAKE_RGB(r, g, b), ((UINT16)(0x1f-ccr)*0xff)/0x1f );
6854                        bitmap_line[x*2+1] = alpha_blend_r32( bitmap_line[x*2+1], MAKE_RGB(r, g, b), ((UINT16)(0x1f-ccr)*0xff)/0x1f );
6855                        if ( interlace_framebuffer == 1 ) bitmap_line2[x*2+1] = alpha_blend_r32( bitmap_line2[x*2+1], MAKE_RGB(r, g, b), ((UINT16)(0x1f-ccr)*0xff)/0x1f);
6856                     }
6857                     else
6858                     {
6859                        bitmap_line[x] = alpha_blend_r32( bitmap_line[x], MAKE_RGB(r, g, b), ((UINT16)(0x1f-ccr)*0xff)/0x1f);
6860                        if ( interlace_framebuffer == 1 ) bitmap_line2[x] = alpha_blend_r32( bitmap_line2[x], MAKE_RGB(r, g, b), ((UINT16)(0x1f-ccr)*0xff)/0x1f);
6861                     }
6862                  }
6863               }
6864            }
6865            else
6866            {
6867               priority = sprite_priorities[(pix >> sprite_priority_shift) & sprite_priority_mask];
6868               if ( priority != pri )
6869               {
6870                  stv_sprite_priorities_used[priority] = 1;
6871                  stv_sprite_priorities_in_fb_line[y][priority] = 1;
6872                  continue;
6873               };
6874
6875               if ( alpha_enabled )
6876                  ccr = sprite_ccr[ (pix >> sprite_ccrr_shift) & sprite_ccrr_mask ];
6877
6878               if ( alpha_enabled == 2 )
6879               {
6880                  if ( ( pix & 0x8000 ) == 0 )
6881                  {
6882                     ccr = 0;
6883                  }
6884               }
6885
6886               {
6887                  pix &= sprite_colormask;
6888                  if ( pix == (sprite_colormask - 1) )
6889                  {
6890                     /*shadow - in reality, we should check from what layer pixel beneath comes...*/
6891                     if ( STV_VDP2_SDCTL & 0x3f )
6892                     {
6893                        UINT32 p = bitmap_line[x];
6894                        if(double_x)
6895                        {
6896                           p = bitmap_line[x*2];
6897                           bitmap_line[x*2] = MAKE_RGB(RGB_RED(p) >> 1, RGB_GREEN(p) >> 1, RGB_BLUE(p) >> 1);
6898                           p = bitmap_line[x*2+1];
6899                           bitmap_line[x*2+1] = MAKE_RGB(RGB_RED(p) >> 1, RGB_GREEN(p) >> 1, RGB_BLUE(p) >> 1);
6900                        }
6901                        else
6902                           bitmap_line[x] = MAKE_RGB(RGB_RED(p) >> 1, RGB_GREEN(p) >> 1, RGB_BLUE(p) >> 1);
6903                     }
6904                     /* note that when shadows are disabled, "shadow" palette entries are not drawn */
6905                  } else if ( pix )
6906                  {
6907                     pix += (STV_VDP2_SPCAOS << 8);
6908                     pix &= 0x7ff;
6909                     pix += color_offset_pal;
6910                     if ( alpha_enabled == 0 )
6911                     {
6912                        if(double_x)
6913                        {
6914                           bitmap_line[x*2] = machine().pens[ pix ];
6915                           if ( interlace_framebuffer == 1 ) bitmap_line2[x*2] = machine().pens[ pix ];
6916                           bitmap_line[x*2+1] = machine().pens[ pix ];
6917                           if ( interlace_framebuffer == 1 ) bitmap_line2[x*2+1] = machine().pens[ pix ];
6918                        }
6919                        else
6920                        {
6921                           bitmap_line[x] = machine().pens[ pix ];
6922                           if ( interlace_framebuffer == 1 ) bitmap_line2[x] = machine().pens[ pix ];
6923                        }
6924                     }
6925                     else // alpha_blend == 1
6926                     {
6927                        if ( STV_VDP2_CCMD )
6928                        {
6929                           if(double_x)
6930                           {
6931                              bitmap_line[x*2] = stv_add_blend( bitmap_line[x*2], machine().pens[pix] );
6932                              if ( interlace_framebuffer == 1 ) bitmap_line2[x*2] = stv_add_blend( bitmap_line2[x], machine().pens[pix] );
6933                              bitmap_line[x*2+1] = stv_add_blend( bitmap_line[x*2+1], machine().pens[pix] );
6934                              if ( interlace_framebuffer == 1 ) bitmap_line2[x*2+1] = stv_add_blend( bitmap_line2[x], machine().pens[pix] );
6935                           }
6936                           else
6937                           {
6938                              bitmap_line[x] = stv_add_blend( bitmap_line[x], machine().pens[pix] );
6939                              if ( interlace_framebuffer == 1 ) bitmap_line2[x] = stv_add_blend( bitmap_line2[x], machine().pens[pix] );
6940                           }
6941                        }
6942                        else
6943                        {
6944                           if(double_x)
6945                           {
6946                              bitmap_line[x*2] = alpha_blend_r32( bitmap_line[x*2], machine().pens[pix], ((UINT16)(0x1f-ccr)*0xff)/0x1f );
6947                              if ( interlace_framebuffer == 1 ) bitmap_line2[x*2] = alpha_blend_r32( bitmap_line2[x], machine().pens[pix], ((UINT16)(0x1f-ccr)*0xff)/0x1f );
6948                              bitmap_line[x*2+1] = alpha_blend_r32( bitmap_line[x*2+1], machine().pens[pix], ((UINT16)(0x1f-ccr)*0xff)/0x1f );
6949                              if ( interlace_framebuffer == 1 ) bitmap_line2[x*2+1] = alpha_blend_r32( bitmap_line2[x], machine().pens[pix], ((UINT16)(0x1f-ccr)*0xff)/0x1f );
6950                           }
6951                           else
6952                           {
6953                              bitmap_line[x] = alpha_blend_r32( bitmap_line[x], machine().pens[pix], ((UINT16)(0x1f-ccr)*0xff)/0x1f );
6954                              if ( interlace_framebuffer == 1 ) bitmap_line2[x] = alpha_blend_r32( bitmap_line2[x], machine().pens[pix], ((UINT16)(0x1f-ccr)*0xff)/0x1f );
6955                           }
6956                        }
6957                     }
6958                  }
6959               }
6960
6961               /* TODO: (1) */
6962               if ( pix & sprite_shadow )
6963               {
6964                  if ( pix & ~sprite_shadow )
6965                  {
6966                     UINT32 p = bitmap_line[x];
6967                     if(double_x)
6968                     {
6969                        p = bitmap_line[x*2];
6970                        bitmap_line[x*2] = MAKE_RGB(RGB_RED(p) >> 1, RGB_GREEN(p) >> 1, RGB_BLUE(p) >> 1);
6971                        p = bitmap_line[x*2+1];
6972                        bitmap_line[x*2+1] = MAKE_RGB(RGB_RED(p) >> 1, RGB_GREEN(p) >> 1, RGB_BLUE(p) >> 1);
6973                     }
6974                     else
6975                        bitmap_line[x] = MAKE_RGB(RGB_RED(p) >> 1, RGB_GREEN(p) >> 1, RGB_BLUE(p) >> 1);
6976                  }
6977               }
6978            }
6979         }
6980      }
6981   }
6982
6983   stv_sprite_priorities_usage_valid = 1;
6984}
6985
6986UINT32 saturn_state::screen_update_stv_vdp2(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
6987{
6988   stv_vdp2_fade_effects();
6989
6990   stv_vdp2_draw_back(m_tmpbitmap,cliprect);
6991
6992   if(STV_VDP2_DISP)
6993   {
6994      UINT8 pri;
6995
6996      stv_sprite_priorities_usage_valid = 0;
6997      memset(stv_sprite_priorities_used, 0, sizeof(stv_sprite_priorities_used));
6998      memset(stv_sprite_priorities_in_fb_line, 0, sizeof(stv_sprite_priorities_in_fb_line));
6999
7000      /*If a plane has a priority value of zero it isn't shown at all.*/
7001      for(pri=1;pri<8;pri++)
7002      {
7003         if(pri==STV_VDP2_N3PRIN) { stv_vdp2_draw_NBG3(m_tmpbitmap,cliprect); }
7004         if(pri==STV_VDP2_N2PRIN) { stv_vdp2_draw_NBG2(m_tmpbitmap,cliprect); }
7005         if(pri==STV_VDP2_N1PRIN) { stv_vdp2_draw_NBG1(m_tmpbitmap,cliprect); }
7006         if(pri==STV_VDP2_N0PRIN) { stv_vdp2_draw_NBG0(m_tmpbitmap,cliprect); }
7007         if(pri==STV_VDP2_R0PRIN) { stv_vdp2_draw_RBG0(m_tmpbitmap,cliprect); }
7008         { draw_sprites(m_tmpbitmap,cliprect,pri); }
7009      }
7010   }
7011
7012   copybitmap(bitmap, m_tmpbitmap, 0, 0, 0, 0, cliprect);
7013
7014   #if 0
7015   /* Do NOT remove me, used to test video code performance. */
7016   if(machine().input().code_pressed(KEYCODE_Q))
7017   {
7018      popmessage("Halt CPUs");
7019      m_maincpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
7020      m_slave->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
7021      m_audiocpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
7022   }
7023   #endif
7024   return 0;
7025}
Property changes on: trunk/src/emu/video/stvvdp2.c
Added: svn:eol-style
   + native
Added: svn:mime-type
   + text/plain
trunk/src/emu/emu.mak
r20946r20947
261261   $(EMUMACHINE)/scsidev.o     \
262262   $(EMUMACHINE)/scsihd.o      \
263263   $(EMUMACHINE)/scsihle.o     \
264   $(EMUMACHINE)/scudsp.o      \
264265   $(EMUMACHINE)/secflash.o    \
265266   $(EMUMACHINE)/seibu_cop.o   \
266267   $(EMUMACHINE)/smc91c9x.o    \
268   $(EMUMACHINE)/smpc.o      \
269   $(EMUMACHINE)/stvcd.o       \
267270   $(EMUMACHINE)/tc009xlvc.o   \
268271   $(EMUMACHINE)/timekpr.o     \
269272   $(EMUMACHINE)/tmp68301.o    \
r20946r20947
328331   $(EMUVIDEO)/s2636.o         \
329332   $(EMUVIDEO)/saa5050.o       \
330333   $(EMUVIDEO)/sed1330.o       \
334   $(EMUVIDEO)/stvvdp1.o       \
335   $(EMUVIDEO)/stvvdp2.o       \
331336   $(EMUVIDEO)/tlc34076.o      \
332337   $(EMUVIDEO)/tms34061.o      \
333338   $(EMUVIDEO)/tms9927.o       \
trunk/src/emu/machine/stvcd.c
r0r20947
1/***************************************************************************
2
3  machine/stvcd.c - Sega Saturn and ST-V CD-ROM handling
4
5  Another tilt at the windmill in 2011 by R. Belmont.
6
7  Status: All known discs at least load their executable, and many load
8          some data files successfully, but there are other problems.
9
10  Information sources:
11  - Tyranid's document
12  - A commented disassembly I made of the Saturn BIOS's CD code
13  - Yabuse's cs2.c
14  - The ISO/IEC "Yellow Book" CD-ROM standard, 1995 version
15
16  Address is mostly in terms of FAD (Frame ADdress).
17  FAD is absolute number of frames from the start of the disc.
18  In other words, FAD = LBA + 150; FAD is the same units as
19  LBA except it counts starting at absolute zero instead of
20  the first sector (00:02:00 in MSF format).
21
22***************************************************************************/
23
24#include "emu.h"
25#include "imagedev/chd_cd.h"
26#include "includes/stv.h"
27#include "cdrom.h"
28#include "sound/cdda.h"
29#include "debugger.h"
30#include "coreutil.h"
31
32// super-verbose
33#if 0
34#define CDROM_LOG(x) printf x;
35#else
36#define CDROM_LOG(x)
37#endif
38
39// HIRQ definitions
40#define CMOK 0x0001 // command dispatch possible
41#define DRDY 0x0002 // data transfer preparations complete
42#define CSCT 0x0004 // finished reading 1 sector
43#define BFUL 0x0008 // CD buffer full
44#define PEND 0x0010 // CD playback completed
45#define DCHG 0x0020 // disc change / tray open
46#define ESEL 0x0040 // selector settings processing complete
47#define EHST 0x0080 // host input/output processing complete
48#define ECPY 0x0100 // duplication/move processing complete
49#define EFLS 0x0200 // file system processing complete
50#define SCDQ 0x0400 // subcode Q update completed
51#define MPED 0x0800 // MPEG-related processing complete
52#define MPCM 0x1000 // MPEG action uncertain
53#define MPST 0x2000 // MPEG interrupt status report
54
55// CD status (hi byte of CR1) definitions:
56// (these defines are shifted up 8)
57#define CD_STAT_BUSY     0x0000     // status change in progress
58#define CD_STAT_PAUSE    0x0100     // CD block paused (temporary stop)
59#define CD_STAT_STANDBY  0x0200     // CD drive stopped
60#define CD_STAT_PLAY     0x0300     // CD play in progress
61#define CD_STAT_SEEK     0x0400     // drive seeking
62#define CD_STAT_SCAN     0x0500     // drive scanning
63#define CD_STAT_OPEN     0x0600     // tray is open
64#define CD_STAT_NODISC   0x0700     // no disc present
65#define CD_STAT_RETRY    0x0800     // read retry in progress
66#define CD_STAT_ERROR    0x0900     // read data error occurred
67#define CD_STAT_FATAL    0x0a00     // fatal error (hard reset required)
68#define CD_STAT_PERI     0x2000     // periodic response if set, else command response
69#define CD_STAT_TRANS    0x4000     // data transfer request if set
70#define CD_STAT_WAIT     0x8000     // waiting for command if set, else executed immediately
71#define CD_STAT_REJECT   0xff00     // ultra-fatal error.
72
73/* FIXME: assume Saturn CD-ROMs to have a 2 secs pre-gap for now. */
74int saturn_state::get_track_index(void)
75{
76   UINT32 rel_fad;
77   UINT8 track;
78
79   if(cdrom_get_track_type(cdrom, cdrom_get_track(cdrom, cd_curfad)) != CD_TRACK_AUDIO)
80      return 1;
81
82   track = cdrom_get_track( cdrom, cd_curfad );
83
84   rel_fad = cd_curfad - cdrom_get_track_start( cdrom, track );
85
86   if(rel_fad < 150)
87      return 0;
88
89   return 1;
90}
91
92void saturn_state::cr_standard_return(UINT16 cur_status)
93{
94   cr1 = cur_status | (playtype << 7) | 0x00 | (cdda_repeat_count & 0xf); //options << 4 | repeat & 0xf
95   cr2 = (cur_track == 0xff) ? 0xffff : (cdrom_get_adr_control(cdrom, cur_track)<<8 | cur_track); // TODO: fix current track
96   cr3 = (get_track_index()<<8) | (cd_curfad>>16); //index & 0xff00
97   cr4 = cd_curfad;
98   cd_stat |= CD_STAT_PERI;
99}
100
101void saturn_state::cd_exec_command( void )
102{
103   UINT32 temp;
104
105   if(cr1 != 0 &&
106      ((cr1 & 0xff00) != 0x5100) &&
107      ((cr1 & 0xff00) != 0x5200) &&
108      ((cr1 & 0xff00) != 0x5300) &&
109      1)
110      printf("CD: command exec %04x %04x %04x %04x %04x (stat %04x)\n", hirqreg, cr1, cr2, cr3, cr4, cd_stat);
111
112   switch (cr1 & 0xff00)
113   {
114      case 0x0000:
115         //CDROM_LOG(("%s:CD: Get Status\n", machine.describe_context()))
116         hirqreg |= CMOK;
117         cr_standard_return(cd_stat);
118         //CDROM_LOG(("   = %04x %04x %04x %04x %04x\n", hirqreg, cr1, cr2, cr3, cr4))
119         break;
120
121      case 0x0100:
122         CDROM_LOG(("%s:CD: Get Hardware Info\n", machine.describe_context()))
123         hirqreg |= CMOK;
124         cr1 = cd_stat;
125         cr2 = 0x0201;
126         cr3 = 0x0000;
127         cr4 = 0x0400;
128         break;
129
130      case 0x0200:    // Get TOC
131         CDROM_LOG(("%s:CD: Get TOC\n", machine.describe_context()))
132         cd_readTOC();
133         cd_stat = CD_STAT_TRANS|CD_STAT_PAUSE;
134         cr1 = cd_stat;
135         cr2 = 102*2;    // TOC length in words (102 entries @ 2 words/4bytes each)
136         cr3 = 0;
137         cr4 = 0;
138         xferdnum = 0;
139         hirqreg |= (CMOK|DRDY);
140         break;
141
142      case 0x0300:    // get session info (lower byte = session # to get?)
143                  // bios is interested in returns in cr3 and cr4
144                  // cr3 should be data track #
145                  // cr4 must be > 1 and < 100 or bios gets angry.
146         CDROM_LOG(("%s:CD: Get Session Info\n", machine.describe_context()))
147         cd_readTOC();
148         switch (cr1 & 0xff)
149         {
150            case 0: // get total session info / disc end
151               cd_stat = CD_STAT_PAUSE;
152               cr1 = cd_stat;
153               cr2 = 0;
154               cr3 = 0x0100 | tocbuf[(101*4)+1];
155               cr4 = tocbuf[(101*4)+2]<<8 | tocbuf[(101*4)+3];
156               break;
157
158            case 1: // get total session info / disc start
159               cd_stat = CD_STAT_PAUSE;
160               cr1 = cd_stat;
161               cr2 = 0;
162               cr3 = 0x0100;   // sessions in high byte, session start in lower
163               cr4 = 0;
164               break;
165
166            default:
167               mame_printf_error("CD: Unknown request to Get Session Info %x\n", cr1 & 0xff);
168               cr1 = cd_stat;
169               cr2 = 0;
170               cr3 = 0;
171               cr4 = 0;
172               break;
173         }
174
175         hirqreg |= (CMOK);
176         break;
177
178      /* TODO: double check this */
179      case 0x0400:    // initialize CD system
180            // CR1 & 1 = reset software
181            // CR1 & 2 = decode RW subcode
182            // CR1 & 4 = don't confirm mode 2 subheader
183            // CR1 & 8 = retry reading mode 2 sectors
184            // CR1 & 10 = force single-speed
185            // CR1 & 80 = no change flag (done by Assault Suit Leynos 2)
186         CDROM_LOG(("%s:CD: Initialize CD system\n", machine.describe_context()))
187         if((cr1 & 0x81) == 0x00) //guess
188         {
189            if(((cd_stat & 0x0f00) != CD_STAT_NODISC) && ((cd_stat & 0x0f00) != CD_STAT_OPEN))
190            {
191               cd_stat = CD_STAT_PAUSE;
192               cd_curfad = 150;
193               //cur_track = 1;
194               fadstoplay = 0;
195            }
196            in_buffer = 0;
197            buffull = 0;
198            hirqreg &= 0xffe5;
199            cd_speed = (cr1 & 0x10) ? 1 : 2;
200
201            /* reset filter connections */
202            /* Guess: X-Men COTA sequence is 0x48->0x48->0x04(01)->0x04(00)->0x30 then 0x10, without this game throws a FAD reject error */
203            /* X-Men vs. SF is even fussier, sequence is  0x04 (1) 0x04 (0) 0x03 (0) 0x03 (1) 0x30 */
204            #if 0
205            for(i=0;i<MAX_FILTERS;i++)
206            {
207               filters[i].fad = 0;
208               filters[i].range = 0xffffffff;
209               filters[i].mode = 0;
210               filters[i].chan = 0;
211               filters[i].smmask = 0;
212               filters[i].cimask = 0;
213               filters[i].fid = 0;
214               filters[i].smval = 0;
215               filters[i].cival = 0;
216            }
217            #endif
218
219            /* reset CD device connection */
220            //cddevice = (filterT *)NULL;
221         }
222
223         hirqreg |= (CMOK|ESEL);
224         cr_standard_return(cd_stat);
225         break;
226
227      case 0x0600:    // end data transfer (TODO: needs to be worked on!)
228            // returns # of bytes transfered (24 bits) in
229            // low byte of cr1 (MSB) and cr2 (middle byte, LSB)
230         CDROM_LOG(("%s:CD: End data transfer (%d bytes xfer'd)\n", machine.describe_context(), xferdnum))
231
232         // clear the "transfer" flag
233         cd_stat &= ~CD_STAT_TRANS;
234
235         if (xferdnum)
236         {
237            cr1 = (cd_stat) | ((xferdnum>>17) & 0xff);
238            cr2 = (xferdnum>>1)&0xffff;
239            cr3 = 0;
240            cr4 = 0;
241         }
242         else
243         {
244            printf("No xferdnum error\n");
245            cr1 = (cd_stat) | (0xff);   // is this right?
246            cr2 = 0xffff;
247            cr3 = 0;
248            cr4 = 0;
249         }
250
251         // try to clean up any transfers still in progress
252         switch (xfertype32)
253         {
254            case XFERTYPE32_GETSECTOR:
255               hirqreg |= EHST;
256               break;
257
258            case XFERTYPE32_GETDELETESECTOR:
259               if (transpart->size > 0)
260               {
261                  INT32 i;
262
263                  xfertype32 = XFERTYPE32_INVALID;
264
265                  // deallocate the blocks
266                  for (i = xfersectpos; i < xfersectpos+xfersectnum; i++)
267                  {
268                     cd_free_block(transpart->blocks[i]);
269                     transpart->blocks[i] = (blockT *)NULL;
270                     transpart->bnum[i] = 0xff;
271                  }
272
273                  // defrag what's left
274                  cd_defragblocks(transpart);
275
276                  // clean up our state
277                  transpart->size -= xferdnum;
278                  transpart->numblks -= xfersectnum;
279
280                  if (freeblocks == 200)
281                  {
282                     sectorstore = 0;
283                  }
284
285                  hirqreg |= EHST;
286               }
287               break;
288
289            default:
290               break;
291         }
292
293
294         xferdnum = 0;
295         hirqreg |= CMOK;
296
297         CDROM_LOG(("   = %04x %04x %04x %04x %04x\n", hirqreg, cr1, cr2, cr3, cr4))
298         break;
299
300      case 0x1000: // Play Disc.  FAD is in lowest 7 bits of cr1 and all of cr2.
301         UINT32 start_pos,end_pos;
302         UINT8 play_mode;
303
304         CDROM_LOG(("%s:CD: Play Disc\n",   machine.describe_context()))
305         cd_stat = CD_STAT_PLAY;
306
307         play_mode = (cr3 >> 8) & 0x7f;
308
309         if (!(cr3 & 0x8000))    // preserve current position if bit 7 set
310         {
311            start_pos = ((cr1&0xff)<<16) | cr2;
312            end_pos = ((cr3&0xff)<<16) | cr4;
313
314            if (start_pos & 0x800000)
315            {
316               if (start_pos != 0xffffff)
317                  cd_curfad = start_pos & 0xfffff;
318
319               printf("fad mode\n");
320               cur_track = cdrom_get_track(cdrom, cd_curfad-150);
321            }
322            else
323            {
324               // track mode
325               if(((start_pos)>>8) != 0)
326               {
327                  cur_track = (start_pos)>>8;
328                  cd_curfad = cdrom_get_track_start(cdrom, cur_track-1);
329               }
330               else
331               {
332                  /* TODO: Waku Waku 7 sets up track 0, that basically doesn't make any sense. Just skip it for now. */
333                  popmessage("Warning: track mode == 0, contact MAMEdev");
334                  cr_standard_return(cd_stat);
335                  hirqreg |= (CMOK);
336                  return;
337               }
338
339               printf("track mode %d\n",cur_track);
340
341            }
342
343            if (end_pos & 0x800000)
344            {
345               if (end_pos != 0xffffff)
346                  fadstoplay = end_pos & 0xfffff;
347            }
348            else
349            {
350               UINT8 end_track;
351
352               end_track = (end_pos)>>8;
353               fadstoplay = cdrom_get_track_start(cdrom, end_track) - cd_curfad;
354            }
355         }
356         else    // play until the end of the disc
357         {
358            start_pos = ((cr1&0xff)<<16) | cr2;
359            end_pos = ((cr3&0xff)<<16) | cr4;
360
361            if(start_pos != 0xffffff)
362            {
363               /* Madou Monogatari sets 0xff80xxxx as end position, needs investigation ... */
364               if(end_pos & 0x800000)
365                  fadstoplay = end_pos & 0xfffff;
366               else
367               {
368                  if(end_pos == 0)
369                     fadstoplay = (cdrom_get_track_start(cdrom, 0xaa)) - cd_curfad;
370                  else
371                     fadstoplay = (cdrom_get_track_start(cdrom, (end_pos & 0xff00) >> 8)) - cd_curfad;
372               }
373               printf("track mode %08x %08x\n",cd_curfad,fadstoplay);
374            }
375            else
376            {
377               /* resume from a pause state */
378               /* TODO: Galaxy Fight calls 10ff ffff ffff ffff, but then it calls 0x04->0x02->0x06->0x11->0x04->0x02->0x06 command sequence
379                  (and current implementation nukes start/end FAD addresses at 0x04). I'm sure that this doesn't work like this, but there could
380                  be countless possible combinations ... */
381               if(fadstoplay == 0)
382               {
383                  cd_curfad = cdrom_get_track_start(cdrom, cur_track-1);
384                  fadstoplay = cdrom_get_track_start(cdrom, cur_track) - cd_curfad;
385               }
386               printf("track resume %08x %08x\n",cd_curfad,fadstoplay);
387            }
388         }
389
390         CDROM_LOG(("CD: Play Disc: start %x length %x\n", cd_curfad, fadstoplay))
391
392         cr_standard_return(cd_stat);
393         hirqreg |= (CMOK);
394         oddframe = 0;
395         in_buffer = 0;
396
397         playtype = 0;
398
399         // cdda
400         if(cdrom_get_track_type(cdrom, cdrom_get_track(cdrom, cd_curfad)) == CD_TRACK_AUDIO)
401         {
402            cdda_pause_audio( machine().device( "cdda" ), 0 );
403            //cdda_start_audio( machine.device( "cdda" ), cd_curfad, fadstoplay  );
404            //cdda_repeat_count = 0;
405         }
406
407         if(play_mode != 0x7f)
408            cdda_maxrepeat = play_mode & 0xf;
409         else
410            cdda_maxrepeat = 0;
411
412         cdda_repeat_count = 0;
413
414         break;
415
416      case 0x1100: // disc seek
417         CDROM_LOG(("%s:CD: Disc seek\n",   machine.describe_context()))
418         //printf("%08x %08x %08x %08x\n",cr1,cr2,cr3,cr4);
419         if (cr1 & 0x80)
420         {
421            temp = (cr1&0xff)<<16;  // get FAD to seek to
422            temp |= cr2;
423
424            //cd_curfad = temp;
425
426            if (temp == 0xffffff)
427            {
428               cd_stat = CD_STAT_PAUSE;
429               cdda_pause_audio( machine().device( "cdda" ), 1 );
430            }
431            else
432            {
433               cd_curfad = ((cr1&0x7f)<<16) | cr2;
434               printf("disc seek with params %04x %04x\n",cr1,cr2); //Area 51 sets this up
435            }
436         }
437         else
438         {
439            // is it a valid track?
440            if (cr2 >> 8)
441            {
442               cd_stat = CD_STAT_PAUSE;
443               cur_track = cr2>>8;;
444               cd_curfad = cdrom_get_track_start(cdrom, cur_track-1);
445               cdda_pause_audio( machine().device( "cdda" ), 1 );
446               // (index is cr2 low byte)
447            }
448            else // error!
449            {
450               cd_stat = CD_STAT_STANDBY;
451               cd_curfad = 0xffffffff;
452               cur_track = 0xff;
453               cdda_stop_audio( machine().device( "cdda" ) ); //stop any pending CD-DA
454            }
455         }
456
457
458         hirqreg |= CMOK;
459         cr_standard_return(cd_stat);
460         break;
461
462      case 0x1200: // FFWD / REW
463         //cr1 bit 0 determines if this is a Fast Forward (0) or a Rewind (1) command
464         // ...
465         break;
466
467      case 0x2000: // Get SubCode Q / RW Channel
468         switch(cr1 & 0xff)
469         {
470            case 0: // Get Q
471            {
472               UINT32 msf_abs,msf_rel;
473               UINT8 track;
474               cr1 = cd_stat | 0;
475               cr2 = 10/2;
476               cr3 = 0;
477               cr4 = 0;
478
479               /*
480               Subcode Q info should be:
481               ---- --x- S0
482               ---- ---x S1
483               xxxx ---- [0] Control (bit 7 Pre-emphasis, bit 6: copy permitted, bit 5 undefined, bit 4 number of channels)
484               ---- xxxx [0] address (0x0001 Mode 1)
485               xxxx xxxx [1] track number (1-99, AA lead-out), BCD format
486               xxxx xxxx [2] index (01 lead-out), BCD format
487               xxxx xxxx [3] Time within' track M
488               xxxx xxxx [4] Time within' track S
489               xxxx xxxx [5] Time within' track F
490               xxxx xxxx [6] Zero
491               xxxx xxxx [7] Absolute M
492               xxxx xxxx [8] Absolute S
493               xxxx xxxx [9] Absolute F
494               xxxx xxxx [10] CRCC
495               xxxx xxxx [11] CRCC
496               */
497
498               msf_abs = lba_to_msf_alt( cd_curfad - 150 );
499               track = cdrom_get_track( cdrom, cd_curfad );
500               msf_rel = lba_to_msf_alt( cd_curfad - 150 - cdrom_get_track_start( cdrom, track ) );
501
502               xfertype = XFERTYPE_SUBQ;
503               xfercount = 0;
504               subqbuf[0] = 0x01 | ((cdrom_get_track_type(cdrom, cdrom_get_track(cdrom, track+1)) == CD_TRACK_AUDIO) ? 0x00 : 0x40);
505               subqbuf[1] = dec_2_bcd(track+1);
506               subqbuf[2] = dec_2_bcd(get_track_index());
507               subqbuf[3] = dec_2_bcd((msf_rel >> 16) & 0xff);
508               subqbuf[4] = dec_2_bcd((msf_rel >> 8) & 0xff);
509               subqbuf[5] = dec_2_bcd((msf_rel >> 0) & 0xff);
510               subqbuf[6] = 0;
511               subqbuf[7] = dec_2_bcd((msf_abs >> 16) & 0xff);
512               subqbuf[8] = dec_2_bcd((msf_abs >> 8) & 0xff);
513               subqbuf[9] = dec_2_bcd((msf_abs >> 0) & 0xff);
514            }
515            break;
516
517            case 1: // Get RW
518               cr1 = cd_stat | 0;
519               cr2 = 12;
520               cr3 = 0;
521               cr4 = 0;
522
523               xfertype = XFERTYPE_SUBRW;
524               xfercount = 0;
525
526               /* return null data for now */
527               {
528                  int i;
529
530                  for(i=0;i<12*2;i++)
531                     subrwbuf[i] = 0;
532               }
533               break;
534         }
535         hirqreg |= CMOK|DRDY;
536         break;
537
538      case 0x3000:    // Set CD Device connection
539         {
540            UINT8 parm;
541
542            // get operation
543            parm = cr3>>8;
544
545            CDROM_LOG(("%s:CD: Set CD Device Connection filter # %x\n",   machine.describe_context(), parm))
546
547            cddevicenum = parm;
548
549            if (parm == 0xff)
550            {
551               cddevice = (filterT *)NULL;
552            }
553            else
554            {
555               if (parm < 0x24)
556               {
557                  cddevice = &filters[(cr3>>8)];
558               }
559            }
560
561
562            hirqreg |= (CMOK|ESEL);
563            cr_standard_return(cd_stat);
564         }
565         break;
566
567      case 0x3100:
568         popmessage("Get CD Device Connection, contact MAMEdev");
569         hirqreg |= CMOK;
570         break;
571
572      case 0x3200:    // Last Buffer Destination
573         cr1 = cd_stat | 0;
574         cr2 = 0;
575         cr3 = lastbuf << 8;
576         cr4 = 0;
577         hirqreg |= (CMOK);
578         break;
579
580      case 0x4000:    // Set Filter Range
581                  // cr1 low + cr2 = FAD0, cr3 low + cr4 = FAD1
582                  // cr3 hi = filter num.
583         {
584            UINT8 fnum = (cr3>>8)&0xff;
585
586            CDROM_LOG(("%s:CD: Set Filter Range\n",   machine.describe_context()))
587
588            filters[fnum].fad = ((cr1 & 0xff)<<16) | cr2;
589            filters[fnum].range = ((cr3 & 0xff)<<16) | cr4;
590
591            printf("%08x %08x %d\n",filters[fnum].fad,filters[fnum].range,fnum);
592
593            hirqreg |= (CMOK|ESEL);
594            cr_standard_return(cd_stat);
595         }
596         break;
597
598      case 0x4100:
599         popmessage("Get Filter Range, contact MAMEdev");
600         hirqreg |= CMOK;
601         break;
602
603      case 0x4200:    // Set Filter Subheader conditions
604         {
605            UINT8 fnum = (cr3>>8)&0xff;
606
607            CDROM_LOG(("%s:CD: Set Filter Subheader conditions %x => chan %x masks %x fid %x vals %x\n", machine.describe_context(), fnum, cr1&0xff, cr2, cr3&0xff, cr4))
608
609            filters[fnum].chan = cr1 & 0xff;
610            filters[fnum].smmask = (cr2>>8)&0xff;
611            filters[fnum].cimask = cr2&0xff;
612            filters[fnum].fid = cr3&0xff;
613            filters[fnum].smval = (cr4>>8)&0xff;
614            filters[fnum].cival = cr4&0xff;
615
616            hirqreg |= (CMOK|ESEL);
617            cr_standard_return(cd_stat);
618         }
619         break;
620
621      case 0x4300:    // Get Filter Subheader conditions
622         {
623            UINT8 fnum = (cr3>>8)&0xff;
624
625            CDROM_LOG(("%s:CD: Set Filter Subheader conditions %x => chan %x masks %x fid %x vals %x\n", machine.describe_context(), fnum, cr1&0xff, cr2, cr3&0xff, cr4))
626
627            cr1 = cd_stat | (filters[fnum].chan & 0xff);
628            cr2 = (filters[fnum].smmask << 8) | (filters[fnum].cimask & 0xff);
629            cr3 = filters[fnum].fid;
630            cr4 = (filters[fnum].smval << 8) | (filters[fnum].cival & 0xff);
631
632            hirqreg |= (CMOK|ESEL);
633         }
634         break;
635
636      case 0x4400:    // Set Filter Mode
637         {
638            UINT8 fnum = (cr3>>8)&0xff;
639            UINT8 mode = (cr1 & 0xff);
640
641            // initialize filter?
642            if (mode & 0x80)
643            {
644               memset(&filters[fnum], 0, sizeof(filterT));
645            }
646            else
647            {
648               filters[fnum].mode = mode;
649            }
650
651            CDROM_LOG(("%s:CD: Set Filter Mode filt %x mode %x\n", machine.describe_context(), fnum, mode))
652            hirqreg |= (CMOK|ESEL);
653            cr_standard_return(cd_stat);
654         }
655         break;
656
657      case 0x4500:    // Get Filter Mode
658         {
659            UINT8 fnum = (cr3>>8)&0xff;
660
661            cr1 = cd_stat | (filters[fnum].mode & 0xff);
662            cr2 = 0;
663            cr3 = 0;
664            cr4 = 0;
665            hirqreg |= (CMOK|ESEL);
666         }
667         break;
668
669      case 0x4600:    // Set Filter Connection
670         {
671            UINT8 fnum = (cr3>>8)&0xff;
672
673            CDROM_LOG(("%s:CD: Set Filter Connection %x => mode %x parm %04x\n", machine.describe_context(), fnum, cr1 & 0xf, cr2))
674
675            // set true condition?
676            if (cr1 & 1)
677            {
678               filters[fnum].condtrue = (cr2>>8)&0xff;
679            }
680            else if (cr1 & 2)   // set false condition
681            {
682               filters[fnum].condfalse = cr2&0xff;
683            }
684
685            hirqreg |= (CMOK|ESEL);
686            cr_standard_return(cd_stat);
687         }
688         break;
689
690      case 0x4800:    // Reset Selector
691         {
692         int i,j;
693
694         CDROM_LOG(("%s:CD: Reset Selector\n",   machine.describe_context()))
695
696         if((cr1 & 0xff) == 0x00)
697         {
698            UINT8 bufnum = cr3>>8;
699
700            if(bufnum < MAX_FILTERS)
701            {
702               for (i = 0; i < MAX_BLOCKS; i++)
703               {
704                  cd_free_block(partitions[bufnum].blocks[i]);
705                  partitions[bufnum].blocks[i] = (blockT *)NULL;
706                  partitions[bufnum].bnum[i] = 0xff;
707               }
708
709               partitions[bufnum].size = -1;
710               partitions[bufnum].numblks = 0;
711            }
712
713            // TODO: buffer full flag
714
715            if (freeblocks == 200) { sectorstore = 0; }
716
717            hirqreg |= (CMOK|ESEL);
718            cr_standard_return(cd_stat);
719            return;
720         }
721
722         /* reset false filter output conditions */
723         if(cr1 & 0x80)
724         {
725            for(i=0;i<MAX_FILTERS;i++)
726               filters[i].condfalse = 0xff;
727         }
728
729         /* reset true filter output conditions */
730         if(cr1 & 0x40)
731         {
732            for(i=0;i<MAX_FILTERS;i++)
733               filters[i].condtrue = i;
734         }
735
736         /* reset filter conditions*/
737         if(cr1 & 0x10)
738         {
739            for(i=0;i<MAX_FILTERS;i++)
740            {
741               filters[i].fad = 0;
742               filters[i].range = 0xffffffff;
743               filters[i].mode = 0;
744               filters[i].chan = 0;
745               filters[i].smmask = 0;
746               filters[i].cimask = 0;
747               filters[i].fid = 0;
748               filters[i].smval = 0;
749               filters[i].cival = 0;
750            }
751         }
752
753         /* reset partition buffer data */
754         if(cr1 & 0x4)
755         {
756            for(i=0;i<MAX_FILTERS;i++)
757            {
758               for (j = 0; j < MAX_BLOCKS; j++)
759               {
760                  cd_free_block(partitions[i].blocks[j]);
761                  partitions[i].blocks[j] = (blockT *)NULL;
762                  partitions[i].bnum[j] = 0xff;
763               }
764
765               partitions[i].size = -1;
766               partitions[i].numblks = 0;
767            }
768
769            buffull = sectorstore = 0;
770         }
771
772         hirqreg |= (CMOK|ESEL);
773         cr_standard_return(cd_stat);
774         }
775         break;
776
777      case 0x5000:    // get Buffer Size
778         cr1 = cd_stat;
779         cr2 = (freeblocks > 200) ? 200 : freeblocks;
780         cr3 = 0x1800;
781         cr4 = 200;
782         CDROM_LOG(("CD: Get Buffer Size = %d\n", cr2))
783         hirqreg |= (CMOK);
784         break;
785
786      case 0x5100:    // get # sectors used in a buffer
787         {
788            UINT32 bufnum = cr3>>8;
789
790            CDROM_LOG(("%s:CD: Get Sector Number (bufno %d) = %d blocks\n",   machine.describe_context(), bufnum, cr4))
791            cr1 = cd_stat;
792            cr2 = 0;
793            cr3 = 0;
794
795            // is the partition empty?
796            if (partitions[bufnum].size == -1)
797            {
798               cr4 = 0;
799            }
800            else
801            {
802               cr4 = partitions[bufnum].numblks;
803            }
804
805            hirqreg |= (CMOK|DRDY);
806         }
807         break;
808
809      case 0x5200:    // calculate actual size
810         {
811            UINT32 bufnum = cr3>>8;
812            UINT32 sectoffs = cr2;
813            UINT32 numsect = cr4;
814
815            CDROM_LOG(("%s:CD: Calculate actual size: buf %x offs %x numsect %x\n", machine.describe_context(), bufnum, sectoffs, numsect))
816
817            calcsize = 0;
818            if (partitions[bufnum].size != -1)
819            {
820               INT32 i;
821
822               for (i = 0; i < numsect; i++)
823               {
824                  if (partitions[bufnum].blocks[sectoffs+i])
825                  {
826                     calcsize += (partitions[bufnum].blocks[sectoffs+i]->size / 2);
827                  }
828               }
829            }
830
831            hirqreg |= (CMOK|ESEL);
832            cr_standard_return(cd_stat);
833         }
834         break;
835
836      case 0x5300:    // get actual block size
837         CDROM_LOG(("%s:CD: Get actual block size\n", machine.describe_context()))
838         hirqreg |= (CMOK|ESEL);
839         cr1 = cd_stat | ((calcsize>>16)&0xff);
840         cr2 = (calcsize & 0xffff);
841         cr3 = 0;
842         cr4 = 0;
843         break;
844
845      case 0x5400:    // get sector info
846         {
847            UINT32 sectoffs = cr2 & 0xff;
848            UINT32 bufnum = cr3>>8;
849
850            if (bufnum >= MAX_FILTERS || !partitions[bufnum].blocks[sectoffs])
851            {
852               cr1 |= CD_STAT_REJECT & 0xff00;
853               hirqreg |= (CMOK|ESEL);
854               printf("Get sector info reject\n");
855            }
856            else
857            {
858               cr1 = cd_stat | ((partitions[bufnum].blocks[sectoffs]->FAD >> 16) & 0xff);
859               cr2 = partitions[bufnum].blocks[sectoffs]->FAD & 0xffff;
860               cr3 = ((partitions[bufnum].blocks[sectoffs]->fnum & 0xff) << 8) | (partitions[bufnum].blocks[sectoffs]->chan & 0xff);
861               cr4 = ((partitions[bufnum].blocks[sectoffs]->subm & 0xff) << 8) | (partitions[bufnum].blocks[sectoffs]->cinf & 0xff);
862               hirqreg |= (CMOK|ESEL);
863            }
864         }
865         break;
866
867      case 0x6000:    // set sector length
868         CDROM_LOG(("%s:CD: Set sector length\n",   machine.describe_context()))
869
870         switch (cr1 & 0xff)
871         {
872            case 0:
873               sectlenin = 2048;
874               break;
875            case 1:
876               sectlenin = 2336;
877               break;
878            case 2:
879               sectlenin = 2340;
880               break;
881            case 3:
882               sectlenin = 2352;
883               break;
884         }
885
886         switch ((cr2>>8) & 0xff)
887         {
888            case 0:
889               sectlenout = 2048;
890               break;
891            case 1:
892               sectlenout = 2336;
893               break;
894            case 2:
895               sectlenout = 2340;
896               break;
897            case 3:
898               sectlenout = 2352;
899               break;
900         }
901         hirqreg |= (CMOK|ESEL);
902         cr_standard_return(cd_stat);
903         break;
904
905      case 0x6100:    // get sector data
906         {
907            UINT32 sectnum = cr4;
908            UINT32 sectofs = cr2;
909            UINT32 bufnum = cr3>>8;
910
911            CDROM_LOG(("%s:CD: Get sector data (SN %d SO %d BN %d)\n",   machine.describe_context(), sectnum, sectofs, bufnum))
912
913            if (bufnum >= MAX_FILTERS)
914            {
915               printf("CD: invalid buffer number\n");
916               /* TODO: why this is happening? */
917               cr_standard_return(CD_STAT_REJECT);
918               hirqreg |= (CMOK|EHST);
919               return;
920            }
921
922            if (partitions[bufnum].numblks == 0)
923            {
924               printf("CD: buffer is empty\n");
925               /* TODO: why this is happening? */
926               cr_standard_return(CD_STAT_REJECT);
927               hirqreg |= (CMOK|EHST);
928               return;
929            }
930
931            cd_getsectoroffsetnum(bufnum, &sectofs, &sectnum);
932
933            xfertype32 = XFERTYPE32_GETSECTOR;
934            xferoffs = 0;
935            xfersect = 0;
936            xferdnum = 0;
937            xfersectpos = sectofs;
938            xfersectnum = sectnum;
939            transpart = &partitions[bufnum];
940
941            cd_stat |= CD_STAT_TRANS;
942            cr_standard_return(cd_stat);
943            hirqreg |= (CMOK|EHST|DRDY);
944         }
945         break;
946
947      case 0x6200:    // delete sector data
948         {
949            UINT32 sectnum = cr4;
950            UINT32 sectofs = cr2;
951            UINT32 bufnum = cr3>>8;
952            INT32 i;
953
954            CDROM_LOG(("%s:CD: Delete sector data (SN %d SO %d BN %d)\n",   machine.describe_context(), sectnum, sectofs, bufnum))
955
956            if (bufnum >= MAX_FILTERS)
957            {
958               printf("CD: invalid buffer number\n");
959               /* TODO: why this is happening? */
960               cr_standard_return(CD_STAT_REJECT);
961               hirqreg |= (CMOK|EHST);
962               return;
963            }
964
965            if (partitions[bufnum].numblks == 0)
966            {
967               printf("CD: buffer is empty\n");
968               /* TODO: why this is happening? */
969               cr_standard_return(CD_STAT_REJECT);
970               hirqreg |= (CMOK|EHST);
971               return;
972            }
973
974            cd_getsectoroffsetnum(bufnum, &sectofs, &sectnum);
975
976            for (i = sectofs; i < (sectofs + sectnum); i++)
977            {
978               partitions[bufnum].size -= partitions[bufnum].blocks[i]->size;
979               cd_free_block(partitions[bufnum].blocks[i]);
980               partitions[bufnum].blocks[i] = (blockT *)NULL;
981               partitions[bufnum].bnum[i] = 0xff;
982            }
983
984            cd_defragblocks(&partitions[bufnum]);
985
986            partitions[bufnum].numblks -= sectnum;
987
988            if (freeblocks == 200)
989            {
990               sectorstore = 0;
991            }
992
993            cd_stat &= ~CD_STAT_TRANS;
994            cr_standard_return(cd_stat);
995            hirqreg |= (CMOK|EHST);
996         }
997         break;
998
999      case 0x6300:    // get then delete sector data
1000         {
1001            UINT32 sectnum = cr4;
1002            UINT32 sectofs = cr2;
1003            UINT32 bufnum = cr3>>8;
1004
1005            CDROM_LOG(("%s:CD: Get and delete sector data (SN %d SO %d BN %d)\n",   machine.describe_context(), sectnum, sectofs, bufnum))
1006
1007            if (bufnum >= MAX_FILTERS)
1008            {
1009               printf("CD: invalid buffer number\n");
1010               /* TODO: why this is happening? */
1011               cr_standard_return(CD_STAT_REJECT);
1012               hirqreg |= (CMOK|EHST);
1013               return;
1014            }
1015
1016            if (partitions[bufnum].numblks == 0)
1017            {
1018               printf("CD: buffer is empty\n");
1019               /* TODO: why this is happening? */
1020               cr_standard_return(CD_STAT_REJECT);
1021               hirqreg |= (CMOK|EHST);
1022               return;
1023            }
1024
1025            cd_getsectoroffsetnum(bufnum, &sectofs, &sectnum);
1026
1027            xfertype32 = XFERTYPE32_GETDELETESECTOR;
1028            xferoffs = 0;
1029            xfersect = 0;
1030            xferdnum = 0;
1031            xfersectpos = sectofs;
1032            xfersectnum = sectnum;
1033            transpart = &partitions[bufnum];
1034
1035            cd_stat |= CD_STAT_TRANS;
1036            cr_standard_return(cd_stat);
1037            hirqreg |= (CMOK|EHST|DRDY);
1038         }
1039         break;
1040
1041      case 0x6400:    // put sector data
1042         /* TODO: After Burner 2, Out Run, Fantasy Zone and Dungeon Master Nexus trips this */
1043         // ...
1044         {
1045            //UINT8 sectnum = cr4 & 0xff;
1046            //UINT8 filtnum = cr3>>8;
1047
1048
1049         }
1050
1051         hirqreg |= (CMOK|EHST);
1052         cr_standard_return(cd_stat);
1053         break;
1054
1055      case 0x6500:
1056         popmessage("Copy Sector data, contact MAMEdev");
1057         hirqreg |= (CMOK);
1058         break;
1059
1060      case 0x6600:    // move sector data
1061         /* TODO: Sword & Sorcery / Riglord Saga 2 */
1062         {
1063            //UINT8 src_filter = (cr3>>8)&0xff;
1064            //UINT8 dst_filter = cr4;
1065         }
1066
1067         hirqreg |= (CMOK|ECPY);
1068         cr_standard_return(cd_stat);
1069         break;
1070
1071
1072      case 0x6700:    // get copy error
1073         CDROM_LOG(("%s:CD: Get copy error\n",   machine.describe_context()))
1074         printf("Get copy error\n");
1075         cr1 = cd_stat;
1076         cr2 = 0;
1077         cr3 = 0;
1078         cr4 = 0;
1079         hirqreg |= (CMOK);
1080         break;
1081
1082      case 0x7000:    // change directory
1083         CDROM_LOG(("%s:CD: Change Directory\n",   machine.describe_context()))
1084         hirqreg |= (CMOK|EFLS);
1085
1086         temp = (cr3&0xff)<<16;
1087         temp |= cr4;
1088
1089         read_new_dir(temp);
1090         cr_standard_return(cd_stat);
1091         break;
1092
1093      case 0x7100:    // Read directory entry
1094         CDROM_LOG(("%s:CD: Read Directory Entry\n",   machine.describe_context()))
1095//          UINT32 read_dir;
1096
1097//          read_dir = ((cr3&0xff)<<16)|cr4;
1098
1099         if((cr3 >> 8) < 0x24)
1100            cddevice = &filters[cr3 >> 8];
1101         else
1102            cddevice = (filterT *)NULL;
1103
1104         /* TODO:  */
1105         //read_new_dir(read_dir - 2);
1106
1107         cr_standard_return(cd_stat);
1108         hirqreg |= (CMOK|EFLS);
1109         break;
1110
1111      case 0x7200:    // Get file system scope
1112         CDROM_LOG(("CD: Get file system scope\n"))
1113         hirqreg |= (CMOK|EFLS);
1114         cr1 = cd_stat;
1115         cr2 = numfiles; // # of files in directory
1116         cr3 = 0x0100;   // report directory held
1117         cr4 = firstfile;    // first file id
1118         printf("%04x %04x %04x %04x\n",cr1,cr2,cr3,cr4);
1119         break;
1120
1121      case 0x7300:    // Get File Info
1122         CDROM_LOG(("%s:CD: Get File Info\n",   machine.describe_context()))
1123         cd_stat |= CD_STAT_TRANS;
1124         cd_stat &= 0xff00;      // clear top byte of return value
1125         playtype = 0;
1126         cdda_repeat_count = 0;
1127         hirqreg |= (CMOK|DRDY);
1128
1129         temp = (cr3&0xff)<<16;
1130         temp |= cr4;
1131
1132         if (temp == 0xffffff)   // special
1133         {
1134            xfertype = XFERTYPE_FILEINFO_254;
1135            xfercount = 0;
1136
1137            cr1 = cd_stat;
1138            cr2 = 0x5f4;
1139            cr3 = 0;
1140            cr4 = 0;
1141         }
1142         else
1143         {
1144            cr1 = cd_stat;
1145            cr2 = 6;    // 6 words for single file
1146                     // first 4 bytes = FAD address
1147                     // second 4 bytes = length
1148                     // last 4 bytes:
1149                     // - unit size
1150                     // - gap size
1151                     // - file #
1152                     // attributes flags
1153
1154            cr3 = 0;
1155            cr4 = 0;
1156
1157            printf("%08x %08x\n",curdir[temp].firstfad,curdir[temp].length);
1158            // first 4 bytes = FAD
1159            finfbuf[0] = (curdir[temp].firstfad>>24)&0xff;
1160            finfbuf[1] = (curdir[temp].firstfad>>16)&0xff;
1161            finfbuf[2] = (curdir[temp].firstfad>>8)&0xff;
1162            finfbuf[3] = (curdir[temp].firstfad&0xff);
1163            // second 4 bytes = length of file
1164            finfbuf[4] = (curdir[temp].length>>24)&0xff;
1165            finfbuf[5] = (curdir[temp].length>>16)&0xff;
1166            finfbuf[6] = (curdir[temp].length>>8)&0xff;
1167            finfbuf[7] = (curdir[temp].length&0xff);
1168            finfbuf[8] = curdir[temp].interleave_gap_size;
1169            finfbuf[9] = curdir[temp].file_unit_size;
1170            finfbuf[10] = temp;
1171            finfbuf[11] = curdir[temp].flags;
1172
1173            xfertype = XFERTYPE_FILEINFO_1;
1174            xfercount = 0;
1175         }
1176         CDROM_LOG(("   = %04x %04x %04x %04x %04x\n", hirqreg, cr1, cr2, cr3, cr4))
1177         break;
1178
1179      case 0x7400:    // Read File
1180         CDROM_LOG(("%s:CD: Read File\n",   machine.describe_context()))
1181         UINT16 file_offset,file_filter,file_id,file_size;
1182
1183         file_offset = ((cr1 & 0xff)<<8)|(cr2 & 0xff); /* correct? */
1184         file_filter = cr3 >> 8;
1185         file_id = ((cr3 & 0xff) << 16)|(cr4);
1186         file_size = ((curdir[file_id].length + sectlenin - 1) / sectlenin) - file_offset;
1187
1188         cd_stat = CD_STAT_PLAY|0x80;    // set "cd-rom" bit
1189         cd_curfad = (curdir[file_id].firstfad + file_offset);
1190         fadstoplay = file_size;
1191         if(file_filter < 0x24)
1192            cddevice = &filters[file_filter];
1193         else
1194            cddevice = (filterT *)NULL;
1195
1196         printf("Read file %08x (%08x %08x) %02x %d\n",curdir[file_id].firstfad,cd_curfad,fadstoplay,file_filter,sectlenin);
1197
1198         cr_standard_return(cd_stat);
1199
1200         oddframe = 0;
1201         in_buffer = 0;
1202
1203         playtype = 1;
1204
1205         hirqreg |= (CMOK|EHST);
1206
1207         break;
1208
1209      case 0x7500:
1210         CDROM_LOG(("%s:CD: Abort File\n",   machine.describe_context()))
1211         // bios expects "2bc" mask to work against this
1212         hirqreg |= (CMOK|EFLS);
1213         sectorstore = 0;
1214         xfertype32 = XFERTYPE32_INVALID;
1215         xferdnum = 0;
1216         if(((cd_stat & 0x0f00) != CD_STAT_NODISC) && ((cd_stat & 0x0f00) != CD_STAT_OPEN))
1217            cd_stat = CD_STAT_PAUSE;    // force to pause
1218         cr_standard_return(cd_stat);
1219         break;
1220
1221      case 0xe000:    // appears to be copy protection check.  needs only to return OK.
1222         CDROM_LOG(("%s:CD: Verify copy protection\n",   machine.describe_context()))
1223         if(((cd_stat & 0x0f00) != CD_STAT_NODISC) && ((cd_stat & 0x0f00) != CD_STAT_OPEN))
1224            cd_stat = CD_STAT_PAUSE;
1225//          cr1 = cd_stat;  // necessary to pass
1226//          cr2 = 0x4;
1227//          hirqreg |= (CMOK|EFLS|CSCT);
1228         sectorstore = 1;
1229         hirqreg = 0xfc5;
1230         cr_standard_return(cd_stat);
1231         break;
1232
1233      case 0xe100:    // get disc region
1234         CDROM_LOG(("%s:CD: Get disc region\n",   machine.describe_context()))
1235         if(cd_stat != CD_STAT_NODISC && cd_stat != CD_STAT_OPEN)
1236            cd_stat = CD_STAT_PAUSE;
1237         cr1 = cd_stat;  // necessary to pass
1238         cr2 = 0x4;      // (must return this value to pass bios checks)
1239         cr3 = 0;
1240         cr4 = 0;
1241         hirqreg |= (CMOK);
1242//          cr_standard_return(cd_stat);
1243         break;
1244
1245      default:
1246         CDROM_LOG(("CD: Unknown command %04x\n", cr1))
1247         hirqreg |= (CMOK);
1248         break;
1249   }
1250}
1251
1252TIMER_DEVICE_CALLBACK_MEMBER( saturn_state::stv_sh1_sim )
1253{
1254   sh1_timer->adjust(attotime::from_hz(16667));
1255
1256   if((cmd_pending == 0xf) && (!(hirqreg & CMOK)))
1257   {
1258      cd_exec_command();
1259      return;
1260   }
1261
1262   /* TODO: doesn't boot if a disk isn't in? */
1263   /* TODO: Check out when this really happens. (Daytona USA original version definitely wants it to be on).*/
1264   //if(((cd_stat & 0x0f00) != CD_STAT_NODISC) && ((cd_stat & 0x0f00) != CD_STAT_OPEN))
1265      hirqreg |= SCDQ;
1266
1267   if(cd_stat & CD_STAT_PERI)
1268   {
1269      cr_standard_return(cd_stat);
1270   }
1271}
1272
1273TIMER_DEVICE_CALLBACK_MEMBER( saturn_state::stv_sector_cb )
1274{
1275   //sector_timer->reset();
1276
1277   //popmessage("%08x %08x %d %d",cd_curfad,fadstoplay,cmd_pending,cd_speed);
1278
1279   cd_playdata();
1280
1281   if(cdrom_get_track_type(cdrom, cdrom_get_track(cdrom, cd_curfad)) == CD_TRACK_AUDIO)
1282      sector_timer->adjust(attotime::from_hz(75));    // 75 sectors / second = 150kBytes/second (cdda track ignores cd_speed setting)
1283   else
1284      sector_timer->adjust(attotime::from_hz(75*cd_speed));   // 75 / 150 sectors / second = 150 / 300kBytes/second
1285}
1286
1287// global functions
1288void saturn_state::stvcd_reset( void )
1289{
1290   INT32 i, j;
1291
1292   hirqmask = 0xffff;
1293   hirqreg = 0xffff;
1294   cr1 = 'C';
1295   cr2 = ('D'<<8) | 'B';
1296   cr3 = ('L'<<8) | 'O';
1297   cr4 = ('C'<<8) | 'K';
1298   cd_stat = CD_STAT_PAUSE;
1299   cd_stat |= CD_STAT_PERI;
1300   cur_track = 0xff;
1301
1302   if (curdir != (direntryT *)NULL)
1303      auto_free(machine(), curdir);
1304   curdir = (direntryT *)NULL;     // no directory yet
1305
1306   xfertype = XFERTYPE_INVALID;
1307   xfertype32 = XFERTYPE32_INVALID;
1308
1309   // reset flag vars
1310   buffull = sectorstore = 0;
1311
1312   freeblocks = 200;
1313
1314   sectlenin = sectlenout = 2048;
1315
1316   lastbuf = 0xff;
1317
1318   // reset buffer partitions
1319   for (i = 0; i < MAX_FILTERS; i++)
1320   {
1321      partitions[i].size = -1;
1322      partitions[i].numblks = 0;
1323
1324      for (j = 0; j < MAX_BLOCKS; j++)
1325      {
1326         partitions[i].blocks[j] = (blockT *)NULL;
1327         partitions[i].bnum[j] = 0xff;
1328      }
1329   }
1330
1331   // reset blocks
1332   for (i = 0; i < MAX_BLOCKS; i++)
1333   {
1334      blocks[i].size = -1;
1335      memset(&blocks[i].data, 0, CD_MAX_SECTOR_DATA);
1336   }
1337
1338   // open device
1339   if (cdrom)
1340   {
1341      cdrom_close(cdrom);
1342      cdrom = (cdrom_file *)NULL;
1343   }
1344
1345   cdrom_image_device *cddevice = machine().device<cdrom_image_device>("cdrom");
1346   if (cddevice!=NULL)
1347   {
1348      // MESS case
1349      cdrom = cddevice->get_cdrom_file();
1350   }
1351   else
1352   {
1353      // MAME case
1354      cdrom = cdrom_open(get_disk_handle(machine(), "cdrom"));
1355   }
1356
1357   cdda_set_cdrom( machine().device("cdda"), cdrom );
1358
1359   if (cdrom)
1360   {
1361      CDROM_LOG(("Opened CD-ROM successfully, reading root directory\n"))
1362      read_new_dir(0xffffff);    // read root directory
1363   }
1364   else
1365   {
1366      cd_stat = CD_STAT_NODISC;
1367   }
1368
1369   cd_speed = 2;
1370   cdda_repeat_count = 0;
1371   tray_is_closed = 1;
1372
1373   sector_timer = machine().device<timer_device>("sector_timer");
1374   sector_timer->adjust(attotime::from_hz(150));   // 150 sectors / second = 300kBytes/second
1375   sh1_timer = machine().device<timer_device>("sh1_cmd");
1376   sh1_timer->adjust(attotime::from_hz(16667));
1377}
1378
1379saturn_state::blockT *saturn_state::cd_alloc_block(UINT8 *blknum)
1380{
1381   INT32 i;
1382
1383   // search the 200 available blocks for a free one
1384   for (i = 0; i < 200; i++)
1385   {
1386      if (blocks[i].size == -1)
1387      {
1388         freeblocks--;
1389         if (freeblocks <= 0)
1390         {
1391            buffull = 1;
1392         }
1393
1394         blocks[i].size = sectlenin;
1395         *blknum = i;
1396
1397         CDROM_LOG(("CD: allocating block %d, size %x\n", i, sectlenin))
1398
1399         return &blocks[i];
1400      }
1401   }
1402
1403   buffull = 1;
1404   return (blockT *)NULL;
1405}
1406
1407void saturn_state::cd_free_block(blockT *blktofree)
1408{
1409   INT32 i;
1410
1411   CDROM_LOG(("cd_free_block: %x\n", (UINT32)(FPTR)blktofree))
1412
1413   if(blktofree == NULL)
1414   {
1415      return;
1416   }
1417
1418   for (i = 0; i < 200; i++)
1419   {
1420      if (&blocks[i] == blktofree)
1421      {
1422         CDROM_LOG(("CD: freeing block %d\n", i))
1423      }
1424   }
1425
1426   blktofree->size = -1;
1427   freeblocks++;
1428   buffull = 0;
1429   hirqreg &= ~BFUL;
1430}
1431
1432void saturn_state::cd_getsectoroffsetnum(UINT32 bufnum, UINT32 *sectoffs, UINT32 *sectnum)
1433{
1434   if (*sectoffs == 0xffff)
1435   {
1436      // last sector
1437      printf("CD: Don't know how to handle offset ffff\n");
1438   }
1439   else if (*sectnum == 0xffff)
1440   {
1441      *sectnum = partitions[bufnum].numblks - *sectoffs;
1442   }
1443}
1444
1445void saturn_state::cd_defragblocks(partitionT *part)
1446{
1447   UINT32 i, j;
1448   blockT *temp;
1449   UINT8 temp2;
1450
1451   for (i = 0; i < (MAX_BLOCKS-1); i++)
1452   {
1453      for (j = i+1; j < MAX_BLOCKS; j++)
1454      {
1455         if ((part->blocks[i] == (blockT *)NULL) && (part->blocks[j] != (blockT *)NULL))
1456         {
1457            temp = part->blocks[i];
1458            part->blocks[i] = part->blocks[j];
1459            part->blocks[j] = temp;
1460
1461            temp2 = part->bnum[i];
1462            part->bnum[i] = part->bnum[j];
1463            part->bnum[j] = temp2;
1464         }
1465      }
1466   }
1467}
1468
1469UINT16 saturn_state::cd_readWord(UINT32 addr)
1470{
1471   UINT16 rv;
1472
1473   switch (addr & 0xffff)
1474   {
1475      case 0x0008:    // read HIRQ register
1476      case 0x000a:
1477         rv = hirqreg;
1478
1479         rv &= ~DCHG;    // always clear bit 6 (tray open)
1480
1481         if (buffull) rv |= BFUL; else rv &= ~BFUL;
1482         if (sectorstore) rv |= CSCT; else rv &= ~CSCT;
1483
1484         hirqreg = rv;
1485
1486//          CDROM_LOG(("RW HIRQ: %04x\n", rv))
1487
1488         return rv;
1489
1490      case 0x000c:
1491      case 0x000e:
1492//          CDROM_LOG(("RW HIRM: %04x\n", hirqmask))
1493         printf("RW HIRM: %04x\n", hirqmask);
1494         return hirqmask;
1495
1496      case 0x0018:
1497      case 0x001a:
1498//          CDROM_LOG(("RW CR1: %04x\n", cr1))
1499         return cr1;
1500
1501      case 0x001c:
1502      case 0x001e:
1503//          CDROM_LOG(("RW CR2: %04x\n", cr2))
1504         return cr2;
1505
1506      case 0x0020:
1507      case 0x0022:
1508//          CDROM_LOG(("RW CR3: %04x\n", cr3))
1509         return cr3;
1510
1511      case 0x0024:
1512      case 0x0026:
1513//          CDROM_LOG(("RW CR4: %04x\n", cr4))
1514         //popmessage("%04x %04x %04x %04x",cr1,cr2,cr3,cr4);
1515         cmd_pending = 0;
1516         cd_stat |= CD_STAT_PERI;
1517         return cr4;
1518
1519      case 0x8000:
1520         rv = 0xffff;
1521         switch (xfertype)
1522         {
1523            case XFERTYPE_TOC:
1524               rv = tocbuf[xfercount]<<8 | tocbuf[xfercount+1];
1525
1526               xfercount += 2;
1527               xferdnum += 2;
1528
1529               if (xfercount > 102*4)
1530               {
1531                  xfercount = 0;
1532                  xfertype = XFERTYPE_INVALID;
1533               }
1534               break;
1535
1536            case XFERTYPE_FILEINFO_1:
1537               rv = finfbuf[xfercount]<<8 | finfbuf[xfercount+1];
1538               xfercount += 2;
1539               xferdnum += 2;
1540
1541               if (xfercount > 6*2)
1542               {
1543                  xfercount = 0;
1544                  xfertype = XFERTYPE_INVALID;
1545               }
1546               break;
1547
1548            case XFERTYPE_FILEINFO_254: // Lunar 2
1549               if((xfercount % (6 * 2)) == 0)
1550               {
1551                  UINT32 temp = 2 + (xfercount / (0x6 * 2));
1552
1553                  // first 4 bytes = FAD
1554                  finfbuf[0] = (curdir[temp].firstfad>>24)&0xff;
1555                  finfbuf[1] = (curdir[temp].firstfad>>16)&0xff;
1556                  finfbuf[2] = (curdir[temp].firstfad>>8)&0xff;
1557                  finfbuf[3] = (curdir[temp].firstfad&0xff);
1558                  // second 4 bytes = length of file
1559                  finfbuf[4] = (curdir[temp].length>>24)&0xff;
1560                  finfbuf[5] = (curdir[temp].length>>16)&0xff;
1561                  finfbuf[6] = (curdir[temp].length>>8)&0xff;
1562                  finfbuf[7] = (curdir[temp].length&0xff);
1563                  finfbuf[8] = curdir[temp].interleave_gap_size;
1564                  finfbuf[9] = curdir[temp].file_unit_size;
1565                  finfbuf[10] = temp;
1566                  finfbuf[11] = curdir[temp].flags;
1567               }
1568
1569               rv = finfbuf[xfercount % (6 * 2)]<<8 | finfbuf[(xfercount % (6 * 2)) +1];
1570
1571               xfercount += 2;
1572               xferdnum += 2;
1573
1574               if (xfercount > (254 * 6 * 2))
1575               {
1576                  xfercount = 0;
1577                  xfertype = XFERTYPE_INVALID;
1578               }
1579               break;
1580
1581            case XFERTYPE_SUBQ:
1582               rv = subqbuf[xfercount]<<8 | subqbuf[xfercount+1];
1583
1584               xfercount += 2;
1585               xferdnum += 2;
1586
1587               if (xfercount > 5*2)
1588               {
1589                  xfercount = 0;
1590                  xfertype = XFERTYPE_INVALID;
1591               }
1592               break;
1593
1594
1595            case XFERTYPE_SUBRW:
1596               rv = subrwbuf[xfercount]<<8 | subrwbuf[xfercount+1];
1597
1598               xfercount += 2;
1599               xferdnum += 2;
1600
1601               if (xfercount > 12*2)
1602               {
1603                  xfercount = 0;
1604                  xfertype = XFERTYPE_INVALID;
1605               }
1606               break;
1607
1608            default:
1609               printf("STVCD: Unhandled xfer type %d\n", (int)xfertype);
1610               rv = 0;
1611               break;
1612         }
1613
1614         return rv;
1615
1616      default:
1617         CDROM_LOG(("CD: RW %08x\n", addr))
1618         return 0xffff;
1619   }
1620
1621}
1622
1623UINT32 saturn_state::cd_readLong(UINT32 addr)
1624{
1625   UINT32 rv = 0;
1626
1627   switch (addr & 0xffff)
1628   {
1629      case 0x8000:
1630         switch (xfertype32)
1631         {
1632            case XFERTYPE32_GETSECTOR:
1633            case XFERTYPE32_GETDELETESECTOR:
1634               // make sure we have sectors left
1635               if (xfersect < xfersectnum)
1636               {
1637                  // get next longword
1638                  rv = (transpart->blocks[xfersectpos+xfersect]->data[xferoffs + 0]<<24) |
1639                        (transpart->blocks[xfersectpos+xfersect]->data[xferoffs + 1]<<16) |
1640                        (transpart->blocks[xfersectpos+xfersect]->data[xferoffs + 2]<<8)  |
1641                        (transpart->blocks[xfersectpos+xfersect]->data[xferoffs + 3]<<0);
1642
1643                  xferdnum += 4;
1644                  xferoffs += 4;
1645
1646                  // did we run out of sector?
1647                  if (xferoffs >= transpart->blocks[xfersect]->size)
1648                  {
1649                     CDROM_LOG(("CD: finished xfer of block %d of %d\n", xfersect+1, xfersectnum))
1650
1651                     xferoffs = 0;
1652                     xfersect++;
1653                  }
1654               }
1655               else    // sectors are done, kill 'em all if we can
1656               {
1657                  if (xfertype32 == XFERTYPE32_GETDELETESECTOR)
1658                  {
1659                     INT32 i;
1660
1661                     CDROM_LOG(("Killing sectors in done\n"))
1662
1663                     // deallocate the blocks
1664                     for (i = xfersectpos; i < xfersectpos+xfersectnum; i++)
1665                     {
1666                        cd_free_block(transpart->blocks[i]);
1667                        transpart->blocks[i] = (blockT *)NULL;
1668                        transpart->bnum[i] = 0xff;
1669                     }
1670
1671                     // defrag what's left
1672                     cd_defragblocks(transpart);
1673
1674                     // clean up our state
1675                     transpart->size -= xferdnum;
1676                     transpart->numblks -= xfersectnum;
1677
1678                     xfertype32 = XFERTYPE32_INVALID;
1679                  }
1680               }
1681               break;
1682
1683            default:
1684               printf("CD: unhandled 32-bit transfer type\n");
1685               break;
1686         }
1687
1688         return rv;
1689
1690      default:
1691         CDROM_LOG(("CD: RL %08x\n", addr))
1692         return 0xffff;
1693   }
1694}
1695
1696void saturn_state::cd_writeWord(UINT32 addr, UINT16 data)
1697{
1698   switch(addr & 0xffff)
1699   {
1700   case 0x0008:
1701   case 0x000a:
1702//      CDROM_LOG(("%s:WW HIRQ: %04x & %04x => %04x\n", machine().describe_context(), hirqreg, data, hirqreg & data))
1703      hirqreg &= data;
1704      if(!(hirqreg & CMOK))
1705      {
1706         sh1_timer->reset();
1707         sh1_timer->adjust(attotime::from_hz(16667));
1708      }
1709      return;
1710   case 0x000c:
1711   case 0x000e:
1712//      CDROM_LOG(("WW HIRM: %04x => %04x\n", hirqmask, data))
1713      printf("WW HIRM: %04x => %04x\n", hirqmask, data);
1714      hirqmask = data;
1715      return;
1716   case 0x0018:
1717   case 0x001a:
1718//      CDROM_LOG(("WW CR1: %04x\n", data))
1719      cr1 = data;
1720      cd_stat &= ~CD_STAT_PERI;
1721      cmd_pending |= 1;
1722      break;
1723   case 0x001c:
1724   case 0x001e:
1725//      CDROM_LOG(("WW CR2: %04x\n", data))
1726      cr2 = data;
1727      cmd_pending |= 2;
1728      break;
1729   case 0x0020:
1730   case 0x0022:
1731//      CDROM_LOG(("WW CR3: %04x\n", data))
1732      cr3 = data;
1733      cmd_pending |= 4;
1734      break;
1735   case 0x0024:
1736   case 0x0026:
1737//      CDROM_LOG(("WW CR4: %04x\n", data))
1738      cr4 = data;
1739      cmd_pending |= 8;
1740      break;
1741   default:
1742      CDROM_LOG(("CD: WW %08x %04x\n", addr, data))
1743      break;
1744   }
1745}
1746
1747READ32_MEMBER( saturn_state::stvcd_r )
1748{
1749   UINT32 rv = 0;
1750
1751   offset <<= 2;
1752
1753   switch (offset)
1754   {
1755      case 0x90008:
1756      case 0x9000a:
1757      case 0x9000c:
1758      case 0x9000e:
1759      case 0x90018:
1760      case 0x9001a:
1761      case 0x9001c:
1762      case 0x9001e:
1763      case 0x90020:
1764      case 0x90022:
1765      case 0x90024:
1766      case 0x90026:
1767         rv = cd_readWord(offset);
1768         return rv<<16;
1769
1770      case 0x98000:
1771      case 0x18000:
1772         if (mem_mask == 0xffffffff)
1773         {
1774            rv = cd_readLong(offset);
1775         }
1776         else if (mem_mask == 0xffff0000)
1777         {
1778            rv = cd_readWord(offset)<<16;
1779         }
1780         else if (mem_mask == 0x0000ffff)
1781         {
1782            rv = cd_readWord(offset);
1783         }
1784         else
1785         {
1786            mame_printf_error("CD: Unknown data buffer read @ mask = %08x\n", mem_mask);
1787         }
1788
1789         break;
1790
1791      default:
1792         CDROM_LOG(("Unknown CD read @ %x\n", offset))
1793         break;
1794   }
1795
1796   return rv;
1797}
1798
1799WRITE32_MEMBER( saturn_state::stvcd_w )
1800{
1801   offset <<= 2;
1802
1803   switch (offset)
1804   {
1805      case 0x90008:
1806      case 0x9000a:
1807      case 0x9000c:
1808      case 0x9000e:
1809      case 0x90018:
1810      case 0x9001a:
1811      case 0x9001c:
1812      case 0x9001e:
1813      case 0x90020:
1814      case 0x90022:
1815      case 0x90024:
1816      case 0x90026:
1817         cd_writeWord(offset, data>>16);
1818         break;
1819
1820      default:
1821         CDROM_LOG(("Unknown CD write %x @ %x\n", data, offset))
1822         break;
1823   }
1824}
1825
1826// iso9660 parsing
1827void saturn_state::read_new_dir(UINT32 fileno)
1828{
1829   int foundpd, i;
1830   UINT32 cfad;//, dirfad;
1831   UINT8 sect[2048];
1832
1833   if (fileno == 0xffffff)
1834   {
1835      cfad = 166;     // first sector of directory as per iso9660 specs
1836
1837      foundpd = 0;    // search for primary vol. desc
1838      while ((!foundpd) && (cfad < 200))
1839      {
1840         if(sectlenin != 2048)
1841            popmessage("Sector Length %d, contact MAMEdev (0)",sectlenin);
1842
1843         memset(sect, 0, 2048);
1844         cd_readblock(cfad++, sect);
1845
1846         if ((sect[1] == 'C') && (sect[2] == 'D') && (sect[3] == '0') && (sect[4] == '0') && (sect[5] == '1'))
1847         {
1848            switch (sect[0])
1849            {
1850               case 0: // boot record
1851                  break;
1852
1853               case 1: // primary vol. desc
1854                  foundpd = 1;
1855                  break;
1856
1857               case 2: // secondary vol desc
1858                  break;
1859
1860               case 3: // vol. section descriptor
1861                  break;
1862
1863               case 0xff:
1864                  cfad = 200;
1865                  break;
1866            }
1867         }
1868      }
1869
1870      // got primary vol. desc.
1871      if (foundpd)
1872      {
1873         //dirfad = sect[140] | (sect[141]<<8) | (sect[142]<<16) | (sect[143]<<24);
1874         //dirfad += 150;
1875
1876         // parse root entry
1877         curroot.firstfad = sect[158] | (sect[159]<<8) | (sect[160]<<16) | (sect[161]<<24);
1878         curroot.firstfad += 150;
1879         curroot.length = sect[166] | (sect[167]<<8) | (sect[168]<<16) | (sect[169]<<24);
1880         curroot.flags = sect[181];
1881         for (i = 0; i < sect[188]; i++)
1882         {
1883            curroot.name[i] = sect[189+i];
1884         }
1885         curroot.name[i] = '\0'; // terminate
1886
1887         // easy to fix, but make sure we *need* to first
1888         if (curroot.length > MAX_DIR_SIZE)
1889         {
1890            mame_printf_error("ERROR: root directory too big (%d)\n", curroot.length);
1891         }
1892
1893         // done with all that, read the root directory now
1894         make_dir_current(curroot.firstfad);
1895      }
1896   }
1897   else
1898   {
1899      if (curdir[fileno].length > MAX_DIR_SIZE)
1900      {
1901         mame_printf_error("ERROR: new directory too big (%d)!\n", curdir[fileno].length);
1902      }
1903      make_dir_current(curdir[fileno].firstfad);
1904   }
1905}
1906
1907// makes the directory pointed to by FAD current
1908void saturn_state::make_dir_current(UINT32 fad)
1909{
1910   int i;
1911   UINT32 nextent, numentries;
1912   UINT8 *sect;
1913   direntryT *curentry;
1914
1915   sect = (UINT8 *)malloc(MAX_DIR_SIZE);
1916   memset(sect, 0, MAX_DIR_SIZE);
1917   if(sectlenin != 2048)
1918      popmessage("Sector Length %d, contact MAMEdev (1)",sectlenin);
1919
1920   for (i = 0; i < (curroot.length/2048); i++)
1921   {
1922      cd_readblock(fad+i, &sect[2048*i]);
1923   }
1924
1925   nextent = 0;
1926   numentries = 0;
1927   while (nextent < MAX_DIR_SIZE)
1928   {
1929      if (sect[nextent])
1930      {
1931         nextent += sect[nextent];
1932         numentries++;
1933      }
1934      else
1935      {
1936         nextent = MAX_DIR_SIZE;
1937      }
1938   }
1939
1940   if (curdir != (direntryT *)NULL)
1941   {
1942      auto_free(machine(), curdir);
1943   }
1944
1945   curdir = auto_alloc_array(machine(), direntryT, numentries);
1946   curentry = curdir;
1947   numfiles = numentries;
1948
1949   nextent = 0;
1950   while (numentries)
1951   {
1952      // [0] record size
1953      // [1] xa record size
1954      // [2-5] lba
1955      // [6-9] (lba?)
1956      // [10-13] size
1957      // [14-17] (size?)
1958      // [18] year
1959      // [19] month
1960      // [20] day
1961      // [21] hour
1962      // [22] minute
1963      // [23] second
1964      // [24] gmt offset
1965      // [25] flags
1966      // [26] file unit size
1967      // [27] interleave gap size
1968      // [28-29] volume sequencer number
1969      // [30-31] (volume sequencer number?)
1970      // [32] name character size
1971      // [33+ ...] file name
1972
1973      curentry->record_size = sect[nextent+0];
1974      curentry->xa_record_size = sect[nextent+1];
1975      curentry->firstfad = sect[nextent+2] | (sect[nextent+3]<<8) | (sect[nextent+4]<<16) | (sect[nextent+5]<<24);
1976      curentry->firstfad += 150;
1977      curentry->length = sect[nextent+10] | (sect[nextent+11]<<8) | (sect[nextent+12]<<16) | (sect[nextent+13]<<24);
1978      curentry->year = sect[nextent+18];
1979      curentry->month = sect[nextent+19];
1980      curentry->day = sect[nextent+20];
1981      curentry->hour = sect[nextent+21];
1982      curentry->minute = sect[nextent+22];
1983      curentry->second = sect[nextent+23];
1984      curentry->gmt_offset = sect[nextent+24];
1985      curentry->flags = sect[nextent+25];
1986      curentry->file_unit_size = sect[nextent+26];
1987      curentry->interleave_gap_size = sect[nextent+27];
1988      curentry->volume_sequencer_number = sect[nextent+28] | (sect[nextent+29] << 8);
1989
1990      for (i = 0; i < sect[nextent+32]; i++)
1991      {
1992         curentry->name[i] = sect[nextent+33+i];
1993      }
1994      //printf("%08x %08x %s %d/%d/%d\n",curentry->firstfad,curentry->length,curentry->name,curentry->year,curentry->month,curentry->day);
1995      curentry->name[i] = '\0';   // terminate
1996
1997      nextent += sect[nextent];
1998      curentry++;
1999      numentries--;
2000   }
2001
2002   for (i = 0; i < numfiles; i++)
2003   {
2004      if (!(curdir[i].flags & 0x02))
2005      {
2006         firstfile = i;
2007         i = numfiles;
2008      }
2009   }
2010
2011   free(sect);
2012}
2013
2014void saturn_state::stvcd_exit( void )
2015{
2016   if (curdir != (direntryT *)NULL)
2017   {
2018      auto_free(machine(), curdir);
2019      curdir = (direntryT *)NULL;
2020   }
2021
2022   if (cdrom)
2023   {
2024      cdrom_image_device *cddevice = machine().device<cdrom_image_device>("cdrom");
2025      if (cddevice==NULL)
2026      {
2027         cdrom_close(cdrom);
2028      }
2029      cdrom = (cdrom_file *)NULL;
2030   }
2031}
2032
2033void saturn_state::cd_readTOC(void)
2034{
2035   int i, ntrks, tocptr, fad;
2036
2037   xfertype = XFERTYPE_TOC;
2038   xfercount = 0;
2039
2040   if (cdrom)
2041   {
2042      ntrks = cdrom_get_last_track(cdrom);
2043   }
2044   else
2045   {
2046      ntrks = 0;
2047   }
2048
2049   // data format for Saturn TOC:
2050   // no header.
2051   // 4 bytes per track
2052   // top nibble of first byte is CTRL info
2053   // low nibble is ADR
2054   // next 3 bytes are FAD address (LBA + 150)
2055   // there are always 99 track entries (0-98)
2056   // unused tracks are ffffffff.
2057   // entries 99-101 are metadata
2058
2059   tocptr = 0; // starting point of toc entries
2060
2061   for (i = 0; i < ntrks; i++)
2062   {
2063      if (cdrom)
2064      {
2065         tocbuf[tocptr] = cdrom_get_adr_control(cdrom, i)<<4 | 0x01;
2066      }
2067      else
2068      {
2069         tocbuf[tocptr] = 0xff;
2070      }
2071
2072      if (cdrom)
2073      {
2074         fad = cdrom_get_track_start(cdrom, i) + 150;
2075
2076         tocbuf[tocptr+1] = (fad>>16)&0xff;
2077         tocbuf[tocptr+2] = (fad>>8)&0xff;
2078         tocbuf[tocptr+3] = fad&0xff;
2079      }
2080      else
2081      {
2082         tocbuf[tocptr+1] = 0xff;
2083         tocbuf[tocptr+2] = 0xff;
2084         tocbuf[tocptr+3] = 0xff;
2085      }
2086
2087      tocptr += 4;
2088   }
2089
2090   // fill in the rest
2091   for ( ; i < 99; i++)
2092   {
2093      tocbuf[tocptr] = 0xff;
2094      tocbuf[tocptr+1] = 0xff;
2095      tocbuf[tocptr+2] = 0xff;
2096      tocbuf[tocptr+3] = 0xff;
2097
2098      tocptr += 4;
2099   }
2100
2101   // tracks 99-101 are special metadata
2102   // $$$FIXME: what to do with the address info for these?
2103   tocptr = 99 * 4;
2104   tocbuf[tocptr] = tocbuf[0]; // get ctrl/adr from first track
2105   tocbuf[tocptr+1] = 1;   // first track's track #
2106   tocbuf[tocptr+2] = 0;
2107   tocbuf[tocptr+3] = 0;
2108
2109   tocbuf[tocptr+4] = tocbuf[(ntrks-1)*4]; // ditto for last track
2110   tocbuf[tocptr+5] = ntrks;   // last track's track #
2111   tocbuf[tocptr+6] = 0;
2112   tocbuf[tocptr+7] = 0;
2113
2114   // get total disc length (start of lead-out)
2115   fad = cdrom_get_track_start(cdrom, 0xaa) + 150;
2116
2117   tocbuf[tocptr+8] = tocbuf[0];
2118   tocbuf[tocptr+9]  = (fad>>16)&0xff;
2119   tocbuf[tocptr+10] = (fad>>8)&0xff;
2120   tocbuf[tocptr+11] = fad&0xff;
2121}
2122
2123saturn_state::partitionT *saturn_state::cd_filterdata(filterT *flt, int trktype, UINT8 *p_ok)
2124{
2125   int match = 1, keepgoing = 2;
2126   partitionT *filterprt = (partitionT *)NULL;
2127
2128   CDROM_LOG(("cd_filterdata, trktype %d\n", trktype))
2129
2130   // loop on the filters
2131   do
2132   {
2133      // FAD range check?
2134      /* according to an obscure document note, this switches the filter connector to be false if the range fails ... I think ... */
2135      if (flt->mode & 0x40)
2136      {
2137         if ((cd_curfad < flt->fad) || (cd_curfad > (flt->fad + flt->range)))
2138         {
2139            printf("curfad reject %08x %08x %08x %08x\n",cd_curfad,fadstoplay,flt->fad,flt->fad+flt->range);
2140            //match = 0;
2141            lastbuf = flt->condfalse;
2142            flt = &filters[lastbuf];
2143
2144            keepgoing--;
2145         }
2146      }
2147
2148      if ((trktype != CD_TRACK_AUDIO) && (curblock.data[15] == 2))
2149      {
2150         if (flt->mode & 1)  // file number
2151         {
2152            if (curblock.fnum != flt->fid)
2153            {
2154               logerror("fnum reject\n");
2155               match = 0;
2156            }
2157         }
2158
2159         if (flt->mode & 2)  // channel number
2160         {
2161            if (curblock.chan != flt->chan)
2162            {
2163               logerror("channel number reject\n");
2164               match = 0;
2165            }
2166         }
2167
2168         if (flt->mode & 4)  // sub mode
2169         {
2170            if((curblock.subm & flt->smmask) != flt->smval)
2171            {
2172               logerror("sub mode reject\n");
2173               match = 0;
2174            }
2175         }
2176
2177         if (flt->mode & 8)  // coding information
2178         {
2179            if((curblock.cinf & flt->cimask) != flt->cival)
2180            {
2181               logerror("coding information reject\n");
2182               match = 0;
2183            }
2184         }
2185
2186         if (flt->mode & 0x10)   // reverse subheader conditions
2187         {
2188            match ^= 1;
2189         }
2190      }
2191
2192      if (match)
2193      {
2194         lastbuf = flt->condtrue;
2195         filterprt = &partitions[lastbuf];
2196         // we're done
2197         keepgoing = 0;
2198      }
2199      else
2200      {
2201         lastbuf = flt->condfalse;
2202
2203         // reject sector if no match on either connector
2204         if ((lastbuf == 0xff) || (keepgoing < 2))
2205         {
2206            *p_ok = 0;
2207            return (partitionT *)NULL;
2208         }
2209
2210         // try again using the filter that was on the "false" connector
2211         flt = &filters[lastbuf];
2212
2213         // and exit if we fail
2214         keepgoing--;
2215      }
2216   } while (keepgoing);
2217
2218   // try to allocate a block
2219   filterprt->blocks[filterprt->numblks] = cd_alloc_block(&filterprt->bnum[filterprt->numblks]);
2220
2221   // did the allocation succeed?
2222   if (filterprt->blocks[filterprt->numblks] == (blockT *)NULL)
2223   {
2224      *p_ok = 0;
2225      return (partitionT *)NULL;
2226   }
2227
2228   // copy working block to the newly allocated one
2229   memcpy(filterprt->blocks[filterprt->numblks], &curblock, sizeof(blockT));
2230
2231   // and massage the data format a bit
2232   switch  (curblock.size)
2233   {
2234      case 2048:  // user data
2235         if (curblock.data[15] == 2)
2236         {
2237            // mode 2
2238            memcpy(&filterprt->blocks[filterprt->numblks]->data[0], &curblock.data[24], curblock.size);
2239         }
2240         else
2241         {
2242            // mode 1
2243            memcpy(&filterprt->blocks[filterprt->numblks]->data[0], &curblock.data[16], curblock.size);
2244         }
2245         break;
2246
2247      case 2324:  // Mode 2 Form 2 data
2248         memcpy(&filterprt->blocks[filterprt->numblks]->data[0], &curblock.data[24], curblock.size);
2249         break;
2250
2251      case 2336:  // Mode 2 Form 2 skip sync/header
2252         memcpy(&filterprt->blocks[filterprt->numblks]->data[0], &curblock.data[16], curblock.size);
2253         break;
2254
2255      case 2340:  // Mode 2 Form 2 skip sync only
2256         memcpy(&filterprt->blocks[filterprt->numblks]->data[0], &curblock.data[12], curblock.size);
2257         break;
2258
2259      case 2352:  // want all data, it's already done, so don't do it again :)
2260         break;
2261   }
2262
2263   // update the status of the partition
2264   if (filterprt->size == -1)
2265   {
2266      filterprt->size = 0;
2267   }
2268   filterprt->size += filterprt->blocks[filterprt->numblks]->size;
2269   filterprt->numblks++;
2270
2271   *p_ok = 1;
2272   return filterprt;
2273}
2274
2275// read a single sector off the CD, applying the current filter(s) as necessary
2276saturn_state::partitionT *saturn_state::cd_read_filtered_sector(INT32 fad, UINT8 *p_ok)
2277{
2278   int trktype;
2279
2280   if ((cddevice != NULL) && (!buffull))
2281   {
2282      // find out the track's type
2283      trktype = cdrom_get_track_type(cdrom, cdrom_get_track(cdrom, fad-150));
2284
2285      // now get a raw 2352 byte sector - if it's mode 1, get mode1_raw
2286      if ((trktype == CD_TRACK_MODE1) || (trktype == CD_TRACK_MODE1_RAW))
2287      {
2288         cdrom_read_data(cdrom, fad-150, curblock.data, CD_TRACK_MODE1_RAW);
2289      }
2290      else if (trktype != CD_TRACK_AUDIO) // if not audio it must be mode 2 so get mode2_raw
2291      {
2292         cdrom_read_data(cdrom, fad-150, curblock.data, CD_TRACK_MODE2_RAW);
2293      }
2294      else
2295      {
2296         cdrom_read_data(cdrom, fad-150, curblock.data, CD_TRACK_AUDIO);
2297      }
2298
2299      curblock.size = sectlenin;
2300      curblock.FAD = fad;
2301
2302      // if track is Mode 2, get the subheader values
2303      if ((trktype != CD_TRACK_AUDIO) && (curblock.data[15] == 2))
2304      {
2305         curblock.chan = curblock.data[17];
2306         curblock.fnum = curblock.data[16];
2307         curblock.subm = curblock.data[18];
2308         curblock.cinf = curblock.data[19];
2309
2310         // if it's Form 2, the length is actually 2324 bytes
2311         if (curblock.subm & 0x20)
2312         {
2313            curblock.size = 2324;
2314         }
2315      }
2316
2317      return cd_filterdata(cddevice, trktype, &*p_ok);
2318   }
2319
2320   *p_ok = 0;
2321   return (partitionT *)NULL;
2322}
2323
2324// loads in data set up by a CD-block PLAY command
2325void saturn_state::cd_playdata( void )
2326{
2327   if ((cd_stat & 0x0f00) == CD_STAT_PLAY)
2328   {
2329      if (fadstoplay)
2330      {
2331         logerror("STVCD: Reading FAD %d\n", cd_curfad);
2332
2333         if (cdrom)
2334         {
2335            UINT8 p_ok;
2336
2337            if(cdrom_get_track_type(cdrom, cdrom_get_track(cdrom, cd_curfad)) != CD_TRACK_AUDIO)
2338            {
2339               cd_read_filtered_sector(cd_curfad,&p_ok);
2340               cdda_stop_audio( machine().device( "cdda" ) ); //stop any pending CD-DA
2341            }
2342            else
2343            {
2344               p_ok = 1; // TODO
2345               cdda_start_audio( machine().device( "cdda" ), cd_curfad, 1  );
2346            }
2347
2348            if(p_ok)
2349            {
2350               cd_curfad++;
2351               fadstoplay--;
2352               hirqreg |= CSCT;
2353               sectorstore = 1;
2354
2355               if (!fadstoplay)
2356               {
2357                  if(cdda_repeat_count >= cdda_maxrepeat)
2358                  {
2359                     CDROM_LOG(("cd_playdata: playback ended\n"))
2360                     cd_stat = CD_STAT_PAUSE;
2361
2362                     hirqreg |= PEND;
2363
2364                     if (playtype == 1)
2365                     {
2366                        CDROM_LOG(("cd_playdata: setting EFLS\n"))
2367                        hirqreg |= EFLS;
2368                     }
2369                  }
2370                  else
2371                  {
2372                     if(cdda_repeat_count < 0xe)
2373                        cdda_repeat_count++;
2374
2375                     cd_curfad = cdrom_get_track_start(cdrom, cur_track-1) + 150;
2376                     fadstoplay = cdrom_get_track_start(cdrom, cur_track) - cd_curfad;
2377                  }
2378               }
2379            }
2380         }
2381      }
2382   }
2383}
2384
2385// loads a single sector off the CD, anywhere from FAD 150 on up
2386void saturn_state::cd_readblock(UINT32 fad, UINT8 *dat)
2387{
2388   if (cdrom)
2389   {
2390      cdrom_read_data(cdrom, fad-150, dat, CD_TRACK_MODE1);
2391   }
2392}
2393
2394void saturn_state::stvcd_set_tray_open( void )
2395{
2396   if(!tray_is_closed)
2397      return;
2398
2399   hirqreg |= DCHG;
2400   cd_stat = CD_STAT_OPEN;
2401
2402   cdrom = (cdrom_file *)NULL;
2403   tray_is_closed = 0;
2404
2405   popmessage("Tray Open");
2406}
2407
2408void saturn_state::stvcd_set_tray_close( void )
2409{
2410   /* avoid user attempts to load a CD-ROM without opening the tray first (emulation asserts anyway with current framework) */
2411   if(tray_is_closed)
2412      return;
2413
2414   hirqreg |= DCHG;
2415
2416   cdrom_image_device *cddevice = machine().device<cdrom_image_device>("cdrom");
2417   if (cddevice!=NULL)
2418   {
2419      // MESS case
2420      cdrom = cddevice->get_cdrom_file();
2421   }
2422   else
2423   {
2424      // MAME case
2425      cdrom = cdrom_open(get_disk_handle(machine(), "cdrom"));
2426   }
2427
2428   cdda_set_cdrom( machine().device("cdda"), cdrom );
2429
2430   if (cdrom)
2431   {
2432      CDROM_LOG(("Opened CD-ROM successfully, reading root directory\n"))
2433      //read_new_dir(0xffffff);  // read root directory
2434      cd_stat = CD_STAT_PAUSE;
2435   }
2436   else
2437   {
2438      cd_stat = CD_STAT_NODISC;
2439   }
2440
2441   cd_speed = 2;
2442   cdda_repeat_count = 0;
2443   tray_is_closed = 1;
2444
2445   popmessage("Tray Close");
2446}
Property changes on: trunk/src/emu/machine/stvcd.c
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/emu/machine/scudsp.c
r0r20947
1/******************************************************************************************
2System Control Unit - DSP emulator version 0.09
3
4Written by Angelo Salese & Mariusz Wojcieszek
5
6Changelog:
7110807: Angelo Salese
8- Allow the Program Counter to be read-backable from SH-2, needed by Virtua Fighter to not
9  get stuck on "round 1" announcement;
10
11110806: Angelo Salese
12- Allows reading from non-work ram h areas;
13- Fixed DMA add values;
14- Fixed a MVI condition shift flag bug, now Sega Saturn produces sound during splash screen;
15- Removed left-over IRQ;
16
17110722: Angelo Salese
18- Added DSP IRQ command, tested with "The King of Boxing"
19
20110527: Angelo Salese
21- Fixed incorrectly setted execute flag clearance, allows animation of the Sega Saturn
22  splash screen;
23
24051129: Mariusz Wojcieszek
25- Fixed parallel instructions which increment CT registers to update CT register only
26  once, after dsp operation is finished. This fixes instructions like
27  MOV MC0,X MOV MC0,Y used by vfremix
28- Changed ALU 32bit instructions to not sign extend their result when loaded to ALU.
29  This matches Sega's dspsim behaviour.
30- Changed DMA addnumber handling to match Sega's dspsim.
31
32050813: Mariusz Wojcieszek
33- Fixed add number in DSP DMA
34
35050412: Angelo Salese
36- Fixed the T0F behaviour in the DMA operation,it was causing an hang in Treasure Hunt
37  due of that.
38- Removed the dsp.log file creation when you are not using the debug build
39
40041114: Angelo Salese
41- Finished flags in ALU opcodes
42- SR opcode: MSB does not change.
43
44040328: Mariusz Wojcieszek
45- rewritten ALU and MUL operations using signed arithmetics
46- improved DMA
47- fixed MOV ALH,x
48
49031211: Mariusz Wojcieszek
50- result of ALU command is stored into ALU register
51- X-Bus command: MOV [s],X can be executed in parallel to other X-Bus commands
52- Y-Bus command: MOV [s],Y can be executed in parallel to other Y-Bus commands
53- Jump and LPS/BTM support:
54    jump addresses are absolute,
55    prefetched instructions are executed before jump is taken
56- after each instruction, X and Y is multiplied and contents are loaded into MUL register
57- fixed RL8
58- fixed MVI
59- flags computation in MVI and JMP is partly guessed (because of errors in docs)
60- added reading DSP mem from SH2 side
61- overworked disassembler
62
63 TODO:
64- Convert this to cpu structure
65- Disassembler: complete it
66- Add control flags
67- Croc: has a bug somewhere that never allows it to trip the ENDI opcode.
68  Snippet of interest is:
69  08    00823500                                            CLR A     MOV M0,PL
70  09    08040000    OR                                      MOV ALU,A
71  0A    D208000D    JMP NZ,$D
72  0B    00000000    NOP
73  0C    F8000000    ENDI
74  ...
75  40    00863502                                            MOV M0,A  MOV M2,PL
76  41    10003009    ADD                                               MOV ALL,MC0
77  42    D3400042    JMP T0,$42
78  43    00000000    NOP
79  44    D0000007    JMP $7
80
81******************************************************************************************/
82#include "emu.h"
83#include "machine/scudsp.h"
84#include "sound/scsp.h"
85#include "includes/stv.h"
86
87/*DSP macros*/
88#define PRF ((state->m_scu_regs[32] & 0x04000000) >> 26)
89#define EPF ((state->m_scu_regs[32] & 0x02000000) >> 25)
90#define T0F ((state->m_scu_regs[32] & 0x00800000) >> 23)
91#define SF  ((state->m_scu_regs[32] & 0x00400000) >> 22)
92#define ZF  ((state->m_scu_regs[32] & 0x00200000) >> 21)
93#define CF  ((state->m_scu_regs[32] & 0x00100000) >> 20)
94#define VF  ((state->m_scu_regs[32] & 0x00080000) >> 19)
95#define EF  ((state->m_scu_regs[32] & 0x00040000) >> 18)
96#define ESF ((state->m_scu_regs[32] & 0x00020000) >> 17)
97#define EXF ((state->m_scu_regs[32] & 0x00010000) >> 16)
98#define LEF ((state->m_scu_regs[32] & 0x00008000) >> 15)
99#define T0F_1 state->m_scu_regs[32]|=0x00800000
100#define T0F_0 state->m_scu_regs[32]&=~0x00800000
101#define EXF_0 state->m_scu_regs[32]&=~0x00010000
102#define EF_1  state->m_scu_regs[32]|=0x00040000
103
104#define SET_C(_val) (state->m_scu_regs[32] = ((state->m_scu_regs[32] & ~0x00100000) | ((_val) ? 0x00100000 : 0)))
105#define SET_S(_val) (state->m_scu_regs[32] = ((state->m_scu_regs[32] & ~0x00400000) | ((_val) ? 0x00400000 : 0)))
106#define SET_Z(_val) (state->m_scu_regs[32] = ((state->m_scu_regs[32] & ~0x00200000) | ((_val) ? 0x00200000 : 0)))
107#define SET_V(_val) (state->m_scu_regs[32] = ((state->m_scu_regs[32] & ~0x00080000) | ((_val) ? 0x00080000 : 0)))
108
109union SCUDSPREG32 {
110   INT32  si;
111   UINT32 ui;
112};
113
114union SCUDSPREG16 {
115   INT16  si;
116   UINT16 ui;
117};
118
119static struct {
120      UINT8 pc;                                      /*Program Counter*/
121      UINT8 delay;                                       /* Delay */
122      UINT8 top;                                     /*Jump Command memory*/
123      UINT16 lop;                                    /*Counter Register*/   /*12-bits*/
124      UINT8  ct0,ct1,ct2,ct3;                        /*Index for RAM*/      /*6-bits */
125      UINT32 md0[0x40],md1[0x40],md2[0x40],md3[0x40]; /*RAM memory*/
126      UINT8  ra;                                     /*RAM selector*/
127      SCUDSPREG32 rx;                                /*X-Bus register*/
128      INT64 mul;                                      /*Multiplier register*//*48-bits*/
129      SCUDSPREG32 ry;                                /*Y-Bus register*/
130      INT64  alu;                                     /*ALU register*/       /*48-bits*/
131      SCUDSPREG16 ph;                                /*ALU high register*/
132      SCUDSPREG32 pl;                                /*ALU low register*/
133      SCUDSPREG16 ach;                                   /*ALU external high register*/
134      SCUDSPREG32 acl;                                   /*ALU external low register*/
135      UINT32 ra0,wa0;                                /*DSP DMA registers*/
136      UINT32 internal_prg[0x100];
137} dsp_reg;
138
139static UINT32 opcode;
140static UINT8 update_mul = 0;
141
142#ifdef MAME_DEBUG
143#define DEBUG_DSP 1
144#else
145#define DEBUG_DSP 0
146#endif
147
148static char dasm_buffer[100];
149#if DEBUG_DSP
150static FILE *log_file = NULL;
151#endif
152static void dsp_dasm_opcode( UINT32 op, char *buffer );
153
154
155
156static UINT32 dsp_get_source_mem_value( UINT32 mode )
157{
158   UINT32 value = 0;
159
160   switch( mode )
161   {
162      case 0x0:   /* M0 */
163         value = dsp_reg.md0[ dsp_reg.ct0 ];
164         break;
165      case 0x1:   /* M1 */
166         value = dsp_reg.md1[ dsp_reg.ct1 ];
167         break;
168      case 0x2:   /* M2 */
169         value = dsp_reg.md2[ dsp_reg.ct2 ];
170         break;
171      case 0x3:   /* M3 */
172         value = dsp_reg.md3[ dsp_reg.ct3 ];
173         break;
174      case 0x4:   /* MC0 */
175         value = dsp_reg.md0[ dsp_reg.ct0++ ];
176         dsp_reg.ct0 &= 0x3f;
177         break;
178      case 0x5:   /* MC1 */
179         value = dsp_reg.md1[ dsp_reg.ct1++ ];
180         dsp_reg.ct1 &= 0x3f;
181         break;
182      case 0x6:   /* MC2 */
183         value = dsp_reg.md2[ dsp_reg.ct2++ ];
184         dsp_reg.ct2 &= 0x3f;
185         break;
186      case 0x7:   /* MC3 */
187         value = dsp_reg.md3[ dsp_reg.ct3++ ];
188         dsp_reg.ct3 &= 0x3f;
189         break;
190   }
191   return value;
192}
193
194static UINT32 dsp_get_source_mem_reg_value( UINT32 mode )
195{
196   if ( mode < 0x8 )
197   {
198      return dsp_get_source_mem_value( mode );
199   }
200   else
201   {
202      switch( mode )
203      {
204         case 0x9:
205            return (UINT32)((dsp_reg.alu & U64(0x00000000ffffffff)) >> 0);
206         case 0xA:
207            return (UINT32)((dsp_reg.alu & U64(0x0000ffffffff0000)) >> 16);
208      }
209   }
210   return 0;
211}
212
213static void dsp_set_dest_mem_reg( UINT32 mode, UINT32 value )
214{
215   switch( mode )
216   {
217      case 0x0:   /* MC0 */
218         dsp_reg.md0[ dsp_reg.ct0++ ] = value;
219         dsp_reg.ct0 &= 0x3f;
220         break;
221      case 0x1:   /* MC1 */
222         dsp_reg.md1[ dsp_reg.ct1++ ] = value;
223         dsp_reg.ct1 &= 0x3f;
224         break;
225      case 0x2:   /* MC2 */
226         dsp_reg.md2[ dsp_reg.ct2++ ] = value;
227         dsp_reg.ct2 &= 0x3f;
228         break;
229      case 0x3:   /* MC3 */
230         dsp_reg.md3[ dsp_reg.ct3++ ] = value;
231         dsp_reg.ct3 &= 0x3f;
232         break;
233      case 0x4:   /* RX */
234         dsp_reg.rx.ui = value;
235         update_mul = 1;
236         break;
237      case 0x5:   /* PL */
238         dsp_reg.pl.ui = value;
239         dsp_reg.ph.si = (dsp_reg.pl.si < 0) ? -1 : 0;
240         break;
241      case 0x6:   /* RA0 */
242         dsp_reg.ra0 = value;
243         break;
244      case 0x7:   /* WA0 */
245         dsp_reg.wa0 = value;
246         break;
247      case 0x8:
248      case 0x9:
249         /* ??? */
250         break;
251      case 0xa:   /* LOP */
252         dsp_reg.lop = value;
253         break;
254      case 0xb:   /* TOP */
255         dsp_reg.top = value;
256         break;
257      case 0xc:   /* CT0 */
258         dsp_reg.ct0 = value & 0x3f;
259         break;
260      case 0xd:   /* CT1 */
261         dsp_reg.ct1 = value & 0x3f;
262         break;
263      case 0xe:   /* CT2 */
264         dsp_reg.ct2 = value & 0x3f;
265         break;
266      case 0xf:   /* CT3 */
267         dsp_reg.ct3 = value & 0x3f;
268         break;
269   }
270}
271
272static void dsp_set_dest_mem_reg_2( UINT32 mode, UINT32 value )
273{
274   if ( mode < 0xb )
275   {
276      dsp_set_dest_mem_reg( mode, value );
277   }
278   else
279   {
280      switch( mode )
281      {
282         case 0xc:   /* PC */
283            dsp_reg.delay = dsp_reg.pc;  /* address next after this command will be executed twice */
284            dsp_reg.top = dsp_reg.pc;
285            dsp_reg.pc = value;
286            break;
287      }
288   }
289}
290
291static UINT32 dsp_compute_condition( address_space &space, UINT32 condition )
292{
293   saturn_state *state = space.machine().driver_data<saturn_state>();
294   UINT32 result = 0;
295
296   switch( condition & 0xf )
297   {
298      case 0x1:   /* Z */
299         result = ZF;
300         break;
301      case 0x2:   /* S */
302         result = SF;
303         break;
304      case 0x3:   /* ZS */
305         result = ZF | SF;
306         break;
307      case  0x4:  /* C */
308         result = CF;
309         break;
310      case 0x8:   /* T0 */
311         result = T0F;
312         break;
313   }
314   if ( !(condition & 0x20) )
315   {
316      result = !result;
317   }
318   return result;
319}
320
321static void dsp_set_dest_dma_mem( UINT32 memcode, UINT32 value, UINT32 counter )
322{
323   if ( memcode < 4 )
324   {
325      dsp_set_dest_mem_reg( memcode, value );
326   }
327   else if ( memcode == 4 )
328   {
329      dsp_reg.internal_prg[ counter & 0x100 ] = value;
330   }
331}
332
333static UINT32 dsp_get_mem_source_dma( UINT32 memcode, UINT32 counter )
334{
335   switch( memcode & 0x3 )
336   {
337      case 0x0:
338         return dsp_reg.md0[ (dsp_reg.ct0 + counter) & 0x3f ];
339      case 0x1:
340         return dsp_reg.md1[ (dsp_reg.ct1 + counter) & 0x3f ];
341      case 0x2:
342         return dsp_reg.md2[ (dsp_reg.ct2 + counter) & 0x3f ];
343      case 0x3:
344         return dsp_reg.md3[ (dsp_reg.ct3 + counter) & 0x3f ];
345   }
346   return 0;
347}
348
349UINT32 dsp_prg_ctrl_r(address_space &space)
350{
351   saturn_state *state = space.machine().driver_data<saturn_state>();
352
353   return (state->m_scu_regs[0x80/4] & 0x06ff8000) | (dsp_reg.pc & 0xff);
354}
355
356void dsp_prg_ctrl_w(address_space &space, UINT32 data)
357{
358   saturn_state *state = space.machine().driver_data<saturn_state>();
359
360   if(LEF) dsp_reg.pc = (data & 0xff);
361   if(EXF) dsp_execute_program(space);
362}
363
364void dsp_prg_data(UINT32 data)
365{
366   dsp_reg.internal_prg[dsp_reg.pc] = data;
367   dsp_reg.pc++;
368}
369
370void dsp_ram_addr_ctrl(UINT32 data)
371{
372   dsp_reg.ra = data & 0xff;
373
374   switch((dsp_reg.ra & 0xc0) >> 6)
375   {
376      case 0: dsp_reg.ct0 = (dsp_reg.ra & 0x3f); break;
377      case 1: dsp_reg.ct1 = (dsp_reg.ra & 0x3f); break;
378      case 2: dsp_reg.ct2 = (dsp_reg.ra & 0x3f); break;
379      case 3: dsp_reg.ct3 = (dsp_reg.ra & 0x3f); break;
380   }
381}
382
383void dsp_ram_addr_w(UINT32 data)
384{
385#if DEBUG_DSP
386   if ( log_file == NULL )
387   {
388      log_file = fopen( "dsp.log", "a" );
389   }
390   fprintf( log_file, "DSP: Writing mem %02X %04X\n", dsp_reg.ra & 0xff, data );
391#endif
392   dsp_set_dest_mem_reg( (dsp_reg.ra & 0xc0) >> 6, data );
393}
394
395UINT32 dsp_ram_addr_r()
396{
397   UINT32 data;
398
399   data = dsp_get_source_mem_value( ((dsp_reg.ra & 0xc0) >> 6) + 4 );
400#if DEBUG_DSP
401   if ( log_file == NULL )
402   {
403      log_file = fopen( "dsp.log", "a" );
404   }
405   fprintf( log_file, "DSP: Reading mem at %02X %04X\n", dsp_reg.ra & 0xff, data );
406#endif
407   return data;
408}
409
410static void dsp_operation(address_space &space)
411{
412   saturn_state *state = space.machine().driver_data<saturn_state>();
413   INT64 i1,i2;
414   INT32 i3;
415   int update_ct[4] = {0,0,0,0};
416   int dsp_mem;
417
418
419   /* ALU */
420   switch( (opcode & 0x3c000000) >> 26 )
421   {
422      case 0x0:   /* NOP */
423         break;
424      case 0x1:   /* AND */
425         i3 = dsp_reg.acl.si & dsp_reg.pl.si;
426         dsp_reg.alu = (UINT64)(UINT32)i3;
427         SET_Z(i3 == 0);
428         SET_C(0);
429         SET_S(i3 < 0);
430         break;
431      case 0x2:   /* OR */
432         i3 = dsp_reg.acl.si | dsp_reg.pl.si;
433         dsp_reg.alu = (UINT64)(UINT32)i3;
434         SET_C(0);
435         SET_S(i3 < 0);
436         /* TODO: Croc and some early Psygnosis games wants Z to be 1 when the result of this one is negative.
437                  Needs HW tests ... */
438         if(i3 < 0)
439            i3 = 0;
440         SET_Z(i3 == 0);
441         break;
442      case 0x3:   /* XOR */
443         i3 = dsp_reg.acl.si ^ dsp_reg.pl.si;
444         dsp_reg.alu = (UINT64)(UINT32)i3;
445         SET_Z(i3 == 0);
446         SET_C(0);
447         SET_S(i3 < 0);
448         break;
449      case 0x4:   /* ADD */
450         i3 = dsp_reg.acl.si + dsp_reg.pl.si;
451         dsp_reg.alu = (UINT64)(UINT32)i3;
452         //SET_Z(i3 == 0);
453         SET_Z( (i3 & S64(0xffffffffffff)) == 0 );
454         //SET_S(i3 < 0);
455         SET_S( i3 & S64(0x1000000000000));
456         SET_C(i3 & S64(0x100000000));
457         SET_V(((i3) ^ (dsp_reg.acl.si)) & ((i3) ^ (dsp_reg.pl.si)) & 0x80000000);
458         break;
459      case 0x5:   /* SUB */
460         i3 = dsp_reg.acl.si - dsp_reg.pl.si;
461         dsp_reg.alu = (UINT64)(UINT32)i3;
462         SET_Z(i3 == 0);
463         SET_C(i3 & S64(0x100000000));
464         SET_S(i3 < 0);
465         SET_V(((dsp_reg.pl.si) ^ (dsp_reg.acl.si)) & ((dsp_reg.pl.si) ^ (i3)) & 0x80000000);
466         break;
467      case 0x6:   /* AD2 */
468         i1 = CONCAT_64((INT32)dsp_reg.ph.si,dsp_reg.pl.si);
469         i2 = CONCAT_64((INT32)dsp_reg.ach.si,dsp_reg.acl.si);
470         dsp_reg.alu = i1 + i2;
471         SET_Z((dsp_reg.alu & S64(0xffffffffffff)) == 0);
472         SET_S((dsp_reg.alu & S64(0x800000000000)) > 0);
473         SET_C((dsp_reg.alu) & S64(0x1000000000000));
474         SET_V(((dsp_reg.alu) ^ (i1)) & ((dsp_reg.alu) ^ (i2)) & S64(0x800000000000));
475         break;
476      case 0x7:   /* ??? */
477         /* Unrecognized opcode */
478         break;
479      case 0x8:   /* SR */
480         i3 = (dsp_reg.acl.si >> 1) | (dsp_reg.acl.si & 0x80000000);/*MSB does not change*/
481         dsp_reg.alu = (UINT64)(UINT32)i3;
482         SET_Z(i3 == 0);
483         SET_S(i3 < 0);
484         SET_C(dsp_reg.acl.ui & 0x80000000);
485         break;
486      case 0x9:   /* RR */
487         i3 = ((dsp_reg.acl.ui >> 1) & 0x7fffffff) | ((dsp_reg.acl.ui << 31) & 0x80000000);
488         dsp_reg.alu = (UINT64)(UINT32)i3;
489         SET_Z( i3 == 0 );
490         SET_S( i3 < 0 );
491         SET_C( dsp_reg.acl.ui & 0x1 );
492         break;
493      case 0xa:   /* SL */
494         i3 = dsp_reg.acl.si << 1;
495         dsp_reg.alu = (UINT64)(UINT32)i3;
496         SET_Z( i3 == 0 );
497         SET_S( i3 < 0 );
498         SET_C( dsp_reg.acl.ui & 0x80000000 );
499         break;
500      case 0xB:   /* RL */
501         i3 = ((dsp_reg.acl.si << 1) & 0xfffffffe) | ((dsp_reg.acl.si >> 31) & 0x1);
502         dsp_reg.alu = (UINT64)(UINT32)i3;
503         SET_Z( i3 == 0 );
504         SET_S( i3 < 0 );
505         SET_C( dsp_reg.acl.ui & 0x80000000 );
506         break;
507      case 0xc:
508      case 0xd:
509      case 0xe:
510         /* Unrecognized opcode */
511         break;
512      case 0xF:   /* RL8 */
513         i3 = ((dsp_reg.acl.si << 8) & 0xffffff00) | ((dsp_reg.acl.si >> 24) & 0xff);
514         dsp_reg.alu = i3;
515         SET_Z( i3 == 0 );
516         SET_S( i3 < 0 );
517         SET_C( dsp_reg.acl.si & 0x01000000 );
518         break;
519   }
520
521   /* X-Bus */
522   if ( opcode & 0x2000000 )
523   {
524      /* MOV [s],X */
525      dsp_mem = (opcode & 0x700000) >> 20;
526      if ( dsp_mem & 4 )
527      {
528         dsp_mem &= 3;
529         update_ct[dsp_mem] = 1;
530      }
531      dsp_reg.rx.ui = dsp_get_source_mem_value( dsp_mem );
532      update_mul = 1;
533   }
534   switch( (opcode & 0x1800000) >> 23 )
535   {
536      case 0x0:   /* NOP */
537      case 0x1:   /* NOP ? */
538         break;
539      case 0x2:   /* MOV MUL,P */
540         dsp_reg.ph.ui = (UINT16)((dsp_reg.mul & U64(0x0000ffff00000000)) >> 32);
541         dsp_reg.pl.ui = (UINT32)((dsp_reg.mul & U64(0x00000000ffffffff)) >> 0);
542         break;
543      case 0x3:   /* MOV [s],P */
544         dsp_mem = (opcode & 0x700000) >> 20;
545         if ( dsp_mem & 4 )
546         {
547            dsp_mem &= 3;
548            update_ct[dsp_mem] = 1;
549         }
550         dsp_reg.pl.ui = dsp_get_source_mem_value(  dsp_mem );
551         dsp_reg.ph.si = (dsp_reg.pl.si < 0) ? -1 : 0;
552         break;
553   }
554
555   /* Y-Bus */
556   if ( opcode & 0x80000 )
557   {
558      /* MOV [s],Y */
559      dsp_mem = (opcode & 0x1C000 ) >> 14;
560      if (dsp_mem & 4)
561      {
562         dsp_mem &= 3;
563         update_ct[dsp_mem] = 1;
564      }
565      dsp_reg.ry.ui = dsp_get_source_mem_value( dsp_mem );
566      update_mul = 1;
567   }
568   switch( (opcode & 0x60000) >> 17 )
569   {
570      case 0x0:   /* NOP */
571         break;
572      case 0x1:   /* CLR A */
573         dsp_reg.acl.ui = 0;
574         dsp_reg.ach.ui = 0;
575         break;
576      case 0x2:   /* MOV ALU,A */
577         dsp_reg.ach.ui = (UINT16)((dsp_reg.alu & U64(0x0000ffff00000000)) >> 32);
578         dsp_reg.acl.ui = (UINT32)((dsp_reg.alu & U64(0x00000000ffffffff)) >> 0);
579         break;
580      case 0x3:   /* MOV [s], A */
581         dsp_mem = (opcode & 0x1C000 ) >> 14;
582         if (dsp_mem & 4)
583         {
584            dsp_mem &= 3;
585            update_ct[dsp_mem] = 1;
586         }
587         dsp_reg.acl.ui = dsp_get_source_mem_value( dsp_mem );
588         dsp_reg.ach.si = ((dsp_reg.acl.si < 0) ? -1 : 0);
589         break;
590   }
591
592   /* update CT registers */
593   if ( update_ct[0] ) { dsp_reg.ct0++; dsp_reg.ct0 &= 0x3f; };
594   if ( update_ct[1] ) { dsp_reg.ct1++; dsp_reg.ct1 &= 0x3f; };
595   if ( update_ct[2] ) { dsp_reg.ct2++; dsp_reg.ct2 &= 0x3f; };
596   if ( update_ct[3] ) { dsp_reg.ct3++; dsp_reg.ct3 &= 0x3f; };
597
598
599   /* D1-Bus */
600   switch( (opcode & 0x3000) >> 12 )
601   {
602      case 0x0:   /* NOP */
603         break;
604      case 0x1:   /* MOV SImm,[d] */
605         dsp_set_dest_mem_reg( (opcode & 0xf00) >> 8, (INT32)(INT8)(opcode & 0xff) );
606         break;
607      case 0x2:
608         /* ??? */
609         break;
610      case 0x3:   /* MOV [s],[d] */
611         dsp_set_dest_mem_reg( (opcode & 0xf00) >> 8, dsp_get_source_mem_reg_value( opcode & 0xf ) );
612         break;
613   }
614
615}
616
617static void dsp_move_immediate( address_space &space )
618{
619   UINT32 value;
620
621   if ( opcode & 0x2000000 )
622   {
623      if ( dsp_compute_condition( space, (opcode & 0x3F80000 ) >> 19 ) )
624      {
625         value = opcode & 0x7ffff;
626         if ( value & 0x40000 ) value |= 0xfff80000;
627         dsp_set_dest_mem_reg_2( (opcode & 0x3C000000) >> 26, value );
628      }
629   }
630   else
631   {
632      value = opcode & 0x1ffffff;
633      if ( value & 0x1000000 ) value |= 0xfe000000;
634      dsp_set_dest_mem_reg_2( (opcode & 0x3C000000) >> 26, value );
635   }
636}
637
638
639static void dsp_dma( address_space &space )
640{
641   saturn_state *state = space.machine().driver_data<saturn_state>();
642
643   UINT8 hold = (opcode &  0x4000) >> 14;
644   UINT32 add = (opcode & 0x38000) >> 15;
645   UINT32 dir_from_D0 = (opcode & 0x1000 ) >> 12;
646   UINT32 transfer_cnt = 0;
647   UINT32 source = 0, dest = 0;
648   UINT32 dsp_mem = (opcode & 0x300) >> 8;
649   UINT32 counter = 0;
650   UINT32 data;
651
652
653   T0F_1;
654
655   if ( opcode & 0x2000 )
656   {
657      transfer_cnt = dsp_get_source_mem_value( opcode & 0xf );
658      switch ( add & 0x7 )
659      {
660         case 0: add = 0; break;
661         case 1: add = 4; break;
662         default: add = 4; break;
663      }
664   }
665   else
666   {
667      transfer_cnt = opcode & 0xff;
668      switch( add )
669      {
670         case 0: add = 0; break;  /* 0 */
671         case 1: add = 4; break;  /* 1 */
672         case 2: add = 4; break;  /* 2 */
673         case 3: add = 16; break; /* 4 */
674         case 4: add = 16; break;  /* 8 */
675         case 5: add = 64; break; /* 16 */
676         case 6: add = 128; break; /* 32 */
677         case 7: add = 256; break; /* 64 */
678      }
679   }
680
681   if ( dir_from_D0 == 0 )
682   {
683      /* DMA D0,[RAM] */
684      source = dsp_reg.ra0 << 2;
685      source &= 0x07ffffff;
686      dest &= 0x07ffffff;
687      transfer_cnt &= 0xff;
688
689#if DEBUG_DSP
690      fprintf( log_file, "/*DSP DMA D0,[RAM%d],%d add=%d*/\n", dsp_mem, transfer_cnt, add );
691#endif
692
693      for ( counter = 0; counter < transfer_cnt ; counter++ )
694      {
695#if DEBUG_DSP
696         fprintf( log_file, "%08X, ", source ); fflush( log_file );
697#endif
698
699         if ( source >= 0x06000000 && source <= 0x060fffff )
700         {
701            data = space.read_dword(source );
702         }
703         else
704         {
705            data = (space.read_word(source)<<16) | space.read_word(source+2);
706            //popmessage( "Bad DSP DMA mem read = %08X", source );
707#if DEBUG_DSP
708            //fprintf( log_file, "/*Bad DSP DMA mem read = %08X*/\n", source );
709#endif
710         }
711
712#if DEBUG_DSP
713         fprintf( log_file, "%08X,\n", data );
714#endif
715         dsp_set_dest_dma_mem( dsp_mem, data, counter );
716         source += add;
717      }
718
719      if ( hold == 0 )
720      {
721         dsp_reg.ra0 += ((counter * add) >> 2);
722      }
723   }
724   else
725   {
726      /* DMA [RAM],D0 */
727      dest = dsp_reg.wa0 << 2;
728      source &= 0x07ffffff;
729      dest &= 0x07ffffff;
730      transfer_cnt &= 0xff;
731      //logerror("[DSP DMA] SRC = %08x | DEST = %08x | SIZE = %08x | ADD VALUE = %08x\n",source,dest,transfer_cnt,add);
732
733#if DEBUG_DSP
734      fprintf( log_file, "/*DSP DMA [RAM%d],D0,%d\tadd=%d,source=%08X*/\n", dsp_mem, transfer_cnt, add, source );
735#endif
736      for ( counter = 0; counter < transfer_cnt; counter++ )
737      {
738         space.write_dword(dest, dsp_get_mem_source_dma( dsp_mem, counter ) );
739         dest += add;
740      }
741
742      if ( hold == 0 )
743      {
744         dsp_reg.wa0 += ((counter * add) >> 2);
745      }
746   }
747
748   /* TODO: move this behind a timer */
749   T0F_0;
750}
751
752static void dsp_jump( address_space &space )
753{
754   if ( opcode & 0x3f80000 )
755   {
756      if ( dsp_compute_condition( space, (opcode & 0x3f80000) >> 19 ) )
757      {
758         dsp_reg.delay = dsp_reg.pc;
759         dsp_reg.pc = opcode & 0xff;
760      }
761   }
762   else
763   {
764      dsp_reg.delay = dsp_reg.pc;
765      dsp_reg.pc = opcode & 0xff;
766   }
767}
768
769static TIMER_CALLBACK( dsp_ended )
770{
771   saturn_state *state = machine.driver_data<saturn_state>();
772
773   if(!(state->m_scu.ism & IRQ_DSP_END))
774      state->m_maincpu->set_input_line_and_vector(0xa, HOLD_LINE, 0x45);
775   else
776      state->m_scu.ist |= (IRQ_DSP_END);
777
778   EF_1;
779}
780
781static void dsp_end( address_space &dmaspace )
782{
783   saturn_state *state = dmaspace.machine().driver_data<saturn_state>();
784
785   if(opcode & 0x08000000)
786   {
787      /*ENDI*/
788      dmaspace.machine().scheduler().timer_set(attotime::from_usec(300), FUNC(dsp_ended));
789   }
790
791   EXF_0; /* END / ENDI */
792}
793
794static void dsp_loop( void )
795{
796   if ( opcode & 0x8000000 )
797   {
798      /* LPS */
799      if ( dsp_reg.lop != 0 )
800      {
801         dsp_reg.lop--;
802         dsp_reg.delay = dsp_reg.pc;
803         dsp_reg.pc--;
804      }
805   }
806   else
807   {
808      /* BTM */
809      if ( dsp_reg.lop != 0 )
810      {
811         dsp_reg.lop--;
812         dsp_reg.delay = dsp_reg.pc;
813         dsp_reg.pc = dsp_reg.top;
814      }
815   }
816}
817
818#if DEBUG_DSP
819static void dsp_dump_mem( FILE *f )
820{
821   UINT16 i;
822
823   fprintf( f, "\n/*MEM 0*/\n{" );
824   for ( i = 0; i < 0x40; i++ )
825   {
826      fprintf( f, "%08X, ", dsp_reg.md0[ i ] );
827   }
828   fprintf( f, "}\n/*MEM 1*/\n{" );
829   for ( i = 0; i < 0x40; i++ )
830   {
831      fprintf( f, "%08X,", dsp_reg.md1[ i ] );
832   }
833   fprintf( f, "}\n/*MEM 2*/\n{" );
834   for ( i = 0; i < 0x40; i++ )
835   {
836      fprintf( f, "%08X,", dsp_reg.md2[ i ] );
837   }
838   fprintf( f, "}\n/*MEM 3*/\n{" );
839   for ( i = 0; i < 0x40; i++ )
840   {
841      fprintf( f, "%08X,", dsp_reg.md3[ i ] );
842   }
843   fprintf( f, "}\n" );
844}
845#endif
846
847void dsp_execute_program(address_space &dmaspace)
848{
849   UINT32 cycles_run = 0;
850   UINT8 cont = 1;
851#if DEBUG_DSP
852   UINT16 i;
853
854   if ( log_file == NULL )
855   {
856      log_file = fopen("dsp.log", "a");
857   }
858   for ( i = 0; i < 0x100; i++ )
859   {
860      dsp_dasm_opcode( dsp_reg.internal_prg[ i ], dasm_buffer );
861      fprintf( log_file, "%02X\t%08X\t%s\n", i, dsp_reg.internal_prg[ i ], dasm_buffer );
862   }
863   dsp_dump_mem( log_file );
864#endif
865
866   update_mul = 0;
867   do
868   {
869      if ( dsp_reg.delay )
870      {
871         opcode = dsp_reg.internal_prg[ dsp_reg.delay ];
872         dsp_reg.delay = 0;
873      }
874      else
875      {
876         opcode = dsp_reg.internal_prg[ dsp_reg.pc ];
877         dsp_reg.pc++;
878      }
879
880      dsp_dasm_opcode( opcode, dasm_buffer );
881
882      switch( (opcode & 0xc0000000) >> 30 )
883      {
884      case 0x00: /* 00 */
885         dsp_operation( dmaspace );
886         break;
887      case 0x01: /* 01 */
888         /* unrecognized opcode */
889         break;
890      case 0x02: /* 10 */
891         dsp_move_immediate( dmaspace );
892         break;
893      case 0x03: /* 11 */
894         switch( (opcode & 0x30000000) >> 28 )
895         {
896            case 0x00:
897               dsp_dma(dmaspace);
898               break;
899            case 0x01:
900               dsp_jump(dmaspace);
901               break;
902            case 0x02:
903               dsp_loop();
904               break;
905            case 0x03:
906               dsp_end(dmaspace);
907               cont = 0;
908               break;
909         }
910         break;
911      }
912      if ( update_mul == 1 )
913      {
914         dsp_reg.mul = (INT64)dsp_reg.rx.si * (INT64)dsp_reg.ry.si;
915         update_mul = 0;
916      }
917
918      cycles_run++;
919
920   } while( cont );
921#if DEBUG_DSP
922   dsp_dump_mem( log_file );
923   fprintf( log_file, "\nRun %d cycles\n\n", cycles_run );
924   fclose( log_file );
925   log_file = NULL;
926#endif
927}
928
929
930
931/***********************************************************************
932
933    SCU DSP Disassembler
934
935************************************************************************/
936static const char *const ALU_Commands[] =
937{
938   "",     /* 0000 */
939   "AND",  /* 0001 */
940   "OR",   /* 0010 */
941   "XOR",  /* 0011 */
942   "ADD",  /* 0100 */
943   "SUB",  /* 0101 */
944   "AD2",  /* 0110 */
945   "???",  /* 0111 */
946   "SR",   /* 1000 */
947   "RR",   /* 1001 */
948   "SL",   /* 1010 */
949   "RL",   /* 1011 */
950   "???",  /* 1100 */
951   "???",  /* 1101 */
952   "???",  /* 1110 */
953   "RL8",  /* 1111 */
954};
955
956static const char *const X_Commands[] =
957{
958   "",             /* 000 */
959   "",             /* 001 */   /* NOP? check instruction @ 0x0B */
960   "MOV MUL,P",    /* 010 */
961   "MOV %s,P",     /* 011 */
962   "MOV %s,X",     /* 100 */
963};
964
965static const char *const Y_Commands[] =
966{
967   "",             /* 000 */
968   "CLR A",        /* 001 */
969   "MOV ALU,A",    /* 010 */
970   "MOV %s,A",     /* 011 */
971   "MOV %s,Y",     /* 100 */
972};
973
974static const char *const D1_Commands[] =
975{
976   "",                 /* 00 */
977   "MOV %I8,%d",       /* 01 */
978   "???",              /* 10 */
979   "MOV %S,%d",        /* 11 */
980};
981
982static const char *const SourceMemory[] =
983{
984   "M0",           /* 000 */
985   "M1",           /* 001 */
986   "M2",           /* 010 */
987   "M3",           /* 011 */
988   "MC0",          /* 100 */
989   "MC1",          /* 101 */
990   "MC2",          /* 110 */
991   "MC3",          /* 111 */
992};
993
994static const char *const SourceMemory2[] =
995{
996   "M0",           /* 0000 */
997   "M1",           /* 0001 */
998   "M2",           /* 0010 */
999   "M3",           /* 0011 */
1000   "MC0",          /* 0100 */
1001   "MC1",          /* 0101 */
1002   "MC2",          /* 0110 */
1003   "MC3",          /* 0111 */
1004   "???",          /* 1000 */
1005   "ALL",          /* 1001 */
1006   "ALH",          /* 1010 */
1007   "???",          /* 1011 */
1008   "???",          /* 1100 */
1009   "???",          /* 1101 */
1010   "???",          /* 1110 */
1011   "???",          /* 1111 */
1012};
1013
1014static const char *const DestMemory[] =
1015{
1016   "MC0",          /* 0000 */
1017   "MC1",          /* 0001 */
1018   "MC2",          /* 0010 */
1019   "MC3",          /* 0011 */
1020   "RX",           /* 0100 */
1021   "PL",           /* 0101 */
1022   "RA0",          /* 0110 */
1023   "WA0",          /* 0111 */
1024   "???",          /* 1000 */
1025   "???",          /* 1001 */
1026   "LOP",          /* 1010 */
1027   "TOP",          /* 1011 */
1028   "CT0",          /* 1100 */
1029   "CT1",          /* 1101 */
1030   "CT2",          /* 1110 */
1031   "CT3",          /* 1111 */
1032};
1033
1034static const char *const DestDMAMemory[] =
1035{
1036   "M0",           /* 000 */
1037   "M1",           /* 001 */
1038   "M2",           /* 010 */
1039   "M3",           /* 011 */
1040   "PRG",          /* 100 */
1041   "???",          /* 101 */
1042   "???",          /* 110 */
1043   "???",          /* 111 */
1044};
1045
1046static const char *const MVI_Command[] =
1047{
1048   "MVI %I,%d",    /* 0 */
1049   "MVI %I,%d,%f", /* 1 */
1050};
1051
1052static const char *const JMP_Command[] =
1053{
1054   "JMP %IA",
1055   "JMP %f,%IA",
1056};
1057
1058static const char *const DMA_Command[] =
1059{
1060   "DMA%H%A D0,%M,%I",
1061   "DMA%H%A %s,D0,%I",
1062   "DMA%H%A D0,%M,%s",
1063   "DMA%H%A %s,D0,%s",
1064};
1065
1066
1067static void dsp_dasm_prefix( const char* format, char* buffer, UINT32 *data )
1068{
1069   for ( ; *format; format++ )
1070   {
1071      if ( *format == '%' )
1072      {
1073         switch( *++format )
1074         {
1075            case 'H':
1076               if ( *data )
1077               {
1078                  strcpy( buffer, "H" );
1079               }
1080               else
1081               {
1082                  *buffer = 0;
1083               }
1084               break;
1085            case 'A':
1086               if ( *data == 0 )
1087               {
1088                  strcpy( buffer, "0" );
1089               }
1090               else if ( *data == 1 )
1091               {
1092                  *buffer = 0;
1093               }
1094               else
1095               {
1096                  sprintf( buffer, "%d", 1 << (*data - 1) );
1097               }
1098               break;
1099            case 's':
1100               strcpy( buffer, SourceMemory[ *data & 0x7 ] );
1101               break;
1102            case 'd':
1103               strcpy( buffer, DestMemory[ *data & 0xf ] );
1104               break;
1105            case 'S':
1106               strcpy( buffer, SourceMemory2[ *data & 0xf ] );
1107               break;
1108            case 'I':
1109               ++format;
1110               if ( *format == '8' )
1111               {
1112                  sprintf( buffer, "#$%x", *data );
1113               }
1114               else if ( *format == 'A' )
1115               {
1116                  sprintf( buffer, "$%X", *data );
1117               }
1118               else
1119               {
1120                  --format;
1121                  sprintf( buffer, "#$%X", *data );
1122               }
1123               break;
1124            case 'f':
1125               if ( !(*data & 0x20) )
1126               {
1127                  strcpy( buffer, "N" );
1128                  buffer++;
1129               }
1130               switch( *data & 0xf )
1131               {
1132                  case 0x3:
1133                     strcpy( buffer, "ZS" );
1134                     break;
1135                  case 0x2:
1136                     strcpy( buffer, "S" );
1137                     break;
1138                  case 0x4:
1139                     strcpy( buffer, "C" );
1140                     break;
1141                  case 0x8:
1142                     strcpy( buffer, "T0" );
1143                     break;
1144                  case 0x1:
1145                     strcpy( buffer, "Z" );
1146                     break;
1147                  default:
1148                     strcpy( buffer, "?" );
1149                     break;
1150               }
1151               break;
1152            case 'M':
1153               strcpy( buffer, DestDMAMemory[ *data ] );
1154               break;
1155
1156         }
1157         data++;
1158         buffer += strlen( buffer );
1159      }
1160      else
1161      {
1162         *buffer++ = *format;
1163      }
1164   }
1165   *buffer = 0;
1166}
1167static void dsp_dasm_operation( UINT32 op, char *buffer )
1168{
1169   char *my_buffer = buffer;
1170   char temp_buffer[64];
1171   UINT32 data[2 ];
1172
1173   /* NOP */
1174   if ( (op & 0x3F8E3000) == 0 )
1175   {
1176      sprintf( buffer, "%-10s", "NOP" );
1177      return;
1178   }
1179   /* ALU */
1180   sprintf( my_buffer, "%-10s", ALU_Commands[ (op & 0x3c000000) >> 26] );
1181   my_buffer += strlen( my_buffer );
1182
1183   /* X-Bus */
1184   data[0] = (op & 0x700000) >> 20;
1185   if ( op & 0x2000000 )
1186   {
1187      dsp_dasm_prefix( X_Commands[ 4 ], temp_buffer, data );
1188   }
1189   else
1190   {
1191      *temp_buffer = 0;
1192   }
1193   sprintf( my_buffer, "%-10s", temp_buffer );
1194   my_buffer += strlen( my_buffer );
1195
1196   dsp_dasm_prefix( X_Commands[ (op & 0x1800000) >> 23 ], temp_buffer,  data );
1197   sprintf( my_buffer, "%-10s", temp_buffer );
1198   my_buffer += strlen( my_buffer );
1199
1200   /* Y-Bus */
1201   data[0] = (op & 0x1C000 ) >> 14 ;
1202   if ( op & 0x80000 )
1203   {
1204      dsp_dasm_prefix( Y_Commands[4], temp_buffer, data );
1205   }
1206   else
1207   {
1208      *temp_buffer = 0;
1209   }
1210   sprintf( my_buffer, "%-10s", temp_buffer );
1211   my_buffer += strlen( my_buffer );
1212
1213   dsp_dasm_prefix( Y_Commands[ (op & 0x60000) >> 17 ], temp_buffer,  data );
1214   sprintf( my_buffer, "%-10s", temp_buffer );
1215   my_buffer += strlen( my_buffer );
1216
1217   /* D1-Bus */
1218   switch( (op & 0x3000) >> 12 )
1219   {
1220   case 0x1:
1221      data[0] = (op & 0xFF);
1222      data[1] = ((op & 0xF00) >> 8);
1223      break;
1224   case 0x3:
1225      data[0] = (op & 0xF);
1226      data[1] = ((op & 0xF00) >> 8);
1227      break;
1228   };
1229   dsp_dasm_prefix( D1_Commands[ (op & 0x3000) >> 12 ], temp_buffer, data );
1230   sprintf( my_buffer, "%-10s", temp_buffer );
1231}
1232
1233static void dsp_dasm_move_immediate( UINT32 op, char *buffer )
1234{
1235   UINT32 data[3];
1236   if ( (op & 0x2000000) )
1237   {
1238      data[0] = op & 0x7FFFF;
1239      data[1] = (op & 0x3C000000) >> 26;
1240      data[2] = (op & 0x3F80000 ) >> 19;
1241      dsp_dasm_prefix( MVI_Command[1], buffer, data ); /* TODO: bad mem*/
1242   }
1243   else
1244   {
1245      data[0] = op & 0x1FFFFFF;
1246      data[1] = (op & 0x3C000000) >> 26;
1247      dsp_dasm_prefix( MVI_Command[0], buffer, data ); /* TODO: bad mem*/
1248   }
1249}
1250
1251static void dsp_dasm_jump( UINT32 op, char *buffer )
1252{
1253   UINT32 data[2];
1254   if ( op & 0x3F80000 )
1255   {
1256      data[0] = (op & 0x3F80000) >> 19;
1257      data[1] = op & 0xff;
1258      dsp_dasm_prefix( JMP_Command[1], buffer, data );
1259   }
1260   else
1261   {
1262      data[0] = op & 0xff;
1263      dsp_dasm_prefix( JMP_Command[0], buffer, data );
1264   }
1265}
1266
1267static void dsp_dasm_loop( UINT32 op, char* buffer )
1268{
1269   if ( op & 0x8000000 )
1270   {
1271      strcpy( buffer, "LPS" );
1272   }
1273   else
1274   {
1275      strcpy( buffer, "BTM" );
1276   }
1277}
1278
1279static void dsp_dasm_end( UINT32 op, char* buffer )
1280{
1281   if ( op & 0x8000000 )
1282   {
1283      strcpy( buffer, "ENDI" );
1284   }
1285   else
1286   {
1287      strcpy( buffer, "END" );
1288   }
1289}
1290
1291static void dsp_dasm_dma( UINT32 op, char* buffer )
1292{
1293   UINT32 data[4];
1294   data[0] = (op &  0x4000) >> 14; /* H */
1295   data[1] = (op & 0x38000) >> 15; /* A */
1296   data[2] = (op & 0x700) >> 8; /* Mem */
1297   data[3] = (op & 0xff);
1298   dsp_dasm_prefix( DMA_Command[(op & 0x3000) >> 12], buffer, data );
1299}
1300
1301static void dsp_dasm_opcode( UINT32 op, char *buffer )
1302{
1303   switch( (op & 0xc0000000) >> 30 )
1304   {
1305   case 0x00: /* 00 */
1306      dsp_dasm_operation( op, buffer );
1307      break;
1308   case 0x01: /* 01 */
1309      strcpy( buffer, "???"  );
1310      break;
1311   case 0x02: /* 10 */
1312      dsp_dasm_move_immediate( op, buffer );
1313      break;
1314   case 0x03: /* 11 */
1315      switch( (op & 0x30000000) >> 28 )
1316      {
1317         case 0x00:
1318            dsp_dasm_dma( op, buffer );
1319            break;
1320         case 0x01:
1321            dsp_dasm_jump( op, buffer );
1322            break;
1323         case 0x02:
1324            dsp_dasm_loop( op, buffer );
1325            break;
1326         case 0x03:
1327            dsp_dasm_end( op, buffer );
1328            break;
1329      }
1330      break;
1331   }
1332}
Property changes on: trunk/src/emu/machine/scudsp.c
Added: svn:eol-style
   + native
Added: svn:mime-type
   + text/plain
trunk/src/emu/machine/scudsp.h
r0r20947
1/*SCU DSP stuff*/
2
3void dsp_prg_ctrl_w(address_space &space, UINT32 data);
4void dsp_prg_data(UINT32 data);
5void dsp_ram_addr_ctrl(UINT32 data);
6void dsp_ram_addr_w(UINT32 data);
7UINT32 dsp_prg_ctrl_r(address_space &space);
8UINT32 dsp_ram_addr_r(void);
9void dsp_execute_program(address_space &dmaspace);
Property changes on: trunk/src/emu/machine/scudsp.h
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/emu/machine/smpc.c
r0r20947
1/************************************************************************************
2
3Sega Saturn SMPC - System Manager and Peripheral Control MCU simulation
4
5The SMPC is actually a 4-bit Hitachi HD404920FS MCU, labeled with a Sega custom
6315-5744 (that needs decapping)
7
8MCU simulation by Angelo Salese & R. Belmont
9
10TODO:
11- timings;
12- fix intback issue with inputs (according to the docs, it should fall in between
13  VBLANK-IN and OUT, for obvious reasons);
14- clean-ups;
15
16*************************************************************************************/
17/* SMPC Addresses
18
1900
2001 -w  Input Register 0 (IREG)
2102
2203 -w  Input Register 1
2304
2405 -w  Input Register 2
2506
2607 -w  Input Register 3
2708
2809 -w  Input Register 4
290a
300b -w  Input Register 5
310c
320d -w  Input Register 6
330e
340f
3510
3611
3712
3813
3914
4015
4116
4217
4318
4419
451a
461b
471c
481d
491e
501f -w  Command Register (COMREG)
5120
5221 r-  Output Register 0 (OREG)
5322
5423 r-  Output Register 1
5524
5625 r-  Output Register 2
5726
5827 r-  Output Register 3
5928
6029 r-  Output Register 4
612a
622b r-  Output Register 5
632c
642d r-  Output Register 6
652e
662f r-  Output Register 7
6730
6831 r-  Output Register 8
6932
7033 r-  Output Register 9
7134
7235 r-  Output Register 10
7336
7437 r-  Output Register 11
7538
7639 r-  Output Register 12
773a
783b r-  Output Register 13
793c
803d r-  Output Register 14
813e
823f r-  Output Register 15
8340
8441 r-  Output Register 16
8542
8643 r-  Output Register 17
8744
8845 r-  Output Register 18
8946
9047 r-  Output Register 19
9148
9249 r-  Output Register 20
934a
944b r-  Output Register 21
954c
964d r-  Output Register 22
974e
984f r-  Output Register 23
9950
10051 r-  Output Register 24
10152
10253 r-  Output Register 25
10354
10455 r-  Output Register 26
10556
10657 r-  Output Register 27
10758
10859 r-  Output Register 28
1095a
1105b r-  Output Register 29
1115c
1125d r-  Output Register 30
1135e
1145f r-  Output Register 31
11560
11661 r-  SR
11762
11863 rw  SF
11964
12065
12166
12267
12368
12469
1256a
1266b
1276c
1286d
1296e
1306f
13170
13271
13372
13473
13574
13675 rw PDR1
13776
13877 rw PDR2
13978
14079 -w DDR1
1417a
1427b -w DDR2
1437c
1447d -w IOSEL2/1
1457e
1467f -w EXLE2/1
147*/
148
149#include "emu.h"
150#include "coreutil.h"
151#include "includes/stv.h"
152#include "machine/smpc.h"
153#include "machine/eeprom.h"
154
155#define LOG_SMPC 0
156#define LOG_PAD_CMD 0
157
158#if 0
159/* TODO: move this into video functions */
160static int vblank_line(running_machine &machine)
161{
162   saturn_state *state = machine.driver_data<saturn_state>();
163   int max_y = machine.primary_screen->height();
164   int y_step,vblank_line;
165
166   y_step = 2;
167
168   if((max_y == 263 && state->m_vdp2.pal == 0) || (max_y == 313 && state->m_vdp2.pal == 1))
169      y_step = 1;
170
171   vblank_line = (state->m_vdp2.pal) ? 288 : 240;
172
173   return vblank_line*y_step;
174}
175#endif
176
177
178/********************************************
179 *
180 * Bankswitch code for ST-V Multi Cart mode
181 *
182 *******************************************/
183
184static TIMER_CALLBACK( stv_bankswitch_state )
185{
186   saturn_state *state = machine.driver_data<saturn_state>();
187   static const char *const banknames[] = { "game0", "game1", "game2", "game3" };
188   UINT8* game_region;
189
190   if(state->m_prev_bankswitch != param)
191   {
192      game_region = machine.root_device().memregion(banknames[param])->base();
193
194      if (game_region)
195         memcpy(machine.root_device().memregion("abus")->base(), game_region, 0x3000000);
196      else
197         memset(machine.root_device().memregion("abus")->base(), 0x00, 0x3000000);
198
199      state->m_prev_bankswitch = param;
200   }
201}
202
203static void stv_select_game(running_machine &machine, int gameno)
204{
205   machine.scheduler().timer_set(attotime::zero, FUNC(stv_bankswitch_state), gameno);
206}
207
208/********************************************
209 *
210 * Command functions
211 *
212 *******************************************/
213
214static void smpc_master_on(running_machine &machine)
215{
216   saturn_state *state = machine.driver_data<saturn_state>();
217
218   state->m_maincpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
219}
220
221static TIMER_CALLBACK( smpc_slave_enable )
222{
223   saturn_state *state = machine.driver_data<saturn_state>();
224
225   state->m_slave->set_input_line(INPUT_LINE_RESET, param ? ASSERT_LINE : CLEAR_LINE);
226   state->m_smpc.OREG[31] = param + 0x02; //read-back for last command issued
227   state->m_smpc.SF = 0x00; //clear hand-shake flag
228   state->m_smpc.slave_on = param;
229//  printf("%d %d\n",machine.primary_screen->hpos(),machine.primary_screen->vpos());
230}
231
232static TIMER_CALLBACK( smpc_sound_enable )
233{
234   saturn_state *state = machine.driver_data<saturn_state>();
235
236   state->m_audiocpu->set_input_line(INPUT_LINE_RESET, param ? ASSERT_LINE : CLEAR_LINE);
237   state->m_en_68k = param ^ 1;
238   state->m_smpc.OREG[31] = param + 0x06; //read-back for last command issued
239   state->m_smpc.SF = 0x00; //clear hand-shake flag
240}
241
242static void smpc_system_reset(running_machine &machine)
243{
244   saturn_state *state = machine.driver_data<saturn_state>();
245
246   /*Only backup ram and SMPC ram are retained after that this command is issued.*/
247   memset(state->m_scu_regs ,0x00,0x000100);
248   memset(state->m_scsp_regs,0x00,0x001000);
249   memset(state->m_sound_ram,0x00,0x080000);
250   memset(state->m_workram_h,0x00,0x100000);
251   memset(state->m_workram_l,0x00,0x100000);
252   memset(state->m_vdp2_regs,0x00,0x040000);
253   memset(state->m_vdp2_vram,0x00,0x100000);
254   memset(state->m_vdp2_cram,0x00,0x080000);
255   memset(state->m_vdp1_vram,0x00,0x100000);
256   //A-Bus
257
258   state->m_maincpu->set_input_line(INPUT_LINE_RESET, PULSE_LINE);
259}
260
261static TIMER_CALLBACK( smpc_change_clock )
262{
263   saturn_state *state = machine.driver_data<saturn_state>();
264   UINT32 xtal;
265
266   if(LOG_SMPC) printf ("Clock change execute at (%d %d)\n",machine.primary_screen->hpos(),machine.primary_screen->vpos());
267
268   xtal = param ? MASTER_CLOCK_320 : MASTER_CLOCK_352;
269
270   machine.device("maincpu")->set_unscaled_clock(xtal/2);
271   machine.device("slave")->set_unscaled_clock(xtal/2);
272
273   state->m_vdp2.dotsel = param ^ 1;
274   state->stv_vdp2_dynamic_res_change();
275
276   if(!state->m_NMI_reset)
277      state->m_maincpu->set_input_line(INPUT_LINE_NMI, PULSE_LINE);
278   state->m_slave->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
279
280   /* put issued command in OREG31 */
281   state->m_smpc.OREG[31] = 0x0e + param;
282   /* clear hand-shake flag */
283   state->m_smpc.SF = 0x00;
284
285   /* TODO: VDP1 / VDP2 / SCU / SCSP default power ON values? */
286}
287
288static TIMER_CALLBACK( stv_smpc_intback )
289{
290   saturn_state *state = machine.driver_data<saturn_state>();
291   int i;
292
293   state->m_smpc.OREG[0] = (0x80) | ((state->m_NMI_reset & 1) << 6);
294
295   for(i=0;i<7;i++)
296      state->m_smpc.OREG[1+i] = state->m_smpc.rtc_data[i];
297
298   state->m_smpc.OREG[8]=0x00;  // CTG0 / CTG1?
299
300   state->m_smpc.OREG[9]=0x00;  // TODO: system region on Saturn
301
302   state->m_smpc.OREG[10]= 0 << 7 |
303                        state->m_vdp2.dotsel << 6 |
304                        1 << 5 |
305                        1 << 4 |
306                        0 << 3 | //MSHNMI
307                        1 << 2 |
308                        0 << 1 | //SYSRES
309                        0 << 0;  //SOUNDRES
310   state->m_smpc.OREG[11]= 0 << 6; //CDRES
311
312   for(i=0;i<4;i++)
313      state->m_smpc.OREG[12+i]=state->m_smpc.SMEM[i];
314
315   for(i=0;i<15;i++)
316      state->m_smpc.OREG[16+i]=0xff; // undefined
317
318   //  /*This is for RTC,cartridge code and similar stuff...*/
319   //if(LOG_SMPC) printf ("Interrupt: System Manager (SMPC) at scanline %04x, Vector 0x47 Level 0x08\n",scanline);
320   if(!(state->m_scu.ism & IRQ_SMPC))
321      state->m_maincpu->set_input_line_and_vector(8, HOLD_LINE, 0x47);
322   else
323      state->m_scu.ist |= (IRQ_SMPC);
324
325   /* put issued command in OREG31 */
326   state->m_smpc.OREG[31] = 0x10; // TODO: doc says 0?
327   /* clear hand-shake flag */
328   state->m_smpc.SF = 0x00;
329}
330
331/*
332    [0] port status:
333        0x04 Sega-tap
334        0x16 Multi-tap
335        0x2x clock serial peripheral
336        0xf0 peripheral isn't connected
337        0xf1 peripheral is connected
338    [1] Peripheral ID (note: lowest four bits determines the size of the input packet)
339        0x02 digital pad
340        0x25 (tested by Game Basic?)
341        0x34 keyboard
342*/
343
344static void smpc_digital_pad(running_machine &machine, UINT8 pad_num, UINT8 offset)
345{
346   saturn_state *state = machine.driver_data<saturn_state>();
347   static const char *const padnames[] = { "JOY1", "JOY2" };
348   UINT16 pad_data;
349
350   pad_data = machine.root_device().ioport(padnames[pad_num])->read();
351   state->m_smpc.OREG[0+pad_num*offset] = 0xf1;
352   state->m_smpc.OREG[1+pad_num*offset] = 0x02;
353   state->m_smpc.OREG[2+pad_num*offset] = pad_data>>8;
354   state->m_smpc.OREG[3+pad_num*offset] = pad_data & 0xff;
355}
356
357static void smpc_analog_pad(running_machine &machine, UINT8 pad_num, UINT8 offset, UINT8 id)
358{
359   saturn_state *state = machine.driver_data<saturn_state>();
360   static const char *const padnames[] = { "AN_JOY1", "AN_JOY2" };
361   static const char *const annames[2][3] = { { "AN_X1", "AN_Y1", "AN_Z1" },
362                                    { "AN_X2", "AN_Y2", "AN_Z2" }};
363   UINT16 pad_data;
364
365   pad_data = machine.root_device().ioport(padnames[pad_num])->read();
366   state->m_smpc.OREG[0+pad_num*offset] = 0xf1;
367   state->m_smpc.OREG[1+pad_num*offset] = id;
368   state->m_smpc.OREG[2+pad_num*offset] = pad_data>>8;
369   state->m_smpc.OREG[3+pad_num*offset] = pad_data & 0xff;
370   state->m_smpc.OREG[4+pad_num*offset] = machine.root_device().ioport(annames[pad_num][0])->read();
371   if(id == 0x15)
372   {
373      state->m_smpc.OREG[5+pad_num*offset] = machine.root_device().ioport(annames[pad_num][1])->read();
374      state->m_smpc.OREG[6+pad_num*offset] = machine.root_device().ioport(annames[pad_num][2])->read();
375   }
376}
377
378static void smpc_keyboard(running_machine &machine, UINT8 pad_num, UINT8 offset)
379{
380   saturn_state *state = machine.driver_data<saturn_state>();
381   UINT16 game_key;
382
383   game_key = 0xffff;
384
385   game_key ^= ((state->ioport("KEYS_1")->read() & 0x80) << 8); // right
386   game_key ^= ((state->ioport("KEYS_1")->read() & 0x40) << 8); // left
387   game_key ^= ((state->ioport("KEYS_1")->read() & 0x20) << 8); // down
388   game_key ^= ((state->ioport("KEYS_1")->read() & 0x10) << 8); // up
389   game_key ^= ((state->ioport("KEYF")->read() & 0x80) << 4); // ESC -> START
390   game_key ^= ((state->ioport("KEY3")->read() & 0x04) << 8); // Z / A trigger
391   game_key ^= ((state->ioport("KEY4")->read() & 0x02) << 8); // C / C trigger
392   game_key ^= ((state->ioport("KEY6")->read() & 0x04) << 6); // X / B trigger
393   game_key ^= ((state->ioport("KEY2")->read() & 0x20) << 2); // Q / R trigger
394   game_key ^= ((state->ioport("KEY3")->read() & 0x10) << 2); // A / X trigger
395   game_key ^= ((state->ioport("KEY3")->read() & 0x08) << 2); // S / Y trigger
396   game_key ^= ((state->ioport("KEY4")->read() & 0x08) << 1); // D / Z trigger
397   game_key ^= ((state->ioport("KEY4")->read() & 0x10) >> 1); // E / L trigger
398
399   state->m_smpc.OREG[0+pad_num*offset] = 0xf1;
400   state->m_smpc.OREG[1+pad_num*offset] = 0x34;
401   state->m_smpc.OREG[2+pad_num*offset] = game_key>>8; // game buttons, TODO
402   state->m_smpc.OREG[3+pad_num*offset] = game_key & 0xff;
403   /*
404       x--- ---- 0
405       -x-- ---- caps lock
406       --x- ---- num lock
407       ---x ---- scroll lock
408       ---- x--- data ok
409       ---- -x-- 1
410       ---- --x- 1
411       ---- ---x Break key
412   */
413   state->m_smpc.OREG[4+pad_num*offset] = state->m_keyb.status | 6;
414   state->m_smpc.OREG[5+pad_num*offset] = state->m_keyb.data;
415}
416
417static void smpc_mouse(running_machine &machine, UINT8 pad_num, UINT8 offset, UINT8 id)
418{
419   saturn_state *state = machine.driver_data<saturn_state>();
420   static const char *const mousenames[2][3] = { { "MOUSEB1", "MOUSEX1", "MOUSEY1" },
421                                       { "MOUSEB2", "MOUSEX2", "MOUSEY2" }};
422   UINT8 mouse_ctrl;
423   INT16 mouse_x, mouse_y;
424
425   mouse_ctrl = machine.root_device().ioport(mousenames[pad_num][0])->read();
426   mouse_x = machine.root_device().ioport(mousenames[pad_num][1])->read();
427   mouse_y = machine.root_device().ioport(mousenames[pad_num][2])->read();
428
429   if(mouse_x < 0)
430      mouse_ctrl |= 0x10;
431
432   if(mouse_y < 0)
433      mouse_ctrl |= 0x20;
434
435   if((mouse_x & 0xff00) != 0xff00 && (mouse_x & 0xff00) != 0x0000)
436      mouse_ctrl |= 0x40;
437
438   if((mouse_y & 0xff00) != 0xff00 && (mouse_y & 0xff00) != 0x0000)
439      mouse_ctrl |= 0x80;
440
441   state->m_smpc.OREG[0+pad_num*offset] = 0xf1;
442   state->m_smpc.OREG[1+pad_num*offset] = id; // 0x23 / 0xe3
443   state->m_smpc.OREG[2+pad_num*offset] = mouse_ctrl;
444   state->m_smpc.OREG[3+pad_num*offset] = mouse_x & 0xff;
445   state->m_smpc.OREG[4+pad_num*offset] = mouse_y & 0xff;
446}
447
448/* TODO: is there ANY game on which the MD pad works? */
449static void smpc_md_pad(running_machine &machine, UINT8 pad_num, UINT8 offset, UINT8 id)
450{
451   saturn_state *state = machine.driver_data<saturn_state>();
452   static const char *const padnames[] = { "MD_JOY1", "MD_JOY2" };
453   UINT16 pad_data;
454
455   pad_data = machine.root_device().ioport(padnames[pad_num])->read();
456   state->m_smpc.OREG[0+pad_num*offset] = 0xf1;
457   state->m_smpc.OREG[1+pad_num*offset] = id;
458   state->m_smpc.OREG[2+pad_num*offset] = pad_data>>8;
459   if(id == 0xe2) // MD 6 Button PAD
460      state->m_smpc.OREG[3+pad_num*offset] = pad_data & 0xff;
461}
462
463static void smpc_unconnected(running_machine &machine, UINT8 pad_num, UINT8 offset)
464{
465   saturn_state *state = machine.driver_data<saturn_state>();
466
467   state->m_smpc.OREG[0+pad_num*offset] = 0xf0;
468}
469
470static TIMER_CALLBACK( intback_peripheral )
471{
472   saturn_state *state = machine.driver_data<saturn_state>();
473   int pad_num;
474   static const UINT8 peri_id[10] = { 0x02, 0x13, 0x15, 0x23, 0x23, 0x34, 0xe1, 0xe2, 0xe3, 0xff };
475   UINT8 read_id[2];
476   UINT8 offset;
477
478//  if (LOG_SMPC) logerror("SMPC: providing PAD data for intback, pad %d\n", intback_stage-2);
479
480   read_id[0] = (machine.root_device().ioport("INPUT_TYPE")->read()) & 0x0f;
481   read_id[1] = (machine.root_device().ioport("INPUT_TYPE")->read()) >> 4;
482
483   /* doesn't work? */
484   //pad_num = state->m_smpc.intback_stage - 1;
485
486   if(LOG_PAD_CMD) printf("%d %d %d\n",state->m_smpc.intback_stage - 1,machine.primary_screen->vpos(),(int)machine.primary_screen->frame_number());
487
488   offset = 0;
489
490   for(pad_num=0;pad_num<2;pad_num++)
491   {
492      switch(read_id[pad_num])
493      {
494         case 0: smpc_digital_pad(machine,pad_num,offset); break;
495         case 1: smpc_analog_pad(machine,pad_num,offset,peri_id[read_id[pad_num]]); break; /* Steering Wheel */
496         case 2: smpc_analog_pad(machine,pad_num,offset,peri_id[read_id[pad_num]]); break; /* Analog Pad */
497         case 4: smpc_mouse(machine,pad_num,offset,peri_id[read_id[pad_num]]); break; /* Pointing Device */
498         case 5: smpc_keyboard(machine,pad_num,offset); break;
499         case 6: smpc_md_pad(machine,pad_num,offset,peri_id[read_id[pad_num]]); break; /* MD 3B PAD */
500         case 7: smpc_md_pad(machine,pad_num,offset,peri_id[read_id[pad_num]]); break; /* MD 6B PAD */
501         case 8: smpc_mouse(machine,pad_num,offset,peri_id[read_id[pad_num]]); break; /* Saturn Mouse */
502         case 9: smpc_unconnected(machine,pad_num,offset); break;
503      }
504
505      offset += (peri_id[read_id[pad_num]] & 0xf) + 2; /* offset for port 2 */
506   }
507
508   if (state->m_smpc.intback_stage == 2)
509   {
510      state->m_smpc.SR = (0x80 | state->m_smpc.pmode);    // pad 2, no more data, echo back pad mode set by intback
511      state->m_smpc.intback_stage = 0;
512   }
513   else
514   {
515      state->m_smpc.SR = (0xc0 | state->m_smpc.pmode);    // pad 1, more data, echo back pad mode set by intback
516      state->m_smpc.intback_stage ++;
517   }
518
519   if(!(state->m_scu.ism & IRQ_SMPC))
520      state->m_maincpu->set_input_line_and_vector(8, HOLD_LINE, 0x47);
521   else
522      state->m_scu.ist |= (IRQ_SMPC);
523
524   state->m_smpc.OREG[31] = 0x10; /* callback for last command issued */
525   state->m_smpc.SF = 0x00;    /* clear hand-shake flag */
526}
527
528static TIMER_CALLBACK( saturn_smpc_intback )
529{
530   saturn_state *state = machine.driver_data<saturn_state>();
531
532   if(state->m_smpc.intback_buf[0] != 0)
533   {
534      {
535         int i;
536
537         state->m_smpc.OREG[0] = (0x80) | ((state->m_NMI_reset & 1) << 6); // bit 7: SETTIME (RTC isn't setted up properly)
538
539         for(i=0;i<7;i++)
540            state->m_smpc.OREG[1+i] = state->m_smpc.rtc_data[i];
541
542         state->m_smpc.OREG[8]=0x00;  //Cartridge code?
543
544         state->m_smpc.OREG[9] = state->m_saturn_region;
545
546         state->m_smpc.OREG[10]= 0 << 7 |
547                              state->m_vdp2.dotsel << 6 |
548                              1 << 5 |
549                              1 << 4 |
550                              0 << 3 | //MSHNMI
551                              1 << 2 |
552                              0 << 1 | //SYSRES
553                              0 << 0;  //SOUNDRES
554         state->m_smpc.OREG[11]= 0 << 6; //CDRES
555
556         for(i=0;i<4;i++)
557            state->m_smpc.OREG[12+i]=state->m_smpc.SMEM[i];
558
559         for(i=0;i<15;i++)
560            state->m_smpc.OREG[16+i]=0xff; // undefined
561      }
562
563      state->m_smpc.intback_stage = (state->m_smpc.intback_buf[1] & 8) >> 3; // first peripheral
564      state->m_smpc.SR = 0x40 | state->m_smpc.intback_stage << 5;
565      state->m_smpc.pmode = state->m_smpc.intback_buf[0]>>4;
566
567      if(!(state->m_scu.ism & IRQ_SMPC))
568         state->m_maincpu->set_input_line_and_vector(8, HOLD_LINE, 0x47);
569      else
570         state->m_scu.ist |= (IRQ_SMPC);
571
572      /* put issued command in OREG31 */
573      state->m_smpc.OREG[31] = 0x10;
574      /* clear hand-shake flag */
575      state->m_smpc.SF = 0x00;
576   }
577   else if(state->m_smpc.intback_buf[1] & 8)
578   {
579      state->m_smpc.intback_stage = (state->m_smpc.intback_buf[1] & 8) >> 3; // first peripheral
580      state->m_smpc.SR = 0x40;
581      state->m_smpc.OREG[31] = 0x10;
582      machine.scheduler().timer_set(attotime::from_usec(0), FUNC(intback_peripheral),0);
583   }
584   else
585   {
586      printf("SMPC intback bogus behaviour called %02x %02x\n",state->m_smpc.IREG[0],state->m_smpc.IREG[1]);
587   }
588
589}
590
591static void smpc_rtc_write(running_machine &machine)
592{
593   saturn_state *state = machine.driver_data<saturn_state>();
594   int i;
595
596   for(i=0;i<7;i++)
597      state->m_smpc.rtc_data[i] = state->m_smpc.IREG[i];
598}
599
600static void smpc_memory_setting(running_machine &machine)
601{
602   saturn_state *state = machine.driver_data<saturn_state>();
603   int i;
604
605   for(i=0;i<4;i++)
606      state->m_smpc.SMEM[i] = state->m_smpc.IREG[i];
607}
608
609static void smpc_nmi_req(running_machine &machine)
610{
611   saturn_state *state = machine.driver_data<saturn_state>();
612
613   /*NMI is unconditionally requested */
614   state->m_maincpu->set_input_line(INPUT_LINE_NMI, PULSE_LINE);
615}
616
617static TIMER_CALLBACK( smpc_nmi_set )
618{
619   saturn_state *state = machine.driver_data<saturn_state>();
620
621//  printf("%d %d\n",machine.primary_screen->hpos(),machine.primary_screen->vpos());
622   state->m_NMI_reset = param;
623   /* put issued command in OREG31 */
624   state->m_smpc.OREG[31] = 0x19 + param;
625   /* clear hand-shake flag */
626   state->m_smpc.SF = 0x00;
627
628   //state->m_smpc.OREG[0] = (0x80) | ((state->m_NMI_reset & 1) << 6);
629}
630
631
632/********************************************
633 *
634 * COMREG sub-routine
635 *
636 *******************************************/
637
638static void smpc_comreg_exec(address_space &space, UINT8 data, UINT8 is_stv)
639{
640   saturn_state *state = space.machine().driver_data<saturn_state>();
641
642   switch (data)
643   {
644      case 0x00:
645         if(LOG_SMPC) printf ("SMPC: Master ON\n");
646         smpc_master_on(space.machine());
647         break;
648      //case 0x01: Master OFF?
649      case 0x02:
650      case 0x03:
651         if(LOG_SMPC) printf ("SMPC: Slave %s %d %d\n",(data & 1) ? "off" : "on",space.machine().primary_screen->hpos(),space.machine().primary_screen->vpos());
652         if((data & 1) != (state->m_smpc.slave_on & 1))
653            space.machine().scheduler().timer_set(attotime::from_usec(100), FUNC(smpc_slave_enable),data & 1);
654         else /* guess: if Slave state is equal to the previous one, just execute less code. ask Greatest Nine '97. Unless SMPC is really so fast ... */
655            space.machine().scheduler().timer_set(attotime::from_usec(5), FUNC(smpc_slave_enable),data & 1);
656         break;
657      case 0x06:
658      case 0x07:
659         if(LOG_SMPC) printf ("SMPC: Sound %s\n",(data & 1) ? "off" : "on");
660
661         if(!is_stv)
662            space.machine().scheduler().timer_set(attotime::from_usec(100), FUNC(smpc_sound_enable),data & 1);
663         break;
664      /*CD (SH-1) ON/OFF */
665      //case 0x08:
666      //case 0x09:
667      case 0x0d:
668         if(LOG_SMPC) printf ("SMPC: System Reset\n");
669         smpc_system_reset(space.machine());
670         break;
671      case 0x0e:
672      case 0x0f:
673         if(LOG_SMPC) printf ("SMPC: Change Clock to %s (%d %d)\n",data & 1 ? "320" : "352",space.machine().primary_screen->hpos(),space.machine().primary_screen->vpos());
674
675         /* on ST-V timing of this is pretty fussy, you get 2 credits at start-up otherwise
676            sokyugurentai threshold is 74 lines
677            shanhigw threshold is 90 lines
678            I assume that it needs ~100 lines, so 6666,(6) usecs. Obviously needs HW tests ... */
679
680         space.machine().scheduler().timer_set(attotime::from_usec(6666), FUNC(smpc_change_clock),data & 1);
681         break;
682      /*"Interrupt Back"*/
683      case 0x10:
684         if(0)
685         {
686            saturn_state *state = space.machine().driver_data<saturn_state>();
687            printf ("SMPC: Status Acquire %02x %02x %02x %d\n",state->m_smpc.IREG[0],state->m_smpc.IREG[1],state->m_smpc.IREG[2],space.machine().primary_screen->vpos());
688         }
689
690         if(is_stv)
691            space.machine().scheduler().timer_set(attotime::from_usec(700), FUNC(stv_smpc_intback),0); //TODO: variable time
692         else
693         {
694            int timing;
695
696            timing = 100;
697
698            if(state->m_smpc.IREG[0] != 0) // non-peripheral data
699               timing += 100;
700
701            if(state->m_smpc.IREG[1] & 8) // peripheral data
702               timing += 700;
703
704            /* TODO: check if IREG[2] is setted to 0xf0 */
705            {
706               int i;
707
708               for(i=0;i<3;i++)
709                  state->m_smpc.intback_buf[i] = state->m_smpc.IREG[i];
710            }
711
712            if(LOG_PAD_CMD) printf("INTBACK %02x %02x %d %d\n",state->m_smpc.IREG[0],state->m_smpc.IREG[1],space.machine().primary_screen->vpos(),(int)space.machine().primary_screen->frame_number());
713            space.machine().scheduler().timer_set(attotime::from_usec(timing), FUNC(saturn_smpc_intback),0); //TODO: is variable time correct?
714         }
715         break;
716      /* RTC write*/
717      case 0x16:
718         if(LOG_SMPC) printf("SMPC: RTC write\n");
719         smpc_rtc_write(space.machine());
720         break;
721      /* SMPC memory setting*/
722      case 0x17:
723         if(LOG_SMPC) printf ("SMPC: memory setting\n");
724         smpc_memory_setting(space.machine());
725         break;
726      case 0x18:
727         if(LOG_SMPC) printf ("SMPC: NMI request\n");
728         smpc_nmi_req(space.machine());
729         break;
730      case 0x19:
731      case 0x1a:
732         if(LOG_SMPC) printf ("SMPC: NMI %sable %d %d\n",data & 1 ? "Dis" : "En",space.machine().primary_screen->hpos(),space.machine().primary_screen->vpos());
733         space.machine().scheduler().timer_set(attotime::from_usec(100), FUNC(smpc_nmi_set),data & 1);
734         break;
735      default:
736         printf ("cpu '%s' (PC=%08X) SMPC: undocumented Command %02x\n", space.device().tag(), space.device().safe_pc(), data);
737   }
738}
739
740/********************************************
741 *
742 * ST-V handlers
743 *
744 *******************************************/
745
746READ8_HANDLER( stv_SMPC_r )
747{
748   saturn_state *state = space.machine().driver_data<saturn_state>();
749   int return_data = 0;
750
751   if(!(offset & 1))
752      return 0;
753
754   if(offset >= 0x21 && offset <= 0x5f)
755      return_data = state->m_smpc.OREG[(offset-0x21) >> 1];
756
757   if (offset == 0x61) // TODO: SR
758      return_data = 0x20 ^ 0xff;
759
760   if (offset == 0x63)
761      return_data = state->m_smpc.SF;
762
763   if (offset == 0x75)//PDR1 read
764      return_data = state->ioport("DSW1")->read();
765
766   if (offset == 0x77)//PDR2 read
767      return_data = (0xfe | space.machine().device<eeprom_device>("eeprom")->read_bit());
768
769   return return_data;
770}
771
772WRITE8_HANDLER( stv_SMPC_w )
773{
774   saturn_state *state = space.machine().driver_data<saturn_state>();
775
776   if (!(offset & 1)) // avoid writing to even bytes
777      return;
778
779//  if(LOG_SMPC) printf ("8-bit SMPC Write to Offset %02x with Data %02x\n", offset, data);
780
781   if(offset >= 1 && offset <= 0xd)
782      state->m_smpc.IREG[offset >> 1] = data;
783
784   if (offset == 0x1f) // COMREG
785   {
786      smpc_comreg_exec(space,data,1);
787
788      // we've processed the command, clear status flag
789      if(data != 0x10 && data != 0x02 && data != 0x03 && data != 0xe && data != 0xf && data != 0x19 && data != 0x1a)
790      {
791         state->m_smpc.OREG[31] = data; //read-back command
792         state->m_smpc.SF = 0x00;
793      }
794      /*TODO:emulate the timing of each command...*/
795   }
796
797   if(offset == 0x63)
798      state->m_smpc.SF = data & 1;
799
800   if(offset == 0x75)
801   {
802      /*
803      -xx- ---- PDR1
804      ---x ---- EEPROM write bit
805      ---- x--- EEPROM CLOCK line
806      ---- -x-- EEPROM CS line
807      ---- --xx A-Bus bank bits
808      */
809      eeprom_device *eeprom = space.machine().device<eeprom_device>("eeprom");
810      eeprom->set_clock_line((data & 0x08) ? ASSERT_LINE : CLEAR_LINE);
811      eeprom->write_bit(data & 0x10);
812      eeprom->set_cs_line((data & 0x04) ? CLEAR_LINE : ASSERT_LINE);
813      state->m_stv_multi_bank = data & 3;
814
815      stv_select_game(space.machine(), state->m_stv_multi_bank);
816
817      state->m_smpc.PDR1 = (data & 0x60);
818   }
819
820   if(offset == 0x77)
821   {
822      /*
823          -xx- ---- PDR2
824          ---x ---- Enable Sound System (ACTIVE LOW)
825      */
826      //popmessage("PDR2 = %02x",state->m_smpc_ram[0x77]);
827
828      if(LOG_SMPC) printf("SMPC: M68k %s\n",(data & 0x10) ? "off" : "on");
829      //space.machine().scheduler().timer_set(attotime::from_usec(100), FUNC(smpc_sound_enable),(state->m_smpc_ram[0x77] & 0x10) >> 4);
830      state->m_audiocpu->set_input_line(INPUT_LINE_RESET, (data & 0x10) ? ASSERT_LINE : CLEAR_LINE);
831      state->m_en_68k = ((data & 0x10) >> 4) ^ 1;
832
833      //if(LOG_SMPC) printf("SMPC: ram [0x77] = %02x\n",data);
834      state->m_smpc.PDR2 = (data & 0x60);
835   }
836
837   if(offset == 0x7d)
838   {
839      /*
840      ---- --x- IOSEL2 direct (1) / control mode (0) port select
841      ---- ---x IOSEL1 direct (1) / control mode (0) port select
842      */
843      state->m_smpc.IOSEL1 = (data & 1) >> 0;
844      state->m_smpc.IOSEL2 = (data & 2) >> 1;
845   }
846
847   if(offset == 0x7f)
848   {
849      //enable PAD irq & VDP2 external latch for port 1/2
850      state->m_smpc.EXLE1 = (data & 1) >> 0;
851      state->m_smpc.EXLE2 = (data & 2) >> 1;
852   }
853}
854
855/********************************************
856 *
857 * Saturn handlers
858 *
859 *******************************************/
860
861UINT8 saturn_state::smpc_th_control_mode(UINT8 pad_n)
862{
863   int th;
864   const char *const padnames[] = { "JOY1", "JOY2" };
865   UINT8 res = 0;
866
867   th = (pad_n == 0) ? ((m_smpc.PDR1>>5) & 3) : ((m_smpc.PDR2>>6) & 3);
868
869   if (LOG_SMPC) printf("SMPC: SH-2 TH control mode, returning pad data %d for phase %d\n",pad_n+1, th);
870
871   switch(th)
872   {
873      /* TODO: 3D Lemmings bogusly enables TH Control mode, wants this to return the ID, needs HW tests.  */
874      case 3:
875         res = th<<6;
876         res |= 0x14;
877         res |= machine().root_device().ioport(padnames[pad_n])->read() & 8; // L
878         break;
879      case 2:
880         res = th<<6;
881         //  1 C B Right Left Down Up
882         res|= (((machine().root_device().ioport(padnames[pad_n])->read()>>4)) & 0x30); // C & B
883         res|= (((machine().root_device().ioport(padnames[pad_n])->read()>>12)) & 0xf);
884         break;
885      case 1:
886         res = th<<6;
887         res |= 0x10;
888         res |= (machine().root_device().ioport(padnames[pad_n])->read()>>4) & 0xf; // R, X, Y, Z
889         break;
890      case 0:
891         res = th<<6;
892         //  0 Start A 0 0    Down Up
893         res|= (((machine().root_device().ioport(padnames[pad_n])->read()>>6)) & 0x30); // Start & A
894         res|= (((machine().root_device().ioport(padnames[pad_n])->read()>>12)) & 0x3);
895         break;
896   }
897
898   return res;
899}
900
901UINT8 saturn_state::smpc_direct_mode(UINT8 pad_n)
902{
903   int hshake;
904   const int shift_bit[4] = { 4, 12, 8, 0 };
905   const char *const padnames[] = { "JOY1", "JOY2" };
906
907   hshake = (pad_n == 0) ? ((m_smpc.PDR1>>5) & 3) : ((m_smpc.PDR2>>5) & 3);
908
909   if (LOG_SMPC) logerror("SMPC: SH-2 direct mode, returning data for phase %d\n", hshake);
910
911   return 0x80 | 0x10 | ((machine().root_device().ioport(padnames[pad_n])->read()>>shift_bit[hshake]) & 0xf);
912}
913
914READ8_MEMBER( saturn_state::saturn_SMPC_r )
915{
916   UINT8 return_data = 0;
917
918   if (!(offset & 1)) // avoid reading to even bytes (TODO: is it 0s or 1s?)
919      return 0x00;
920
921   if(offset >= 0x21 && offset <= 0x5f)
922      return_data = m_smpc.OREG[(offset-0x21) >> 1];
923
924   if (offset == 0x61)
925      return_data = m_smpc.SR;
926
927   if (offset == 0x63)
928   {
929      //printf("SF %d %d\n",space.machine().primary_screen->hpos(),space.machine().primary_screen->vpos());
930      return_data = m_smpc.SF;
931   }
932
933   if (offset == 0x75 || offset == 0x77)//PDR1/2 read
934   {
935      if ((m_smpc.IOSEL1 && offset == 0x75) || (m_smpc.IOSEL2 && offset == 0x77))
936      {
937         UINT8 cur_ddr;
938
939         if(machine().root_device().ioport("INPUT_TYPE")->read() && !(space.debugger_access()))
940         {
941            popmessage("Warning: read with SH-2 direct mode with a non-pad device");
942            return 0;
943         }
944
945         cur_ddr = (offset == 0x75) ? m_smpc.DDR1 : m_smpc.DDR2;
946
947         switch(cur_ddr & 0x60)
948         {
949            case 0x40: return_data = smpc_th_control_mode(offset == 0x77); break;
950            case 0x60: return_data = smpc_direct_mode(offset == 0x77); break;
951            default:
952               popmessage("SMPC: unemulated control method %02x, contact MAMEdev",cur_ddr & 0x60);
953               return_data = 0;
954               break;
955         }
956      }
957   }
958
959   if (LOG_SMPC) logerror ("cpu %s (PC=%08X) SMPC: Read from Byte Offset %02x (%d) Returns %02x\n", space.device().tag(), space.device().safe_pc(), offset, offset>>1, return_data);
960
961   return return_data;
962}
963
964WRITE8_MEMBER( saturn_state::saturn_SMPC_w )
965{
966   if (LOG_SMPC) logerror ("8-bit SMPC Write to Offset %02x (reg %d) with Data %02x\n", offset, offset>>1, data);
967
968   if (!(offset & 1)) // avoid writing to even bytes
969      return;
970
971   if(offset >= 1 && offset <= 0xd)
972      m_smpc.IREG[offset >> 1] = data;
973
974   if(offset == 1) //IREG0, check if a BREAK / CONTINUE request for INTBACK command
975   {
976      if(m_smpc.intback_stage)
977      {
978         if(data & 0x40)
979         {
980            if(LOG_PAD_CMD) printf("SMPC: BREAK request\n");
981            m_smpc.SR &= 0x0f;
982            m_smpc.intback_stage = 0;
983         }
984         else if(data & 0x80)
985         {
986            if(LOG_PAD_CMD) printf("SMPC: CONTINUE request\n");
987            machine().scheduler().timer_set(attotime::from_usec(700), FUNC(intback_peripheral),0); /* TODO: is timing correct? */
988            m_smpc.OREG[31] = 0x10;
989            m_smpc.SF = 0x01; //TODO: set hand-shake flag?
990         }
991      }
992   }
993
994   if (offset == 0x1f)
995   {
996      smpc_comreg_exec(space,data,0);
997
998      // we've processed the command, clear status flag
999      if(data != 0x10 && data != 2 && data != 3 && data != 6 && data != 7 && data != 0x0e && data != 0x0f && data != 0x19 && data != 0x1a)
1000      {
1001         m_smpc.OREG[31] = data; //read-back for last command issued
1002         m_smpc.SF = 0x00; //clear hand-shake flag
1003      }
1004      /*TODO:emulate the timing of each command...*/
1005   }
1006
1007   if (offset == 0x63)
1008      m_smpc.SF = data & 1; // hand-shake flag
1009
1010   if(offset == 0x75)  // PDR1
1011      m_smpc.PDR1 = data & 0x7f;
1012
1013   if(offset == 0x77)  // PDR2
1014      m_smpc.PDR2 = data & 0x7f;
1015
1016   if(offset == 0x79)
1017      m_smpc.DDR1 = data & 0x7f;
1018
1019   if(offset == 0x7b)
1020      m_smpc.DDR2 = data & 0x7f;
1021
1022   if(offset == 0x7d)
1023   {
1024      m_smpc.IOSEL1 = data & 1;
1025      m_smpc.IOSEL2 = (data & 2) >> 1;
1026   }
1027
1028   if(offset == 0x7f)
1029   {
1030      //enable PAD irq & VDP2 external latch for port 1/2
1031      m_smpc.EXLE1 = (data & 1) >> 0;
1032      m_smpc.EXLE2 = (data & 2) >> 1;
1033   }
1034}
Property changes on: trunk/src/emu/machine/smpc.c
Added: svn:eol-style
   + native
Added: svn:mime-type
   + text/plain
trunk/src/emu/machine/smpc.h
r0r20947
1DECLARE_WRITE8_HANDLER( stv_SMPC_w );
2DECLARE_READ8_HANDLER( stv_SMPC_r );
3DECLARE_WRITE8_HANDLER( saturn_SMPC_w );
4DECLARE_READ8_HANDLER( saturn_SMPC_r );
Property changes on: trunk/src/emu/machine/smpc.h
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/mess/mess.mak
r20946r20947
491491   $(MAME_DRIVERS)/vectrex.o   \
492492   $(MAME_VIDEO)/vectrex.o     \
493493   $(MAME_MACHINE)/vectrex.o   \
494   $(MAME_DRIVERS)/saturn.o    \
495   $(MAME_MACHINE)/stvcd.o     \
496   $(MAME_MACHINE)/scudsp.o    \
497   $(MAME_MACHINE)/stvprot.o   \
498   $(MAME_MACHINE)/smpc.o      \
499   $(MAME_VIDEO)/stvvdp1.o     \
500   $(MAME_VIDEO)/stvvdp2.o     \
501494   $(MAME_DRIVERS)/cps1.o  \
502495   $(MAME_VIDEO)/cps1.o    \
503496   $(MAME_DRIVERS)/konamim2.o \
r20946r20947
16511644   $(MESS_DRIVERS)/dccons.o    \
16521645   $(MAME_MACHINE)/gdrom.o     \
16531646   $(MESS_MACHINE)/dccons.o    \
1654   $(MESS_MACHINE)/sms.o   \
1655   $(MESS_DRIVERS)/sms.o   \
1647   $(MAME_DRIVERS)/saturn.o    \
1648   $(MESS_MACHINE)/sms.o       \
1649   $(MESS_DRIVERS)/sms.o       \
1650   $(MAME_MACHINE)/stvprot.o   \
16561651   $(MESS_DRIVERS)/svmu.o      \
16571652
16581653$(MESSOBJ)/sgi.a:               \
trunk/src/mame/drivers/saturn.c
r20946r20947
800800   AM_RANGE(0xc0000000, 0xc00007ff) AM_RAM // cache data array, Dragon Ball Z sprites relies on this
801801ADDRESS_MAP_END
802802
803static ADDRESS_MAP_START( stv_mem, AS_PROGRAM, 32, saturn_state )
804   AM_RANGE(0x00000000, 0x0007ffff) AM_ROM AM_SHARE("share6")  // bios
805   AM_RANGE(0x00100000, 0x0010007f) AM_READWRITE8_LEGACY(stv_SMPC_r, stv_SMPC_w,0xffffffff)
806   AM_RANGE(0x00180000, 0x0018ffff) AM_READWRITE8(saturn_backupram_r,saturn_backupram_w,0xffffffff) AM_SHARE("share1")
807   AM_RANGE(0x00200000, 0x002fffff) AM_RAM AM_MIRROR(0x20100000) AM_SHARE("workram_l")
808//  AM_RANGE(0x00400000, 0x0040001f) AM_READWRITE_LEGACY(stv_ioga_r32, stv_io_w32) AM_SHARE("ioga") AM_MIRROR(0x20) /* installed with per-game specific */
809   AM_RANGE(0x01000000, 0x017fffff) AM_WRITE(minit_w)
810   AM_RANGE(0x01800000, 0x01ffffff) AM_WRITE(sinit_w)
811   AM_RANGE(0x02000000, 0x04ffffff) AM_ROM AM_SHARE("share7") AM_REGION("abus", 0) // cartridge
812   AM_RANGE(0x05800000, 0x0589ffff) AM_READWRITE(stvcd_r, stvcd_w)
813   /* Sound */
814   AM_RANGE(0x05a00000, 0x05afffff) AM_READWRITE16(saturn_soundram_r, saturn_soundram_w,0xffffffff)
815   AM_RANGE(0x05b00000, 0x05b00fff) AM_DEVREADWRITE16_LEGACY("scsp", scsp_r, scsp_w, 0xffffffff)
816   /* VDP1 */
817   AM_RANGE(0x05c00000, 0x05c7ffff) AM_READWRITE(saturn_vdp1_vram_r, saturn_vdp1_vram_w)
818   AM_RANGE(0x05c80000, 0x05cbffff) AM_READWRITE(saturn_vdp1_framebuffer0_r, saturn_vdp1_framebuffer0_w)
819   AM_RANGE(0x05d00000, 0x05d0001f) AM_READWRITE16(saturn_vdp1_regs_r, saturn_vdp1_regs_w,0xffffffff)
820   AM_RANGE(0x05e00000, 0x05e7ffff) AM_MIRROR(0x80000) AM_READWRITE(saturn_vdp2_vram_r, saturn_vdp2_vram_w)
821   AM_RANGE(0x05f00000, 0x05f7ffff) AM_READWRITE(saturn_vdp2_cram_r, saturn_vdp2_cram_w)
822   AM_RANGE(0x05f80000, 0x05fbffff) AM_READWRITE16(saturn_vdp2_regs_r, saturn_vdp2_regs_w,0xffffffff)
823   AM_RANGE(0x05fe0000, 0x05fe00cf) AM_READWRITE(saturn_scu_r, saturn_scu_w)
824   AM_RANGE(0x06000000, 0x060fffff) AM_RAM AM_MIRROR(0x21f00000) AM_SHARE("workram_h")
825   AM_RANGE(0x20000000, 0x2007ffff) AM_ROM AM_SHARE("share6")  // bios mirror
826   AM_RANGE(0x22000000, 0x24ffffff) AM_ROM AM_SHARE("share7")  // cart mirror
827   AM_RANGE(0xc0000000, 0xc00007ff) AM_RAM // cache RAM
828ADDRESS_MAP_END
829
830803static ADDRESS_MAP_START( sound_mem, AS_PROGRAM, 16, saturn_state )
831804   AM_RANGE(0x000000, 0x0fffff) AM_RAM AM_SHARE("sound_ram")
832805   AM_RANGE(0x100000, 0x100fff) AM_DEVREADWRITE_LEGACY("scsp", scsp_r, scsp_w)
r20946r20947
12351208   PORT_CONFSETTING(0x01,"One Shot (Hack)")
12361209INPUT_PORTS_END
12371210
1238#define STV_PLAYER_INPUTS(_n_, _b1_, _b2_, _b3_,_b4_)                       \
1239   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_##_b1_ ) PORT_PLAYER(_n_)            \
1240   PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_##_b2_ ) PORT_PLAYER(_n_)            \
1241   PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_##_b3_ ) PORT_PLAYER(_n_)            \
1242   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_##_b4_ ) PORT_PLAYER(_n_)            \
1243   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(_n_)     \
1244   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(_n_)       \
1245   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(_n_)    \
1246   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(_n_)
1247
1248static INPUT_PORTS_START( stv )
1249   PORT_START("DSW1")
1250   PORT_DIPNAME( 0x01, 0x01, "PDR1" )
1251   PORT_DIPSETTING(    0x01, DEF_STR( Off ) )
1252   PORT_DIPSETTING(    0x00, DEF_STR( On ) )
1253   PORT_DIPNAME( 0x02, 0x02, DEF_STR( Unknown ) )
1254   PORT_DIPSETTING(    0x02, DEF_STR( Off ) )
1255   PORT_DIPSETTING(    0x00, DEF_STR( On ) )
1256   PORT_DIPNAME( 0x04, 0x04, DEF_STR( Unknown ) )
1257   PORT_DIPSETTING(    0x04, DEF_STR( Off ) )
1258   PORT_DIPSETTING(    0x00, DEF_STR( On ) )
1259   PORT_DIPNAME( 0x08, 0x08, DEF_STR( Unknown ) )
1260   PORT_DIPSETTING(    0x08, DEF_STR( Off ) )
1261   PORT_DIPSETTING(    0x00, DEF_STR( On ) )
1262   PORT_DIPNAME( 0x10, 0x10, DEF_STR( Unknown ) )
1263   PORT_DIPSETTING(    0x10, DEF_STR( Off ) )
1264   PORT_DIPSETTING(    0x00, DEF_STR( On ) )
1265   PORT_DIPNAME( 0x20, 0x20, DEF_STR( Unknown ) )
1266   PORT_DIPSETTING(    0x20, DEF_STR( Off ) )
1267   PORT_DIPSETTING(    0x00, DEF_STR( On ) )
1268   PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unknown ) )
1269   PORT_DIPSETTING(    0x40, DEF_STR( Off ) )
1270   PORT_DIPSETTING(    0x00, DEF_STR( On ) )
1271   PORT_DIPNAME( 0x80, 0x80, DEF_STR( Unknown ) )
1272   PORT_DIPSETTING(    0x80, DEF_STR( Off ) )
1273   PORT_DIPSETTING(    0x00, DEF_STR( On ) )
1274
1275   PORT_START("DSW2")
1276   PORT_DIPNAME( 0x01, 0x01, "PDR2" )
1277   PORT_DIPSETTING(    0x01, DEF_STR( Off ) )
1278   PORT_DIPSETTING(    0x00, DEF_STR( On ) )
1279   PORT_DIPNAME( 0x02, 0x02, DEF_STR( Unknown ) )
1280   PORT_DIPSETTING(    0x02, DEF_STR( Off ) )
1281   PORT_DIPSETTING(    0x00, DEF_STR( On ) )
1282   PORT_DIPNAME( 0x04, 0x04, DEF_STR( Unknown ) )
1283   PORT_DIPSETTING(    0x04, DEF_STR( Off ) )
1284   PORT_DIPSETTING(    0x00, DEF_STR( On ) )
1285   PORT_DIPNAME( 0x08, 0x08, DEF_STR( Unknown ) )
1286   PORT_DIPSETTING(    0x08, DEF_STR( Off ) )
1287   PORT_DIPSETTING(    0x00, DEF_STR( On ) )
1288   PORT_DIPNAME( 0x10, 0x10, DEF_STR( Unknown ) )
1289   PORT_DIPSETTING(    0x10, DEF_STR( Off ) )
1290   PORT_DIPSETTING(    0x00, DEF_STR( On ) )
1291   PORT_DIPNAME( 0x20, 0x20, DEF_STR( Unknown ) )
1292   PORT_DIPSETTING(    0x20, DEF_STR( Off ) )
1293   PORT_DIPSETTING(    0x00, DEF_STR( On ) )
1294   PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unknown ) )
1295   PORT_DIPSETTING(    0x40, DEF_STR( Off ) )
1296   PORT_DIPSETTING(    0x00, DEF_STR( On ) )
1297   PORT_DIPNAME( 0x80, 0x80, DEF_STR( Unknown ) )
1298   PORT_DIPSETTING(    0x80, DEF_STR( Off ) )
1299   PORT_DIPSETTING(    0x00, DEF_STR( On ) )
1300
1301   PORT_START("PORTA")
1302   STV_PLAYER_INPUTS(1, BUTTON1, BUTTON2, BUTTON3, BUTTON4)
1303
1304   PORT_START("PORTB")
1305   STV_PLAYER_INPUTS(2, BUTTON1, BUTTON2, BUTTON3, BUTTON4)
1306
1307   PORT_START("PORTC")
1308   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 )
1309   PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 )
1310   PORT_SERVICE_NO_TOGGLE( 0x04, IP_ACTIVE_LOW )
1311   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_SERVICE1 )
1312   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(1)
1313   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(2)
1314   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_SERVICE ) PORT_NAME("1P Push Switch") PORT_CODE(KEYCODE_7)
1315   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_SERVICE ) PORT_NAME("2P Push Switch") PORT_CODE(KEYCODE_8)
1316
1317   PORT_START("PORTE")
1318   STV_PLAYER_INPUTS(3, BUTTON1, BUTTON2, BUTTON3, START)
1319
1320   PORT_START("PORTF")
1321   STV_PLAYER_INPUTS(4, BUTTON1, BUTTON2, BUTTON3, START)
1322INPUT_PORTS_END
1323
1324static INPUT_PORTS_START( stv6b )
1325   PORT_INCLUDE( stv )
1326
1327   PORT_MODIFY("PORTA")
1328   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
1329
1330   PORT_MODIFY("PORTB")
1331   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
1332
1333   PORT_MODIFY("PORTE")
1334   PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
1335
1336   /* Extra button layout, used by Power Instinct 3, Suikoenbu, Elan Doree, Golden Axe Duel & Astra SuperStars */
1337   PORT_MODIFY("PORTF")
1338   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(1)
1339   PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_PLAYER(1)
1340   PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_PLAYER(1)
1341   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
1342   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(2)
1343   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_PLAYER(2)
1344   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_PLAYER(2)
1345   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED )
1346INPUT_PORTS_END
1347
1348static INPUT_PORTS_START( critcrsh )
1349   PORT_INCLUDE( stv )
1350
1351   PORT_MODIFY("PORTA")
1352   PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
1353
1354   PORT_MODIFY("PORTB")
1355   PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
1356
1357   PORT_MODIFY("PORTC")
1358   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("Hammer Hit")
1359   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
1360
1361   PORT_MODIFY("PORTE")
1362   PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
1363
1364   PORT_MODIFY("PORTF")
1365   PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
1366
1367   PORT_START("LIGHTX") /* mask default type                     sens delta min max */
1368   PORT_BIT( 0x3f, 0x00, IPT_LIGHTGUN_X ) PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_MINMAX(0,0x3f) PORT_SENSITIVITY(50) PORT_KEYDELTA(1) PORT_PLAYER(1)
1369
1370   PORT_START("LIGHTY")
1371   PORT_BIT( 0x3f, 0x00, IPT_LIGHTGUN_Y ) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_MINMAX(0x0,0x3f) PORT_SENSITIVITY(50) PORT_KEYDELTA(1) PORT_PLAYER(1)
1372INPUT_PORTS_END
1373
1374/* Same as the regular one, but with an additional & optional mahjong panel */
1375static INPUT_PORTS_START( stvmp )
1376   PORT_INCLUDE( stv )
1377
1378   PORT_MODIFY("PORTE")
1379   PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
1380
1381   PORT_MODIFY("PORTF")
1382   PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
1383
1384   /* Mahjong panel/player 1 side */
1385   PORT_START("P1_KEY0")
1386   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_MAHJONG_KAN )
1387   PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_START1 )
1388   PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )
1389   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
1390   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_MAHJONG_E )
1391   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_MAHJONG_A )
1392   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_MAHJONG_M )
1393   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_MAHJONG_I )
1394
1395   PORT_START("P1_KEY1")
1396   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_MAHJONG_REACH )
1397   PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
1398   PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )
1399   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
1400   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_MAHJONG_F )
1401   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_MAHJONG_B )
1402   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_MAHJONG_N )
1403   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_MAHJONG_J )
1404
1405   PORT_START("P1_KEY2")
1406   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_MAHJONG_RON )
1407   PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
1408   PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )
1409   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
1410   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_MAHJONG_G )
1411   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_MAHJONG_C )
1412   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_MAHJONG_CHI )
1413   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_MAHJONG_K )
1414
1415   PORT_START("P1_KEY3")
1416   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED )
1417   PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
1418   PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )
1419   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
1420   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_MAHJONG_H )
1421   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_MAHJONG_D )
1422   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_MAHJONG_PON )
1423   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_MAHJONG_L )
1424
1425   PORT_START("P1_KEY4")
1426   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED )
1427   PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
1428   PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )
1429   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
1430   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED )
1431   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
1432   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_MAHJONG_FLIP_FLOP )
1433   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED )
1434
1435   /* Mahjong panel/player 2 side */
1436   PORT_START("P2_KEY0")
1437   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_MAHJONG_KAN ) PORT_PLAYER(2)
1438   PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_START2 )
1439   PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )
1440   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
1441   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_MAHJONG_E ) PORT_PLAYER(2)
1442   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_MAHJONG_A ) PORT_PLAYER(2)
1443   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_MAHJONG_M ) PORT_PLAYER(2)
1444   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_MAHJONG_I ) PORT_PLAYER(2)
1445
1446   PORT_START("P2_KEY1")
1447   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_MAHJONG_REACH ) PORT_PLAYER(2)
1448   PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
1449   PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )
1450   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
1451   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_MAHJONG_F ) PORT_PLAYER(2)
1452   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_MAHJONG_B ) PORT_PLAYER(2)
1453   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_MAHJONG_N ) PORT_PLAYER(2)
1454   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_MAHJONG_J ) PORT_PLAYER(2)
1455
1456   PORT_START("P2_KEY2")
1457   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_MAHJONG_RON ) PORT_PLAYER(2)
1458   PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
1459   PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )
1460   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
1461   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_MAHJONG_G ) PORT_PLAYER(2)
1462   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_MAHJONG_C ) PORT_PLAYER(2)
1463   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_MAHJONG_CHI ) PORT_PLAYER(2)
1464   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_MAHJONG_K ) PORT_PLAYER(2)
1465
1466   PORT_START("P2_KEY3")
1467   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED )
1468   PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
1469   PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )
1470   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
1471   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_MAHJONG_H ) PORT_PLAYER(2)
1472   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_MAHJONG_D ) PORT_PLAYER(2)
1473   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_MAHJONG_PON ) PORT_PLAYER(2)
1474   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_MAHJONG_L ) PORT_PLAYER(2)
1475
1476   PORT_START("P2_KEY4")
1477   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED )
1478   PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
1479   PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )
1480   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
1481   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED )
1482   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
1483   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_MAHJONG_FLIP_FLOP ) PORT_PLAYER(2)
1484   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED )
1485INPUT_PORTS_END
1486
1487/* Micronet layout, routes joystick port to the mux! */
1488static INPUT_PORTS_START( myfairld )
1489   PORT_INCLUDE( stv )
1490
1491   PORT_MODIFY("PORTA")
1492   PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
1493
1494   PORT_MODIFY("PORTB")
1495   PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
1496
1497   PORT_MODIFY("PORTC")
1498   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1499   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(1) PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x01)
1500   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
1501
1502   PORT_MODIFY("PORTE")
1503   PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
1504
1505   PORT_MODIFY("PORTF")
1506   PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
1507
1508   PORT_START("P1_KEY0")
1509   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_MAHJONG_KAN )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1510   PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_START1 )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1511   PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1512   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1513   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_MAHJONG_E )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1514   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_MAHJONG_A )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1515   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_MAHJONG_M )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1516   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_MAHJONG_I )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1517   PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x01)
1518
1519   PORT_START("P1_KEY1")
1520   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_MAHJONG_REACH )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1521   PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_MAHJONG_BET )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1522   PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1523   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1524   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_MAHJONG_F )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1525   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_MAHJONG_B )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1526   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_MAHJONG_N )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1527   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_MAHJONG_J )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1528   PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x01)
1529
1530   PORT_START("P1_KEY2")
1531   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_MAHJONG_RON )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1532   PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1533   PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1534   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1535   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_MAHJONG_G )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1536   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_MAHJONG_C )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1537   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_MAHJONG_CHI )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1538   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_MAHJONG_K )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1539   PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x01)
1540
1541   PORT_START("P1_KEY3")
1542   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1543   PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1544   PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1545   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1546   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_MAHJONG_H ) PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1547   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_MAHJONG_D ) PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1548   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_MAHJONG_PON ) PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1549   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_MAHJONG_L ) PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1550   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x01)
1551   PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x01)
1552   PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x01)
1553   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x01)
1554   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1) PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x01)
1555   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(1) PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x01)
1556   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1) PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x01)
1557   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1) PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x01)
1558
1559   PORT_START("P1_KEY4")
1560   PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED ) /* F/F is there, but these two games are single player so it isn't connected */
1561
1562   PORT_START("P2_KEY0")
1563   PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
1564
1565   PORT_START("P2_KEY1")
1566   PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
1567
1568   PORT_START("P2_KEY2")
1569   PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
1570
1571   PORT_START("P2_KEY3")
1572   PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
1573
1574   PORT_START("P2_KEY4")
1575   PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
1576
1577   PORT_START("IO_TYPE")
1578   PORT_CONFNAME( 0x01, 0x01, "I/O Device type" )
1579   PORT_CONFSETTING(    0x00, "Mahjong Panel" )
1580   PORT_CONFSETTING(    0x01, "Joystick" )
1581INPUT_PORTS_END
1582
15831211static const gfx_layout tiles8x8x4_layout =
15841212{
15851213   8,8,
r20946r20947
16381266
16391267
16401268
1641static GFXDECODE_START( stv )
1269GFXDECODE_START( stv )
16421270   GFXDECODE_ENTRY( NULL, 0, tiles8x8x4_layout,   0x00, (0x80*(2+1))  )
16431271   GFXDECODE_ENTRY( NULL, 0, tiles16x16x4_layout, 0x00, (0x80*(2+1))  )
16441272   GFXDECODE_ENTRY( NULL, 0, tiles8x8x8_layout,   0x00, (0x08*(2+1))  )
r20946r20947
16481276static const sh2_cpu_core sh2_conf_master = { 0, NULL };
16491277static const sh2_cpu_core sh2_conf_slave  = { 1, NULL };
16501278
1651static void scsp_irq(device_t *device, int irq)
1279void scsp_irq(device_t *device, int irq)
16521280{
16531281   saturn_state *state = device->machine().driver_data<saturn_state>();
16541282
r20946r20947
22671895MACHINE_CONFIG_END
22681896
22691897
2270static MACHINE_CONFIG_START( stv, saturn_state )
2271
2272   /* basic machine hardware */
2273   MCFG_CPU_ADD("maincpu", SH2, MASTER_CLOCK_352/2) // 28.6364 MHz
2274   MCFG_CPU_PROGRAM_MAP(stv_mem)
2275   MCFG_CPU_CONFIG(sh2_conf_master)
2276   MCFG_TIMER_DRIVER_ADD_SCANLINE("scantimer", saturn_state, saturn_scanline, "screen", 0, 1)
2277
2278   MCFG_CPU_ADD("slave", SH2, MASTER_CLOCK_352/2) // 28.6364 MHz
2279   MCFG_CPU_PROGRAM_MAP(stv_mem)
2280   MCFG_CPU_CONFIG(sh2_conf_slave)
2281   MCFG_TIMER_DRIVER_ADD_SCANLINE("slave_scantimer", saturn_state, saturn_slave_scanline, "screen", 0, 1)
2282
2283   MCFG_CPU_ADD("audiocpu", M68000, 11289600) //11.2896 MHz
2284   MCFG_CPU_PROGRAM_MAP(sound_mem)
2285
2286   MCFG_MACHINE_START_OVERRIDE(saturn_state,stv)
2287   MCFG_MACHINE_RESET_OVERRIDE(saturn_state,stv)
2288
2289   MCFG_EEPROM_93C46_ADD("eeprom") /* Actually 93c45 */
2290
2291   MCFG_TIMER_DRIVER_ADD("sector_timer", saturn_state, stv_sector_cb)
2292   MCFG_TIMER_DRIVER_ADD("sh1_cmd", saturn_state, stv_sh1_sim)
2293
2294   /* video hardware */
2295   MCFG_VIDEO_ATTRIBUTES(VIDEO_UPDATE_AFTER_VBLANK)
2296   MCFG_SCREEN_ADD("screen", RASTER)
2297   MCFG_SCREEN_RAW_PARAMS(MASTER_CLOCK_320/8, 427, 0, 320, 263, 0, 224)
2298   MCFG_SCREEN_UPDATE_DRIVER(saturn_state, screen_update_stv_vdp2)
2299   MCFG_PALETTE_LENGTH(2048+(2048*2))//standard palette + extra memory for rgb brightness.
2300
2301   MCFG_GFXDECODE(stv)
2302
2303   MCFG_VIDEO_START_OVERRIDE(saturn_state,stv_vdp2)
2304
2305   MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
2306
2307   MCFG_SOUND_ADD("scsp", SCSP, 0)
2308   MCFG_SOUND_CONFIG(scsp_config)
2309   MCFG_SOUND_ROUTE(0, "lspeaker", 1.0)
2310   MCFG_SOUND_ROUTE(1, "rspeaker", 1.0)
2311
2312   MCFG_SOUND_ADD("cdda", CDDA, 0)
2313   MCFG_SOUND_ROUTE(0, "lspeaker", 1.0)
2314   MCFG_SOUND_ROUTE(1, "rspeaker", 1.0)
2315MACHINE_CONFIG_END
2316
2317struct stv_cart_region
2318{
2319   const char *tag;
2320   int        slot;
2321   const char *region;
2322};
2323
2324static const struct stv_cart_region stv_cart_table[] =
2325{
2326   { ":cart1", 0, "game0" },
2327   { ":cart2", 1, "game1" },
2328   { ":cart3", 2, "game2" },
2329   { ":cart4", 3, "game3" },
2330   { 0 }
2331};
2332
2333DEVICE_IMAGE_LOAD_MEMBER( saturn_state, stv_cart )
2334{
2335//  saturn_state *state = image.device().machine().driver_data<saturn_state>();
2336   const struct stv_cart_region *stv_cart = &stv_cart_table[0], *this_cart;
2337   //const char    *pcb_name;
2338
2339   /* First, determine where this cart has to be loaded */
2340   while (stv_cart->tag)
2341   {
2342      if (strcmp(stv_cart->tag, image.device().tag()) == 0)
2343         break;
2344
2345      stv_cart++;
2346   }
2347
2348   this_cart = stv_cart;
2349
2350   if (image.software_entry() == NULL)
2351      return IMAGE_INIT_FAIL;
2352
2353   UINT8 *ROM = image.device().machine().root_device().memregion(this_cart->region)->base();
2354   UINT32 length = image.get_software_region_length("rom");
2355
2356   memcpy(ROM, image.get_software_region("rom"), length);
2357
2358   /* fix endianess */
2359   {
2360      UINT8 j[4];
2361      int i;
2362
2363      for(i=0;i<length;i+=4)
2364      {
2365         j[0] = ROM[i];
2366         j[1] = ROM[i+1];
2367         j[2] = ROM[i+2];
2368         j[3] = ROM[i+3];
2369         ROM[i] = j[3];
2370         ROM[i+1] = j[2];
2371         ROM[i+2] = j[1];
2372         ROM[i+3] = j[0];
2373      }
2374   }
2375
2376   //if ((pcb_name = image.get_feature("pcb_type")) == NULL)
2377   //  return IMAGE_INIT_FAIL;
2378
2379   return IMAGE_INIT_PASS;
2380}
2381
2382
2383#define MCFG_STV_CARTSLOT_ADD(_tag) \
2384   MCFG_CARTSLOT_ADD(_tag) \
2385   MCFG_CARTSLOT_INTERFACE("stv_cart") \
2386   MCFG_CARTSLOT_LOAD(saturn_state,stv_cart)
2387
2388MACHINE_CONFIG_FRAGMENT( stv_cartslot )
2389   MCFG_STV_CARTSLOT_ADD("cart1")
2390   MCFG_STV_CARTSLOT_ADD("cart2")
2391   MCFG_STV_CARTSLOT_ADD("cart3")
2392   MCFG_STV_CARTSLOT_ADD("cart4")
2393
2394   MCFG_SOFTWARE_LIST_ADD("cart_list","stv")
2395MACHINE_CONFIG_END
2396
2397static MACHINE_CONFIG_DERIVED( stv_slot, stv )
2398   MCFG_FRAGMENT_ADD( stv_cartslot )
2399MACHINE_CONFIG_END
2400
2401
2402
24031898void saturn_state::saturn_init_driver(int rgn)
24041899{
24051900   m_saturn_region = rgn;
r20946r20947
24991994CONS( 1994, saturneu,   saturn, 0,      saturneu, saturn, saturn_state, saturneu,   "Sega",     "Saturn (PAL)",     GAME_NOT_WORKING )
25001995CONS( 1995, vsaturn,    saturn, 0,      saturnjp, saturn, saturn_state, saturnjp,   "JVC",      "V-Saturn",         GAME_NOT_WORKING )
25011996CONS( 1995, hisaturn,   saturn, 0,      saturnjp, saturn, saturn_state, saturnjp,   "Hitachi",  "HiSaturn",         GAME_NOT_WORKING )
2502
2503#include "stv.c"
trunk/src/mame/drivers/stv.c
r20946r20947
1010
1111************************************************************************/
1212
13#include "emu.h"
14#include "cpu/m68000/m68000.h"
15#include "machine/eeprom.h"
16#include "cpu/sh2/sh2.h"
17#include "machine/scudsp.h"
18#include "sound/scsp.h"
19#include "sound/cdda.h"
20#include "machine/stvprot.h"
21#include "machine/smpc.h"
22#include "includes/stv.h"
23#include "imagedev/chd_cd.h"
24#include "imagedev/cartslot.h"
25#include "coreutil.h"
26
1327#define FIRST_SPEEDUP_SLOT  (2)         // in case we remove/alter the BIOS speedups later
1428
1529
r20946r20947
904918}
905919
906920
921static const sh2_cpu_core sh2_conf_master = { 0, NULL };
922static const sh2_cpu_core sh2_conf_slave  = { 1, NULL };
923
924static const scsp_interface scsp_config =
925{
926   0,
927   scsp_irq,
928   DEVCB_DRIVER_LINE_MEMBER(saturn_state, scsp_to_main_irq)
929};
930
931static ADDRESS_MAP_START( stv_mem, AS_PROGRAM, 32, saturn_state )
932   AM_RANGE(0x00000000, 0x0007ffff) AM_ROM AM_SHARE("share6")  // bios
933   AM_RANGE(0x00100000, 0x0010007f) AM_READWRITE8_LEGACY(stv_SMPC_r, stv_SMPC_w,0xffffffff)
934   AM_RANGE(0x00180000, 0x0018ffff) AM_READWRITE8(saturn_backupram_r,saturn_backupram_w,0xffffffff) AM_SHARE("share1")
935   AM_RANGE(0x00200000, 0x002fffff) AM_RAM AM_MIRROR(0x20100000) AM_SHARE("workram_l")
936//  AM_RANGE(0x00400000, 0x0040001f) AM_READWRITE_LEGACY(stv_ioga_r32, stv_io_w32) AM_SHARE("ioga") AM_MIRROR(0x20) /* installed with per-game specific */
937   AM_RANGE(0x01000000, 0x017fffff) AM_WRITE(minit_w)
938   AM_RANGE(0x01800000, 0x01ffffff) AM_WRITE(sinit_w)
939   AM_RANGE(0x02000000, 0x04ffffff) AM_ROM AM_SHARE("share7") AM_REGION("abus", 0) // cartridge
940   AM_RANGE(0x05800000, 0x0589ffff) AM_READWRITE(stvcd_r, stvcd_w)
941   /* Sound */
942   AM_RANGE(0x05a00000, 0x05afffff) AM_READWRITE16(saturn_soundram_r, saturn_soundram_w,0xffffffff)
943   AM_RANGE(0x05b00000, 0x05b00fff) AM_DEVREADWRITE16_LEGACY("scsp", scsp_r, scsp_w, 0xffffffff)
944   /* VDP1 */
945   AM_RANGE(0x05c00000, 0x05c7ffff) AM_READWRITE(saturn_vdp1_vram_r, saturn_vdp1_vram_w)
946   AM_RANGE(0x05c80000, 0x05cbffff) AM_READWRITE(saturn_vdp1_framebuffer0_r, saturn_vdp1_framebuffer0_w)
947   AM_RANGE(0x05d00000, 0x05d0001f) AM_READWRITE16(saturn_vdp1_regs_r, saturn_vdp1_regs_w,0xffffffff)
948   AM_RANGE(0x05e00000, 0x05e7ffff) AM_MIRROR(0x80000) AM_READWRITE(saturn_vdp2_vram_r, saturn_vdp2_vram_w)
949   AM_RANGE(0x05f00000, 0x05f7ffff) AM_READWRITE(saturn_vdp2_cram_r, saturn_vdp2_cram_w)
950   AM_RANGE(0x05f80000, 0x05fbffff) AM_READWRITE16(saturn_vdp2_regs_r, saturn_vdp2_regs_w,0xffffffff)
951   AM_RANGE(0x05fe0000, 0x05fe00cf) AM_READWRITE(saturn_scu_r, saturn_scu_w)
952   AM_RANGE(0x06000000, 0x060fffff) AM_RAM AM_MIRROR(0x21f00000) AM_SHARE("workram_h")
953   AM_RANGE(0x20000000, 0x2007ffff) AM_ROM AM_SHARE("share6")  // bios mirror
954   AM_RANGE(0x22000000, 0x24ffffff) AM_ROM AM_SHARE("share7")  // cart mirror
955   AM_RANGE(0xc0000000, 0xc00007ff) AM_RAM // cache RAM
956ADDRESS_MAP_END
957
958static ADDRESS_MAP_START( sound_mem, AS_PROGRAM, 16, saturn_state )
959   AM_RANGE(0x000000, 0x0fffff) AM_RAM AM_SHARE("sound_ram")
960   AM_RANGE(0x100000, 0x100fff) AM_DEVREADWRITE_LEGACY("scsp", scsp_r, scsp_w)
961ADDRESS_MAP_END
962
963static MACHINE_CONFIG_START( stv, saturn_state )
964
965   /* basic machine hardware */
966   MCFG_CPU_ADD("maincpu", SH2, MASTER_CLOCK_352/2) // 28.6364 MHz
967   MCFG_CPU_PROGRAM_MAP(stv_mem)
968   MCFG_CPU_CONFIG(sh2_conf_master)
969   MCFG_TIMER_DRIVER_ADD_SCANLINE("scantimer", saturn_state, saturn_scanline, "screen", 0, 1)
970
971   MCFG_CPU_ADD("slave", SH2, MASTER_CLOCK_352/2) // 28.6364 MHz
972   MCFG_CPU_PROGRAM_MAP(stv_mem)
973   MCFG_CPU_CONFIG(sh2_conf_slave)
974   MCFG_TIMER_DRIVER_ADD_SCANLINE("slave_scantimer", saturn_state, saturn_slave_scanline, "screen", 0, 1)
975
976   MCFG_CPU_ADD("audiocpu", M68000, 11289600) //11.2896 MHz
977   MCFG_CPU_PROGRAM_MAP(sound_mem)
978
979   MCFG_MACHINE_START_OVERRIDE(saturn_state,stv)
980   MCFG_MACHINE_RESET_OVERRIDE(saturn_state,stv)
981
982   MCFG_EEPROM_93C46_ADD("eeprom") /* Actually 93c45 */
983
984   MCFG_TIMER_DRIVER_ADD("sector_timer", saturn_state, stv_sector_cb)
985   MCFG_TIMER_DRIVER_ADD("sh1_cmd", saturn_state, stv_sh1_sim)
986
987   /* video hardware */
988   MCFG_VIDEO_ATTRIBUTES(VIDEO_UPDATE_AFTER_VBLANK)
989   MCFG_SCREEN_ADD("screen", RASTER)
990   MCFG_SCREEN_RAW_PARAMS(MASTER_CLOCK_320/8, 427, 0, 320, 263, 0, 224)
991   MCFG_SCREEN_UPDATE_DRIVER(saturn_state, screen_update_stv_vdp2)
992   MCFG_PALETTE_LENGTH(2048+(2048*2))//standard palette + extra memory for rgb brightness.
993
994   MCFG_GFXDECODE(stv)
995
996   MCFG_VIDEO_START_OVERRIDE(saturn_state,stv_vdp2)
997
998   MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
999
1000   MCFG_SOUND_ADD("scsp", SCSP, 0)
1001   MCFG_SOUND_CONFIG(scsp_config)
1002   MCFG_SOUND_ROUTE(0, "lspeaker", 1.0)
1003   MCFG_SOUND_ROUTE(1, "rspeaker", 1.0)
1004
1005   MCFG_SOUND_ADD("cdda", CDDA, 0)
1006   MCFG_SOUND_ROUTE(0, "lspeaker", 1.0)
1007   MCFG_SOUND_ROUTE(1, "rspeaker", 1.0)
1008MACHINE_CONFIG_END
1009
1010#define MCFG_STV_CARTSLOT_ADD(_tag) \
1011   MCFG_CARTSLOT_ADD(_tag) \
1012   MCFG_CARTSLOT_INTERFACE("stv_cart") \
1013   MCFG_CARTSLOT_LOAD(saturn_state,stv_cart)
1014
1015MACHINE_CONFIG_FRAGMENT( stv_cartslot )
1016   MCFG_STV_CARTSLOT_ADD("cart1")
1017   MCFG_STV_CARTSLOT_ADD("cart2")
1018   MCFG_STV_CARTSLOT_ADD("cart3")
1019   MCFG_STV_CARTSLOT_ADD("cart4")
1020
1021   MCFG_SOFTWARE_LIST_ADD("cart_list","stv")
1022MACHINE_CONFIG_END
1023
1024static MACHINE_CONFIG_DERIVED( stv_slot, stv )
1025   MCFG_FRAGMENT_ADD( stv_cartslot )
1026MACHINE_CONFIG_END
1027
1028
1029struct stv_cart_region
1030{
1031   const char *tag;
1032   int        slot;
1033   const char *region;
1034};
1035
1036static const struct stv_cart_region stv_cart_table[] =
1037{
1038   { ":cart1", 0, "game0" },
1039   { ":cart2", 1, "game1" },
1040   { ":cart3", 2, "game2" },
1041   { ":cart4", 3, "game3" },
1042   { 0 }
1043};
1044
1045DEVICE_IMAGE_LOAD_MEMBER( saturn_state, stv_cart )
1046{
1047//  saturn_state *state = image.device().machine().driver_data<saturn_state>();
1048   const struct stv_cart_region *stv_cart = &stv_cart_table[0], *this_cart;
1049   //const char    *pcb_name;
1050
1051   /* First, determine where this cart has to be loaded */
1052   while (stv_cart->tag)
1053   {
1054      if (strcmp(stv_cart->tag, image.device().tag()) == 0)
1055         break;
1056
1057      stv_cart++;
1058   }
1059
1060   this_cart = stv_cart;
1061
1062   if (image.software_entry() == NULL)
1063      return IMAGE_INIT_FAIL;
1064
1065   UINT8 *ROM = image.device().machine().root_device().memregion(this_cart->region)->base();
1066   UINT32 length = image.get_software_region_length("rom");
1067
1068   memcpy(ROM, image.get_software_region("rom"), length);
1069
1070   /* fix endianess */
1071   {
1072      UINT8 j[4];
1073      int i;
1074
1075      for(i=0;i<length;i+=4)
1076      {
1077         j[0] = ROM[i];
1078         j[1] = ROM[i+1];
1079         j[2] = ROM[i+2];
1080         j[3] = ROM[i+3];
1081         ROM[i] = j[3];
1082         ROM[i+1] = j[2];
1083         ROM[i+2] = j[1];
1084         ROM[i+3] = j[0];
1085      }
1086   }
1087
1088   //if ((pcb_name = image.get_feature("pcb_type")) == NULL)
1089   //  return IMAGE_INIT_FAIL;
1090
1091   return IMAGE_INIT_PASS;
1092}
1093
1094
1095
1096#define STV_PLAYER_INPUTS(_n_, _b1_, _b2_, _b3_,_b4_)                       \
1097   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_##_b1_ ) PORT_PLAYER(_n_)            \
1098   PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_##_b2_ ) PORT_PLAYER(_n_)            \
1099   PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_##_b3_ ) PORT_PLAYER(_n_)            \
1100   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_##_b4_ ) PORT_PLAYER(_n_)            \
1101   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(_n_)     \
1102   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(_n_)       \
1103   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(_n_)    \
1104   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(_n_)
1105
1106static INPUT_PORTS_START( stv )
1107   PORT_START("DSW1")
1108   PORT_DIPNAME( 0x01, 0x01, "PDR1" )
1109   PORT_DIPSETTING(    0x01, DEF_STR( Off ) )
1110   PORT_DIPSETTING(    0x00, DEF_STR( On ) )
1111   PORT_DIPNAME( 0x02, 0x02, DEF_STR( Unknown ) )
1112   PORT_DIPSETTING(    0x02, DEF_STR( Off ) )
1113   PORT_DIPSETTING(    0x00, DEF_STR( On ) )
1114   PORT_DIPNAME( 0x04, 0x04, DEF_STR( Unknown ) )
1115   PORT_DIPSETTING(    0x04, DEF_STR( Off ) )
1116   PORT_DIPSETTING(    0x00, DEF_STR( On ) )
1117   PORT_DIPNAME( 0x08, 0x08, DEF_STR( Unknown ) )
1118   PORT_DIPSETTING(    0x08, DEF_STR( Off ) )
1119   PORT_DIPSETTING(    0x00, DEF_STR( On ) )
1120   PORT_DIPNAME( 0x10, 0x10, DEF_STR( Unknown ) )
1121   PORT_DIPSETTING(    0x10, DEF_STR( Off ) )
1122   PORT_DIPSETTING(    0x00, DEF_STR( On ) )
1123   PORT_DIPNAME( 0x20, 0x20, DEF_STR( Unknown ) )
1124   PORT_DIPSETTING(    0x20, DEF_STR( Off ) )
1125   PORT_DIPSETTING(    0x00, DEF_STR( On ) )
1126   PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unknown ) )
1127   PORT_DIPSETTING(    0x40, DEF_STR( Off ) )
1128   PORT_DIPSETTING(    0x00, DEF_STR( On ) )
1129   PORT_DIPNAME( 0x80, 0x80, DEF_STR( Unknown ) )
1130   PORT_DIPSETTING(    0x80, DEF_STR( Off ) )
1131   PORT_DIPSETTING(    0x00, DEF_STR( On ) )
1132
1133   PORT_START("DSW2")
1134   PORT_DIPNAME( 0x01, 0x01, "PDR2" )
1135   PORT_DIPSETTING(    0x01, DEF_STR( Off ) )
1136   PORT_DIPSETTING(    0x00, DEF_STR( On ) )
1137   PORT_DIPNAME( 0x02, 0x02, DEF_STR( Unknown ) )
1138   PORT_DIPSETTING(    0x02, DEF_STR( Off ) )
1139   PORT_DIPSETTING(    0x00, DEF_STR( On ) )
1140   PORT_DIPNAME( 0x04, 0x04, DEF_STR( Unknown ) )
1141   PORT_DIPSETTING(    0x04, DEF_STR( Off ) )
1142   PORT_DIPSETTING(    0x00, DEF_STR( On ) )
1143   PORT_DIPNAME( 0x08, 0x08, DEF_STR( Unknown ) )
1144   PORT_DIPSETTING(    0x08, DEF_STR( Off ) )
1145   PORT_DIPSETTING(    0x00, DEF_STR( On ) )
1146   PORT_DIPNAME( 0x10, 0x10, DEF_STR( Unknown ) )
1147   PORT_DIPSETTING(    0x10, DEF_STR( Off ) )
1148   PORT_DIPSETTING(    0x00, DEF_STR( On ) )
1149   PORT_DIPNAME( 0x20, 0x20, DEF_STR( Unknown ) )
1150   PORT_DIPSETTING(    0x20, DEF_STR( Off ) )
1151   PORT_DIPSETTING(    0x00, DEF_STR( On ) )
1152   PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unknown ) )
1153   PORT_DIPSETTING(    0x40, DEF_STR( Off ) )
1154   PORT_DIPSETTING(    0x00, DEF_STR( On ) )
1155   PORT_DIPNAME( 0x80, 0x80, DEF_STR( Unknown ) )
1156   PORT_DIPSETTING(    0x80, DEF_STR( Off ) )
1157   PORT_DIPSETTING(    0x00, DEF_STR( On ) )
1158
1159   PORT_START("PORTA")
1160   STV_PLAYER_INPUTS(1, BUTTON1, BUTTON2, BUTTON3, BUTTON4)
1161
1162   PORT_START("PORTB")
1163   STV_PLAYER_INPUTS(2, BUTTON1, BUTTON2, BUTTON3, BUTTON4)
1164
1165   PORT_START("PORTC")
1166   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 )
1167   PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 )
1168   PORT_SERVICE_NO_TOGGLE( 0x04, IP_ACTIVE_LOW )
1169   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_SERVICE1 )
1170   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(1)
1171   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(2)
1172   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_SERVICE ) PORT_NAME("1P Push Switch") PORT_CODE(KEYCODE_7)
1173   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_SERVICE ) PORT_NAME("2P Push Switch") PORT_CODE(KEYCODE_8)
1174
1175   PORT_START("PORTE")
1176   STV_PLAYER_INPUTS(3, BUTTON1, BUTTON2, BUTTON3, START)
1177
1178   PORT_START("PORTF")
1179   STV_PLAYER_INPUTS(4, BUTTON1, BUTTON2, BUTTON3, START)
1180INPUT_PORTS_END
1181
1182static INPUT_PORTS_START( stv6b )
1183   PORT_INCLUDE( stv )
1184
1185   PORT_MODIFY("PORTA")
1186   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
1187
1188   PORT_MODIFY("PORTB")
1189   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
1190
1191   PORT_MODIFY("PORTE")
1192   PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
1193
1194   /* Extra button layout, used by Power Instinct 3, Suikoenbu, Elan Doree, Golden Axe Duel & Astra SuperStars */
1195   PORT_MODIFY("PORTF")
1196   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(1)
1197   PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_PLAYER(1)
1198   PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_PLAYER(1)
1199   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
1200   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(2)
1201   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_PLAYER(2)
1202   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_PLAYER(2)
1203   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED )
1204INPUT_PORTS_END
1205
1206static INPUT_PORTS_START( critcrsh )
1207   PORT_INCLUDE( stv )
1208
1209   PORT_MODIFY("PORTA")
1210   PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
1211
1212   PORT_MODIFY("PORTB")
1213   PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
1214
1215   PORT_MODIFY("PORTC")
1216   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("Hammer Hit")
1217   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
1218
1219   PORT_MODIFY("PORTE")
1220   PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
1221
1222   PORT_MODIFY("PORTF")
1223   PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
1224
1225   PORT_START("LIGHTX") /* mask default type                     sens delta min max */
1226   PORT_BIT( 0x3f, 0x00, IPT_LIGHTGUN_X ) PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_MINMAX(0,0x3f) PORT_SENSITIVITY(50) PORT_KEYDELTA(1) PORT_PLAYER(1)
1227
1228   PORT_START("LIGHTY")
1229   PORT_BIT( 0x3f, 0x00, IPT_LIGHTGUN_Y ) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_MINMAX(0x0,0x3f) PORT_SENSITIVITY(50) PORT_KEYDELTA(1) PORT_PLAYER(1)
1230INPUT_PORTS_END
1231
1232/* Same as the regular one, but with an additional & optional mahjong panel */
1233static INPUT_PORTS_START( stvmp )
1234   PORT_INCLUDE( stv )
1235
1236   PORT_MODIFY("PORTE")
1237   PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
1238
1239   PORT_MODIFY("PORTF")
1240   PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
1241
1242   /* Mahjong panel/player 1 side */
1243   PORT_START("P1_KEY0")
1244   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_MAHJONG_KAN )
1245   PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_START1 )
1246   PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )
1247   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
1248   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_MAHJONG_E )
1249   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_MAHJONG_A )
1250   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_MAHJONG_M )
1251   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_MAHJONG_I )
1252
1253   PORT_START("P1_KEY1")
1254   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_MAHJONG_REACH )
1255   PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
1256   PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )
1257   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
1258   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_MAHJONG_F )
1259   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_MAHJONG_B )
1260   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_MAHJONG_N )
1261   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_MAHJONG_J )
1262
1263   PORT_START("P1_KEY2")
1264   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_MAHJONG_RON )
1265   PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
1266   PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )
1267   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
1268   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_MAHJONG_G )
1269   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_MAHJONG_C )
1270   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_MAHJONG_CHI )
1271   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_MAHJONG_K )
1272
1273   PORT_START("P1_KEY3")
1274   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED )
1275   PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
1276   PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )
1277   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
1278   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_MAHJONG_H )
1279   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_MAHJONG_D )
1280   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_MAHJONG_PON )
1281   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_MAHJONG_L )
1282
1283   PORT_START("P1_KEY4")
1284   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED )
1285   PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
1286   PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )
1287   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
1288   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED )
1289   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
1290   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_MAHJONG_FLIP_FLOP )
1291   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED )
1292
1293   /* Mahjong panel/player 2 side */
1294   PORT_START("P2_KEY0")
1295   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_MAHJONG_KAN ) PORT_PLAYER(2)
1296   PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_START2 )
1297   PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )
1298   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
1299   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_MAHJONG_E ) PORT_PLAYER(2)
1300   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_MAHJONG_A ) PORT_PLAYER(2)
1301   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_MAHJONG_M ) PORT_PLAYER(2)
1302   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_MAHJONG_I ) PORT_PLAYER(2)
1303
1304   PORT_START("P2_KEY1")
1305   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_MAHJONG_REACH ) PORT_PLAYER(2)
1306   PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
1307   PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )
1308   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
1309   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_MAHJONG_F ) PORT_PLAYER(2)
1310   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_MAHJONG_B ) PORT_PLAYER(2)
1311   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_MAHJONG_N ) PORT_PLAYER(2)
1312   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_MAHJONG_J ) PORT_PLAYER(2)
1313
1314   PORT_START("P2_KEY2")
1315   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_MAHJONG_RON ) PORT_PLAYER(2)
1316   PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
1317   PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )
1318   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
1319   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_MAHJONG_G ) PORT_PLAYER(2)
1320   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_MAHJONG_C ) PORT_PLAYER(2)
1321   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_MAHJONG_CHI ) PORT_PLAYER(2)
1322   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_MAHJONG_K ) PORT_PLAYER(2)
1323
1324   PORT_START("P2_KEY3")
1325   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED )
1326   PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
1327   PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )
1328   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
1329   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_MAHJONG_H ) PORT_PLAYER(2)
1330   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_MAHJONG_D ) PORT_PLAYER(2)
1331   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_MAHJONG_PON ) PORT_PLAYER(2)
1332   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_MAHJONG_L ) PORT_PLAYER(2)
1333
1334   PORT_START("P2_KEY4")
1335   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED )
1336   PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
1337   PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )
1338   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
1339   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED )
1340   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
1341   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_MAHJONG_FLIP_FLOP ) PORT_PLAYER(2)
1342   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED )
1343INPUT_PORTS_END
1344
1345/* Micronet layout, routes joystick port to the mux! */
1346static INPUT_PORTS_START( myfairld )
1347   PORT_INCLUDE( stv )
1348
1349   PORT_MODIFY("PORTA")
1350   PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
1351
1352   PORT_MODIFY("PORTB")
1353   PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
1354
1355   PORT_MODIFY("PORTC")
1356   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1357   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(1) PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x01)
1358   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
1359
1360   PORT_MODIFY("PORTE")
1361   PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
1362
1363   PORT_MODIFY("PORTF")
1364   PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
1365
1366   PORT_START("P1_KEY0")
1367   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_MAHJONG_KAN )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1368   PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_START1 )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1369   PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1370   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1371   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_MAHJONG_E )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1372   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_MAHJONG_A )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1373   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_MAHJONG_M )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1374   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_MAHJONG_I )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1375   PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x01)
1376
1377   PORT_START("P1_KEY1")
1378   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_MAHJONG_REACH )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1379   PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_MAHJONG_BET )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1380   PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1381   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1382   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_MAHJONG_F )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1383   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_MAHJONG_B )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1384   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_MAHJONG_N )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1385   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_MAHJONG_J )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1386   PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x01)
1387
1388   PORT_START("P1_KEY2")
1389   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_MAHJONG_RON )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1390   PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1391   PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1392   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1393   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_MAHJONG_G )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1394   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_MAHJONG_C )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1395   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_MAHJONG_CHI )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1396   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_MAHJONG_K )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1397   PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )  PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x01)
1398
1399   PORT_START("P1_KEY3")
1400   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1401   PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1402   PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1403   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1404   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_MAHJONG_H ) PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1405   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_MAHJONG_D ) PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1406   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_MAHJONG_PON ) PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1407   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_MAHJONG_L ) PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x00)
1408   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x01)
1409   PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x01)
1410   PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x01)
1411   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x01)
1412   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1) PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x01)
1413   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(1) PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x01)
1414   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1) PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x01)
1415   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1) PORT_CONDITION("IO_TYPE", 0x01, EQUALS, 0x01)
1416
1417   PORT_START("P1_KEY4")
1418   PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED ) /* F/F is there, but these two games are single player so it isn't connected */
1419
1420   PORT_START("P2_KEY0")
1421   PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
1422
1423   PORT_START("P2_KEY1")
1424   PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
1425
1426   PORT_START("P2_KEY2")
1427   PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
1428
1429   PORT_START("P2_KEY3")
1430   PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
1431
1432   PORT_START("P2_KEY4")
1433   PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
1434
1435   PORT_START("IO_TYPE")
1436   PORT_CONFNAME( 0x01, 0x01, "I/O Device type" )
1437   PORT_CONFSETTING(    0x00, "Mahjong Panel" )
1438   PORT_CONFSETTING(    0x01, "Joystick" )
1439INPUT_PORTS_END
1440
1441
9071442#define ROM_LOAD16_WORD_SWAP_BIOS(bios,name,offset,length,hash) \
9081443      ROMX_LOAD(name, offset, length, hash, ROM_GROUPWORD | ROM_REVERSE | ROM_BIOS(bios+1)) /* Note '+1' */
9091444
trunk/src/mame/machine/smpc.c
r20946r20947
1/************************************************************************************
2
3Sega Saturn SMPC - System Manager and Peripheral Control MCU simulation
4
5The SMPC is actually a 4-bit Hitachi HD404920FS MCU, labeled with a Sega custom
6315-5744 (that needs decapping)
7
8MCU simulation by Angelo Salese & R. Belmont
9
10TODO:
11- timings;
12- fix intback issue with inputs (according to the docs, it should fall in between
13  VBLANK-IN and OUT, for obvious reasons);
14- clean-ups;
15
16*************************************************************************************/
17/* SMPC Addresses
18
1900
2001 -w  Input Register 0 (IREG)
2102
2203 -w  Input Register 1
2304
2405 -w  Input Register 2
2506
2607 -w  Input Register 3
2708
2809 -w  Input Register 4
290a
300b -w  Input Register 5
310c
320d -w  Input Register 6
330e
340f
3510
3611
3712
3813
3914
4015
4116
4217
4318
4419
451a
461b
471c
481d
491e
501f -w  Command Register (COMREG)
5120
5221 r-  Output Register 0 (OREG)
5322
5423 r-  Output Register 1
5524
5625 r-  Output Register 2
5726
5827 r-  Output Register 3
5928
6029 r-  Output Register 4
612a
622b r-  Output Register 5
632c
642d r-  Output Register 6
652e
662f r-  Output Register 7
6730
6831 r-  Output Register 8
6932
7033 r-  Output Register 9
7134
7235 r-  Output Register 10
7336
7437 r-  Output Register 11
7538
7639 r-  Output Register 12
773a
783b r-  Output Register 13
793c
803d r-  Output Register 14
813e
823f r-  Output Register 15
8340
8441 r-  Output Register 16
8542
8643 r-  Output Register 17
8744
8845 r-  Output Register 18
8946
9047 r-  Output Register 19
9148
9249 r-  Output Register 20
934a
944b r-  Output Register 21
954c
964d r-  Output Register 22
974e
984f r-  Output Register 23
9950
10051 r-  Output Register 24
10152
10253 r-  Output Register 25
10354
10455 r-  Output Register 26
10556
10657 r-  Output Register 27
10758
10859 r-  Output Register 28
1095a
1105b r-  Output Register 29
1115c
1125d r-  Output Register 30
1135e
1145f r-  Output Register 31
11560
11661 r-  SR
11762
11863 rw  SF
11964
12065
12166
12267
12368
12469
1256a
1266b
1276c
1286d
1296e
1306f
13170
13271
13372
13473
13574
13675 rw PDR1
13776
13877 rw PDR2
13978
14079 -w DDR1
1417a
1427b -w DDR2
1437c
1447d -w IOSEL2/1
1457e
1467f -w EXLE2/1
147*/
148
149#include "emu.h"
150#include "coreutil.h"
151#include "includes/stv.h"
152#include "machine/smpc.h"
153#include "machine/eeprom.h"
154
155#define LOG_SMPC 0
156#define LOG_PAD_CMD 0
157
158#if 0
159/* TODO: move this into video functions */
160static int vblank_line(running_machine &machine)
161{
162   saturn_state *state = machine.driver_data<saturn_state>();
163   int max_y = machine.primary_screen->height();
164   int y_step,vblank_line;
165
166   y_step = 2;
167
168   if((max_y == 263 && state->m_vdp2.pal == 0) || (max_y == 313 && state->m_vdp2.pal == 1))
169      y_step = 1;
170
171   vblank_line = (state->m_vdp2.pal) ? 288 : 240;
172
173   return vblank_line*y_step;
174}
175#endif
176
177
178/********************************************
179 *
180 * Bankswitch code for ST-V Multi Cart mode
181 *
182 *******************************************/
183
184static TIMER_CALLBACK( stv_bankswitch_state )
185{
186   saturn_state *state = machine.driver_data<saturn_state>();
187   static const char *const banknames[] = { "game0", "game1", "game2", "game3" };
188   UINT8* game_region;
189
190   if(state->m_prev_bankswitch != param)
191   {
192      game_region = machine.root_device().memregion(banknames[param])->base();
193
194      if (game_region)
195         memcpy(machine.root_device().memregion("abus")->base(), game_region, 0x3000000);
196      else
197         memset(machine.root_device().memregion("abus")->base(), 0x00, 0x3000000);
198
199      state->m_prev_bankswitch = param;
200   }
201}
202
203static void stv_select_game(running_machine &machine, int gameno)
204{
205   machine.scheduler().timer_set(attotime::zero, FUNC(stv_bankswitch_state), gameno);
206}
207
208/********************************************
209 *
210 * Command functions
211 *
212 *******************************************/
213
214static void smpc_master_on(running_machine &machine)
215{
216   saturn_state *state = machine.driver_data<saturn_state>();
217
218   state->m_maincpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
219}
220
221static TIMER_CALLBACK( smpc_slave_enable )
222{
223   saturn_state *state = machine.driver_data<saturn_state>();
224
225   state->m_slave->set_input_line(INPUT_LINE_RESET, param ? ASSERT_LINE : CLEAR_LINE);
226   state->m_smpc.OREG[31] = param + 0x02; //read-back for last command issued
227   state->m_smpc.SF = 0x00; //clear hand-shake flag
228   state->m_smpc.slave_on = param;
229//  printf("%d %d\n",machine.primary_screen->hpos(),machine.primary_screen->vpos());
230}
231
232static TIMER_CALLBACK( smpc_sound_enable )
233{
234   saturn_state *state = machine.driver_data<saturn_state>();
235
236   state->m_audiocpu->set_input_line(INPUT_LINE_RESET, param ? ASSERT_LINE : CLEAR_LINE);
237   state->m_en_68k = param ^ 1;
238   state->m_smpc.OREG[31] = param + 0x06; //read-back for last command issued
239   state->m_smpc.SF = 0x00; //clear hand-shake flag
240}
241
242static void smpc_system_reset(running_machine &machine)
243{
244   saturn_state *state = machine.driver_data<saturn_state>();
245
246   /*Only backup ram and SMPC ram are retained after that this command is issued.*/
247   memset(state->m_scu_regs ,0x00,0x000100);
248   memset(state->m_scsp_regs,0x00,0x001000);
249   memset(state->m_sound_ram,0x00,0x080000);
250   memset(state->m_workram_h,0x00,0x100000);
251   memset(state->m_workram_l,0x00,0x100000);
252   memset(state->m_vdp2_regs,0x00,0x040000);
253   memset(state->m_vdp2_vram,0x00,0x100000);
254   memset(state->m_vdp2_cram,0x00,0x080000);
255   memset(state->m_vdp1_vram,0x00,0x100000);
256   //A-Bus
257
258   state->m_maincpu->set_input_line(INPUT_LINE_RESET, PULSE_LINE);
259}
260
261static TIMER_CALLBACK( smpc_change_clock )
262{
263   saturn_state *state = machine.driver_data<saturn_state>();
264   UINT32 xtal;
265
266   if(LOG_SMPC) printf ("Clock change execute at (%d %d)\n",machine.primary_screen->hpos(),machine.primary_screen->vpos());
267
268   xtal = param ? MASTER_CLOCK_320 : MASTER_CLOCK_352;
269
270   machine.device("maincpu")->set_unscaled_clock(xtal/2);
271   machine.device("slave")->set_unscaled_clock(xtal/2);
272
273   state->m_vdp2.dotsel = param ^ 1;
274   state->stv_vdp2_dynamic_res_change();
275
276   if(!state->m_NMI_reset)
277      state->m_maincpu->set_input_line(INPUT_LINE_NMI, PULSE_LINE);
278   state->m_slave->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
279
280   /* put issued command in OREG31 */
281   state->m_smpc.OREG[31] = 0x0e + param;
282   /* clear hand-shake flag */
283   state->m_smpc.SF = 0x00;
284
285   /* TODO: VDP1 / VDP2 / SCU / SCSP default power ON values? */
286}
287
288static TIMER_CALLBACK( stv_smpc_intback )
289{
290   saturn_state *state = machine.driver_data<saturn_state>();
291   int i;
292
293   state->m_smpc.OREG[0] = (0x80) | ((state->m_NMI_reset & 1) << 6);
294
295   for(i=0;i<7;i++)
296      state->m_smpc.OREG[1+i] = state->m_smpc.rtc_data[i];
297
298   state->m_smpc.OREG[8]=0x00;  // CTG0 / CTG1?
299
300   state->m_smpc.OREG[9]=0x00;  // TODO: system region on Saturn
301
302   state->m_smpc.OREG[10]= 0 << 7 |
303                        state->m_vdp2.dotsel << 6 |
304                        1 << 5 |
305                        1 << 4 |
306                        0 << 3 | //MSHNMI
307                        1 << 2 |
308                        0 << 1 | //SYSRES
309                        0 << 0;  //SOUNDRES
310   state->m_smpc.OREG[11]= 0 << 6; //CDRES
311
312   for(i=0;i<4;i++)
313      state->m_smpc.OREG[12+i]=state->m_smpc.SMEM[i];
314
315   for(i=0;i<15;i++)
316      state->m_smpc.OREG[16+i]=0xff; // undefined
317
318   //  /*This is for RTC,cartridge code and similar stuff...*/
319   //if(LOG_SMPC) printf ("Interrupt: System Manager (SMPC) at scanline %04x, Vector 0x47 Level 0x08\n",scanline);
320   if(!(state->m_scu.ism & IRQ_SMPC))
321      state->m_maincpu->set_input_line_and_vector(8, HOLD_LINE, 0x47);
322   else
323      state->m_scu.ist |= (IRQ_SMPC);
324
325   /* put issued command in OREG31 */
326   state->m_smpc.OREG[31] = 0x10; // TODO: doc says 0?
327   /* clear hand-shake flag */
328   state->m_smpc.SF = 0x00;
329}
330
331/*
332    [0] port status:
333        0x04 Sega-tap
334        0x16 Multi-tap
335        0x2x clock serial peripheral
336        0xf0 peripheral isn't connected
337        0xf1 peripheral is connected
338    [1] Peripheral ID (note: lowest four bits determines the size of the input packet)
339        0x02 digital pad
340        0x25 (tested by Game Basic?)
341        0x34 keyboard
342*/
343
344static void smpc_digital_pad(running_machine &machine, UINT8 pad_num, UINT8 offset)
345{
346   saturn_state *state = machine.driver_data<saturn_state>();
347   static const char *const padnames[] = { "JOY1", "JOY2" };
348   UINT16 pad_data;
349
350   pad_data = machine.root_device().ioport(padnames[pad_num])->read();
351   state->m_smpc.OREG[0+pad_num*offset] = 0xf1;
352   state->m_smpc.OREG[1+pad_num*offset] = 0x02;
353   state->m_smpc.OREG[2+pad_num*offset] = pad_data>>8;
354   state->m_smpc.OREG[3+pad_num*offset] = pad_data & 0xff;
355}
356
357static void smpc_analog_pad(running_machine &machine, UINT8 pad_num, UINT8 offset, UINT8 id)
358{
359   saturn_state *state = machine.driver_data<saturn_state>();
360   static const char *const padnames[] = { "AN_JOY1", "AN_JOY2" };
361   static const char *const annames[2][3] = { { "AN_X1", "AN_Y1", "AN_Z1" },
362                                    { "AN_X2", "AN_Y2", "AN_Z2" }};
363   UINT16 pad_data;
364
365   pad_data = machine.root_device().ioport(padnames[pad_num])->read();
366   state->m_smpc.OREG[0+pad_num*offset] = 0xf1;
367   state->m_smpc.OREG[1+pad_num*offset] = id;
368   state->m_smpc.OREG[2+pad_num*offset] = pad_data>>8;
369   state->m_smpc.OREG[3+pad_num*offset] = pad_data & 0xff;
370   state->m_smpc.OREG[4+pad_num*offset] = machine.root_device().ioport(annames[pad_num][0])->read();
371   if(id == 0x15)
372   {
373      state->m_smpc.OREG[5+pad_num*offset] = machine.root_device().ioport(annames[pad_num][1])->read();
374      state->m_smpc.OREG[6+pad_num*offset] = machine.root_device().ioport(annames[pad_num][2])->read();
375   }
376}
377
378static void smpc_keyboard(running_machine &machine, UINT8 pad_num, UINT8 offset)
379{
380   saturn_state *state = machine.driver_data<saturn_state>();
381   UINT16 game_key;
382
383   game_key = 0xffff;
384
385   game_key ^= ((state->ioport("KEYS_1")->read() & 0x80) << 8); // right
386   game_key ^= ((state->ioport("KEYS_1")->read() & 0x40) << 8); // left
387   game_key ^= ((state->ioport("KEYS_1")->read() & 0x20) << 8); // down
388   game_key ^= ((state->ioport("KEYS_1")->read() & 0x10) << 8); // up
389   game_key ^= ((state->ioport("KEYF")->read() & 0x80) << 4); // ESC -> START
390   game_key ^= ((state->ioport("KEY3")->read() & 0x04) << 8); // Z / A trigger
391   game_key ^= ((state->ioport("KEY4")->read() & 0x02) << 8); // C / C trigger
392   game_key ^= ((state->ioport("KEY6")->read() & 0x04) << 6); // X / B trigger
393   game_key ^= ((state->ioport("KEY2")->read() & 0x20) << 2); // Q / R trigger
394   game_key ^= ((state->ioport("KEY3")->read() & 0x10) << 2); // A / X trigger
395   game_key ^= ((state->ioport("KEY3")->read() & 0x08) << 2); // S / Y trigger
396   game_key ^= ((state->ioport("KEY4")->read() & 0x08) << 1); // D / Z trigger
397   game_key ^= ((state->ioport("KEY4")->read() & 0x10) >> 1); // E / L trigger
398
399   state->m_smpc.OREG[0+pad_num*offset] = 0xf1;
400   state->m_smpc.OREG[1+pad_num*offset] = 0x34;
401   state->m_smpc.OREG[2+pad_num*offset] = game_key>>8; // game buttons, TODO
402   state->m_smpc.OREG[3+pad_num*offset] = game_key & 0xff;
403   /*
404       x--- ---- 0
405       -x-- ---- caps lock
406       --x- ---- num lock
407       ---x ---- scroll lock
408       ---- x--- data ok
409       ---- -x-- 1
410       ---- --x- 1
411       ---- ---x Break key
412   */
413   state->m_smpc.OREG[4+pad_num*offset] = state->m_keyb.status | 6;
414   state->m_smpc.OREG[5+pad_num*offset] = state->m_keyb.data;
415}
416
417static void smpc_mouse(running_machine &machine, UINT8 pad_num, UINT8 offset, UINT8 id)
418{
419   saturn_state *state = machine.driver_data<saturn_state>();
420   static const char *const mousenames[2][3] = { { "MOUSEB1", "MOUSEX1", "MOUSEY1" },
421                                       { "MOUSEB2", "MOUSEX2", "MOUSEY2" }};
422   UINT8 mouse_ctrl;
423   INT16 mouse_x, mouse_y;
424
425   mouse_ctrl = machine.root_device().ioport(mousenames[pad_num][0])->read();
426   mouse_x = machine.root_device().ioport(mousenames[pad_num][1])->read();
427   mouse_y = machine.root_device().ioport(mousenames[pad_num][2])->read();
428
429   if(mouse_x < 0)
430      mouse_ctrl |= 0x10;
431
432   if(mouse_y < 0)
433      mouse_ctrl |= 0x20;
434
435   if((mouse_x & 0xff00) != 0xff00 && (mouse_x & 0xff00) != 0x0000)
436      mouse_ctrl |= 0x40;
437
438   if((mouse_y & 0xff00) != 0xff00 && (mouse_y & 0xff00) != 0x0000)
439      mouse_ctrl |= 0x80;
440
441   state->m_smpc.OREG[0+pad_num*offset] = 0xf1;
442   state->m_smpc.OREG[1+pad_num*offset] = id; // 0x23 / 0xe3
443   state->m_smpc.OREG[2+pad_num*offset] = mouse_ctrl;
444   state->m_smpc.OREG[3+pad_num*offset] = mouse_x & 0xff;
445   state->m_smpc.OREG[4+pad_num*offset] = mouse_y & 0xff;
446}
447
448/* TODO: is there ANY game on which the MD pad works? */
449static void smpc_md_pad(running_machine &machine, UINT8 pad_num, UINT8 offset, UINT8 id)
450{
451   saturn_state *state = machine.driver_data<saturn_state>();
452   static const char *const padnames[] = { "MD_JOY1", "MD_JOY2" };
453   UINT16 pad_data;
454
455   pad_data = machine.root_device().ioport(padnames[pad_num])->read();
456   state->m_smpc.OREG[0+pad_num*offset] = 0xf1;
457   state->m_smpc.OREG[1+pad_num*offset] = id;
458   state->m_smpc.OREG[2+pad_num*offset] = pad_data>>8;
459   if(id == 0xe2) // MD 6 Button PAD
460      state->m_smpc.OREG[3+pad_num*offset] = pad_data & 0xff;
461}
462
463static void smpc_unconnected(running_machine &machine, UINT8 pad_num, UINT8 offset)
464{
465   saturn_state *state = machine.driver_data<saturn_state>();
466
467   state->m_smpc.OREG[0+pad_num*offset] = 0xf0;
468}
469
470static TIMER_CALLBACK( intback_peripheral )
471{
472   saturn_state *state = machine.driver_data<saturn_state>();
473   int pad_num;
474   static const UINT8 peri_id[10] = { 0x02, 0x13, 0x15, 0x23, 0x23, 0x34, 0xe1, 0xe2, 0xe3, 0xff };
475   UINT8 read_id[2];
476   UINT8 offset;
477
478//  if (LOG_SMPC) logerror("SMPC: providing PAD data for intback, pad %d\n", intback_stage-2);
479
480   read_id[0] = (machine.root_device().ioport("INPUT_TYPE")->read()) & 0x0f;
481   read_id[1] = (machine.root_device().ioport("INPUT_TYPE")->read()) >> 4;
482
483   /* doesn't work? */
484   //pad_num = state->m_smpc.intback_stage - 1;
485
486   if(LOG_PAD_CMD) printf("%d %d %d\n",state->m_smpc.intback_stage - 1,machine.primary_screen->vpos(),(int)machine.primary_screen->frame_number());
487
488   offset = 0;
489
490   for(pad_num=0;pad_num<2;pad_num++)
491   {
492      switch(read_id[pad_num])
493      {
494         case 0: smpc_digital_pad(machine,pad_num,offset); break;
495         case 1: smpc_analog_pad(machine,pad_num,offset,peri_id[read_id[pad_num]]); break; /* Steering Wheel */
496         case 2: smpc_analog_pad(machine,pad_num,offset,peri_id[read_id[pad_num]]); break; /* Analog Pad */
497         case 4: smpc_mouse(machine,pad_num,offset,peri_id[read_id[pad_num]]); break; /* Pointing Device */
498         case 5: smpc_keyboard(machine,pad_num,offset); break;
499         case 6: smpc_md_pad(machine,pad_num,offset,peri_id[read_id[pad_num]]); break; /* MD 3B PAD */
500         case 7: smpc_md_pad(machine,pad_num,offset,peri_id[read_id[pad_num]]); break; /* MD 6B PAD */
501         case 8: smpc_mouse(machine,pad_num,offset,peri_id[read_id[pad_num]]); break; /* Saturn Mouse */
502         case 9: smpc_unconnected(machine,pad_num,offset); break;
503      }
504
505      offset += (peri_id[read_id[pad_num]] & 0xf) + 2; /* offset for port 2 */
506   }
507
508   if (state->m_smpc.intback_stage == 2)
509   {
510      state->m_smpc.SR = (0x80 | state->m_smpc.pmode);    // pad 2, no more data, echo back pad mode set by intback
511      state->m_smpc.intback_stage = 0;
512   }
513   else
514   {
515      state->m_smpc.SR = (0xc0 | state->m_smpc.pmode);    // pad 1, more data, echo back pad mode set by intback
516      state->m_smpc.intback_stage ++;
517   }
518
519   if(!(state->m_scu.ism & IRQ_SMPC))
520      state->m_maincpu->set_input_line_and_vector(8, HOLD_LINE, 0x47);
521   else
522      state->m_scu.ist |= (IRQ_SMPC);
523
524   state->m_smpc.OREG[31] = 0x10; /* callback for last command issued */
525   state->m_smpc.SF = 0x00;    /* clear hand-shake flag */
526}
527
528static TIMER_CALLBACK( saturn_smpc_intback )
529{
530   saturn_state *state = machine.driver_data<saturn_state>();
531
532   if(state->m_smpc.intback_buf[0] != 0)
533   {
534      {
535         int i;
536
537         state->m_smpc.OREG[0] = (0x80) | ((state->m_NMI_reset & 1) << 6); // bit 7: SETTIME (RTC isn't setted up properly)
538
539         for(i=0;i<7;i++)
540            state->m_smpc.OREG[1+i] = state->m_smpc.rtc_data[i];
541
542         state->m_smpc.OREG[8]=0x00;  //Cartridge code?
543
544         state->m_smpc.OREG[9] = state->m_saturn_region;
545
546         state->m_smpc.OREG[10]= 0 << 7 |
547                              state->m_vdp2.dotsel << 6 |
548                              1 << 5 |
549                              1 << 4 |
550                              0 << 3 | //MSHNMI
551                              1 << 2 |
552                              0 << 1 | //SYSRES
553                              0 << 0;  //SOUNDRES
554         state->m_smpc.OREG[11]= 0 << 6; //CDRES
555
556         for(i=0;i<4;i++)
557            state->m_smpc.OREG[12+i]=state->m_smpc.SMEM[i];
558
559         for(i=0;i<15;i++)
560            state->m_smpc.OREG[16+i]=0xff; // undefined
561      }
562
563      state->m_smpc.intback_stage = (state->m_smpc.intback_buf[1] & 8) >> 3; // first peripheral
564      state->m_smpc.SR = 0x40 | state->m_smpc.intback_stage << 5;
565      state->m_smpc.pmode = state->m_smpc.intback_buf[0]>>4;
566
567      if(!(state->m_scu.ism & IRQ_SMPC))
568         state->m_maincpu->set_input_line_and_vector(8, HOLD_LINE, 0x47);
569      else
570         state->m_scu.ist |= (IRQ_SMPC);
571
572      /* put issued command in OREG31 */
573      state->m_smpc.OREG[31] = 0x10;
574      /* clear hand-shake flag */
575      state->m_smpc.SF = 0x00;
576   }
577   else if(state->m_smpc.intback_buf[1] & 8)
578   {
579      state->m_smpc.intback_stage = (state->m_smpc.intback_buf[1] & 8) >> 3; // first peripheral
580      state->m_smpc.SR = 0x40;
581      state->m_smpc.OREG[31] = 0x10;
582      machine.scheduler().timer_set(attotime::from_usec(0), FUNC(intback_peripheral),0);
583   }
584   else
585   {
586      printf("SMPC intback bogus behaviour called %02x %02x\n",state->m_smpc.IREG[0],state->m_smpc.IREG[1]);
587   }
588
589}
590
591static void smpc_rtc_write(running_machine &machine)
592{
593   saturn_state *state = machine.driver_data<saturn_state>();
594   int i;
595
596   for(i=0;i<7;i++)
597      state->m_smpc.rtc_data[i] = state->m_smpc.IREG[i];
598}
599
600static void smpc_memory_setting(running_machine &machine)
601{
602   saturn_state *state = machine.driver_data<saturn_state>();
603   int i;
604
605   for(i=0;i<4;i++)
606      state->m_smpc.SMEM[i] = state->m_smpc.IREG[i];
607}
608
609static void smpc_nmi_req(running_machine &machine)
610{
611   saturn_state *state = machine.driver_data<saturn_state>();
612
613   /*NMI is unconditionally requested */
614   state->m_maincpu->set_input_line(INPUT_LINE_NMI, PULSE_LINE);
615}
616
617static TIMER_CALLBACK( smpc_nmi_set )
618{
619   saturn_state *state = machine.driver_data<saturn_state>();
620
621//  printf("%d %d\n",machine.primary_screen->hpos(),machine.primary_screen->vpos());
622   state->m_NMI_reset = param;
623   /* put issued command in OREG31 */
624   state->m_smpc.OREG[31] = 0x19 + param;
625   /* clear hand-shake flag */
626   state->m_smpc.SF = 0x00;
627
628   //state->m_smpc.OREG[0] = (0x80) | ((state->m_NMI_reset & 1) << 6);
629}
630
631
632/********************************************
633 *
634 * COMREG sub-routine
635 *
636 *******************************************/
637
638static void smpc_comreg_exec(address_space &space, UINT8 data, UINT8 is_stv)
639{
640   saturn_state *state = space.machine().driver_data<saturn_state>();
641
642   switch (data)
643   {
644      case 0x00:
645         if(LOG_SMPC) printf ("SMPC: Master ON\n");
646         smpc_master_on(space.machine());
647         break;
648      //case 0x01: Master OFF?
649      case 0x02:
650      case 0x03:
651         if(LOG_SMPC) printf ("SMPC: Slave %s %d %d\n",(data & 1) ? "off" : "on",space.machine().primary_screen->hpos(),space.machine().primary_screen->vpos());
652         if((data & 1) != (state->m_smpc.slave_on & 1))
653            space.machine().scheduler().timer_set(attotime::from_usec(100), FUNC(smpc_slave_enable),data & 1);
654         else /* guess: if Slave state is equal to the previous one, just execute less code. ask Greatest Nine '97. Unless SMPC is really so fast ... */
655            space.machine().scheduler().timer_set(attotime::from_usec(5), FUNC(smpc_slave_enable),data & 1);
656         break;
657      case 0x06:
658      case 0x07:
659         if(LOG_SMPC) printf ("SMPC: Sound %s\n",(data & 1) ? "off" : "on");
660
661         if(!is_stv)
662            space.machine().scheduler().timer_set(attotime::from_usec(100), FUNC(smpc_sound_enable),data & 1);
663         break;
664      /*CD (SH-1) ON/OFF */
665      //case 0x08:
666      //case 0x09:
667      case 0x0d:
668         if(LOG_SMPC) printf ("SMPC: System Reset\n");
669         smpc_system_reset(space.machine());
670         break;
671      case 0x0e:
672      case 0x0f:
673         if(LOG_SMPC) printf ("SMPC: Change Clock to %s (%d %d)\n",data & 1 ? "320" : "352",space.machine().primary_screen->hpos(),space.machine().primary_screen->vpos());
674
675         /* on ST-V timing of this is pretty fussy, you get 2 credits at start-up otherwise
676            sokyugurentai threshold is 74 lines
677            shanhigw threshold is 90 lines
678            I assume that it needs ~100 lines, so 6666,(6) usecs. Obviously needs HW tests ... */
679
680         space.machine().scheduler().timer_set(attotime::from_usec(6666), FUNC(smpc_change_clock),data & 1);
681         break;
682      /*"Interrupt Back"*/
683      case 0x10:
684         if(0)
685         {
686            saturn_state *state = space.machine().driver_data<saturn_state>();
687            printf ("SMPC: Status Acquire %02x %02x %02x %d\n",state->m_smpc.IREG[0],state->m_smpc.IREG[1],state->m_smpc.IREG[2],space.machine().primary_screen->vpos());
688         }
689
690         if(is_stv)
691            space.machine().scheduler().timer_set(attotime::from_usec(700), FUNC(stv_smpc_intback),0); //TODO: variable time
692         else
693         {
694            int timing;
695
696            timing = 100;
697
698            if(state->m_smpc.IREG[0] != 0) // non-peripheral data
699               timing += 100;
700
701            if(state->m_smpc.IREG[1] & 8) // peripheral data
702               timing += 700;
703
704            /* TODO: check if IREG[2] is setted to 0xf0 */
705            {
706               int i;
707
708               for(i=0;i<3;i++)
709                  state->m_smpc.intback_buf[i] = state->m_smpc.IREG[i];
710            }
711
712            if(LOG_PAD_CMD) printf("INTBACK %02x %02x %d %d\n",state->m_smpc.IREG[0],state->m_smpc.IREG[1],space.machine().primary_screen->vpos(),(int)space.machine().primary_screen->frame_number());
713            space.machine().scheduler().timer_set(attotime::from_usec(timing), FUNC(saturn_smpc_intback),0); //TODO: is variable time correct?
714         }
715         break;
716      /* RTC write*/
717      case 0x16:
718         if(LOG_SMPC) printf("SMPC: RTC write\n");
719         smpc_rtc_write(space.machine());
720         break;
721      /* SMPC memory setting*/
722      case 0x17:
723         if(LOG_SMPC) printf ("SMPC: memory setting\n");
724         smpc_memory_setting(space.machine());
725         break;
726      case 0x18:
727         if(LOG_SMPC) printf ("SMPC: NMI request\n");
728         smpc_nmi_req(space.machine());
729         break;
730      case 0x19:
731      case 0x1a:
732         if(LOG_SMPC) printf ("SMPC: NMI %sable %d %d\n",data & 1 ? "Dis" : "En",space.machine().primary_screen->hpos(),space.machine().primary_screen->vpos());
733         space.machine().scheduler().timer_set(attotime::from_usec(100), FUNC(smpc_nmi_set),data & 1);
734         break;
735      default:
736         printf ("cpu '%s' (PC=%08X) SMPC: undocumented Command %02x\n", space.device().tag(), space.device().safe_pc(), data);
737   }
738}
739
740/********************************************
741 *
742 * ST-V handlers
743 *
744 *******************************************/
745
746READ8_HANDLER( stv_SMPC_r )
747{
748   saturn_state *state = space.machine().driver_data<saturn_state>();
749   int return_data = 0;
750
751   if(!(offset & 1))
752      return 0;
753
754   if(offset >= 0x21 && offset <= 0x5f)
755      return_data = state->m_smpc.OREG[(offset-0x21) >> 1];
756
757   if (offset == 0x61) // TODO: SR
758      return_data = 0x20 ^ 0xff;
759
760   if (offset == 0x63)
761      return_data = state->m_smpc.SF;
762
763   if (offset == 0x75)//PDR1 read
764      return_data = state->ioport("DSW1")->read();
765
766   if (offset == 0x77)//PDR2 read
767      return_data = (0xfe | space.machine().device<eeprom_device>("eeprom")->read_bit());
768
769   return return_data;
770}
771
772WRITE8_HANDLER( stv_SMPC_w )
773{
774   saturn_state *state = space.machine().driver_data<saturn_state>();
775
776   if (!(offset & 1)) // avoid writing to even bytes
777      return;
778
779//  if(LOG_SMPC) printf ("8-bit SMPC Write to Offset %02x with Data %02x\n", offset, data);
780
781   if(offset >= 1 && offset <= 0xd)
782      state->m_smpc.IREG[offset >> 1] = data;
783
784   if (offset == 0x1f) // COMREG
785   {
786      smpc_comreg_exec(space,data,1);
787
788      // we've processed the command, clear status flag
789      if(data != 0x10 && data != 0x02 && data != 0x03 && data != 0xe && data != 0xf && data != 0x19 && data != 0x1a)
790      {
791         state->m_smpc.OREG[31] = data; //read-back command
792         state->m_smpc.SF = 0x00;
793      }
794      /*TODO:emulate the timing of each command...*/
795   }
796
797   if(offset == 0x63)
798      state->m_smpc.SF = data & 1;
799
800   if(offset == 0x75)
801   {
802      /*
803      -xx- ---- PDR1
804      ---x ---- EEPROM write bit
805      ---- x--- EEPROM CLOCK line
806      ---- -x-- EEPROM CS line
807      ---- --xx A-Bus bank bits
808      */
809      eeprom_device *eeprom = space.machine().device<eeprom_device>("eeprom");
810      eeprom->set_clock_line((data & 0x08) ? ASSERT_LINE : CLEAR_LINE);
811      eeprom->write_bit(data & 0x10);
812      eeprom->set_cs_line((data & 0x04) ? CLEAR_LINE : ASSERT_LINE);
813      state->m_stv_multi_bank = data & 3;
814
815      stv_select_game(space.machine(), state->m_stv_multi_bank);
816
817      state->m_smpc.PDR1 = (data & 0x60);
818   }
819
820   if(offset == 0x77)
821   {
822      /*
823          -xx- ---- PDR2
824          ---x ---- Enable Sound System (ACTIVE LOW)
825      */
826      //popmessage("PDR2 = %02x",state->m_smpc_ram[0x77]);
827
828      if(LOG_SMPC) printf("SMPC: M68k %s\n",(data & 0x10) ? "off" : "on");
829      //space.machine().scheduler().timer_set(attotime::from_usec(100), FUNC(smpc_sound_enable),(state->m_smpc_ram[0x77] & 0x10) >> 4);
830      state->m_audiocpu->set_input_line(INPUT_LINE_RESET, (data & 0x10) ? ASSERT_LINE : CLEAR_LINE);
831      state->m_en_68k = ((data & 0x10) >> 4) ^ 1;
832
833      //if(LOG_SMPC) printf("SMPC: ram [0x77] = %02x\n",data);
834      state->m_smpc.PDR2 = (data & 0x60);
835   }
836
837   if(offset == 0x7d)
838   {
839      /*
840      ---- --x- IOSEL2 direct (1) / control mode (0) port select
841      ---- ---x IOSEL1 direct (1) / control mode (0) port select
842      */
843      state->m_smpc.IOSEL1 = (data & 1) >> 0;
844      state->m_smpc.IOSEL2 = (data & 2) >> 1;
845   }
846
847   if(offset == 0x7f)
848   {
849      //enable PAD irq & VDP2 external latch for port 1/2
850      state->m_smpc.EXLE1 = (data & 1) >> 0;
851      state->m_smpc.EXLE2 = (data & 2) >> 1;
852   }
853}
854
855/********************************************
856 *
857 * Saturn handlers
858 *
859 *******************************************/
860
861UINT8 saturn_state::smpc_th_control_mode(UINT8 pad_n)
862{
863   int th;
864   const char *const padnames[] = { "JOY1", "JOY2" };
865   UINT8 res = 0;
866
867   th = (pad_n == 0) ? ((m_smpc.PDR1>>5) & 3) : ((m_smpc.PDR2>>6) & 3);
868
869   if (LOG_SMPC) printf("SMPC: SH-2 TH control mode, returning pad data %d for phase %d\n",pad_n+1, th);
870
871   switch(th)
872   {
873      /* TODO: 3D Lemmings bogusly enables TH Control mode, wants this to return the ID, needs HW tests.  */
874      case 3:
875         res = th<<6;
876         res |= 0x14;
877         res |= machine().root_device().ioport(padnames[pad_n])->read() & 8; // L
878         break;
879      case 2:
880         res = th<<6;
881         //  1 C B Right Left Down Up
882         res|= (((machine().root_device().ioport(padnames[pad_n])->read()>>4)) & 0x30); // C & B
883         res|= (((machine().root_device().ioport(padnames[pad_n])->read()>>12)) & 0xf);
884         break;
885      case 1:
886         res = th<<6;
887         res |= 0x10;
888         res |= (machine().root_device().ioport(padnames[pad_n])->read()>>4) & 0xf; // R, X, Y, Z
889         break;
890      case 0:
891         res = th<<6;
892         //  0 Start A 0 0    Down Up
893         res|= (((machine().root_device().ioport(padnames[pad_n])->read()>>6)) & 0x30); // Start & A
894         res|= (((machine().root_device().ioport(padnames[pad_n])->read()>>12)) & 0x3);
895         break;
896   }
897
898   return res;
899}
900
901UINT8 saturn_state::smpc_direct_mode(UINT8 pad_n)
902{
903   int hshake;
904   const int shift_bit[4] = { 4, 12, 8, 0 };
905   const char *const padnames[] = { "JOY1", "JOY2" };
906
907   hshake = (pad_n == 0) ? ((m_smpc.PDR1>>5) & 3) : ((m_smpc.PDR2>>5) & 3);
908
909   if (LOG_SMPC) logerror("SMPC: SH-2 direct mode, returning data for phase %d\n", hshake);
910
911   return 0x80 | 0x10 | ((machine().root_device().ioport(padnames[pad_n])->read()>>shift_bit[hshake]) & 0xf);
912}
913
914READ8_MEMBER( saturn_state::saturn_SMPC_r )
915{
916   UINT8 return_data = 0;
917
918   if (!(offset & 1)) // avoid reading to even bytes (TODO: is it 0s or 1s?)
919      return 0x00;
920
921   if(offset >= 0x21 && offset <= 0x5f)
922      return_data = m_smpc.OREG[(offset-0x21) >> 1];
923
924   if (offset == 0x61)
925      return_data = m_smpc.SR;
926
927   if (offset == 0x63)
928   {
929      //printf("SF %d %d\n",space.machine().primary_screen->hpos(),space.machine().primary_screen->vpos());
930      return_data = m_smpc.SF;
931   }
932
933   if (offset == 0x75 || offset == 0x77)//PDR1/2 read
934   {
935      if ((m_smpc.IOSEL1 && offset == 0x75) || (m_smpc.IOSEL2 && offset == 0x77))
936      {
937         UINT8 cur_ddr;
938
939         if(machine().root_device().ioport("INPUT_TYPE")->read() && !(space.debugger_access()))
940         {
941            popmessage("Warning: read with SH-2 direct mode with a non-pad device");
942            return 0;
943         }
944
945         cur_ddr = (offset == 0x75) ? m_smpc.DDR1 : m_smpc.DDR2;
946
947         switch(cur_ddr & 0x60)
948         {
949            case 0x40: return_data = smpc_th_control_mode(offset == 0x77); break;
950            case 0x60: return_data = smpc_direct_mode(offset == 0x77); break;
951            default:
952               popmessage("SMPC: unemulated control method %02x, contact MAMEdev",cur_ddr & 0x60);
953               return_data = 0;
954               break;
955         }
956      }
957   }
958
959   if (LOG_SMPC) logerror ("cpu %s (PC=%08X) SMPC: Read from Byte Offset %02x (%d) Returns %02x\n", space.device().tag(), space.device().safe_pc(), offset, offset>>1, return_data);
960
961   return return_data;
962}
963
964WRITE8_MEMBER( saturn_state::saturn_SMPC_w )
965{
966   if (LOG_SMPC) logerror ("8-bit SMPC Write to Offset %02x (reg %d) with Data %02x\n", offset, offset>>1, data);
967
968   if (!(offset & 1)) // avoid writing to even bytes
969      return;
970
971   if(offset >= 1 && offset <= 0xd)
972      m_smpc.IREG[offset >> 1] = data;
973
974   if(offset == 1) //IREG0, check if a BREAK / CONTINUE request for INTBACK command
975   {
976      if(m_smpc.intback_stage)
977      {
978         if(data & 0x40)
979         {
980            if(LOG_PAD_CMD) printf("SMPC: BREAK request\n");
981            m_smpc.SR &= 0x0f;
982            m_smpc.intback_stage = 0;
983         }
984         else if(data & 0x80)
985         {
986            if(LOG_PAD_CMD) printf("SMPC: CONTINUE request\n");
987            machine().scheduler().timer_set(attotime::from_usec(700), FUNC(intback_peripheral),0); /* TODO: is timing correct? */
988            m_smpc.OREG[31] = 0x10;
989            m_smpc.SF = 0x01; //TODO: set hand-shake flag?
990         }
991      }
992   }
993
994   if (offset == 0x1f)
995   {
996      smpc_comreg_exec(space,data,0);
997
998      // we've processed the command, clear status flag
999      if(data != 0x10 && data != 2 && data != 3 && data != 6 && data != 7 && data != 0x0e && data != 0x0f && data != 0x19 && data != 0x1a)
1000      {
1001         m_smpc.OREG[31] = data; //read-back for last command issued
1002         m_smpc.SF = 0x00; //clear hand-shake flag
1003      }
1004      /*TODO:emulate the timing of each command...*/
1005   }
1006
1007   if (offset == 0x63)
1008      m_smpc.SF = data & 1; // hand-shake flag
1009
1010   if(offset == 0x75)  // PDR1
1011      m_smpc.PDR1 = data & 0x7f;
1012
1013   if(offset == 0x77)  // PDR2
1014      m_smpc.PDR2 = data & 0x7f;
1015
1016   if(offset == 0x79)
1017      m_smpc.DDR1 = data & 0x7f;
1018
1019   if(offset == 0x7b)
1020      m_smpc.DDR2 = data & 0x7f;
1021
1022   if(offset == 0x7d)
1023   {
1024      m_smpc.IOSEL1 = data & 1;
1025      m_smpc.IOSEL2 = (data & 2) >> 1;
1026   }
1027
1028   if(offset == 0x7f)
1029   {
1030      //enable PAD irq & VDP2 external latch for port 1/2
1031      m_smpc.EXLE1 = (data & 1) >> 0;
1032      m_smpc.EXLE2 = (data & 2) >> 1;
1033   }
1034}
trunk/src/mame/machine/smpc.h
r20946r20947
1DECLARE_WRITE8_HANDLER( stv_SMPC_w );
2DECLARE_READ8_HANDLER( stv_SMPC_r );
3DECLARE_WRITE8_HANDLER( saturn_SMPC_w );
4DECLARE_READ8_HANDLER( saturn_SMPC_r );
trunk/src/mame/machine/scudsp.c
r20946r20947
1/******************************************************************************************
2System Control Unit - DSP emulator version 0.09
3
4Written by Angelo Salese & Mariusz Wojcieszek
5
6Changelog:
7110807: Angelo Salese
8- Allow the Program Counter to be read-backable from SH-2, needed by Virtua Fighter to not
9  get stuck on "round 1" announcement;
10
11110806: Angelo Salese
12- Allows reading from non-work ram h areas;
13- Fixed DMA add values;
14- Fixed a MVI condition shift flag bug, now Sega Saturn produces sound during splash screen;
15- Removed left-over IRQ;
16
17110722: Angelo Salese
18- Added DSP IRQ command, tested with "The King of Boxing"
19
20110527: Angelo Salese
21- Fixed incorrectly setted execute flag clearance, allows animation of the Sega Saturn
22  splash screen;
23
24051129: Mariusz Wojcieszek
25- Fixed parallel instructions which increment CT registers to update CT register only
26  once, after dsp operation is finished. This fixes instructions like
27  MOV MC0,X MOV MC0,Y used by vfremix
28- Changed ALU 32bit instructions to not sign extend their result when loaded to ALU.
29  This matches Sega's dspsim behaviour.
30- Changed DMA addnumber handling to match Sega's dspsim.
31
32050813: Mariusz Wojcieszek
33- Fixed add number in DSP DMA
34
35050412: Angelo Salese
36- Fixed the T0F behaviour in the DMA operation,it was causing an hang in Treasure Hunt
37  due of that.
38- Removed the dsp.log file creation when you are not using the debug build
39
40041114: Angelo Salese
41- Finished flags in ALU opcodes
42- SR opcode: MSB does not change.
43
44040328: Mariusz Wojcieszek
45- rewritten ALU and MUL operations using signed arithmetics
46- improved DMA
47- fixed MOV ALH,x
48
49031211: Mariusz Wojcieszek
50- result of ALU command is stored into ALU register
51- X-Bus command: MOV [s],X can be executed in parallel to other X-Bus commands
52- Y-Bus command: MOV [s],Y can be executed in parallel to other Y-Bus commands
53- Jump and LPS/BTM support:
54    jump addresses are absolute,
55    prefetched instructions are executed before jump is taken
56- after each instruction, X and Y is multiplied and contents are loaded into MUL register
57- fixed RL8
58- fixed MVI
59- flags computation in MVI and JMP is partly guessed (because of errors in docs)
60- added reading DSP mem from SH2 side
61- overworked disassembler
62
63 TODO:
64- Convert this to cpu structure
65- Disassembler: complete it
66- Add control flags
67- Croc: has a bug somewhere that never allows it to trip the ENDI opcode.
68  Snippet of interest is:
69  08    00823500                                            CLR A     MOV M0,PL
70  09    08040000    OR                                      MOV ALU,A
71  0A    D208000D    JMP NZ,$D
72  0B    00000000    NOP
73  0C    F8000000    ENDI
74  ...
75  40    00863502                                            MOV M0,A  MOV M2,PL
76  41    10003009    ADD                                               MOV ALL,MC0
77  42    D3400042    JMP T0,$42
78  43    00000000    NOP
79  44    D0000007    JMP $7
80
81******************************************************************************************/
82#include "emu.h"
83#include "machine/scudsp.h"
84#include "sound/scsp.h"
85#include "includes/stv.h"
86
87/*DSP macros*/
88#define PRF ((state->m_scu_regs[32] & 0x04000000) >> 26)
89#define EPF ((state->m_scu_regs[32] & 0x02000000) >> 25)
90#define T0F ((state->m_scu_regs[32] & 0x00800000) >> 23)
91#define SF  ((state->m_scu_regs[32] & 0x00400000) >> 22)
92#define ZF  ((state->m_scu_regs[32] & 0x00200000) >> 21)
93#define CF  ((state->m_scu_regs[32] & 0x00100000) >> 20)
94#define VF  ((state->m_scu_regs[32] & 0x00080000) >> 19)
95#define EF  ((state->m_scu_regs[32] & 0x00040000) >> 18)
96#define ESF ((state->m_scu_regs[32] & 0x00020000) >> 17)
97#define EXF ((state->m_scu_regs[32] & 0x00010000) >> 16)
98#define LEF ((state->m_scu_regs[32] & 0x00008000) >> 15)
99#define T0F_1 state->m_scu_regs[32]|=0x00800000
100#define T0F_0 state->m_scu_regs[32]&=~0x00800000
101#define EXF_0 state->m_scu_regs[32]&=~0x00010000
102#define EF_1  state->m_scu_regs[32]|=0x00040000
103
104#define SET_C(_val) (state->m_scu_regs[32] = ((state->m_scu_regs[32] & ~0x00100000) | ((_val) ? 0x00100000 : 0)))
105#define SET_S(_val) (state->m_scu_regs[32] = ((state->m_scu_regs[32] & ~0x00400000) | ((_val) ? 0x00400000 : 0)))
106#define SET_Z(_val) (state->m_scu_regs[32] = ((state->m_scu_regs[32] & ~0x00200000) | ((_val) ? 0x00200000 : 0)))
107#define SET_V(_val) (state->m_scu_regs[32] = ((state->m_scu_regs[32] & ~0x00080000) | ((_val) ? 0x00080000 : 0)))
108
109union SCUDSPREG32 {
110   INT32  si;
111   UINT32 ui;
112};
113
114union SCUDSPREG16 {
115   INT16  si;
116   UINT16 ui;
117};
118
119static struct {
120      UINT8 pc;                                      /*Program Counter*/
121      UINT8 delay;                                       /* Delay */
122      UINT8 top;                                     /*Jump Command memory*/
123      UINT16 lop;                                    /*Counter Register*/   /*12-bits*/
124      UINT8  ct0,ct1,ct2,ct3;                        /*Index for RAM*/      /*6-bits */
125      UINT32 md0[0x40],md1[0x40],md2[0x40],md3[0x40]; /*RAM memory*/
126      UINT8  ra;                                     /*RAM selector*/
127      SCUDSPREG32 rx;                                /*X-Bus register*/
128      INT64 mul;                                      /*Multiplier register*//*48-bits*/
129      SCUDSPREG32 ry;                                /*Y-Bus register*/
130      INT64  alu;                                     /*ALU register*/       /*48-bits*/
131      SCUDSPREG16 ph;                                /*ALU high register*/
132      SCUDSPREG32 pl;                                /*ALU low register*/
133      SCUDSPREG16 ach;                                   /*ALU external high register*/
134      SCUDSPREG32 acl;                                   /*ALU external low register*/
135      UINT32 ra0,wa0;                                /*DSP DMA registers*/
136      UINT32 internal_prg[0x100];
137} dsp_reg;
138
139static UINT32 opcode;
140static UINT8 update_mul = 0;
141
142#ifdef MAME_DEBUG
143#define DEBUG_DSP 1
144#else
145#define DEBUG_DSP 0
146#endif
147
148static char dasm_buffer[100];
149#if DEBUG_DSP
150static FILE *log_file = NULL;
151#endif
152static void dsp_dasm_opcode( UINT32 op, char *buffer );
153
154
155
156static UINT32 dsp_get_source_mem_value( UINT32 mode )
157{
158   UINT32 value = 0;
159
160   switch( mode )
161   {
162      case 0x0:   /* M0 */
163         value = dsp_reg.md0[ dsp_reg.ct0 ];
164         break;
165      case 0x1:   /* M1 */
166         value = dsp_reg.md1[ dsp_reg.ct1 ];
167         break;
168      case 0x2:   /* M2 */
169         value = dsp_reg.md2[ dsp_reg.ct2 ];
170         break;
171      case 0x3:   /* M3 */
172         value = dsp_reg.md3[ dsp_reg.ct3 ];
173         break;
174      case 0x4:   /* MC0 */
175         value = dsp_reg.md0[ dsp_reg.ct0++ ];
176         dsp_reg.ct0 &= 0x3f;
177         break;
178      case 0x5:   /* MC1 */
179         value = dsp_reg.md1[ dsp_reg.ct1++ ];
180         dsp_reg.ct1 &= 0x3f;
181         break;
182      case 0x6:   /* MC2 */
183         value = dsp_reg.md2[ dsp_reg.ct2++ ];
184         dsp_reg.ct2 &= 0x3f;
185         break;
186      case 0x7:   /* MC3 */
187         value = dsp_reg.md3[ dsp_reg.ct3++ ];
188         dsp_reg.ct3 &= 0x3f;
189         break;
190   }
191   return value;
192}
193
194static UINT32 dsp_get_source_mem_reg_value( UINT32 mode )
195{
196   if ( mode < 0x8 )
197   {
198      return dsp_get_source_mem_value( mode );
199   }
200   else
201   {
202      switch( mode )
203      {
204         case 0x9:
205            return (UINT32)((dsp_reg.alu & U64(0x00000000ffffffff)) >> 0);
206         case 0xA:
207            return (UINT32)((dsp_reg.alu & U64(0x0000ffffffff0000)) >> 16);
208      }
209   }
210   return 0;
211}
212
213static void dsp_set_dest_mem_reg( UINT32 mode, UINT32 value )
214{
215   switch( mode )
216   {
217      case 0x0:   /* MC0 */
218         dsp_reg.md0[ dsp_reg.ct0++ ] = value;
219         dsp_reg.ct0 &= 0x3f;
220         break;
221      case 0x1:   /* MC1 */
222         dsp_reg.md1[ dsp_reg.ct1++ ] = value;
223         dsp_reg.ct1 &= 0x3f;
224         break;
225      case 0x2:   /* MC2 */
226         dsp_reg.md2[ dsp_reg.ct2++ ] = value;
227         dsp_reg.ct2 &= 0x3f;
228         break;
229      case 0x3:   /* MC3 */
230         dsp_reg.md3[ dsp_reg.ct3++ ] = value;
231         dsp_reg.ct3 &= 0x3f;
232         break;
233      case 0x4:   /* RX */
234         dsp_reg.rx.ui = value;
235         update_mul = 1;
236         break;
237      case 0x5:   /* PL */
238         dsp_reg.pl.ui = value;
239         dsp_reg.ph.si = (dsp_reg.pl.si < 0) ? -1 : 0;
240         break;
241      case 0x6:   /* RA0 */
242         dsp_reg.ra0 = value;
243         break;
244      case 0x7:   /* WA0 */
245         dsp_reg.wa0 = value;
246         break;
247      case 0x8:
248      case 0x9:
249         /* ??? */
250         break;
251      case 0xa:   /* LOP */
252         dsp_reg.lop = value;
253         break;
254      case 0xb:   /* TOP */
255         dsp_reg.top = value;
256         break;
257      case 0xc:   /* CT0 */
258         dsp_reg.ct0 = value & 0x3f;
259         break;
260      case 0xd:   /* CT1 */
261         dsp_reg.ct1 = value & 0x3f;
262         break;
263      case 0xe:   /* CT2 */
264         dsp_reg.ct2 = value & 0x3f;
265         break;
266      case 0xf:   /* CT3 */
267         dsp_reg.ct3 = value & 0x3f;
268         break;
269   }
270}
271
272static void dsp_set_dest_mem_reg_2( UINT32 mode, UINT32 value )
273{
274   if ( mode < 0xb )
275   {
276      dsp_set_dest_mem_reg( mode, value );
277   }
278   else
279   {
280      switch( mode )
281      {
282         case 0xc:   /* PC */
283            dsp_reg.delay = dsp_reg.pc;  /* address next after this command will be executed twice */
284            dsp_reg.top = dsp_reg.pc;
285            dsp_reg.pc = value;
286            break;
287      }
288   }
289}
290
291static UINT32 dsp_compute_condition( address_space &space, UINT32 condition )
292{
293   saturn_state *state = space.machine().driver_data<saturn_state>();
294   UINT32 result = 0;
295
296   switch( condition & 0xf )
297   {
298      case 0x1:   /* Z */
299         result = ZF;
300         break;
301      case 0x2:   /* S */
302         result = SF;
303         break;
304      case 0x3:   /* ZS */
305         result = ZF | SF;
306         break;
307      case  0x4:  /* C */
308         result = CF;
309         break;
310      case 0x8:   /* T0 */
311         result = T0F;
312         break;
313   }
314   if ( !(condition & 0x20) )
315   {
316      result = !result;
317   }
318   return result;
319}
320
321static void dsp_set_dest_dma_mem( UINT32 memcode, UINT32 value, UINT32 counter )
322{
323   if ( memcode < 4 )
324   {
325      dsp_set_dest_mem_reg( memcode, value );
326   }
327   else if ( memcode == 4 )
328   {
329      dsp_reg.internal_prg[ counter & 0x100 ] = value;
330   }
331}
332
333static UINT32 dsp_get_mem_source_dma( UINT32 memcode, UINT32 counter )
334{
335   switch( memcode & 0x3 )
336   {
337      case 0x0:
338         return dsp_reg.md0[ (dsp_reg.ct0 + counter) & 0x3f ];
339      case 0x1:
340         return dsp_reg.md1[ (dsp_reg.ct1 + counter) & 0x3f ];
341      case 0x2:
342         return dsp_reg.md2[ (dsp_reg.ct2 + counter) & 0x3f ];
343      case 0x3:
344         return dsp_reg.md3[ (dsp_reg.ct3 + counter) & 0x3f ];
345   }
346   return 0;
347}
348
349UINT32 dsp_prg_ctrl_r(address_space &space)
350{
351   saturn_state *state = space.machine().driver_data<saturn_state>();
352
353   return (state->m_scu_regs[0x80/4] & 0x06ff8000) | (dsp_reg.pc & 0xff);
354}
355
356void dsp_prg_ctrl_w(address_space &space, UINT32 data)
357{
358   saturn_state *state = space.machine().driver_data<saturn_state>();
359
360   if(LEF) dsp_reg.pc = (data & 0xff);
361   if(EXF) dsp_execute_program(space);
362}
363
364void dsp_prg_data(UINT32 data)
365{
366   dsp_reg.internal_prg[dsp_reg.pc] = data;
367   dsp_reg.pc++;
368}
369
370void dsp_ram_addr_ctrl(UINT32 data)
371{
372   dsp_reg.ra = data & 0xff;
373
374   switch((dsp_reg.ra & 0xc0) >> 6)
375   {
376      case 0: dsp_reg.ct0 = (dsp_reg.ra & 0x3f); break;
377      case 1: dsp_reg.ct1 = (dsp_reg.ra & 0x3f); break;
378      case 2: dsp_reg.ct2 = (dsp_reg.ra & 0x3f); break;
379      case 3: dsp_reg.ct3 = (dsp_reg.ra & 0x3f); break;
380   }
381}
382
383void dsp_ram_addr_w(UINT32 data)
384{
385#if DEBUG_DSP
386   if ( log_file == NULL )
387   {
388      log_file = fopen( "dsp.log", "a" );
389   }
390   fprintf( log_file, "DSP: Writing mem %02X %04X\n", dsp_reg.ra & 0xff, data );
391#endif
392   dsp_set_dest_mem_reg( (dsp_reg.ra & 0xc0) >> 6, data );
393}
394
395UINT32 dsp_ram_addr_r()
396{
397   UINT32 data;
398
399   data = dsp_get_source_mem_value( ((dsp_reg.ra & 0xc0) >> 6) + 4 );
400#if DEBUG_DSP
401   if ( log_file == NULL )
402   {
403      log_file = fopen( "dsp.log", "a" );
404   }
405   fprintf( log_file, "DSP: Reading mem at %02X %04X\n", dsp_reg.ra & 0xff, data );
406#endif
407   return data;
408}
409
410static void dsp_operation(address_space &space)
411{
412   saturn_state *state = space.machine().driver_data<saturn_state>();
413   INT64 i1,i2;
414   INT32 i3;
415   int update_ct[4] = {0,0,0,0};
416   int dsp_mem;
417
418
419   /* ALU */
420   switch( (opcode & 0x3c000000) >> 26 )
421   {
422      case 0x0:   /* NOP */
423         break;
424      case 0x1:   /* AND */
425         i3 = dsp_reg.acl.si & dsp_reg.pl.si;
426         dsp_reg.alu = (UINT64)(UINT32)i3;
427         SET_Z(i3 == 0);
428         SET_C(0);
429         SET_S(i3 < 0);
430         break;
431      case 0x2:   /* OR */
432         i3 = dsp_reg.acl.si | dsp_reg.pl.si;
433         dsp_reg.alu = (UINT64)(UINT32)i3;
434         SET_C(0);
435         SET_S(i3 < 0);
436         /* TODO: Croc and some early Psygnosis games wants Z to be 1 when the result of this one is negative.
437                  Needs HW tests ... */
438         if(i3 < 0)
439            i3 = 0;
440         SET_Z(i3 == 0);
441         break;
442      case 0x3:   /* XOR */
443         i3 = dsp_reg.acl.si ^ dsp_reg.pl.si;
444         dsp_reg.alu = (UINT64)(UINT32)i3;
445         SET_Z(i3 == 0);
446         SET_C(0);
447         SET_S(i3 < 0);
448         break;
449      case 0x4:   /* ADD */
450         i3 = dsp_reg.acl.si + dsp_reg.pl.si;
451         dsp_reg.alu = (UINT64)(UINT32)i3;
452         //SET_Z(i3 == 0);
453         SET_Z( (i3 & S64(0xffffffffffff)) == 0 );
454         //SET_S(i3 < 0);
455         SET_S( i3 & S64(0x1000000000000));
456         SET_C(i3 & S64(0x100000000));
457         SET_V(((i3) ^ (dsp_reg.acl.si)) & ((i3) ^ (dsp_reg.pl.si)) & 0x80000000);
458         break;
459      case 0x5:   /* SUB */
460         i3 = dsp_reg.acl.si - dsp_reg.pl.si;
461         dsp_reg.alu = (UINT64)(UINT32)i3;
462         SET_Z(i3 == 0);
463         SET_C(i3 & S64(0x100000000));
464         SET_S(i3 < 0);
465         SET_V(((dsp_reg.pl.si) ^ (dsp_reg.acl.si)) & ((dsp_reg.pl.si) ^ (i3)) & 0x80000000);
466         break;
467      case 0x6:   /* AD2 */
468         i1 = CONCAT_64((INT32)dsp_reg.ph.si,dsp_reg.pl.si);
469         i2 = CONCAT_64((INT32)dsp_reg.ach.si,dsp_reg.acl.si);
470         dsp_reg.alu = i1 + i2;
471         SET_Z((dsp_reg.alu & S64(0xffffffffffff)) == 0);
472         SET_S((dsp_reg.alu & S64(0x800000000000)) > 0);
473         SET_C((dsp_reg.alu) & S64(0x1000000000000));
474         SET_V(((dsp_reg.alu) ^ (i1)) & ((dsp_reg.alu) ^ (i2)) & S64(0x800000000000));
475         break;
476      case 0x7:   /* ??? */
477         /* Unrecognized opcode */
478         break;
479      case 0x8:   /* SR */
480         i3 = (dsp_reg.acl.si >> 1) | (dsp_reg.acl.si & 0x80000000);/*MSB does not change*/
481         dsp_reg.alu = (UINT64)(UINT32)i3;
482         SET_Z(i3 == 0);
483         SET_S(i3 < 0);
484         SET_C(dsp_reg.acl.ui & 0x80000000);
485         break;
486      case 0x9:   /* RR */
487         i3 = ((dsp_reg.acl.ui >> 1) & 0x7fffffff) | ((dsp_reg.acl.ui << 31) & 0x80000000);
488         dsp_reg.alu = (UINT64)(UINT32)i3;
489         SET_Z( i3 == 0 );
490         SET_S( i3 < 0 );
491         SET_C( dsp_reg.acl.ui & 0x1 );
492         break;
493      case 0xa:   /* SL */
494         i3 = dsp_reg.acl.si << 1;
495         dsp_reg.alu = (UINT64)(UINT32)i3;
496         SET_Z( i3 == 0 );
497         SET_S( i3 < 0 );
498         SET_C( dsp_reg.acl.ui & 0x80000000 );
499         break;
500      case 0xB:   /* RL */
501         i3 = ((dsp_reg.acl.si << 1) & 0xfffffffe) | ((dsp_reg.acl.si >> 31) & 0x1);
502         dsp_reg.alu = (UINT64)(UINT32)i3;
503         SET_Z( i3 == 0 );
504         SET_S( i3 < 0 );
505         SET_C( dsp_reg.acl.ui & 0x80000000 );
506         break;
507      case 0xc:
508      case 0xd:
509      case 0xe:
510         /* Unrecognized opcode */
511         break;
512      case 0xF:   /* RL8 */
513         i3 = ((dsp_reg.acl.si << 8) & 0xffffff00) | ((dsp_reg.acl.si >> 24) & 0xff);
514         dsp_reg.alu = i3;
515         SET_Z( i3 == 0 );
516         SET_S( i3 < 0 );
517         SET_C( dsp_reg.acl.si & 0x01000000 );
518         break;
519   }
520
521   /* X-Bus */
522   if ( opcode & 0x2000000 )
523   {
524      /* MOV [s],X */
525      dsp_mem = (opcode & 0x700000) >> 20;
526      if ( dsp_mem & 4 )
527      {
528         dsp_mem &= 3;
529         update_ct[dsp_mem] = 1;
530      }
531      dsp_reg.rx.ui = dsp_get_source_mem_value( dsp_mem );
532      update_mul = 1;
533   }
534   switch( (opcode & 0x1800000) >> 23 )
535   {
536      case 0x0:   /* NOP */
537      case 0x1:   /* NOP ? */
538         break;
539      case 0x2:   /* MOV MUL,P */
540         dsp_reg.ph.ui = (UINT16)((dsp_reg.mul & U64(0x0000ffff00000000)) >> 32);
541         dsp_reg.pl.ui = (UINT32)((dsp_reg.mul & U64(0x00000000ffffffff)) >> 0);
542         break;
543      case 0x3:   /* MOV [s],P */
544         dsp_mem = (opcode & 0x700000) >> 20;
545         if ( dsp_mem & 4 )
546         {
547            dsp_mem &= 3;
548            update_ct[dsp_mem] = 1;
549         }
550         dsp_reg.pl.ui = dsp_get_source_mem_value(  dsp_mem );
551         dsp_reg.ph.si = (dsp_reg.pl.si < 0) ? -1 : 0;
552         break;
553   }
554
555   /* Y-Bus */
556   if ( opcode & 0x80000 )
557   {
558      /* MOV [s],Y */
559      dsp_mem = (opcode & 0x1C000 ) >> 14;
560      if (dsp_mem & 4)
561      {
562         dsp_mem &= 3;
563         update_ct[dsp_mem] = 1;
564      }
565      dsp_reg.ry.ui = dsp_get_source_mem_value( dsp_mem );
566      update_mul = 1;
567   }
568   switch( (opcode & 0x60000) >> 17 )
569   {
570      case 0x0:   /* NOP */
571         break;
572      case 0x1:   /* CLR A */
573         dsp_reg.acl.ui = 0;
574         dsp_reg.ach.ui = 0;
575         break;
576      case 0x2:   /* MOV ALU,A */
577         dsp_reg.ach.ui = (UINT16)((dsp_reg.alu & U64(0x0000ffff00000000)) >> 32);
578         dsp_reg.acl.ui = (UINT32)((dsp_reg.alu & U64(0x00000000ffffffff)) >> 0);
579         break;
580      case 0x3:   /* MOV [s], A */
581         dsp_mem = (opcode & 0x1C000 ) >> 14;
582         if (dsp_mem & 4)
583         {
584            dsp_mem &= 3;
585            update_ct[dsp_mem] = 1;
586         }
587         dsp_reg.acl.ui = dsp_get_source_mem_value( dsp_mem );
588         dsp_reg.ach.si = ((dsp_reg.acl.si < 0) ? -1 : 0);
589         break;
590   }
591
592   /* update CT registers */
593   if ( update_ct[0] ) { dsp_reg.ct0++; dsp_reg.ct0 &= 0x3f; };
594   if ( update_ct[1] ) { dsp_reg.ct1++; dsp_reg.ct1 &= 0x3f; };
595   if ( update_ct[2] ) { dsp_reg.ct2++; dsp_reg.ct2 &= 0x3f; };
596   if ( update_ct[3] ) { dsp_reg.ct3++; dsp_reg.ct3 &= 0x3f; };
597
598
599   /* D1-Bus */
600   switch( (opcode & 0x3000) >> 12 )
601   {
602      case 0x0:   /* NOP */
603         break;
604      case 0x1:   /* MOV SImm,[d] */
605         dsp_set_dest_mem_reg( (opcode & 0xf00) >> 8, (INT32)(INT8)(opcode & 0xff) );
606         break;
607      case 0x2:
608         /* ??? */
609         break;
610      case 0x3:   /* MOV [s],[d] */
611         dsp_set_dest_mem_reg( (opcode & 0xf00) >> 8, dsp_get_source_mem_reg_value( opcode & 0xf ) );
612         break;
613   }
614
615}
616
617static void dsp_move_immediate( address_space &space )
618{
619   UINT32 value;
620
621   if ( opcode & 0x2000000 )
622   {
623      if ( dsp_compute_condition( space, (opcode & 0x3F80000 ) >> 19 ) )
624      {
625         value = opcode & 0x7ffff;
626         if ( value & 0x40000 ) value |= 0xfff80000;
627         dsp_set_dest_mem_reg_2( (opcode & 0x3C000000) >> 26, value );
628      }
629   }
630   else
631   {
632      value = opcode & 0x1ffffff;
633      if ( value & 0x1000000 ) value |= 0xfe000000;
634      dsp_set_dest_mem_reg_2( (opcode & 0x3C000000) >> 26, value );
635   }
636}
637
638
639static void dsp_dma( address_space &space )
640{
641   saturn_state *state = space.machine().driver_data<saturn_state>();
642
643   UINT8 hold = (opcode &  0x4000) >> 14;
644   UINT32 add = (opcode & 0x38000) >> 15;
645   UINT32 dir_from_D0 = (opcode & 0x1000 ) >> 12;
646   UINT32 transfer_cnt = 0;
647   UINT32 source = 0, dest = 0;
648   UINT32 dsp_mem = (opcode & 0x300) >> 8;
649   UINT32 counter = 0;
650   UINT32 data;
651
652
653   T0F_1;
654
655   if ( opcode & 0x2000 )
656   {
657      transfer_cnt = dsp_get_source_mem_value( opcode & 0xf );
658      switch ( add & 0x7 )
659      {
660         case 0: add = 0; break;
661         case 1: add = 4; break;
662         default: add = 4; break;
663      }
664   }
665   else
666   {
667      transfer_cnt = opcode & 0xff;
668      switch( add )
669      {
670         case 0: add = 0; break;  /* 0 */
671         case 1: add = 4; break;  /* 1 */
672         case 2: add = 4; break;  /* 2 */
673         case 3: add = 16; break; /* 4 */
674         case 4: add = 16; break;  /* 8 */
675         case 5: add = 64; break; /* 16 */
676         case 6: add = 128; break; /* 32 */
677         case 7: add = 256; break; /* 64 */
678      }
679   }
680
681   if ( dir_from_D0 == 0 )
682   {
683      /* DMA D0,[RAM] */
684      source = dsp_reg.ra0 << 2;
685      source &= 0x07ffffff;
686      dest &= 0x07ffffff;
687      transfer_cnt &= 0xff;
688
689#if DEBUG_DSP
690      fprintf( log_file, "/*DSP DMA D0,[RAM%d],%d add=%d*/\n", dsp_mem, transfer_cnt, add );
691#endif
692
693      for ( counter = 0; counter < transfer_cnt ; counter++ )
694      {
695#if DEBUG_DSP
696         fprintf( log_file, "%08X, ", source ); fflush( log_file );
697#endif
698
699         if ( source >= 0x06000000 && source <= 0x060fffff )
700         {
701            data = space.read_dword(source );
702         }
703         else
704         {
705            data = (space.read_word(source)<<16) | space.read_word(source+2);
706            //popmessage( "Bad DSP DMA mem read = %08X", source );
707#if DEBUG_DSP
708            //fprintf( log_file, "/*Bad DSP DMA mem read = %08X*/\n", source );
709#endif
710         }
711
712#if DEBUG_DSP
713         fprintf( log_file, "%08X,\n", data );
714#endif
715         dsp_set_dest_dma_mem( dsp_mem, data, counter );
716         source += add;
717      }
718
719      if ( hold == 0 )
720      {
721         dsp_reg.ra0 += ((counter * add) >> 2);
722      }
723   }
724   else
725   {
726      /* DMA [RAM],D0 */
727      dest = dsp_reg.wa0 << 2;
728      source &= 0x07ffffff;
729      dest &= 0x07ffffff;
730      transfer_cnt &= 0xff;
731      //logerror("[DSP DMA] SRC = %08x | DEST = %08x | SIZE = %08x | ADD VALUE = %08x\n",source,dest,transfer_cnt,add);
732
733#if DEBUG_DSP
734      fprintf( log_file, "/*DSP DMA [RAM%d],D0,%d\tadd=%d,source=%08X*/\n", dsp_mem, transfer_cnt, add, source );
735#endif
736      for ( counter = 0; counter < transfer_cnt; counter++ )
737      {
738         space.write_dword(dest, dsp_get_mem_source_dma( dsp_mem, counter ) );
739         dest += add;
740      }
741
742      if ( hold == 0 )
743      {
744         dsp_reg.wa0 += ((counter * add) >> 2);
745      }
746   }
747
748   /* TODO: move this behind a timer */
749   T0F_0;
750}
751
752static void dsp_jump( address_space &space )
753{
754   if ( opcode & 0x3f80000 )
755   {
756      if ( dsp_compute_condition( space, (opcode & 0x3f80000) >> 19 ) )
757      {
758         dsp_reg.delay = dsp_reg.pc;
759         dsp_reg.pc = opcode & 0xff;
760      }
761   }
762   else
763   {
764      dsp_reg.delay = dsp_reg.pc;
765      dsp_reg.pc = opcode & 0xff;
766   }
767}
768
769static TIMER_CALLBACK( dsp_ended )
770{
771   saturn_state *state = machine.driver_data<saturn_state>();
772
773   if(!(state->m_scu.ism & IRQ_DSP_END))
774      state->m_maincpu->set_input_line_and_vector(0xa, HOLD_LINE, 0x45);
775   else
776      state->m_scu.ist |= (IRQ_DSP_END);
777
778   EF_1;
779}
780
781static void dsp_end( address_space &dmaspace )
782{
783   saturn_state *state = dmaspace.machine().driver_data<saturn_state>();
784
785   if(opcode & 0x08000000)
786   {
787      /*ENDI*/
788      dmaspace.machine().scheduler().timer_set(attotime::from_usec(300), FUNC(dsp_ended));
789   }
790
791   EXF_0; /* END / ENDI */
792}
793
794static void dsp_loop( void )
795{
796   if ( opcode & 0x8000000 )
797   {
798      /* LPS */
799      if ( dsp_reg.lop != 0 )
800      {
801         dsp_reg.lop--;
802         dsp_reg.delay = dsp_reg.pc;
803         dsp_reg.pc--;
804      }
805   }
806   else
807   {
808      /* BTM */
809      if ( dsp_reg.lop != 0 )
810      {
811         dsp_reg.lop--;
812         dsp_reg.delay = dsp_reg.pc;
813         dsp_reg.pc = dsp_reg.top;
814      }
815   }
816}
817
818#if DEBUG_DSP
819static void dsp_dump_mem( FILE *f )
820{
821   UINT16 i;
822
823   fprintf( f, "\n/*MEM 0*/\n{" );
824   for ( i = 0; i < 0x40; i++ )
825   {
826      fprintf( f, "%08X, ", dsp_reg.md0[ i ] );
827   }
828   fprintf( f, "}\n/*MEM 1*/\n{" );
829   for ( i = 0; i < 0x40; i++ )
830   {
831      fprintf( f, "%08X,", dsp_reg.md1[ i ] );
832   }
833   fprintf( f, "}\n/*MEM 2*/\n{" );
834   for ( i = 0; i < 0x40; i++ )
835   {
836      fprintf( f, "%08X,", dsp_reg.md2[ i ] );
837   }
838   fprintf( f, "}\n/*MEM 3*/\n{" );
839   for ( i = 0; i < 0x40; i++ )
840   {
841      fprintf( f, "%08X,", dsp_reg.md3[ i ] );
842   }
843   fprintf( f, "}\n" );
844}
845#endif
846
847void dsp_execute_program(address_space &dmaspace)
848{
849   UINT32 cycles_run = 0;
850   UINT8 cont = 1;
851#if DEBUG_DSP
852   UINT16 i;
853
854   if ( log_file == NULL )
855   {
856      log_file = fopen("dsp.log", "a");
857   }
858   for ( i = 0; i < 0x100; i++ )
859   {
860      dsp_dasm_opcode( dsp_reg.internal_prg[ i ], dasm_buffer );
861      fprintf( log_file, "%02X\t%08X\t%s\n", i, dsp_reg.internal_prg[ i ], dasm_buffer );
862   }
863   dsp_dump_mem( log_file );
864#endif
865
866   update_mul = 0;
867   do
868   {
869      if ( dsp_reg.delay )
870      {
871         opcode = dsp_reg.internal_prg[ dsp_reg.delay ];
872         dsp_reg.delay = 0;
873      }
874      else
875      {
876         opcode = dsp_reg.internal_prg[ dsp_reg.pc ];
877         dsp_reg.pc++;
878      }
879
880      dsp_dasm_opcode( opcode, dasm_buffer );
881
882      switch( (opcode & 0xc0000000) >> 30 )
883      {
884      case 0x00: /* 00 */
885         dsp_operation( dmaspace );
886         break;
887      case 0x01: /* 01 */
888         /* unrecognized opcode */
889         break;
890      case 0x02: /* 10 */
891         dsp_move_immediate( dmaspace );
892         break;
893      case 0x03: /* 11 */
894         switch( (opcode & 0x30000000) >> 28 )
895         {
896            case 0x00:
897               dsp_dma(dmaspace);
898               break;
899            case 0x01:
900               dsp_jump(dmaspace);
901               break;
902            case 0x02:
903               dsp_loop();
904               break;
905            case 0x03:
906               dsp_end(dmaspace);
907               cont = 0;
908               break;
909         }
910         break;
911      }
912      if ( update_mul == 1 )
913      {
914         dsp_reg.mul = (INT64)dsp_reg.rx.si * (INT64)dsp_reg.ry.si;
915         update_mul = 0;
916      }
917
918      cycles_run++;
919
920   } while( cont );
921#if DEBUG_DSP
922   dsp_dump_mem( log_file );
923   fprintf( log_file, "\nRun %d cycles\n\n", cycles_run );
924   fclose( log_file );
925   log_file = NULL;
926#endif
927}
928
929
930
931/***********************************************************************
932
933    SCU DSP Disassembler
934
935************************************************************************/
936static const char *const ALU_Commands[] =
937{
938   "",     /* 0000 */
939   "AND",  /* 0001 */
940   "OR",   /* 0010 */
941   "XOR",  /* 0011 */
942   "ADD",  /* 0100 */
943   "SUB",  /* 0101 */
944   "AD2",  /* 0110 */
945   "???",  /* 0111 */
946   "SR",   /* 1000 */
947   "RR",   /* 1001 */
948   "SL",   /* 1010 */
949   "RL",   /* 1011 */
950   "???",  /* 1100 */
951   "???",  /* 1101 */
952   "???",  /* 1110 */
953   "RL8",  /* 1111 */
954};
955
956static const char *const X_Commands[] =
957{
958   "",             /* 000 */
959   "",             /* 001 */   /* NOP? check instruction @ 0x0B */
960   "MOV MUL,P",    /* 010 */
961   "MOV %s,P",     /* 011 */
962   "MOV %s,X",     /* 100 */
963};
964
965static const char *const Y_Commands[] =
966{
967   "",             /* 000 */
968   "CLR A",        /* 001 */
969   "MOV ALU,A",    /* 010 */
970   "MOV %s,A",     /* 011 */
971   "MOV %s,Y",     /* 100 */
972};
973
974static const char *const D1_Commands[] =
975{
976   "",                 /* 00 */
977   "MOV %I8,%d",       /* 01 */
978   "???",              /* 10 */
979   "MOV %S,%d",        /* 11 */
980};
981
982static const char *const SourceMemory[] =
983{
984   "M0",           /* 000 */
985   "M1",           /* 001 */
986   "M2",           /* 010 */
987   "M3",           /* 011 */
988   "MC0",          /* 100 */
989   "MC1",          /* 101 */
990   "MC2",          /* 110 */
991   "MC3",          /* 111 */
992};
993
994static const char *const SourceMemory2[] =
995{
996   "M0",           /* 0000 */
997   "M1",           /* 0001 */
998   "M2",           /* 0010 */
999   "M3",           /* 0011 */
1000   "MC0",          /* 0100 */
1001   "MC1",          /* 0101 */
1002   "MC2",          /* 0110 */
1003   "MC3",          /* 0111 */
1004   "???",          /* 1000 */
1005   "ALL",          /* 1001 */
1006   "ALH",          /* 1010 */
1007   "???",          /* 1011 */
1008   "???",          /* 1100 */
1009   "???",          /* 1101 */
1010   "???",          /* 1110 */
1011   "???",          /* 1111 */
1012};
1013
1014static const char *const DestMemory[] =
1015{
1016   "MC0",          /* 0000 */
1017   "MC1",          /* 0001 */
1018   "MC2",          /* 0010 */
1019   "MC3",          /* 0011 */
1020   "RX",           /* 0100 */
1021   "PL",           /* 0101 */
1022   "RA0",          /* 0110 */
1023   "WA0",          /* 0111 */
1024   "???",          /* 1000 */
1025   "???",          /* 1001 */
1026   "LOP",          /* 1010 */
1027   "TOP",          /* 1011 */
1028   "CT0",          /* 1100 */
1029   "CT1",          /* 1101 */
1030   "CT2",          /* 1110 */
1031   "CT3",          /* 1111 */
1032};
1033
1034static const char *const DestDMAMemory[] =
1035{
1036   "M0",           /* 000 */
1037   "M1",           /* 001 */
1038   "M2",           /* 010 */
1039   "M3",           /* 011 */
1040   "PRG",          /* 100 */
1041   "???",          /* 101 */
1042   "???",          /* 110 */
1043   "???",          /* 111 */
1044};
1045
1046static const char *const MVI_Command[] =
1047{
1048   "MVI %I,%d",    /* 0 */
1049   "MVI %I,%d,%f", /* 1 */
1050};
1051
1052static const char *const JMP_Command[] =
1053{
1054   "JMP %IA",
1055   "JMP %f,%IA",
1056};
1057
1058static const char *const DMA_Command[] =
1059{
1060   "DMA%H%A D0,%M,%I",
1061   "DMA%H%A %s,D0,%I",
1062   "DMA%H%A D0,%M,%s",
1063   "DMA%H%A %s,D0,%s",
1064};
1065
1066
1067static void dsp_dasm_prefix( const char* format, char* buffer, UINT32 *data )
1068{
1069   for ( ; *format; format++ )
1070   {
1071      if ( *format == '%' )
1072      {
1073         switch( *++format )
1074         {
1075            case 'H':
1076               if ( *data )
1077               {
1078                  strcpy( buffer, "H" );
1079               }
1080               else
1081               {
1082                  *buffer = 0;
1083               }
1084               break;
1085            case 'A':
1086               if ( *data == 0 )
1087               {
1088                  strcpy( buffer, "0" );
1089               }
1090               else if ( *data == 1 )
1091               {
1092                  *buffer = 0;
1093               }
1094               else
1095               {
1096                  sprintf( buffer, "%d", 1 << (*data - 1) );
1097               }
1098               break;
1099            case 's':
1100               strcpy( buffer, SourceMemory[ *data & 0x7 ] );
1101               break;
1102            case 'd':
1103               strcpy( buffer, DestMemory[ *data & 0xf ] );
1104               break;
1105            case 'S':
1106               strcpy( buffer, SourceMemory2[ *data & 0xf ] );
1107               break;
1108            case 'I':
1109               ++format;
1110               if ( *format == '8' )
1111               {
1112                  sprintf( buffer, "#$%x", *data );
1113               }
1114               else if ( *format == 'A' )
1115               {
1116                  sprintf( buffer, "$%X", *data );
1117               }
1118               else
1119               {
1120                  --format;
1121                  sprintf( buffer, "#$%X", *data );
1122               }
1123               break;
1124            case 'f':
1125               if ( !(*data & 0x20) )
1126               {
1127                  strcpy( buffer, "N" );
1128                  buffer++;
1129               }
1130               switch( *data & 0xf )
1131               {
1132                  case 0x3:
1133                     strcpy( buffer, "ZS" );
1134                     break;
1135                  case 0x2:
1136                     strcpy( buffer, "S" );
1137                     break;
1138                  case 0x4:
1139                     strcpy( buffer, "C" );
1140                     break;
1141                  case 0x8:
1142                     strcpy( buffer, "T0" );
1143                     break;
1144                  case 0x1:
1145                     strcpy( buffer, "Z" );
1146                     break;
1147                  default:
1148                     strcpy( buffer, "?" );
1149                     break;
1150               }
1151               break;
1152            case 'M':
1153               strcpy( buffer, DestDMAMemory[ *data ] );
1154               break;
1155
1156         }
1157         data++;
1158         buffer += strlen( buffer );
1159      }
1160      else
1161      {
1162         *buffer++ = *format;
1163      }
1164   }
1165   *buffer = 0;
1166}
1167static void dsp_dasm_operation( UINT32 op, char *buffer )
1168{
1169   char *my_buffer = buffer;
1170   char temp_buffer[64];
1171   UINT32 data[2 ];
1172
1173   /* NOP */
1174   if ( (op & 0x3F8E3000) == 0 )
1175   {
1176      sprintf( buffer, "%-10s", "NOP" );
1177      return;
1178   }
1179   /* ALU */
1180   sprintf( my_buffer, "%-10s", ALU_Commands[ (op & 0x3c000000) >> 26] );
1181   my_buffer += strlen( my_buffer );
1182
1183   /* X-Bus */
1184   data[0] = (op & 0x700000) >> 20;
1185   if ( op & 0x2000000 )
1186   {
1187      dsp_dasm_prefix( X_Commands[ 4 ], temp_buffer, data );
1188   }
1189   else
1190   {
1191      *temp_buffer = 0;
1192   }
1193   sprintf( my_buffer, "%-10s", temp_buffer );
1194   my_buffer += strlen( my_buffer );
1195
1196   dsp_dasm_prefix( X_Commands[ (op & 0x1800000) >> 23 ], temp_buffer,  data );
1197   sprintf( my_buffer, "%-10s", temp_buffer );
1198   my_buffer += strlen( my_buffer );
1199
1200   /* Y-Bus */
1201   data[0] = (op & 0x1C000 ) >> 14 ;
1202   if ( op & 0x80000 )
1203   {
1204      dsp_dasm_prefix( Y_Commands[4], temp_buffer, data );
1205   }
1206   else
1207   {
1208      *temp_buffer = 0;
1209   }
1210   sprintf( my_buffer, "%-10s", temp_buffer );
1211   my_buffer += strlen( my_buffer );
1212
1213   dsp_dasm_prefix( Y_Commands[ (op & 0x60000) >> 17 ], temp_buffer,  data );
1214   sprintf( my_buffer, "%-10s", temp_buffer );
1215   my_buffer += strlen( my_buffer );
1216
1217   /* D1-Bus */
1218   switch( (op & 0x3000) >> 12 )
1219   {
1220   case 0x1:
1221      data[0] = (op & 0xFF);
1222      data[1] = ((op & 0xF00) >> 8);
1223      break;
1224   case 0x3:
1225      data[0] = (op & 0xF);
1226      data[1] = ((op & 0xF00) >> 8);
1227      break;
1228   };
1229   dsp_dasm_prefix( D1_Commands[ (op & 0x3000) >> 12 ], temp_buffer, data );
1230   sprintf( my_buffer, "%-10s", temp_buffer );
1231}
1232
1233static void dsp_dasm_move_immediate( UINT32 op, char *buffer )
1234{
1235   UINT32 data[3];
1236   if ( (op & 0x2000000) )
1237   {
1238      data[0] = op & 0x7FFFF;
1239      data[1] = (op & 0x3C000000) >> 26;
1240      data[2] = (op & 0x3F80000 ) >> 19;
1241      dsp_dasm_prefix( MVI_Command[1], buffer, data ); /* TODO: bad mem*/
1242   }
1243   else
1244   {
1245      data[0] = op & 0x1FFFFFF;
1246      data[1] = (op & 0x3C000000) >> 26;
1247      dsp_dasm_prefix( MVI_Command[0], buffer, data ); /* TODO: bad mem*/
1248   }
1249}
1250
1251static void dsp_dasm_jump( UINT32 op, char *buffer )
1252{
1253   UINT32 data[2];
1254   if ( op & 0x3F80000 )
1255   {
1256      data[0] = (op & 0x3F80000) >> 19;
1257      data[1] = op & 0xff;
1258      dsp_dasm_prefix( JMP_Command[1], buffer, data );
1259   }
1260   else
1261   {
1262      data[0] = op & 0xff;
1263      dsp_dasm_prefix( JMP_Command[0], buffer, data );
1264   }
1265}
1266
1267static void dsp_dasm_loop( UINT32 op, char* buffer )
1268{
1269   if ( op & 0x8000000 )
1270   {
1271      strcpy( buffer, "LPS" );
1272   }
1273   else
1274   {
1275      strcpy( buffer, "BTM" );
1276   }
1277}
1278
1279static void dsp_dasm_end( UINT32 op, char* buffer )
1280{
1281   if ( op & 0x8000000 )
1282   {
1283      strcpy( buffer, "ENDI" );
1284   }
1285   else
1286   {
1287      strcpy( buffer, "END" );
1288   }
1289}
1290
1291static void dsp_dasm_dma( UINT32 op, char* buffer )
1292{
1293   UINT32 data[4];
1294   data[0] = (op &  0x4000) >> 14; /* H */
1295   data[1] = (op & 0x38000) >> 15; /* A */
1296   data[2] = (op & 0x700) >> 8; /* Mem */
1297   data[3] = (op & 0xff);
1298   dsp_dasm_prefix( DMA_Command[(op & 0x3000) >> 12], buffer, data );
1299}
1300
1301static void dsp_dasm_opcode( UINT32 op, char *buffer )
1302{
1303   switch( (op & 0xc0000000) >> 30 )
1304   {
1305   case 0x00: /* 00 */
1306      dsp_dasm_operation( op, buffer );
1307      break;
1308   case 0x01: /* 01 */
1309      strcpy( buffer, "???"  );
1310      break;
1311   case 0x02: /* 10 */
1312      dsp_dasm_move_immediate( op, buffer );
1313      break;
1314   case 0x03: /* 11 */
1315      switch( (op & 0x30000000) >> 28 )
1316      {
1317         case 0x00:
1318            dsp_dasm_dma( op, buffer );
1319            break;
1320         case 0x01:
1321            dsp_dasm_jump( op, buffer );
1322            break;
1323         case 0x02:
1324            dsp_dasm_loop( op, buffer );
1325            break;
1326         case 0x03:
1327            dsp_dasm_end( op, buffer );
1328            break;
1329      }
1330      break;
1331   }
1332}
trunk/src/mame/machine/scudsp.h
r20946r20947
1/*SCU DSP stuff*/
2
3void dsp_prg_ctrl_w(address_space &space, UINT32 data);
4void dsp_prg_data(UINT32 data);
5void dsp_ram_addr_ctrl(UINT32 data);
6void dsp_ram_addr_w(UINT32 data);
7UINT32 dsp_prg_ctrl_r(address_space &space);
8UINT32 dsp_ram_addr_r(void);
9void dsp_execute_program(address_space &dmaspace);
trunk/src/mame/machine/stvcd.c
r20946r20947
1/***************************************************************************
2
3  machine/stvcd.c - Sega Saturn and ST-V CD-ROM handling
4
5  Another tilt at the windmill in 2011 by R. Belmont.
6
7  Status: All known discs at least load their executable, and many load
8          some data files successfully, but there are other problems.
9
10  Information sources:
11  - Tyranid's document
12  - A commented disassembly I made of the Saturn BIOS's CD code
13  - Yabuse's cs2.c
14  - The ISO/IEC "Yellow Book" CD-ROM standard, 1995 version
15
16  Address is mostly in terms of FAD (Frame ADdress).
17  FAD is absolute number of frames from the start of the disc.
18  In other words, FAD = LBA + 150; FAD is the same units as
19  LBA except it counts starting at absolute zero instead of
20  the first sector (00:02:00 in MSF format).
21
22***************************************************************************/
23
24#include "emu.h"
25#include "imagedev/chd_cd.h"
26#include "includes/stv.h"
27#include "cdrom.h"
28#include "sound/cdda.h"
29#include "debugger.h"
30#include "coreutil.h"
31
32// super-verbose
33#if 0
34#define CDROM_LOG(x) printf x;
35#else
36#define CDROM_LOG(x)
37#endif
38
39// HIRQ definitions
40#define CMOK 0x0001 // command dispatch possible
41#define DRDY 0x0002 // data transfer preparations complete
42#define CSCT 0x0004 // finished reading 1 sector
43#define BFUL 0x0008 // CD buffer full
44#define PEND 0x0010 // CD playback completed
45#define DCHG 0x0020 // disc change / tray open
46#define ESEL 0x0040 // selector settings processing complete
47#define EHST 0x0080 // host input/output processing complete
48#define ECPY 0x0100 // duplication/move processing complete
49#define EFLS 0x0200 // file system processing complete
50#define SCDQ 0x0400 // subcode Q update completed
51#define MPED 0x0800 // MPEG-related processing complete
52#define MPCM 0x1000 // MPEG action uncertain
53#define MPST 0x2000 // MPEG interrupt status report
54
55// CD status (hi byte of CR1) definitions:
56// (these defines are shifted up 8)
57#define CD_STAT_BUSY     0x0000     // status change in progress
58#define CD_STAT_PAUSE    0x0100     // CD block paused (temporary stop)
59#define CD_STAT_STANDBY  0x0200     // CD drive stopped
60#define CD_STAT_PLAY     0x0300     // CD play in progress
61#define CD_STAT_SEEK     0x0400     // drive seeking
62#define CD_STAT_SCAN     0x0500     // drive scanning
63#define CD_STAT_OPEN     0x0600     // tray is open
64#define CD_STAT_NODISC   0x0700     // no disc present
65#define CD_STAT_RETRY    0x0800     // read retry in progress
66#define CD_STAT_ERROR    0x0900     // read data error occurred
67#define CD_STAT_FATAL    0x0a00     // fatal error (hard reset required)
68#define CD_STAT_PERI     0x2000     // periodic response if set, else command response
69#define CD_STAT_TRANS    0x4000     // data transfer request if set
70#define CD_STAT_WAIT     0x8000     // waiting for command if set, else executed immediately
71#define CD_STAT_REJECT   0xff00     // ultra-fatal error.
72
73/* FIXME: assume Saturn CD-ROMs to have a 2 secs pre-gap for now. */
74int saturn_state::get_track_index(void)
75{
76   UINT32 rel_fad;
77   UINT8 track;
78
79   if(cdrom_get_track_type(cdrom, cdrom_get_track(cdrom, cd_curfad)) != CD_TRACK_AUDIO)
80      return 1;
81
82   track = cdrom_get_track( cdrom, cd_curfad );
83
84   rel_fad = cd_curfad - cdrom_get_track_start( cdrom, track );
85
86   if(rel_fad < 150)
87      return 0;
88
89   return 1;
90}
91
92void saturn_state::cr_standard_return(UINT16 cur_status)
93{
94   cr1 = cur_status | (playtype << 7) | 0x00 | (cdda_repeat_count & 0xf); //options << 4 | repeat & 0xf
95   cr2 = (cur_track == 0xff) ? 0xffff : (cdrom_get_adr_control(cdrom, cur_track)<<8 | cur_track); // TODO: fix current track
96   cr3 = (get_track_index()<<8) | (cd_curfad>>16); //index & 0xff00
97   cr4 = cd_curfad;
98   cd_stat |= CD_STAT_PERI;
99}
100
101void saturn_state::cd_exec_command( void )
102{
103   UINT32 temp;
104
105   if(cr1 != 0 &&
106      ((cr1 & 0xff00) != 0x5100) &&
107      ((cr1 & 0xff00) != 0x5200) &&
108      ((cr1 & 0xff00) != 0x5300) &&
109      1)
110      printf("CD: command exec %04x %04x %04x %04x %04x (stat %04x)\n", hirqreg, cr1, cr2, cr3, cr4, cd_stat);
111
112   switch (cr1 & 0xff00)
113   {
114      case 0x0000:
115         //CDROM_LOG(("%s:CD: Get Status\n", machine.describe_context()))
116         hirqreg |= CMOK;
117         cr_standard_return(cd_stat);
118         //CDROM_LOG(("   = %04x %04x %04x %04x %04x\n", hirqreg, cr1, cr2, cr3, cr4))
119         break;
120
121      case 0x0100:
122         CDROM_LOG(("%s:CD: Get Hardware Info\n", machine.describe_context()))
123         hirqreg |= CMOK;
124         cr1 = cd_stat;
125         cr2 = 0x0201;
126         cr3 = 0x0000;
127         cr4 = 0x0400;
128         break;
129
130      case 0x0200:    // Get TOC
131         CDROM_LOG(("%s:CD: Get TOC\n", machine.describe_context()))
132         cd_readTOC();
133         cd_stat = CD_STAT_TRANS|CD_STAT_PAUSE;
134         cr1 = cd_stat;
135         cr2 = 102*2;    // TOC length in words (102 entries @ 2 words/4bytes each)
136         cr3 = 0;
137         cr4 = 0;
138         xferdnum = 0;
139         hirqreg |= (CMOK|DRDY);
140         break;
141
142      case 0x0300:    // get session info (lower byte = session # to get?)
143                  // bios is interested in returns in cr3 and cr4
144                  // cr3 should be data track #
145                  // cr4 must be > 1 and < 100 or bios gets angry.
146         CDROM_LOG(("%s:CD: Get Session Info\n", machine.describe_context()))
147         cd_readTOC();
148         switch (cr1 & 0xff)
149         {
150            case 0: // get total session info / disc end
151               cd_stat = CD_STAT_PAUSE;
152               cr1 = cd_stat;
153               cr2 = 0;
154               cr3 = 0x0100 | tocbuf[(101*4)+1];
155               cr4 = tocbuf[(101*4)+2]<<8 | tocbuf[(101*4)+3];
156               break;
157
158            case 1: // get total session info / disc start
159               cd_stat = CD_STAT_PAUSE;
160               cr1 = cd_stat;
161               cr2 = 0;
162               cr3 = 0x0100;   // sessions in high byte, session start in lower
163               cr4 = 0;
164               break;
165
166            default:
167               mame_printf_error("CD: Unknown request to Get Session Info %x\n", cr1 & 0xff);
168               cr1 = cd_stat;
169               cr2 = 0;
170               cr3 = 0;
171               cr4 = 0;
172               break;
173         }
174
175         hirqreg |= (CMOK);
176         break;
177
178      /* TODO: double check this */
179      case 0x0400:    // initialize CD system
180            // CR1 & 1 = reset software
181            // CR1 & 2 = decode RW subcode
182            // CR1 & 4 = don't confirm mode 2 subheader
183            // CR1 & 8 = retry reading mode 2 sectors
184            // CR1 & 10 = force single-speed
185            // CR1 & 80 = no change flag (done by Assault Suit Leynos 2)
186         CDROM_LOG(("%s:CD: Initialize CD system\n", machine.describe_context()))
187         if((cr1 & 0x81) == 0x00) //guess
188         {
189            if(((cd_stat & 0x0f00) != CD_STAT_NODISC) && ((cd_stat & 0x0f00) != CD_STAT_OPEN))
190            {
191               cd_stat = CD_STAT_PAUSE;
192               cd_curfad = 150;
193               //cur_track = 1;
194               fadstoplay = 0;
195            }
196            in_buffer = 0;
197            buffull = 0;
198            hirqreg &= 0xffe5;
199            cd_speed = (cr1 & 0x10) ? 1 : 2;
200
201            /* reset filter connections */
202            /* Guess: X-Men COTA sequence is 0x48->0x48->0x04(01)->0x04(00)->0x30 then 0x10, without this game throws a FAD reject error */
203            /* X-Men vs. SF is even fussier, sequence is  0x04 (1) 0x04 (0) 0x03 (0) 0x03 (1) 0x30 */
204            #if 0
205            for(i=0;i<MAX_FILTERS;i++)
206            {
207               filters[i].fad = 0;
208               filters[i].range = 0xffffffff;
209               filters[i].mode = 0;
210               filters[i].chan = 0;
211               filters[i].smmask = 0;
212               filters[i].cimask = 0;
213               filters[i].fid = 0;
214               filters[i].smval = 0;
215               filters[i].cival = 0;
216            }
217            #endif
218
219            /* reset CD device connection */
220            //cddevice = (filterT *)NULL;
221         }
222
223         hirqreg |= (CMOK|ESEL);
224         cr_standard_return(cd_stat);
225         break;
226
227      case 0x0600:    // end data transfer (TODO: needs to be worked on!)
228            // returns # of bytes transfered (24 bits) in
229            // low byte of cr1 (MSB) and cr2 (middle byte, LSB)
230         CDROM_LOG(("%s:CD: End data transfer (%d bytes xfer'd)\n", machine.describe_context(), xferdnum))
231
232         // clear the "transfer" flag
233         cd_stat &= ~CD_STAT_TRANS;
234
235         if (xferdnum)
236         {
237            cr1 = (cd_stat) | ((xferdnum>>17) & 0xff);
238            cr2 = (xferdnum>>1)&0xffff;
239            cr3 = 0;
240            cr4 = 0;
241         }
242         else
243         {
244            printf("No xferdnum error\n");
245            cr1 = (cd_stat) | (0xff);   // is this right?
246            cr2 = 0xffff;
247            cr3 = 0;
248            cr4 = 0;
249         }
250
251         // try to clean up any transfers still in progress
252         switch (xfertype32)
253         {
254            case XFERTYPE32_GETSECTOR:
255               hirqreg |= EHST;
256               break;
257
258            case XFERTYPE32_GETDELETESECTOR:
259               if (transpart->size > 0)
260               {
261                  INT32 i;
262
263                  xfertype32 = XFERTYPE32_INVALID;
264
265                  // deallocate the blocks
266                  for (i = xfersectpos; i < xfersectpos+xfersectnum; i++)
267                  {
268                     cd_free_block(transpart->blocks[i]);
269                     transpart->blocks[i] = (blockT *)NULL;
270                     transpart->bnum[i] = 0xff;
271                  }
272
273                  // defrag what's left
274                  cd_defragblocks(transpart);
275
276                  // clean up our state
277                  transpart->size -= xferdnum;
278                  transpart->numblks -= xfersectnum;
279
280                  if (freeblocks == 200)
281                  {
282                     sectorstore = 0;
283                  }
284
285                  hirqreg |= EHST;
286               }
287               break;
288
289            default:
290               break;
291         }
292
293
294         xferdnum = 0;
295         hirqreg |= CMOK;
296
297         CDROM_LOG(("   = %04x %04x %04x %04x %04x\n", hirqreg, cr1, cr2, cr3, cr4))
298         break;
299
300      case 0x1000: // Play Disc.  FAD is in lowest 7 bits of cr1 and all of cr2.
301         UINT32 start_pos,end_pos;
302         UINT8 play_mode;
303
304         CDROM_LOG(("%s:CD: Play Disc\n",   machine.describe_context()))
305         cd_stat = CD_STAT_PLAY;
306
307         play_mode = (cr3 >> 8) & 0x7f;
308
309         if (!(cr3 & 0x8000))    // preserve current position if bit 7 set
310         {
311            start_pos = ((cr1&0xff)<<16) | cr2;
312            end_pos = ((cr3&0xff)<<16) | cr4;
313
314            if (start_pos & 0x800000)
315            {
316               if (start_pos != 0xffffff)
317                  cd_curfad = start_pos & 0xfffff;
318
319               printf("fad mode\n");
320               cur_track = cdrom_get_track(cdrom, cd_curfad-150);
321            }
322            else
323            {
324               // track mode
325               if(((start_pos)>>8) != 0)
326               {
327                  cur_track = (start_pos)>>8;
328                  cd_curfad = cdrom_get_track_start(cdrom, cur_track-1);
329               }
330               else
331               {
332                  /* TODO: Waku Waku 7 sets up track 0, that basically doesn't make any sense. Just skip it for now. */
333                  popmessage("Warning: track mode == 0, contact MAMEdev");
334                  cr_standard_return(cd_stat);
335                  hirqreg |= (CMOK);
336                  return;
337               }
338
339               printf("track mode %d\n",cur_track);
340
341            }
342
343            if (end_pos & 0x800000)
344            {
345               if (end_pos != 0xffffff)
346                  fadstoplay = end_pos & 0xfffff;
347            }
348            else
349            {
350               UINT8 end_track;
351
352               end_track = (end_pos)>>8;
353               fadstoplay = cdrom_get_track_start(cdrom, end_track) - cd_curfad;
354            }
355         }
356         else    // play until the end of the disc
357         {
358            start_pos = ((cr1&0xff)<<16) | cr2;
359            end_pos = ((cr3&0xff)<<16) | cr4;
360
361            if(start_pos != 0xffffff)
362            {
363               /* Madou Monogatari sets 0xff80xxxx as end position, needs investigation ... */
364               if(end_pos & 0x800000)
365                  fadstoplay = end_pos & 0xfffff;
366               else
367               {
368                  if(end_pos == 0)
369                     fadstoplay = (cdrom_get_track_start(cdrom, 0xaa)) - cd_curfad;
370                  else
371                     fadstoplay = (cdrom_get_track_start(cdrom, (end_pos & 0xff00) >> 8)) - cd_curfad;
372               }
373               printf("track mode %08x %08x\n",cd_curfad,fadstoplay);
374            }
375            else
376            {
377               /* resume from a pause state */
378               /* TODO: Galaxy Fight calls 10ff ffff ffff ffff, but then it calls 0x04->0x02->0x06->0x11->0x04->0x02->0x06 command sequence
379                  (and current implementation nukes start/end FAD addresses at 0x04). I'm sure that this doesn't work like this, but there could
380                  be countless possible combinations ... */
381               if(fadstoplay == 0)
382               {
383                  cd_curfad = cdrom_get_track_start(cdrom, cur_track-1);
384                  fadstoplay = cdrom_get_track_start(cdrom, cur_track) - cd_curfad;
385               }
386               printf("track resume %08x %08x\n",cd_curfad,fadstoplay);
387            }
388         }
389
390         CDROM_LOG(("CD: Play Disc: start %x length %x\n", cd_curfad, fadstoplay))
391
392         cr_standard_return(cd_stat);
393         hirqreg |= (CMOK);
394         oddframe = 0;
395         in_buffer = 0;
396
397         playtype = 0;
398
399         // cdda
400         if(cdrom_get_track_type(cdrom, cdrom_get_track(cdrom, cd_curfad)) == CD_TRACK_AUDIO)
401         {
402            cdda_pause_audio( machine().device( "cdda" ), 0 );
403            //cdda_start_audio( machine.device( "cdda" ), cd_curfad, fadstoplay  );
404            //cdda_repeat_count = 0;
405         }
406
407         if(play_mode != 0x7f)
408            cdda_maxrepeat = play_mode & 0xf;
409         else
410            cdda_maxrepeat = 0;
411
412         cdda_repeat_count = 0;
413
414         break;
415
416      case 0x1100: // disc seek
417         CDROM_LOG(("%s:CD: Disc seek\n",   machine.describe_context()))
418         //printf("%08x %08x %08x %08x\n",cr1,cr2,cr3,cr4);
419         if (cr1 & 0x80)
420         {
421            temp = (cr1&0xff)<<16;  // get FAD to seek to
422            temp |= cr2;
423
424            //cd_curfad = temp;
425
426            if (temp == 0xffffff)
427            {
428               cd_stat = CD_STAT_PAUSE;
429               cdda_pause_audio( machine().device( "cdda" ), 1 );
430            }
431            else
432            {
433               cd_curfad = ((cr1&0x7f)<<16) | cr2;
434               printf("disc seek with params %04x %04x\n",cr1,cr2); //Area 51 sets this up
435            }
436         }
437         else
438         {
439            // is it a valid track?
440            if (cr2 >> 8)
441            {
442               cd_stat = CD_STAT_PAUSE;
443               cur_track = cr2>>8;;
444               cd_curfad = cdrom_get_track_start(cdrom, cur_track-1);
445               cdda_pause_audio( machine().device( "cdda" ), 1 );
446               // (index is cr2 low byte)
447            }
448            else // error!
449            {
450               cd_stat = CD_STAT_STANDBY;
451               cd_curfad = 0xffffffff;
452               cur_track = 0xff;
453               cdda_stop_audio( machine().device( "cdda" ) ); //stop any pending CD-DA
454            }
455         }
456
457
458         hirqreg |= CMOK;
459         cr_standard_return(cd_stat);
460         break;
461
462      case 0x1200: // FFWD / REW
463         //cr1 bit 0 determines if this is a Fast Forward (0) or a Rewind (1) command
464         // ...
465         break;
466
467      case 0x2000: // Get SubCode Q / RW Channel
468         switch(cr1 & 0xff)
469         {
470            case 0: // Get Q
471            {
472               UINT32 msf_abs,msf_rel;
473               UINT8 track;
474               cr1 = cd_stat | 0;
475               cr2 = 10/2;
476               cr3 = 0;
477               cr4 = 0;
478
479               /*
480               Subcode Q info should be:
481               ---- --x- S0
482               ---- ---x S1
483               xxxx ---- [0] Control (bit 7 Pre-emphasis, bit 6: copy permitted, bit 5 undefined, bit 4 number of channels)
484               ---- xxxx [0] address (0x0001 Mode 1)
485               xxxx xxxx [1] track number (1-99, AA lead-out), BCD format
486               xxxx xxxx [2] index (01 lead-out), BCD format
487               xxxx xxxx [3] Time within' track M
488               xxxx xxxx [4] Time within' track S
489               xxxx xxxx [5] Time within' track F
490               xxxx xxxx [6] Zero
491               xxxx xxxx [7] Absolute M
492               xxxx xxxx [8] Absolute S
493               xxxx xxxx [9] Absolute F
494               xxxx xxxx [10] CRCC
495               xxxx xxxx [11] CRCC
496               */
497
498               msf_abs = lba_to_msf_alt( cd_curfad - 150 );
499               track = cdrom_get_track( cdrom, cd_curfad );
500               msf_rel = lba_to_msf_alt( cd_curfad - 150 - cdrom_get_track_start( cdrom, track ) );
501
502               xfertype = XFERTYPE_SUBQ;
503               xfercount = 0;
504               subqbuf[0] = 0x01 | ((cdrom_get_track_type(cdrom, cdrom_get_track(cdrom, track+1)) == CD_TRACK_AUDIO) ? 0x00 : 0x40);
505               subqbuf[1] = dec_2_bcd(track+1);
506               subqbuf[2] = dec_2_bcd(get_track_index());
507               subqbuf[3] = dec_2_bcd((msf_rel >> 16) & 0xff);
508               subqbuf[4] = dec_2_bcd((msf_rel >> 8) & 0xff);
509               subqbuf[5] = dec_2_bcd((msf_rel >> 0) & 0xff);
510               subqbuf[6] = 0;
511               subqbuf[7] = dec_2_bcd((msf_abs >> 16) & 0xff);
512               subqbuf[8] = dec_2_bcd((msf_abs >> 8) & 0xff);
513               subqbuf[9] = dec_2_bcd((msf_abs >> 0) & 0xff);
514            }
515            break;
516
517            case 1: // Get RW
518               cr1 = cd_stat | 0;
519               cr2 = 12;
520               cr3 = 0;
521               cr4 = 0;
522
523               xfertype = XFERTYPE_SUBRW;
524               xfercount = 0;
525
526               /* return null data for now */
527               {
528                  int i;
529
530                  for(i=0;i<12*2;i++)
531                     subrwbuf[i] = 0;
532               }
533               break;
534         }
535         hirqreg |= CMOK|DRDY;
536         break;
537
538      case 0x3000:    // Set CD Device connection
539         {
540            UINT8 parm;
541
542            // get operation
543            parm = cr3>>8;
544
545            CDROM_LOG(("%s:CD: Set CD Device Connection filter # %x\n",   machine.describe_context(), parm))
546
547            cddevicenum = parm;
548
549            if (parm == 0xff)
550            {
551               cddevice = (filterT *)NULL;
552            }
553            else
554            {
555               if (parm < 0x24)
556               {
557                  cddevice = &filters[(cr3>>8)];
558               }
559            }
560
561
562            hirqreg |= (CMOK|ESEL);
563            cr_standard_return(cd_stat);
564         }
565         break;
566
567      case 0x3100:
568         popmessage("Get CD Device Connection, contact MAMEdev");
569         hirqreg |= CMOK;
570         break;
571
572      case 0x3200:    // Last Buffer Destination
573         cr1 = cd_stat | 0;
574         cr2 = 0;
575         cr3 = lastbuf << 8;
576         cr4 = 0;
577         hirqreg |= (CMOK);
578         break;
579
580      case 0x4000:    // Set Filter Range
581                  // cr1 low + cr2 = FAD0, cr3 low + cr4 = FAD1
582                  // cr3 hi = filter num.
583         {
584            UINT8 fnum = (cr3>>8)&0xff;
585
586            CDROM_LOG(("%s:CD: Set Filter Range\n",   machine.describe_context()))
587
588            filters[fnum].fad = ((cr1 & 0xff)<<16) | cr2;
589            filters[fnum].range = ((cr3 & 0xff)<<16) | cr4;
590
591            printf("%08x %08x %d\n",filters[fnum].fad,filters[fnum].range,fnum);
592
593            hirqreg |= (CMOK|ESEL);
594            cr_standard_return(cd_stat);
595         }
596         break;
597
598      case 0x4100:
599         popmessage("Get Filter Range, contact MAMEdev");
600         hirqreg |= CMOK;
601         break;
602
603      case 0x4200:    // Set Filter Subheader conditions
604         {
605            UINT8 fnum = (cr3>>8)&0xff;
606
607            CDROM_LOG(("%s:CD: Set Filter Subheader conditions %x => chan %x masks %x fid %x vals %x\n", machine.describe_context(), fnum, cr1&0xff, cr2, cr3&0xff, cr4))
608
609            filters[fnum].chan = cr1 & 0xff;
610            filters[fnum].smmask = (cr2>>8)&0xff;
611            filters[fnum].cimask = cr2&0xff;
612            filters[fnum].fid = cr3&0xff;
613            filters[fnum].smval = (cr4>>8)&0xff;
614            filters[fnum].cival = cr4&0xff;
615
616            hirqreg |= (CMOK|ESEL);
617            cr_standard_return(cd_stat);
618         }
619         break;
620
621      case 0x4300:    // Get Filter Subheader conditions
622         {
623            UINT8 fnum = (cr3>>8)&0xff;
624
625            CDROM_LOG(("%s:CD: Set Filter Subheader conditions %x => chan %x masks %x fid %x vals %x\n", machine.describe_context(), fnum, cr1&0xff, cr2, cr3&0xff, cr4))
626
627            cr1 = cd_stat | (filters[fnum].chan & 0xff);
628            cr2 = (filters[fnum].smmask << 8) | (filters[fnum].cimask & 0xff);
629            cr3 = filters[fnum].fid;
630            cr4 = (filters[fnum].smval << 8) | (filters[fnum].cival & 0xff);
631
632            hirqreg |= (CMOK|ESEL);
633         }
634         break;
635
636      case 0x4400:    // Set Filter Mode
637         {
638            UINT8 fnum = (cr3>>8)&0xff;
639            UINT8 mode = (cr1 & 0xff);
640
641            // initialize filter?
642            if (mode & 0x80)
643            {
644               memset(&filters[fnum], 0, sizeof(filterT));
645            }
646            else
647            {
648               filters[fnum].mode = mode;
649            }
650
651            CDROM_LOG(("%s:CD: Set Filter Mode filt %x mode %x\n", machine.describe_context(), fnum, mode))
652            hirqreg |= (CMOK|ESEL);
653            cr_standard_return(cd_stat);
654         }
655         break;
656
657      case 0x4500:    // Get Filter Mode
658         {
659            UINT8 fnum = (cr3>>8)&0xff;
660
661            cr1 = cd_stat | (filters[fnum].mode & 0xff);
662            cr2 = 0;
663            cr3 = 0;
664            cr4 = 0;
665            hirqreg |= (CMOK|ESEL);
666         }
667         break;
668
669      case 0x4600:    // Set Filter Connection
670         {
671            UINT8 fnum = (cr3>>8)&0xff;
672
673            CDROM_LOG(("%s:CD: Set Filter Connection %x => mode %x parm %04x\n", machine.describe_context(), fnum, cr1 & 0xf, cr2))
674
675            // set true condition?
676            if (cr1 & 1)
677            {
678               filters[fnum].condtrue = (cr2>>8)&0xff;
679            }
680            else if (cr1 & 2)   // set false condition
681            {
682               filters[fnum].condfalse = cr2&0xff;
683            }
684
685            hirqreg |= (CMOK|ESEL);
686            cr_standard_return(cd_stat);
687         }
688         break;
689
690      case 0x4800:    // Reset Selector
691         {
692         int i,j;
693
694         CDROM_LOG(("%s:CD: Reset Selector\n",   machine.describe_context()))
695
696         if((cr1 & 0xff) == 0x00)
697         {
698            UINT8 bufnum = cr3>>8;
699
700            if(bufnum < MAX_FILTERS)
701            {
702               for (i = 0; i < MAX_BLOCKS; i++)
703               {
704                  cd_free_block(partitions[bufnum].blocks[i]);
705                  partitions[bufnum].blocks[i] = (blockT *)NULL;
706                  partitions[bufnum].bnum[i] = 0xff;
707               }
708
709               partitions[bufnum].size = -1;
710               partitions[bufnum].numblks = 0;
711            }
712
713            // TODO: buffer full flag
714
715            if (freeblocks == 200) { sectorstore = 0; }
716
717            hirqreg |= (CMOK|ESEL);
718            cr_standard_return(cd_stat);
719            return;
720         }
721
722         /* reset false filter output conditions */
723         if(cr1 & 0x80)
724         {
725            for(i=0;i<MAX_FILTERS;i++)
726               filters[i].condfalse = 0xff;
727         }
728
729         /* reset true filter output conditions */
730         if(cr1 & 0x40)
731         {
732            for(i=0;i<MAX_FILTERS;i++)
733               filters[i].condtrue = i;
734         }
735
736         /* reset filter conditions*/
737         if(cr1 & 0x10)
738         {
739            for(i=0;i<MAX_FILTERS;i++)
740            {
741               filters[i].fad = 0;
742               filters[i].range = 0xffffffff;
743               filters[i].mode = 0;
744               filters[i].chan = 0;
745               filters[i].smmask = 0;
746               filters[i].cimask = 0;
747               filters[i].fid = 0;
748               filters[i].smval = 0;
749               filters[i].cival = 0;
750            }
751         }
752
753         /* reset partition buffer data */
754         if(cr1 & 0x4)
755         {
756            for(i=0;i<MAX_FILTERS;i++)
757            {
758               for (j = 0; j < MAX_BLOCKS; j++)
759               {
760                  cd_free_block(partitions[i].blocks[j]);
761                  partitions[i].blocks[j] = (blockT *)NULL;
762                  partitions[i].bnum[j] = 0xff;
763               }
764
765               partitions[i].size = -1;
766               partitions[i].numblks = 0;
767            }
768
769            buffull = sectorstore = 0;
770         }
771
772         hirqreg |= (CMOK|ESEL);
773         cr_standard_return(cd_stat);
774         }
775         break;
776
777      case 0x5000:    // get Buffer Size
778         cr1 = cd_stat;
779         cr2 = (freeblocks > 200) ? 200 : freeblocks;
780         cr3 = 0x1800;
781         cr4 = 200;
782         CDROM_LOG(("CD: Get Buffer Size = %d\n", cr2))
783         hirqreg |= (CMOK);
784         break;
785
786      case 0x5100:    // get # sectors used in a buffer
787         {
788            UINT32 bufnum = cr3>>8;
789
790            CDROM_LOG(("%s:CD: Get Sector Number (bufno %d) = %d blocks\n",   machine.describe_context(), bufnum, cr4))
791            cr1 = cd_stat;
792            cr2 = 0;
793            cr3 = 0;
794
795            // is the partition empty?
796            if (partitions[bufnum].size == -1)
797            {
798               cr4 = 0;
799            }
800            else
801            {
802               cr4 = partitions[bufnum].numblks;
803            }
804
805            hirqreg |= (CMOK|DRDY);
806         }
807         break;
808
809      case 0x5200:    // calculate actual size
810         {
811            UINT32 bufnum = cr3>>8;
812            UINT32 sectoffs = cr2;
813            UINT32 numsect = cr4;
814
815            CDROM_LOG(("%s:CD: Calculate actual size: buf %x offs %x numsect %x\n", machine.describe_context(), bufnum, sectoffs, numsect))
816
817            calcsize = 0;
818            if (partitions[bufnum].size != -1)
819            {
820               INT32 i;
821
822               for (i = 0; i < numsect; i++)
823               {
824                  if (partitions[bufnum].blocks[sectoffs+i])
825                  {
826                     calcsize += (partitions[bufnum].blocks[sectoffs+i]->size / 2);
827                  }
828               }
829            }
830
831            hirqreg |= (CMOK|ESEL);
832            cr_standard_return(cd_stat);
833         }
834         break;
835
836      case 0x5300:    // get actual block size
837         CDROM_LOG(("%s:CD: Get actual block size\n", machine.describe_context()))
838         hirqreg |= (CMOK|ESEL);
839         cr1 = cd_stat | ((calcsize>>16)&0xff);
840         cr2 = (calcsize & 0xffff);
841         cr3 = 0;
842         cr4 = 0;
843         break;
844
845      case 0x5400:    // get sector info
846         {
847            UINT32 sectoffs = cr2 & 0xff;
848            UINT32 bufnum = cr3>>8;
849
850            if (bufnum >= MAX_FILTERS || !partitions[bufnum].blocks[sectoffs])
851            {
852               cr1 |= CD_STAT_REJECT & 0xff00;
853               hirqreg |= (CMOK|ESEL);
854               printf("Get sector info reject\n");
855            }
856            else
857            {
858               cr1 = cd_stat | ((partitions[bufnum].blocks[sectoffs]->FAD >> 16) & 0xff);
859               cr2 = partitions[bufnum].blocks[sectoffs]->FAD & 0xffff;
860               cr3 = ((partitions[bufnum].blocks[sectoffs]->fnum & 0xff) << 8) | (partitions[bufnum].blocks[sectoffs]->chan & 0xff);
861               cr4 = ((partitions[bufnum].blocks[sectoffs]->subm & 0xff) << 8) | (partitions[bufnum].blocks[sectoffs]->cinf & 0xff);
862               hirqreg |= (CMOK|ESEL);
863            }
864         }
865         break;
866
867      case 0x6000:    // set sector length
868         CDROM_LOG(("%s:CD: Set sector length\n",   machine.describe_context()))
869
870         switch (cr1 & 0xff)
871         {
872            case 0:
873               sectlenin = 2048;
874               break;
875            case 1:
876               sectlenin = 2336;
877               break;
878            case 2:
879               sectlenin = 2340;
880               break;
881            case 3:
882               sectlenin = 2352;
883               break;
884         }
885
886         switch ((cr2>>8) & 0xff)
887         {
888            case 0:
889               sectlenout = 2048;
890               break;
891            case 1:
892               sectlenout = 2336;
893               break;
894            case 2:
895               sectlenout = 2340;
896               break;
897            case 3:
898               sectlenout = 2352;
899               break;
900         }
901         hirqreg |= (CMOK|ESEL);
902         cr_standard_return(cd_stat);
903         break;
904
905      case 0x6100:    // get sector data
906         {
907            UINT32 sectnum = cr4;
908            UINT32 sectofs = cr2;
909            UINT32 bufnum = cr3>>8;
910
911            CDROM_LOG(("%s:CD: Get sector data (SN %d SO %d BN %d)\n",   machine.describe_context(), sectnum, sectofs, bufnum))
912
913            if (bufnum >= MAX_FILTERS)
914            {
915               printf("CD: invalid buffer number\n");
916               /* TODO: why this is happening? */
917               cr_standard_return(CD_STAT_REJECT);
918               hirqreg |= (CMOK|EHST);
919               return;
920            }
921
922            if (partitions[bufnum].numblks == 0)
923            {
924               printf("CD: buffer is empty\n");
925               /* TODO: why this is happening? */
926               cr_standard_return(CD_STAT_REJECT);
927               hirqreg |= (CMOK|EHST);
928               return;
929            }
930
931            cd_getsectoroffsetnum(bufnum, &sectofs, &sectnum);
932
933            xfertype32 = XFERTYPE32_GETSECTOR;
934            xferoffs = 0;
935            xfersect = 0;
936            xferdnum = 0;
937            xfersectpos = sectofs;
938            xfersectnum = sectnum;
939            transpart = &partitions[bufnum];
940
941            cd_stat |= CD_STAT_TRANS;
942            cr_standard_return(cd_stat);
943            hirqreg |= (CMOK|EHST|DRDY);
944         }
945         break;
946
947      case 0x6200:    // delete sector data
948         {
949            UINT32 sectnum = cr4;
950            UINT32 sectofs = cr2;
951            UINT32 bufnum = cr3>>8;
952            INT32 i;
953
954            CDROM_LOG(("%s:CD: Delete sector data (SN %d SO %d BN %d)\n",   machine.describe_context(), sectnum, sectofs, bufnum))
955
956            if (bufnum >= MAX_FILTERS)
957            {
958               printf("CD: invalid buffer number\n");
959               /* TODO: why this is happening? */
960               cr_standard_return(CD_STAT_REJECT);
961               hirqreg |= (CMOK|EHST);
962               return;
963            }
964
965            if (partitions[bufnum].numblks == 0)
966            {
967               printf("CD: buffer is empty\n");
968               /* TODO: why this is happening? */
969               cr_standard_return(CD_STAT_REJECT);
970               hirqreg |= (CMOK|EHST);
971               return;
972            }
973
974            cd_getsectoroffsetnum(bufnum, &sectofs, &sectnum);
975
976            for (i = sectofs; i < (sectofs + sectnum); i++)
977            {
978               partitions[bufnum].size -= partitions[bufnum].blocks[i]->size;
979               cd_free_block(partitions[bufnum].blocks[i]);
980               partitions[bufnum].blocks[i] = (blockT *)NULL;
981               partitions[bufnum].bnum[i] = 0xff;
982            }
983
984            cd_defragblocks(&partitions[bufnum]);
985
986            partitions[bufnum].numblks -= sectnum;
987
988            if (freeblocks == 200)
989            {
990               sectorstore = 0;
991            }
992
993            cd_stat &= ~CD_STAT_TRANS;
994            cr_standard_return(cd_stat);
995            hirqreg |= (CMOK|EHST);
996         }
997         break;
998
999      case 0x6300:    // get then delete sector data
1000         {
1001            UINT32 sectnum = cr4;
1002            UINT32 sectofs = cr2;
1003            UINT32 bufnum = cr3>>8;
1004
1005            CDROM_LOG(("%s:CD: Get and delete sector data (SN %d SO %d BN %d)\n",   machine.describe_context(), sectnum, sectofs, bufnum))
1006
1007            if (bufnum >= MAX_FILTERS)
1008            {
1009               printf("CD: invalid buffer number\n");
1010               /* TODO: why this is happening? */
1011               cr_standard_return(CD_STAT_REJECT);
1012               hirqreg |= (CMOK|EHST);
1013               return;
1014            }
1015
1016            if (partitions[bufnum].numblks == 0)
1017            {
1018               printf("CD: buffer is empty\n");
1019               /* TODO: why this is happening? */
1020               cr_standard_return(CD_STAT_REJECT);
1021               hirqreg |= (CMOK|EHST);
1022               return;
1023            }
1024
1025            cd_getsectoroffsetnum(bufnum, &sectofs, &sectnum);
1026
1027            xfertype32 = XFERTYPE32_GETDELETESECTOR;
1028            xferoffs = 0;
1029            xfersect = 0;
1030            xferdnum = 0;
1031            xfersectpos = sectofs;
1032            xfersectnum = sectnum;
1033            transpart = &partitions[bufnum];
1034
1035            cd_stat |= CD_STAT_TRANS;
1036            cr_standard_return(cd_stat);
1037            hirqreg |= (CMOK|EHST|DRDY);
1038         }
1039         break;
1040
1041      case 0x6400:    // put sector data
1042         /* TODO: After Burner 2, Out Run, Fantasy Zone and Dungeon Master Nexus trips this */
1043         // ...
1044         {
1045            //UINT8 sectnum = cr4 & 0xff;
1046            //UINT8 filtnum = cr3>>8;
1047
1048
1049         }
1050
1051         hirqreg |= (CMOK|EHST);
1052         cr_standard_return(cd_stat);
1053         break;
1054
1055      case 0x6500:
1056         popmessage("Copy Sector data, contact MAMEdev");
1057         hirqreg |= (CMOK);
1058         break;
1059
1060      case 0x6600:    // move sector data
1061         /* TODO: Sword & Sorcery / Riglord Saga 2 */
1062         {
1063            //UINT8 src_filter = (cr3>>8)&0xff;
1064            //UINT8 dst_filter = cr4;
1065         }
1066
1067         hirqreg |= (CMOK|ECPY);
1068         cr_standard_return(cd_stat);
1069         break;
1070
1071
1072      case 0x6700:    // get copy error
1073         CDROM_LOG(("%s:CD: Get copy error\n",   machine.describe_context()))
1074         printf("Get copy error\n");
1075         cr1 = cd_stat;
1076         cr2 = 0;
1077         cr3 = 0;
1078         cr4 = 0;
1079         hirqreg |= (CMOK);
1080         break;
1081
1082      case 0x7000:    // change directory
1083         CDROM_LOG(("%s:CD: Change Directory\n",   machine.describe_context()))
1084         hirqreg |= (CMOK|EFLS);
1085
1086         temp = (cr3&0xff)<<16;
1087         temp |= cr4;
1088
1089         read_new_dir(temp);
1090         cr_standard_return(cd_stat);
1091         break;
1092
1093      case 0x7100:    // Read directory entry
1094         CDROM_LOG(("%s:CD: Read Directory Entry\n",   machine.describe_context()))
1095//          UINT32 read_dir;
1096
1097//          read_dir = ((cr3&0xff)<<16)|cr4;
1098
1099         if((cr3 >> 8) < 0x24)
1100            cddevice = &filters[cr3 >> 8];
1101         else
1102            cddevice = (filterT *)NULL;
1103
1104         /* TODO:  */
1105         //read_new_dir(read_dir - 2);
1106
1107         cr_standard_return(cd_stat);
1108         hirqreg |= (CMOK|EFLS);
1109         break;
1110
1111      case 0x7200:    // Get file system scope
1112         CDROM_LOG(("CD: Get file system scope\n"))
1113         hirqreg |= (CMOK|EFLS);
1114         cr1 = cd_stat;
1115         cr2 = numfiles; // # of files in directory
1116         cr3 = 0x0100;   // report directory held
1117         cr4 = firstfile;    // first file id
1118         printf("%04x %04x %04x %04x\n",cr1,cr2,cr3,cr4);
1119         break;
1120
1121      case 0x7300:    // Get File Info
1122         CDROM_LOG(("%s:CD: Get File Info\n",   machine.describe_context()))
1123         cd_stat |= CD_STAT_TRANS;
1124         cd_stat &= 0xff00;      // clear top byte of return value
1125         playtype = 0;
1126         cdda_repeat_count = 0;
1127         hirqreg |= (CMOK|DRDY);
1128
1129         temp = (cr3&0xff)<<16;
1130         temp |= cr4;
1131
1132         if (temp == 0xffffff)   // special
1133         {
1134            xfertype = XFERTYPE_FILEINFO_254;
1135            xfercount = 0;
1136
1137            cr1 = cd_stat;
1138            cr2 = 0x5f4;
1139            cr3 = 0;
1140            cr4 = 0;
1141         }
1142         else
1143         {
1144            cr1 = cd_stat;
1145            cr2 = 6;    // 6 words for single file
1146                     // first 4 bytes = FAD address
1147                     // second 4 bytes = length
1148                     // last 4 bytes:
1149                     // - unit size
1150                     // - gap size
1151                     // - file #
1152                     // attributes flags
1153
1154            cr3 = 0;
1155            cr4 = 0;
1156
1157            printf("%08x %08x\n",curdir[temp].firstfad,curdir[temp].length);
1158            // first 4 bytes = FAD
1159            finfbuf[0] = (curdir[temp].firstfad>>24)&0xff;
1160            finfbuf[1] = (curdir[temp].firstfad>>16)&0xff;
1161            finfbuf[2] = (curdir[temp].firstfad>>8)&0xff;
1162            finfbuf[3] = (curdir[temp].firstfad&0xff);
1163            // second 4 bytes = length of file
1164            finfbuf[4] = (curdir[temp].length>>24)&0xff;
1165            finfbuf[5] = (curdir[temp].length>>16)&0xff;
1166            finfbuf[6] = (curdir[temp].length>>8)&0xff;
1167            finfbuf[7] = (curdir[temp].length&0xff);
1168            finfbuf[8] = curdir[temp].interleave_gap_size;
1169            finfbuf[9] = curdir[temp].file_unit_size;
1170            finfbuf[10] = temp;
1171            finfbuf[11] = curdir[temp].flags;
1172
1173            xfertype = XFERTYPE_FILEINFO_1;
1174            xfercount = 0;
1175         }
1176         CDROM_LOG(("   = %04x %04x %04x %04x %04x\n", hirqreg, cr1, cr2, cr3, cr4))
1177         break;
1178
1179      case 0x7400:    // Read File
1180         CDROM_LOG(("%s:CD: Read File\n",   machine.describe_context()))
1181         UINT16 file_offset,file_filter,file_id,file_size;
1182
1183         file_offset = ((cr1 & 0xff)<<8)|(cr2 & 0xff); /* correct? */
1184         file_filter = cr3 >> 8;
1185         file_id = ((cr3 & 0xff) << 16)|(cr4);
1186         file_size = ((curdir[file_id].length + sectlenin - 1) / sectlenin) - file_offset;
1187
1188         cd_stat = CD_STAT_PLAY|0x80;    // set "cd-rom" bit
1189         cd_curfad = (curdir[file_id].firstfad + file_offset);
1190         fadstoplay = file_size;
1191         if(file_filter < 0x24)
1192            cddevice = &filters[file_filter];
1193         else
1194            cddevice = (filterT *)NULL;
1195
1196         printf("Read file %08x (%08x %08x) %02x %d\n",curdir[file_id].firstfad,cd_curfad,fadstoplay,file_filter,sectlenin);
1197
1198         cr_standard_return(cd_stat);
1199
1200         oddframe = 0;
1201         in_buffer = 0;
1202
1203         playtype = 1;
1204
1205         hirqreg |= (CMOK|EHST);
1206
1207         break;
1208
1209      case 0x7500:
1210         CDROM_LOG(("%s:CD: Abort File\n",   machine.describe_context()))
1211         // bios expects "2bc" mask to work against this
1212         hirqreg |= (CMOK|EFLS);
1213         sectorstore = 0;
1214         xfertype32 = XFERTYPE32_INVALID;
1215         xferdnum = 0;
1216         if(((cd_stat & 0x0f00) != CD_STAT_NODISC) && ((cd_stat & 0x0f00) != CD_STAT_OPEN))
1217            cd_stat = CD_STAT_PAUSE;    // force to pause
1218         cr_standard_return(cd_stat);
1219         break;
1220
1221      case 0xe000:    // appears to be copy protection check.  needs only to return OK.
1222         CDROM_LOG(("%s:CD: Verify copy protection\n",   machine.describe_context()))
1223         if(((cd_stat & 0x0f00) != CD_STAT_NODISC) && ((cd_stat & 0x0f00) != CD_STAT_OPEN))
1224            cd_stat = CD_STAT_PAUSE;
1225//          cr1 = cd_stat;  // necessary to pass
1226//          cr2 = 0x4;
1227//          hirqreg |= (CMOK|EFLS|CSCT);
1228         sectorstore = 1;
1229         hirqreg = 0xfc5;
1230         cr_standard_return(cd_stat);
1231         break;
1232
1233      case 0xe100:    // get disc region
1234         CDROM_LOG(("%s:CD: Get disc region\n",   machine.describe_context()))
1235         if(cd_stat != CD_STAT_NODISC && cd_stat != CD_STAT_OPEN)
1236            cd_stat = CD_STAT_PAUSE;
1237         cr1 = cd_stat;  // necessary to pass
1238         cr2 = 0x4;      // (must return this value to pass bios checks)
1239         cr3 = 0;
1240         cr4 = 0;
1241         hirqreg |= (CMOK);
1242//          cr_standard_return(cd_stat);
1243         break;
1244
1245      default:
1246         CDROM_LOG(("CD: Unknown command %04x\n", cr1))
1247         hirqreg |= (CMOK);
1248         break;
1249   }
1250}
1251
1252TIMER_DEVICE_CALLBACK_MEMBER( saturn_state::stv_sh1_sim )
1253{
1254   sh1_timer->adjust(attotime::from_hz(16667));
1255
1256   if((cmd_pending == 0xf) && (!(hirqreg & CMOK)))
1257   {
1258      cd_exec_command();
1259      return;
1260   }
1261
1262   /* TODO: doesn't boot if a disk isn't in? */
1263   /* TODO: Check out when this really happens. (Daytona USA original version definitely wants it to be on).*/
1264   //if(((cd_stat & 0x0f00) != CD_STAT_NODISC) && ((cd_stat & 0x0f00) != CD_STAT_OPEN))
1265      hirqreg |= SCDQ;
1266
1267   if(cd_stat & CD_STAT_PERI)
1268   {
1269      cr_standard_return(cd_stat);
1270   }
1271}
1272
1273TIMER_DEVICE_CALLBACK_MEMBER( saturn_state::stv_sector_cb )
1274{
1275   //sector_timer->reset();
1276
1277   //popmessage("%08x %08x %d %d",cd_curfad,fadstoplay,cmd_pending,cd_speed);
1278
1279   cd_playdata();
1280
1281   if(cdrom_get_track_type(cdrom, cdrom_get_track(cdrom, cd_curfad)) == CD_TRACK_AUDIO)
1282      sector_timer->adjust(attotime::from_hz(75));    // 75 sectors / second = 150kBytes/second (cdda track ignores cd_speed setting)
1283   else
1284      sector_timer->adjust(attotime::from_hz(75*cd_speed));   // 75 / 150 sectors / second = 150 / 300kBytes/second
1285}
1286
1287// global functions
1288void saturn_state::stvcd_reset( void )
1289{
1290   INT32 i, j;
1291
1292   hirqmask = 0xffff;
1293   hirqreg = 0xffff;
1294   cr1 = 'C';
1295   cr2 = ('D'<<8) | 'B';
1296   cr3 = ('L'<<8) | 'O';
1297   cr4 = ('C'<<8) | 'K';
1298   cd_stat = CD_STAT_PAUSE;
1299   cd_stat |= CD_STAT_PERI;
1300   cur_track = 0xff;
1301
1302   if (curdir != (direntryT *)NULL)
1303      auto_free(machine(), curdir);
1304   curdir = (direntryT *)NULL;     // no directory yet
1305
1306   xfertype = XFERTYPE_INVALID;
1307   xfertype32 = XFERTYPE32_INVALID;
1308
1309   // reset flag vars
1310   buffull = sectorstore = 0;
1311
1312   freeblocks = 200;
1313
1314   sectlenin = sectlenout = 2048;
1315
1316   lastbuf = 0xff;
1317
1318   // reset buffer partitions
1319   for (i = 0; i < MAX_FILTERS; i++)
1320   {
1321      partitions[i].size = -1;
1322      partitions[i].numblks = 0;
1323
1324      for (j = 0; j < MAX_BLOCKS; j++)
1325      {
1326         partitions[i].blocks[j] = (blockT *)NULL;
1327         partitions[i].bnum[j] = 0xff;
1328      }
1329   }
1330
1331   // reset blocks
1332   for (i = 0; i < MAX_BLOCKS; i++)
1333   {
1334      blocks[i].size = -1;
1335      memset(&blocks[i].data, 0, CD_MAX_SECTOR_DATA);
1336   }
1337
1338   // open device
1339   if (cdrom)
1340   {
1341      cdrom_close(cdrom);
1342      cdrom = (cdrom_file *)NULL;
1343   }
1344
1345   cdrom_image_device *cddevice = machine().device<cdrom_image_device>("cdrom");
1346   if (cddevice!=NULL)
1347   {
1348      // MESS case
1349      cdrom = cddevice->get_cdrom_file();
1350   }
1351   else
1352   {
1353      // MAME case
1354      cdrom = cdrom_open(get_disk_handle(machine(), "cdrom"));
1355   }
1356
1357   cdda_set_cdrom( machine().device("cdda"), cdrom );
1358
1359   if (cdrom)
1360   {
1361      CDROM_LOG(("Opened CD-ROM successfully, reading root directory\n"))
1362      read_new_dir(0xffffff);    // read root directory
1363   }
1364   else
1365   {
1366      cd_stat = CD_STAT_NODISC;
1367   }
1368
1369   cd_speed = 2;
1370   cdda_repeat_count = 0;
1371   tray_is_closed = 1;
1372
1373   sector_timer = machine().device<timer_device>("sector_timer");
1374   sector_timer->adjust(attotime::from_hz(150));   // 150 sectors / second = 300kBytes/second
1375   sh1_timer = machine().device<timer_device>("sh1_cmd");
1376   sh1_timer->adjust(attotime::from_hz(16667));
1377}
1378
1379saturn_state::blockT *saturn_state::cd_alloc_block(UINT8 *blknum)
1380{
1381   INT32 i;
1382
1383   // search the 200 available blocks for a free one
1384   for (i = 0; i < 200; i++)
1385   {
1386      if (blocks[i].size == -1)
1387      {
1388         freeblocks--;
1389         if (freeblocks <= 0)
1390         {
1391            buffull = 1;
1392         }
1393
1394         blocks[i].size = sectlenin;
1395         *blknum = i;
1396
1397         CDROM_LOG(("CD: allocating block %d, size %x\n", i, sectlenin))
1398
1399         return &blocks[i];
1400      }
1401   }
1402
1403   buffull = 1;
1404   return (blockT *)NULL;
1405}
1406
1407void saturn_state::cd_free_block(blockT *blktofree)
1408{
1409   INT32 i;
1410
1411   CDROM_LOG(("cd_free_block: %x\n", (UINT32)(FPTR)blktofree))
1412
1413   if(blktofree == NULL)
1414   {
1415      return;
1416   }
1417
1418   for (i = 0; i < 200; i++)
1419   {
1420      if (&blocks[i] == blktofree)
1421      {
1422         CDROM_LOG(("CD: freeing block %d\n", i))
1423      }
1424   }
1425
1426   blktofree->size = -1;
1427   freeblocks++;
1428   buffull = 0;
1429   hirqreg &= ~BFUL;
1430}
1431
1432void saturn_state::cd_getsectoroffsetnum(UINT32 bufnum, UINT32 *sectoffs, UINT32 *sectnum)
1433{
1434   if (*sectoffs == 0xffff)
1435   {
1436      // last sector
1437      printf("CD: Don't know how to handle offset ffff\n");
1438   }
1439   else if (*sectnum == 0xffff)
1440   {
1441      *sectnum = partitions[bufnum].numblks - *sectoffs;
1442   }
1443}
1444
1445void saturn_state::cd_defragblocks(partitionT *part)
1446{
1447   UINT32 i, j;
1448   blockT *temp;
1449   UINT8 temp2;
1450
1451   for (i = 0; i < (MAX_BLOCKS-1); i++)
1452   {
1453      for (j = i+1; j < MAX_BLOCKS; j++)
1454      {
1455         if ((part->blocks[i] == (blockT *)NULL) && (part->blocks[j] != (blockT *)NULL))
1456         {
1457            temp = part->blocks[i];
1458            part->blocks[i] = part->blocks[j];
1459            part->blocks[j] = temp;
1460
1461            temp2 = part->bnum[i];
1462            part->bnum[i] = part->bnum[j];
1463            part->bnum[j] = temp2;
1464         }
1465      }
1466   }
1467}
1468
1469UINT16 saturn_state::cd_readWord(UINT32 addr)
1470{
1471   UINT16 rv;
1472
1473   switch (addr & 0xffff)
1474   {
1475      case 0x0008:    // read HIRQ register
1476      case 0x000a:
1477         rv = hirqreg;
1478
1479         rv &= ~DCHG;    // always clear bit 6 (tray open)
1480
1481         if (buffull) rv |= BFUL; else rv &= ~BFUL;
1482         if (sectorstore) rv |= CSCT; else rv &= ~CSCT;
1483
1484         hirqreg = rv;
1485
1486//          CDROM_LOG(("RW HIRQ: %04x\n", rv))
1487
1488         return rv;
1489
1490      case 0x000c:
1491      case 0x000e:
1492//          CDROM_LOG(("RW HIRM: %04x\n", hirqmask))
1493         printf("RW HIRM: %04x\n", hirqmask);
1494         return hirqmask;
1495
1496      case 0x0018:
1497      case 0x001a:
1498//          CDROM_LOG(("RW CR1: %04x\n", cr1))
1499         return cr1;
1500
1501      case 0x001c:
1502      case 0x001e:
1503//          CDROM_LOG(("RW CR2: %04x\n", cr2))
1504         return cr2;
1505
1506      case 0x0020:
1507      case 0x0022:
1508//          CDROM_LOG(("RW CR3: %04x\n", cr3))
1509         return cr3;
1510
1511      case 0x0024:
1512      case 0x0026:
1513//          CDROM_LOG(("RW CR4: %04x\n", cr4))
1514         //popmessage("%04x %04x %04x %04x",cr1,cr2,cr3,cr4);
1515         cmd_pending = 0;
1516         cd_stat |= CD_STAT_PERI;
1517         return cr4;
1518
1519      case 0x8000:
1520         rv = 0xffff;
1521         switch (xfertype)
1522         {
1523            case XFERTYPE_TOC:
1524               rv = tocbuf[xfercount]<<8 | tocbuf[xfercount+1];
1525
1526               xfercount += 2;
1527               xferdnum += 2;
1528
1529               if (xfercount > 102*4)
1530               {
1531                  xfercount = 0;
1532                  xfertype = XFERTYPE_INVALID;
1533               }
1534               break;
1535
1536            case XFERTYPE_FILEINFO_1:
1537               rv = finfbuf[xfercount]<<8 | finfbuf[xfercount+1];
1538               xfercount += 2;
1539               xferdnum += 2;
1540
1541               if (xfercount > 6*2)
1542               {
1543                  xfercount = 0;
1544                  xfertype = XFERTYPE_INVALID;
1545               }
1546               break;
1547
1548            case XFERTYPE_FILEINFO_254: // Lunar 2
1549               if((xfercount % (6 * 2)) == 0)
1550               {
1551                  UINT32 temp = 2 + (xfercount / (0x6 * 2));
1552
1553                  // first 4 bytes = FAD
1554                  finfbuf[0] = (curdir[temp].firstfad>>24)&0xff;
1555                  finfbuf[1] = (curdir[temp].firstfad>>16)&0xff;
1556                  finfbuf[2] = (curdir[temp].firstfad>>8)&0xff;
1557                  finfbuf[3] = (curdir[temp].firstfad&0xff);
1558                  // second 4 bytes = length of file
1559                  finfbuf[4] = (curdir[temp].length>>24)&0xff;
1560                  finfbuf[5] = (curdir[temp].length>>16)&0xff;
1561                  finfbuf[6] = (curdir[temp].length>>8)&0xff;
1562                  finfbuf[7] = (curdir[temp].length&0xff);
1563                  finfbuf[8] = curdir[temp].interleave_gap_size;
1564                  finfbuf[9] = curdir[temp].file_unit_size;
1565                  finfbuf[10] = temp;
1566                  finfbuf[11] = curdir[temp].flags;
1567               }
1568
1569               rv = finfbuf[xfercount % (6 * 2)]<<8 | finfbuf[(xfercount % (6 * 2)) +1];
1570
1571               xfercount += 2;
1572               xferdnum += 2;
1573
1574               if (xfercount > (254 * 6 * 2))
1575               {
1576                  xfercount = 0;
1577                  xfertype = XFERTYPE_INVALID;
1578               }
1579               break;
1580
1581            case XFERTYPE_SUBQ:
1582               rv = subqbuf[xfercount]<<8 | subqbuf[xfercount+1];
1583
1584               xfercount += 2;
1585               xferdnum += 2;
1586
1587               if (xfercount > 5*2)
1588               {
1589                  xfercount = 0;
1590                  xfertype = XFERTYPE_INVALID;
1591               }
1592               break;
1593
1594
1595            case XFERTYPE_SUBRW:
1596               rv = subrwbuf[xfercount]<<8 | subrwbuf[xfercount+1];
1597
1598               xfercount += 2;
1599               xferdnum += 2;
1600
1601               if (xfercount > 12*2)
1602               {
1603                  xfercount = 0;
1604                  xfertype = XFERTYPE_INVALID;
1605               }
1606               break;
1607
1608            default:
1609               printf("STVCD: Unhandled xfer type %d\n", (int)xfertype);
1610               rv = 0;
1611               break;
1612         }
1613
1614         return rv;
1615
1616      default:
1617         CDROM_LOG(("CD: RW %08x\n", addr))
1618         return 0xffff;
1619   }
1620
1621}
1622
1623UINT32 saturn_state::cd_readLong(UINT32 addr)
1624{
1625   UINT32 rv = 0;
1626
1627   switch (addr & 0xffff)
1628   {
1629      case 0x8000:
1630         switch (xfertype32)
1631         {
1632            case XFERTYPE32_GETSECTOR:
1633            case XFERTYPE32_GETDELETESECTOR:
1634               // make sure we have sectors left
1635               if (xfersect < xfersectnum)
1636               {
1637                  // get next longword
1638                  rv = (transpart->blocks[xfersectpos+xfersect]->data[xferoffs + 0]<<24) |
1639                        (transpart->blocks[xfersectpos+xfersect]->data[xferoffs + 1]<<16) |
1640                        (transpart->blocks[xfersectpos+xfersect]->data[xferoffs + 2]<<8)  |
1641                        (transpart->blocks[xfersectpos+xfersect]->data[xferoffs + 3]<<0);
1642
1643                  xferdnum += 4;
1644                  xferoffs += 4;
1645
1646                  // did we run out of sector?
1647                  if (xferoffs >= transpart->blocks[xfersect]->size)
1648                  {
1649                     CDROM_LOG(("CD: finished xfer of block %d of %d\n", xfersect+1, xfersectnum))
1650
1651                     xferoffs = 0;
1652                     xfersect++;
1653                  }
1654               }
1655               else    // sectors are done, kill 'em all if we can
1656               {
1657                  if (xfertype32 == XFERTYPE32_GETDELETESECTOR)
1658                  {
1659                     INT32 i;
1660
1661                     CDROM_LOG(("Killing sectors in done\n"))
1662
1663                     // deallocate the blocks
1664                     for (i = xfersectpos; i < xfersectpos+xfersectnum; i++)
1665                     {
1666                        cd_free_block(transpart->blocks[i]);
1667                        transpart->blocks[i] = (blockT *)NULL;
1668                        transpart->bnum[i] = 0xff;
1669                     }
1670
1671                     // defrag what's left
1672                     cd_defragblocks(transpart);
1673
1674                     // clean up our state
1675                     transpart->size -= xferdnum;
1676                     transpart->numblks -= xfersectnum;
1677
1678                     xfertype32 = XFERTYPE32_INVALID;
1679                  }
1680               }
1681               break;
1682
1683            default:
1684               printf("CD: unhandled 32-bit transfer type\n");
1685               break;
1686         }
1687
1688         return rv;
1689
1690      default:
1691         CDROM_LOG(("CD: RL %08x\n", addr))
1692         return 0xffff;
1693   }
1694}
1695
1696void saturn_state::cd_writeWord(UINT32 addr, UINT16 data)
1697{
1698   switch(addr & 0xffff)
1699   {
1700   case 0x0008:
1701   case 0x000a:
1702//      CDROM_LOG(("%s:WW HIRQ: %04x & %04x => %04x\n", machine().describe_context(), hirqreg, data, hirqreg & data))
1703      hirqreg &= data;
1704      if(!(hirqreg & CMOK))
1705      {
1706         sh1_timer->reset();
1707         sh1_timer->adjust(attotime::from_hz(16667));
1708      }
1709      return;
1710   case 0x000c:
1711   case 0x000e:
1712//      CDROM_LOG(("WW HIRM: %04x => %04x\n", hirqmask, data))
1713      printf("WW HIRM: %04x => %04x\n", hirqmask, data);
1714      hirqmask = data;
1715      return;
1716   case 0x0018:
1717   case 0x001a:
1718//      CDROM_LOG(("WW CR1: %04x\n", data))
1719      cr1 = data;
1720      cd_stat &= ~CD_STAT_PERI;
1721      cmd_pending |= 1;
1722      break;
1723   case 0x001c:
1724   case 0x001e:
1725//      CDROM_LOG(("WW CR2: %04x\n", data))
1726      cr2 = data;
1727      cmd_pending |= 2;
1728      break;
1729   case 0x0020:
1730   case 0x0022:
1731//      CDROM_LOG(("WW CR3: %04x\n", data))
1732      cr3 = data;
1733      cmd_pending |= 4;
1734      break;
1735   case 0x0024:
1736   case 0x0026:
1737//      CDROM_LOG(("WW CR4: %04x\n", data))
1738      cr4 = data;
1739      cmd_pending |= 8;
1740      break;
1741   default:
1742      CDROM_LOG(("CD: WW %08x %04x\n", addr, data))
1743      break;
1744   }
1745}
1746
1747READ32_MEMBER( saturn_state::stvcd_r )
1748{
1749   UINT32 rv = 0;
1750
1751   offset <<= 2;
1752
1753   switch (offset)
1754   {
1755      case 0x90008:
1756      case 0x9000a:
1757      case 0x9000c:
1758      case 0x9000e:
1759      case 0x90018:
1760      case 0x9001a:
1761      case 0x9001c:
1762      case 0x9001e:
1763      case 0x90020:
1764      case 0x90022:
1765      case 0x90024:
1766      case 0x90026:
1767         rv = cd_readWord(offset);
1768         return rv<<16;
1769
1770      case 0x98000:
1771      case 0x18000:
1772         if (mem_mask == 0xffffffff)
1773         {
1774            rv = cd_readLong(offset);
1775         }
1776         else if (mem_mask == 0xffff0000)
1777         {
1778            rv = cd_readWord(offset)<<16;
1779         }
1780         else if (mem_mask == 0x0000ffff)
1781         {
1782            rv = cd_readWord(offset);
1783         }
1784         else
1785         {
1786            mame_printf_error("CD: Unknown data buffer read @ mask = %08x\n", mem_mask);
1787         }
1788
1789         break;
1790
1791      default:
1792         CDROM_LOG(("Unknown CD read @ %x\n", offset))
1793         break;
1794   }
1795
1796   return rv;
1797}
1798
1799WRITE32_MEMBER( saturn_state::stvcd_w )
1800{
1801   offset <<= 2;
1802
1803   switch (offset)
1804   {
1805      case 0x90008:
1806      case 0x9000a:
1807      case 0x9000c:
1808      case 0x9000e:
1809      case 0x90018:
1810      case 0x9001a:
1811      case 0x9001c:
1812      case 0x9001e:
1813      case 0x90020:
1814      case 0x90022:
1815      case 0x90024:
1816      case 0x90026:
1817         cd_writeWord(offset, data>>16);
1818         break;
1819
1820      default:
1821         CDROM_LOG(("Unknown CD write %x @ %x\n", data, offset))
1822         break;
1823   }
1824}
1825
1826// iso9660 parsing
1827void saturn_state::read_new_dir(UINT32 fileno)
1828{
1829   int foundpd, i;
1830   UINT32 cfad;//, dirfad;
1831   UINT8 sect[2048];
1832
1833   if (fileno == 0xffffff)
1834   {
1835      cfad = 166;     // first sector of directory as per iso9660 specs
1836
1837      foundpd = 0;    // search for primary vol. desc
1838      while ((!foundpd) && (cfad < 200))
1839      {
1840         if(sectlenin != 2048)
1841            popmessage("Sector Length %d, contact MAMEdev (0)",sectlenin);
1842
1843         memset(sect, 0, 2048);
1844         cd_readblock(cfad++, sect);
1845
1846         if ((sect[1] == 'C') && (sect[2] == 'D') && (sect[3] == '0') && (sect[4] == '0') && (sect[5] == '1'))
1847         {
1848            switch (sect[0])
1849            {
1850               case 0: // boot record
1851                  break;
1852
1853               case 1: // primary vol. desc
1854                  foundpd = 1;
1855                  break;
1856
1857               case 2: // secondary vol desc
1858                  break;
1859
1860               case 3: // vol. section descriptor
1861                  break;
1862
1863               case 0xff:
1864                  cfad = 200;
1865                  break;
1866            }
1867         }
1868      }
1869
1870      // got primary vol. desc.
1871      if (foundpd)
1872      {
1873         //dirfad = sect[140] | (sect[141]<<8) | (sect[142]<<16) | (sect[143]<<24);
1874         //dirfad += 150;
1875
1876         // parse root entry
1877         curroot.firstfad = sect[158] | (sect[159]<<8) | (sect[160]<<16) | (sect[161]<<24);
1878         curroot.firstfad += 150;
1879         curroot.length = sect[166] | (sect[167]<<8) | (sect[168]<<16) | (sect[169]<<24);
1880         curroot.flags = sect[181];
1881         for (i = 0; i < sect[188]; i++)
1882         {
1883            curroot.name[i] = sect[189+i];
1884         }
1885         curroot.name[i] = '\0'; // terminate
1886
1887         // easy to fix, but make sure we *need* to first
1888         if (curroot.length > MAX_DIR_SIZE)
1889         {
1890            mame_printf_error("ERROR: root directory too big (%d)\n", curroot.length);
1891         }
1892
1893         // done with all that, read the root directory now
1894         make_dir_current(curroot.firstfad);
1895      }
1896   }
1897   else
1898   {
1899      if (curdir[fileno].length > MAX_DIR_SIZE)
1900      {
1901         mame_printf_error("ERROR: new directory too big (%d)!\n", curdir[fileno].length);
1902      }
1903      make_dir_current(curdir[fileno].firstfad);
1904   }
1905}
1906
1907// makes the directory pointed to by FAD current
1908void saturn_state::make_dir_current(UINT32 fad)
1909{
1910   int i;
1911   UINT32 nextent, numentries;
1912   UINT8 *sect;
1913   direntryT *curentry;
1914
1915   sect = (UINT8 *)malloc(MAX_DIR_SIZE);
1916   memset(sect, 0, MAX_DIR_SIZE);
1917   if(sectlenin != 2048)
1918      popmessage("Sector Length %d, contact MAMEdev (1)",sectlenin);
1919
1920   for (i = 0; i < (curroot.length/2048); i++)
1921   {
1922      cd_readblock(fad+i, &sect[2048*i]);
1923   }
1924
1925   nextent = 0;
1926   numentries = 0;
1927   while (nextent < MAX_DIR_SIZE)
1928   {
1929      if (sect[nextent])
1930      {
1931         nextent += sect[nextent];
1932         numentries++;
1933      }
1934      else
1935      {
1936         nextent = MAX_DIR_SIZE;
1937      }
1938   }
1939
1940   if (curdir != (direntryT *)NULL)
1941   {
1942      auto_free(machine(), curdir);
1943   }
1944
1945   curdir = auto_alloc_array(machine(), direntryT, numentries);
1946   curentry = curdir;
1947   numfiles = numentries;
1948
1949   nextent = 0;
1950   while (numentries)
1951   {
1952      // [0] record size
1953      // [1] xa record size
1954      // [2-5] lba
1955      // [6-9] (lba?)
1956      // [10-13] size
1957      // [14-17] (size?)
1958      // [18] year
1959      // [19] month
1960      // [20] day
1961      // [21] hour
1962      // [22] minute
1963      // [23] second
1964      // [24] gmt offset
1965      // [25] flags
1966      // [26] file unit size
1967      // [27] interleave gap size
1968      // [28-29] volume sequencer number
1969      // [30-31] (volume sequencer number?)
1970      // [32] name character size
1971      // [33+ ...] file name
1972
1973      curentry->record_size = sect[nextent+0];
1974      curentry->xa_record_size = sect[nextent+1];
1975      curentry->firstfad = sect[nextent+2] | (sect[nextent+3]<<8) | (sect[nextent+4]<<16) | (sect[nextent+5]<<24);
1976      curentry->firstfad += 150;
1977      curentry->length = sect[nextent+10] | (sect[nextent+11]<<8) | (sect[nextent+12]<<16) | (sect[nextent+13]<<24);
1978      curentry->year = sect[nextent+18];
1979      curentry->month = sect[nextent+19];
1980      curentry->day = sect[nextent+20];
1981      curentry->hour = sect[nextent+21];
1982      curentry->minute = sect[nextent+22];
1983      curentry->second = sect[nextent+23];
1984      curentry->gmt_offset = sect[nextent+24];
1985      curentry->flags = sect[nextent+25];
1986      curentry->file_unit_size = sect[nextent+26];
1987      curentry->interleave_gap_size = sect[nextent+27];
1988      curentry->volume_sequencer_number = sect[nextent+28] | (sect[nextent+29] << 8);
1989
1990      for (i = 0; i < sect[nextent+32]; i++)
1991      {
1992         curentry->name[i] = sect[nextent+33+i];
1993      }
1994      //printf("%08x %08x %s %d/%d/%d\n",curentry->firstfad,curentry->length,curentry->name,curentry->year,curentry->month,curentry->day);
1995      curentry->name[i] = '\0';   // terminate
1996
1997      nextent += sect[nextent];
1998      curentry++;
1999      numentries--;
2000   }
2001
2002   for (i = 0; i < numfiles; i++)
2003   {
2004      if (!(curdir[i].flags & 0x02))
2005      {
2006         firstfile = i;
2007         i = numfiles;
2008      }
2009   }
2010
2011   free(sect);
2012}
2013
2014void saturn_state::stvcd_exit( void )
2015{
2016   if (curdir != (direntryT *)NULL)
2017   {
2018      auto_free(machine(), curdir);
2019      curdir = (direntryT *)NULL;
2020   }
2021
2022   if (cdrom)
2023   {
2024      cdrom_image_device *cddevice = machine().device<cdrom_image_device>("cdrom");
2025      if (cddevice==NULL)
2026      {
2027         cdrom_close(cdrom);
2028      }
2029      cdrom = (cdrom_file *)NULL;
2030   }
2031}
2032
2033void saturn_state::cd_readTOC(void)
2034{
2035   int i, ntrks, tocptr, fad;
2036
2037   xfertype = XFERTYPE_TOC;
2038   xfercount = 0;
2039
2040   if (cdrom)
2041   {
2042      ntrks = cdrom_get_last_track(cdrom);
2043   }
2044   else
2045   {
2046      ntrks = 0;
2047   }
2048
2049   // data format for Saturn TOC:
2050   // no header.
2051   // 4 bytes per track
2052   // top nibble of first byte is CTRL info
2053   // low nibble is ADR
2054   // next 3 bytes are FAD address (LBA + 150)
2055   // there are always 99 track entries (0-98)
2056   // unused tracks are ffffffff.
2057   // entries 99-101 are metadata
2058
2059   tocptr = 0; // starting point of toc entries
2060
2061   for (i = 0; i < ntrks; i++)
2062   {
2063      if (cdrom)
2064      {
2065         tocbuf[tocptr] = cdrom_get_adr_control(cdrom, i)<<4 | 0x01;
2066      }
2067      else
2068      {
2069         tocbuf[tocptr] = 0xff;
2070      }
2071
2072      if (cdrom)
2073      {
2074         fad = cdrom_get_track_start(cdrom, i) + 150;
2075
2076         tocbuf[tocptr+1] = (fad>>16)&0xff;
2077         tocbuf[tocptr+2] = (fad>>8)&0xff;
2078         tocbuf[tocptr+3] = fad&0xff;
2079      }
2080      else
2081      {
2082         tocbuf[tocptr+1] = 0xff;
2083         tocbuf[tocptr+2] = 0xff;
2084         tocbuf[tocptr+3] = 0xff;
2085      }
2086
2087      tocptr += 4;
2088   }
2089
2090   // fill in the rest
2091   for ( ; i < 99; i++)
2092   {
2093      tocbuf[tocptr] = 0xff;
2094      tocbuf[tocptr+1] = 0xff;
2095      tocbuf[tocptr+2] = 0xff;
2096      tocbuf[tocptr+3] = 0xff;
2097
2098      tocptr += 4;
2099   }
2100
2101   // tracks 99-101 are special metadata
2102   // $$$FIXME: what to do with the address info for these?
2103   tocptr = 99 * 4;
2104   tocbuf[tocptr] = tocbuf[0]; // get ctrl/adr from first track
2105   tocbuf[tocptr+1] = 1;   // first track's track #
2106   tocbuf[tocptr+2] = 0;
2107   tocbuf[tocptr+3] = 0;
2108
2109   tocbuf[tocptr+4] = tocbuf[(ntrks-1)*4]; // ditto for last track
2110   tocbuf[tocptr+5] = ntrks;   // last track's track #
2111   tocbuf[tocptr+6] = 0;
2112   tocbuf[tocptr+7] = 0;
2113
2114   // get total disc length (start of lead-out)
2115   fad = cdrom_get_track_start(cdrom, 0xaa) + 150;
2116
2117   tocbuf[tocptr+8] = tocbuf[0];
2118   tocbuf[tocptr+9]  = (fad>>16)&0xff;
2119   tocbuf[tocptr+10] = (fad>>8)&0xff;
2120   tocbuf[tocptr+11] = fad&0xff;
2121}
2122
2123saturn_state::partitionT *saturn_state::cd_filterdata(filterT *flt, int trktype, UINT8 *p_ok)
2124{
2125   int match = 1, keepgoing = 2;
2126   partitionT *filterprt = (partitionT *)NULL;
2127
2128   CDROM_LOG(("cd_filterdata, trktype %d\n", trktype))
2129
2130   // loop on the filters
2131   do
2132   {
2133      // FAD range check?
2134      /* according to an obscure document note, this switches the filter connector to be false if the range fails ... I think ... */
2135      if (flt->mode & 0x40)
2136      {
2137         if ((cd_curfad < flt->fad) || (cd_curfad > (flt->fad + flt->range)))
2138         {
2139            printf("curfad reject %08x %08x %08x %08x\n",cd_curfad,fadstoplay,flt->fad,flt->fad+flt->range);
2140            //match = 0;
2141            lastbuf = flt->condfalse;
2142            flt = &filters[lastbuf];
2143
2144            keepgoing--;
2145         }
2146      }
2147
2148      if ((trktype != CD_TRACK_AUDIO) && (curblock.data[15] == 2))
2149      {
2150         if (flt->mode & 1)  // file number
2151         {
2152            if (curblock.fnum != flt->fid)
2153            {
2154               logerror("fnum reject\n");
2155               match = 0;
2156            }
2157         }
2158
2159         if (flt->mode & 2)  // channel number
2160         {
2161            if (curblock.chan != flt->chan)
2162            {
2163               logerror("channel number reject\n");
2164               match = 0;
2165            }
2166         }
2167
2168         if (flt->mode & 4)  // sub mode
2169         {
2170            if((curblock.subm & flt->smmask) != flt->smval)
2171            {
2172               logerror("sub mode reject\n");
2173               match = 0;
2174            }
2175         }
2176
2177         if (flt->mode & 8)  // coding information
2178         {
2179            if((curblock.cinf & flt->cimask) != flt->cival)
2180            {
2181               logerror("coding information reject\n");
2182               match = 0;
2183            }
2184         }
2185
2186         if (flt->mode & 0x10)   // reverse subheader conditions
2187         {
2188            match ^= 1;
2189         }
2190      }
2191
2192      if (match)
2193      {
2194         lastbuf = flt->condtrue;
2195         filterprt = &partitions[lastbuf];
2196         // we're done
2197         keepgoing = 0;
2198      }
2199      else
2200      {
2201         lastbuf = flt->condfalse;
2202
2203         // reject sector if no match on either connector
2204         if ((lastbuf == 0xff) || (keepgoing < 2))
2205         {
2206            *p_ok = 0;
2207            return (partitionT *)NULL;
2208         }
2209
2210         // try again using the filter that was on the "false" connector
2211         flt = &filters[lastbuf];
2212
2213         // and exit if we fail
2214         keepgoing--;
2215      }
2216   } while (keepgoing);
2217
2218   // try to allocate a block
2219   filterprt->blocks[filterprt->numblks] = cd_alloc_block(&filterprt->bnum[filterprt->numblks]);
2220
2221   // did the allocation succeed?
2222   if (filterprt->blocks[filterprt->numblks] == (blockT *)NULL)
2223   {
2224      *p_ok = 0;
2225      return (partitionT *)NULL;
2226   }
2227
2228   // copy working block to the newly allocated one
2229   memcpy(filterprt->blocks[filterprt->numblks], &curblock, sizeof(blockT));
2230
2231   // and massage the data format a bit
2232   switch  (curblock.size)
2233   {
2234      case 2048:  // user data
2235         if (curblock.data[15] == 2)
2236         {
2237            // mode 2
2238            memcpy(&filterprt->blocks[filterprt->numblks]->data[0], &curblock.data[24], curblock.size);
2239         }
2240         else
2241         {
2242            // mode 1
2243            memcpy(&filterprt->blocks[filterprt->numblks]->data[0], &curblock.data[16], curblock.size);
2244         }
2245         break;
2246
2247      case 2324:  // Mode 2 Form 2 data
2248         memcpy(&filterprt->blocks[filterprt->numblks]->data[0], &curblock.data[24], curblock.size);
2249         break;
2250
2251      case 2336:  // Mode 2 Form 2 skip sync/header
2252         memcpy(&filterprt->blocks[filterprt->numblks]->data[0], &curblock.data[16], curblock.size);
2253         break;
2254
2255      case 2340:  // Mode 2 Form 2 skip sync only
2256         memcpy(&filterprt->blocks[filterprt->numblks]->data[0], &curblock.data[12], curblock.size);
2257         break;
2258
2259      case 2352:  // want all data, it's already done, so don't do it again :)
2260         break;
2261   }
2262
2263   // update the status of the partition
2264   if (filterprt->size == -1)
2265   {
2266      filterprt->size = 0;
2267   }
2268   filterprt->size += filterprt->blocks[filterprt->numblks]->size;
2269   filterprt->numblks++;
2270
2271   *p_ok = 1;
2272   return filterprt;
2273}
2274
2275// read a single sector off the CD, applying the current filter(s) as necessary
2276saturn_state::partitionT *saturn_state::cd_read_filtered_sector(INT32 fad, UINT8 *p_ok)
2277{
2278   int trktype;
2279
2280   if ((cddevice != NULL) && (!buffull))
2281   {
2282      // find out the track's type
2283      trktype = cdrom_get_track_type(cdrom, cdrom_get_track(cdrom, fad-150));
2284
2285      // now get a raw 2352 byte sector - if it's mode 1, get mode1_raw
2286      if ((trktype == CD_TRACK_MODE1) || (trktype == CD_TRACK_MODE1_RAW))
2287      {
2288         cdrom_read_data(cdrom, fad-150, curblock.data, CD_TRACK_MODE1_RAW);
2289      }
2290      else if (trktype != CD_TRACK_AUDIO) // if not audio it must be mode 2 so get mode2_raw
2291      {
2292         cdrom_read_data(cdrom, fad-150, curblock.data, CD_TRACK_MODE2_RAW);
2293      }
2294      else
2295      {
2296         cdrom_read_data(cdrom, fad-150, curblock.data, CD_TRACK_AUDIO);
2297      }
2298
2299      curblock.size = sectlenin;
2300      curblock.FAD = fad;
2301
2302      // if track is Mode 2, get the subheader values
2303      if ((trktype != CD_TRACK_AUDIO) && (curblock.data[15] == 2))
2304      {
2305         curblock.chan = curblock.data[17];
2306         curblock.fnum = curblock.data[16];
2307         curblock.subm = curblock.data[18];
2308         curblock.cinf = curblock.data[19];
2309
2310         // if it's Form 2, the length is actually 2324 bytes
2311         if (curblock.subm & 0x20)
2312         {
2313            curblock.size = 2324;
2314         }
2315      }
2316
2317      return cd_filterdata(cddevice, trktype, &*p_ok);
2318   }
2319
2320   *p_ok = 0;
2321   return (partitionT *)NULL;
2322}
2323
2324// loads in data set up by a CD-block PLAY command
2325void saturn_state::cd_playdata( void )
2326{
2327   if ((cd_stat & 0x0f00) == CD_STAT_PLAY)
2328   {
2329      if (fadstoplay)
2330      {
2331         logerror("STVCD: Reading FAD %d\n", cd_curfad);
2332
2333         if (cdrom)
2334         {
2335            UINT8 p_ok;
2336
2337            if(cdrom_get_track_type(cdrom, cdrom_get_track(cdrom, cd_curfad)) != CD_TRACK_AUDIO)
2338            {
2339               cd_read_filtered_sector(cd_curfad,&p_ok);
2340               cdda_stop_audio( machine().device( "cdda" ) ); //stop any pending CD-DA
2341            }
2342            else
2343            {
2344               p_ok = 1; // TODO
2345               cdda_start_audio( machine().device( "cdda" ), cd_curfad, 1  );
2346            }
2347
2348            if(p_ok)
2349            {
2350               cd_curfad++;
2351               fadstoplay--;
2352               hirqreg |= CSCT;
2353               sectorstore = 1;
2354
2355               if (!fadstoplay)
2356               {
2357                  if(cdda_repeat_count >= cdda_maxrepeat)
2358                  {
2359                     CDROM_LOG(("cd_playdata: playback ended\n"))
2360                     cd_stat = CD_STAT_PAUSE;
2361
2362                     hirqreg |= PEND;
2363
2364                     if (playtype == 1)
2365                     {
2366                        CDROM_LOG(("cd_playdata: setting EFLS\n"))
2367                        hirqreg |= EFLS;
2368                     }
2369                  }
2370                  else
2371                  {
2372                     if(cdda_repeat_count < 0xe)
2373                        cdda_repeat_count++;
2374
2375                     cd_curfad = cdrom_get_track_start(cdrom, cur_track-1) + 150;
2376                     fadstoplay = cdrom_get_track_start(cdrom, cur_track) - cd_curfad;
2377                  }
2378               }
2379            }
2380         }
2381      }
2382   }
2383}
2384
2385// loads a single sector off the CD, anywhere from FAD 150 on up
2386void saturn_state::cd_readblock(UINT32 fad, UINT8 *dat)
2387{
2388   if (cdrom)
2389   {
2390      cdrom_read_data(cdrom, fad-150, dat, CD_TRACK_MODE1);
2391   }
2392}
2393
2394void saturn_state::stvcd_set_tray_open( void )
2395{
2396   if(!tray_is_closed)
2397      return;
2398
2399   hirqreg |= DCHG;
2400   cd_stat = CD_STAT_OPEN;
2401
2402   cdrom = (cdrom_file *)NULL;
2403   tray_is_closed = 0;
2404
2405   popmessage("Tray Open");
2406}
2407
2408void saturn_state::stvcd_set_tray_close( void )
2409{
2410   /* avoid user attempts to load a CD-ROM without opening the tray first (emulation asserts anyway with current framework) */
2411   if(tray_is_closed)
2412      return;
2413
2414   hirqreg |= DCHG;
2415
2416   cdrom_image_device *cddevice = machine().device<cdrom_image_device>("cdrom");
2417   if (cddevice!=NULL)
2418   {
2419      // MESS case
2420      cdrom = cddevice->get_cdrom_file();
2421   }
2422   else
2423   {
2424      // MAME case
2425      cdrom = cdrom_open(get_disk_handle(machine(), "cdrom"));
2426   }
2427
2428   cdda_set_cdrom( machine().device("cdda"), cdrom );
2429
2430   if (cdrom)
2431   {
2432      CDROM_LOG(("Opened CD-ROM successfully, reading root directory\n"))
2433      //read_new_dir(0xffffff);  // read root directory
2434      cd_stat = CD_STAT_PAUSE;
2435   }
2436   else
2437   {
2438      cd_stat = CD_STAT_NODISC;
2439   }
2440
2441   cd_speed = 2;
2442   cdda_repeat_count = 0;
2443   tray_is_closed = 1;
2444
2445   popmessage("Tray Close");
2446}
trunk/src/mame/includes/stv.h
r20946r20947
714714#define IRQ_DMAILL     1 << 12
715715#define IRQ_VDP1_END   1 << 13
716716#define IRQ_ABUS       1 << 15
717
718extern void scsp_irq(device_t *device, int irq);
719GFXDECODE_EXTERN( stv );
trunk/src/mame/mame.mak
r20946r20947
12881288   $(DRIVERS)/segaybd.o $(VIDEO)/segaybd.o \
12891289   $(DRIVERS)/sg1000a.o \
12901290   $(DRIVERS)/stactics.o $(VIDEO)/stactics.o \
1291   $(DRIVERS)/saturn.o $(MACHINE)/stvprot.o $(MACHINE)/stvcd.o $(MACHINE)/smpc.o $(VIDEO)/stvvdp1.o $(VIDEO)/stvvdp2.o \
1291   $(DRIVERS)/stv.o $(DRIVERS)/saturn.o $(MACHINE)/stvprot.o \
12921292   $(DRIVERS)/suprloco.o $(VIDEO)/suprloco.o \
12931293   $(DRIVERS)/system1.o $(VIDEO)/system1.o \
12941294   $(DRIVERS)/system16.o $(VIDEO)/system16.o \
r20946r20947
13001300   $(MACHINE)/fd1094.o \
13011301   $(MACHINE)/fddebug.o \
13021302   $(MACHINE)/mc8123.o \
1303   $(MACHINE)/scudsp.o \
13041303   $(MACHINE)/segaic16.o \
13051304   $(AUDIO)/carnival.o \
13061305   $(AUDIO)/depthch.o \
trunk/src/mame/video/stvvdp1.c
r20946r20947
1/*
2
3STV - VDP1
4
5the vdp1 draws to the FRAMEBUFFER which is mapped in memory
6
7Framebuffer todo:
8- finish manual erase
9- add proper framebuffer erase
10- 8 bpp support - now we always draw as 16 bpp, but this is not a problem since
11  VDP2 interprets framebuffer as 8 bpp in these cases
12
13*/
14
15
16#include "emu.h"
17#include "includes/stv.h"
18
19#define VDP1_LOG 0
20
21
22enum { FRAC_SHIFT = 16 };
23
24struct spoint {
25   INT32 x, y;
26   INT32 u, v;
27};
28
29struct shaded_point
30{
31   INT32 x,y;
32   INT32 r,g,b;
33};
34
35#define RGB_R(_color)   (_color & 0x1f)
36#define RGB_G(_color)   ((_color >> 5) & 0x1f)
37#define RGB_B(_color)   ((_color >> 10) & 0x1f)
38
39#define SWAP_INT32(_a,_b) \
40   { \
41      INT32 t; \
42      t = _a; \
43      _a = _b; \
44      _b = t; \
45   }
46
47#define SWAP_INT32PTR(_p1, _p2) \
48   { \
49      INT32 *p; \
50      p = _p1; \
51      _p1 = _p2; \
52      _p2 = p; \
53   }
54
55/*TV Mode Selection Register */
56/*
57   xxxx xxxx xxxx ---- | UNUSED
58   ---- ---- ---- x--- | VBlank Erase/Write (VBE)
59   ---- ---- ---- -xxx | TV Mode (TVM)
60   TV-Mode:
61   This sets the Frame Buffer size,the rotation of the Frame Buffer & the bit width.
62   bit 2 HDTV disable(0)/enable(1)
63   bit 1 non-rotation/rotation(1)
64   bit 0 16(0)/8(1) bits per pixel
65   Size of the Frame Buffer:
66   7 invalid
67   6 invalid
68   5 invalid
69   4 512x256
70   3 512x512
71   2 512x256
72   1 1024x256
73   0 512x256
74*/
75
76/*Frame Buffer Change Mode Register*/
77/*
78   xxxx xxxx xxx- ---- | UNUSED
79   ---- ---- ---x ---- | Even/Odd Coordinate Select Bit (EOS)
80   ---- ---- ---- x--- | Double Interlace Mode (DIE)
81   ---- ---- ---- -x-- | Double Interlace Draw Line (DIL)
82   ---- ---- ---- --x- | Frame Buffer Change Trigger (FCM)
83   ---- ---- ---- ---x | Frame Buffer Change Mode (FCT)
84*/
85#define STV_VDP1_FBCR ((m_vdp1_regs[0x002/2] >> 0)&0xffff)
86#define STV_VDP1_EOS ((STV_VDP1_FBCR & 0x0010) >> 4)
87#define STV_VDP1_DIE ((STV_VDP1_FBCR & 0x0008) >> 3)
88#define STV_VDP1_DIL ((STV_VDP1_FBCR & 0x0004) >> 2)
89#define STV_VDP1_FCM ((STV_VDP1_FBCR & 0x0002) >> 1)
90#define STV_VDP1_FCT ((STV_VDP1_FBCR & 0x0001) >> 0)
91
92/*Plot Trigger Register*/
93/*
94   xxxx xxxx xxxx xx-- | UNUSED
95   ---- ---- ---- --xx | Plot Trigger Mode (PTM)
96
97   Plot Trigger Mode:
98   3 Invalid
99   2 Automatic draw
100   1 VDP1 draw by request
101   0 VDP1 Idle (no access)
102*/
103#define STV_VDP1_PTMR ((m_vdp1_regs[0x004/2])&0xffff)
104#define STV_VDP1_PTM  ((STV_VDP1_PTMR & 0x0003) >> 0)
105#define PTM_0         m_vdp1_regs[0x004/2]&=~0x0001
106
107/*
108    Erase/Write Data Register
109    16 bpp = data
110    8 bpp = erase/write data for even/odd X coordinates
111*/
112#define STV_VDP1_EWDR ((m_vdp1_regs[0x006/2])&0xffff)
113
114/*Erase/Write Upper-Left register*/
115/*
116   x--- ---- ---- ---- | UNUSED
117   -xxx xxx- ---- ---- | X1 register
118   ---- ---x xxxx xxxx | Y1 register
119
120*/
121#define STV_VDP1_EWLR ((m_vdp1_regs[0x008/2])&0xffff)
122#define STV_VDP1_EWLR_X1 ((STV_VDP1_EWLR & 0x7e00) >> 9)
123#define STV_VDP1_EWLR_Y1 ((STV_VDP1_EWLR & 0x01ff) >> 0)
124/*Erase/Write Lower-Right register*/
125/*
126   xxxx xxx- ---- ---- | X3 register
127   ---- ---x xxxx xxxx | Y3 register
128
129*/
130#define STV_VDP1_EWRR ((m_vdp1_regs[0x00a/2])&0xffff)
131#define STV_VDP1_EWRR_X3 ((STV_VDP1_EWRR & 0xfe00) >> 9)
132#define STV_VDP1_EWRR_Y3 ((STV_VDP1_EWRR & 0x01ff) >> 0)
133/*Transfer End Status Register*/
134/*
135   xxxx xxxx xxxx xx-- | UNUSED
136   ---- ---- ---- --x- | CEF
137   ---- ---- ---- ---x | BEF
138
139*/
140#define STV_VDP1_EDSR ((m_vdp1_regs[0x010/2])&0xffff)
141#define STV_VDP1_CEF  (STV_VDP1_EDSR & 2)
142#define STV_VDP1_BEF  (STV_VDP1_EDSR & 1)
143/**/
144
145
146
147READ16_MEMBER( saturn_state::saturn_vdp1_regs_r )
148{
149   //logerror ("cpu %s (PC=%08X) VDP1: Read from Registers, Offset %04x\n", space.device().tag(), space.device().safe_pc(), offset);
150
151   switch(offset)
152   {
153      case 0x02/2:
154         return 0;
155      case 0x10/2:
156         break;
157      case 0x12/2: return m_vdp1.lopr;
158      case 0x14/2: return m_vdp1.copr;
159      /* MODR register, read register for the other VDP1 regs
160         (Shienryu SS version abuses of this during intro) */
161      case 0x16/2:
162         UINT16 modr;
163
164         modr = 0x1000; //vdp1 VER
165         modr |= (STV_VDP1_PTM >> 1) << 8; // PTM1
166         modr |= STV_VDP1_EOS << 7; // EOS
167         modr |= STV_VDP1_DIE << 6; // DIE
168         modr |= STV_VDP1_DIL << 5; // DIL
169         modr |= STV_VDP1_FCM << 4; //FCM
170         modr |= STV_VDP1_VBE << 3; //VBE
171         modr |= STV_VDP1_TVM & 7; //TVM
172
173         return modr;
174      default:
175         if(!space.debugger_access())
176            printf ("cpu %s (PC=%08X) VDP1: Read from Registers, Offset %04x\n", space.device().tag(), space.device().safe_pc(), offset*2);
177         break;
178   }
179
180   return m_vdp1_regs[offset]; //TODO: write-only regs should return open bus or zero
181}
182
183void saturn_state::stv_clear_framebuffer( int which_framebuffer )
184{
185   if ( VDP1_LOG ) logerror( "Clearing %d framebuffer\n", m_vdp1.framebuffer_current_draw );
186   memset( m_vdp1.framebuffer[ which_framebuffer ], m_vdp1.ewdr, 1024 * 256 * sizeof(UINT16) * 2 );
187}
188
189
190void saturn_state::stv_prepare_framebuffers( void )
191{
192   int i,rowsize;
193
194   rowsize = m_vdp1.framebuffer_width;
195   if ( m_vdp1.framebuffer_current_draw == 0 )
196   {
197      for ( i = 0; i < m_vdp1.framebuffer_height; i++ )
198      {
199         m_vdp1.framebuffer_draw_lines[i] = &m_vdp1.framebuffer[0][ i * rowsize ];
200         m_vdp1.framebuffer_display_lines[i] = &m_vdp1.framebuffer[1][ i * rowsize ];
201      }
202      for ( ; i < 512; i++ )
203      {
204         m_vdp1.framebuffer_draw_lines[i] = &m_vdp1.framebuffer[0][0];
205         m_vdp1.framebuffer_display_lines[i] = &m_vdp1.framebuffer[1][0];
206      }
207   }
208   else
209   {
210      for ( i = 0; i < m_vdp1.framebuffer_height; i++ )
211      {
212         m_vdp1.framebuffer_draw_lines[i] = &m_vdp1.framebuffer[1][ i * rowsize ];
213         m_vdp1.framebuffer_display_lines[i] = &m_vdp1.framebuffer[0][ i * rowsize ];
214      }
215      for ( ; i < 512; i++ )
216      {
217         m_vdp1.framebuffer_draw_lines[i] = &m_vdp1.framebuffer[1][0];
218         m_vdp1.framebuffer_display_lines[i] = &m_vdp1.framebuffer[0][0];
219      }
220
221   }
222
223   for ( ; i < 512; i++ )
224   {
225      m_vdp1.framebuffer_draw_lines[i] = &m_vdp1.framebuffer[0][0];
226      m_vdp1.framebuffer_display_lines[i] = &m_vdp1.framebuffer[1][0];
227   }
228
229}
230
231void saturn_state::stv_vdp1_change_framebuffers( void )
232{
233   m_vdp1.framebuffer_current_display ^= 1;
234   m_vdp1.framebuffer_current_draw ^= 1;
235   if ( VDP1_LOG ) logerror( "Changing framebuffers: %d - draw, %d - display\n", m_vdp1.framebuffer_current_draw, m_vdp1.framebuffer_current_display );
236   stv_prepare_framebuffers();
237}
238
239void saturn_state::stv_set_framebuffer_config( void )
240{
241   if ( m_vdp1.framebuffer_mode == STV_VDP1_TVM &&
242         m_vdp1.framebuffer_double_interlace == STV_VDP1_DIE ) return;
243
244   if ( VDP1_LOG ) logerror( "Setting framebuffer config\n" );
245   m_vdp1.framebuffer_mode = STV_VDP1_TVM;
246   m_vdp1.framebuffer_double_interlace = STV_VDP1_DIE;
247   switch( m_vdp1.framebuffer_mode )
248   {
249      case 0: m_vdp1.framebuffer_width = 512; m_vdp1.framebuffer_height = 256; break;
250      case 1: m_vdp1.framebuffer_width = 1024; m_vdp1.framebuffer_height = 256; break;
251      case 2: m_vdp1.framebuffer_width = 512; m_vdp1.framebuffer_height = 256; break;
252      case 3: m_vdp1.framebuffer_width = 512; m_vdp1.framebuffer_height = 512; break;
253      case 4: m_vdp1.framebuffer_width = 512; m_vdp1.framebuffer_height = 256; break;
254      default: logerror( "Invalid framebuffer config %x\n", STV_VDP1_TVM ); m_vdp1.framebuffer_width = 512; m_vdp1.framebuffer_height = 256; break;
255   }
256   if ( STV_VDP1_DIE ) m_vdp1.framebuffer_height *= 2; /* double interlace */
257
258   m_vdp1.framebuffer_current_draw = 0;
259   m_vdp1.framebuffer_current_display = 1;
260   stv_prepare_framebuffers();
261}
262
263WRITE16_MEMBER( saturn_state::saturn_vdp1_regs_w )
264{
265   COMBINE_DATA(&m_vdp1_regs[offset]);
266
267   switch(offset)
268   {
269      case 0x00/2:
270         stv_set_framebuffer_config();
271         if ( VDP1_LOG ) logerror( "VDP1: Access to register TVMR = %1X\n", STV_VDP1_TVMR );
272
273         break;
274      case 0x02/2:
275         stv_set_framebuffer_config();
276         if ( VDP1_LOG ) logerror( "VDP1: Access to register FBCR = %1X\n", STV_VDP1_FBCR );
277         m_vdp1.fbcr_accessed = 1;
278         break;
279      case 0x04/2:
280         if ( VDP1_LOG ) logerror( "VDP1: Access to register PTMR = %1X\n", STV_VDP1_PTM );
281         if ( STV_VDP1_PTMR == 1 )
282            stv_vdp1_process_list();
283
284         break;
285      case 0x06/2:
286         if ( VDP1_LOG ) logerror( "VDP1: Erase data set %08X\n", data );
287
288         m_vdp1.ewdr = STV_VDP1_EWDR;
289         break;
290      case 0x08/2:
291         if ( VDP1_LOG ) logerror( "VDP1: Erase upper-left coord set: %08X\n", data );
292         break;
293      case 0x0a/2:
294         if ( VDP1_LOG ) logerror( "VDP1: Erase lower-right coord set: %08X\n", data );
295         break;
296      case 0x0c/2:
297         if ( VDP1_LOG ) logerror( "VDP1: Draw forced termination register write: %08X\n", data );
298         break;
299      default:
300         printf("Warning: write to unknown VDP1 reg %08x %08x\n",offset*2,data);
301         break;
302   }
303
304}
305
306READ32_MEMBER ( saturn_state::saturn_vdp1_vram_r )
307{
308   return m_vdp1_vram[offset];
309}
310
311
312WRITE32_MEMBER ( saturn_state::saturn_vdp1_vram_w )
313{
314   UINT8 *vdp1 = m_vdp1.gfx_decode;
315
316   COMBINE_DATA (&m_vdp1_vram[offset]);
317
318//  if (((offset * 4) > 0xdf) && ((offset * 4) < 0x140))
319//  {
320//      logerror("cpu %s (PC=%08X): VRAM dword write to %08X = %08X & %08X\n", space.device().tag(), space.device().safe_pc(), offset*4, data, mem_mask);
321//  }
322
323   data = m_vdp1_vram[offset];
324   /* put in gfx region for easy decoding */
325   vdp1[offset*4+0] = (data & 0xff000000) >> 24;
326   vdp1[offset*4+1] = (data & 0x00ff0000) >> 16;
327   vdp1[offset*4+2] = (data & 0x0000ff00) >> 8;
328   vdp1[offset*4+3] = (data & 0x000000ff) >> 0;
329}
330
331WRITE32_MEMBER ( saturn_state::saturn_vdp1_framebuffer0_w )
332{
333   //popmessage ("STV VDP1 Framebuffer 0 WRITE offset %08x data %08x",offset, data);
334   if ( STV_VDP1_TVM & 1 )
335   {
336      /* 8-bit mode */
337      //printf("VDP1 8-bit mode %08x %02x\n",offset,data);
338      if ( ACCESSING_BITS_24_31 )
339      {
340         m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2] &= 0x00ff;
341         m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2] |= data & 0xff00;
342      }
343      if ( ACCESSING_BITS_16_23 )
344      {
345         m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2] &= 0xff00;
346         m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2] |= data & 0x00ff;
347      }
348      if ( ACCESSING_BITS_8_15 )
349      {
350         m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2+1] &= 0x00ff;
351         m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2+1] |= data & 0xff00;
352      }
353      if ( ACCESSING_BITS_0_7 )
354      {
355         m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2+1] &= 0xff00;
356         m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2+1] |= data & 0x00ff;
357      }
358   }
359   else
360   {
361      /* 16-bit mode */
362      if ( ACCESSING_BITS_16_31 )
363      {
364         m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2] = (data >> 16) & 0xffff;
365      }
366      if ( ACCESSING_BITS_0_15 )
367      {
368         m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2+1] = data & 0xffff;
369      }
370   }
371}
372
373READ32_MEMBER ( saturn_state::saturn_vdp1_framebuffer0_r )
374{
375   UINT32 result = 0;
376   //popmessage ("STV VDP1 Framebuffer 0 READ offset %08x",offset);
377   if ( STV_VDP1_TVM & 1 )
378   {
379      /* 8-bit mode */
380      //printf("VDP1 8-bit mode %08x\n",offset);
381      if ( ACCESSING_BITS_24_31 )
382         result |= ((m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2] & 0xff00) << 16);
383      if ( ACCESSING_BITS_16_23 )
384         result |= ((m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2] & 0x00ff) << 16);
385      if ( ACCESSING_BITS_8_15 )
386         result |= ((m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2+1] & 0xff00));
387      if ( ACCESSING_BITS_0_7 )
388         result |= ((m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2+1] & 0x00ff));
389   }
390   else
391   {
392      /* 16-bit mode */
393      if ( ACCESSING_BITS_16_31 )
394      {
395         result |= (m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2] << 16);
396      }
397      if ( ACCESSING_BITS_0_15 )
398      {
399         result |= (m_vdp1.framebuffer[m_vdp1.framebuffer_current_draw][offset*2+1]);
400      }
401
402   }
403
404   return result;
405}
406
407#ifdef UNUSED_FUNCTION
408WRITE32_HANDLER ( saturn_vdp1_framebuffer1_w )
409{
410   //popmessage ("STV VDP1 Framebuffer 1 WRITE offset %08x data %08x",offset, data);
411}
412
413READ32_HANDLER ( saturn_vdp1_framebuffer1_r )
414{
415   //popmessage ("STV VDP1 Framebuffer 1 READ offset %08x",offset);
416   return 0xffff;
417}
418#endif
419
420
421/*
422
423there is a command every 0x20 bytes
424the first word is the control word
425the rest are data used by it
426
427---
42800 CMDCTRL
429   e--- ---- ---- ---- | end bit (15)
430   -jjj ---- ---- ---- | jump select bits (12-14)
431   ---- zzzz ---- ---- | zoom point / hotspot (8-11)
432   ---- ---- 00-- ---- | UNUSED
433   ---- ---- --dd ---- | character read direction (4,5)
434   ---- ---- ---- cccc | command bits (0-3)
435
43602 CMDLINK
437   llll llll llll ll-- | link
438   ---- ---- ---- --00 | UNUSED
439
44004 CMDPMOD
441   m--- ---- ---- ---- | MON (looks at MSB and apply shadows etc.)
442   -00- ---- ---- ---- | UNUSED
443   ---h ---- ---- ---- | HSS (High Speed Shrink)
444   ---- p--- ---- ---- | PCLIP (Pre Clipping Disable)
445   ---- -c-- ---- ---- | CLIP (Clipping Mode Bit)
446   ---- --m- ---- ---- | CMOD (User Clipping Enable Bit)
447   ---- ---M ---- ---- | MESH (Mesh Enable Bit)
448   ---- ---- e--- ---- | ECD (End Code Disable)
449   ---- ---- -S-- ---- | SPD (Transparent Pixel Disable)
450   ---- ---- --cc c--- | Colour Mode
451   ---- ---- ---- -CCC | Colour Calculation bits
452
45306 CMDCOLR
454   mmmm mmmm mmmm mmmm | Colour Bank, Colour Lookup /8
455
45608 CMDSRCA (Character Address)
457   aaaa aaaa aaaa aa-- | Character Address
458   ---- ---- ---- --00 | UNUSED
459
4600a CMDSIZE (Character Size)
461   00-- ---- ---- ---- | UNUSED
462   --xx xxxx ---- ---- | Character Size (X)
463   ---- ---- yyyy yyyy | Character Size (Y)
464
4650c CMDXA (used for normal sprite)
466   eeee ee-- ---- ---- | extension bits
467   ---- --xx xxxx xxxx | x position
468
4690e CMDYA (used for normal sprite)
470   eeee ee-- ---- ---- | extension bits
471   ---- --yy yyyy yyyy | y position
472
47310 CMDXB
47412 CMDYB
47514 CMDXC
47616 CMDYC
47718 CMDXD
4781a CMDYD
4791c CMDGRDA (Gouraud Shading Table)
4801e UNUSED
481---
482
483
484*/
485
486void saturn_state::stv_clear_gouraud_shading(void)
487{
488   memset( &stv_gouraud_shading, 0, sizeof( stv_gouraud_shading ) );
489}
490
491UINT8 saturn_state::stv_read_gouraud_table( void )
492{
493   int gaddr;
494
495   if ( (stv2_current_sprite.CMDPMOD & 0x7) == 4 )
496   {
497      gaddr = stv2_current_sprite.CMDGRDA * 8;
498      stv_gouraud_shading.GA = (m_vdp1_vram[gaddr/4] >> 16) & 0xffff;
499      stv_gouraud_shading.GB = (m_vdp1_vram[gaddr/4] >> 0) & 0xffff;
500      stv_gouraud_shading.GC = (m_vdp1_vram[gaddr/4 + 1] >> 16) & 0xffff;
501      stv_gouraud_shading.GD = (m_vdp1_vram[gaddr/4 + 1] >> 0) & 0xffff;
502      return 1;
503   }
504   else
505   {
506      return 0;
507   }
508}
509
510INLINE INT32 _shading( INT32 color, INT32 correction )
511{
512   correction = (correction >> 16) & 0x1f;
513   color += (correction - 16);
514
515   if ( color < 0 ) color = 0;
516   if ( color > 0x1f ) color = 0x1f;
517
518   return color;
519}
520
521UINT16 saturn_state::stv_vdp1_apply_gouraud_shading( int x, int y, UINT16 pix )
522{
523   INT32 r,g,b, msb;
524
525   msb = pix & 0x8000;
526
527#ifdef MAME_DEBUG
528   if ( (stv_vdp1_shading_data->scanline[y].x[0] >> 16) != x )
529   {
530      logerror( "ERROR in computing x coordinates (line %d, x = %x, %d, xc = %x, %d)\n", y, x, x, stv_vdp1_shading_data->scanline[y].x[0], stv_vdp1_shading_data->scanline[y].x[0] >> 16 );
531   };
532#endif
533
534   b = RGB_B(pix);
535   g = RGB_G(pix);
536   r = RGB_R(pix);
537
538   b = _shading( b, stv_vdp1_shading_data->scanline[y].b[0] );
539   g = _shading( g, stv_vdp1_shading_data->scanline[y].g[0] );
540   r = _shading( r, stv_vdp1_shading_data->scanline[y].r[0] );
541
542   stv_vdp1_shading_data->scanline[y].b[0] += stv_vdp1_shading_data->scanline[y].db;
543   stv_vdp1_shading_data->scanline[y].g[0] += stv_vdp1_shading_data->scanline[y].dg;
544   stv_vdp1_shading_data->scanline[y].r[0] += stv_vdp1_shading_data->scanline[y].dr;
545
546   stv_vdp1_shading_data->scanline[y].x[0] += 1 << FRAC_SHIFT;
547
548   return msb | b << 10 | g << 5 | r;
549}
550
551void saturn_state::stv_vdp1_setup_shading_for_line(INT32 y, INT32 x1, INT32 x2,
552                                 INT32 r1, INT32 g1, INT32 b1,
553                                 INT32 r2, INT32 g2, INT32 b2)
554{
555   int xx1 = x1>>FRAC_SHIFT;
556   int xx2 = x2>>FRAC_SHIFT;
557
558
559   if ( xx1 > xx2 )
560   {
561      SWAP_INT32(xx1, xx2);
562      SWAP_INT32(r1, r2);
563      SWAP_INT32(g1, g2);
564      SWAP_INT32(b1, b2);
565   }
566
567   if ( (y >= 0) && (y < 512) )
568   {
569      INT32  dx;
570      INT32   gbd, ggd, grd;
571
572      dx = xx2 - xx1;
573
574      if ( dx == 0 )
575      {
576         gbd = ggd = grd = 0;
577      }
578      else
579      {
580         gbd = abs(b2 - b1) / dx;
581         if (b2 < b1) gbd = -gbd;
582         ggd = abs(g2 - g1) / dx;
583         if (g2 < g1) ggd = -ggd;
584         grd = abs(r2 - r1) / dx;
585         if (r2 < r1) grd = -grd;
586      }
587
588      stv_vdp1_shading_data->scanline[y].x[0] = x1;
589      stv_vdp1_shading_data->scanline[y].x[1] = x2;
590
591      stv_vdp1_shading_data->scanline[y].b[0] = b1;
592      stv_vdp1_shading_data->scanline[y].g[0] = g1;
593      stv_vdp1_shading_data->scanline[y].r[0] = r1;
594      stv_vdp1_shading_data->scanline[y].b[1] = b2;
595      stv_vdp1_shading_data->scanline[y].g[1] = g2;
596      stv_vdp1_shading_data->scanline[y].r[1] = r2;
597
598      stv_vdp1_shading_data->scanline[y].db = gbd;
599      stv_vdp1_shading_data->scanline[y].dg = ggd;
600      stv_vdp1_shading_data->scanline[y].dr = grd;
601
602   }
603}
604
605void saturn_state::stv_vdp1_setup_shading_for_slope(
606                     INT32 x1, INT32 x2, INT32 sl1, INT32 sl2, INT32 *nx1, INT32 *nx2,
607                     INT32 r1, INT32 r2, INT32 slr1, INT32 slr2, INT32 *nr1, INT32 *nr2,
608                     INT32 g1, INT32 g2, INT32 slg1, INT32 slg2, INT32 *ng1, INT32 *ng2,
609                     INT32 b1, INT32 b2, INT32 slb1, INT32 slb2, INT32 *nb1, INT32 *nb2,
610                     INT32 _y1, INT32 y2)
611{
612   if(x1 > x2 || (x1==x2 && sl1 > sl2)) {
613      SWAP_INT32(x1,x2);
614      SWAP_INT32(sl1,sl2);
615      SWAP_INT32PTR(nx1, nx2);
616      SWAP_INT32(r1,r2);
617      SWAP_INT32(slr1, slr2);
618      SWAP_INT32PTR(nr1, nr2);
619      SWAP_INT32(g1, g2);
620      SWAP_INT32(slg1, slg2);
621      SWAP_INT32PTR(ng1, ng2);
622      SWAP_INT32(b1, b2);
623      SWAP_INT32(slb1, slb2);
624      SWAP_INT32PTR(nb1, nb2);
625   }
626
627   while(_y1 < y2)
628   {
629      stv_vdp1_setup_shading_for_line(_y1, x1, x2, r1, g1, b1, r2, g2, b2);
630      x1 += sl1;
631      r1 += slr1;
632      g1 += slg1;
633      b1 += slb1;
634
635      x2 += sl2;
636      r2 += slr2;
637      g2 += slg2;
638      b2 += slb2;
639      _y1++;
640   }
641   *nx1 = x1;
642   *nr1 = r1;
643   *ng1 = g1;
644   *nb1 = b1;
645
646   *nx2 = x2;
647   *nr2 = r2;
648   *nb2 = b2;
649   *ng2 = g2;
650}
651
652void saturn_state::stv_vdp1_setup_shading(const struct spoint* q, const rectangle &cliprect)
653{
654   INT32 x1, x2, delta, cury, limy;
655   INT32 r1, g1, b1, r2, g2, b2;
656   INT32 sl1, slg1, slb1, slr1;
657   INT32 sl2, slg2, slb2, slr2;
658   int pmin, pmax, i, ps1, ps2;
659   struct shaded_point p[8];
660   UINT16 gd[4];
661
662   if ( stv_read_gouraud_table() == 0 ) return;
663
664   gd[0] = stv_gouraud_shading.GA;
665   gd[1] = stv_gouraud_shading.GB;
666   gd[2] = stv_gouraud_shading.GC;
667   gd[3] = stv_gouraud_shading.GD;
668
669   for(i=0; i<4; i++) {
670      p[i].x = p[i+4].x = q[i].x << FRAC_SHIFT;
671      p[i].y = p[i+4].y = q[i].y;
672      p[i].r = p[i+4].r = RGB_R(gd[i]) << FRAC_SHIFT;
673      p[i].g = p[i+4].g = RGB_G(gd[i]) << FRAC_SHIFT;
674      p[i].b = p[i+4].b = RGB_B(gd[i]) << FRAC_SHIFT;
675   }
676
677   pmin = pmax = 0;
678   for(i=1; i<4; i++) {
679      if(p[i].y < p[pmin].y)
680         pmin = i;
681      if(p[i].y > p[pmax].y)
682         pmax = i;
683   }
684
685   cury = p[pmin].y;
686   limy = p[pmax].y;
687
688   stv_vdp1_shading_data->sy = cury;
689   stv_vdp1_shading_data->ey = limy;
690
691   if(cury == limy) {
692      x1 = x2 = p[0].x;
693      ps1 = ps2 = 0;
694      for(i=1; i<4; i++) {
695         if(p[i].x < x1) {
696            x1 = p[i].x;
697            ps1 = i;
698         }
699         if(p[i].x > x2) {
700            x2 = p[i].x;
701            ps2 = i;
702         }
703      }
704      stv_vdp1_setup_shading_for_line(cury, x1, x2, p[ps1].r, p[ps1].g, p[ps1].b, p[ps2].r, p[ps2].g, p[ps2].b);
705      goto finish;
706   }
707
708   ps1 = pmin+4;
709   ps2 = pmin;
710
711   goto startup;
712
713   for(;;) {
714      if(p[ps1-1].y == p[ps2+1].y) {
715         stv_vdp1_setup_shading_for_slope(
716                     x1, x2, sl1, sl2, &x1, &x2,
717                     r1, r2, slr1, slr2, &r1, &r2,
718                     g1, g2, slg1, slg2, &g1, &g2,
719                     b1, b2, slb1, slb2, &b1, &b2,
720                     cury, p[ps1-1].y);
721         cury = p[ps1-1].y;
722         if(cury >= limy)
723            break;
724         ps1--;
725         ps2++;
726
727      startup:
728         while(p[ps1-1].y == cury)
729            ps1--;
730         while(p[ps2+1].y == cury)
731            ps2++;
732         x1 = p[ps1].x;
733         r1 = p[ps1].r;
734         g1 = p[ps1].g;
735         b1 = p[ps1].b;
736         x2 = p[ps2].x;
737         r2 = p[ps2].r;
738         g2 = p[ps2].g;
739         b2 = p[ps2].b;
740
741         delta = cury-p[ps1-1].y;
742         sl1 = (x1-p[ps1-1].x)/delta;
743         slr1 = (r1-p[ps1-1].r)/delta;
744         slg1 = (g1-p[ps1-1].g)/delta;
745         slb1 = (b1-p[ps1-1].b)/delta;
746
747         delta = cury-p[ps2+1].y;
748         sl2 = (x2-p[ps2+1].x)/delta;
749         slr2 = (r2-p[ps2+1].r)/delta;
750         slg2 = (g2-p[ps2+1].g)/delta;
751         slb2 = (b2-p[ps2+1].b)/delta;
752      } else if(p[ps1-1].y < p[ps2+1].y) {
753         stv_vdp1_setup_shading_for_slope(
754                     x1, x2, sl1, sl2, &x1, &x2,
755                     r1, r2, slr1, slr2, &r1, &r2,
756                     g1, g2, slg1, slg2, &g1, &g2,
757                     b1, b2, slb1, slb2, &b1, &b2,
758                     cury, p[ps1-1].y);
759         cury = p[ps1-1].y;
760         if(cury >= limy)
761            break;
762         ps1--;
763         while(p[ps1-1].y == cury)
764            ps1--;
765         x1 = p[ps1].x;
766         r1 = p[ps1].r;
767         g1 = p[ps1].g;
768         b1 = p[ps1].b;
769
770         delta = cury-p[ps1-1].y;
771         sl1 = (x1-p[ps1-1].x)/delta;
772         slr1 = (r1-p[ps1-1].r)/delta;
773         slg1 = (g1-p[ps1-1].g)/delta;
774         slb1 = (b1-p[ps1-1].b)/delta;
775      } else {
776         stv_vdp1_setup_shading_for_slope(
777                     x1, x2, sl1, sl2, &x1, &x2,
778                     r1, r2, slr1, slr2, &r1, &r2,
779                     g1, g2, slg1, slg2, &g1, &g2,
780                     b1, b2, slb1, slb2, &b1, &b2,
781                     cury, p[ps2+1].y);
782         cury = p[ps2+1].y;
783         if(cury >= limy)
784            break;
785         ps2++;
786         while(p[ps2+1].y == cury)
787            ps2++;
788         x2 = p[ps2].x;
789         r2 = p[ps2].r;
790         g2 = p[ps2].g;
791         b2 = p[ps2].b;
792
793         delta = cury-p[ps2+1].y;
794         sl2 = (x2-p[ps2+1].x)/delta;
795         slr2 = (r2-p[ps2+1].r)/delta;
796         slg2 = (g2-p[ps2+1].g)/delta;
797         slb2 = (b2-p[ps2+1].b)/delta;
798      }
799   }
800   if(cury == limy)
801      stv_vdp1_setup_shading_for_line(cury, x1, x2, r1, g1, b1, r2, g2, b2 );
802
803finish:
804
805   if ( stv_vdp1_shading_data->sy < 0 ) stv_vdp1_shading_data->sy = 0;
806   if ( stv_vdp1_shading_data->sy >= 512 ) return;
807   if ( stv_vdp1_shading_data->ey < 0 ) return;
808   if ( stv_vdp1_shading_data->ey >= 512 ) stv_vdp1_shading_data->ey = 511;
809
810   for ( cury = stv_vdp1_shading_data->sy; cury <= stv_vdp1_shading_data->ey; cury++ )
811   {
812      while( (stv_vdp1_shading_data->scanline[cury].x[0] >> 16) < cliprect.min_x )
813      {
814         stv_vdp1_shading_data->scanline[cury].x[0] += (1 << FRAC_SHIFT);
815         stv_vdp1_shading_data->scanline[cury].b[0] += stv_vdp1_shading_data->scanline[cury].db;
816         stv_vdp1_shading_data->scanline[cury].g[0] += stv_vdp1_shading_data->scanline[cury].dg;
817         stv_vdp1_shading_data->scanline[cury].r[0] += stv_vdp1_shading_data->scanline[cury].dr;
818      }
819   }
820
821}
822
823/* note that if we're drawing
824to the framebuffer we CAN'T frameskip the vdp1 drawing as the hardware can READ the framebuffer
825and if we skip the drawing the content could be incorrect when it reads it, although i have no idea
826why they would want to */
827
828
829
830void saturn_state::drawpixel_poly(int x, int y, int patterndata, int offsetcnt)
831{
832   /* Capcom Collection Dai 4 uses a dummy polygon to clear VDP1 framebuffer that goes over our current max size ... */
833   if(x >= 1024 || y >= 512)
834      return;
835
836   m_vdp1.framebuffer_draw_lines[y][x] = stv2_current_sprite.CMDCOLR;
837}
838
839void saturn_state::drawpixel_8bpp_trans(int x, int y, int patterndata, int offsetcnt)
840{
841   UINT16 pix;
842
843   pix = m_vdp1.gfx_decode[patterndata+offsetcnt];
844   if ( pix & 0xff )
845   {
846      m_vdp1.framebuffer_draw_lines[y][x] = pix | m_sprite_colorbank;
847   }
848}
849
850void saturn_state::drawpixel_4bpp_notrans(int x, int y, int patterndata, int offsetcnt)
851{
852   UINT16 pix;
853
854   pix = m_vdp1.gfx_decode[patterndata+offsetcnt/2];
855   pix = offsetcnt&1 ? (pix & 0x0f) : ((pix & 0xf0)>>4);
856   m_vdp1.framebuffer_draw_lines[y][x] = pix | m_sprite_colorbank;
857}
858
859void saturn_state::drawpixel_4bpp_trans(int x, int y, int patterndata, int offsetcnt)
860{
861   UINT16 pix;
862
863   pix = m_vdp1.gfx_decode[patterndata+offsetcnt/2];
864   pix = offsetcnt&1 ? (pix & 0x0f) : ((pix & 0xf0)>>4);
865   if ( pix )
866      m_vdp1.framebuffer_draw_lines[y][x] = pix | m_sprite_colorbank;
867}
868
869void saturn_state::drawpixel_generic(int x, int y, int patterndata, int offsetcnt)
870{
871   int pix,mode,transmask, spd = stv2_current_sprite.CMDPMOD & 0x40;
872   int mesh = stv2_current_sprite.CMDPMOD & 0x100;
873   int pix2;
874
875   if ( mesh && !((x ^ y) & 1) )
876   {
877      return;
878   }
879
880   if ( stv2_current_sprite.ispoly )
881   {
882      pix = stv2_current_sprite.CMDCOLR&0xffff;
883
884      transmask = 0xffff;
885      if ( pix & 0x8000 )
886      {
887         mode = 5;
888      }
889      else
890      {
891         mode = 1;
892      }
893   }
894   else
895   {
896      switch (stv2_current_sprite.CMDPMOD&0x0038)
897      {
898         case 0x0000: // mode 0 16 colour bank mode (4bits) (hanagumi blocks)
899            // most of the shienryu sprites use this mode
900            pix = m_vdp1.gfx_decode[(patterndata+offsetcnt/2) & 0xfffff];
901            pix = offsetcnt&1 ? (pix & 0x0f) : ((pix & 0xf0)>>4);
902            pix = pix+((stv2_current_sprite.CMDCOLR&0xfff0));
903            mode = 0;
904            transmask = 0xf;
905            break;
906         case 0x0008: // mode 1 16 colour lookup table mode (4bits)
907            // shienryu explosisons (and some enemies) use this mode
908            pix2 = m_vdp1.gfx_decode[(patterndata+offsetcnt/2) & 0xfffff];
909            pix2 = offsetcnt&1 ? (pix2 & 0x0f) : ((pix2 & 0xf0)>>4);
910            pix = pix2&1 ?
911            ((((m_vdp1_vram[(((stv2_current_sprite.CMDCOLR&0xffff)*8)>>2)+((pix2&0xfffe)/2)])) & 0x0000ffff) >> 0):
912            ((((m_vdp1_vram[(((stv2_current_sprite.CMDCOLR&0xffff)*8)>>2)+((pix2&0xfffe)/2)])) & 0xffff0000) >> 16);
913
914            mode = 5;
915            transmask = 0xffff;
916
917            if ( !spd )
918            {
919               if ( (pix2 & 0xf) == 0 )
920               {
921                  return;
922               }
923               else
924               {
925                  spd = 1;
926               }
927            }
928            break;
929         case 0x0010: // mode 2 64 colour bank mode (8bits) (character select portraits on hanagumi)
930            pix = m_vdp1.gfx_decode[(patterndata+offsetcnt) & 0xfffff];
931            mode = 2;
932            pix = pix+(stv2_current_sprite.CMDCOLR&0xffc0);
933            transmask = 0x3f;
934            break;
935         case 0x0018: // mode 3 128 colour bank mode (8bits) (little characters on hanagumi use this mode)
936            pix = m_vdp1.gfx_decode[(patterndata+offsetcnt) & 0xfffff];
937            pix = pix+(stv2_current_sprite.CMDCOLR&0xff80);
938            transmask = 0x7f;
939            mode = 3;
940            break;
941         case 0x0020: // mode 4 256 colour bank mode (8bits) (hanagumi title)
942            pix = m_vdp1.gfx_decode[(patterndata+offsetcnt) & 0xfffff];
943            pix = pix+(stv2_current_sprite.CMDCOLR&0xff00);
944            transmask = 0xff;
945            mode = 4;
946            break;
947         case 0x0028: // mode 5 32,768 colour RGB mode (16bits)
948            pix = m_vdp1.gfx_decode[(patterndata+offsetcnt*2+1) & 0xfffff] | (m_vdp1.gfx_decode[(patterndata+offsetcnt*2) & 0xfffff]<<8) ;
949            mode = 5;
950            transmask = -1; /* TODO: check me */
951            break;
952         default: // other settings illegal
953            pix = machine().rand();
954            mode = 0;
955            transmask = 0xff;
956            popmessage("Illegal Sprite Mode, contact MAMEdev");
957      }
958
959
960      // preliminary end code disable support
961      if ( ((stv2_current_sprite.CMDPMOD & 0x80) == 0) &&
962         ((pix & transmask) == transmask) )
963      {
964         return;
965      }
966   }
967
968   /* MSBON */
969   pix |= stv2_current_sprite.CMDPMOD & 0x8000;
970   if ( mode != 5 )
971   {
972      if ( (pix & transmask) || spd )
973      {
974         m_vdp1.framebuffer_draw_lines[y][x] = pix;
975      }
976   }
977   else
978   {
979      if ( (pix & transmask) || spd )
980      {
981         switch( stv2_current_sprite.CMDPMOD & 0x7 )
982         {
983            case 0: /* replace */
984               m_vdp1.framebuffer_draw_lines[y][x] = pix;
985               break;
986            case 1: /* shadow */
987               if ( m_vdp1.framebuffer_draw_lines[y][x] & 0x8000 )
988               {
989                  m_vdp1.framebuffer_draw_lines[y][x] = ((m_vdp1.framebuffer_draw_lines[y][x] & ~0x8421) >> 1) | 0x8000;
990               }
991               break;
992            case 2: /* half luminance */
993               m_vdp1.framebuffer_draw_lines[y][x] = ((pix & ~0x8421) >> 1) | 0x8000;
994               break;
995            case 3: /* half transparent */
996               if ( m_vdp1.framebuffer_draw_lines[y][x] & 0x8000 )
997               {
998                  m_vdp1.framebuffer_draw_lines[y][x] = alpha_blend_r16( m_vdp1.framebuffer_draw_lines[y][x], pix, 0x80 ) | 0x8000;
999               }
1000               else
1001               {
1002                  m_vdp1.framebuffer_draw_lines[y][x] = pix;
1003               }
1004               break;
1005            case 4: /* Gouraud shading */
1006               m_vdp1.framebuffer_draw_lines[y][x] = stv_vdp1_apply_gouraud_shading( x, y, pix );
1007               break;
1008            default:
1009               m_vdp1.framebuffer_draw_lines[y][x] = pix;
1010               break;
1011         }
1012      }
1013   }
1014}
1015
1016
1017void saturn_state::stv_vdp1_set_drawpixel( void )
1018{
1019   int sprite_type = stv2_current_sprite.CMDCTRL & 0x000f;
1020   int sprite_mode = stv2_current_sprite.CMDPMOD&0x0038;
1021   int spd = stv2_current_sprite.CMDPMOD & 0x40;
1022   int mesh = stv2_current_sprite.CMDPMOD & 0x100;
1023   int ecd = stv2_current_sprite.CMDPMOD & 0x80;
1024
1025   if ( mesh || !ecd || ((stv2_current_sprite.CMDPMOD & 0x7) != 0) )
1026   {
1027      drawpixel = &saturn_state::drawpixel_generic;
1028      return;
1029   }
1030
1031   if (sprite_type == 4 && ((stv2_current_sprite.CMDPMOD & 0x7) == 0))
1032   {
1033      drawpixel = &saturn_state::drawpixel_poly;
1034   }
1035   else if ( (sprite_mode == 0x20) && !spd )
1036   {
1037      m_sprite_colorbank = (stv2_current_sprite.CMDCOLR&0xff00);
1038      drawpixel = &saturn_state::drawpixel_8bpp_trans;
1039   }
1040   else if ((sprite_mode == 0x00) && spd)
1041   {
1042      m_sprite_colorbank = (stv2_current_sprite.CMDCOLR&0xfff0);
1043      drawpixel = &saturn_state::drawpixel_4bpp_notrans;
1044   }
1045   else if (sprite_mode == 0x00 && !spd )
1046   {
1047      m_sprite_colorbank = (stv2_current_sprite.CMDCOLR&0xfff0);
1048      drawpixel = &saturn_state::drawpixel_4bpp_trans;
1049   }
1050   else
1051   {
1052      drawpixel = &saturn_state::drawpixel_generic;
1053   }
1054}
1055
1056
1057void saturn_state::vdp1_fill_slope(const rectangle &cliprect, int patterndata, int xsize,
1058                     INT32 x1, INT32 x2, INT32 sl1, INT32 sl2, INT32 *nx1, INT32 *nx2,
1059                     INT32 u1, INT32 u2, INT32 slu1, INT32 slu2, INT32 *nu1, INT32 *nu2,
1060                     INT32 v1, INT32 v2, INT32 slv1, INT32 slv2, INT32 *nv1, INT32 *nv2,
1061                     INT32 _y1, INT32 y2)
1062{
1063   if(_y1 > cliprect.max_y)
1064      return;
1065
1066   if(y2 <= cliprect.min_y) {
1067      int delta = y2-_y1;
1068      *nx1 = x1+delta*sl1;
1069      *nu1 = u1+delta*slu1;
1070      *nv1 = v1+delta*slv1;
1071      *nx2 = x2+delta*sl2;
1072      *nu2 = u2+delta*slu2;
1073      *nv2 = v2+delta*slv2;
1074      return;
1075   }
1076
1077   if(y2 > cliprect.max_y)
1078      y2 = cliprect.max_y+1;
1079
1080   if(_y1 < cliprect.min_y) {
1081      int delta = cliprect.min_y - _y1;
1082      x1 += delta*sl1;
1083      u1 += delta*slu1;
1084      v1 += delta*slv1;
1085      x2 += delta*sl2;
1086      u2 += delta*slu2;
1087      v2 += delta*slv2;
1088      _y1 = cliprect.min_y;
1089   }
1090
1091   if(x1 > x2 || (x1==x2 && sl1 > sl2)) {
1092      INT32 t, *tp;
1093      t = x1;
1094      x1 = x2;
1095      x2 = t;
1096      t = sl1;
1097      sl1 = sl2;
1098      sl2 = t;
1099      tp = nx1;
1100      nx1 = nx2;
1101      nx2 = tp;
1102
1103      t = u1;
1104      u1 = u2;
1105      u2 = t;
1106      t = slu1;
1107      slu1 = slu2;
1108      slu2 = t;
1109      tp = nu1;
1110      nu1 = nu2;
1111      nu2 = tp;
1112
1113      t = v1;
1114      v1 = v2;
1115      v2 = t;
1116      t = slv1;
1117      slv1 = slv2;
1118      slv2 = t;
1119      tp = nv1;
1120      nv1 = nv2;
1121      nv2 = tp;
1122   }
1123
1124   while(_y1 < y2) {
1125      if(_y1 >= cliprect.min_y) {
1126         INT32 slux = 0, slvx = 0;
1127         int xx1 = x1>>FRAC_SHIFT;
1128         int xx2 = x2>>FRAC_SHIFT;
1129         INT32 u = u1;
1130         INT32 v = v1;
1131         if(xx1 != xx2) {
1132            int delta = xx2-xx1;
1133            slux = (u2-u1)/delta;
1134            slvx = (v2-v1)/delta;
1135         }
1136         if(xx1 <= cliprect.max_x || xx2 >= cliprect.min_x) {
1137            if(xx1 < cliprect.min_x) {
1138               int delta = cliprect.min_x-xx1;
1139               u += slux*delta;
1140               v += slvx*delta;
1141               xx1 = cliprect.min_x;
1142            }
1143            if(xx2 > cliprect.max_x)
1144               xx2 = cliprect.max_x;
1145
1146            while(xx1 <= xx2) {
1147               (this->*drawpixel)(xx1,_y1, patterndata, (v>>FRAC_SHIFT)*xsize+(u>>FRAC_SHIFT));
1148               xx1++;
1149               u += slux;
1150               v += slvx;
1151            }
1152         }
1153      }
1154
1155      x1 += sl1;
1156      u1 += slu1;
1157      v1 += slv1;
1158      x2 += sl2;
1159      u2 += slu2;
1160      v2 += slv2;
1161      _y1++;
1162   }
1163   *nx1 = x1;
1164   *nu1 = u1;
1165   *nv1 = v1;
1166   *nx2 = x2;
1167   *nu2 = u2;
1168   *nv2 = v2;
1169}
1170
1171void saturn_state::vdp1_fill_line(const rectangle &cliprect, int patterndata, int xsize, INT32 y,
1172                     INT32 x1, INT32 x2, INT32 u1, INT32 u2, INT32 v1, INT32 v2)
1173{
1174   int xx1 = x1>>FRAC_SHIFT;
1175   int xx2 = x2>>FRAC_SHIFT;
1176
1177   if(y > cliprect.max_y || y < cliprect.min_y)
1178      return;
1179
1180   if(xx1 <= cliprect.max_x || xx2 >= cliprect.min_x) {
1181      INT32 slux = 0, slvx = 0;
1182      INT32 u = u1;
1183      INT32 v = v1;
1184      if(xx1 != xx2) {
1185         int delta = xx2-xx1;
1186         slux = (u2-u1)/delta;
1187         slvx = (v2-v1)/delta;
1188      }
1189      if(xx1 < cliprect.min_x) {
1190         int delta = cliprect.min_x-xx1;
1191         u += slux*delta;
1192         v += slvx*delta;
1193         xx1 = cliprect.min_x;
1194      }
1195      if(xx2 > cliprect.max_x)
1196         xx2 = cliprect.max_x;
1197
1198      while(xx1 <= xx2) {
1199         (this->*drawpixel)(xx1,y,patterndata,(v>>FRAC_SHIFT)*xsize+(u>>FRAC_SHIFT));
1200         xx1++;
1201         u += slux;
1202         v += slvx;
1203      }
1204   }
1205}
1206
1207void saturn_state::vdp1_fill_quad(const rectangle &cliprect, int patterndata, int xsize, const struct spoint *q)
1208{
1209   INT32 sl1, sl2, slu1, slu2, slv1, slv2, cury, limy, x1, x2, u1, u2, v1, v2, delta;
1210   int pmin, pmax, i, ps1, ps2;
1211   struct spoint p[8];
1212
1213   for(i=0; i<4; i++) {
1214      p[i].x = p[i+4].x = q[i].x << FRAC_SHIFT;
1215      p[i].y = p[i+4].y = q[i].y;
1216      p[i].u = p[i+4].u = q[i].u << FRAC_SHIFT;
1217      p[i].v = p[i+4].v = q[i].v << FRAC_SHIFT;
1218   }
1219
1220   pmin = pmax = 0;
1221   for(i=1; i<4; i++) {
1222      if(p[i].y < p[pmin].y)
1223         pmin = i;
1224      if(p[i].y > p[pmax].y)
1225         pmax = i;
1226   }
1227
1228   cury = p[pmin].y;
1229   limy = p[pmax].y;
1230
1231   if(cury == limy) {
1232      x1 = x2 = p[0].x;
1233      u1 = u2 = p[0].u;
1234      v1 = v2 = p[0].v;
1235      for(i=1; i<4; i++) {
1236         if(p[i].x < x1) {
1237            x1 = p[i].x;
1238            u1 = p[i].u;
1239            v1 = p[i].v;
1240         }
1241         if(p[i].x > x2) {
1242            x2 = p[i].x;
1243            u2 = p[i].u;
1244            v2 = p[i].v;
1245         }
1246      }
1247      vdp1_fill_line(cliprect, patterndata, xsize, cury, x1, x2, u1, u2, v1, v2);
1248      return;
1249   }
1250
1251   if(cury > cliprect.max_y)
1252      return;
1253   if(limy <= cliprect.min_y)
1254      return;
1255
1256   if(limy > cliprect.max_y)
1257      limy = cliprect.max_y;
1258
1259   ps1 = pmin+4;
1260   ps2 = pmin;
1261
1262   goto startup;
1263
1264   for(;;) {
1265      if(p[ps1-1].y == p[ps2+1].y) {
1266         vdp1_fill_slope(cliprect, patterndata, xsize,
1267                     x1, x2, sl1, sl2, &x1, &x2,
1268                     u1, u2, slu1, slu2, &u1, &u2,
1269                     v1, v2, slv1, slv2, &v1, &v2,
1270                     cury, p[ps1-1].y);
1271         cury = p[ps1-1].y;
1272         if(cury >= limy)
1273            break;
1274         ps1--;
1275         ps2++;
1276
1277      startup:
1278         while(p[ps1-1].y == cury)
1279            ps1--;
1280         while(p[ps2+1].y == cury)
1281            ps2++;
1282         x1 = p[ps1].x;
1283         u1 = p[ps1].u;
1284         v1 = p[ps1].v;
1285         x2 = p[ps2].x;
1286         u2 = p[ps2].u;
1287         v2 = p[ps2].v;
1288
1289         delta = cury-p[ps1-1].y;
1290         sl1 = (x1-p[ps1-1].x)/delta;
1291         slu1 = (u1-p[ps1-1].u)/delta;
1292         slv1 = (v1-p[ps1-1].v)/delta;
1293
1294         delta = cury-p[ps2+1].y;
1295         sl2 = (x2-p[ps2+1].x)/delta;
1296         slu2 = (u2-p[ps2+1].u)/delta;
1297         slv2 = (v2-p[ps2+1].v)/delta;
1298      } else if(p[ps1-1].y < p[ps2+1].y) {
1299         vdp1_fill_slope(cliprect, patterndata, xsize,
1300                     x1, x2, sl1, sl2, &x1, &x2,
1301                     u1, u2, slu1, slu2, &u1, &u2,
1302                     v1, v2, slv1, slv2, &v1, &v2,
1303                     cury, p[ps1-1].y);
1304         cury = p[ps1-1].y;
1305         if(cury >= limy)
1306            break;
1307         ps1--;
1308         while(p[ps1-1].y == cury)
1309            ps1--;
1310         x1 = p[ps1].x;
1311         u1 = p[ps1].u;
1312         v1 = p[ps1].v;
1313
1314         delta = cury-p[ps1-1].y;
1315         sl1 = (x1-p[ps1-1].x)/delta;
1316         slu1 = (u1-p[ps1-1].u)/delta;
1317         slv1 = (v1-p[ps1-1].v)/delta;
1318      } else {
1319         vdp1_fill_slope(cliprect, patterndata, xsize,
1320                     x1, x2, sl1, sl2, &x1, &x2,
1321                     u1, u2, slu1, slu2, &u1, &u2,
1322                     v1, v2, slv1, slv2, &v1, &v2,
1323                     cury, p[ps2+1].y);
1324         cury = p[ps2+1].y;
1325         if(cury >= limy)
1326            break;
1327         ps2++;
1328         while(p[ps2+1].y == cury)
1329            ps2++;
1330         x2 = p[ps2].x;
1331         u2 = p[ps2].u;
1332         v2 = p[ps2].v;
1333
1334         delta = cury-p[ps2+1].y;
1335         sl2 = (x2-p[ps2+1].x)/delta;
1336         slu2 = (u2-p[ps2+1].u)/delta;
1337         slv2 = (v2-p[ps2+1].v)/delta;
1338      }
1339   }
1340   if(cury == limy)
1341      vdp1_fill_line(cliprect, patterndata, xsize, cury, x1, x2, u1, u2, v1, v2);
1342}
1343
1344int saturn_state::x2s(int v)
1345{
1346   return (INT32)(INT16)v + m_vdp1.local_x;
1347}
1348
1349int saturn_state::y2s(int v)
1350{
1351   return (INT32)(INT16)v + m_vdp1.local_y;
1352}
1353
1354void saturn_state::stv_vdp1_draw_line(const rectangle &cliprect)
1355{
1356   struct spoint q[4];
1357
1358   q[0].x = x2s(stv2_current_sprite.CMDXA);
1359   q[0].y = y2s(stv2_current_sprite.CMDYA);
1360   q[1].x = x2s(stv2_current_sprite.CMDXB);
1361   q[1].y = y2s(stv2_current_sprite.CMDYB);
1362   q[2].x = x2s(stv2_current_sprite.CMDXA);
1363   q[2].y = y2s(stv2_current_sprite.CMDYA);
1364   q[3].x = x2s(stv2_current_sprite.CMDXB);
1365   q[3].y = y2s(stv2_current_sprite.CMDYB);
1366
1367   q[0].u = q[3].u = q[1].u = q[2].u = 0;
1368   q[0].v = q[1].v = q[2].v = q[3].v = 0;
1369
1370   vdp1_fill_quad(cliprect, 0, 1, q);
1371}
1372
1373void saturn_state::stv_vdp1_draw_poly_line(const rectangle &cliprect)
1374{
1375   struct spoint q[4];
1376
1377   q[0].x = x2s(stv2_current_sprite.CMDXA);
1378   q[0].y = y2s(stv2_current_sprite.CMDYA);
1379   q[1].x = x2s(stv2_current_sprite.CMDXB);
1380   q[1].y = y2s(stv2_current_sprite.CMDYB);
1381   q[2].x = x2s(stv2_current_sprite.CMDXA);
1382   q[2].y = y2s(stv2_current_sprite.CMDYA);
1383   q[3].x = x2s(stv2_current_sprite.CMDXB);
1384   q[3].y = y2s(stv2_current_sprite.CMDYB);
1385
1386   q[0].u = q[3].u = q[1].u = q[2].u = 0;
1387   q[0].v = q[1].v = q[2].v = q[3].v = 0;
1388
1389   vdp1_fill_quad(cliprect, 0, 1, q);
1390
1391   q[0].x = x2s(stv2_current_sprite.CMDXB);
1392   q[0].y = y2s(stv2_current_sprite.CMDYB);
1393   q[1].x = x2s(stv2_current_sprite.CMDXC);
1394   q[1].y = y2s(stv2_current_sprite.CMDYC);
1395   q[2].x = x2s(stv2_current_sprite.CMDXB);
1396   q[2].y = y2s(stv2_current_sprite.CMDYB);
1397   q[3].x = x2s(stv2_current_sprite.CMDXC);
1398   q[3].y = y2s(stv2_current_sprite.CMDYC);
1399
1400   q[0].u = q[3].u = q[1].u = q[2].u = 0;
1401   q[0].v = q[1].v = q[2].v = q[3].v = 0;
1402
1403   vdp1_fill_quad(cliprect, 0, 1, q);
1404
1405   q[0].x = x2s(stv2_current_sprite.CMDXC);
1406   q[0].y = y2s(stv2_current_sprite.CMDYC);
1407   q[1].x = x2s(stv2_current_sprite.CMDXD);
1408   q[1].y = y2s(stv2_current_sprite.CMDYD);
1409   q[2].x = x2s(stv2_current_sprite.CMDXC);
1410   q[2].y = y2s(stv2_current_sprite.CMDYC);
1411   q[3].x = x2s(stv2_current_sprite.CMDXD);
1412   q[3].y = y2s(stv2_current_sprite.CMDYD);
1413
1414   q[0].u = q[3].u = q[1].u = q[2].u = 0;
1415   q[0].v = q[1].v = q[2].v = q[3].v = 0;
1416
1417   vdp1_fill_quad(cliprect, 0, 1, q);
1418
1419   q[0].x = x2s(stv2_current_sprite.CMDXD);
1420   q[0].y = y2s(stv2_current_sprite.CMDYD);
1421   q[1].x = x2s(stv2_current_sprite.CMDXA);
1422   q[1].y = y2s(stv2_current_sprite.CMDYA);
1423   q[2].x = x2s(stv2_current_sprite.CMDXD);
1424   q[2].y = y2s(stv2_current_sprite.CMDYD);
1425   q[3].x = x2s(stv2_current_sprite.CMDXA);
1426   q[3].y = y2s(stv2_current_sprite.CMDYA);
1427
1428   q[0].u = q[3].u = q[1].u = q[2].u = 0;
1429   q[0].v = q[1].v = q[2].v = q[3].v = 0;
1430
1431   stv_vdp1_setup_shading(q, cliprect);
1432   vdp1_fill_quad(cliprect, 0, 1, q);
1433
1434}
1435
1436void saturn_state::stv_vdp1_draw_distorted_sprite(const rectangle &cliprect)
1437{
1438   struct spoint q[4];
1439
1440   int xsize, ysize;
1441   int direction;
1442   int patterndata;
1443
1444   direction = (stv2_current_sprite.CMDCTRL & 0x0030)>>4;
1445
1446   if ( stv2_current_sprite.ispoly )
1447   {
1448      xsize = ysize = 1;
1449      patterndata = 0;
1450   }
1451   else
1452   {
1453      xsize = (stv2_current_sprite.CMDSIZE & 0x3f00) >> 8;
1454      xsize = xsize * 8;
1455      if (xsize == 0) return; /* setting prohibited */
1456
1457      ysize = (stv2_current_sprite.CMDSIZE & 0x00ff);
1458      if (ysize == 0) return; /* setting prohibited */
1459
1460      patterndata = (stv2_current_sprite.CMDSRCA) & 0xffff;
1461      patterndata = patterndata * 0x8;
1462
1463   }
1464
1465
1466   q[0].x = x2s(stv2_current_sprite.CMDXA);
1467   q[0].y = y2s(stv2_current_sprite.CMDYA);
1468   q[1].x = x2s(stv2_current_sprite.CMDXB);
1469   q[1].y = y2s(stv2_current_sprite.CMDYB);
1470   q[2].x = x2s(stv2_current_sprite.CMDXC);
1471   q[2].y = y2s(stv2_current_sprite.CMDYC);
1472   q[3].x = x2s(stv2_current_sprite.CMDXD);
1473   q[3].y = y2s(stv2_current_sprite.CMDYD);
1474
1475   if(direction & 1) { // xflip
1476      q[0].u = q[3].u = xsize-1;
1477      q[1].u = q[2].u = 0;
1478   } else {
1479      q[0].u = q[3].u = 0;
1480      q[1].u = q[2].u = xsize-1;
1481   }
1482   if(direction & 2) { // yflip
1483      q[0].v = q[1].v = ysize-1;
1484      q[2].v = q[3].v = 0;
1485   } else {
1486      q[0].v = q[1].v = 0;
1487      q[2].v = q[3].v = ysize-1;
1488   }
1489
1490   stv_vdp1_setup_shading(q, cliprect);
1491   vdp1_fill_quad(cliprect, patterndata, xsize, q);
1492}
1493
1494void saturn_state::stv_vdp1_draw_scaled_sprite(const rectangle &cliprect)
1495{
1496   struct spoint q[4];
1497
1498   int xsize, ysize;
1499   int direction;
1500   int patterndata;
1501   int zoompoint;
1502   int x,y;
1503   int x2,y2;
1504   int screen_width,screen_height,screen_height_negative = 0;
1505
1506   direction = (stv2_current_sprite.CMDCTRL & 0x0030)>>4;
1507
1508   xsize = (stv2_current_sprite.CMDSIZE & 0x3f00) >> 8;
1509   xsize = xsize * 8;
1510
1511   ysize = (stv2_current_sprite.CMDSIZE & 0x00ff);
1512
1513   patterndata = (stv2_current_sprite.CMDSRCA) & 0xffff;
1514   patterndata = patterndata * 0x8;
1515
1516   zoompoint = (stv2_current_sprite.CMDCTRL & 0x0f00)>>8;
1517
1518   x = stv2_current_sprite.CMDXA;
1519   y = stv2_current_sprite.CMDYA;
1520
1521   screen_width = (INT16)stv2_current_sprite.CMDXB;
1522   if ( (screen_width < 0) && zoompoint)
1523   {
1524      screen_width = -screen_width;
1525      direction |= 1;
1526   }
1527
1528   screen_height = (INT16)stv2_current_sprite.CMDYB;
1529   if ( (screen_height < 0) && zoompoint )
1530   {
1531      screen_height_negative = 1;
1532      screen_height = -screen_height;
1533      direction |= 2;
1534   }
1535
1536   x2 = stv2_current_sprite.CMDXC; // second co-ordinate set x
1537   y2 = stv2_current_sprite.CMDYC; // second co-ordinate set y
1538
1539   switch (zoompoint)
1540   {
1541      case 0x0: // specified co-ordinates
1542         break;
1543      case 0x5: // up left
1544         break;
1545      case 0x6: // up center
1546         x -= screen_width/2 ;
1547         break;
1548      case 0x7: // up right
1549         x -= screen_width;
1550         break;
1551
1552      case 0x9: // center left
1553         y -= screen_height/2 ;
1554         break;
1555      case 0xa: // center center
1556         y -= screen_height/2 ;
1557         x -= screen_width/2 ;
1558
1559         break;
1560
1561      case 0xb: // center right
1562         y -= screen_height/2 ;
1563         x -= screen_width;
1564         break;
1565
1566      case 0xd: // center left
1567         y -= screen_height;
1568         break;
1569
1570      case 0xe: // center center
1571         y -= screen_height;
1572         x -= screen_width/2 ;
1573         break;
1574
1575      case 0xf: // center right
1576         y -= screen_height;
1577         x -= screen_width;
1578         break;
1579
1580      default: // illegal
1581         break;
1582
1583   }
1584
1585   /*  0----1
1586       |    |
1587       |    |
1588       3----2   */
1589
1590   if (zoompoint)
1591   {
1592      q[0].x = x2s(x);
1593      q[0].y = y2s(y);
1594      q[1].x = x2s(x)+screen_width;
1595      q[1].y = y2s(y);
1596      q[2].x = x2s(x)+screen_width;
1597      q[2].y = y2s(y)+screen_height;
1598      q[3].x = x2s(x);
1599      q[3].y = y2s(y)+screen_height;
1600
1601      if ( screen_height_negative )
1602      {
1603         q[0].y += screen_height;
1604         q[1].y += screen_height;
1605         q[2].y += screen_height;
1606         q[3].y += screen_height;
1607      }
1608   }
1609   else
1610   {
1611      q[0].x = x2s(x);
1612      q[0].y = y2s(y);
1613      q[1].x = x2s(x2);
1614      q[1].y = y2s(y);
1615      q[2].x = x2s(x2);
1616      q[2].y = y2s(y2);
1617      q[3].x = x2s(x);
1618      q[3].y = y2s(y2);
1619   }
1620
1621
1622   if(direction & 1) { // xflip
1623      q[0].u = q[3].u = xsize-1;
1624      q[1].u = q[2].u = 0;
1625   } else {
1626      q[0].u = q[3].u = 0;
1627      q[1].u = q[2].u = xsize-1;
1628   }
1629   if(direction & 2) { // yflip
1630      q[0].v = q[1].v = ysize-1;
1631      q[2].v = q[3].v = 0;
1632   } else {
1633      q[0].v = q[1].v = 0;
1634      q[2].v = q[3].v = ysize-1;
1635   }
1636
1637   stv_vdp1_setup_shading(q, cliprect);
1638   vdp1_fill_quad(cliprect, patterndata, xsize, q);
1639}
1640
1641
1642void saturn_state::stv_vdp1_draw_normal_sprite(const rectangle &cliprect, int sprite_type)
1643{
1644   //UINT16 *destline;
1645   //saturn_state *state = machine.driver_data<saturn_state>();
1646   int y, ysize, drawypos;
1647   int x, xsize, drawxpos;
1648   int direction;
1649   int patterndata;
1650   UINT8 shading;
1651   int su, u, dux, duy;
1652   int maxdrawypos, maxdrawxpos;
1653
1654   x = x2s(stv2_current_sprite.CMDXA);
1655   y = y2s(stv2_current_sprite.CMDYA);
1656
1657   direction = (stv2_current_sprite.CMDCTRL & 0x0030)>>4;
1658
1659   xsize = (stv2_current_sprite.CMDSIZE & 0x3f00) >> 8;
1660   xsize = xsize * 8;
1661
1662   ysize = (stv2_current_sprite.CMDSIZE & 0x00ff);
1663
1664   patterndata = (stv2_current_sprite.CMDSRCA) & 0xffff;
1665   patterndata = patterndata * 0x8;
1666
1667   if (VDP1_LOG) logerror ("Drawing Normal Sprite x %04x y %04x xsize %04x ysize %04x patterndata %06x\n",x,y,xsize,ysize,patterndata);
1668
1669   if ( x > cliprect.max_x ) return;
1670   if ( y > cliprect.max_y ) return;
1671
1672   shading = stv_read_gouraud_table();
1673   if ( shading )
1674   {
1675      struct spoint q[4];
1676      q[0].x = x; q[0].y = y;
1677      q[1].x = x + xsize; q[1].y = y;
1678      q[2].x = x + xsize; q[2].y = y + ysize;
1679      q[3].x = x; q[3].y = y + ysize;
1680
1681      stv_vdp1_setup_shading( q, cliprect );
1682   }
1683
1684   u = 0;
1685   dux = 1;
1686   duy = xsize;
1687   if ( direction & 0x1 ) //xflip
1688   {
1689      dux = -1;
1690      u = xsize - 1;
1691   }
1692   if ( direction & 0x2 ) //yflip
1693   {
1694      duy = -xsize;
1695      u += xsize*(ysize-1);
1696   }
1697   if ( y < cliprect.min_y ) //clip y
1698   {
1699      u += xsize*(cliprect.min_y - y);
1700      ysize -= (cliprect.min_y - y);
1701      y = cliprect.min_y;
1702   }
1703   if ( x < cliprect.min_x ) //clip x
1704   {
1705      u += dux*(cliprect.min_x - x);
1706      xsize -= (cliprect.min_x - x);
1707      x = cliprect.min_x;
1708   }
1709   maxdrawypos = MIN(y+ysize-1,cliprect.max_y);
1710   maxdrawxpos = MIN(x+xsize-1,cliprect.max_x);
1711   for (drawypos = y; drawypos <= maxdrawypos; drawypos++ )
1712   {
1713      //destline = m_vdp1.framebuffer_draw_lines[drawypos];
1714      su = u;
1715      for (drawxpos = x; drawxpos <= maxdrawxpos; drawxpos++ )
1716      {
1717         (this->*drawpixel)( drawxpos, drawypos, patterndata, u );
1718         u += dux;
1719      }
1720      u = su + duy;
1721   }
1722}
1723
1724void saturn_state::stv_vdp1_process_list( void )
1725{
1726   int position;
1727   int spritecount;
1728   int vdp1_nest;
1729   rectangle *cliprect;
1730
1731   spritecount = 0;
1732   position = 0;
1733
1734   if (VDP1_LOG) logerror ("Sprite List Process START\n");
1735
1736   vdp1_nest = -1;
1737
1738   stv_clear_gouraud_shading();
1739
1740   /*Set CEF bit to 0*/
1741   CEF_0;
1742
1743   while (spritecount<10000) // if its drawn this many sprites something is probably wrong or sega were crazy ;-)
1744   {
1745      int draw_this_sprite;
1746
1747      draw_this_sprite = 1;
1748
1749   //  if (position >= ((0x80000/0x20)/4)) // safety check
1750   //  {
1751   //      if (VDP1_LOG) logerror ("Sprite List Position Too High!\n");
1752   //      position = 0;
1753   //  }
1754
1755      stv2_current_sprite.CMDCTRL = (m_vdp1_vram[position * (0x20/4)+0] & 0xffff0000) >> 16;
1756
1757      if (stv2_current_sprite.CMDCTRL == 0x8000)
1758      {
1759         if (VDP1_LOG) logerror ("List Terminator (0x8000) Encountered, Sprite List Process END\n");
1760         goto end; // end of list
1761      }
1762
1763      stv2_current_sprite.CMDLINK = (m_vdp1_vram[position * (0x20/4)+0] & 0x0000ffff) >> 0;
1764      stv2_current_sprite.CMDPMOD = (m_vdp1_vram[position * (0x20/4)+1] & 0xffff0000) >> 16;
1765      stv2_current_sprite.CMDCOLR = (m_vdp1_vram[position * (0x20/4)+1] & 0x0000ffff) >> 0;
1766      stv2_current_sprite.CMDSRCA = (m_vdp1_vram[position * (0x20/4)+2] & 0xffff0000) >> 16;
1767      stv2_current_sprite.CMDSIZE = (m_vdp1_vram[position * (0x20/4)+2] & 0x0000ffff) >> 0;
1768      stv2_current_sprite.CMDXA   = (m_vdp1_vram[position * (0x20/4)+3] & 0xffff0000) >> 16;
1769      stv2_current_sprite.CMDYA   = (m_vdp1_vram[position * (0x20/4)+3] & 0x0000ffff) >> 0;
1770      stv2_current_sprite.CMDXB   = (m_vdp1_vram[position * (0x20/4)+4] & 0xffff0000) >> 16;
1771      stv2_current_sprite.CMDYB   = (m_vdp1_vram[position * (0x20/4)+4] & 0x0000ffff) >> 0;
1772      stv2_current_sprite.CMDXC   = (m_vdp1_vram[position * (0x20/4)+5] & 0xffff0000) >> 16;
1773      stv2_current_sprite.CMDYC   = (m_vdp1_vram[position * (0x20/4)+5] & 0x0000ffff) >> 0;
1774      stv2_current_sprite.CMDXD   = (m_vdp1_vram[position * (0x20/4)+6] & 0xffff0000) >> 16;
1775      stv2_current_sprite.CMDYD   = (m_vdp1_vram[position * (0x20/4)+6] & 0x0000ffff) >> 0;
1776      stv2_current_sprite.CMDGRDA = (m_vdp1_vram[position * (0x20/4)+7] & 0xffff0000) >> 16;
1777//      stv2_current_sprite.UNUSED  = (m_vdp1_vram[position * (0x20/4)+7] & 0x0000ffff) >> 0;
1778
1779      /* proecess jump / skip commands, set position for next sprite */
1780      switch (stv2_current_sprite.CMDCTRL & 0x7000)
1781      {
1782         case 0x0000: // jump next
1783            if (VDP1_LOG) logerror ("Sprite List Process + Next (Normal)\n");
1784            position++;
1785            break;
1786         case 0x1000: // jump assign
1787            if (VDP1_LOG) logerror ("Sprite List Process + Jump Old %06x New %06x\n", position, (stv2_current_sprite.CMDLINK>>2));
1788            position= (stv2_current_sprite.CMDLINK>>2);
1789            break;
1790         case 0x2000: // jump call
1791            if (vdp1_nest == -1)
1792            {
1793               if (VDP1_LOG) logerror ("Sprite List Process + Call Old %06x New %06x\n",position, (stv2_current_sprite.CMDLINK>>2));
1794               vdp1_nest = position+1;
1795               position = (stv2_current_sprite.CMDLINK>>2);
1796            }
1797            else
1798            {
1799               if (VDP1_LOG) logerror ("Sprite List Nested Call, ignoring\n");
1800               position++;
1801            }
1802            break;
1803         case 0x3000:
1804            if (vdp1_nest != -1)
1805            {
1806               if (VDP1_LOG) logerror ("Sprite List Process + Return\n");
1807               position = vdp1_nest;
1808               vdp1_nest = -1;
1809            }
1810            else
1811            {
1812               if (VDP1_LOG) logerror ("Attempted return from no subroutine, aborting\n");
1813               position++;
1814               goto end; // end of list
1815            }
1816            break;
1817         case 0x4000:
1818            draw_this_sprite = 0;
1819            position++;
1820            break;
1821         case 0x5000:
1822            if (VDP1_LOG) logerror ("Sprite List Skip + Jump Old %06x New %06x\n", position, (stv2_current_sprite.CMDLINK>>2));
1823            draw_this_sprite = 0;
1824            position= (stv2_current_sprite.CMDLINK>>2);
1825
1826            break;
1827         case 0x6000:
1828            draw_this_sprite = 0;
1829            if (vdp1_nest == -1)
1830            {
1831               if (VDP1_LOG) logerror ("Sprite List Skip + Call To Subroutine Old %06x New %06x\n",position, (stv2_current_sprite.CMDLINK>>2));
1832
1833               vdp1_nest = position+1;
1834               position = (stv2_current_sprite.CMDLINK>>2);
1835            }
1836            else
1837            {
1838               if (VDP1_LOG) logerror ("Sprite List Nested Call, ignoring\n");
1839               position++;
1840            }
1841            break;
1842         case 0x7000:
1843            draw_this_sprite = 0;
1844            if (vdp1_nest != -1)
1845            {
1846               if (VDP1_LOG) logerror ("Sprite List Skip + Return from Subroutine\n");
1847
1848               position = vdp1_nest;
1849               vdp1_nest = -1;
1850            }
1851            else
1852            {
1853               if (VDP1_LOG) logerror ("Attempted return from no subroutine, aborting\n");
1854               position++;
1855               goto end; // end of list
1856            }
1857            break;
1858      }
1859
1860      /* continue to draw this sprite only if the command wasn't to skip it */
1861      if (draw_this_sprite ==1)
1862      {
1863         if ( stv2_current_sprite.CMDPMOD & 0x0400 )
1864         {
1865            //if(stv2_current_sprite.CMDPMOD & 0x0200) /* TODO: Bio Hazard inventory screen uses outside cliprect */
1866            //  cliprect = &m_vdp1.system_cliprect;
1867            //else
1868               cliprect = &m_vdp1.user_cliprect;
1869         }
1870         else
1871         {
1872            cliprect = &m_vdp1.system_cliprect;
1873         }
1874
1875         stv_vdp1_set_drawpixel();
1876
1877         switch (stv2_current_sprite.CMDCTRL & 0x000f)
1878         {
1879            case 0x0000:
1880               if (VDP1_LOG) logerror ("Sprite List Normal Sprite (%d %d)\n",stv2_current_sprite.CMDXA,stv2_current_sprite.CMDYA);
1881               stv2_current_sprite.ispoly = 0;
1882               stv_vdp1_draw_normal_sprite(*cliprect, 0);
1883               break;
1884
1885            case 0x0001:
1886               if (VDP1_LOG) logerror ("Sprite List Scaled Sprite (%d %d)\n",stv2_current_sprite.CMDXA,stv2_current_sprite.CMDYA);
1887               stv2_current_sprite.ispoly = 0;
1888               stv_vdp1_draw_scaled_sprite(*cliprect);
1889               break;
1890
1891            case 0x0002:
1892            case 0x0003: // used by Hardcore 4x4
1893               if (VDP1_LOG) logerror ("Sprite List Distorted Sprite\n");
1894               if (VDP1_LOG) logerror ("(A: %d %d)\n",stv2_current_sprite.CMDXA,stv2_current_sprite.CMDYA);
1895               if (VDP1_LOG) logerror ("(B: %d %d)\n",stv2_current_sprite.CMDXB,stv2_current_sprite.CMDYB);
1896               if (VDP1_LOG) logerror ("(C: %d %d)\n",stv2_current_sprite.CMDXC,stv2_current_sprite.CMDYC);
1897               if (VDP1_LOG) logerror ("(D: %d %d)\n",stv2_current_sprite.CMDXD,stv2_current_sprite.CMDYD);
1898               if (VDP1_LOG) logerror ("CMDPMOD = %04x\n",stv2_current_sprite.CMDPMOD);
1899
1900               stv2_current_sprite.ispoly = 0;
1901               stv_vdp1_draw_distorted_sprite(*cliprect);
1902               break;
1903
1904            case 0x0004:
1905               if (VDP1_LOG) logerror ("Sprite List Polygon\n");
1906               stv2_current_sprite.ispoly = 1;
1907               stv_vdp1_draw_distorted_sprite(*cliprect);
1908               break;
1909
1910            case 0x0005:
1911//              case 0x0007: // mirror? Baroque uses it, crashes for whatever reason
1912               if (VDP1_LOG) logerror ("Sprite List Polyline\n");
1913               stv2_current_sprite.ispoly = 1;
1914               stv_vdp1_draw_poly_line(*cliprect);
1915               break;
1916
1917            case 0x0006:
1918               if (VDP1_LOG) logerror ("Sprite List Line\n");
1919               stv2_current_sprite.ispoly = 1;
1920               stv_vdp1_draw_line(*cliprect);
1921               break;
1922
1923            case 0x0008:
1924//              case 0x000b: // mirror? Bug 2
1925               if (VDP1_LOG) logerror ("Sprite List Set Command for User Clipping (%d,%d),(%d,%d)\n", stv2_current_sprite.CMDXA, stv2_current_sprite.CMDYA, stv2_current_sprite.CMDXC, stv2_current_sprite.CMDYC);
1926               m_vdp1.user_cliprect.set(stv2_current_sprite.CMDXA, stv2_current_sprite.CMDXC, stv2_current_sprite.CMDYA, stv2_current_sprite.CMDYC);
1927               break;
1928
1929            case 0x0009:
1930               if (VDP1_LOG) logerror ("Sprite List Set Command for System Clipping (0,0),(%d,%d)\n", stv2_current_sprite.CMDXC, stv2_current_sprite.CMDYC);
1931               m_vdp1.system_cliprect.set(0, stv2_current_sprite.CMDXC, 0, stv2_current_sprite.CMDYC);
1932               break;
1933
1934            case 0x000a:
1935               if (VDP1_LOG) logerror ("Sprite List Local Co-Ordinate Set (%d %d)\n",(INT16)stv2_current_sprite.CMDXA,(INT16)stv2_current_sprite.CMDYA);
1936               m_vdp1.local_x = (INT16)stv2_current_sprite.CMDXA;
1937               m_vdp1.local_y = (INT16)stv2_current_sprite.CMDYA;
1938               break;
1939
1940            default:
1941               popmessage ("VDP1: Sprite List Illegal %02x, contact MAMEdev",stv2_current_sprite.CMDCTRL & 0xf);
1942               m_vdp1.lopr = (position * 0x20) >> 3;
1943               m_vdp1.copr = (position * 0x20) >> 3;
1944               return;
1945         }
1946      }
1947
1948      spritecount++;
1949
1950   }
1951
1952
1953   end:
1954   /* set CEF to 1*/
1955   CEF_1;
1956   m_vdp1.copr = (position * 0x20) >> 3;
1957
1958   if (VDP1_LOG) logerror ("End of list processing!\n");
1959}
1960
1961void saturn_state::video_update_vdp1( void )
1962{
1963   int framebuffer_changed = 0;
1964
1965//  int enable;
1966//  if (machine.input().code_pressed (KEYCODE_R)) VDP1_LOG = 1;
1967//  if (machine.input().code_pressed (KEYCODE_T)) VDP1_LOG = 0;
1968
1969//  if (machine.input().code_pressed (KEYCODE_Y)) VDP1_LOG = 0;
1970//  {
1971//      FILE *fp;
1972//
1973//      fp=fopen("vdp1_ram.dmp", "w+b");
1974//      if (fp)
1975//      {
1976//          fwrite(stv_vdp1, 0x00100000, 1, fp);
1977//          fclose(fp);
1978//      }
1979//  }
1980   if (VDP1_LOG) logerror("video_update_vdp1 called\n");
1981   if (VDP1_LOG) logerror( "FBCR = %0x, accessed = %d\n", STV_VDP1_FBCR, m_vdp1.fbcr_accessed );
1982
1983   if(STV_VDP1_CEF)
1984      BEF_1;
1985   else
1986      BEF_0;
1987
1988   if ( m_vdp1.framebuffer_clear_on_next_frame )
1989   {
1990      if ( ((STV_VDP1_FBCR & 0x3) == 3) &&
1991         m_vdp1.fbcr_accessed )
1992      {
1993         stv_clear_framebuffer(m_vdp1.framebuffer_current_display);
1994         m_vdp1.framebuffer_clear_on_next_frame = 0;
1995      }
1996   }
1997
1998   switch( STV_VDP1_FBCR & 0x3 )
1999   {
2000      case 0: /* Automatic mode */
2001         stv_vdp1_change_framebuffers();
2002         stv_clear_framebuffer(m_vdp1.framebuffer_current_draw);
2003         framebuffer_changed = 1;
2004         break;
2005      case 1: /* Setting prohibited */
2006         break;
2007      case 2: /* Manual mode - erase */
2008         if ( m_vdp1.fbcr_accessed )
2009         {
2010            m_vdp1.framebuffer_clear_on_next_frame = 1;
2011         }
2012         break;
2013      case 3: /* Manual mode - change */
2014         if ( m_vdp1.fbcr_accessed )
2015         {
2016            stv_vdp1_change_framebuffers();
2017            if ( STV_VDP1_VBE )
2018            {
2019               stv_clear_framebuffer(m_vdp1.framebuffer_current_draw);
2020            }
2021            /* TODO: Slam n Jam 96 & Cross Romance doesn't like this, investigate. */
2022            framebuffer_changed = 1;
2023         }
2024   //      framebuffer_changed = 1;
2025         break;
2026   }
2027   m_vdp1.fbcr_accessed = 0;
2028
2029   if (VDP1_LOG) logerror( "PTM = %0x, TVM = %x\n", STV_VDP1_PTM, STV_VDP1_TVM );
2030   switch(STV_VDP1_PTM & 3)
2031   {
2032      case 0:/*Idle Mode*/
2033         break;
2034      case 1:/*Draw by request*/
2035         break;
2036      case 2:/*Automatic Draw*/
2037         if ( framebuffer_changed || VDP1_LOG )
2038         {
2039            /*set CEF to 1*/
2040            stv_vdp1_process_list();
2041         }
2042         break;
2043      case 3: /*<invalid>*/
2044         logerror("Warning: Invalid PTM mode set for VDP1!\n");
2045         break;
2046   }
2047   //popmessage("%04x %04x",STV_VDP1_EWRR_X3,STV_VDP1_EWRR_Y3);
2048}
2049
2050void saturn_state::stv_vdp1_state_save_postload( void )
2051{
2052   UINT8 *vdp1 = m_vdp1.gfx_decode;
2053   int offset;
2054   UINT32 data;
2055
2056   m_vdp1.framebuffer_mode = -1;
2057   m_vdp1.framebuffer_double_interlace = -1;
2058
2059   stv_set_framebuffer_config();
2060
2061   for (offset = 0; offset < 0x80000/4; offset++ )
2062   {
2063      data = m_vdp1_vram[offset];
2064      /* put in gfx region for easy decoding */
2065      vdp1[offset*4+0] = (data & 0xff000000) >> 24;
2066      vdp1[offset*4+1] = (data & 0x00ff0000) >> 16;
2067      vdp1[offset*4+2] = (data & 0x0000ff00) >> 8;
2068      vdp1[offset*4+3] = (data & 0x000000ff) >> 0;
2069   }
2070}
2071
2072int saturn_state::stv_vdp1_start ( void )
2073{
2074   m_vdp1_regs = auto_alloc_array_clear(machine(), UINT16, 0x020/2 );
2075   m_vdp1_vram = auto_alloc_array_clear(machine(), UINT32, 0x100000/4 );
2076   m_vdp1.gfx_decode = auto_alloc_array(machine(), UINT8, 0x100000 );
2077
2078   stv_vdp1_shading_data = auto_alloc(machine(), struct stv_vdp1_poly_scanline_data);
2079
2080   m_vdp1.framebuffer[0] = auto_alloc_array(machine(), UINT16, 1024 * 256 * 2 ); /* *2 is for double interlace */
2081   m_vdp1.framebuffer[1] = auto_alloc_array(machine(), UINT16, 1024 * 256 * 2 );
2082
2083   m_vdp1.framebuffer_display_lines = auto_alloc_array(machine(), UINT16 *, 512);
2084   m_vdp1.framebuffer_draw_lines = auto_alloc_array(machine(), UINT16 *, 512);
2085
2086   m_vdp1.framebuffer_width = m_vdp1.framebuffer_height = 0;
2087   m_vdp1.framebuffer_mode = -1;
2088   m_vdp1.framebuffer_double_interlace = -1;
2089   m_vdp1.fbcr_accessed = 0;
2090   m_vdp1.framebuffer_current_display = 0;
2091   m_vdp1.framebuffer_current_draw = 1;
2092   stv_clear_framebuffer(m_vdp1.framebuffer_current_draw);
2093   m_vdp1.framebuffer_clear_on_next_frame = 0;
2094
2095   m_vdp1.system_cliprect.set(0, 0, 0, 0);
2096   /* Kidou Senshi Z Gundam - Zenpen Zeta no Kodou loves to use the user cliprect vars in an undefined state ... */
2097   m_vdp1.user_cliprect.set(0, 512, 0, 256);
2098
2099   // save state
2100   state_save_register_global_pointer(machine(), m_vdp1_regs, 0x020/2);
2101   state_save_register_global_pointer(machine(), m_vdp1_vram, 0x100000/4);
2102   state_save_register_global(machine(), m_vdp1.fbcr_accessed);
2103   state_save_register_global(machine(), m_vdp1.framebuffer_current_display);
2104   state_save_register_global(machine(), m_vdp1.framebuffer_current_draw);
2105   state_save_register_global(machine(), m_vdp1.framebuffer_clear_on_next_frame);
2106   state_save_register_global(machine(), m_vdp1.local_x);
2107   state_save_register_global(machine(), m_vdp1.local_y);
2108   machine().save().register_postload(save_prepost_delegate(FUNC(saturn_state::stv_vdp1_state_save_postload), this));
2109   return 0;
2110}
trunk/src/mame/video/stvvdp2.c
r20946r20947
1/* Sega Saturn VDP2 */
2
3#define DEBUG_MODE 0
4#define TEST_FUNCTIONS 0
5
6/*
7
8the dirty marking stuff and tile decoding will probably be removed in the end anyway as we'll need custom
9rendering code since mame's drawgfx / tilesytem don't offer everything st-v needs
10
11this system seems far too complex to use Mame's tilemap system
12
134 'scroll' planes (scroll screens)
14
15the scroll planes have slightly different capabilities
16
17NBG0
18NBG1
19NBG2
20NBG3
21
222 'rotate' planes
23
24RBG0
25RBG1
26
27-- other crap
28EXBG (external)
29
30-----------------------------------------------------------------------------------------------------------
31
32Video emulation TODO:
33-all games:
34 \-priorities (check myfairld,thunt)
35 \-complete windows effects
36 \-mosaic effect
37 \-ODD bit/H/V Counter not yet emulated properly
38 \-Reduction enable bits
39 \-Check if there are any remaining video registers that are yet to be macroized & added to the rumble.
40-batmanfr:
41 \-If you reset the game after the character selection screen,when you get again to it there's garbage
42   floating behind Batman.
43-elandore:
44 \-(BTANB) priorities at the VS. screen apparently is wrong,but it's like this on the Saturn version too.
45-hanagumi:
46 \-ending screens have corrupt graphics. (*untested*)
47-kiwames:
48 \-incorrect color emulation for the alpha blended flames on the title screen,it's caused by a schizoid
49   linescroll emulation quirk.
50 \-the VDP1 sprites refresh is too slow,causing the "Draw by request" mode to
51   flicker.Moved back to default ATM.
52-pblbeach:
53 \-Sprites are offset, because it doesn't clear vdp1 local coordinates set by bios,
54   I guess that they are cleared when some vdp1 register is written (kludged for now)
55-prikura:
56 \-Attract mode presentation has corrupted graphics in various places,probably caused by incomplete
57   framebuffer data delete.
58-seabass:
59 \-Player sprite is corrupt/missing during movements,caused by incomplete framebuffer switching.
60
61Notes of Interest & Unclear features:
62
63-the test mode / bios is drawn with layer NBG3;
64-hanagumi puts a 'RED' dragon logo in tileram (base 0x64000, 4bpp, 8x8 tiles) but
65its not displayed because its priority value is 0.Left-over?
66
67-scrolling is screen display wise,meaning that a scrolling value is masked with the
68screen resolution size values;
69
70-H-Blank bit is INDIPENDENT of the V-Blank bit...trying to fix enable/disable it during V-Blank period
71 causes wrong gameplay speed in Golden Axe:The Duel.
72
73-Bitmaps uses transparency pens,examples are:
74\-elandore's energy bars;
75\-mausuke's foreground(the one used on the playfield)
76\-shanhigw's tile-based sprites;
77The transparency pen table is like this:
78
79|------------------|---------------------|
80| Character count  | Transparency code   |
81|------------------|---------------------|
82| 16 colors        |=0x0 (4 bits)        |
83| 256 colors       |=0x00 (8 bits)       |
84| 2048 colors      |=0x000 (11 bits)     |
85| 32,768 colors    |MSB=0 (bit 15)       |
86| 16,770,000 colors|MSB=0 (bit 31)       |
87|------------------|---------------------|
88In other words,the first three types uses the offset and not the color allocated.
89
90-double density interlace setting (LSMD == 3) apparently does a lot of fancy stuff in the graphics sizes.
91
92-Debug key list(only if you enable the debug mode on top of this file):
93    \-T: NBG3 layer toggle
94    \-Y: NBG2 layer toggle
95    \-U: NBG1 layer toggle
96    \-I: NBG0 layer toggle
97    \-O: SPRITE toggle
98    \-K: RBG0 layer toggle
99    \-W Decodes the graphics for F4 menu.
100    \-M Stores VDP1 ram contents from a file.
101    \-N Stores VDP1 ram contents into a file.
102*/
103
104#include "emu.h"
105#include "includes/stv.h"
106
107enum
108{
109   STV_TRANSPARENCY_NONE,
110   STV_TRANSPARENCY_PEN,
111   STV_TRANSPARENCY_ADD_BLEND,
112   STV_TRANSPARENCY_ALPHA
113};
114
115#if DEBUG_MODE
116#define LOG_VDP2 1
117#define LOG_ROZ 0
118#else
119#define LOG_VDP2 0
120#define LOG_ROZ 0
121#endif
122
123/*
124
125-------------------------------------------------|-----------------------------|------------------------------
126|  Function        |  Normal Scroll Screen                                     |  Rotation Scroll Screen     |
127|                  |-----------------------------|-----------------------------|------------------------------
128|                  | NBG0         | NBG1         | NBG2         | NBG3         | RBG0         | RBG1         |
129-------------------------------------------------|-----------------------------|------------------------------
130| Character Colour | 16 colours   | 16 colours   | 16 colours   | 16 colours   | 16 colours   | 16 colours   |
131| Count            | 256 " "      | 256 " "      | 256 " "      | 256 " "      | 256 " "      | 256 " "      |
132|                  | 2048 " "     | 2048 " "     |              |              | 2048 " "     | 2048 " "     |
133|                  | 32768 " "    | 32768 " "    |              |              | 32768 " "    | 32768 " "    |
134|                  | 16770000 " " |              |              |              | 16770000 " " | 16770000 " " |
135-------------------------------------------------|-----------------------------|------------------------------
136| Character Size   | 1x1 Cells , 2x2 Cells                                                                   |
137-------------------------------------------------|-----------------------------|------------------------------
138| Pattern Name     | 1 word , 2 words                                                                        |
139| Data Size        |                                                                                         |
140-------------------------------------------------|-----------------------------|------------------------------
141| Plane Size       | 1 H x 1 V 1 Pages ; 2 H x 1 V 1 Pages ; 2 H x 2 V Pages                                 |
142-------------------------------------------------|-----------------------------|------------------------------
143| Plane Count      | 4                                                         | 16                          |
144-------------------------------------------------|-----------------------------|------------------------------
145| Bitmap Possible  | Yes                         | No                          | Yes          | No           |
146-------------------------------------------------|-----------------------------|------------------------------
147| Bitmap Size      | 512 x 256                   | N/A                         | 512x256      | N/A          |
148|                  | 512 x 512                   |                             | 512x512      |              |
149|                  | 1024 x 256                  |                             |              |              |
150|                  | 1024 x 512                  |                             |              |              |
151-------------------------------------------------|-----------------------------|------------------------------
152| Scale            | 0.25 x - 256 x              | None                        | Any ?                       |
153-------------------------------------------------|-----------------------------|------------------------------
154| Rotation         | No                                                        | Yes                         |
155-------------------------------------------------|-----------------------------|-----------------------------|
156| Linescroll       | Yes                         | No                                                        |
157-------------------------------------------------|-----------------------------|------------------------------
158| Column Scroll    | Yes                         | No                                                        |
159-------------------------------------------------|-----------------------------|------------------------------
160| Mosaic           | Yes                                                       | Horizontal Only             |
161-------------------------------------------------|-----------------------------|------------------------------
162
163*/
164
165/* 180000 - r/w - TVMD - TV Screen Mode
166 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
167       | DISP     |    --    |    --    |    --    |    --    |    --    |    --    | BDCLMD   |
168       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
169       | LSMD1    | LSMD0    | VRESO1   | VRESO0   |    --    | HRESO2   | HRESO1   | HRESO0   |
170       \----------|----------|----------|----------|----------|----------|----------|---------*/
171
172   #define STV_VDP2_TVMD   (m_vdp2_regs[0x000/2])
173
174   #define STV_VDP2_DISP   ((STV_VDP2_TVMD & 0x8000) >> 15)
175   #define STV_VDP2_BDCLMD ((STV_VDP2_TVMD & 0x0100) >> 8)
176   #define STV_VDP2_LSMD   ((STV_VDP2_TVMD & 0x00c0) >> 6)
177   #define STV_VDP2_VRES   ((STV_VDP2_TVMD & 0x0030) >> 4)
178   #define STV_VDP2_HRES   ((STV_VDP2_TVMD & 0x0007) >> 0)
179
180/* 180002 - r/w - EXTEN - External Signal Enable Register
181 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
182       |    --    |    --    |    --    |    --    |    --    |    --    | EXLTEN   | EXSYEN   |
183       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
184       |    --    |    --    |    --    |    --    |    --    |    --    | DASEL    | EXBGEN   |
185       \----------|----------|----------|----------|----------|----------|----------|---------*/
186
187   #define STV_VDP2_EXTEN  (m_vdp2_regs[0x002/2])
188
189   #define STV_VDP2_EXLTEN ((STV_VDP2_EXTEN & 0x0200) >> 9)
190
191/* 180004 - r/o - TVSTAT - Screen Status
192 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
193       |    --    |    --    |    --    |    --    |    --    |    --    | EXLTFG   | EXSYFG   |
194       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
195       |    --    |    --    |    --    |    --    | VBLANK   | HBLANK   | ODD      | EVEN     |
196       \----------|----------|----------|----------|----------|----------|----------|---------*/
197
198/* 180006 - r/w - VRSIZE - VRAM Size
199 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
200       | VRAMSZ   |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
201       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
202       |    --    |    --    |    --    |    --    | VER3     | VER2     | VER1     | VER0     |
203       \----------|----------|----------|----------|----------|----------|----------|---------*/
204
205   #define STV_VDP2_VRSIZE (m_vdp2_regs[0x006/2])
206
207   #define STV_VDP2_VRAMSZ ((STV_VDP2_VRSIZE & 0x8000) >> 15)
208
209/* 180008 - r/o - HCNT - H-Counter
210 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
211       |    --    |    --    |    --    |    --    |    --    |    --    | HCT9     | HCT8     |
212       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
213       | HCT7     | HCT6     | HCT5     | HCT4     | HCT3     | HCT2     | HCT1     | HCT0     |
214       \----------|----------|----------|----------|----------|----------|----------|---------*/
215
216   #define STV_VDP2_HCNT (m_vdp2_regs[0x008/2])
217
218/* 18000A - r/o - VCNT - V-Counter
219 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
220       |    --    |    --    |    --    |    --    |    --    |    --    | VCT9     | VCT8     |
221       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
222       | VCT7     | VCT6     | VCT5     | VCT4     | VCT3     | VCT2     | VCT1     | VCT0     |
223       \----------|----------|----------|----------|----------|----------|----------|---------*/
224
225   #define STV_VDP2_VCNT (m_vdp2_regs[0x00a/2])
226
227/* 18000C - RESERVED
228 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
229       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
230       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
231       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
232       \----------|----------|----------|----------|----------|----------|----------|---------*/
233
234/* 18000E - r/w - RAMCTL - RAM Control
235 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
236       |  CRKTE   |    --    | CRMD1    | CRMD0    |    --    |    --    | VRBMD    | VRAMD    |
237       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
238       | RDBSB11  | RDBSB10  | RDBSB01  | RDBSB00  | RDBSA11  | RDBSA10  | RDBSA01  | RDBSA00  |
239       \----------|----------|----------|----------|----------|----------|----------|---------*/
240
241   #define STV_VDP2_RAMCTL (m_vdp2_regs[0x00e/2])
242
243   #define STV_VDP2_CRKTE ((STV_VDP2_RAMCTL & 0x8000) >> 15)
244   #define STV_VDP2_CRMD  ((STV_VDP2_RAMCTL & 0x3000) >> 12)
245   #define STV_VDP2_RDBSB1 ((STV_VDP2_RAMCTL & 0x00c0) >> 6)
246   #define STV_VDP2_RDBSB0 ((STV_VDP2_RAMCTL & 0x0030) >> 4)
247   #define STV_VDP2_RDBSA1 ((STV_VDP2_RAMCTL & 0x000c) >> 2)
248   #define STV_VDP2_RDBSA0 ((STV_VDP2_RAMCTL & 0x0003) >> 0)
249
250
251/* 180010 - r/w - -CYCA0L - VRAM CYCLE PATTERN (BANK A0)
252 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
253       | VCP0A03  | VCP0A02  | VCP0A01  | VCP0A00  | VCP1A03  | VCP1A02  | VCP1A01  | VCP1A00  |
254       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
255       | VCP2A03  | VCP2A02  | VCP2A01  | VCP2A00  | VCP3A03  | VCP3A02  | VCP3A01  | VCP3A00  |
256       \----------|----------|----------|----------|----------|----------|----------|---------*/
257
258   #define STV_VDP2_CYCA0L (m_vdp2_regs[0x010/2])
259
260/* 180012 - r/w - -CYCA0U - VRAM CYCLE PATTERN (BANK A0)
261 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
262       | VCP4A03  | VCP4A02  | VCP4A01  | VCP4A00  | VCP5A03  | VCP5A02  | VCP5A01  | VCP5A00  |
263       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
264       | VCP6A03  | VCP6A02  | VCP6A01  | VCP6A00  | VCP7A03  | VCP7A02  | VCP7A01  | VCP7A00  |
265       \----------|----------|----------|----------|----------|----------|----------|---------*/
266
267   #define STV_VDP2_CYCA0U (m_vdp2_regs[0x012/2])
268
269/* 180014 - r/w - -CYCA1L - VRAM CYCLE PATTERN (BANK A1)
270 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
271       | VCP0A13  | VCP0A12  | VCP0A11  | VCP0A10  | VCP1A13  | VCP1A12  | VCP1A11  | VCP1A10  |
272       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
273       | VCP2A13  | VCP2A12  | VCP2A11  | VCP2A10  | VCP3A13  | VCP3A12  | VCP3A11  | VCP3A10  |
274       \----------|----------|----------|----------|----------|----------|----------|---------*/
275
276   #define STV_VDP2_CYCA1L (m_vdp2_regs[0x014/2])
277
278/* 180016 - r/w - -CYCA1U - VRAM CYCLE PATTERN (BANK A1)
279 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
280       | VCP4A13  | VCP4A12  | VCP4A11  | VCP4A10  | VCP5A13  | VCP5A12  | VCP5A11  | VCP5A10  |
281       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
282       | VCP6A13  | VCP6A12  | VCP6A11  | VCP6A10  | VCP7A13  | VCP7A12  | VCP7A11  | VCP7A10  |
283       \----------|----------|----------|----------|----------|----------|----------|---------*/
284
285   #define STV_VDP2_CYCA1U (m_vdp2_regs[0x016/2])
286
287/* 180018 - r/w - -CYCB0L - VRAM CYCLE PATTERN (BANK B0)
288 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
289       | VCP0B03  | VCP0B02  | VCP0B01  | VCP0B00  | VCP1B03  | VCP1B02  | VCP1B01  | VCP1B00  |
290       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
291       | VCP2B03  | VCP2B02  | VCP2B01  | VCP2B00  | VCP3B03  | VCP3B02  | VCP3B01  | VCP3B00  |
292       \----------|----------|----------|----------|----------|----------|----------|---------*/
293
294   #define STV_VDP2_CYCA2L (m_vdp2_regs[0x018/2])
295
296/* 18001A - r/w - -CYCB0U - VRAM CYCLE PATTERN (BANK B0)
297 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
298       | VCP4B03  | VCP4B02  | VCP4B01  | VCP4B00  | VCP5B03  | VCP5B02  | VCP5B01  | VCP5B00  |
299       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
300       | VCP6B03  | VCP6B02  | VCP6B01  | VCP6B00  | VCP7B03  | VCP7B02  | VCP7B01  | VCP7B00  |
301       \----------|----------|----------|----------|----------|----------|----------|---------*/
302
303   #define STV_VDP2_CYCA2U (m_vdp2_regs[0x01a/2])
304
305/* 18001C - r/w - -CYCB1L - VRAM CYCLE PATTERN (BANK B1)
306 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
307       | VCP0B13  | VCP0B12  | VCP0B11  | VCP0B10  | VCP1B13  | VCP1B12  | VCP1B11  | VCP1B10  |
308       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
309       | VCP2B13  | VCP2B12  | VCP2B11  | VCP2B10  | VCP3B13  | VCP3B12  | VCP3B11  | VCP3B10  |
310       \----------|----------|----------|----------|----------|----------|----------|---------*/
311
312   #define STV_VDP2_CYCA3L (m_vdp2_regs[0x01c/2])
313
314/* 18001E - r/w - -CYCB1U - VRAM CYCLE PATTERN (BANK B1)
315 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
316       | VCP4B13  | VCP4B12  | VCP4B11  | VCP4B10  | VCP5B13  | VCP5B12  | VCP5B11  | VCP5B10  |
317       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
318       | VCP6B13  | VCP6B12  | VCP6B11  | VCP6B10  | VCP7B13  | VCP7B12  | VCP7B11  | VCP7B10  |
319       \----------|----------|----------|----------|----------|----------|----------|---------*/
320
321   #define STV_VDP2_CYCA3U (m_vdp2_regs[0x01e/2])
322
323/* 180020 - r/w - BGON - SCREEN DISPLAY ENABLE
324
325 this register allows each tilemap to be enabled or disabled and also which layers are solid
326
327 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
328       |    --    |    --    |    --    | R0TPON   | N3TPON   | N2TPON   | N1TPON   | N0TPON   |
329       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
330       |    --    |    --    | R1ON     | R0ON     | N3ON     | N2ON     | N1ON     | N0ON     |
331       \----------|----------|----------|----------|----------|----------|----------|---------*/
332
333   #define STV_VDP2_BGON (m_vdp2_regs[0x020/2])
334
335   // NxOn - Layer Enable Register
336   #define STV_VDP2_xxON ((STV_VDP2_BGON & 0x001f) >> 0) /* to see if anything is enabled */
337
338   #define STV_VDP2_N0ON ((STV_VDP2_BGON & 0x0001) >> 0) /* N0On = NBG0 Enable */
339   #define STV_VDP2_N1ON ((STV_VDP2_BGON & 0x0002) >> 1) /* N1On = NBG1 Enable */
340   #define STV_VDP2_N2ON ((STV_VDP2_BGON & 0x0004) >> 2) /* N2On = NBG2 Enable */
341   #define STV_VDP2_N3ON ((STV_VDP2_BGON & 0x0008) >> 3) /* N3On = NBG3 Enable */
342   #define STV_VDP2_R0ON ((STV_VDP2_BGON & 0x0010) >> 4) /* R0On = RBG0 Enable */
343   #define STV_VDP2_R1ON ((STV_VDP2_BGON & 0x0020) >> 5) /* R1On = RBG1 Enable */
344
345   // NxTPON - Transparency Pen Enable Registers
346   #define STV_VDP2_N0TPON ((STV_VDP2_BGON & 0x0100) >> 8) /*  N0TPON = NBG0 Draw Transparent Pen (as solid) /or/ RBG1 Draw Transparent Pen */
347   #define STV_VDP2_N1TPON ((STV_VDP2_BGON & 0x0200) >> 9) /*  N1TPON = NBG1 Draw Transparent Pen (as solid) /or/ EXBG Draw Transparent Pen */
348   #define STV_VDP2_N2TPON ((STV_VDP2_BGON & 0x0400) >> 10)/*  N2TPON = NBG2 Draw Transparent Pen (as solid) */
349   #define STV_VDP2_N3TPON ((STV_VDP2_BGON & 0x0800) >> 11)/*  N3TPON = NBG3 Draw Transparent Pen (as solid) */
350   #define STV_VDP2_R0TPON ((STV_VDP2_BGON & 0x1000) >> 12)/*  R0TPON = RBG0 Draw Transparent Pen (as solid) */
351
352/*
353180022 - MZCTL - Mosaic Control
354bit->  /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
355       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
356       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
357       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
358       \----------|----------|----------|----------|----------|----------|----------|---------*/
359
360   #define STV_VDP2_MZCTL (m_vdp2_regs[0x022/2])
361
362   #define STV_VDP2_MZSZV ((STV_VDP2_MZCTL & 0xf000) >> 12)
363   #define STV_VDP2_MZSZH ((STV_VDP2_MZCTL & 0x0f00) >> 8)
364   #define STV_VDP2_R0MZE ((STV_VDP2_MZCTL & 0x0010) >> 4)
365   #define STV_VDP2_N3MZE ((STV_VDP2_MZCTL & 0x0008) >> 3)
366   #define STV_VDP2_N2MZE ((STV_VDP2_MZCTL & 0x0004) >> 2)
367   #define STV_VDP2_N1MZE ((STV_VDP2_MZCTL & 0x0002) >> 1)
368   #define STV_VDP2_N0MZE ((STV_VDP2_MZCTL & 0x0001) >> 0)
369
370/*180024 - Special Function Code Select
371
372*/
373
374   #define STV_VDP2_SFSEL (m_vdp2_regs[0x024/2])
375
376/*180026 - Special Function Code
377
378*/
379
380   #define STV_VDP2_SFCODE (m_vdp2_regs[0x026/2])
381
382
383/*
384180028 - CHCTLA - Character Control (NBG0, NBG1)
385 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
386       |    --    |    --    | N1CHCN1  | N1CHCN0  | N1BMSZ1  | N1BMSZ0  | N1BMEN   | N1CHSZ   |
387       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
388       |    --    | N0CHCN2  | N0CHCN1  | N0CHCN0  | N0BMSZ1  | N0BMSZ0  | N0BMEN   | N0CHSZ   |
389       \----------|----------|----------|----------|----------|----------|----------|---------*/
390
391   #define STV_VDP2_CHCTLA (m_vdp2_regs[0x028/2])
392
393/* -------------------------- NBG0 Character Control Registers -------------------------- */
394
395/*  N0CHCNx  NBG0 (or RGB1) Colour Depth
396    000 - 16 Colours
397    001 - 256 Colours
398    010 - 2048 Colours
399    011 - 32768 Colours (RGB5)
400    100 - 16770000 Colours (RGB8)
401    101 - invalid
402    110 - invalid
403    111 - invalid   */
404   #define STV_VDP2_N0CHCN ((STV_VDP2_CHCTLA & 0x0070) >> 4)
405
406/*  N0BMSZx - NBG0 Bitmap Size *guessed*
407    00 - 512 x 256
408    01 - 512 x 512
409    10 - 1024 x 256
410    11 - 1024 x 512   */
411   #define STV_VDP2_N0BMSZ ((STV_VDP2_CHCTLA & 0x000c) >> 2)
412
413/*  N0BMEN - NBG0 Bitmap Enable
414    0 - use cell mode
415    1 - use bitmap mode   */
416   #define STV_VDP2_N0BMEN ((STV_VDP2_CHCTLA & 0x0002) >> 1)
417
418/*  N0CHSZ - NBG0 Character (Tile) Size
419    0 - 1 cell  x 1 cell  (8x8)
420    1 - 2 cells x 2 cells (16x16)  */
421   #define STV_VDP2_N0CHSZ ((STV_VDP2_CHCTLA & 0x0001) >> 0)
422
423/* -------------------------- NBG1 Character Control Registers -------------------------- */
424
425/*  N1CHCNx - NBG1 (or EXB1) Colour Depth
426    00 - 16 Colours
427    01 - 256 Colours
428    10 - 2048 Colours
429    11 - 32768 Colours (RGB5)  */
430   #define STV_VDP2_N1CHCN ((STV_VDP2_CHCTLA & 0x3000) >> 12)
431
432/*  N1BMSZx - NBG1 Bitmap Size *guessed*
433    00 - 512 x 256
434    01 - 512 x 512
435    10 - 1024 x 256
436    11 - 1024 x 512   */
437   #define STV_VDP2_N1BMSZ ((STV_VDP2_CHCTLA & 0x0c00) >> 10)
438
439/*  N1BMEN - NBG1 Bitmap Enable
440    0 - use cell mode
441    1 - use bitmap mode   */
442   #define STV_VDP2_N1BMEN ((STV_VDP2_CHCTLA & 0x0200) >> 9)
443
444/*  N1CHSZ - NBG1 Character (Tile) Size
445    0 - 1 cell  x 1 cell  (8x8)
446    1 - 2 cells x 2 cells (16x16)  */
447   #define STV_VDP2_N1CHSZ ((STV_VDP2_CHCTLA & 0x0100) >> 8)
448
449/*
45018002A - CHCTLB - Character Control (NBG2, NBG1, RBG0)
451 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
452       |    --    | R0CHCN2  | R0CHCN1  | R0CHCN0  |    --    | R0BMSZ   | R0BMEN   | R0CHSZ   |
453       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
454       |    --    |    --    | N3CHCN   | N3CHSZ   |    --    |    --    | N2CHCN   | N2CHSZ   |
455       \----------|----------|----------|----------|----------|----------|----------|---------*/
456
457   #define STV_VDP2_CHCTLB (m_vdp2_regs[0x02a/2])
458
459/* -------------------------- RBG0 Character Control Registers -------------------------- */
460
461
462/*  R0CHCNx  RBG0  Colour Depth
463    000 - 16 Colours
464    001 - 256 Colours
465    010 - 2048 Colours
466    011 - 32768 Colours (RGB5)
467    100 - 16770000 Colours (RGB8)
468    101 - invalid
469    110 - invalid
470    111 - invalid   */
471   #define STV_VDP2_R0CHCN ((STV_VDP2_CHCTLB & 0x7000) >> 12)
472
473/*  R0BMSZx - RBG0 Bitmap Size *guessed*
474    00 - 512 x 256
475    01 - 512 x 512  */
476   #define STV_VDP2_R0BMSZ ((STV_VDP2_CHCTLB & 0x0400) >> 10)
477
478/*  R0BMEN - RBG0 Bitmap Enable
479    0 - use cell mode
480    1 - use bitmap mode   */
481   #define STV_VDP2_R0BMEN ((STV_VDP2_CHCTLB & 0x0200) >> 9)
482
483/*  R0CHSZ - RBG0 Character (Tile) Size
484    0 - 1 cell  x 1 cell  (8x8)
485    1 - 2 cells x 2 cells (16x16)  */
486   #define STV_VDP2_R0CHSZ ((STV_VDP2_CHCTLB & 0x0100) >> 8)
487
488   #define STV_VDP2_N3CHCN ((STV_VDP2_CHCTLB & 0x0020) >> 5)
489   #define STV_VDP2_N3CHSZ ((STV_VDP2_CHCTLB & 0x0010) >> 4)
490   #define STV_VDP2_N2CHCN ((STV_VDP2_CHCTLB & 0x0002) >> 1)
491   #define STV_VDP2_N2CHSZ ((STV_VDP2_CHCTLB & 0x0001) >> 0)
492
493
494/*
49518002C - BMPNA - Bitmap Palette Number (NBG0, NBG1)
496 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
497       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
498       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
499       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
500       \----------|----------|----------|----------|----------|----------|----------|---------*/
501
502   #define STV_VDP2_BMPNA (m_vdp2_regs[0x02c/2])
503
504   #define STV_VDP2_N1BMP ((STV_VDP2_BMPNA & 0x0700) >> 8)
505   #define STV_VDP2_N0BMP ((STV_VDP2_BMPNA & 0x0007) >> 0)
506
507/* 18002E - Bitmap Palette Number (RBG0)
508 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
509       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
510       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
511       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
512       \----------|----------|----------|----------|----------|----------|----------|---------*/
513
514   #define STV_VDP2_BMPNB (m_vdp2_regs[0x02e/2])
515
516   #define STV_VDP2_R0BMP ((STV_VDP2_BMPNB & 0x0007) >> 0)
517
518/* 180030 - PNCN0 - Pattern Name Control (NBG0)
519 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
520       | N0PNB    | N0CNSM   |    --    |    --    |    --    |    --    | N0SPR    | N0SCC    |
521       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
522       | N0SPLT6  | N0SPLT5  | N0SPLT4  | N0SPCN4  | N0SPCN3  | N0SPCN2  | N0SPCN1  | N0SPCN0  |
523       \----------|----------|----------|----------|----------|----------|----------|---------*/
524
525   #define STV_VDP2_PNCN0 (m_vdp2_regs[0x030/2])
526
527/*  Pattern Data Size
528    0 = 2 bytes
529    1 = 1 byte */
530   #define STV_VDP2_N0PNB  ((STV_VDP2_PNCN0 & 0x8000) >> 15)
531
532/*  Character Number Supplement (in 1 byte mode)
533    0 = Character Number = 10bits + 2bits for flip
534    1 = Character Number = 12 bits, no flip  */
535   #define STV_VDP2_N0CNSM ((STV_VDP2_PNCN0 & 0x4000) >> 14)
536
537/*  NBG0 Special Priority Register (in 1 byte mode) */
538   #define STV_VDP2_N0SPR ((STV_VDP2_PNCN0 & 0x0200) >> 9)
539
540/*  NBG0 Special Colour Control Register (in 1 byte mode) */
541   #define STV_VDP2_N0SCC ((STV_VDP2_PNCN0 & 0x0100) >> 8)
542
543/*  Supplementary Palette Bits (in 1 byte mode) */
544   #define STV_VDP2_N0SPLT ((STV_VDP2_PNCN0 & 0x00e0) >> 5)
545
546/*  Supplementary Character Bits (in 1 byte mode) */
547   #define STV_VDP2_N0SPCN ((STV_VDP2_PNCN0 & 0x001f) >> 0)
548
549/* 180032 - Pattern Name Control (NBG1)
550 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
551       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
552       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
553       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
554       \----------|----------|----------|----------|----------|----------|----------|---------*/
555
556   #define STV_VDP2_PNCN1 (m_vdp2_regs[0x032/2])
557
558/*  Pattern Data Size
559    0 = 2 bytes
560    1 = 1 byte */
561   #define STV_VDP2_N1PNB  ((STV_VDP2_PNCN1 & 0x8000) >> 15)
562
563/*  Character Number Supplement (in 1 byte mode)
564    0 = Character Number = 10bits + 2bits for flip
565    1 = Character Number = 12 bits, no flip  */
566   #define STV_VDP2_N1CNSM ((STV_VDP2_PNCN1 & 0x4000) >> 14)
567
568/*  NBG0 Special Priority Register (in 1 byte mode) */
569   #define STV_VDP2_N1SPR ((STV_VDP2_PNCN1 & 0x0200) >> 9)
570
571/*  NBG0 Special Colour Control Register (in 1 byte mode) */
572   #define STV_VDP2_N1SCC ((STV_VDP2_PNCN1 & 0x0100) >> 8)
573
574/*  Supplementary Palette Bits (in 1 byte mode) */
575   #define STV_VDP2_N1SPLT ((STV_VDP2_PNCN1 & 0x00e0) >> 5)
576
577/*  Supplementary Character Bits (in 1 byte mode) */
578   #define STV_VDP2_N1SPCN ((STV_VDP2_PNCN1 & 0x001f) >> 0)
579
580
581/* 180034 - Pattern Name Control (NBG2)
582 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
583       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
584       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
585       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
586       \----------|----------|----------|----------|----------|----------|----------|---------*/
587
588   #define STV_VDP2_PNCN2 (m_vdp2_regs[0x034/2])
589
590/*  Pattern Data Size
591    0 = 2 bytes
592    1 = 1 byte */
593   #define STV_VDP2_N2PNB  ((STV_VDP2_PNCN2 & 0x8000) >> 15)
594
595/*  Character Number Supplement (in 1 byte mode)
596    0 = Character Number = 10bits + 2bits for flip
597    1 = Character Number = 12 bits, no flip  */
598   #define STV_VDP2_N2CNSM ((STV_VDP2_PNCN2 & 0x4000) >> 14)
599
600/*  NBG0 Special Priority Register (in 1 byte mode) */
601   #define STV_VDP2_N2SPR ((STV_VDP2_PNCN2 & 0x0200) >> 9)
602
603/*  NBG0 Special Colour Control Register (in 1 byte mode) */
604   #define STV_VDP2_N2SCC ((STV_VDP2_PNCN2 & 0x0100) >> 8)
605
606/*  Supplementary Palette Bits (in 1 byte mode) */
607   #define STV_VDP2_N2SPLT ((STV_VDP2_PNCN2 & 0x00e0) >> 5)
608
609/*  Supplementary Character Bits (in 1 byte mode) */
610   #define STV_VDP2_N2SPCN ((STV_VDP2_PNCN2 & 0x001f) >> 0)
611
612
613/* 180036 - Pattern Name Control (NBG3)
614 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
615       | N3PNB    | N3CNSM   |    --    |    --    |    --    |    --    | N3SPR    | N3SCC    |
616       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
617       | N3SPLT6  | N3SPLT5  | N3SPLT4  | N3SPCN4  | N3SPCN3  | N3SPCN2  | N3SPCN1  | N3SPCN0  |
618       \----------|----------|----------|----------|----------|----------|----------|---------*/
619
620   #define STV_VDP2_PNCN3 (m_vdp2_regs[0x036/2])
621
622/*  Pattern Data Size
623    0 = 2 bytes
624    1 = 1 byte */
625   #define STV_VDP2_N3PNB  ((STV_VDP2_PNCN3 & 0x8000) >> 15)
626
627/*  Character Number Supplement (in 1 byte mode)
628    0 = Character Number = 10bits + 2bits for flip
629    1 = Character Number = 12 bits, no flip  */
630   #define STV_VDP2_N3CNSM ((STV_VDP2_PNCN3 & 0x4000) >> 14)
631
632/*  NBG0 Special Priority Register (in 1 byte mode) */
633   #define STV_VDP2_N3SPR ((STV_VDP2_PNCN3 & 0x0200) >> 9)
634
635/*  NBG0 Special Colour Control Register (in 1 byte mode) */
636   #define STV_VDP2_N3SCC ((STV_VDP2_PNCN3 & 0x0100) >> 8)
637
638/*  Supplementary Palette Bits (in 1 byte mode) */
639   #define STV_VDP2_N3SPLT ((STV_VDP2_PNCN3 & 0x00e0) >> 5)
640
641/*  Supplementary Character Bits (in 1 byte mode) */
642   #define STV_VDP2_N3SPCN ((STV_VDP2_PNCN3 & 0x001f) >> 0)
643
644
645/* 180038 - Pattern Name Control (RBG0)
646 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
647       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
648       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
649       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
650       \----------|----------|----------|----------|----------|----------|----------|---------*/
651
652   #define STV_VDP2_PNCR (m_vdp2_regs[0x038/2])
653
654/*  Pattern Data Size
655    0 = 2 bytes
656    1 = 1 byte */
657   #define STV_VDP2_R0PNB  ((STV_VDP2_PNCR & 0x8000) >> 15)
658
659/*  Character Number Supplement (in 1 byte mode)
660    0 = Character Number = 10bits + 2bits for flip
661    1 = Character Number = 12 bits, no flip  */
662   #define STV_VDP2_R0CNSM ((STV_VDP2_PNCR & 0x4000) >> 14)
663
664/*  NBG0 Special Priority Register (in 1 byte mode) */
665   #define STV_VDP2_R0SPR ((STV_VDP2_PNCR & 0x0200) >> 9)
666
667/*  NBG0 Special Colour Control Register (in 1 byte mode) */
668   #define STV_VDP2_R0SCC ((STV_VDP2_PNCR & 0x0100) >> 8)
669
670/*  Supplementary Palette Bits (in 1 byte mode) */
671   #define STV_VDP2_R0SPLT ((STV_VDP2_PNCR & 0x00e0) >> 5)
672
673/*  Supplementary Character Bits (in 1 byte mode) */
674   #define STV_VDP2_R0SPCN ((STV_VDP2_PNCR & 0x001f) >> 0)
675
676/* 18003A - PLSZ - Plane Size
677 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
678       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
679       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
680       | N3PLSZ1  | N3PLSZ0  |    --    |    --    | N1PLSZ1  | N1PLSZ0  | N0PLSZ1  | N0PLSZ0  |
681       \----------|----------|----------|----------|----------|----------|----------|---------*/
682
683   #define STV_VDP2_PLSZ (m_vdp2_regs[0x03a/2])
684
685   /* NBG0 Plane Size
686   00 1H Page x 1V Page
687   01 2H Pages x 1V Page
688   10 invalid
689   11 2H Pages x 2V Pages  */
690   #define STV_VDP2_RBOVR  ((STV_VDP2_PLSZ & 0xc000) >> 14)
691   #define STV_VDP2_RBPLSZ ((STV_VDP2_PLSZ & 0x3000) >> 12)
692   #define STV_VDP2_RAOVR  ((STV_VDP2_PLSZ & 0x0c00) >> 10)
693   #define STV_VDP2_RAPLSZ ((STV_VDP2_PLSZ & 0x0300) >> 8)
694   #define STV_VDP2_N3PLSZ ((STV_VDP2_PLSZ & 0x00c0) >> 6)
695   #define STV_VDP2_N2PLSZ ((STV_VDP2_PLSZ & 0x0030) >> 4)
696   #define STV_VDP2_N1PLSZ ((STV_VDP2_PLSZ & 0x000c) >> 2)
697   #define STV_VDP2_N0PLSZ ((STV_VDP2_PLSZ & 0x0003) >> 0)
698
699/* 18003C - MPOFN - Map Offset (NBG0, NBG1, NBG2, NBG3)
700 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
701       |    --    | N3MP8    | N3MP7    | N3MP6    |    --    | N2MP8    | N2MP7    | N2MP6    |
702       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
703       |    --    | N1MP8    | N1MP7    | N1MP6    |    --    | N0MP8    | N0MP7    | N0MP6    |
704       \----------|----------|----------|----------|----------|----------|----------|---------*/
705
706   #define STV_VDP2_MPOFN_ (m_vdp2_regs[0x03c/2])
707
708   /* Higher 3 bits of the map offset for each layer */
709   #define STV_VDP2_N3MP_ ((STV_VDP2_MPOFN_ & 0x3000) >> 12)
710   #define STV_VDP2_N2MP_ ((STV_VDP2_MPOFN_ & 0x0300) >> 8)
711   #define STV_VDP2_N1MP_ ((STV_VDP2_MPOFN_ & 0x0030) >> 4)
712   #define STV_VDP2_N0MP_ ((STV_VDP2_MPOFN_ & 0x0003) >> 0)
713
714
715
716
717/* 18003E - Map Offset (Rotation Parameter A,B)
718 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
719       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
720       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
721       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
722       \----------|----------|----------|----------|----------|----------|----------|---------*/
723
724   #define STV_VDP2_MPOFR_ (m_vdp2_regs[0x03e/2])
725
726   #define STV_VDP2_RBMP_ ((STV_VDP2_MPOFR_ & 0x0030) >> 4)
727   #define STV_VDP2_RAMP_ ((STV_VDP2_MPOFR_ & 0x0003) >> 0)
728
729/* 180040 - MPABN0 - Map (NBG0, Plane A,B)
730 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
731       |    --    |    --    | N0MPB5   | N0MPB4   | N0MPB3   | N0MPB2   | N0MPB1   | N0MPB0   |
732       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
733       |    --    |    --    | N0MPA5   | N0MPA4   | N0MPA3   | N0MPA2   | N0MPA1   | N0MPA0   |
734       \----------|----------|----------|----------|----------|----------|----------|---------*/
735
736   #define STV_VDP2_MPABN0 (m_vdp2_regs[0x040/2])
737
738   /* N0MPB5 = lower 6 bits of Map Address of Plane B of Tilemap NBG0 */
739   #define STV_VDP2_N0MPB ((STV_VDP2_MPABN0 & 0x3f00) >> 8)
740
741   /* N0MPA5 = lower 6 bits of Map Address of Plane A of Tilemap NBG0 */
742   #define STV_VDP2_N0MPA ((STV_VDP2_MPABN0 & 0x003f) >> 0)
743
744
745/* 180042 - MPCDN0 - (NBG0, Plane C,D)
746 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
747       |    --    |    --    | N0MPD5   | N0MPD4   | N0MPD3   | N0MPD2   | N0MPD1   | N0MPD0   |
748       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
749       |    --    |    --    | N0MPC5   | N0MPC4   | N0MPC3   | N0MPC2   | N0MPC1   | N0MPC0   |
750       \----------|----------|----------|----------|----------|----------|----------|---------*/
751
752   #define STV_VDP2_MPCDN0 (m_vdp2_regs[0x042/2])
753
754   /* N0MPB5 = lower 6 bits of Map Address of Plane D of Tilemap NBG0 */
755   #define STV_VDP2_N0MPD ((STV_VDP2_MPCDN0 & 0x3f00) >> 8)
756
757   /* N0MPA5 = lower 6 bits of Map Address of Plane C of Tilemap NBG0 */
758   #define STV_VDP2_N0MPC ((STV_VDP2_MPCDN0 & 0x003f) >> 0)
759
760
761/* 180044 - Map (NBG1, Plane A,B)
762 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
763       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
764       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
765       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
766       \----------|----------|----------|----------|----------|----------|----------|---------*/
767
768   #define STV_VDP2_MPABN1 (m_vdp2_regs[0x044/2])
769
770   /* N0MPB5 = lower 6 bits of Map Address of Plane B of Tilemap NBG1 */
771   #define STV_VDP2_N1MPB ((STV_VDP2_MPABN1 & 0x3f00) >> 8)
772
773   /* N0MPA5 = lower 6 bits of Map Address of Plane A of Tilemap NBG1 */
774   #define STV_VDP2_N1MPA ((STV_VDP2_MPABN1 & 0x003f) >> 0)
775
776/* 180046 - Map (NBG1, Plane C,D)
777 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
778       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
779       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
780       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
781       \----------|----------|----------|----------|----------|----------|----------|---------*/
782
783   #define STV_VDP2_MPCDN1 (m_vdp2_regs[0x046/2])
784
785   /* N0MPB5 = lower 6 bits of Map Address of Plane D of Tilemap NBG0 */
786   #define STV_VDP2_N1MPD ((STV_VDP2_MPCDN1 & 0x3f00) >> 8)
787
788   /* N0MPA5 = lower 6 bits of Map Address of Plane C of Tilemap NBG0 */
789   #define STV_VDP2_N1MPC ((STV_VDP2_MPCDN1 & 0x003f) >> 0)
790
791
792/* 180048 - Map (NBG2, Plane A,B)
793 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
794       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
795       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
796       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
797       \----------|----------|----------|----------|----------|----------|----------|---------*/
798
799   #define STV_VDP2_MPABN2 (m_vdp2_regs[0x048/2])
800
801   /* N0MPB5 = lower 6 bits of Map Address of Plane B of Tilemap NBG2 */
802   #define STV_VDP2_N2MPB ((STV_VDP2_MPABN2 & 0x3f00) >> 8)
803
804   /* N0MPA5 = lower 6 bits of Map Address of Plane A of Tilemap NBG2 */
805   #define STV_VDP2_N2MPA ((STV_VDP2_MPABN2 & 0x003f) >> 0)
806
807/* 18004a - Map (NBG2, Plane C,D)
808 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
809       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
810       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
811       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
812       \----------|----------|----------|----------|----------|----------|----------|---------*/
813
814   #define STV_VDP2_MPCDN2 (m_vdp2_regs[0x04a/2])
815
816   /* N0MPB5 = lower 6 bits of Map Address of Plane D of Tilemap NBG2 */
817   #define STV_VDP2_N2MPD ((STV_VDP2_MPCDN2 & 0x3f00) >> 8)
818
819   /* N0MPA5 = lower 6 bits of Map Address of Plane C of Tilemap NBG2 */
820   #define STV_VDP2_N2MPC ((STV_VDP2_MPCDN2 & 0x003f) >> 0)
821
822/* 18004c - Map (NBG3, Plane A,B)
823 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
824       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
825       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
826       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
827       \----------|----------|----------|----------|----------|----------|----------|---------*/
828
829   #define STV_VDP2_MPABN3 (m_vdp2_regs[0x04c/2])
830
831   /* N0MPB5 = lower 6 bits of Map Address of Plane B of Tilemap NBG1 */
832   #define STV_VDP2_N3MPB ((STV_VDP2_MPABN3 & 0x3f00) >> 8)
833
834   /* N0MPA5 = lower 6 bits of Map Address of Plane A of Tilemap NBG1 */
835   #define STV_VDP2_N3MPA ((STV_VDP2_MPABN3 & 0x003f) >> 0)
836
837
838/* 18004e - Map (NBG3, Plane C,D)
839 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
840       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
841       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
842       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
843       \----------|----------|----------|----------|----------|----------|----------|---------*/
844
845   #define STV_VDP2_MPCDN3 (m_vdp2_regs[0x04e/2])
846
847   /* N0MPB5 = lower 6 bits of Map Address of Plane B of Tilemap NBG0 */
848   #define STV_VDP2_N3MPD ((STV_VDP2_MPCDN3 & 0x3f00) >> 8)
849
850   /* N0MPA5 = lower 6 bits of Map Address of Plane A of Tilemap NBG0 */
851   #define STV_VDP2_N3MPC ((STV_VDP2_MPCDN3 & 0x003f) >> 0)
852
853/* 180050 - Map (Rotation Parameter A, Plane A,B)
854 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
855       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
856       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
857       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
858       \----------|----------|----------|----------|----------|----------|----------|---------*/
859
860   #define STV_VDP2_MPABRA (m_vdp2_regs[0x050/2])
861
862   /* R0MPB5 = lower 6 bits of Map Address of Plane B of Tilemap RBG0 */
863   #define STV_VDP2_RAMPB ((STV_VDP2_MPABRA & 0x3f00) >> 8)
864
865   /* R0MPA5 = lower 6 bits of Map Address of Plane A of Tilemap RBG0 */
866   #define STV_VDP2_RAMPA ((STV_VDP2_MPABRA & 0x003f) >> 0)
867
868
869
870/* 180052 - Map (Rotation Parameter A, Plane C,D)
871 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
872       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
873       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
874       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
875       \----------|----------|----------|----------|----------|----------|----------|---------*/
876   #define STV_VDP2_MPCDRA (m_vdp2_regs[0x052/2])
877
878   /* R0MPB5 = lower 6 bits of Map Address of Plane D of Tilemap RBG0 */
879   #define STV_VDP2_RAMPD ((STV_VDP2_MPCDRA & 0x3f00) >> 8)
880
881   /* R0MPA5 = lower 6 bits of Map Address of Plane C of Tilemap RBG0 */
882   #define STV_VDP2_RAMPC ((STV_VDP2_MPCDRA & 0x003f) >> 0)
883
884/* 180054 - Map (Rotation Parameter A, Plane E,F)
885 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
886       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
887       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
888       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
889       \----------|----------|----------|----------|----------|----------|----------|---------*/
890   #define STV_VDP2_MPEFRA (m_vdp2_regs[0x054/2])
891
892   /* R0MPB5 = lower 6 bits of Map Address of Plane F of Tilemap RBG0 */
893   #define STV_VDP2_RAMPF ((STV_VDP2_MPEFRA & 0x3f00) >> 8)
894
895   /* R0MPA5 = lower 6 bits of Map Address of Plane E of Tilemap RBG0 */
896   #define STV_VDP2_RAMPE ((STV_VDP2_MPEFRA & 0x003f) >> 0)
897
898/* 180056 - Map (Rotation Parameter A, Plane G,H)
899 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
900       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
901       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
902       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
903       \----------|----------|----------|----------|----------|----------|----------|---------*/
904   #define STV_VDP2_MPGHRA (m_vdp2_regs[0x056/2])
905
906   /* R0MPB5 = lower 6 bits of Map Address of Plane H of Tilemap RBG0 */
907   #define STV_VDP2_RAMPH ((STV_VDP2_MPGHRA & 0x3f00) >> 8)
908
909   /* R0MPA5 = lower 6 bits of Map Address of Plane G of Tilemap RBG0 */
910   #define STV_VDP2_RAMPG ((STV_VDP2_MPGHRA & 0x003f) >> 0)
911
912/* 180058 - Map (Rotation Parameter A, Plane I,J)
913 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
914       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
915       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
916       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
917       \----------|----------|----------|----------|----------|----------|----------|---------*/
918   #define STV_VDP2_MPIJRA (m_vdp2_regs[0x058/2])
919
920   /* R0MPB5 = lower 6 bits of Map Address of Plane J of Tilemap RBG0 */
921   #define STV_VDP2_RAMPJ ((STV_VDP2_MPIJRA & 0x3f00) >> 8)
922
923   /* R0MPA5 = lower 6 bits of Map Address of Plane I of Tilemap RBG0 */
924   #define STV_VDP2_RAMPI ((STV_VDP2_MPIJRA & 0x003f) >> 0)
925
926/* 18005a - Map (Rotation Parameter A, Plane K,L)
927 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
928       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
929       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
930       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
931       \----------|----------|----------|----------|----------|----------|----------|---------*/
932   #define STV_VDP2_MPKLRA (m_vdp2_regs[0x05a/2])
933
934   /* R0MPB5 = lower 6 bits of Map Address of Plane L of Tilemap RBG0 */
935   #define STV_VDP2_RAMPL ((STV_VDP2_MPKLRA & 0x3f00) >> 8)
936
937   /* R0MPA5 = lower 6 bits of Map Address of Plane K of Tilemap RBG0 */
938   #define STV_VDP2_RAMPK ((STV_VDP2_MPKLRA & 0x003f) >> 0)
939
940/* 18005c - Map (Rotation Parameter A, Plane M,N)
941 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
942       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
943       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
944       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
945       \----------|----------|----------|----------|----------|----------|----------|---------*/
946   #define STV_VDP2_MPMNRA (m_vdp2_regs[0x05c/2])
947
948   /* R0MPB5 = lower 6 bits of Map Address of Plane N of Tilemap RBG0 */
949   #define STV_VDP2_RAMPN ((STV_VDP2_MPMNRA & 0x3f00) >> 8)
950
951   /* R0MPA5 = lower 6 bits of Map Address of Plane M of Tilemap RBG0 */
952   #define STV_VDP2_RAMPM ((STV_VDP2_MPMNRA & 0x003f) >> 0)
953
954/* 18005e - Map (Rotation Parameter A, Plane O,P)
955 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
956       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
957       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
958       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
959       \----------|----------|----------|----------|----------|----------|----------|---------*/
960   #define STV_VDP2_MPOPRA (m_vdp2_regs[0x05e/2])
961
962   /* R0MPB5 = lower 6 bits of Map Address of Plane P of Tilemap RBG0 */
963   #define STV_VDP2_RAMPP ((STV_VDP2_MPOPRA & 0x3f00) >> 8)
964
965   /* R0MPA5 = lower 6 bits of Map Address of Plane O of Tilemap RBG0 */
966   #define STV_VDP2_RAMPO ((STV_VDP2_MPOPRA & 0x003f) >> 0)
967
968/* 180060 - Map (Rotation Parameter B, Plane A,B)
969 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
970       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
971       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
972       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
973       \----------|----------|----------|----------|----------|----------|----------|---------*/
974
975   #define STV_VDP2_MPABRB (m_vdp2_regs[0x060/2])
976
977   /* R0MPB5 = lower 6 bits of Map Address of Plane B of Tilemap RBG0 */
978   #define STV_VDP2_RBMPB ((STV_VDP2_MPABRB & 0x3f00) >> 8)
979
980   /* R0MPA5 = lower 6 bits of Map Address of Plane A of Tilemap RBG0 */
981   #define STV_VDP2_RBMPA ((STV_VDP2_MPABRB & 0x003f) >> 0)
982
983
984/* 180062 - Map (Rotation Parameter B, Plane C,D)
985 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
986       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
987       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
988       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
989       \----------|----------|----------|----------|----------|----------|----------|---------*/
990
991   #define STV_VDP2_MPCDRB (m_vdp2_regs[0x062/2])
992
993   /* R0MPD5 = lower 6 bits of Map Address of Plane D of Tilemap RBG0 */
994   #define STV_VDP2_RBMPD ((STV_VDP2_MPCDRB & 0x3f00) >> 8)
995
996   /* R0MPc5 = lower 6 bits of Map Address of Plane C of Tilemap RBG0 */
997   #define STV_VDP2_RBMPC ((STV_VDP2_MPCDRB & 0x003f) >> 0)
998
999/* 180064 - Map (Rotation Parameter B, Plane E,F)
1000 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1001       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1002       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1003       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1004       \----------|----------|----------|----------|----------|----------|----------|---------*/
1005
1006   #define STV_VDP2_MPEFRB (m_vdp2_regs[0x064/2])
1007
1008   /* R0MPF5 = lower 6 bits of Map Address of Plane F of Tilemap RBG0 */
1009   #define STV_VDP2_RBMPF ((STV_VDP2_MPEFRB & 0x3f00) >> 8)
1010
1011   /* R0MPE5 = lower 6 bits of Map Address of Plane E of Tilemap RBG0 */
1012   #define STV_VDP2_RBMPE ((STV_VDP2_MPEFRB & 0x003f) >> 0)
1013
1014/* 180066 - Map (Rotation Parameter B, Plane G,H)
1015 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1016       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1017       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1018       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1019       \----------|----------|----------|----------|----------|----------|----------|---------*/
1020
1021   #define STV_VDP2_MPGHRB (m_vdp2_regs[0x066/2])
1022
1023   /* R0MPH5 = lower 6 bits of Map Address of Plane H of Tilemap RBG0 */
1024   #define STV_VDP2_RBMPH ((STV_VDP2_MPGHRB & 0x3f00) >> 8)
1025
1026   /* R0MPG5 = lower 6 bits of Map Address of Plane G of Tilemap RBG0 */
1027   #define STV_VDP2_RBMPG ((STV_VDP2_MPGHRB & 0x003f) >> 0)
1028
1029/* 180068 - Map (Rotation Parameter B, Plane I,J)
1030 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1031       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1032       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1033       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1034       \----------|----------|----------|----------|----------|----------|----------|---------*/
1035
1036   #define STV_VDP2_MPIJRB (m_vdp2_regs[0x068/2])
1037
1038   /* R0MPJ5 = lower 6 bits of Map Address of Plane J of Tilemap RBG0 */
1039   #define STV_VDP2_RBMPJ ((STV_VDP2_MPIJRB & 0x3f00) >> 8)
1040
1041   /* R0MPI5 = lower 6 bits of Map Address of Plane E of Tilemap RBG0 */
1042   #define STV_VDP2_RBMPI ((STV_VDP2_MPIJRB & 0x003f) >> 0)
1043
1044/* 18006a - Map (Rotation Parameter B, Plane K,L)
1045 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1046       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1047       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1048       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1049       \----------|----------|----------|----------|----------|----------|----------|---------*/
1050
1051   #define STV_VDP2_MPKLRB (m_vdp2_regs[0x06a/2])
1052
1053   /* R0MPL5 = lower 6 bits of Map Address of Plane L of Tilemap RBG0 */
1054   #define STV_VDP2_RBMPL ((STV_VDP2_MPKLRB & 0x3f00) >> 8)
1055
1056   /* R0MPK5 = lower 6 bits of Map Address of Plane K of Tilemap RBG0 */
1057   #define STV_VDP2_RBMPK ((STV_VDP2_MPKLRB & 0x003f) >> 0)
1058
1059/* 18006c - Map (Rotation Parameter B, Plane M,N)
1060 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1061       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1062       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1063       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1064       \----------|----------|----------|----------|----------|----------|----------|---------*/
1065
1066   #define STV_VDP2_MPMNRB (m_vdp2_regs[0x06c/2])
1067
1068   /* R0MPN5 = lower 6 bits of Map Address of Plane N of Tilemap RBG0 */
1069   #define STV_VDP2_RBMPN ((STV_VDP2_MPMNRB & 0x3f00) >> 8)
1070
1071   /* R0MPM5 = lower 6 bits of Map Address of Plane M of Tilemap RBG0 */
1072   #define STV_VDP2_RBMPM ((STV_VDP2_MPMNRB & 0x003f) >> 0)
1073
1074/* 18006e - Map (Rotation Parameter B, Plane O,P)
1075 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1076       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1077       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1078       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1079       \----------|----------|----------|----------|----------|----------|----------|---------*/
1080
1081   #define STV_VDP2_MPOPRB (m_vdp2_regs[0x06e/2])
1082
1083   /* R0MPP5 = lower 6 bits of Map Address of Plane P of Tilemap RBG0 */
1084   #define STV_VDP2_RBMPP ((STV_VDP2_MPOPRB & 0x3f00) >> 8)
1085
1086   /* R0MPO5 = lower 6 bits of Map Address of Plane O of Tilemap RBG0 */
1087   #define STV_VDP2_RBMPO ((STV_VDP2_MPOPRB & 0x003f) >> 0)
1088
1089/* 180070 - SCXIN0 - Screen Scroll (NBG0, Horizontal Integer Part)
1090 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1091       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1092       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1093       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1094       \----------|----------|----------|----------|----------|----------|----------|---------*/
1095
1096   #define STV_VDP2_SCXIN0 (m_vdp2_regs[0x070/2])
1097
1098
1099/* 180072 - Screen Scroll (NBG0, Horizontal Fractional Part)
1100 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1101       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1102       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1103       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1104       \----------|----------|----------|----------|----------|----------|----------|---------*/
1105
1106   #define STV_VDP2_SCXDN0 (m_vdp2_regs[0x072/2])
1107
1108/* 180074 - SCYIN0 - Screen Scroll (NBG0, Vertical Integer Part)
1109 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1110       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1111       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1112       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1113       \----------|----------|----------|----------|----------|----------|----------|---------*/
1114   #define STV_VDP2_SCYIN0 (m_vdp2_regs[0x074/2])
1115
1116
1117/* 180076 - Screen Scroll (NBG0, Vertical Fractional Part)
1118 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1119       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1120       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1121       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1122       \----------|----------|----------|----------|----------|----------|----------|---------*/
1123
1124   #define STV_VDP2_SCYDN0 (m_vdp2_regs[0x076/2])
1125
1126/* 180078 - Coordinate Inc (NBG0, Horizontal Integer Part)
1127 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1128       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1129       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1130       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1131       \----------|----------|----------|----------|----------|----------|----------|---------*/
1132
1133   #define STV_VDP2_ZMXIN0 (m_vdp2_regs[0x078/2])
1134
1135   #define STV_VDP2_N0ZMXI ((STV_VDP2_ZMXIN0 & 0x0007) >> 0)
1136
1137/* 18007a - Coordinate Inc (NBG0, Horizontal Fractional Part)
1138 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1139       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1140       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1141       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1142       \----------|----------|----------|----------|----------|----------|----------|---------*/
1143
1144   #define STV_VDP2_ZMXDN0 (m_vdp2_regs[0x07a/2])
1145
1146   #define STV_VDP2_N0ZMXD ((STV_VDP2_ZMXDN0 >> 8)& 0xff)
1147   #define STV_VDP2_ZMXN0  (((STV_VDP2_N0ZMXI<<16) | (STV_VDP2_N0ZMXD<<8))  & 0x0007ff00)
1148
1149
1150/* 18007c - Coordinate Inc (NBG0, Vertical Integer Part)
1151 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1152       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1153       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1154       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1155       \----------|----------|----------|----------|----------|----------|----------|---------*/
1156
1157   #define STV_VDP2_ZMYIN0 (m_vdp2_regs[0x07c/2])
1158
1159   #define STV_VDP2_N0ZMYI ((STV_VDP2_ZMYIN0 & 0x0007) >> 0)
1160
1161/* 18007e - Coordinate Inc (NBG0, Vertical Fractional Part)
1162 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1163       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1164       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1165       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1166       \----------|----------|----------|----------|----------|----------|----------|---------*/
1167
1168   #define STV_VDP2_ZMYDN0 (m_vdp2_regs[0x07e/2])
1169
1170   #define STV_VDP2_N0ZMYD ((STV_VDP2_ZMYDN0 >> 8)& 0xff)
1171   #define STV_VDP2_ZMYN0  (((STV_VDP2_N0ZMYI<<16) | (STV_VDP2_N0ZMYD<<8))  & 0x0007ff00)
1172
1173/* 180080 - SCXIN1 - Screen Scroll (NBG1, Horizontal Integer Part)
1174 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1175       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1176       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1177       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1178       \----------|----------|----------|----------|----------|----------|----------|---------*/
1179
1180   #define STV_VDP2_SCXIN1 (m_vdp2_regs[0x080/2])
1181
1182/* 180082 - Screen Scroll (NBG1, Horizontal Fractional Part)
1183 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1184       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1185       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1186       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1187       \----------|----------|----------|----------|----------|----------|----------|---------*/
1188
1189   #define STV_VDP2_SCXDN1 (m_vdp2_regs[0x082/2])
1190
1191/* 180084 - SCYIN1 - Screen Scroll (NBG1, Vertical Integer Part)
1192 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1193       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1194       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1195       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1196       \----------|----------|----------|----------|----------|----------|----------|---------*/
1197
1198   #define STV_VDP2_SCYIN1 (m_vdp2_regs[0x084/2])
1199
1200/* 180086 - Screen Scroll (NBG1, Vertical Fractional Part)
1201 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1202       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1203       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1204       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1205       \----------|----------|----------|----------|----------|----------|----------|---------*/
1206
1207   #define STV_VDP2_SCYDN1 (m_vdp2_regs[0x086/2])
1208
1209/* 180088 - Coordinate Inc (NBG1, Horizontal Integer Part)
1210 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1211       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1212       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1213       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1214       \----------|----------|----------|----------|----------|----------|----------|---------*/
1215
1216   #define STV_VDP2_ZMXIN1 (m_vdp2_regs[0x088/2])
1217
1218   #define STV_VDP2_N1ZMXI ((STV_VDP2_ZMXIN1 & 0x0007) >> 0)
1219
1220/* 18008a - Coordinate Inc (NBG1, Horizontal Fractional Part)
1221 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1222       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1223       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1224       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1225       \----------|----------|----------|----------|----------|----------|----------|---------*/
1226
1227   #define STV_VDP2_ZMXDN1 (m_vdp2_regs[0x08a/2])
1228
1229   #define STV_VDP2_N1ZMXD ((STV_VDP2_ZMXDN1 >> 8)& 0xff)
1230   #define STV_VDP2_ZMXN1  (((STV_VDP2_N1ZMXI<<16) | (STV_VDP2_N1ZMXD<<8)) & 0x0007ff00)
1231
1232/* 18008c - Coordinate Inc (NBG1, Vertical Integer Part)
1233 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1234       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1235       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1236       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1237       \----------|----------|----------|----------|----------|----------|----------|---------*/
1238
1239   #define STV_VDP2_ZMYIN1 (m_vdp2_regs[0x08c/2])
1240
1241   #define STV_VDP2_N1ZMYI ((STV_VDP2_ZMYIN1 & 0x0007) >> 0)
1242
1243/* 18008e - Coordinate Inc (NBG1, Vertical Fractional Part)
1244 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1245       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1246       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1247       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1248       \----------|----------|----------|----------|----------|----------|----------|---------*/
1249
1250   #define STV_VDP2_ZMYDN1 (m_vdp2_regs[0x08e/2])
1251
1252   #define STV_VDP2_N1ZMYD ((STV_VDP2_ZMYDN1 >> 8)& 0xff)
1253   #define STV_VDP2_ZMYN1  (((STV_VDP2_N1ZMYI<<16) | (STV_VDP2_N1ZMYD<<8)) & 0x007ff00)
1254
1255/* 180090 - SCXN2 - Screen Scroll (NBG2, Horizontal)
1256 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1257       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1258       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1259       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1260       \----------|----------|----------|----------|----------|----------|----------|---------*/
1261
1262   #define STV_VDP2_SCXN2 (m_vdp2_regs[0x090/2])
1263
1264/* 180092 - SCYN2 - Screen Scroll (NBG2, Vertical)
1265 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1266       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1267       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1268       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1269       \----------|----------|----------|----------|----------|----------|----------|---------*/
1270
1271   #define STV_VDP2_SCYN2 (m_vdp2_regs[0x092/2])
1272
1273/* 180094 - SCXN3 - Screen Scroll (NBG3, Horizontal)
1274 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1275       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1276       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1277       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1278       \----------|----------|----------|----------|----------|----------|----------|---------*/
1279
1280   #define STV_VDP2_SCXN3 (m_vdp2_regs[0x094/2])
1281
1282/* 180096 - SCYN3 - Screen Scroll (NBG3, Vertical)
1283 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1284       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1285       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1286       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1287       \----------|----------|----------|----------|----------|----------|----------|---------*/
1288
1289   #define STV_VDP2_SCYN3 (m_vdp2_regs[0x096/2])
1290
1291/* 180098 - Reduction Enable
1292 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1293       |    --    |    --    |    --    |    --    |    --    |    --    | N1ZMQT   | N1ZMHF   |
1294       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1295       |    --    |    --    |    --    |    --    |    --    |    --    | N0ZMQT   | N0ZMHF   |
1296       \----------|----------|----------|----------|----------|----------|----------|---------*/
1297
1298   #define STV_VDP2_ZMCTL (m_vdp2_regs[0x098/2])
1299
1300   #define STV_VDP2_N1ZMQT  ((STV_VDP2_ZMCTL & 0x0200) >> 9)
1301   #define STV_VDP2_N1ZMHF  ((STV_VDP2_ZMCTL & 0x0100) >> 8)
1302   #define STV_VDP2_N0ZMQT  ((STV_VDP2_ZMCTL & 0x0002) >> 1)
1303   #define STV_VDP2_N0ZMHF  ((STV_VDP2_ZMCTL & 0x0001) >> 0)
1304
1305/* 18009a - Line and Vertical Cell Scroll Control (NBG0, NBG1)
1306 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1307       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1308       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1309       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1310       \----------|----------|----------|----------|----------|----------|----------|---------*/
1311
1312   #define STV_VDP2_SCRCTL (m_vdp2_regs[0x09a/2])
1313
1314   #define STV_VDP2_N1LSS  ((STV_VDP2_SCRCTL & 0x3000) >> 12)
1315   #define STV_VDP2_N1LZMX ((STV_VDP2_SCRCTL & 0x0800) >> 11)
1316   #define STV_VDP2_N1LSCY ((STV_VDP2_SCRCTL & 0x0400) >> 10)
1317   #define STV_VDP2_N1LSCX ((STV_VDP2_SCRCTL & 0x0200) >> 9)
1318   #define STV_VDP2_N1VCSC ((STV_VDP2_SCRCTL & 0x0100) >> 8)
1319   #define STV_VDP2_N0LSS  ((STV_VDP2_SCRCTL & 0x0030) >> 4)
1320   #define STV_VDP2_N0LZMX ((STV_VDP2_SCRCTL & 0x0008) >> 3)
1321   #define STV_VDP2_N0LSCY ((STV_VDP2_SCRCTL & 0x0004) >> 2)
1322   #define STV_VDP2_N0LSCX ((STV_VDP2_SCRCTL & 0x0002) >> 1)
1323   #define STV_VDP2_N0VCSC ((STV_VDP2_SCRCTL & 0x0001) >> 0)
1324
1325/* 18009c - Vertical Cell Table Address (NBG0, NBG1)
1326 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1327       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1328       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1329       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1330       \----------|----------|----------|----------|----------|----------|----------|---------*/
1331
1332   #define STV_VDP2_VCSTAU (m_vdp2_regs[0x09c/2] & 7)
1333
1334
1335/* 18009e - Vertical Cell Table Address (NBG0, NBG1)
1336 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1337       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1338       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1339       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1340       \----------|----------|----------|----------|----------|----------|----------|---------*/
1341
1342   #define STV_VDP2_VCSTAL (m_vdp2_regs[0x09e/2])
1343
1344
1345/* 1800a0 - LSTA0U - Line Scroll Table Address (NBG0)
1346 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1347       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1348       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1349       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1350       \----------|----------|----------|----------|----------|----------|----------|---------*/
1351
1352   /*bit 2 unused when VRAM = 4 Mbits*/
1353   #define STV_VDP2_LSTA0U (m_vdp2_regs[0x0a0/2] & 7)
1354
1355/* 1800a2 - LSTA0L - Line Scroll Table Address (NBG0)
1356 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1357       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1358       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1359       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1360       \----------|----------|----------|----------|----------|----------|----------|---------*/
1361
1362   #define STV_VDP2_LSTA0L (m_vdp2_regs[0x0a2/2])
1363
1364/* 1800a4 - LSTA1U - Line Scroll Table Address (NBG1)
1365 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1366       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1367       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1368       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1369       \----------|----------|----------|----------|----------|----------|----------|---------*/
1370
1371   /*bit 2 unused when VRAM = 4 Mbits*/
1372   #define STV_VDP2_LSTA1U (m_vdp2_regs[0x0a4/2] & 7)
1373
1374/* 1800a6 - LSTA1L - Line Scroll Table Address (NBG1)
1375 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1376       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1377       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1378       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1379       \----------|----------|----------|----------|----------|----------|----------|---------*/
1380
1381   #define STV_VDP2_LSTA1L (m_vdp2_regs[0x0a6/2])
1382
1383/* 1800a8 - LCTAU - Line Colour Screen Table Address
1384 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1385       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1386       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1387       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1388       \----------|----------|----------|----------|----------|----------|----------|---------*/
1389
1390   #define STV_VDP2_LCTAU  (m_vdp2_regs[0x0a8/2])
1391   #define STV_VDP2_LCCLMD ((STV_VDP2_LCTAU & 0x8000) >> 15)
1392
1393/* 1800aa - LCTAL - Line Colour Screen Table Address
1394 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1395       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1396       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1397       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1398       \----------|----------|----------|----------|----------|----------|----------|---------*/
1399   #define STV_VDP2_LCTAL  (m_vdp2_regs[0x0aa/2])
1400
1401   #define STV_VDP2_LCTA   (((STV_VDP2_LCTAU & 0x0007) << 16) | (STV_VDP2_LCTAL & 0xffff))
1402
1403/* 1800ac - Back Screen Table Address
1404 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1405       |  BKCLMD  |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1406       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1407       |    --    |    --    |    --    |    --    |    --    |  BKTA18  |  BKTA17  |  BKTA16  |
1408       \----------|----------|----------|----------|----------|----------|----------|---------*/
1409
1410   #define STV_VDP2_BKTAU  (m_vdp2_regs[0x0ac/2])
1411
1412   #define STV_VDP2_BKCLMD ((STV_VDP2_BKTAU & 0x8000) >> 15)
1413
1414
1415/* 1800ae - Back Screen Table Address
1416 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1417       |  BKTA15  |  BKTA14  |  BKTA13  |  BKTA12  |  BKTA11  |  BKTA10  |  BKTA9   |  BKTA8   |
1418       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1419       |  BKTA7   |  BKTA7   |  BKTA6   |  BKTA5   |  BKTA4   |  BKTA3   |  BKTA2   |  BKTA0   |
1420       \----------|----------|----------|----------|----------|----------|----------|---------*/
1421
1422   #define STV_VDP2_BKTAL  (m_vdp2_regs[0x0ae/2])
1423
1424   #define STV_VDP2_BKTA   (((STV_VDP2_BKTAU & 0x0007) << 16) | (STV_VDP2_BKTAL & 0xffff))
1425
1426/* 1800b0 - RPMD - Rotation Parameter Mode
1427 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1428       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1429       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1430       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1431       \----------|----------|----------|----------|----------|----------|----------|---------*/
1432
1433   #define STV_VDP2_RPMD   ((m_vdp2_regs[0x0b0/2]) & 0x0003)
1434
1435/* 1800b2 - RPRCTL - Rotation Parameter Read Control
1436 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1437       |    --    |    --    |    --    |    --    |    --    | RBKASTRE | RBYSTRE  | RBXSTRE  |
1438       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1439       |    --    |    --    |    --    |    --    |    --    | RAKASTRE | RAYSTRE  | RBXSTRE  |
1440       \----------|----------|----------|----------|----------|----------|----------|---------*/
1441
1442   #define STV_VDP2_RPRCTL     (m_vdp2_regs[0x0b2/2])
1443   #define STV_VDP2_RBKASTRE   ((STV_VDP2_RPRCTL & 0x0400) >> 10)
1444   #define STV_VDP2_RBYSTRE    ((STV_VDP2_RPRCTL & 0x0200) >> 9)
1445   #define STV_VDP2_RBXSTRE    ((STV_VDP2_RPRCTL & 0x0100) >> 8)
1446   #define STV_VDP2_RAKASTRE   ((STV_VDP2_RPRCTL & 0x0004) >> 2)
1447   #define STV_VDP2_RAYSTRE    ((STV_VDP2_RPRCTL & 0x0002) >> 1)
1448   #define STV_VDP2_RAXSTRE    ((STV_VDP2_RPRCTL & 0x0001) >> 0)
1449
1450/* 1800b4 - KTCTL - Coefficient Table Control
1451 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1452       |    --    |    --    |    --    |  RBKLCE  |  RBKMD1  |  RBKMD0  |  RBKDBS  |   RBKTE  |
1453       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1454       |    --    |    --    |    --    |  RAKLCE  |  RAKMD1  |  RAKMD0  |  RAKDBS  |   RAKTE  |
1455       \----------|----------|----------|----------|----------|----------|----------|---------*/
1456
1457   #define STV_VDP2_KTCTL  (m_vdp2_regs[0x0b4/2])
1458   #define STV_VDP2_RBKLCE ((STV_VDP2_KTCTL & 0x1000) >> 12)
1459   #define STV_VDP2_RBKMD  ((STV_VDP2_KTCTL & 0x0c00) >> 10)
1460   #define STV_VDP2_RBKDBS ((STV_VDP2_KTCTL & 0x0200) >> 9)
1461   #define STV_VDP2_RBKTE  ((STV_VDP2_KTCTL & 0x0100) >> 8)
1462   #define STV_VDP2_RAKLCE ((STV_VDP2_KTCTL & 0x0010) >> 4)
1463   #define STV_VDP2_RAKMD  ((STV_VDP2_KTCTL & 0x000c) >> 2)
1464   #define STV_VDP2_RAKDBS ((STV_VDP2_KTCTL & 0x0002) >> 1)
1465   #define STV_VDP2_RAKTE  ((STV_VDP2_KTCTL & 0x0001) >> 0)
1466
1467/* 1800b6 - KTAOF - Coefficient Table Address Offset (Rotation Parameter A,B)
1468 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1469       |    --    |    --    |    --    |    --    |    --    | RBKTAOS2 | RBKTAOS1 | RBKTAOS0 |
1470       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1471       |    --    |    --    |    --    |    --    |    --    | RAKTAOS2 | RAKTAOS1 | RAKTAOS0 |
1472       \----------|----------|----------|----------|----------|----------|----------|---------*/
1473
1474   #define STV_VDP2_KTAOF  (m_vdp2_regs[0x0b6/2])
1475   #define STV_VDP2_RBKTAOS ((STV_VDP2_KTAOF & 0x0700) >> 8)
1476   #define STV_VDP2_RAKTAOS ((STV_VDP2_KTAOF & 0x0007) >> 0)
1477
1478/* 1800b8 - OVPNRA - Screen Over Pattern Name (Rotation Parameter A)
1479 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1480       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1481       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1482       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1483       \----------|----------|----------|----------|----------|----------|----------|---------*/
1484
1485   #define STV_VDP2_OVPNRA (m_vdp2_regs[0x0b8/2])
1486
1487/* 1800ba - Screen Over Pattern Name (Rotation Parameter B)
1488 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1489       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1490       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1491       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1492       \----------|----------|----------|----------|----------|----------|----------|---------*/
1493
1494   #define STV_VDP2_OVPNRB (m_vdp2_regs[0x0ba/2])
1495
1496/* 1800bc - RPTAU - Rotation Parameter Table Address (Rotation Parameter A,B)
1497 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1498       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1499       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1500       |    --    |    --    |    --    |    --    |    --    |  RPTA18  |  RPTA17  |  RPTA16  |
1501       \----------|----------|----------|----------|----------|----------|----------|---------*/
1502   #define STV_VDP2_RPTAU  (m_vdp2_regs[0x0bc/2] & 7)
1503
1504/* 1800be - RPTAL - Rotation Parameter Table Address (Rotation Parameter A,B)
1505 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1506       |  RPTA15  |  RPTA14  |  RPTA13  |  RPTA12  |  RPTA11  |  RPTA10  |   RPTA9  |   RPTA8  |
1507       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1508       |   RPTA7  |   RPTA6  |   RPTA5  |   RPTA4  |   RPTA3  |   RPTA2  |   RPTA1  |    --    |
1509       \----------|----------|----------|----------|----------|----------|----------|---------*/
1510
1511   #define STV_VDP2_RPTAL  (m_vdp2_regs[0x0be/2] & 0x0000ffff)
1512
1513/* 1800c0 - Window Position (W0, Horizontal Start Point)
1514 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1515       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1516       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1517       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1518       \----------|----------|----------|----------|----------|----------|----------|---------*/
1519
1520   #define STV_VDP2_WPSX0 (m_vdp2_regs[0x0c0/2])
1521
1522   #define STV_VDP2_W0SX ((STV_VDP2_WPSX0 & 0x03ff) >> 0)
1523
1524/* 1800c2 - Window Position (W0, Vertical Start Point)
1525 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1526       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1527       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1528       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1529       \----------|----------|----------|----------|----------|----------|----------|---------*/
1530
1531   #define STV_VDP2_WPSY0 (m_vdp2_regs[0x0c2/2])
1532
1533   #define STV_VDP2_W0SY ((STV_VDP2_WPSY0 & 0x03ff) >> 0)
1534
1535/* 1800c4 - Window Position (W0, Horizontal End Point)
1536 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1537       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1538       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1539       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1540       \----------|----------|----------|----------|----------|----------|----------|---------*/
1541
1542   #define STV_VDP2_WPEX0 (m_vdp2_regs[0x0c4/2])
1543
1544   #define STV_VDP2_W0EX ((STV_VDP2_WPEX0 & 0x03ff) >> 0)
1545
1546/* 1800c6 - Window Position (W0, Vertical End Point)
1547 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1548       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1549       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1550       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1551       \----------|----------|----------|----------|----------|----------|----------|---------*/
1552
1553   #define STV_VDP2_WPEY0 (m_vdp2_regs[0x0c6/2])
1554
1555   #define STV_VDP2_W0EY ((STV_VDP2_WPEY0 & 0x03ff) >> 0)
1556
1557/* 1800c8 - Window Position (W1, Horizontal Start Point)
1558 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1559       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1560       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1561       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1562       \----------|----------|----------|----------|----------|----------|----------|---------*/
1563
1564   #define STV_VDP2_WPSX1 (m_vdp2_regs[0x0c8/2])
1565
1566   #define STV_VDP2_W1SX ((STV_VDP2_WPSX1 & 0x03ff) >> 0)
1567
1568/* 1800ca - Window Position (W1, Vertical Start Point)
1569 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1570       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1571       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1572       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1573       \----------|----------|----------|----------|----------|----------|----------|---------*/
1574
1575   #define STV_VDP2_WPSY1 (m_vdp2_regs[0x0ca/2])
1576
1577   #define STV_VDP2_W1SY ((STV_VDP2_WPSY1 & 0x03ff) >> 0)
1578
1579/* 1800cc - Window Position (W1, Horizontal End Point)
1580 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1581       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1582       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1583       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1584       \----------|----------|----------|----------|----------|----------|----------|---------*/
1585
1586   #define STV_VDP2_WPEX1 (m_vdp2_regs[0x0cc/2])
1587
1588   #define STV_VDP2_W1EX ((STV_VDP2_WPEX1 & 0x03ff) >> 0)
1589
1590/* 1800ce - Window Position (W1, Vertical End Point)
1591 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1592       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1593       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1594       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1595       \----------|----------|----------|----------|----------|----------|----------|---------*/
1596
1597   #define STV_VDP2_WPEY1 (m_vdp2_regs[0x0ce/2])
1598
1599   #define STV_VDP2_W1EY ((STV_VDP2_WPEY1 & 0x03ff) >> 0)
1600
1601/* 1800d0 - Window Control (NBG0, NBG1)
1602 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1603       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1604       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1605       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1606       \----------|----------|----------|----------|----------|----------|----------|---------*/
1607
1608   #define STV_VDP2_WCTLA (m_vdp2_regs[0x0d0/2])
1609   #define STV_VDP2_N1LOG ((STV_VDP2_WCTLA & 0x8000) >> 15)
1610   #define STV_VDP2_N1SWE ((STV_VDP2_WCTLA & 0x2000) >> 13)
1611   #define STV_VDP2_N1SWA ((STV_VDP2_WCTLA & 0x1000) >> 12)
1612   #define STV_VDP2_N1W1E ((STV_VDP2_WCTLA & 0x0800) >> 11)
1613   #define STV_VDP2_N1W1A ((STV_VDP2_WCTLA & 0x0400) >> 10)
1614   #define STV_VDP2_N1W0E ((STV_VDP2_WCTLA & 0x0200) >> 9)
1615   #define STV_VDP2_N1W0A ((STV_VDP2_WCTLA & 0x0100) >> 8)
1616   #define STV_VDP2_N0LOG ((STV_VDP2_WCTLA & 0x0080) >> 7)
1617   #define STV_VDP2_N0SWE ((STV_VDP2_WCTLA & 0x0020) >> 5)
1618   #define STV_VDP2_N0SWA ((STV_VDP2_WCTLA & 0x0010) >> 4)
1619   #define STV_VDP2_N0W1E ((STV_VDP2_WCTLA & 0x0008) >> 3)
1620   #define STV_VDP2_N0W1A ((STV_VDP2_WCTLA & 0x0004) >> 2)
1621   #define STV_VDP2_N0W0E ((STV_VDP2_WCTLA & 0x0002) >> 1)
1622   #define STV_VDP2_N0W0A ((STV_VDP2_WCTLA & 0x0001) >> 0)
1623
1624/* 1800d2 - Window Control (NBG2, NBG3)
1625 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1626       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1627       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1628       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1629       \----------|----------|----------|----------|----------|----------|----------|---------*/
1630
1631   #define STV_VDP2_WCTLB (m_vdp2_regs[0x0d2/2])
1632   #define STV_VDP2_N3LOG ((STV_VDP2_WCTLB & 0x8000) >> 15)
1633   #define STV_VDP2_N3SWE ((STV_VDP2_WCTLB & 0x2000) >> 13)
1634   #define STV_VDP2_N3SWA ((STV_VDP2_WCTLB & 0x1000) >> 12)
1635   #define STV_VDP2_N3W1E ((STV_VDP2_WCTLB & 0x0800) >> 11)
1636   #define STV_VDP2_N3W1A ((STV_VDP2_WCTLB & 0x0400) >> 10)
1637   #define STV_VDP2_N3W0E ((STV_VDP2_WCTLB & 0x0200) >> 9)
1638   #define STV_VDP2_N3W0A ((STV_VDP2_WCTLB & 0x0100) >> 8)
1639   #define STV_VDP2_N2LOG ((STV_VDP2_WCTLB & 0x0080) >> 7)
1640   #define STV_VDP2_N2SWE ((STV_VDP2_WCTLB & 0x0020) >> 5)
1641   #define STV_VDP2_N2SWA ((STV_VDP2_WCTLB & 0x0010) >> 4)
1642   #define STV_VDP2_N2W1E ((STV_VDP2_WCTLB & 0x0008) >> 3)
1643   #define STV_VDP2_N2W1A ((STV_VDP2_WCTLB & 0x0004) >> 2)
1644   #define STV_VDP2_N2W0E ((STV_VDP2_WCTLB & 0x0002) >> 1)
1645   #define STV_VDP2_N2W0A ((STV_VDP2_WCTLB & 0x0001) >> 0)
1646
1647/* 1800d4 - Window Control (RBG0, Sprite)
1648 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1649       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1650       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1651       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1652       \----------|----------|----------|----------|----------|----------|----------|---------*/
1653
1654   #define STV_VDP2_WCTLC (m_vdp2_regs[0x0d4/2])
1655   #define STV_VDP2_SPLOG ((STV_VDP2_WCTLC & 0x8000) >> 15)
1656   #define STV_VDP2_SPSWE ((STV_VDP2_WCTLC & 0x2000) >> 13)
1657   #define STV_VDP2_SPSWA ((STV_VDP2_WCTLC & 0x1000) >> 12)
1658   #define STV_VDP2_SPW1E ((STV_VDP2_WCTLC & 0x0800) >> 11)
1659   #define STV_VDP2_SPW1A ((STV_VDP2_WCTLC & 0x0400) >> 10)
1660   #define STV_VDP2_SPW0E ((STV_VDP2_WCTLC & 0x0200) >> 9)
1661   #define STV_VDP2_SPW0A ((STV_VDP2_WCTLC & 0x0100) >> 8)
1662   #define STV_VDP2_R0LOG ((STV_VDP2_WCTLC & 0x0080) >> 7)
1663   #define STV_VDP2_R0SWE ((STV_VDP2_WCTLC & 0x0020) >> 5)
1664   #define STV_VDP2_R0SWA ((STV_VDP2_WCTLC & 0x0010) >> 4)
1665   #define STV_VDP2_R0W1E ((STV_VDP2_WCTLC & 0x0008) >> 3)
1666   #define STV_VDP2_R0W1A ((STV_VDP2_WCTLC & 0x0004) >> 2)
1667   #define STV_VDP2_R0W0E ((STV_VDP2_WCTLC & 0x0002) >> 1)
1668   #define STV_VDP2_R0W0A ((STV_VDP2_WCTLC & 0x0001) >> 0)
1669
1670/* 1800d6 - Window Control (Parameter Window, Colour Calc. Window)
1671 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1672       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1673       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1674       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1675       \----------|----------|----------|----------|----------|----------|----------|---------*/
1676
1677   #define STV_VDP2_WCTLD (m_vdp2_regs[0x0d6/2])
1678   #define STV_VDP2_CCLOG ((STV_VDP2_WCTLD & 0x8000) >> 15)
1679   #define STV_VDP2_CCSWE ((STV_VDP2_WCTLD & 0x2000) >> 13)
1680   #define STV_VDP2_CCSWA ((STV_VDP2_WCTLD & 0x1000) >> 12)
1681   #define STV_VDP2_CCW1E ((STV_VDP2_WCTLD & 0x0800) >> 11)
1682   #define STV_VDP2_CCW1A ((STV_VDP2_WCTLD & 0x0400) >> 10)
1683   #define STV_VDP2_CCW0E ((STV_VDP2_WCTLD & 0x0200) >> 9)
1684   #define STV_VDP2_CCW0A ((STV_VDP2_WCTLD & 0x0100) >> 8)
1685   #define STV_VDP2_RPLOG ((STV_VDP2_WCTLD & 0x0080) >> 7)
1686   #define STV_VDP2_RPW1E ((STV_VDP2_WCTLD & 0x0008) >> 3)
1687   #define STV_VDP2_RPW1A ((STV_VDP2_WCTLD & 0x0004) >> 2)
1688   #define STV_VDP2_RPW0E ((STV_VDP2_WCTLD & 0x0002) >> 1)
1689   #define STV_VDP2_RPW0A ((STV_VDP2_WCTLD & 0x0001) >> 0)
1690
1691/* 1800d8 - Line Window Table Address (W0)
1692 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1693       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1694       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1695       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1696       \----------|----------|----------|----------|----------|----------|----------|---------*/
1697
1698   #define STV_VDP2_LWTA0U (m_vdp2_regs[0x0d8/2])
1699
1700   #define STV_VDP2_W0LWE  ((STV_VDP2_LWTA0U & 0x8000) >> 15)
1701
1702/* 1800da - Line Window Table Address (W0)
1703 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1704       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1705       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1706       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1707       \----------|----------|----------|----------|----------|----------|----------|---------*/
1708
1709   #define STV_VDP2_LWTA0L (m_vdp2_regs[0x0da/2])
1710
1711   /* bit 19 isn't used when VRAM = 4 Mbit */
1712   #define STV_VDP2_W0LWTA (((STV_VDP2_LWTA0U & 0x0007) << 16) | (STV_VDP2_LWTA0L & 0xfffe))
1713
1714
1715/* 1800dc - Line Window Table Address (W1)
1716 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1717       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1718       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1719       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1720       \----------|----------|----------|----------|----------|----------|----------|---------*/
1721
1722   #define STV_VDP2_LWTA1U (m_vdp2_regs[0x0dc/2])
1723
1724   #define STV_VDP2_W1LWE  ((STV_VDP2_LWTA0U & 0x8000) >> 15)
1725
1726
1727/* 1800de - Line Window Table Address (W1)
1728 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1729       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1730       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1731       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1732       \----------|----------|----------|----------|----------|----------|----------|---------*/
1733
1734   #define STV_VDP2_LWTA1L (m_vdp2_regs[0x0de/2])
1735
1736   /* bit 19 isn't used when VRAM = 4 Mbit */
1737   #define STV_VDP2_W1LWTA (((STV_VDP2_LWTA1U & 0x0007) << 16) | (STV_VDP2_LWTA1L & 0xfffe))
1738
1739
1740/* 1800e0 - Sprite Control
1741 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1742       |    --    |    --    | SPCCCS1  | SPCCCS0  |    --    |  SPCCN2  |  SPCCN1  |  SPCCN0  |
1743       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1744       |    --    |    --    |  SPCLMD  | SPWINEN  |  SPTYPE3 |  SPTYPE2 |  SPTYPE1 |  SPTYPE0 |
1745       \----------|----------|----------|----------|----------|----------|----------|---------*/
1746
1747   #define STV_VDP2_SPCTL  (m_vdp2_regs[0xe0/2])
1748   #define STV_VDP2_SPCCCS     ((STV_VDP2_SPCTL & 0x3000) >> 12)
1749   #define STV_VDP2_SPCCN      ((STV_VDP2_SPCTL & 0x700) >> 8)
1750   #define STV_VDP2_SPCLMD     ((STV_VDP2_SPCTL & 0x20) >> 5)
1751   #define STV_VDP2_SPWINEN    ((STV_VDP2_SPCTL & 0x10) >> 4)
1752   #define STV_VDP2_SPTYPE     (STV_VDP2_SPCTL & 0xf)
1753
1754/* 1800e2 - Shadow Control
1755 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1756       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1757       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1758       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1759       \----------|----------|----------|----------|----------|----------|----------|---------*/
1760
1761   #define STV_VDP2_SDCTL  (m_vdp2_regs[0x0e2/2])
1762
1763/* 1800e4 - CRAOFA - Colour Ram Address Offset (NBG0 - NBG3)
1764 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1765       |    --    | N0CAOS2  | N3CAOS1  | N3CAOS0  |    --    | N2CAOS2  | N2CAOS1  | N2CAOS0  |
1766       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1767       |    --    | N1CAOS2  | N1CAOS1  | N1CAOS0  |    --    | N0CAOS2  | N0CAOS1  | N0CAOS0  |
1768       \----------|----------|----------|----------|----------|----------|----------|---------*/
1769
1770   #define STV_VDP2_CRAOFA (m_vdp2_regs[0x0e4/2])
1771
1772   /* NxCAOS =  */
1773   #define STV_VDP2_N0CAOS ((STV_VDP2_CRAOFA & 0x0007) >> 0)
1774   #define STV_VDP2_N1CAOS ((STV_VDP2_CRAOFA & 0x0070) >> 4)
1775   #define STV_VDP2_N2CAOS ((STV_VDP2_CRAOFA & 0x0700) >> 8)
1776   #define STV_VDP2_N3CAOS ((STV_VDP2_CRAOFA & 0x7000) >> 12)
1777
1778
1779/* 1800e6 - Colour Ram Address Offset (RBG0, SPRITE)
1780 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1781       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1782       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1783       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1784       \----------|----------|----------|----------|----------|----------|----------|---------*/
1785   #define STV_VDP2_CRAOFB (m_vdp2_regs[0x0e6/2])
1786   #define STV_VDP2_R0CAOS ((STV_VDP2_CRAOFB & 0x0007) >> 0)
1787   #define STV_VDP2_SPCAOS ((STV_VDP2_CRAOFB & 0x0070) >> 4)
1788
1789/* 1800e8 - LNCLEN - Line Colour Screen Enable
1790 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1791       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1792       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1793       |    --    |    --    |  SPLCEN  |  R0LCEN  |  N3LCEN  |  N2LCEN  |  N1LCEN  | N0LCEN   |
1794       \----------|----------|----------|----------|----------|----------|----------|---------*/
1795
1796   #define STV_VDP2_LNCLEN (m_vdp2_regs[0x0e8/2])
1797   #define STV_VDP2_SPLCEN ((STV_VDP2_LNCLEN & 0x0020) >> 5)
1798   #define STV_VDP2_R0LCEN ((STV_VDP2_LNCLEN & 0x0010) >> 4)
1799   #define STV_VDP2_N3LCEN ((STV_VDP2_LNCLEN & 0x0008) >> 3)
1800   #define STV_VDP2_N2LCEN ((STV_VDP2_LNCLEN & 0x0004) >> 2)
1801   #define STV_VDP2_N1LCEN ((STV_VDP2_LNCLEN & 0x0002) >> 1)
1802   #define STV_VDP2_N0LCEN ((STV_VDP2_LNCLEN & 0x0001) >> 0)
1803
1804/* 1800ea - Special Priority Mode
1805 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1806       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1807       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1808       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1809       \----------|----------|----------|----------|----------|----------|----------|---------*/
1810
1811   #define STV_VDP2_SFPRMD (m_vdp2_regs[0x0ea/2])
1812
1813
1814/* 1800ec - Colour Calculation Control
1815 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1816       |  BOKEN   |  BOKN2   |  BOKN1   |   BOKN0  |    --    |  EXCCEN  |  CCRTMD  |  CCMD    |
1817       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1818       |    --    |  SPCCEN  |  LCCCEN  |  R0CCEN  |  N3CCEN  |  N2CCEN  |  N1CCEN  |  N0CCEN  |
1819       \----------|----------|----------|----------|----------|----------|----------|---------*/
1820
1821   #define STV_VDP2_CCCR       (m_vdp2_regs[0x0ec/2])
1822   #define STV_VDP2_CCMD       ((STV_VDP2_CCCR & 0x100) >> 8)
1823   #define STV_VDP2_SPCCEN     ((STV_VDP2_CCCR & 0x40) >> 6)
1824   #define STV_VDP2_LCCCEN     ((STV_VDP2_CCCR & 0x20) >> 5)
1825   #define STV_VDP2_R0CCEN     ((STV_VDP2_CCCR & 0x10) >> 4)
1826   #define STV_VDP2_N3CCEN     ((STV_VDP2_CCCR & 0x8) >> 3)
1827   #define STV_VDP2_N2CCEN     ((STV_VDP2_CCCR & 0x4) >> 2)
1828   #define STV_VDP2_N1CCEN     ((STV_VDP2_CCCR & 0x2) >> 1)
1829   #define STV_VDP2_N0CCEN     ((STV_VDP2_CCCR & 0x1) >> 0)
1830
1831
1832/* 1800ee - Special Colour Calculation Mode
1833 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1834       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1835       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1836       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1837       \----------|----------|----------|----------|----------|----------|----------|---------*/
1838
1839   #define STV_VDP2_SFCCMD     (m_vdp2_regs[0x0ee/2])
1840
1841/* 1800f0 - Priority Number (Sprite 0,1)
1842 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1843       |    --    |    --    |    --    |    --    |    --    |  S1PRIN2 |  S1PRIN1 |  S1PRIN0 |
1844       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1845       |    --    |    --    |    --    |    --    |    --    |  S0PRIN2 |  S0PRIN1 |  S0PRIN0 |
1846       \----------|----------|----------|----------|----------|----------|----------|---------*/
1847
1848   #define STV_VDP2_PRISA      (m_vdp2_regs[0x0f0/2])
1849   #define STV_VDP2_S1PRIN     ((STV_VDP2_PRISA & 0x0700) >> 8)
1850   #define STV_VDP2_S0PRIN     ((STV_VDP2_PRISA & 0x0007) >> 0)
1851
1852/* 1800f2 - Priority Number (Sprite 2,3)
1853 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1854       |    --    |    --    |    --    |    --    |    --    |  S3PRIN2 |  S3PRIN1 |  S3PRIN0 |
1855       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1856       |    --    |    --    |    --    |    --    |    --    |  S2PRIN2 |  S2PRIN1 |  S2PRIN0 |
1857       \----------|----------|----------|----------|----------|----------|----------|---------*/
1858
1859   #define STV_VDP2_PRISB      (m_vdp2_regs[0x0f2/2])
1860   #define STV_VDP2_S3PRIN     ((STV_VDP2_PRISB & 0x0700) >> 8)
1861   #define STV_VDP2_S2PRIN     ((STV_VDP2_PRISB & 0x0007) >> 0)
1862
1863/* 1800f4 - Priority Number (Sprite 4,5)
1864 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1865       |    --    |    --    |    --    |    --    |    --    |  S5PRIN2 |  S5PRIN1 |  S5PRIN0 |
1866       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1867       |    --    |    --    |    --    |    --    |    --    |  S4PRIN2 |  S4PRIN1 |  S4PRIN0 |
1868       \----------|----------|----------|----------|----------|----------|----------|---------*/
1869
1870   #define STV_VDP2_PRISC      (m_vdp2_regs[0x0f4/2])
1871   #define STV_VDP2_S5PRIN     ((STV_VDP2_PRISC & 0x0700) >> 8)
1872   #define STV_VDP2_S4PRIN     ((STV_VDP2_PRISC & 0x0007) >> 0)
1873
1874/* 1800f6 - Priority Number (Sprite 6,7)
1875 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1876       |    --    |    --    |    --    |    --    |    --    |  S7PRIN2 |  S7PRIN1 |  S7PRIN0 |
1877       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1878       |    --    |    --    |    --    |    --    |    --    |  S6PRIN2 |  S6PRIN1 |  S6PRIN0 |
1879       \----------|----------|----------|----------|----------|----------|----------|---------*/
1880
1881   #define STV_VDP2_PRISD      (m_vdp2_regs[0x0f6/2])
1882   #define STV_VDP2_S7PRIN     ((STV_VDP2_PRISD & 0x0700) >> 8)
1883   #define STV_VDP2_S6PRIN     ((STV_VDP2_PRISD & 0x0007) >> 0)
1884
1885
1886/* 1800f8 - PRINA - Priority Number (NBG 0,1)
1887 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1888       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1889       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1890       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1891       \----------|----------|----------|----------|----------|----------|----------|---------*/
1892
1893   #define STV_VDP2_PRINA (m_vdp2_regs[0x0f8/2])
1894
1895   #define STV_VDP2_N1PRIN ((STV_VDP2_PRINA & 0x0700) >> 8)
1896   #define STV_VDP2_N0PRIN ((STV_VDP2_PRINA & 0x0007) >> 0)
1897
1898/* 1800fa - PRINB - Priority Number (NBG 2,3)
1899 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1900       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1901       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1902       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1903       \----------|----------|----------|----------|----------|----------|----------|---------*/
1904
1905   #define STV_VDP2_PRINB (m_vdp2_regs[0x0fa/2])
1906
1907   #define STV_VDP2_N3PRIN ((STV_VDP2_PRINB & 0x0700) >> 8)
1908   #define STV_VDP2_N2PRIN ((STV_VDP2_PRINB & 0x0007) >> 0)
1909
1910/* 1800fc - Priority Number (RBG0)
1911 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1912       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1913       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1914       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1915       \----------|----------|----------|----------|----------|----------|----------|---------*/
1916   #define STV_VDP2_PRIR (m_vdp2_regs[0x0fc/2])
1917
1918   #define STV_VDP2_R0PRIN ((STV_VDP2_PRIR & 0x0007) >> 0)
1919
1920/* 1800fe - Reserved
1921 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1922       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1923       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1924       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1925       \----------|----------|----------|----------|----------|----------|----------|---------*/
1926
1927/* 180100 - Colour Calculation Ratio (Sprite 0,1)
1928 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1929       |    --    |    --    |    --    |  S1CCRT4 |  S1CCRT3 |  S1CCRT2 |  S1CCRT1 |  S1CCRT0 |
1930       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1931       |    --    |    --    |    --    |  S0CCRT4 |  S0CCRT3 |  S0CCRT2 |  S0CCRT1 |  S0CCRT0 |
1932       \----------|----------|----------|----------|----------|----------|----------|---------*/
1933
1934   #define STV_VDP2_CCRSA      (m_vdp2_regs[0x100/2])
1935   #define STV_VDP2_S1CCRT     ((STV_VDP2_CCRSA & 0x1f00) >> 8)
1936   #define STV_VDP2_S0CCRT     ((STV_VDP2_CCRSA & 0x001f) >> 0)
1937
1938/* 180102 - Colour Calculation Ratio (Sprite 2,3)
1939 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1940       |    --    |    --    |    --    |  S3CCRT4 |  S3CCRT3 |  S3CCRT2 |  S3CCRT1 |  S3CCRT0 |
1941       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1942       |    --    |    --    |    --    |  S2CCRT4 |  S2CCRT3 |  S2CCRT2 |  S2CCRT1 |  S2CCRT0 |
1943       \----------|----------|----------|----------|----------|----------|----------|---------*/
1944
1945   #define STV_VDP2_CCRSB      (m_vdp2_regs[0x102/2])
1946   #define STV_VDP2_S3CCRT     ((STV_VDP2_CCRSB & 0x1f00) >> 8)
1947   #define STV_VDP2_S2CCRT     ((STV_VDP2_CCRSB & 0x001f) >> 0)
1948
1949/* 180104 - Colour Calculation Ratio (Sprite 4,5)
1950 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1951       |    --    |    --    |    --    |  S5CCRT4 |  S5CCRT3 |  S5CCRT2 |  S5CCRT1 |  S5CCRT0 |
1952       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1953       |    --    |    --    |    --    |  S4CCRT4 |  S4CCRT3 |  S4CCRT2 |  S4CCRT1 |  S4CCRT0 |
1954       \----------|----------|----------|----------|----------|----------|----------|---------*/
1955
1956   #define STV_VDP2_CCRSC      (m_vdp2_regs[0x104/2])
1957   #define STV_VDP2_S5CCRT     ((STV_VDP2_CCRSC & 0x1f00) >> 8)
1958   #define STV_VDP2_S4CCRT     ((STV_VDP2_CCRSC & 0x001f) >> 0)
1959
1960/* 180106 - Colour Calculation Ratio (Sprite 6,7)
1961 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1962       |    --    |    --    |    --    |  S7CCRT4 |  S7CCRT3 |  S7CCRT2 |  S7CCRT1 |  S7CCRT0 |
1963       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1964       |    --    |    --    |    --    |  S6CCRT4 |  S6CCRT3 |  S6CCRT2 |  S6CCRT1 |  S6CCRT0 |
1965       \----------|----------|----------|----------|----------|----------|----------|---------*/
1966
1967   #define STV_VDP2_CCRSD      (m_vdp2_regs[0x106/2])
1968   #define STV_VDP2_S7CCRT     ((STV_VDP2_CCRSD & 0x1f00) >> 8)
1969   #define STV_VDP2_S6CCRT     ((STV_VDP2_CCRSD & 0x001f) >> 0)
1970
1971/* 180108 - Colour Calculation Ratio (NBG 0,1)
1972 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1973       |    --    |    --    |    --    | N1CCRT4  | N1CCRT3  | N1CCRT2  | N1CCRT1  | N1CCRT0  |
1974       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1975       |    --    |    --    |    --    | N0CCRT4  | N0CCRT3  | N0CCRT2  | N0CCRT1  | N0CCRT0  |
1976       \----------|----------|----------|----------|----------|----------|----------|---------*/
1977
1978   #define STV_VDP2_CCRNA  (m_vdp2_regs[0x108/2])
1979   #define STV_VDP2_N1CCRT ((STV_VDP2_CCRNA & 0x1f00) >> 8)
1980   #define STV_VDP2_N0CCRT (STV_VDP2_CCRNA & 0x1f)
1981
1982/* 18010a - Colour Calculation Ratio (NBG 2,3)
1983 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1984       |    --    |    --    |    --    | N3CCRT4  | N3CCRT3  | N3CCRT2  | N3CCRT1  | N3CCRT0  |
1985       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1986       |    --    |    --    |    --    | N2CCRT4  | N2CCRT3  | N2CCRT2  | N2CCRT1  | N2CCRT0  |
1987       \----------|----------|----------|----------|----------|----------|----------|---------*/
1988
1989   #define STV_VDP2_CCRNB  (m_vdp2_regs[0x10a/2])
1990   #define STV_VDP2_N3CCRT ((STV_VDP2_CCRNB & 0x1f00) >> 8)
1991   #define STV_VDP2_N2CCRT (STV_VDP2_CCRNB & 0x1f)
1992
1993/* 18010c - Colour Calculation Ratio (RBG 0)
1994 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
1995       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1996       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
1997       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
1998       \----------|----------|----------|----------|----------|----------|----------|---------*/
1999
2000   #define STV_VDP2_CCRR   (m_vdp2_regs[0x10c/2])
2001   #define STV_VDP2_R0CCRT (STV_VDP2_CCRR & 0x1f)
2002
2003/* 18010e - Colour Calculation Ratio (Line Colour Screen, Back Colour Screen)
2004 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
2005       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
2006       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
2007       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
2008       \----------|----------|----------|----------|----------|----------|----------|---------*/
2009
2010/* 180110 - Colour Offset Enable
2011 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
2012       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
2013       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
2014       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
2015       \----------|----------|----------|----------|----------|----------|----------|---------*/
2016
2017   #define STV_VDP2_CLOFEN (m_vdp2_regs[0x110/2])
2018   #define STV_VDP2_N0COEN ((STV_VDP2_CLOFEN & 0x01) >> 0)
2019   #define STV_VDP2_N1COEN ((STV_VDP2_CLOFEN & 0x02) >> 1)
2020   #define STV_VDP2_N2COEN ((STV_VDP2_CLOFEN & 0x04) >> 2)
2021   #define STV_VDP2_N3COEN ((STV_VDP2_CLOFEN & 0x08) >> 3)
2022   #define STV_VDP2_R0COEN ((STV_VDP2_CLOFEN & 0x10) >> 4)
2023   #define STV_VDP2_BKCOEN ((STV_VDP2_CLOFEN & 0x20) >> 5)
2024   #define STV_VDP2_SPCOEN ((STV_VDP2_CLOFEN & 0x40) >> 6)
2025
2026/* 180112 - Colour Offset Select
2027 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
2028       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
2029       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
2030       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
2031       \----------|----------|----------|----------|----------|----------|----------|---------*/
2032
2033   #define STV_VDP2_CLOFSL (m_vdp2_regs[0x112/2])
2034   #define STV_VDP2_N0COSL ((STV_VDP2_CLOFSL & 0x01) >> 0)
2035   #define STV_VDP2_N1COSL ((STV_VDP2_CLOFSL & 0x02) >> 1)
2036   #define STV_VDP2_N2COSL ((STV_VDP2_CLOFSL & 0x04) >> 2)
2037   #define STV_VDP2_N3COSL ((STV_VDP2_CLOFSL & 0x08) >> 3)
2038   #define STV_VDP2_R0COSL ((STV_VDP2_CLOFSL & 0x10) >> 4)
2039   #define STV_VDP2_BKCOSL ((STV_VDP2_CLOFSL & 0x20) >> 5)
2040   #define STV_VDP2_SPCOSL ((STV_VDP2_CLOFSL & 0x40) >> 6)
2041
2042/* 180114 - Colour Offset A (Red)
2043 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
2044       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
2045       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
2046       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
2047       \----------|----------|----------|----------|----------|----------|----------|---------*/
2048
2049   #define STV_VDP2_COAR (m_vdp2_regs[0x114/2])
2050
2051/* 180116 - Colour Offset A (Green)
2052 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
2053       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
2054       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
2055       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
2056       \----------|----------|----------|----------|----------|----------|----------|---------*/
2057   #define STV_VDP2_COAG (m_vdp2_regs[0x116/2])
2058
2059/* 180118 - Colour Offset A (Blue)
2060 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
2061       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
2062       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
2063       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
2064       \----------|----------|----------|----------|----------|----------|----------|---------*/
2065
2066   #define STV_VDP2_COAB (m_vdp2_regs[0x118/2])
2067
2068/* 18011a - Colour Offset B (Red)
2069 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
2070       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
2071       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
2072       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
2073       \----------|----------|----------|----------|----------|----------|----------|---------*/
2074   #define STV_VDP2_COBR (m_vdp2_regs[0x11a/2])
2075
2076/* 18011c - Colour Offset B (Green)
2077 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
2078       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
2079       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
2080       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
2081       \----------|----------|----------|----------|----------|----------|----------|---------*/
2082   #define STV_VDP2_COBG (m_vdp2_regs[0x11c/2])
2083
2084/* 18011e - Colour Offset B (Blue)
2085 bit-> /----15----|----14----|----13----|----12----|----11----|----10----|----09----|----08----\
2086       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
2087       |----07----|----06----|----05----|----04----|----03----|----02----|----01----|----00----|
2088       |    --    |    --    |    --    |    --    |    --    |    --    |    --    |    --    |
2089       \----------|----------|----------|----------|----------|----------|----------|---------*/
2090   #define STV_VDP2_COBB (m_vdp2_regs[0x11e/2])
2091
2092
2093#define STV_VDP2_RBG_ROTATION_PARAMETER_A   1
2094#define STV_VDP2_RBG_ROTATION_PARAMETER_B   2
2095
2096
2097#define mul_fixed32( a, b ) mul_32x32_shift( a, b, 16 )
2098
2099void saturn_state::stv_vdp2_fill_rotation_parameter_table( UINT8 rot_parameter )
2100{
2101   UINT32 address = 0;
2102
2103   address = (((STV_VDP2_RPTAU << 16) | STV_VDP2_RPTAL) << 1);
2104   if ( rot_parameter == 1 )
2105   {
2106      address &= ~0x00000080;
2107   }
2108   else if ( rot_parameter == 2 )
2109   {
2110      address |= 0x00000080;
2111   }
2112
2113   stv_current_rotation_parameter_table.xst  = (m_vdp2_vram[address/4] & 0x1fffffc0) | ((m_vdp2_vram[address/4] & 0x10000000) ? 0xe0000000 : 0x00000000 );
2114   stv_current_rotation_parameter_table.yst  = (m_vdp2_vram[address/4 + 1] & 0x1fffffc0) | ((m_vdp2_vram[address/4 + 1] & 0x10000000) ? 0xe0000000 : 0x00000000 );
2115   stv_current_rotation_parameter_table.zst  = (m_vdp2_vram[address/4 + 2] & 0x1fffffc0) | ((m_vdp2_vram[address/4 + 2] & 0x10000000) ? 0xe0000000 : 0x00000000 );
2116   stv_current_rotation_parameter_table.dxst = (m_vdp2_vram[address/4 + 3] & 0x0007ffc0) | ((m_vdp2_vram[address/4 + 3] & 0x00040000) ? 0xfff80000 : 0x00000000 );
2117   stv_current_rotation_parameter_table.dyst = (m_vdp2_vram[address/4 + 4] & 0x0007ffc0) | ((m_vdp2_vram[address/4 + 4] & 0x00040000) ? 0xfff80000 : 0x00000000 );
2118   stv_current_rotation_parameter_table.dx   = (m_vdp2_vram[address/4 + 5] & 0x0007ffc0) | ((m_vdp2_vram[address/4 + 5] & 0x00040000) ? 0xfff80000 : 0x00000000 );
2119   stv_current_rotation_parameter_table.dy   = (m_vdp2_vram[address/4 + 6] & 0x0007ffc0) | ((m_vdp2_vram[address/4 + 6] & 0x00040000) ? 0xfff80000 : 0x00000000 );
2120   stv_current_rotation_parameter_table.A    = (m_vdp2_vram[address/4 + 7] & 0x000fffc0) | ((m_vdp2_vram[address/4 + 7] & 0x00080000) ? 0xfff00000 : 0x00000000 );
2121   stv_current_rotation_parameter_table.B    = (m_vdp2_vram[address/4 + 8] & 0x000fffc0) | ((m_vdp2_vram[address/4 + 8] & 0x00080000) ? 0xfff00000 : 0x00000000 );
2122   stv_current_rotation_parameter_table.C    = (m_vdp2_vram[address/4 + 9] & 0x000fffc0) | ((m_vdp2_vram[address/4 + 9] & 0x00080000) ? 0xfff00000 : 0x00000000 );
2123   stv_current_rotation_parameter_table.D    = (m_vdp2_vram[address/4 + 10] & 0x000fffc0) | ((m_vdp2_vram[address/4 + 10] & 0x00080000) ? 0xfff00000 : 0x00000000 );
2124   stv_current_rotation_parameter_table.E    = (m_vdp2_vram[address/4 + 11] & 0x000fffc0) | ((m_vdp2_vram[address/4 + 11] & 0x00080000) ? 0xfff00000 : 0x00000000 );
2125   stv_current_rotation_parameter_table.F    = (m_vdp2_vram[address/4 + 12] & 0x000fffc0) | ((m_vdp2_vram[address/4 + 12] & 0x00080000) ? 0xfff00000 : 0x00000000 );
2126   stv_current_rotation_parameter_table.px   = (m_vdp2_vram[address/4 + 13] & 0x3fff0000) | ((m_vdp2_vram[address/4 + 13] & 0x30000000) ? 0xc0000000 : 0x00000000 );
2127   stv_current_rotation_parameter_table.py   = (m_vdp2_vram[address/4 + 13] & 0x00003fff) << 16;
2128   if ( stv_current_rotation_parameter_table.py & 0x20000000 ) stv_current_rotation_parameter_table.py |= 0xc0000000;
2129   stv_current_rotation_parameter_table.pz   = (m_vdp2_vram[address/4 + 14] & 0x3fff0000) | ((m_vdp2_vram[address/4 + 14] & 0x20000000) ? 0xc0000000 : 0x00000000 );
2130   stv_current_rotation_parameter_table.cx   = (m_vdp2_vram[address/4 + 15] & 0x3fff0000) | ((m_vdp2_vram[address/4 + 15] & 0x20000000) ? 0xc0000000 : 0x00000000 );
2131   stv_current_rotation_parameter_table.cy   = (m_vdp2_vram[address/4 + 15] & 0x00003fff) << 16;
2132   if ( stv_current_rotation_parameter_table.cy & 0x20000000 ) stv_current_rotation_parameter_table.cy |= 0xc0000000;
2133   stv_current_rotation_parameter_table.cz   = (m_vdp2_vram[address/4 + 16] & 0x3fff0000) | ((m_vdp2_vram[address/4 + 16] & 0x20000000) ? 0xc0000000 : 0x00000000 );
2134   stv_current_rotation_parameter_table.mx   = (m_vdp2_vram[address/4 + 17] & 0x3fffffc0) | ((m_vdp2_vram[address/4 + 17] & 0x20000000) ? 0xc0000000 : 0x00000000 );
2135   stv_current_rotation_parameter_table.my   = (m_vdp2_vram[address/4 + 18] & 0x3fffffc0) | ((m_vdp2_vram[address/4 + 18] & 0x20000000) ? 0xc0000000 : 0x00000000 );
2136   stv_current_rotation_parameter_table.kx   = (m_vdp2_vram[address/4 + 19] & 0x00ffffff) | ((m_vdp2_vram[address/4 + 19] & 0x00800000) ? 0xff000000 : 0x00000000 );
2137   stv_current_rotation_parameter_table.ky   = (m_vdp2_vram[address/4 + 20] & 0x00ffffff) | ((m_vdp2_vram[address/4 + 20] & 0x00800000) ? 0xff000000 : 0x00000000 );
2138   stv_current_rotation_parameter_table.kast = (m_vdp2_vram[address/4 + 21] & 0xffffffc0);
2139   stv_current_rotation_parameter_table.dkast= (m_vdp2_vram[address/4 + 22] & 0x03ffffc0) | ((m_vdp2_vram[address/4 + 22] & 0x02000000) ? 0xfc000000 : 0x00000000 );
2140   stv_current_rotation_parameter_table.dkax = (m_vdp2_vram[address/4 + 23] & 0x03ffffc0) | ((m_vdp2_vram[address/4 + 23] & 0x02000000) ? 0xfc000000 : 0x00000000 );
2141
2142#define RP  stv_current_rotation_parameter_table
2143
2144   if(LOG_ROZ == 1) logerror( "Rotation parameter table (%d)\n", rot_parameter );
2145   if(LOG_ROZ == 1) logerror( "xst = %x, yst = %x, zst = %x\n", RP.xst, RP.yst, RP.zst );
2146   if(LOG_ROZ == 1) logerror( "dxst = %x, dyst = %x\n", RP.dxst, RP.dyst );
2147   if(LOG_ROZ == 1) logerror( "dx = %x, dy = %x\n", RP.dx, RP.dy );
2148   if(LOG_ROZ == 1) logerror( "A = %x, B = %x, C = %x, D = %x, E = %x, F = %x\n", RP.A, RP.B, RP.C, RP.D, RP.E, RP.F );
2149   if(LOG_ROZ == 1) logerror( "px = %x, py = %x, pz = %x\n", RP.px, RP.py, RP.pz );
2150   if(LOG_ROZ == 1) logerror( "cx = %x, cy = %x, cz = %x\n", RP.cx, RP.cy, RP.cz );
2151   if(LOG_ROZ == 1) logerror( "mx = %x, my = %x\n", RP.mx, RP.my );
2152   if(LOG_ROZ == 1) logerror( "kx = %x, ky = %x\n", RP.kx, RP.ky );
2153   if(LOG_ROZ == 1) logerror( "kast = %x, dkast = %x, dkax = %x\n", RP.kast, RP.dkast, RP.dkax );
2154
2155   /*Attempt to show on screen the rotation table*/
2156   #if 0
2157   if(LOG_ROZ == 2)
2158   {
2159      if(machine().input().code_pressed_once(JOYCODE_Y_UP_SWITCH))
2160         m_vdpdebug_roz++;
2161
2162      if(machine().input().code_pressed_once(JOYCODE_Y_DOWN_SWITCH))
2163         m_vdpdebug_roz--;
2164
2165      if(m_vdpdebug_roz > 10)
2166         m_vdpdebug_roz = 10;
2167
2168      switch(m_vdpdebug_roz)
2169      {
2170         case 0: popmessage( "Rotation parameter Table (%d)", rot_parameter ); break;
2171         case 1: popmessage( "xst = %x, yst = %x, zst = %x", RP.xst, RP.yst, RP.zst ); break;
2172         case 2: popmessage( "dxst = %x, dyst = %x", RP.dxst, RP.dyst ); break;
2173         case 3: popmessage( "dx = %x, dy = %x", RP.dx, RP.dy ); break;
2174         case 4: popmessage( "A = %x, B = %x, C = %x, D = %x, E = %x, F = %x", RP.A, RP.B, RP.C, RP.D, RP.E, RP.F ); break;
2175         case 5: popmessage( "px = %x, py = %x, pz = %x", RP.px, RP.py, RP.pz ); break;
2176         case 6: popmessage( "cx = %x, cy = %x, cz = %x", RP.cx, RP.cy, RP.cz ); break;
2177         case 7: popmessage( "mx = %x, my = %x", RP.mx, RP.my ); break;
2178         case 8: popmessage( "kx = %x, ky = %x", RP.kx, RP.ky ); break;
2179         case 9: popmessage( "kast = %x, dkast = %x, dkax = %x", RP.kast, RP.dkast, RP.dkax ); break;
2180         case 10: break;
2181      }
2182   }
2183   #endif
2184}
2185
2186/* check if RGB layer has rotation applied */
2187UINT8 saturn_state::stv_vdp2_is_rotation_applied(void)
2188{
2189#define _FIXED_1    (0x00010000)
2190#define _FIXED_0    (0x00000000)
2191
2192   if ( RP.A == _FIXED_1 &&
2193         RP.B == _FIXED_0 &&
2194         RP.C == _FIXED_0 &&
2195         RP.D == _FIXED_0 &&
2196         RP.E == _FIXED_1 &&
2197         RP.F == _FIXED_0 &&
2198         RP.dxst == _FIXED_0 &&
2199         RP.dyst == _FIXED_1 &&
2200         RP.dx == _FIXED_1 &&
2201         RP.dy == _FIXED_0 &&
2202         RP.kx == _FIXED_1 &&
2203         RP.ky == _FIXED_1 )
2204   {
2205      return 0;
2206   }
2207   else
2208   {
2209      return 1;
2210   }
2211}
2212
2213UINT8 saturn_state::stv_vdp2_are_map_registers_equal(void)
2214{
2215   int i;
2216
2217   for ( i = 1; i < stv2_current_tilemap.map_count; i++ )
2218   {
2219      if ( stv2_current_tilemap.map_offset[i] != stv2_current_tilemap.map_offset[0] )
2220      {
2221         return 0;
2222      }
2223   }
2224   return 1;
2225}
2226
2227void saturn_state::stv_vdp2_check_fade_control_for_layer( void )
2228{
2229   if ( stv2_current_tilemap.fade_control & 1 )
2230   {
2231      if ( stv2_current_tilemap.fade_control & 2 )
2232      {
2233         if ((STV_VDP2_COBR & 0x1ff) == 0 &&
2234            (STV_VDP2_COBG & 0x1ff) == 0 &&
2235            (STV_VDP2_COBB & 0x1ff) == 0 )
2236         {
2237            stv2_current_tilemap.fade_control = 0;
2238         }
2239      }
2240      else
2241      {
2242         if ((STV_VDP2_COAR & 0x1ff) == 0 &&
2243            (STV_VDP2_COAG & 0x1ff) == 0 &&
2244            (STV_VDP2_COAB & 0x1ff) == 0 )
2245         {
2246            stv2_current_tilemap.fade_control = 0;
2247         }
2248      }
2249   }
2250}
2251
2252#define STV_VDP2_CP_NBG0_PNMDR      0x0
2253#define STV_VDP2_CP_NBG1_PNMDR      0x1
2254#define STV_VDP2_CP_NBG2_PNMDR      0x2
2255#define STV_VDP2_CP_NBG3_PNMDR      0x3
2256#define STV_VDP2_CP_NBG0_CPDR       0x4
2257#define STV_VDP2_CP_NBG1_CPDR       0x5
2258#define STV_VDP2_CP_NBG2_CPDR       0x6
2259#define STV_VDP2_CP_NBG3_CPDR       0x7
2260
2261UINT8 saturn_state::stv_vdp2_check_vram_cycle_pattern_registers( UINT8 access_command_pnmdr, UINT8 access_command_cpdr, UINT8 bitmap_enable )
2262{
2263   int i;
2264   UINT8  access_command_ok = 0;
2265   UINT16 cp_regs[8];
2266   cp_regs[0] = STV_VDP2_CYCA0L;
2267   cp_regs[1] = STV_VDP2_CYCA0U;
2268   cp_regs[2] = STV_VDP2_CYCA1L;
2269   cp_regs[3] = STV_VDP2_CYCA1U;
2270   cp_regs[4] = STV_VDP2_CYCA2L;
2271   cp_regs[5] = STV_VDP2_CYCA2U;
2272   cp_regs[6] = STV_VDP2_CYCA3L;
2273   cp_regs[7] = STV_VDP2_CYCA3U;
2274
2275   if ( bitmap_enable ) access_command_ok = 1;
2276
2277   for ( i = 0; i < 8; i++ )
2278   {
2279      if ( ((cp_regs[i] >> 12) & 0xf) == access_command_pnmdr )
2280      {
2281         access_command_ok |= 1;
2282      }
2283      if ( ((cp_regs[i] >> 12) & 0xf) == access_command_cpdr )
2284      {
2285         access_command_ok |= 2;
2286      }
2287      if ( ((cp_regs[i] >> 8) & 0xf) == access_command_pnmdr )
2288      {
2289         access_command_ok |= 1;
2290      }
2291      if ( ((cp_regs[i] >> 8) & 0xf) == access_command_cpdr )
2292      {
2293         access_command_ok |= 2;
2294      }
2295      if ( ((cp_regs[i] >> 4) & 0xf) == access_command_pnmdr )
2296      {
2297         access_command_ok |= 1;
2298      }
2299      if ( ((cp_regs[i] >> 4) & 0xf) == access_command_cpdr )
2300      {
2301         access_command_ok |= 2;
2302      }
2303      if ( ((cp_regs[i] >> 0) & 0xf) == access_command_pnmdr )
2304      {
2305         access_command_ok |= 1;
2306      }
2307      if ( ((cp_regs[i] >> 0) & 0xf) == access_command_cpdr )
2308      {
2309         access_command_ok |= 2;
2310      }
2311   }
2312   return access_command_ok == 3 ? 1 : 0;
2313}
2314
2315INLINE UINT32 stv_add_blend(UINT32 a, UINT32 b)
2316{
2317   UINT32 rb = (a & 0xff00ff) + (b & 0xff00ff);
2318   UINT32 g = (a & 0x00ff00) + (b & 0x00ff00);
2319   return MAKE_RGB((rb & 0x1000000) ? 0xff : RGB_RED(rb),
2320      (g & 0x0010000) ? 0xff : RGB_GREEN(g),
2321      (rb & 0x0000100) ? 0xff : RGB_BLUE(rb)
2322   );
2323}
2324
2325
2326void saturn_state::stv_vdp2_compute_color_offset( int *r, int *g, int *b, int cor )
2327{
2328   if ( cor == 0 )
2329   {
2330      *r = (STV_VDP2_COAR & 0x100) ? (*r - (0x100 - (STV_VDP2_COAR & 0xff))) : ((STV_VDP2_COAR & 0xff) + *r);
2331      *g = (STV_VDP2_COAG & 0x100) ? (*g - (0x100 - (STV_VDP2_COAG & 0xff))) : ((STV_VDP2_COAG & 0xff) + *g);
2332      *b = (STV_VDP2_COAB & 0x100) ? (*b - (0x100 - (STV_VDP2_COAB & 0xff))) : ((STV_VDP2_COAB & 0xff) + *b);
2333   }
2334   else
2335   {
2336      *r = (STV_VDP2_COBR & 0x100) ? (*r - (0xff - (STV_VDP2_COBR & 0xff))) : ((STV_VDP2_COBR & 0xff) + *r);
2337      *g = (STV_VDP2_COBG & 0x100) ? (*g - (0xff - (STV_VDP2_COBG & 0xff))) : ((STV_VDP2_COBG & 0xff) + *g);
2338      *b = (STV_VDP2_COBB & 0x100) ? (*b - (0xff - (STV_VDP2_COBB & 0xff))) : ((STV_VDP2_COBB & 0xff) + *b);
2339   }
2340   if(*r < 0)      { *r = 0; }
2341   if(*r > 0xff)   { *r = 0xff; }
2342   if(*g < 0)      { *g = 0; }
2343   if(*g > 0xff)   { *g = 0xff; }
2344   if(*b < 0)      { *b = 0; }
2345   if(*b > 0xff)   { *b = 0xff; }
2346}
2347
2348void saturn_state::stv_vdp2_compute_color_offset_UINT32(UINT32 *rgb, int cor)
2349{
2350   int _r = RGB_RED(*rgb);
2351   int _g = RGB_GREEN(*rgb);
2352   int _b = RGB_BLUE(*rgb);
2353   if ( cor == 0 )
2354   {
2355      _r = (STV_VDP2_COAR & 0x100) ? (_r - (0x100 - (STV_VDP2_COAR & 0xff))) : ((STV_VDP2_COAR & 0xff) + _r);
2356      _g = (STV_VDP2_COAG & 0x100) ? (_g - (0x100 - (STV_VDP2_COAG & 0xff))) : ((STV_VDP2_COAG & 0xff) + _g);
2357      _b = (STV_VDP2_COAB & 0x100) ? (_b - (0x100 - (STV_VDP2_COAB & 0xff))) : ((STV_VDP2_COAB & 0xff) + _b);
2358   }
2359   else
2360   {
2361      _r = (STV_VDP2_COBR & 0x100) ? (_r - (0xff - (STV_VDP2_COBR & 0xff))) : ((STV_VDP2_COBR & 0xff) + _r);
2362      _g = (STV_VDP2_COBG & 0x100) ? (_g - (0xff - (STV_VDP2_COBG & 0xff))) : ((STV_VDP2_COBG & 0xff) + _g);
2363      _b = (STV_VDP2_COBB & 0x100) ? (_b - (0xff - (STV_VDP2_COBB & 0xff))) : ((STV_VDP2_COBB & 0xff) + _b);
2364   }
2365   if(_r < 0)      { _r = 0; }
2366   if(_r > 0xff)   { _r = 0xff; }
2367   if(_g < 0)      { _g = 0; }
2368   if(_g > 0xff)   { _g = 0xff; }
2369   if(_b < 0)      { _b = 0; }
2370   if(_b > 0xff)   { _b = 0xff; }
2371
2372   *rgb = MAKE_RGB(_r, _g, _b);
2373}
2374
2375void saturn_state::stv_vdp2_drawgfxzoom(
2376      bitmap_rgb32 &dest_bmp,const rectangle &clip,gfx_element *gfx,
2377      UINT32 code,UINT32 color,int flipx,int flipy,int sx,int sy,
2378      int transparency,int transparent_color,int scalex, int scaley,
2379      int sprite_screen_width, int sprite_screen_height, int alpha)
2380{
2381   rectangle myclip;
2382
2383   if (!scalex || !scaley) return;
2384
2385   if (gfx->has_pen_usage() && transparency == STV_TRANSPARENCY_PEN)
2386   {
2387      int transmask = 0;
2388
2389      transmask = 1 << (transparent_color & 0xff);
2390
2391      if ((gfx->pen_usage(code) & ~transmask) == 0)
2392         /* character is totally transparent, no need to draw */
2393         return;
2394      else if ((gfx->pen_usage(code) & transmask) == 0)
2395         /* character is totally opaque, can disable transparency */
2396         transparency = STV_TRANSPARENCY_NONE;
2397   }
2398
2399   /*
2400   scalex and scaley are 16.16 fixed point numbers
2401   1<<15 : shrink to 50%
2402   1<<16 : uniform scale
2403   1<<17 : double to 200%
2404   */
2405
2406
2407   /* KW 991012 -- Added code to force clip to bitmap boundary */
2408   myclip = clip;
2409   myclip &= dest_bmp.cliprect();
2410
2411   if( gfx )
2412   {
2413      const pen_t *pal = &gfx->machine().pens[gfx->colorbase() + gfx->granularity() * (color % gfx->colors())];
2414      const UINT8 *source_base = gfx->get_data(code % gfx->elements());
2415
2416      //int sprite_screen_height = (scaley*gfx->height()+0x8000)>>16;
2417      //int sprite_screen_width = (scalex*gfx->width()+0x8000)>>16;
2418
2419      if (sprite_screen_width && sprite_screen_height)
2420      {
2421         /* compute sprite increment per screen pixel */
2422         //int dx = (gfx->width()<<16)/sprite_screen_width;
2423         //int dy = (gfx->height()<<16)/sprite_screen_height;
2424         int dx = stv2_current_tilemap.incx;
2425         int dy = stv2_current_tilemap.incy;
2426
2427         int ex = sx+sprite_screen_width;
2428         int ey = sy+sprite_screen_height;
2429
2430         int x_index_base;
2431         int y_index;
2432
2433         if( flipx )
2434         {
2435            x_index_base = (sprite_screen_width-1)*dx;
2436            dx = -dx;
2437         }
2438         else
2439         {
2440            x_index_base = 0;
2441         }
2442
2443         if( flipy )
2444         {
2445            y_index = (sprite_screen_height-1)*dy;
2446            dy = -dy;
2447         }
2448         else
2449         {
2450            y_index = 0;
2451         }
2452
2453         if( sx < myclip.min_x)
2454         { /* clip left */
2455            int pixels = myclip.min_x-sx;
2456            sx += pixels;
2457            x_index_base += pixels*dx;
2458         }
2459         if( sy < myclip.min_y )
2460         { /* clip top */
2461            int pixels = myclip.min_y-sy;
2462            sy += pixels;
2463            y_index += pixels*dy;
2464         }
2465         /* NS 980211 - fixed incorrect clipping */
2466         if( ex > myclip.max_x+1 )
2467         { /* clip right */
2468            int pixels = ex-myclip.max_x-1;
2469            ex -= pixels;
2470         }
2471         if( ey > myclip.max_y+1 )
2472         { /* clip bottom */
2473            int pixels = ey-myclip.max_y-1;
2474            ey -= pixels;
2475         }
2476
2477         if( ex>sx )
2478         { /* skip if inner loop doesn't draw anything */
2479            int y;
2480
2481            /* case 0: STV_TRANSPARENCY_NONE */
2482            if (transparency == STV_TRANSPARENCY_NONE)
2483            {
2484               for( y=sy; y<ey; y++ )
2485               {
2486                  const UINT8 *source = source_base + (y_index>>16) * gfx->rowbytes();
2487                  UINT32 *dest = &dest_bmp.pix32(y);
2488
2489                  int x, x_index = x_index_base;
2490                  for( x=sx; x<ex; x++ )
2491                  {
2492                     dest[x] = pal[source[x_index>>16]];
2493                     x_index += dx;
2494                  }
2495
2496                  y_index += dy;
2497               }
2498            }
2499
2500            /* case 1: STV_TRANSPARENCY_PEN */
2501            if (transparency == STV_TRANSPARENCY_PEN)
2502            {
2503               for( y=sy; y<ey; y++ )
2504               {
2505                  const UINT8 *source = source_base + (y_index>>16) * gfx->rowbytes();
2506                  UINT32 *dest = &dest_bmp.pix32(y);
2507
2508                  int x, x_index = x_index_base;
2509                  for( x=sx; x<ex; x++ )
2510                  {
2511                     int c = source[x_index>>16];
2512                     if( c != transparent_color ) dest[x] = pal[c];
2513                     x_index += dx;
2514                  }
2515
2516                  y_index += dy;
2517               }
2518            }
2519
2520            /* case 6: STV_TRANSPARENCY_ALPHA */
2521            if (transparency == STV_TRANSPARENCY_ALPHA)
2522            {
2523               for( y=sy; y<ey; y++ )
2524               {
2525                  const UINT8 *source = source_base + (y_index>>16) * gfx->rowbytes();
2526                  UINT32 *dest = &dest_bmp.pix32(y);
2527
2528                  int x, x_index = x_index_base;
2529                  for( x=sx; x<ex; x++ )
2530                  {
2531                     int c = source[x_index>>16];
2532                     if( c != transparent_color ) dest[x] = alpha_blend_r32(dest[x], pal[c], alpha);
2533                     x_index += dx;
2534                  }
2535
2536                  y_index += dy;
2537               }
2538            }
2539
2540            /* case : STV_TRANSPARENCY_ADD_BLEND */
2541            if (transparency == STV_TRANSPARENCY_ADD_BLEND )
2542            {
2543               for( y=sy; y<ey; y++ )
2544               {
2545                  const UINT8 *source = source_base + (y_index>>16) * gfx->rowbytes();
2546                  UINT32 *dest = &dest_bmp.pix32(y);
2547
2548                  int x, x_index = x_index_base;
2549                  for( x=sx; x<ex; x++ )
2550                  {
2551                     int c = source[x_index>>16];
2552                     if( c != transparent_color ) dest[x] = stv_add_blend(dest[x],pal[c]);
2553                     x_index += dx;
2554                  }
2555
2556                  y_index += dy;
2557               }
2558            }
2559
2560         }
2561      }
2562   }
2563
2564}
2565
2566void saturn_state::stv_vdp2_drawgfxzoom_rgb555(
2567      bitmap_rgb32 &dest_bmp,const rectangle &clip,
2568      UINT32 code,UINT32 color,int flipx,int flipy,int sx,int sy,
2569      int transparency,int transparent_color,int scalex, int scaley,
2570      int sprite_screen_width, int sprite_screen_height, int alpha)
2571{
2572   rectangle myclip;
2573   UINT8* gfxdata;
2574
2575   gfxdata = m_vdp2.gfx_decode + code * 0x20;
2576
2577   if (!scalex || !scaley) return;
2578
2579   #if 0
2580   if (gfx->has_pen_usage() && transparency == STV_TRANSPARENCY_PEN)
2581   {
2582      int transmask = 0;
2583
2584      transmask = 1 << (transparent_color & 0xff);
2585
2586      if ((gfx->pen_usage(code) & ~transmask) == 0)
2587         /* character is totally transparent, no need to draw */
2588         return;
2589      else if ((gfx->pen_usage(code) & transmask) == 0)
2590         /* character is totally opaque, can disable transparency */
2591         transparency = STV_TRANSPARENCY_NONE;
2592   }
2593   #endif
2594
2595   /*
2596   scalex and scaley are 16.16 fixed point numbers
2597   1<<15 : shrink to 50%
2598   1<<16 : uniform scale
2599   1<<17 : double to 200%
2600   */
2601
2602
2603   /* KW 991012 -- Added code to force clip to bitmap boundary */
2604   myclip = clip;
2605   myclip &= dest_bmp.cliprect();
2606
2607//  if( gfx )
2608   {
2609//      const UINT8 *source_base = gfx->get_data(code % gfx->elements());
2610
2611      //int sprite_screen_height = (scaley*gfx->height()+0x8000)>>16;
2612      //int sprite_screen_width = (scalex*gfx->width()+0x8000)>>16;
2613
2614      if (sprite_screen_width && sprite_screen_height)
2615      {
2616         /* compute sprite increment per screen pixel */
2617         //int dx = (gfx->width()<<16)/sprite_screen_width;
2618         //int dy = (gfx->height()<<16)/sprite_screen_height;
2619         int dx = stv2_current_tilemap.incx;
2620         int dy = stv2_current_tilemap.incy;
2621
2622         int ex = sx+sprite_screen_width;
2623         int ey = sy+sprite_screen_height;
2624
2625         int x_index_base;
2626         int y_index;
2627
2628         if( flipx )
2629         {
2630            x_index_base = (sprite_screen_width-1)*dx;
2631            dx = -dx;
2632         }
2633         else
2634         {
2635            x_index_base = 0;
2636         }
2637
2638         if( flipy )
2639         {
2640            y_index = (sprite_screen_height-1)*dy;
2641            dy = -dy;
2642         }
2643         else
2644         {
2645            y_index = 0;
2646         }
2647
2648         if( sx < myclip.min_x)
2649         { /* clip left */
2650            int pixels = myclip.min_x-sx;
2651            sx += pixels;
2652            x_index_base += pixels*dx;
2653         }
2654         if( sy < myclip.min_y )
2655         { /* clip top */
2656            int pixels = myclip.min_y-sy;
2657            sy += pixels;
2658            y_index += pixels*dy;
2659         }
2660         /* NS 980211 - fixed incorrect clipping */
2661         if( ex > myclip.max_x+1 )
2662         { /* clip right */
2663            int pixels = ex-myclip.max_x-1;
2664            ex -= pixels;
2665         }
2666         if( ey > myclip.max_y+1 )
2667         { /* clip bottom */
2668            int pixels = ey-myclip.max_y-1;
2669            ey -= pixels;
2670         }
2671
2672         if( ex>sx )
2673         { /* skip if inner loop doesn't draw anything */
2674            int y;
2675
2676            /* case 0: STV_TRANSPARENCY_NONE */
2677            if (transparency == STV_TRANSPARENCY_NONE)
2678            {
2679               for( y=sy; y<ey; y++ )
2680               {
2681                  const UINT8 *source = gfxdata + (y_index>>16)*16;
2682                  UINT32 *dest = &dest_bmp.pix32(y);
2683                  int r,g,b,data;
2684
2685                  int x, x_index = x_index_base;
2686                  for( x=sx; x<ex; x++ )
2687                  {
2688                     data = (source[(x_index>>16)*2] << 8) | source[(x_index>>16)*2+1];
2689                     b = pal5bit((data & 0x7c00) >> 10);
2690                     g = pal5bit((data & 0x03e0) >> 5);
2691                     r = pal5bit( data & 0x001f);
2692                     if(stv2_current_tilemap.fade_control & 1)
2693                        stv_vdp2_compute_color_offset(&r,&g,&b,stv2_current_tilemap.fade_control & 2);
2694
2695                     dest[x] = MAKE_RGB(r, g, b);
2696                     x_index += dx;
2697                  }
2698
2699                  y_index += dy;
2700               }
2701            }
2702
2703            /* case 1: STV_TRANSPARENCY_PEN */
2704            if (transparency == STV_TRANSPARENCY_PEN)
2705            {
2706               for( y=sy; y<ey; y++ )
2707               {
2708                  const UINT8 *source = gfxdata + (y_index>>16)*16;
2709                  UINT32 *dest = &dest_bmp.pix32(y);
2710                  int r,g,b,data;
2711
2712                  int x, x_index = x_index_base;
2713                  for( x=sx; x<ex; x++ )
2714                  {
2715                     data = (source[(x_index>>16)*2] << 8) | source[(x_index>>16)*2+1];
2716                     b = pal5bit((data & 0x7c00) >> 10);
2717                     g = pal5bit((data & 0x03e0) >> 5);
2718                     r = pal5bit( data & 0x001f);
2719                     if(stv2_current_tilemap.fade_control & 1)
2720                        stv_vdp2_compute_color_offset(&r,&g,&b,stv2_current_tilemap.fade_control & 2);
2721
2722                     if( data ) dest[x] = MAKE_RGB(r, g, b);
2723                     x_index += dx;
2724                  }
2725
2726                  y_index += dy;
2727               }
2728            }
2729
2730            /* case 6: STV_TRANSPARENCY_ALPHA */
2731            if (transparency == STV_TRANSPARENCY_ALPHA)
2732            {
2733               for( y=sy; y<ey; y++ )
2734               {
2735                  const UINT8 *source = gfxdata + (y_index>>16)*16;
2736                  UINT32 *dest = &dest_bmp.pix32(y);
2737                  int r,g,b,data;
2738
2739                  int x, x_index = x_index_base;
2740                  for( x=sx; x<ex; x++ )
2741                  {
2742                     data = (source[(x_index>>16)*2] << 8) | source[(x_index>>16)*2+1];
2743                     b = pal5bit((data & 0x7c00) >> 10);
2744                     g = pal5bit((data & 0x03e0) >> 5);
2745                     r = pal5bit( data & 0x001f);
2746                     if(stv2_current_tilemap.fade_control & 1)
2747                        stv_vdp2_compute_color_offset(&r,&g,&b,stv2_current_tilemap.fade_control & 2);
2748
2749                     if( data ) dest[x] = alpha_blend_r32(dest[x], MAKE_RGB(r, g, b), alpha);
2750                     x_index += dx;
2751                  }
2752
2753                  y_index += dy;
2754               }
2755            }
2756
2757            /* case : STV_TRANSPARENCY_ADD_BLEND */
2758            if (transparency == STV_TRANSPARENCY_ADD_BLEND )
2759            {
2760               for( y=sy; y<ey; y++ )
2761               {
2762                  const UINT8 *source = gfxdata + (y_index>>16)*16;
2763                  UINT32 *dest = &dest_bmp.pix32(y);
2764                  int r,g,b,data;
2765
2766                  int x, x_index = x_index_base;
2767                  for( x=sx; x<ex; x++ )
2768                  {
2769                     data = (source[(x_index*2+0)>>16]<<0)|(source[(x_index*2+1)>>16]<<8);
2770                     b = pal5bit((data & 0x7c00) >> 10);
2771                     g = pal5bit((data & 0x03e0) >> 5);
2772                     r = pal5bit( data & 0x001f);
2773                     if(stv2_current_tilemap.fade_control & 1)
2774                        stv_vdp2_compute_color_offset(&r,&g,&b,stv2_current_tilemap.fade_control & 2);
2775
2776                     if( data ) dest[x] = stv_add_blend(dest[x], MAKE_RGB(r, g, b));
2777                     x_index += dx;
2778                  }
2779
2780                  y_index += dy;
2781               }
2782            }
2783
2784         }
2785      }
2786   }
2787
2788}
2789
2790
2791void saturn_state::stv_vdp2_drawgfx_rgb555( bitmap_rgb32 &dest_bmp, const rectangle &clip, UINT32 code, int flipx, int flipy, int sx, int sy, int transparency, int alpha)
2792{
2793   rectangle myclip;
2794   UINT8* gfxdata;
2795   int sprite_screen_width, sprite_screen_height;
2796
2797   gfxdata = m_vdp2.gfx_decode + code * 0x20;
2798   sprite_screen_width = sprite_screen_height = 8;
2799
2800   /* KW 991012 -- Added code to force clip to bitmap boundary */
2801   myclip = clip;
2802   myclip &= dest_bmp.cliprect();
2803
2804   {
2805      int dx = stv2_current_tilemap.incx;
2806      int dy = stv2_current_tilemap.incy;
2807
2808      int ex = sx+sprite_screen_width;
2809      int ey = sy+sprite_screen_height;
2810
2811      int x_index_base;
2812      int y_index;
2813
2814      if( flipx )
2815      {
2816         x_index_base = (sprite_screen_width-1)*dx;
2817         dx = -dx;
2818      }
2819      else
2820      {
2821         x_index_base = 0;
2822      }
2823
2824      if( flipy )
2825      {
2826         y_index = (sprite_screen_height-1)*dy;
2827         dy = -dy;
2828      }
2829      else
2830      {
2831         y_index = 0;
2832      }
2833
2834      if( sx < myclip.min_x)
2835      { /* clip left */
2836         int pixels = myclip.min_x-sx;
2837         sx += pixels;
2838         x_index_base += pixels*dx;
2839      }
2840      if( sy < myclip.min_y )
2841      { /* clip top */
2842         int pixels = myclip.min_y-sy;
2843         sy += pixels;
2844         y_index += pixels*dy;
2845      }
2846      /* NS 980211 - fixed incorrect clipping */
2847      if( ex > myclip.max_x+1 )
2848      { /* clip right */
2849         int pixels = ex-myclip.max_x-1;
2850         ex -= pixels;
2851      }
2852      if( ey > myclip.max_y+1 )
2853      { /* clip bottom */
2854         int pixels = ey-myclip.max_y-1;
2855         ey -= pixels;
2856      }
2857
2858      if( ex>sx )
2859      { /* skip if inner loop doesn't draw anything */
2860         int y;
2861
2862         for( y=sy; y<ey; y++ )
2863         {
2864            const UINT8 *source = gfxdata + (y_index>>16)*16;
2865            UINT32 *dest = &dest_bmp.pix32(y);
2866            UINT16 data;
2867
2868            int x, x_index = x_index_base;
2869            for( x=sx; x<ex; x++ )
2870            {
2871               int r,g,b;
2872
2873               data = (source[(x_index>>16)*2] << 8) | source[(x_index>>16)*2+1];
2874               if ((data & 0x8000) || (transparency == STV_TRANSPARENCY_NONE))
2875               {
2876                  b = pal5bit((data & 0x7c00) >> 10);
2877                  g = pal5bit((data & 0x03e0) >> 5);
2878                  r = pal5bit( data & 0x001f);
2879                  if(stv2_current_tilemap.fade_control & 1)
2880                     stv_vdp2_compute_color_offset(&r,&g,&b,stv2_current_tilemap.fade_control & 2);
2881
2882                  if ( transparency == STV_TRANSPARENCY_ALPHA )
2883                     dest[x] = alpha_blend_r32( dest[x], MAKE_RGB(r, g, b), alpha );
2884                  else
2885                     dest[x] = MAKE_RGB(r, g, b);
2886               }
2887               x_index += dx;
2888            }
2889
2890            y_index += dy;
2891         }
2892
2893      }
2894
2895   }
2896
2897}
2898
2899
2900void saturn_state::stv_vdp2_drawgfx_rgb888( bitmap_rgb32 &dest_bmp, const rectangle &clip, UINT32 code, int flipx, int flipy,
2901                              int sx, int sy, int transparency, int alpha)
2902{
2903   rectangle myclip;
2904   UINT8* gfxdata;
2905   int sprite_screen_width, sprite_screen_height;
2906
2907   gfxdata = m_vdp2.gfx_decode + code * 0x20;
2908   sprite_screen_width = sprite_screen_height = 8;
2909
2910   /* KW 991012 -- Added code to force clip to bitmap boundary */
2911   myclip = clip;
2912   myclip &= dest_bmp.cliprect();
2913   {
2914      int dx = stv2_current_tilemap.incx;
2915      int dy = stv2_current_tilemap.incy;
2916
2917      int ex = sx+sprite_screen_width;
2918      int ey = sy+sprite_screen_height;
2919
2920      int x_index_base;
2921      int y_index;
2922
2923      if( flipx )
2924      {
2925         x_index_base = (sprite_screen_width-1)*dx;
2926         dx = -dx;
2927      }
2928      else
2929      {
2930         x_index_base = 0;
2931      }
2932
2933      if( flipy )
2934      {
2935         y_index = (sprite_screen_height-1)*dy;
2936         dy = -dy;
2937      }
2938      else
2939      {
2940         y_index = 0;
2941      }
2942
2943      if( sx < myclip.min_x)
2944      { /* clip left */
2945         int pixels = myclip.min_x-sx;
2946         sx += pixels;
2947         x_index_base += pixels*dx;
2948      }
2949      if( sy < myclip.min_y )
2950      { /* clip top */
2951         int pixels = myclip.min_y-sy;
2952         sy += pixels;
2953         y_index += pixels*dy;
2954      }
2955      /* NS 980211 - fixed incorrect clipping */
2956      if( ex > myclip.max_x+1 )
2957      { /* clip right */
2958         int pixels = ex-myclip.max_x-1;
2959         ex -= pixels;
2960      }
2961      if( ey > myclip.max_y+1 )
2962      { /* clip bottom */
2963         int pixels = ey-myclip.max_y-1;
2964         ey -= pixels;
2965      }
2966
2967      if( ex>sx )
2968      { /* skip if inner loop doesn't draw anything */
2969         int y;
2970
2971         for( y=sy; y<ey; y++ )
2972         {
2973            const UINT8 *source = gfxdata + (y_index>>16)*32;
2974            UINT32 *dest = &dest_bmp.pix32(y);
2975            UINT32 data;
2976
2977            int x, x_index = x_index_base;
2978
2979            for( x=sx; x<ex; x++ )
2980            {
2981               int r,g,b;
2982
2983               data = (source[(x_index>>16)*4+0] << 24) | (source[(x_index>>16)*4+1] << 16) | (source[(x_index>>16)*4+2] << 8) | (source[(x_index>>16)*4+3] << 0);
2984               if ((data & 0x80000000) || (transparency == STV_TRANSPARENCY_NONE))
2985               {
2986                  b = (data & 0xff0000) >> 16;
2987                  g = (data & 0x00ff00) >> 8;
2988                  r = (data & 0x0000ff);
2989
2990                  if(stv2_current_tilemap.fade_control & 1)
2991                     stv_vdp2_compute_color_offset(&r,&g,&b,stv2_current_tilemap.fade_control & 2);
2992
2993                  if ( transparency == STV_TRANSPARENCY_ALPHA )
2994                     dest[x] = alpha_blend_r32( dest[x], MAKE_RGB(r, g, b), alpha );
2995                  else
2996                     dest[x] = MAKE_RGB(r, g, b);
2997               }
2998               x_index += dx;
2999            }
3000
3001            y_index += dy;
3002         }
3003
3004      }
3005
3006   }
3007
3008}
3009
3010void saturn_state::draw_4bpp_bitmap(bitmap_rgb32 &bitmap, const rectangle &cliprect)
3011{
3012   int xsize, ysize, xsize_mask, ysize_mask;
3013   int xsrc,ysrc,xdst,ydst;
3014   int src_offs;
3015   UINT8* vram = m_vdp2.gfx_decode;
3016   UINT32 map_offset = stv2_current_tilemap.bitmap_map * 0x20000;
3017   int scrollx = stv2_current_tilemap.scrollx;
3018   int scrolly = stv2_current_tilemap.scrolly;
3019   UINT16 dot_data;
3020   UINT16 pal_bank;
3021
3022   xsize = (stv2_current_tilemap.bitmap_size & 2) ? 1024 : 512;
3023   ysize = (stv2_current_tilemap.bitmap_size & 1) ? 512 : 256;
3024
3025   xsize_mask = (stv2_current_tilemap.linescroll_enable) ? 1024 : xsize;
3026   ysize_mask = (stv2_current_tilemap.vertical_linescroll_enable) ? 512 : ysize;
3027
3028   pal_bank = stv2_current_tilemap.bitmap_palette_number;
3029   pal_bank+= stv2_current_tilemap.colour_ram_address_offset;
3030   pal_bank&= 7;
3031   pal_bank<<=8;
3032   if(stv2_current_tilemap.fade_control & 1)
3033      pal_bank += ((stv2_current_tilemap.fade_control & 2) ? (2*2048) : (2048));
3034
3035   for(ydst=cliprect.min_y;ydst<=cliprect.max_y;ydst++)
3036   {
3037      for(xdst=cliprect.min_x;xdst<=cliprect.max_x;xdst++)
3038      {
3039         if(stv_vdp2_window_process(xdst,ydst))
3040            continue;
3041
3042         xsrc = (xdst + scrollx) & (xsize_mask-1);
3043         ysrc = (ydst + scrolly) & (ysize_mask-1);
3044         src_offs = (xsrc + (ysrc*xsize));
3045         src_offs/= 2;
3046         src_offs += map_offset;
3047         src_offs &= 0x7ffff;
3048
3049         dot_data = vram[src_offs] >> ((xsrc & 1) ? 0 : 4);
3050         dot_data&= 0xf;
3051
3052         if ((dot_data != 0) || (stv2_current_tilemap.transparency == STV_TRANSPARENCY_NONE))
3053         {
3054            dot_data += pal_bank;
3055
3056            if ( stv2_current_tilemap.colour_calculation_enabled == 0 )
3057               bitmap.pix32(ydst, xdst) = machine().pens[dot_data];
3058            else
3059               bitmap.pix32(ydst, xdst) = alpha_blend_r32(bitmap.pix32(ydst, xdst), machine().pens[dot_data], stv2_current_tilemap.alpha);
3060         }
3061      }
3062   }
3063}
3064
3065
3066void saturn_state::draw_8bpp_bitmap(bitmap_rgb32 &bitmap, const rectangle &cliprect)
3067{
3068   int xsize, ysize, xsize_mask, ysize_mask;
3069   int xsrc,ysrc,xdst,ydst;
3070   int src_offs;
3071   UINT8* vram = m_vdp2.gfx_decode;
3072   UINT32 map_offset = stv2_current_tilemap.bitmap_map * 0x20000;
3073   int scrollx = stv2_current_tilemap.scrollx;
3074   int scrolly = stv2_current_tilemap.scrolly;
3075   UINT16 dot_data;
3076   UINT16 pal_bank;
3077   int xf, yf;
3078
3079   xsize = (stv2_current_tilemap.bitmap_size & 2) ? 1024 : 512;
3080   ysize = (stv2_current_tilemap.bitmap_size & 1) ? 512 : 256;
3081
3082   xsize_mask = (stv2_current_tilemap.linescroll_enable) ? 1024 : xsize;
3083   ysize_mask = (stv2_current_tilemap.vertical_linescroll_enable) ? 512 : ysize;
3084
3085   pal_bank = stv2_current_tilemap.bitmap_palette_number;
3086   pal_bank+= stv2_current_tilemap.colour_ram_address_offset;
3087   pal_bank&= 7;
3088   pal_bank<<=8;
3089   if(stv2_current_tilemap.fade_control & 1)
3090      pal_bank += ((stv2_current_tilemap.fade_control & 2) ? (2*2048) : (2048));
3091
3092   for(ydst=cliprect.min_y;ydst<=cliprect.max_y;ydst++)
3093   {
3094      for(xdst=cliprect.min_x;xdst<=cliprect.max_x;xdst++)
3095      {
3096         if(stv_vdp2_window_process(xdst,ydst))
3097            continue;
3098
3099         xf = stv2_current_tilemap.incx * xdst;
3100         xf>>=16;
3101         yf = stv2_current_tilemap.incy * ydst;
3102         yf>>=16;
3103
3104         xsrc = (xf + scrollx) & (xsize_mask-1);
3105         ysrc = (yf + scrolly) & (ysize_mask-1);
3106         src_offs = (xsrc + (ysrc*xsize));
3107         src_offs += map_offset;
3108         src_offs &= 0x7ffff;
3109
3110         dot_data = vram[src_offs];
3111
3112         if ((dot_data != 0) || (stv2_current_tilemap.transparency == STV_TRANSPARENCY_NONE))
3113         {
3114            dot_data += pal_bank;
3115
3116            if ( stv2_current_tilemap.colour_calculation_enabled == 0 )
3117               bitmap.pix32(ydst, xdst) = machine().pens[dot_data];
3118            else
3119               bitmap.pix32(ydst, xdst) = alpha_blend_r32(bitmap.pix32(ydst, xdst), machine().pens[dot_data], stv2_current_tilemap.alpha);
3120         }
3121      }
3122   }
3123}
3124
3125void saturn_state::draw_rgb15_bitmap(bitmap_rgb32 &bitmap, const rectangle &cliprect)
3126{
3127   int xsize, ysize, xsize_mask, ysize_mask;
3128   int xsrc,ysrc,xdst,ydst;
3129   int src_offs;
3130   UINT8* vram = m_vdp2.gfx_decode;
3131   UINT32 map_offset = stv2_current_tilemap.bitmap_map * 0x20000;
3132   int scrollx = stv2_current_tilemap.scrollx;
3133   int scrolly = stv2_current_tilemap.scrolly;
3134   int r,g,b;
3135   UINT16 dot_data;
3136   int xf, yf;
3137
3138   xsize = (stv2_current_tilemap.bitmap_size & 2) ? 1024 : 512;
3139   ysize = (stv2_current_tilemap.bitmap_size & 1) ? 512 : 256;
3140
3141   xsize_mask = (stv2_current_tilemap.linescroll_enable) ? 1024 : xsize;
3142   ysize_mask = (stv2_current_tilemap.vertical_linescroll_enable) ? 512 : ysize;
3143
3144   for(ydst=cliprect.min_y;ydst<=cliprect.max_y;ydst++)
3145   {
3146      for(xdst=cliprect.min_x;xdst<=cliprect.max_x;xdst++)
3147      {
3148         if(stv_vdp2_window_process(xdst,ydst))
3149            continue;
3150
3151         xf = stv2_current_tilemap.incx * xdst;
3152         xf>>=16;
3153         yf = stv2_current_tilemap.incy * ydst;
3154         yf>>=16;
3155
3156         xsrc = (xf + scrollx) & (xsize_mask-1);
3157         ysrc = (yf + scrolly) & (ysize_mask-1);
3158         src_offs = (xsrc + (ysrc*xsize));
3159         src_offs *= 2;
3160         src_offs += map_offset;
3161         src_offs &= 0x7ffff;
3162
3163         dot_data =(vram[src_offs]<<8)|(vram[src_offs+1]<<0);
3164
3165         if ((dot_data & 0x8000) || (stv2_current_tilemap.transparency == STV_TRANSPARENCY_NONE))
3166         {
3167            b = pal5bit((dot_data & 0x7c00) >> 10);
3168            g = pal5bit((dot_data & 0x03e0) >> 5);
3169            r = pal5bit((dot_data & 0x001f) >> 0);
3170
3171            if(stv2_current_tilemap.fade_control & 1)
3172               stv_vdp2_compute_color_offset(&r,&g,&b,stv2_current_tilemap.fade_control & 2);
3173
3174            if ( stv2_current_tilemap.colour_calculation_enabled == 0 )
3175               bitmap.pix32(ydst, xdst) = MAKE_RGB(r, g, b);
3176            else
3177               bitmap.pix32(ydst, xdst) = alpha_blend_r32( bitmap.pix32(ydst, xdst), MAKE_RGB(r, g, b), stv2_current_tilemap.alpha );
3178         }
3179      }
3180   }
3181}
3182
3183void saturn_state::draw_rgb32_bitmap(bitmap_rgb32 &bitmap, const rectangle &cliprect)
3184{
3185   int xsize, ysize, xsize_mask, ysize_mask;
3186   int xsrc,ysrc,xdst,ydst;
3187   int src_offs;
3188   UINT8* vram = m_vdp2.gfx_decode;
3189   UINT32 map_offset = stv2_current_tilemap.bitmap_map * 0x20000;
3190   int scrollx = stv2_current_tilemap.scrollx;
3191   int scrolly = stv2_current_tilemap.scrolly;
3192   int r,g,b;
3193   UINT32 dot_data;
3194
3195   xsize = (stv2_current_tilemap.bitmap_size & 2) ? 1024 : 512;
3196   ysize = (stv2_current_tilemap.bitmap_size & 1) ? 512 : 256;
3197
3198   xsize_mask = (stv2_current_tilemap.linescroll_enable) ? 1024 : xsize;
3199   ysize_mask = (stv2_current_tilemap.vertical_linescroll_enable) ? 512 : ysize;
3200
3201   for(ydst=cliprect.min_y;ydst<=cliprect.max_y;ydst++)
3202   {
3203      for(xdst=cliprect.min_x;xdst<=cliprect.max_x;xdst++)
3204      {
3205         if(stv_vdp2_window_process(xdst,ydst))
3206            continue;
3207
3208         xsrc = (xdst + scrollx) & (xsize_mask-1);
3209         ysrc = (ydst + scrolly) & (ysize_mask-1);
3210         src_offs = (xsrc + (ysrc*xsize));
3211         src_offs *= 4;
3212         src_offs += map_offset;
3213         src_offs &= 0x7ffff;
3214
3215         dot_data = (vram[src_offs+0]<<24)|(vram[src_offs+1]<<16)|(vram[src_offs+2]<<8)|(vram[src_offs+3]<<0);
3216
3217         if ((dot_data & 0x80000000) || (stv2_current_tilemap.transparency == STV_TRANSPARENCY_NONE))
3218         {
3219            b = ((dot_data & 0x00ff0000) >> 16);
3220            g = ((dot_data & 0x0000ff00) >> 8);
3221            r = ((dot_data & 0x000000ff) >> 0);
3222
3223            if(stv2_current_tilemap.fade_control & 1)
3224               stv_vdp2_compute_color_offset(&r,&g,&b,stv2_current_tilemap.fade_control & 2);
3225
3226            if ( stv2_current_tilemap.colour_calculation_enabled == 0 )
3227               bitmap.pix32(ydst, xdst) = MAKE_RGB(r, g, b);
3228            else
3229               bitmap.pix32(ydst, xdst) = alpha_blend_r32( bitmap.pix32(ydst, xdst), MAKE_RGB(r, g, b), stv2_current_tilemap.alpha );
3230         }
3231      }
3232   }
3233}
3234
3235
3236void saturn_state::stv_vdp2_draw_basic_bitmap(bitmap_rgb32 &bitmap, const rectangle &cliprect)
3237{
3238//  if(LOG_VDP2) logerror ("bitmap enable %02x size %08x depth %08x\n", stv2_current_tilemap.layer_name, stv2_current_tilemap.bitmap_size, stv2_current_tilemap.colour_depth);
3239//  popmessage ("bitmap enable %02x size %08x depth %08x number %02x", stv2_current_tilemap.layer_name, stv2_current_tilemap.bitmap_size, stv2_current_tilemap.colour_depth,stv2_current_tilemap.bitmap_palette_number);
3240   //popmessage("%04x",STV_VDP2_SCRCTL);
3241
3242   int xsize = 0, xsizemask = 0;
3243   int ysize = 0/*, ysizemask = 0*/;
3244   int xlinesize = 0/*, xpixelsize = 0*/;
3245   int xcnt,ycnt;
3246   UINT8* gfxdata = m_vdp2.gfx_decode;
3247   UINT32 *destline;
3248   UINT16 pal_color_offset = 0;
3249   UINT8* gfxdatalow, *gfxdatahigh;
3250   int screen_x,screen_y;
3251
3252   if (!stv2_current_tilemap.enabled) return;
3253
3254   /* new bitmap code, supposed to rewrite the old one. Not supposed to be clean, but EFFICIENT! */
3255   if(stv2_current_tilemap.incx == 0x10000 && stv2_current_tilemap.incy == 0x10000)
3256   {
3257      switch(stv2_current_tilemap.colour_depth)
3258      {
3259         case 0: draw_4bpp_bitmap(bitmap,cliprect); return;
3260         case 1: draw_8bpp_bitmap(bitmap,cliprect); return;
3261         case 3: draw_rgb15_bitmap(bitmap,cliprect); return;
3262         case 4: draw_rgb32_bitmap(bitmap,cliprect); return;
3263      }
3264
3265      /* intentional fall-through*/
3266      popmessage("%d %s %s %s %s",stv2_current_tilemap.colour_depth,
3267                           stv2_current_tilemap.transparency == STV_TRANSPARENCY_NONE ? "no trans" : "trans",
3268                           stv2_current_tilemap.window_control & 6 ? "window" : "no window",
3269                           stv2_current_tilemap.colour_calculation_enabled ? "cc" : "no cc",
3270                           (stv2_current_tilemap.incx == 0x10000 && stv2_current_tilemap.incy == 0x10000) ? "no zoom" : "zoom");
3271   }
3272   else
3273   {
3274      switch(stv2_current_tilemap.colour_depth)
3275      {
3276      //  case 0: draw_4bpp_bitmap(bitmap,cliprect); return;
3277         case 1: draw_8bpp_bitmap(bitmap,cliprect); return;
3278         case 3: draw_rgb15_bitmap(bitmap,cliprect); return;
3279      //  case 4: draw_rgb32_bitmap(bitmap,cliprect); return;
3280      }
3281
3282      /* intentional fall-through*/
3283      popmessage("%d %s %s %s %s",stv2_current_tilemap.colour_depth,
3284                           stv2_current_tilemap.transparency == STV_TRANSPARENCY_NONE ? "no trans" : "trans",
3285                           stv2_current_tilemap.window_control & 6 ? "window" : "no window",
3286                           stv2_current_tilemap.colour_calculation_enabled ? "cc" : "no cc",
3287                           (stv2_current_tilemap.incx == 0x10000 && stv2_current_tilemap.incy == 0x10000) ? "no zoom" : "zoom");
3288   }
3289
3290   /* size for n0 / n1 */
3291   switch (stv2_current_tilemap.bitmap_size)
3292   {
3293      case 0: xsize=512; ysize=256; break;
3294      case 1: xsize=512; ysize=512; break;
3295      case 2: xsize=1024; ysize=256; break;
3296      case 3: xsize=1024; ysize=512; break;
3297   }
3298   xsizemask = xsize - 1;
3299   /*ysizemask = ysize - 1;*/
3300
3301   switch( stv2_current_tilemap.colour_depth )
3302   {
3303      case 0: xlinesize = xsize / 2; /*xpixelsize = 0;*/ break;
3304      case 1: xlinesize = xsize; /*xpixelsize = 1;*/ break;
3305      case 2: case 3: xlinesize = xsize * 2; /*xpixelsize = 2;*/ break;
3306      case 4: xlinesize = xsize * 4; /*xpixelsize = 4;*/ break;
3307   }
3308
3309   if(stv2_current_tilemap.colour_depth == 0)
3310      stv2_current_tilemap.scrollx /= 2;
3311   if(stv2_current_tilemap.colour_depth == 2 || stv2_current_tilemap.colour_depth == 3)
3312      stv2_current_tilemap.scrollx*=2;
3313   if(stv2_current_tilemap.colour_depth == 4)
3314      stv2_current_tilemap.scrollx*=4;
3315
3316   gfxdatalow = gfxdata + stv2_current_tilemap.bitmap_map * 0x20000;
3317   gfxdata+=(
3318   (stv2_current_tilemap.scrollx & (xlinesize-1)) +
3319   ((stv2_current_tilemap.scrolly & (ysize-1)) * (xlinesize)) + /* TODO: mask ysize, check me! */
3320   (stv2_current_tilemap.bitmap_map * 0x20000)
3321   );
3322   gfxdatahigh = gfxdatalow + xlinesize*ysize;
3323
3324//  popmessage("%04x %04x",stv2_current_tilemap.scrollx,stv2_current_tilemap.scrolly);
3325
3326   /*Enable fading bit*/
3327   if(stv2_current_tilemap.fade_control & 1)
3328   {
3329      /*Select fading bit*/
3330      pal_color_offset += ((stv2_current_tilemap.fade_control & 2) ? (2*2048) : (2048));
3331   }
3332
3333   stv2_current_tilemap.bitmap_palette_number+=stv2_current_tilemap.colour_ram_address_offset;
3334   stv2_current_tilemap.bitmap_palette_number&=7;//safety check
3335
3336   screen_x = machine().primary_screen->visible_area().max_x;
3337   screen_y = machine().primary_screen->visible_area().max_y;
3338
3339   switch(stv2_current_tilemap.colour_depth)
3340   {
3341      /*Palette Format*/
3342      case 0:
3343         for (ycnt = 0; ycnt <ysize;ycnt++)
3344         {
3345            for (xcnt = 0; xcnt <xsize;xcnt+=2)
3346            {
3347               if (!stv_vdp2_window_process(xcnt+1,ycnt))
3348               {
3349                  if ((gfxdata[0] & 0x0f) || (stv2_current_tilemap.transparency == STV_TRANSPARENCY_NONE))
3350                  {
3351                     if (((xcnt + 1) <= screen_x) && (ycnt <= screen_y))
3352                     {
3353                        if ( stv2_current_tilemap.colour_calculation_enabled == 0 )
3354                           bitmap.pix32(ycnt, xcnt+1) = machine().pens[((gfxdata[0] & 0x0f) >> 0) | (stv2_current_tilemap.bitmap_palette_number * 0x100) | pal_color_offset];
3355                        else
3356                           bitmap.pix32(ycnt, xcnt+1) = alpha_blend_r32(bitmap.pix32(ycnt, xcnt+1), machine().pens[((gfxdata[0] & 0x0f) >> 0) | (stv2_current_tilemap.bitmap_palette_number * 0x100) | pal_color_offset], stv2_current_tilemap.alpha);
3357                     }
3358                  }
3359               }
3360               if (!stv_vdp2_window_process(xcnt,ycnt))
3361               {
3362                  if ((gfxdata[0] & 0xf0) || (stv2_current_tilemap.transparency == STV_TRANSPARENCY_NONE))
3363                  {
3364                     if (((xcnt + 0) <= screen_x) && (ycnt <= screen_y))
3365                     {
3366                        if ( stv2_current_tilemap.colour_calculation_enabled == 0 )
3367                           bitmap.pix32(ycnt, xcnt) = machine().pens[((gfxdata[0] & 0xf0) >> 4) | (stv2_current_tilemap.bitmap_palette_number * 0x100) | pal_color_offset];
3368                        else
3369                           bitmap.pix32(ycnt, xcnt) = alpha_blend_r32(bitmap.pix32(ycnt, xcnt), machine().pens[((gfxdata[0] & 0xf0) >> 4) | (stv2_current_tilemap.bitmap_palette_number * 0x100) | pal_color_offset], stv2_current_tilemap.alpha);
3370                     }
3371                  }
3372               }
3373               gfxdata++;
3374               if ( gfxdata >= gfxdatahigh ) gfxdata = gfxdatalow;
3375            }
3376         }
3377         break;
3378      case 1:
3379         if ( stv2_current_tilemap.incx == 0x10000 && stv2_current_tilemap.incy == 0x10000 )
3380         {
3381            //int gfx_wraparound = -1;
3382
3383            gfxdata += xlinesize*cliprect.min_y;
3384
3385            for (ycnt = cliprect.min_y; ycnt <= cliprect.max_y; ycnt++)
3386            {
3387               for (xcnt = cliprect.min_x; xcnt <= cliprect.max_x; xcnt++)
3388               {
3389                  int xs = xcnt & xsizemask;
3390
3391                  if (!stv_vdp2_window_process(xcnt,ycnt))
3392                  {
3393                     //60aee2c = $0013 at @605d838
3394                     if ((gfxdata[xs] & 0xff) || (stv2_current_tilemap.transparency == STV_TRANSPARENCY_NONE))
3395                     {
3396                        if (((xcnt + 0) <= screen_x) && (ycnt <= screen_y))
3397                        {
3398                           if ( stv2_current_tilemap.colour_calculation_enabled == 0 )
3399                              bitmap.pix32(ycnt, xcnt) = machine().pens[(gfxdata[xs] & 0xff) | (stv2_current_tilemap.bitmap_palette_number * 0x100) | pal_color_offset];
3400                           else
3401                              bitmap.pix32(ycnt, xcnt) = alpha_blend_r32(bitmap.pix32(ycnt, xcnt), machine().pens[(gfxdata[xs] & 0xff) | (stv2_current_tilemap.bitmap_palette_number * 0x100) | pal_color_offset], stv2_current_tilemap.alpha);
3402                        }
3403                     }
3404                  }
3405                  if ( (gfxdata + xs) >= gfxdatahigh )
3406                  {
3407                     //gfx_wraparound = (ycnt << 16) | xcnt;
3408                     gfxdata = gfxdatalow - xs;
3409                  }
3410               }
3411               if ( (gfxdata + xlinesize) < gfxdatahigh )
3412               {
3413                  gfxdata += xlinesize;
3414               }
3415               else
3416               {
3417                  gfxdata = gfxdatalow + ((gfxdata + xlinesize) - gfxdatahigh);
3418               }
3419            }
3420
3421         }
3422         else
3423         {
3424            int xx, xs, yy=0;
3425            for (ycnt = cliprect.min_y; ycnt <= cliprect.max_y; yy+=stv2_current_tilemap.incy, ycnt++ )
3426            {
3427               gfxdata += xlinesize*(yy>>16);
3428               yy &= 0xffff;
3429
3430               xx = 0;
3431               for (xcnt = cliprect.min_x; xcnt <= cliprect.max_x; xx+=stv2_current_tilemap.incx, xcnt++)
3432               {
3433                  xs = xx >> 16;
3434                  if (!stv_vdp2_window_process(xcnt,ycnt))
3435                  {
3436                     if ((gfxdata[xs] & 0xff) || (stv2_current_tilemap.transparency == STV_TRANSPARENCY_NONE))
3437                     {
3438                        if (((xcnt + 0) <= screen_x) && (ycnt <= screen_y))
3439                        {
3440                           if ( stv2_current_tilemap.colour_calculation_enabled == 0 )
3441                              bitmap.pix32(ycnt, xcnt) = machine().pens[(gfxdata[xs] & 0xff) | (stv2_current_tilemap.bitmap_palette_number * 0x100) | pal_color_offset];
3442                           else
3443                              bitmap.pix32(ycnt, xcnt) = alpha_blend_r32(bitmap.pix32(ycnt, xcnt), machine().pens[(gfxdata[xs] & 0xff) | (stv2_current_tilemap.bitmap_palette_number * 0x100) | pal_color_offset], stv2_current_tilemap.alpha);
3444                        }
3445                     }
3446                  }
3447
3448                  if ( (gfxdata + xs) >= gfxdatahigh ) gfxdata = gfxdatalow;
3449
3450               }
3451            }
3452         }
3453         break;
3454      case 2:
3455         for (ycnt = 0; ycnt <ysize;ycnt++)
3456         {
3457            for (xcnt = 0; xcnt <xsize;xcnt++)
3458            {
3459               if (!stv_vdp2_window_process(xcnt,ycnt))
3460               {
3461                  if (((gfxdata[0] & 0x07) | (gfxdata[1] & 0xff)) || (stv2_current_tilemap.transparency == STV_TRANSPARENCY_NONE))
3462                  {
3463                     if (((xcnt + 0) <= screen_x) && (ycnt <= screen_y))
3464                     {
3465                        if ( stv2_current_tilemap.colour_calculation_enabled == 0 )
3466                           bitmap.pix32(ycnt, xcnt) = machine().pens[((gfxdata[0] & 0x07) * 0x100) | (gfxdata[1] & 0xff) | pal_color_offset];
3467                        else
3468                           bitmap.pix32(ycnt, xcnt) = alpha_blend_r32(bitmap.pix32(ycnt, xcnt), machine().pens[((gfxdata[0] & 0x07) * 0x100) | (gfxdata[1] & 0xff) | pal_color_offset], stv2_current_tilemap.alpha);
3469                     }
3470                  }
3471               }
3472
3473               gfxdata+=2;
3474               if ( gfxdata >= gfxdatahigh ) gfxdata = gfxdatalow;
3475            }
3476         }
3477         break;
3478      /*RGB format*/
3479      /*
3480      M                     L
3481      S                     S
3482      B                     B
3483      --------BBBBBGGGGGRRRRR
3484      */
3485      case 3:
3486         if ( stv2_current_tilemap.incx == 0x10000 && stv2_current_tilemap.incy == 0x10000 )
3487         {
3488            /* adjust for cliprect */
3489            gfxdata += xlinesize*cliprect.min_y;
3490
3491            for (ycnt = cliprect.min_y; ycnt <= cliprect.max_y; ycnt++)
3492            {
3493               destline = &bitmap.pix32(ycnt);
3494
3495               for (xcnt = cliprect.min_x; xcnt <= cliprect.max_x; xcnt++)
3496               {
3497                  int r,g,b;
3498                  int xs = xcnt & xsizemask;
3499
3500                  if ((gfxdata[2*xs] & 0x80) || (stv2_current_tilemap.transparency == STV_TRANSPARENCY_NONE))
3501                  {
3502                     b = pal5bit(((gfxdata[2*xs] & 0x7c) >> 2));
3503                     g = pal5bit(((gfxdata[2*xs] & 0x03) << 3) | ((gfxdata[2*xs+1] & 0xe0) >> 5));
3504                     r = pal5bit(gfxdata[2*xs+1] & 0x1f);
3505                     if(stv2_current_tilemap.fade_control & 1)
3506                        stv_vdp2_compute_color_offset(&r,&g,&b,stv2_current_tilemap.fade_control & 2);
3507
3508                     if (!stv_vdp2_window_process(xcnt,ycnt))
3509                     {
3510                        if (((xcnt + 0) <= screen_x) && (ycnt <= screen_y))
3511                        {
3512                           if ( stv2_current_tilemap.colour_calculation_enabled == 0 )
3513                              destline[xcnt] = MAKE_RGB(r, g, b);
3514                           else
3515                              destline[xcnt] = alpha_blend_r32( destline[xcnt], MAKE_RGB(r, g, b), stv2_current_tilemap.alpha );
3516                        }
3517                     }
3518                  }
3519
3520                  if ( (gfxdata + 2*xs) >= gfxdatahigh ) gfxdata = gfxdatalow;
3521               }
3522
3523               gfxdata += xlinesize;
3524               if ( gfxdata >= gfxdatahigh ) gfxdata = gfxdatalow + (gfxdata - gfxdatahigh);
3525            }
3526
3527         }
3528         else
3529         {
3530            int xx, xs, yy=0;
3531
3532            for (ycnt = cliprect.min_y; ycnt <= cliprect.max_y; yy+=stv2_current_tilemap.incy, ycnt++ )
3533            {
3534               gfxdata += xlinesize*(yy>>16);
3535               yy &= 0xffff;
3536
3537               destline = &bitmap.pix32(ycnt);
3538               xx = 0;
3539               for (xcnt = cliprect.min_x; xcnt <= cliprect.max_x; xx+=stv2_current_tilemap.incx, xcnt++)
3540               {
3541                  int r,g,b;
3542
3543                  xs = xx >> 16;
3544                  b = pal5bit(((gfxdata[2*xs] & 0x7c) >> 2));
3545                  g = pal5bit(((gfxdata[2*xs] & 0x03) << 3) | ((gfxdata[2*xs+1] & 0xe0) >> 5));
3546                  r = pal5bit(gfxdata[2*xs+1] & 0x1f);
3547                  if(stv2_current_tilemap.fade_control & 1)
3548                     stv_vdp2_compute_color_offset( &r,&g,&b,stv2_current_tilemap.fade_control & 2);
3549
3550                  if (!stv_vdp2_window_process(xcnt,ycnt))
3551                  {
3552                     if ((gfxdata[2*xs] & 0x80) || (stv2_current_tilemap.transparency == STV_TRANSPARENCY_NONE))
3553                     {
3554                        if (((xcnt + 0) <= screen_x) && (ycnt <= screen_y))
3555                        {
3556                        if ( stv2_current_tilemap.colour_calculation_enabled == 1 )
3557                           destline[xcnt] = alpha_blend_r32( destline[xcnt], MAKE_RGB(r, g, b), stv2_current_tilemap.alpha );
3558                        else
3559                           destline[xcnt] = MAKE_RGB(r, g, b);
3560                        }
3561                     }
3562                  }
3563
3564                  if ( (gfxdata + 2*xs) >= gfxdatahigh ) gfxdata = gfxdatalow;
3565               }
3566               /*Guess: myfairlady needs that the vertical resolution is doubled because it's using the double density mode.*/
3567               if(STV_VDP2_LSMD == 3) { gfxdata += xlinesize*(yy>>16); }
3568               else                   { gfxdata += xlinesize; }
3569               if ( gfxdata >= gfxdatahigh ) gfxdata = gfxdatalow + (gfxdata - gfxdatahigh);
3570            }
3571         }
3572         break;
3573      /*
3574      M                              L
3575      S                              S
3576      B                              B
3577      --------BBBBBBBBGGGGGGGGRRRRRRRR
3578      */
3579      case 4:
3580         /* adjust for cliprect */
3581         gfxdata += xlinesize*(cliprect.min_y);
3582
3583         for (ycnt = cliprect.min_y; ycnt <= cliprect.max_y; ycnt++)
3584         {
3585            destline = &bitmap.pix32(ycnt);
3586
3587            for (xcnt = cliprect.min_x; xcnt <= cliprect.max_x; xcnt++)
3588            {
3589               int r,g,b;
3590               int xs = xcnt & xsizemask;
3591               UINT32 dot_data;
3592
3593               dot_data = (gfxdata[4*xs+0]<<24)|(gfxdata[4*xs+1]<<16)|(gfxdata[4*xs+2]<<8)|(gfxdata[4*xs+3]<<0);
3594               if ((dot_data & 0x80000000) || (stv2_current_tilemap.transparency == STV_TRANSPARENCY_NONE))
3595               {
3596                  b = ((dot_data & 0x00ff0000) >> 16);
3597                  g = ((dot_data & 0x0000ff00) >> 8);
3598                  r = ((dot_data & 0x000000ff) >> 0);
3599
3600                  if(stv2_current_tilemap.fade_control & 1)
3601                     stv_vdp2_compute_color_offset(&r,&g,&b,stv2_current_tilemap.fade_control & 2);
3602
3603                  if (!stv_vdp2_window_process(xcnt,ycnt))
3604                  {
3605                     if (((xcnt + 0) <= screen_x) && (ycnt <= screen_y))
3606                     {
3607                        if ( stv2_current_tilemap.colour_calculation_enabled == 0 )
3608                           destline[xcnt] = MAKE_RGB(r, g, b);
3609                        else
3610                           destline[xcnt] = alpha_blend_r32( destline[xcnt], MAKE_RGB(r, g, b), stv2_current_tilemap.alpha );
3611                     }
3612                  }
3613               }
3614
3615               if ( (gfxdata + 4*xs) >= gfxdatahigh ) gfxdata = gfxdatalow;
3616            }
3617
3618            gfxdata += xlinesize;
3619            if ( gfxdata >= gfxdatahigh ) gfxdata = gfxdatalow + (gfxdata - gfxdatahigh);
3620         }
3621
3622         break;
3623   }
3624}
3625
3626   /*---------------------------------------------------------------------------
3627   | Plane Size | Pattern Name Data Size | Character Size | Map Bits / Address |
3628   ----------------------------------------------------------------------------|
3629   |            |                        | 1 H x 1 V      | bits 6-0 * 0x02000 |
3630   |            | 1 word                 |-------------------------------------|
3631   |            |                        | 2 H x 2 V      | bits 8-0 * 0x00800 |
3632   | 1 H x 1 V  ---------------------------------------------------------------|
3633   |            |                        | 1 H x 1 V      | bits 5-0 * 0x04000 |
3634   |            | 2 words                |-------------------------------------|
3635   |            |                        | 2 H x 2 V      | bits 7-0 * 0x01000 |
3636   -----------------------------------------------------------------------------
3637   |            |                        | 1 H x 1 V      | bits 6-1 * 0x04000 |
3638   |            | 1 word                 |-------------------------------------|
3639   |            |                        | 2 H x 2 V      | bits 8-1 * 0x01000 |
3640   | 2 H x 1 V  ---------------------------------------------------------------|
3641   |            |                        | 1 H x 1 V      | bits 5-1 * 0x08000 |
3642   |            | 2 words                |-------------------------------------|
3643   |            |                        | 2 H x 2 V      | bits 7-1 * 0x02000 |
3644   -----------------------------------------------------------------------------
3645   |            |                        | 1 H x 1 V      | bits 6-2 * 0x08000 |
3646   |            | 1 word                 |-------------------------------------|
3647   |            |                        | 2 H x 2 V      | bits 8-2 * 0x02000 |
3648   | 2 H x 2 V  ---------------------------------------------------------------|
3649   |            |                        | 1 H x 1 V      | bits 5-2 * 0x10000 |
3650   |            | 2 words                |-------------------------------------|
3651   |            |                        | 2 H x 2 V      | bits 7-2 * 0x04000 |
3652   --the-highest-bit-is-ignored-if-vram-is-only-4mbits------------------------*/
3653
3654
3655/*
36564.2 Sega's Cell / Character Pattern / Page / Plane / Map system, aka a rather annoying thing that makes optimizations hard
3657 (this is only for the normal tilemaps at the moment, i haven't even thought about the ROZ ones)
3658
3659Tiles:
3660
3661Cells are 8x8 gfx stored in video ram, they can be of various colour depths
3662
3663Character Patterns can be 8x8 or 16x16 (1 hcell x 1 vcell or 2 hcell x 2 vcell)
3664  (a 16x16 character pattern is 4 8x8 cells put together)
3665
3666A page is made up of 64x64 cells, thats 64x64 character patterns in 8x8 mode or 32x32 character patterns in 16x16 mode.
3667  64 * 8  = 512 (0x200)
3668  32 * 16 = 512 (0x200)
3669A page is _always_ 512 (0x200) pixels in each direction
3670
3671in 1 word mode a 32*16 x 32*16 page is 0x0800 bytes
3672in 1 word mode a 64*8  x 64*8  page is 0x2000 bytes
3673in 2 word mode a 32*16 x 32*16 page is 0x1000 bytes
3674in 2 word mode a 64*8  x 64*8  page is 0x4000 bytes
3675
3676either 1, 2 or 4 pages make each plane depending on the plane size register (per tilemap)
3677  therefore each plane is either
3678  64 * 8 * 1 x 64 * 8 * 1 (512 x 512)
3679  64 * 8 * 2 x 64 * 8 * 1 (1024 x 512)
3680  64 * 8 * 2 x 64 * 8 * 2 (1024 x 1024)
3681
3682  32 * 16 * 1 x 32 * 16 * 1 (512 x 512)
3683  32 * 16 * 2 x 32 * 16 * 1 (1024 x 512)
3684  32 * 16 * 2 x 32 * 16 * 2 (1024 x 1024)
3685
3686map is always enabled?
3687  map is a 2x2 arrangement of planes, all 4 of the planes can be the same.
3688
3689*/
3690
3691void saturn_state::stv_vdp2_get_map_page( int x, int y, int *_map, int *_page )
3692{
3693   int page = 0;
3694   int map = 0;
3695
3696   if ( stv2_current_tilemap.map_count == 4 )
3697   {
3698      if ( stv2_current_tilemap.tile_size == 0 )
3699      {
3700         if ( stv2_current_tilemap.plane_size & 1 )
3701         {
3702            page = ((x >> 6) & 1);
3703            map = (x >> 7) & 1;
3704         }
3705         else
3706         {
3707            map = (x >> 6) & 1;
3708         }
3709
3710         if ( stv2_current_tilemap.plane_size & 2 )
3711         {
3712            page |= ((y >> (6-1)) & 2);
3713            map |= ((y >> (7-1)) & 2);
3714         }
3715         else
3716         {
3717            map |= ((y >> (6-1)) & 2);
3718         }
3719      }
3720      else
3721      {
3722         if ( stv2_current_tilemap.plane_size & 1 )
3723         {
3724            page = ((x >> 5) & 1);
3725            map = (x >> 6) & 1;
3726         }
3727         else
3728         {
3729            map = (x >> 5) & 1;
3730         }
3731
3732         if ( stv2_current_tilemap.plane_size & 2 )
3733         {
3734            page |= ((y >> (5 - 1)) & 2);
3735            map |= ((y >> (6-1)) & 2);
3736         }
3737         else
3738         {
3739            map |= ((y >> (5-1)) & 2);
3740         }
3741      }
3742   }
3743   else //16
3744   {
3745      if ( stv2_current_tilemap.tile_size == 0 )
3746      {
3747         if ( stv2_current_tilemap.plane_size & 1 )
3748         {
3749            page = ((x >> 6) & 1);
3750            map = (x >> 7) & 3;
3751         }
3752         else
3753         {
3754            map = (x >> 6) & 3;
3755         }
3756
3757         if ( stv2_current_tilemap.plane_size & 2 )
3758         {
3759            page |= ((y >> (6-1)) & 2);
3760            map |= ((y >> (7-2)) & 12);
3761         }
3762         else
3763         {
3764            map |= ((y >> (6-2)) & 12);
3765         }
3766      }
3767      else
3768      {
3769         if ( stv2_current_tilemap.plane_size & 1 )
3770         {
3771            page = ((x >> 5) & 1);
3772            map = (x >> 6) & 3;
3773         }
3774         else
3775         {
3776            map = (x >> 5) & 3;
3777         }
3778
3779         if ( stv2_current_tilemap.plane_size & 2 )
3780         {
3781            page |= ((y >> (5 - 1)) & 2);
3782            map |= ((y >> (6-2)) & 12);
3783         }
3784         else
3785         {
3786            map |= ((y >> (5-2)) & 12);
3787         }
3788      }
3789   }
3790   *_page = page;
3791   *_map = map;
3792}
3793
3794void saturn_state::stv_vdp2_draw_basic_tilemap(bitmap_rgb32 &bitmap, const rectangle &cliprect)
3795{
3796   /* hopefully this is easier to follow than it is efficient .. */
3797
3798   /* I call character patterns tiles .. even if they represent up to 4 tiles */
3799
3800   /* Page variables */
3801   int pgtiles_x, pgpixels_x;
3802   int pgtiles_y, pgpixels_y;
3803   int pgsize_bytes, pgsize_dwords;
3804
3805   /* Plane Variables */
3806   int pltiles_x, plpixels_x;
3807   int pltiles_y, plpixels_y;
3808   int plsize_bytes/*, plsize_dwords*/;
3809
3810   /* Map Variables */
3811   int mptiles_x, mppixels_x;
3812   int mptiles_y, mppixels_y;
3813   int mpsize_bytes, mpsize_dwords;
3814
3815   /* work Variables */
3816   int i, x, y;
3817   int base[16];
3818
3819   int scalex,scaley;
3820   int tilesizex, tilesizey;
3821   int drawypos, drawxpos;
3822
3823   int tilecodemin = 0x10000000, tilecodemax = 0;
3824
3825   if ( stv2_current_tilemap.incx == 0 || stv2_current_tilemap.incy == 0 ) return;
3826
3827   if ( stv2_current_tilemap.colour_calculation_enabled == 1 )
3828   {
3829      if ( STV_VDP2_CCMD )
3830      {
3831         stv2_current_tilemap.transparency = STV_TRANSPARENCY_ADD_BLEND;
3832      }
3833      else
3834      {
3835         stv2_current_tilemap.transparency = STV_TRANSPARENCY_ALPHA;
3836      }
3837   }
3838
3839   scalex = (INT32)((INT64)S64(0x100000000) / (INT64)stv2_current_tilemap.incx);
3840   scaley = (INT32)((INT64)S64(0x100000000) / (INT64)stv2_current_tilemap.incy);
3841   tilesizex = scalex * 8;
3842   tilesizey = scaley * 8;
3843   drawypos = drawxpos = 0;
3844
3845   /* Calculate the Number of tiles for x / y directions of each page (actually these will be the same */
3846   /* (2-stv2_current_tilemap.tile_size) << 5) */
3847   pgtiles_x = ((2-stv2_current_tilemap.tile_size) << 5); // 64 (8x8 mode) or 32 (16x16 mode)
3848   pgtiles_y = ((2-stv2_current_tilemap.tile_size) << 5); // 64 (8x8 mode) or 32 (16x16 mode)
3849
3850   /* Calculate the Page Size in BYTES */
3851   /* 64 * 64 * (1 * 2) = 0x2000 bytes
3852      32 * 32 * (1 * 2) = 0x0800 bytes
3853      64 * 64 * (2 * 2) = 0x4000 bytes
3854      32 * 32 * (2 * 2) = 0x1000 bytes */
3855
3856   pgsize_bytes = (pgtiles_x * pgtiles_y) * ((2-stv2_current_tilemap.pattern_data_size)*2);
3857
3858   /*---------------------------------------------------------------------------
3859   | Plane Size | Pattern Name Data Size | Character Size | Map Bits / Address |
3860   ----------------------------------------------------------------------------|
3861   |            |                        | 1 H x 1 V      | bits 6-0 * 0x02000 |
3862   |            | 1 word                 |-------------------------------------|
3863   |            |                        | 2 H x 2 V      | bits 8-0 * 0x00800 |
3864   | 1 H x 1 V  ---------------------------------------------------------------|
3865   |            |                        | 1 H x 1 V      | bits 5-0 * 0x04000 |
3866   |            | 2 words                |-------------------------------------|
3867   |            |                        | 2 H x 2 V      | bits 7-0 * 0x01000 |
3868   ---------------------------------------------------------------------------*/
3869
3870
3871   /* Page Dimensions are always 0x200 pixes (512x512) */
3872   pgpixels_x = 0x200;
3873   pgpixels_y = 0x200;
3874
3875   /* Work out the Plane Size in tiles and Plane Dimensions (pixels) */
3876   switch (stv2_current_tilemap.plane_size & 3)
3877   {
3878      case 0: // 1 page * 1 page
3879         pltiles_x  = pgtiles_x;
3880         plpixels_x = pgpixels_x;
3881         pltiles_y  = pgtiles_y;
3882         plpixels_y = pgpixels_y;
3883         break;
3884
3885      case 1: // 2 pages * 1 page
3886         pltiles_x  = pgtiles_x * 2;
3887         plpixels_x = pgpixels_x * 2;
3888         pltiles_y  = pgtiles_y;
3889         plpixels_y = pgpixels_y;
3890         break;
3891
3892      case 3: // 2 pages * 2 pages
3893         pltiles_x  = pgtiles_x * 2;
3894         plpixels_x = pgpixels_x * 2;
3895         pltiles_y  = pgtiles_y * 2;
3896         plpixels_y = pgpixels_y * 2;
3897         break;
3898
3899      default:
3900         // illegal
3901         pltiles_x  = pgtiles_x;
3902         plpixels_x = pgpixels_x;
3903         pltiles_y  = pgtiles_y * 2;
3904         plpixels_y = pgpixels_y * 2;
3905      break;
3906   }
3907
3908   /* Plane Size in BYTES */
3909   /* still the same as before
3910      (64 * 1) * (64 * 1) * (1 * 2) = 0x02000 bytes
3911      (32 * 1) * (32 * 1) * (1 * 2) = 0x00800 bytes
3912      (64 * 1) * (64 * 1) * (2 * 2) = 0x04000 bytes
3913      (32 * 1) * (32 * 1) * (2 * 2) = 0x01000 bytes
3914      changed
3915      (64 * 2) * (64 * 1) * (1 * 2) = 0x04000 bytes
3916      (32 * 2) * (32 * 1) * (1 * 2) = 0x01000 bytes
3917      (64 * 2) * (64 * 1) * (2 * 2) = 0x08000 bytes
3918      (32 * 2) * (32 * 1) * (2 * 2) = 0x02000 bytes
3919      changed
3920      (64 * 2) * (64 * 1) * (1 * 2) = 0x08000 bytes
3921      (32 * 2) * (32 * 1) * (1 * 2) = 0x02000 bytes
3922      (64 * 2) * (64 * 1) * (2 * 2) = 0x10000 bytes
3923      (32 * 2) * (32 * 1) * (2 * 2) = 0x04000 bytes
3924   */
3925
3926   plsize_bytes = (pltiles_x * pltiles_y) * ((2-stv2_current_tilemap.pattern_data_size)*2);
3927
3928   /*---------------------------------------------------------------------------
3929   | Plane Size | Pattern Name Data Size | Character Size | Map Bits / Address |
3930   -----------------------------------------------------------------------------
3931   | 1 H x 1 V   see above, nothing has changed                                |
3932   -----------------------------------------------------------------------------
3933   |            |                        | 1 H x 1 V      | bits 6-1 * 0x04000 |
3934   |            | 1 word                 |-------------------------------------|
3935   |            |                        | 2 H x 2 V      | bits 8-1 * 0x01000 |
3936   | 2 H x 1 V  ---------------------------------------------------------------|
3937   |            |                        | 1 H x 1 V      | bits 5-1 * 0x08000 |
3938   |            | 2 words                |-------------------------------------|
3939   |            |                        | 2 H x 2 V      | bits 7-1 * 0x02000 |
3940   -----------------------------------------------------------------------------
3941   |            |                        | 1 H x 1 V      | bits 6-2 * 0x08000 |
3942   |            | 1 word                 |-------------------------------------|
3943   |            |                        | 2 H x 2 V      | bits 8-2 * 0x02000 |
3944   | 2 H x 2 V  ---------------------------------------------------------------|
3945   |            |                        | 1 H x 1 V      | bits 5-2 * 0x10000 |
3946   |            | 2 words                |-------------------------------------|
3947   |            |                        | 2 H x 2 V      | bits 7-2 * 0x04000 |
3948   --the-highest-bit-is-ignored-if-vram-is-only-4mbits------------------------*/
3949
3950
3951   /* Work out the Map Sizes in tiles, Map Dimensions */
3952   /* maps are always enabled? */
3953   if ( stv2_current_tilemap.map_count == 4 )
3954   {
3955      mptiles_x = pltiles_x * 2;
3956      mptiles_y = pltiles_y * 2;
3957      mppixels_x = plpixels_x * 2;
3958      mppixels_y = plpixels_y * 2;
3959   }
3960   else
3961   {
3962      mptiles_x = pltiles_x * 4;
3963      mptiles_y = pltiles_y * 4;
3964      mppixels_x = plpixels_x * 4;
3965      mppixels_y = plpixels_y * 4;
3966   }
3967
3968   /* Map Size in BYTES */
3969   mpsize_bytes = (mptiles_x * mptiles_y) * ((2-stv2_current_tilemap.pattern_data_size)*2);
3970
3971
3972   /*-----------------------------------------------------------------------------------------------------------
3973   |            |                        | 1 H x 1 V      | bits 6-1 (upper mask 0x07f) (0x1ff >> 2) * 0x04000 |
3974   |            | 1 word                 |---------------------------------------------------------------------|
3975   |            |                        | 2 H x 2 V      | bits 8-1 (upper mask 0x1ff) (0x1ff >> 0) * 0x01000 |
3976   | 2 H x 1 V  -----------------------------------------------------------------------------------------------|
3977   |            |                        | 1 H x 1 V      | bits 5-1 (upper mask 0x03f) (0x1ff >> 3) * 0x08000 |
3978   |            | 2 words                |---------------------------------------------------------------------|
3979   |            |                        | 2 H x 2 V      | bits 7-1 (upper mask 0x0ff) (0x1ff >> 1) * 0x02000 |
3980   -------------------------------------------------------------------------------------------------------------
3981   lower mask = ~stv2_current_tilemap.plane_size
3982   -----------------------------------------------------------------------------------------------------------*/
3983
3984   /* Precalculate bases from MAP registers */
3985   for (i = 0; i < stv2_current_tilemap.map_count; i++)
3986   {
3987      static const int shifttable[4] = {0,1,2,2};
3988
3989      int uppermask, uppermaskshift;
3990
3991      uppermaskshift = (1-stv2_current_tilemap.pattern_data_size) | ((1-stv2_current_tilemap.tile_size)<<1);
3992      uppermask = 0x1ff >> uppermaskshift;
3993
3994      base[i] = ((stv2_current_tilemap.map_offset[i] & uppermask) >> shifttable[stv2_current_tilemap.plane_size]) * plsize_bytes;
3995
3996      base[i] &= 0x7ffff; /* shienryu needs this for the text layer, is there a problem elsewhere or is it just right without the ram cart */
3997
3998      base[i] = base[i] / 4; // convert bytes to DWORDS
3999   }
4000
4001   /* other bits */
4002   //stv2_current_tilemap.trans_enabled = stv2_current_tilemap.trans_enabled ? STV_TRANSPARENCY_NONE : STV_TRANSPARENCY_PEN;
4003   stv2_current_tilemap.scrollx &= mppixels_x-1;
4004   stv2_current_tilemap.scrolly &= mppixels_y-1;
4005
4006   pgsize_dwords = pgsize_bytes /4;
4007   //plsize_dwords = plsize_bytes /4;
4008   mpsize_dwords = mpsize_bytes /4;
4009
4010//  if (stv2_current_tilemap.layer_name==3) popmessage ("well this is a bit  %08x", stv2_current_tilemap.map_offset[0]);
4011//  if (stv2_current_tilemap.layer_name==3) popmessage ("well this is a bit  %08x %08x %08x %08x", stv2_current_tilemap.plane_size, pgtiles_x, pltiles_x, mptiles_x);
4012
4013   if (!stv2_current_tilemap.enabled) return; // stop right now if its disabled ...
4014
4015   /* most things we need (or don't need) to work out are now worked out */
4016
4017   for (y = 0; y<mptiles_y; y++) {
4018      int ypageoffs;
4019      int page, map, newbase, offs, data;
4020      int tilecode, flipyx, pal, gfx = 0;
4021
4022      map = 0 ; page = 0 ;
4023      if ( y == 0 )
4024      {
4025         int drawyposinc = tilesizey*(stv2_current_tilemap.tile_size ? 2 : 1);
4026         drawypos = -(stv2_current_tilemap.scrolly*scaley);
4027         while( ((drawypos + drawyposinc) >> 16) < cliprect.min_y )
4028         {
4029            drawypos += drawyposinc;
4030            y++;
4031         }
4032         mptiles_y += y;
4033      }
4034      else
4035      {
4036         drawypos += tilesizey*(stv2_current_tilemap.tile_size ? 2 : 1);
4037      }
4038      if ((drawypos >> 16) > cliprect.max_y) break;
4039
4040      ypageoffs = y & (pgtiles_y-1);
4041
4042      for (x = 0; x<mptiles_x; x++) {
4043         int xpageoffs;
4044         int tilecodespacing = 1;
4045
4046         if ( x == 0 )
4047         {
4048            int drawxposinc = tilesizex*(stv2_current_tilemap.tile_size ? 2 : 1);
4049            drawxpos = -(stv2_current_tilemap.scrollx*scalex);
4050            while( ((drawxpos + drawxposinc) >> 16) < cliprect.min_x )
4051            {
4052               drawxpos += drawxposinc;
4053               x++;
4054            }
4055            mptiles_x += x;
4056         }
4057         else
4058         {
4059            drawxpos+=tilesizex*(stv2_current_tilemap.tile_size ? 2 : 1);
4060         }
4061         if ( (drawxpos >> 16) > cliprect.max_x ) break;
4062
4063         xpageoffs = x & (pgtiles_x-1);
4064
4065         stv_vdp2_get_map_page(x,y,&map,&page);
4066
4067         newbase = base[map] + page * pgsize_dwords;
4068         offs = (ypageoffs * pgtiles_x) + xpageoffs;
4069
4070/* GET THE TILE INFO ... */
4071         /* 1 word per tile mode with supplement bits */
4072         if (stv2_current_tilemap.pattern_data_size ==1)
4073         {
4074            data = m_vdp2_vram[newbase + offs/2];
4075            data = (offs&1) ? (data & 0x0000ffff) : ((data & 0xffff0000) >> 16);
4076
4077            /* Supplement Mode 12 bits, no flip */
4078            if (stv2_current_tilemap.character_number_supplement == 1)
4079            {
4080/* no flip */       flipyx   = 0;
4081/* 8x8 */           if (stv2_current_tilemap.tile_size==0) tilecode = (data & 0x0fff) + ( (stv2_current_tilemap.supplementary_character_bits&0x1c) << 10);
4082/* 16x16 */         else tilecode = ((data & 0x0fff) << 2) + (stv2_current_tilemap.supplementary_character_bits&0x03) + ((stv2_current_tilemap.supplementary_character_bits&0x10) << 10);
4083            }
4084            /* Supplement Mode 10 bits, with flip */
4085            else
4086            {
4087/* flip bits */     flipyx   = (data & 0x0c00) >> 10;
4088/* 8x8 */           if (stv2_current_tilemap.tile_size==0) tilecode = (data & 0x03ff) +  ( (stv2_current_tilemap.supplementary_character_bits) << 10);
4089/* 16x16 */         else tilecode = ((data & 0x03ff) <<2) +  (stv2_current_tilemap.supplementary_character_bits&0x03) + ((stv2_current_tilemap.supplementary_character_bits&0x1c) << 10);
4090            }
4091
4092/*>16cols*/     if (stv2_current_tilemap.colour_depth != 0) pal = ((data & 0x7000)>>8);
4093/*16 cols*/     else pal = ((data & 0xf000)>>12) +( (stv2_current_tilemap.supplementary_palette_bits) << 4);
4094
4095         }
4096         /* 2 words per tile, no supplement bits */
4097         else
4098         {
4099            data = m_vdp2_vram[newbase + offs];
4100            tilecode = (data & 0x00007fff);
4101            pal   = (data &    0x007f0000)>>16;
4102   //          specialc = (data & 0x10000000)>>28;
4103            flipyx   = (data & 0xc0000000)>>30;
4104         }
4105/* WE'VE GOT THE TILE INFO ... */
4106
4107         if ( tilecode < tilecodemin ) tilecodemin = tilecode;
4108         if ( tilecode > tilecodemax ) tilecodemax = tilecode;
4109
4110/* DECODE ANY TILES WE NEED TO DECODE */
4111
4112         pal += stv2_current_tilemap.colour_ram_address_offset<< 4; // bios uses this ..
4113
4114         /*Enable fading bit*/
4115         if(stv2_current_tilemap.fade_control & 1)
4116         {
4117            /*Select fading bit*/
4118            pal += ((stv2_current_tilemap.fade_control & 2) ? (0x100) : (0x80));
4119         }
4120
4121         if (stv2_current_tilemap.colour_depth == 1)
4122         {
4123            gfx = 2;
4124            pal = pal >>4;
4125            tilecode &=0x7fff;
4126            if (tilecode == 0x7fff) tilecode--; /* prevents crash but unsure what should happen; wrapping? */
4127            tilecodespacing = 2;
4128         }
4129         else if (stv2_current_tilemap.colour_depth == 0)
4130         {
4131            gfx = 0;
4132            tilecode &=0x7fff;
4133            tilecodespacing = 1;
4134         }
4135/* TILES ARE NOW DECODED */
4136
4137         if(!STV_VDP2_VRAMSZ)
4138            tilecode &= 0x3fff;
4139
4140/* DRAW! */
4141         if(stv2_current_tilemap.incx != 0x10000 ||
4142            stv2_current_tilemap.incy != 0x10000 ||
4143            stv2_current_tilemap.transparency == STV_TRANSPARENCY_ADD_BLEND )
4144         {
4145#define SCR_TILESIZE_X          (((drawxpos + tilesizex) >> 16) - (drawxpos >> 16))
4146#define SCR_TILESIZE_X1(startx) (((drawxpos + (startx) + tilesizex) >> 16) - ((drawxpos + (startx))>>16))
4147#define SCR_TILESIZE_Y          (((drawypos + tilesizey) >> 16) - (drawypos >> 16))
4148#define SCR_TILESIZE_Y1(starty) (((drawypos + (starty) + tilesizey) >> 16) - ((drawypos + (starty))>>16))
4149            if (stv2_current_tilemap.tile_size==1)
4150            {
4151               if ( stv2_current_tilemap.colour_depth == 4 )
4152               {
4153                  popmessage("Unsupported tilemap gfx zoom color depth = 4, tile size = 1, contact MAMEdev");
4154               }
4155               else if ( stv2_current_tilemap.colour_depth == 3 )
4156               {
4157                  /* RGB555 */
4158                  stv_vdp2_drawgfxzoom_rgb555(bitmap,cliprect,tilecode+(0+(flipyx&1)+(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos >> 16, drawypos >> 16,stv2_current_tilemap.transparency,0,scalex,scaley,SCR_TILESIZE_X, SCR_TILESIZE_Y,stv2_current_tilemap.alpha);
4159                  stv_vdp2_drawgfxzoom_rgb555(bitmap,cliprect,tilecode+(1-(flipyx&1)+(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,(drawxpos+tilesizex) >> 16,drawypos >> 16,stv2_current_tilemap.transparency,0,scalex,scaley,SCR_TILESIZE_X1(tilesizex), SCR_TILESIZE_Y,stv2_current_tilemap.alpha);
4160                  stv_vdp2_drawgfxzoom_rgb555(bitmap,cliprect,tilecode+(2+(flipyx&1)-(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos >> 16,(drawypos+tilesizey) >> 16,stv2_current_tilemap.transparency,0,scalex,scaley,SCR_TILESIZE_X, SCR_TILESIZE_Y1(tilesizey),stv2_current_tilemap.alpha);
4161                  stv_vdp2_drawgfxzoom_rgb555(bitmap,cliprect,tilecode+(3-(flipyx&1)-(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,(drawxpos+tilesizex)>> 16,(drawypos+tilesizey) >> 16,stv2_current_tilemap.transparency,0,scalex,scaley,SCR_TILESIZE_X1(tilesizex), SCR_TILESIZE_Y1(tilesizey),stv2_current_tilemap.alpha);
4162               }
4163               else
4164               {
4165                  /* normal */
4166                  stv_vdp2_drawgfxzoom(bitmap,cliprect,machine().gfx[gfx],tilecode+(0+(flipyx&1)+(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos >> 16, drawypos >> 16,stv2_current_tilemap.transparency,0,scalex,scaley,SCR_TILESIZE_X, SCR_TILESIZE_Y,stv2_current_tilemap.alpha);
4167                  stv_vdp2_drawgfxzoom(bitmap,cliprect,machine().gfx[gfx],tilecode+(1-(flipyx&1)+(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,(drawxpos+tilesizex) >> 16,drawypos >> 16,stv2_current_tilemap.transparency,0,scalex,scaley,SCR_TILESIZE_X1(tilesizex), SCR_TILESIZE_Y,stv2_current_tilemap.alpha);
4168                  stv_vdp2_drawgfxzoom(bitmap,cliprect,machine().gfx[gfx],tilecode+(2+(flipyx&1)-(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos >> 16,(drawypos+tilesizey) >> 16,stv2_current_tilemap.transparency,0,scalex,scaley,SCR_TILESIZE_X, SCR_TILESIZE_Y1(tilesizey),stv2_current_tilemap.alpha);
4169                  stv_vdp2_drawgfxzoom(bitmap,cliprect,machine().gfx[gfx],tilecode+(3-(flipyx&1)-(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,(drawxpos+tilesizex)>> 16,(drawypos+tilesizey) >> 16,stv2_current_tilemap.transparency,0,scalex,scaley,SCR_TILESIZE_X1(tilesizex), SCR_TILESIZE_Y1(tilesizey),stv2_current_tilemap.alpha);
4170               }
4171            }
4172            else
4173            {
4174               if ( stv2_current_tilemap.colour_depth == 4 )
4175                  popmessage("Unsupported tilemap gfx zoom color depth = 4, tile size = 0, contact MAMEdev");
4176               else if ( stv2_current_tilemap.colour_depth == 3)
4177               {
4178                  stv_vdp2_drawgfxzoom_rgb555(bitmap,cliprect,tilecode,pal,flipyx&1,flipyx&2, drawxpos >> 16, drawypos >> 16,stv2_current_tilemap.transparency,0,scalex,scaley,SCR_TILESIZE_X,SCR_TILESIZE_Y,stv2_current_tilemap.alpha);
4179               }
4180               else
4181                  stv_vdp2_drawgfxzoom(bitmap,cliprect,machine().gfx[gfx],tilecode,pal,flipyx&1,flipyx&2, drawxpos >> 16, drawypos >> 16,stv2_current_tilemap.transparency,0,scalex,scaley,SCR_TILESIZE_X,SCR_TILESIZE_Y,stv2_current_tilemap.alpha);
4182            }
4183         }
4184         else
4185         {
4186            int olddrawxpos, olddrawypos;
4187            olddrawxpos = drawxpos; drawxpos >>= 16;
4188            olddrawypos = drawypos; drawypos >>= 16;
4189            if (stv2_current_tilemap.tile_size==1)
4190            {
4191               if ( stv2_current_tilemap.colour_depth == 4 )
4192               {
4193                  /* normal */
4194                  stv_vdp2_drawgfx_rgb888(bitmap,cliprect,tilecode+(0+(flipyx&1)+(flipyx&2))*4,flipyx&1,flipyx&2,drawxpos, drawypos,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha);
4195                  stv_vdp2_drawgfx_rgb888(bitmap,cliprect,tilecode+(1-(flipyx&1)+(flipyx&2))*4,flipyx&1,flipyx&2,drawxpos+8,drawypos,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha);
4196                  stv_vdp2_drawgfx_rgb888(bitmap,cliprect,tilecode+(2+(flipyx&1)-(flipyx&2))*4,flipyx&1,flipyx&2,drawxpos,drawypos+8,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha);
4197                  stv_vdp2_drawgfx_rgb888(bitmap,cliprect,tilecode+(3-(flipyx&1)-(flipyx&2))*4,flipyx&1,flipyx&2,drawxpos+8,drawypos+8,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha);
4198               }
4199               else if ( stv2_current_tilemap.colour_depth == 3 )
4200               {
4201                  /* normal */
4202                  stv_vdp2_drawgfx_rgb555(bitmap,cliprect,tilecode+(0+(flipyx&1)+(flipyx&2))*4,flipyx&1,flipyx&2,drawxpos, drawypos,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha);
4203                  stv_vdp2_drawgfx_rgb555(bitmap,cliprect,tilecode+(1-(flipyx&1)+(flipyx&2))*4,flipyx&1,flipyx&2,drawxpos+8,drawypos,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha);
4204                  stv_vdp2_drawgfx_rgb555(bitmap,cliprect,tilecode+(2+(flipyx&1)-(flipyx&2))*4,flipyx&1,flipyx&2,drawxpos,drawypos+8,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha);
4205                  stv_vdp2_drawgfx_rgb555(bitmap,cliprect,tilecode+(3-(flipyx&1)-(flipyx&2))*4,flipyx&1,flipyx&2,drawxpos+8,drawypos+8,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha);
4206               }
4207               else if (stv2_current_tilemap.transparency == STV_TRANSPARENCY_ALPHA)
4208               {
4209                  /* alpha */
4210                  drawgfx_alpha(bitmap,cliprect,machine().gfx[gfx],tilecode+(0+(flipyx&1)+(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos, drawypos,0,stv2_current_tilemap.alpha);
4211                  drawgfx_alpha(bitmap,cliprect,machine().gfx[gfx],tilecode+(1-(flipyx&1)+(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos+8,drawypos,0,stv2_current_tilemap.alpha);
4212                  drawgfx_alpha(bitmap,cliprect,machine().gfx[gfx],tilecode+(2+(flipyx&1)-(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos,drawypos+8,0,stv2_current_tilemap.alpha);
4213                  drawgfx_alpha(bitmap,cliprect,machine().gfx[gfx],tilecode+(3-(flipyx&1)-(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos+8,drawypos+8,0,stv2_current_tilemap.alpha);
4214               }
4215               else
4216               {
4217                  /* normal */
4218                  drawgfx_transpen(bitmap,cliprect,machine().gfx[gfx],tilecode+(0+(flipyx&1)+(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos, drawypos,(stv2_current_tilemap.transparency==STV_TRANSPARENCY_PEN)?0:-1);
4219                  drawgfx_transpen(bitmap,cliprect,machine().gfx[gfx],tilecode+(1-(flipyx&1)+(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos+8,drawypos,(stv2_current_tilemap.transparency==STV_TRANSPARENCY_PEN)?0:-1);
4220                  drawgfx_transpen(bitmap,cliprect,machine().gfx[gfx],tilecode+(2+(flipyx&1)-(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos,drawypos+8,(stv2_current_tilemap.transparency==STV_TRANSPARENCY_PEN)?0:-1);
4221                  drawgfx_transpen(bitmap,cliprect,machine().gfx[gfx],tilecode+(3-(flipyx&1)-(flipyx&2))*tilecodespacing,pal,flipyx&1,flipyx&2,drawxpos+8,drawypos+8,(stv2_current_tilemap.transparency==STV_TRANSPARENCY_PEN)?0:-1);
4222               }
4223            }
4224            else
4225            {
4226               if ( stv2_current_tilemap.colour_depth == 4)
4227               {
4228                  stv_vdp2_drawgfx_rgb888(bitmap,cliprect,tilecode,flipyx&1,flipyx&2,drawxpos,drawypos,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha);
4229               }
4230               else if ( stv2_current_tilemap.colour_depth == 3)
4231               {
4232                  stv_vdp2_drawgfx_rgb555(bitmap,cliprect,tilecode,flipyx&1,flipyx&2,drawxpos,drawypos,stv2_current_tilemap.transparency,stv2_current_tilemap.alpha);
4233               }
4234               else
4235               {
4236                  if (stv2_current_tilemap.transparency == STV_TRANSPARENCY_ALPHA)
4237                     drawgfx_alpha(bitmap,cliprect,machine().gfx[gfx],tilecode,pal,flipyx&1,flipyx&2, drawxpos, drawypos,0,stv2_current_tilemap.alpha);
4238                  else
4239                     drawgfx_transpen(bitmap,cliprect,machine().gfx[gfx],tilecode,pal,flipyx&1,flipyx&2, drawxpos, drawypos,(stv2_current_tilemap.transparency==STV_TRANSPARENCY_PEN)?0:-1);
4240               }
4241            }
4242            drawxpos = olddrawxpos;
4243            drawypos = olddrawypos;
4244         }
4245/* DRAWN?! */
4246
4247      }
4248   }
4249   if ( stv2_current_tilemap.layer_name & 0x80 )
4250   {
4251      static const int shifttable[4] = {0,1,2,2};
4252      int uppermask, uppermaskshift;
4253      int mapsize;
4254      uppermaskshift = (1-stv2_current_tilemap.pattern_data_size) | ((1-stv2_current_tilemap.tile_size)<<1);
4255      uppermask = 0x1ff >> uppermaskshift;
4256
4257      if ( LOG_VDP2 )
4258      {
4259         logerror( "Layer RBG%d, size %d x %d\n", stv2_current_tilemap.layer_name & 0x7f, cliprect.max_x + 1, cliprect.max_y + 1 );
4260         logerror( "Tiles: min %08X, max %08X\n", tilecodemin, tilecodemax );
4261         logerror( "MAP size in dwords %08X\n", mpsize_dwords );
4262         for (i = 0; i < stv2_current_tilemap.map_count; i++)
4263         {
4264            logerror( "Map register %d: base %08X\n", stv2_current_tilemap.map_offset[i], base[i] );
4265         }
4266      }
4267
4268      // store map information
4269      stv_vdp2_layer_data_placement.map_offset_min = 0x7fffffff;
4270      stv_vdp2_layer_data_placement.map_offset_max = 0x00000000;
4271      for (i = 0; i < stv2_current_tilemap.map_count; i++)
4272      {
4273         if ( base[i] < stv_vdp2_layer_data_placement.map_offset_min )
4274            stv_vdp2_layer_data_placement.map_offset_min = base[i];
4275         if ( base[i] > stv_vdp2_layer_data_placement.map_offset_max )
4276            stv_vdp2_layer_data_placement.map_offset_max = base[i];
4277      }
4278
4279
4280      mapsize = ((1 & uppermask) >> shifttable[stv2_current_tilemap.plane_size]) * plsize_bytes -
4281               ((0 & uppermask) >> shifttable[stv2_current_tilemap.plane_size]) * plsize_bytes;
4282      mapsize /= 4;
4283
4284      stv_vdp2_layer_data_placement.map_offset_max += mapsize;
4285
4286      stv_vdp2_layer_data_placement.tile_offset_min = tilecodemin * 0x20 / 4;
4287      stv_vdp2_layer_data_placement.tile_offset_max = (tilecodemax + 1) * 0x20 / 4;
4288   }
4289
4290}
4291
4292#define STV_VDP2_READ_VERTICAL_LINESCROLL( _val, _address ) \
4293   { \
4294      _val = m_vdp2_vram[ _address ]; \
4295      _val &= 0x07ffff00; \
4296      if ( _val & 0x04000000 ) _val |= 0xf8000000; \
4297   }
4298
4299
4300void saturn_state::stv_vdp2_check_tilemap_with_linescroll(bitmap_rgb32 &bitmap, const rectangle &cliprect)
4301{
4302   rectangle mycliprect;
4303   int cur_line = cliprect.min_y;
4304   int address;
4305   int active_functions = 0;
4306   INT32 scroll_values[3], prev_scroll_values[3];
4307   int i;
4308   int scroll_values_equal;
4309   int lines;
4310   INT16 main_scrollx, main_scrolly;
4311//  INT32 incx;
4312   int linescroll_enable, vertical_linescroll_enable, linezoom_enable;
4313   int vertical_linescroll_index = -1;
4314
4315   // read original scroll values
4316   main_scrollx = stv2_current_tilemap.scrollx;
4317   main_scrolly = stv2_current_tilemap.scrolly;
4318//  incx = stv2_current_tilemap.incx;
4319
4320   // prepare linescroll flags
4321   linescroll_enable = stv2_current_tilemap.linescroll_enable;
4322//  stv2_current_tilemap.linescroll_enable = 0;
4323   vertical_linescroll_enable = stv2_current_tilemap.vertical_linescroll_enable;
4324//  stv2_current_tilemap.vertical_linescroll_enable = 0;
4325   linezoom_enable = stv2_current_tilemap.linezoom_enable;
4326//  stv2_current_tilemap.linezoom_enable = 0;
4327
4328   // prepare working clipping rectangle
4329   memcpy( &mycliprect, &cliprect, sizeof(rectangle) );
4330
4331   // calculate the number of active functions
4332   if ( linescroll_enable ) active_functions++;
4333   if ( vertical_linescroll_enable )
4334   {
4335      vertical_linescroll_index = active_functions;
4336      active_functions++;
4337   }
4338   if ( linezoom_enable ) active_functions++;
4339
4340   // address of data table
4341   address = stv2_current_tilemap.linescroll_table_address + active_functions*4*cliprect.min_y;
4342
4343   // get the first scroll values
4344   for ( i = 0; i < active_functions; i++ )
4345   {
4346      if ( i == vertical_linescroll_index )
4347      {
4348         STV_VDP2_READ_VERTICAL_LINESCROLL( prev_scroll_values[i], (address / 4) + i );
4349         prev_scroll_values[i] -= (cur_line * stv2_current_tilemap.incy);
4350      }
4351      else
4352      {
4353         prev_scroll_values[i] = m_vdp2_vram[ (address / 4) + i ];
4354      }
4355   }
4356
4357   while( cur_line <= cliprect.max_y )
4358   {
4359      lines = 0;
4360      do
4361      {
4362         // update address
4363         address += active_functions*4;
4364
4365         // update lines count
4366         lines += stv2_current_tilemap.linescroll_interval;
4367
4368         // get scroll values
4369         for ( i = 0; i < active_functions; i++ )
4370         {
4371            if ( i == vertical_linescroll_index )
4372            {
4373               STV_VDP2_READ_VERTICAL_LINESCROLL( scroll_values[i], (address/4) + i );
4374               scroll_values[i] -= (cur_line + lines) * stv2_current_tilemap.incy;
4375            }
4376            else
4377            {
4378               scroll_values[i] = m_vdp2_vram[ (address / 4) + i ];
4379            }
4380         }
4381
4382         // compare scroll values
4383         scroll_values_equal = 1;
4384         for ( i = 0; i < active_functions; i++ )
4385         {
4386            scroll_values_equal &= (scroll_values[i] == prev_scroll_values[i]);
4387         }
4388      } while( scroll_values_equal && ((cur_line + lines) <= cliprect.max_y) );
4389
4390      // determined how many lines can be drawn
4391      // prepare clipping rectangle
4392      mycliprect.min_y = cur_line;
4393      mycliprect.max_y = cur_line + lines - 1;
4394
4395      // prepare scroll values
4396      i = 0;
4397      // linescroll
4398      if ( linescroll_enable )
4399      {
4400         prev_scroll_values[i] &= 0x07ffff00;
4401         if ( prev_scroll_values[i] & 0x04000000 ) prev_scroll_values[i] |= 0xf8000000;
4402         stv2_current_tilemap.scrollx = main_scrollx + (prev_scroll_values[i] >> 16);
4403         i++;
4404      }
4405      // vertical line scroll
4406      if ( vertical_linescroll_enable )
4407      {
4408         stv2_current_tilemap.scrolly = main_scrolly + (prev_scroll_values[i] >> 16);
4409         i++;
4410      }
4411
4412      // linezooom
4413      if ( linezoom_enable )
4414      {
4415         prev_scroll_values[i] &= 0x0007ff00;
4416         if ( prev_scroll_values[i] & 0x00040000 ) prev_scroll_values[i] |= 0xfff80000;
4417         stv2_current_tilemap.incx = prev_scroll_values[i];
4418         i++;
4419      }
4420
4421//      if ( LOG_VDP2 ) logerror( "Linescroll: y < %d, %d >, scrollx = %d, scrolly = %d, incx = %f\n", mycliprect.min_y, mycliprect.max_y, stv2_current_tilemap.scrollx, stv2_current_tilemap.scrolly, (float)stv2_current_tilemap.incx/65536.0 );
4422      // render current tilemap portion
4423      if (stv2_current_tilemap.bitmap_enable) // this layer is a bitmap
4424      {
4425         stv_vdp2_draw_basic_bitmap(bitmap, mycliprect);
4426      }
4427      else
4428      {
4429         stv_vdp2_apply_window_on_layer(mycliprect);
4430         stv_vdp2_draw_basic_tilemap(bitmap, mycliprect);
4431      }
4432
4433      // update parameters for next iteration
4434      memcpy( prev_scroll_values, scroll_values, sizeof(scroll_values));
4435      cur_line += lines;
4436   }
4437}
4438
4439void saturn_state::stv_vdp2_draw_line(bitmap_rgb32 &bitmap, const rectangle &cliprect)
4440{
4441   int x,y;
4442   UINT8* gfxdata = m_vdp2.gfx_decode;
4443   UINT32 base_offs,base_mask;
4444   UINT32 pix;
4445   UINT8 interlace;
4446
4447   interlace = (STV_VDP2_LSMD == 3)+1;
4448
4449   {
4450      base_mask = STV_VDP2_VRAMSZ ? 0x7ffff : 0x3ffff;
4451
4452      for(y=cliprect.min_y;y<=cliprect.max_y;y++)
4453      {
4454         base_offs = (STV_VDP2_LCTA & base_mask) << 1;
4455
4456         if(STV_VDP2_LCCLMD)
4457            base_offs += (y / interlace) << 1;
4458
4459         for(x=cliprect.min_x;x<=cliprect.max_x;x++)
4460         {
4461            UINT16 pen;
4462
4463            pen = (gfxdata[base_offs+0]<<8)|gfxdata[base_offs+1];
4464            pix = bitmap.pix32(y, x);
4465
4466            bitmap.pix32(y, x) = stv_add_blend(machine().pens[pen & 0x7ff],pix);
4467         }
4468      }
4469   }
4470}
4471
4472void saturn_state::stv_vdp2_draw_mosaic(bitmap_rgb32 &bitmap, const rectangle &cliprect, UINT8 is_roz)
4473{
4474   int x,y,xi,yi;
4475   UINT8 h_size,v_size;
4476   UINT32 pix;
4477
4478   h_size = STV_VDP2_MZSZH+1;
4479   v_size = STV_VDP2_MZSZV+1;
4480
4481   if(is_roz)
4482      v_size = 1;
4483
4484   if(h_size == 1 && v_size == 1)
4485      return; // don't bother
4486
4487   if(STV_VDP2_LSMD == 3)
4488      v_size <<= 1;
4489
4490   for(y=cliprect.min_y;y<=cliprect.max_y;y+=v_size)
4491   {
4492      for(x=cliprect.min_x;x<=cliprect.max_x;x+=h_size)
4493      {
4494         pix = bitmap.pix32(y, x);
4495
4496         for(yi=0;yi<v_size;yi++)
4497            for(xi=0;xi<h_size;xi++)
4498               bitmap.pix32(y+yi, x+xi) = pix;
4499      }
4500   }
4501}
4502
4503void saturn_state::stv_vdp2_check_tilemap(bitmap_rgb32 &bitmap, const rectangle &cliprect)
4504{
4505   /* the idea is here we check the tilemap capabilities / whats enabled and call an appropriate tilemap drawing routine, or
4506     at the very list throw up a few errors if the tilemaps want to do something we don't support yet */
4507//  int window_applied = 0;
4508   rectangle mycliprect = cliprect;
4509
4510   if ( stv2_current_tilemap.linescroll_enable ||
4511         stv2_current_tilemap.vertical_linescroll_enable ||
4512         stv2_current_tilemap.linezoom_enable )
4513   {
4514      stv_vdp2_check_tilemap_with_linescroll(bitmap, cliprect);
4515      return;
4516   }
4517
4518
4519   if (stv2_current_tilemap.bitmap_enable) // this layer is a bitmap
4520   {
4521      /*elandore doesn't like current cliprect code,will be worked on...*/
4522      //if ( window_applied && stv2_current_tilemap.colour_depth != 4)
4523      //  stv2_current_tilemap.window_control = 0;
4524
4525      stv_vdp2_draw_basic_bitmap(bitmap, mycliprect);
4526   }
4527   else
4528   {
4529      stv_vdp2_apply_window_on_layer(mycliprect);
4530      stv_vdp2_draw_basic_tilemap(bitmap, mycliprect);
4531   }
4532
4533   /* post-processing functions (TODO: needs layer bitmaps to be individual planes to work correctly) */
4534   if(stv2_current_tilemap.line_screen_enabled && TEST_FUNCTIONS)
4535      stv_vdp2_draw_line(bitmap,cliprect);
4536
4537   if(stv2_current_tilemap.mosaic_screen_enabled && TEST_FUNCTIONS)
4538      stv_vdp2_draw_mosaic(bitmap,cliprect,stv2_current_tilemap.layer_name & 0x80);
4539
4540
4541   {
4542      if(stv2_current_tilemap.colour_depth == 2 && !stv2_current_tilemap.bitmap_enable)
4543         popmessage("2048 color mode used on a non-bitmap plane");
4544
4545//      if(STV_VDP2_SCXDN0 || STV_VDP2_SCXDN1 || STV_VDP2_SCYDN0 || STV_VDP2_SCYDN1)
4546//          popmessage("Fractional part scrolling write, contact MAMEdev");
4547
4548      /* Pukunpa */
4549      //if(STV_VDP2_SPWINEN)
4550      //  popmessage("Sprite Window enabled");
4551
4552      /* Capcom Collection Dai 2 - Choh Makaimura (Duh!) */
4553      if(STV_VDP2_MZCTL & 0x1f && 0)
4554         popmessage("Mosaic control enabled = %04x\n",STV_VDP2_MZCTL);
4555
4556      /* Bio Hazard bit 1 */
4557      /* Airs Adventure 0x3e */
4558      /* Bakuretsu Hunter */
4559      if(STV_VDP2_LNCLEN & ~2 && 0)
4560         popmessage("Line Colour screen enabled %04x %08x, contact MAMEdev",STV_VDP2_LNCLEN,STV_VDP2_LCTAU<<16|STV_VDP2_LCTAL);
4561
4562      /* Bio Hazard 0x400 = extended color calculation enabled */
4563      /* Advanced World War 0x200 = color calculation ratio mode */
4564      //if(STV_VDP2_CCCR & 0xf600)
4565      if(STV_VDP2_CCCR & 0xf000)
4566         popmessage("Gradation enabled %04x, contact MAMEdev",STV_VDP2_CCCR);
4567
4568      /* Advanced VG, Shining Force III */
4569      if(STV_VDP2_SFCCMD && 0)
4570         popmessage("Special Color Calculation enable %04x, contact MAMEdev",STV_VDP2_SFCCMD);
4571
4572      /* Cleopatra Fortune Transparent Shadow */
4573      /* Pretty Fighter X Back & Transparent Shadow*/
4574      //if(STV_VDP2_SDCTL & 0x0120)
4575      //  popmessage("%s shadow select bit enabled, contact MAMEdev",STV_VDP2_SDCTL & 0x100 ? "Transparent" : "Back");
4576
4577      /* Langrisser III bit 3 normal, bit 1 during battle field */
4578      /* Metal Slug bit 0 during gameplay */
4579      if(STV_VDP2_SFSEL & ~0xb)
4580         popmessage("Special Function Code Select enable %04x %04x, contact MAMEdev",STV_VDP2_SFSEL,STV_VDP2_SFCODE);
4581
4582      /* Albert Odyssey Gaiden 0x0001 */
4583      /* Asuka 120% (doesn't make sense?) 0x0101 */
4584      /* Slam n Jam 96 0x0003 */
4585      if(STV_VDP2_ZMCTL & 0x0200)
4586         popmessage("Reduction enable %04x, contact MAMEdev",STV_VDP2_ZMCTL);
4587
4588      /* Burning Rangers and friends FMV, J.League Pro Soccer Club Wo Tsukurou!! backgrounds */
4589      if(STV_VDP2_SCRCTL & 0x0101 && 0)
4590         popmessage("Vertical cell scroll enable %04x, contact MAMEdev",STV_VDP2_SCRCTL);
4591
4592      /* Magical Drop III 0x200 -> color calculation window */
4593      /* Ide Yousuke Meijin No Shin Jissen Mahjong 0x0303 */
4594      /* Decathlete 0x088 */
4595      if(STV_VDP2_WCTLD & 0x2000)
4596         popmessage("Special window enabled %04x, contact MAMEdev",STV_VDP2_WCTLD);
4597
4598      /* Shining Force III, After Burner 2 (doesn't make a proper use tho?) */
4599      /* Layer Section */
4600      //if(STV_VDP2_W0LWE || STV_VDP2_W1LWE)
4601      //  popmessage("Line Window %s %08x enabled, contact MAMEdev",STV_VDP2_W0LWE ? "0" : "1",STV_VDP2_W0LWTA);
4602
4603      /* Akumajou Dracula, bits 2-4 */
4604      /* Arcana Strikes bit 5 */
4605      /* Choh Makai Mura 0x0055 */
4606      /* Sega Rally 0x0155 */
4607      /* Find Love  0x4400 */
4608      /* Dragon Ball Z 0x3800 - 0x2c00 */
4609      /* Assault Suit Leynos 2 0x0200*/
4610      if(STV_VDP2_SFPRMD & ~0x7f75)
4611         popmessage("Special Priority Mode enabled %04x, contact MAMEdev",STV_VDP2_SFPRMD);
4612   }
4613}
4614
4615
4616void saturn_state::stv_vdp2_copy_roz_bitmap(bitmap_rgb32 &bitmap,
4617                              bitmap_rgb32 &roz_bitmap,
4618                              const rectangle &cliprect,
4619                              int iRP,
4620                              int planesizex,
4621                              int planesizey,
4622                              int planerenderedsizex,
4623                              int planerenderedsizey)
4624{
4625   INT32 xsp, ysp, xp, yp, dx, dy, x, y, xs, ys, dxs, dys;
4626   INT32 vcnt, hcnt;
4627   INT32 kx, ky;
4628   INT8  use_coeff_table, coeff_table_mode, coeff_table_size, coeff_table_shift;
4629   INT8  screen_over_process;
4630   UINT8 vcnt_shift, hcnt_shift;
4631   UINT8 coeff_msb;
4632   UINT32 *coeff_table_base, coeff_table_offset;
4633   INT32 coeff_table_val;
4634   UINT32 address;
4635   UINT32 *line;
4636   UINT32 pix;
4637   //UINT32 coeff_line_color_screen_data;
4638   INT32 clipxmask = 0, clipymask = 0;
4639
4640
4641   vcnt_shift = ((STV_VDP2_LSMD & 3) == 3);
4642   hcnt_shift = ((STV_VDP2_HRES & 2) == 2);
4643
4644   planesizex--;
4645   planesizey--;
4646   planerenderedsizex--;
4647   planerenderedsizey--;
4648
4649   kx = RP.kx;
4650   ky = RP.ky;
4651
4652   use_coeff_table = coeff_table_mode = coeff_table_size = coeff_table_shift = 0;
4653   coeff_table_offset = 0;
4654   coeff_table_val = 0;
4655   coeff_table_base = NULL;
4656
4657   if ( LOG_ROZ == 1 ) logerror( "Rendering RBG with parameter %s\n", iRP == 1 ? "A" : "B" );
4658   if ( LOG_ROZ == 1 ) logerror( "RPMD (parameter mode) = %x\n", STV_VDP2_RPMD );
4659   if ( LOG_ROZ == 1 ) logerror( "RPRCTL (parameter read control) = %04x\n", STV_VDP2_RPRCTL );
4660   if ( LOG_ROZ == 1 ) logerror( "KTCTL (coefficient table control) = %04x\n", STV_VDP2_KTCTL );
4661   if ( LOG_ROZ == 1 ) logerror( "KTAOF (coefficient table address offset) = %04x\n", STV_VDP2_KTAOF );
4662   if ( LOG_ROZ == 1 ) logerror( "RAOVR (screen-over process) = %x\n", STV_VDP2_RAOVR );
4663   if ( iRP == 1 )
4664   {
4665      use_coeff_table = STV_VDP2_RAKTE;
4666      if ( use_coeff_table == 1 )
4667      {
4668         coeff_table_mode = STV_VDP2_RAKMD;
4669         coeff_table_size = STV_VDP2_RAKDBS;
4670         coeff_table_offset = STV_VDP2_RAKTAOS;
4671      }
4672      screen_over_process = STV_VDP2_RAOVR;
4673   }
4674   else
4675   {
4676      use_coeff_table = STV_VDP2_RBKTE;
4677      if ( use_coeff_table == 1 )
4678      {
4679         coeff_table_mode = STV_VDP2_RBKMD;
4680         coeff_table_size = STV_VDP2_RBKDBS;
4681         coeff_table_offset = STV_VDP2_RBKTAOS;
4682      }
4683      screen_over_process = STV_VDP2_RBOVR;
4684   }
4685   if ( use_coeff_table )
4686   {
4687      if ( STV_VDP2_CRKTE == 0 )
4688      {
4689         coeff_table_base = m_vdp2_vram;
4690      }
4691      else
4692      {
4693         coeff_table_base = m_vdp2_cram;
4694      }
4695      if ( coeff_table_size == 0 )
4696      {
4697         coeff_table_offset = (coeff_table_offset & 0x0003) * 0x40000;
4698         coeff_table_shift = 2;
4699      }
4700      else
4701      {
4702         coeff_table_offset = (coeff_table_offset & 0x0007) * 0x20000;
4703         coeff_table_shift = 1;
4704      }
4705   }
4706
4707   if ( stv2_current_tilemap.colour_calculation_enabled == 1 )
4708   {
4709      if ( STV_VDP2_CCMD )
4710      {
4711         stv2_current_tilemap.transparency = STV_TRANSPARENCY_ADD_BLEND;
4712      }
4713      else
4714      {
4715         stv2_current_tilemap.transparency = STV_TRANSPARENCY_ALPHA;
4716      }
4717   }
4718
4719   /* clipping */
4720   switch( screen_over_process )
4721   {
4722      case 0:
4723         /* repeated */
4724         clipxmask = clipymask = 0;
4725         break;
4726      case 1:
4727         /* screen over pattern, not supported */
4728         clipxmask = clipymask = 0;
4729         break;
4730      case 2:
4731         /* outside display area, scroll screen is transparent */
4732         clipxmask = ~planesizex;
4733         clipymask = ~planesizey;
4734         break;
4735      case 3:
4736         /* display area is 512x512, outside is transparent */
4737         clipxmask = ~511;
4738         clipymask = ~511;
4739         break;
4740   }
4741
4742   //dx  = (RP.A * RP.dx) + (RP.B * RP.dy);
4743   //dy  = (RP.D * RP.dx) + (RP.E * RP.dy);
4744   dx = mul_fixed32( RP.A, RP.dx ) + mul_fixed32( RP.B, RP.dy );
4745   dy = mul_fixed32( RP.D, RP.dx ) + mul_fixed32( RP.E, RP.dy );
4746
4747   //xp  = RP.A * ( RP.px - RP.cx ) + RP.B * ( RP.py - RP.cy ) + RP.C * ( RP.pz - RP.cz ) + RP.cx + RP.mx;
4748   //yp  = RP.D * ( RP.px - RP.cx ) + RP.E * ( RP.py - RP.cy ) + RP.F * ( RP.pz - RP.cz ) + RP.cy + RP.my;
4749   xp = mul_fixed32( RP.A, RP.px - RP.cx ) + mul_fixed32( RP.B, RP.py - RP.cy ) + mul_fixed32( RP.C, RP.pz - RP.cz ) + RP.cx + RP.mx;
4750   yp = mul_fixed32( RP.D, RP.px - RP.cx ) + mul_fixed32( RP.E, RP.py - RP.cy ) + mul_fixed32( RP.F, RP.pz - RP.cz ) + RP.cy + RP.my;
4751
4752   for (vcnt = cliprect.min_y; vcnt <= cliprect.max_y; vcnt++ )
4753   {
4754      /*xsp = RP.A * ( ( RP.xst + RP.dxst * (vcnt << 16) ) - RP.px ) +
4755            RP.B * ( ( RP.yst + RP.dyst * (vcnt << 16) ) - RP.py ) +
4756            RP.C * ( RP.zst - RP.pz);
4757      ysp = RP.D * ( ( RP.xst + RP.dxst * (vcnt << 16) ) - RP.px ) +
4758            RP.E * ( ( RP.yst + RP.dyst * (vcnt << 16) ) - RP.py ) +
4759            RP.F * ( RP.zst - RP.pz );*/
4760      xsp = mul_fixed32( RP.A, RP.xst + mul_fixed32( RP.dxst, vcnt << (16 - vcnt_shift)) - RP.px ) +
4761            mul_fixed32( RP.B, RP.yst + mul_fixed32( RP.dyst, vcnt << (16 - vcnt_shift)) - RP.py ) +
4762            mul_fixed32( RP.C, RP.zst - RP.pz );
4763      ysp = mul_fixed32( RP.D, RP.xst + mul_fixed32( RP.dxst, vcnt << (16 - vcnt_shift)) - RP.px ) +
4764            mul_fixed32( RP.E, RP.yst + mul_fixed32( RP.dyst, vcnt << (16 - vcnt_shift)) - RP.py ) +
4765            mul_fixed32( RP.F, RP.zst - RP.pz );
4766      //xp  = RP.A * ( RP.px - RP.cx ) + RP.B * ( RP.py - RP.cy ) + RP.C * ( RP.pz - RP.cz ) + RP.cx + RP.mx;
4767      //yp  = RP.D * ( RP.px - RP.cx ) + RP.E * ( RP.py - RP.cy ) + RP.F * ( RP.pz - RP.cz ) + RP.cy + RP.my;
4768      //dx  = (RP.A * RP.dx) + (RP.B * RP.dy);
4769      //dy  = (RP.D * RP.dx) + (RP.E * RP.dy);
4770
4771      line = &bitmap.pix32(vcnt);
4772
4773      if ( !use_coeff_table || RP.dkax == 0 )
4774      {
4775         if ( use_coeff_table )
4776         {
4777            switch( coeff_table_size )
4778            {
4779               case 0:
4780                  address = coeff_table_offset + ((RP.kast + RP.dkast*(vcnt>>vcnt_shift)) >> 16) * 4;
4781                  coeff_table_val = coeff_table_base[ address / 4 ];
4782                  //coeff_line_color_screen_data = (coeff_table_val & 0x7f000000) >> 24;
4783                  coeff_msb = (coeff_table_val & 0x80000000) > 0;
4784                  if ( coeff_table_val & 0x00800000 )
4785                  {
4786                     coeff_table_val |= 0xff000000;
4787                  }
4788                  else
4789                  {
4790                     coeff_table_val &= 0x007fffff;
4791                  }
4792                  break;
4793               case 1:
4794                  address = coeff_table_offset + ((RP.kast + RP.dkast*(vcnt>>vcnt_shift)) >> 16) * 2;
4795                  coeff_table_val = coeff_table_base[ address / 4 ];
4796                  if ( (address & 2) == 0 )
4797                  {
4798                     coeff_table_val >>= 16;
4799                  }
4800                  coeff_table_val &= 0xffff;
4801                  //coeff_line_color_screen_data = 0;
4802                  coeff_msb = (coeff_table_val & 0x8000) > 0;
4803                  if ( coeff_table_val & 0x4000 )
4804                  {
4805                     coeff_table_val |= 0xffff8000;
4806                  }
4807                  else
4808                  {
4809                     coeff_table_val &= 0x3fff;
4810                  }
4811                  coeff_table_val <<= 6; /* to form 16.16 fixed point val */
4812                  break;
4813               default:
4814                  coeff_msb = 1;
4815                  break;
4816            }
4817            if ( coeff_msb ) continue;
4818
4819            switch( coeff_table_mode )
4820            {
4821               case 0:
4822                  kx = ky = coeff_table_val;
4823                  break;
4824               case 1:
4825                  kx = coeff_table_val;
4826                  break;
4827               case 2:
4828                  ky = coeff_table_val;
4829                  break;
4830               case 3:
4831                  xp = coeff_table_val;
4832                  break;
4833            }
4834         }
4835
4836         //x = RP.kx * ( xsp + dx * (hcnt << 16)) + xp;
4837         //y = RP.ky * ( ysp + dy * (hcnt << 16)) + yp;
4838         xs = mul_fixed32( kx, xsp ) + xp;
4839         ys = mul_fixed32( ky, ysp ) + yp;
4840         dxs = mul_fixed32( kx, mul_fixed32( dx, 1 << (16-hcnt_shift)));
4841         dys = mul_fixed32( ky, mul_fixed32( dy, 1 << (16-hcnt_shift)));
4842
4843         for (hcnt = cliprect.min_x; hcnt <= cliprect.max_x; xs+=dxs, ys+=dys, hcnt++ )
4844         {
4845            x = xs >> 16;
4846            y = ys >> 16;
4847
4848            if ( x & clipxmask || y & clipymask ) continue;
4849            pix = roz_bitmap.pix32(y & planerenderedsizey, x & planerenderedsizex);
4850            switch( stv2_current_tilemap.transparency )
4851            {
4852               case STV_TRANSPARENCY_PEN:
4853                  if (pix & 0xffffff)
4854                  {
4855                     if(stv2_current_tilemap.fade_control & 1)
4856                        stv_vdp2_compute_color_offset_UINT32(&pix,stv2_current_tilemap.fade_control & 2);
4857
4858                     line[hcnt] = pix;
4859                  }
4860                  break;
4861               case STV_TRANSPARENCY_NONE:
4862                  if(stv2_current_tilemap.fade_control & 1)
4863                     stv_vdp2_compute_color_offset_UINT32(&pix,stv2_current_tilemap.fade_control & 2);
4864
4865                  line[hcnt] = pix;
4866                  break;
4867               case STV_TRANSPARENCY_ALPHA:
4868                  if (pix & 0xffffff)
4869                  {
4870                     if(stv2_current_tilemap.fade_control & 1)
4871                        stv_vdp2_compute_color_offset_UINT32(&pix,stv2_current_tilemap.fade_control & 2);
4872
4873                     line[hcnt] = alpha_blend_r32( line[hcnt], pix, stv2_current_tilemap.alpha );
4874                  }
4875                  break;
4876               case STV_TRANSPARENCY_ADD_BLEND:
4877                  if (pix & 0xffffff)
4878                  {
4879                     if(stv2_current_tilemap.fade_control & 1)
4880                        stv_vdp2_compute_color_offset_UINT32(&pix,stv2_current_tilemap.fade_control & 2);
4881
4882                     line[hcnt] = stv_add_blend( line[hcnt], pix );
4883                  }
4884                  break;
4885            }
4886
4887         }
4888      }
4889      else
4890      {
4891         for (hcnt = cliprect.min_x; hcnt <= cliprect.max_x; hcnt++ )
4892         {
4893            switch( coeff_table_size )
4894            {
4895               case 0:
4896                  address = coeff_table_offset + ((RP.kast + RP.dkast*(vcnt>>vcnt_shift) + RP.dkax*hcnt) >> 16) * 4;
4897                  coeff_table_val = coeff_table_base[ address / 4 ];
4898                  //coeff_line_color_screen_data = (coeff_table_val & 0x7f000000) >> 24;
4899                  coeff_msb = (coeff_table_val & 0x80000000) > 0;
4900                  if ( coeff_table_val & 0x00800000 )
4901                  {
4902                     coeff_table_val |= 0xff000000;
4903                  }
4904                  else
4905                  {
4906                     coeff_table_val &= 0x007fffff;
4907                  }
4908                  break;
4909               case 1:
4910                  address = coeff_table_offset + ((RP.kast + RP.dkast*(vcnt>>vcnt_shift) + RP.dkax*hcnt) >> 16) * 2;
4911                  coeff_table_val = coeff_table_base[ address / 4 ];
4912                  if ( (address & 2) == 0 )
4913                  {
4914                     coeff_table_val >>= 16;
4915                  }
4916                  coeff_table_val &= 0xffff;
4917                  //coeff_line_color_screen_data = 0;
4918                  coeff_msb = (coeff_table_val & 0x8000) > 0;
4919                  if ( coeff_table_val & 0x4000 )
4920                  {
4921                     coeff_table_val |= 0xffff8000;
4922                  }
4923                  else
4924                  {
4925                     coeff_table_val &= 0x3fff;
4926                  }
4927                  coeff_table_val <<= 6; /* to form 16.16 fixed point val */
4928                  break;
4929               default:
4930                  coeff_msb = 1;
4931                  break;
4932            }
4933            if ( coeff_msb ) continue;
4934            switch( coeff_table_mode )
4935            {
4936               case 0:
4937                  kx = ky = coeff_table_val;
4938                  break;
4939               case 1:
4940                  kx = coeff_table_val;
4941                  break;
4942               case 2:
4943                  ky = coeff_table_val;
4944                  break;
4945               case 3:
4946                  xp = coeff_table_val;
4947                  break;
4948            }
4949
4950            //x = RP.kx * ( xsp + dx * (hcnt << 16)) + xp;
4951            //y = RP.ky * ( ysp + dy * (hcnt << 16)) + yp;
4952            x = mul_fixed32( kx, xsp + mul_fixed32( dx, (hcnt>>hcnt_shift) << 16 ) ) + xp;
4953            y = mul_fixed32( ky, ysp + mul_fixed32( dy, (hcnt>>hcnt_shift) << 16 ) ) + yp;
4954
4955            x >>= 16;
4956            y >>= 16;
4957
4958            if ( x & clipxmask || y & clipymask ) continue;
4959
4960            pix = roz_bitmap.pix32(y & planerenderedsizey, x & planerenderedsizex);
4961            switch( stv2_current_tilemap.transparency )
4962            {
4963               case STV_TRANSPARENCY_PEN:
4964                  if (pix & 0xffffff)
4965                  {
4966                     if(stv2_current_tilemap.fade_control & 1)
4967                        stv_vdp2_compute_color_offset_UINT32(&pix,stv2_current_tilemap.fade_control & 2);
4968
4969                     line[hcnt] = pix;
4970                  }
4971                  break;
4972               case STV_TRANSPARENCY_NONE:
4973                  if(stv2_current_tilemap.fade_control & 1)
4974                     stv_vdp2_compute_color_offset_UINT32(&pix,stv2_current_tilemap.fade_control & 2);
4975
4976                  line[hcnt] = pix;
4977                  break;
4978               case STV_TRANSPARENCY_ALPHA:
4979                  if (pix & 0xffffff)
4980                  {
4981                     if(stv2_current_tilemap.fade_control & 1)
4982                        stv_vdp2_compute_color_offset_UINT32(&pix,stv2_current_tilemap.fade_control & 2);
4983
4984                     line[hcnt] = alpha_blend_r32( line[hcnt], pix, stv2_current_tilemap.alpha );
4985                  }
4986                  break;
4987               case STV_TRANSPARENCY_ADD_BLEND:
4988                  if (pix & 0xffffff)
4989                  {
4990                     if(stv2_current_tilemap.fade_control & 1)
4991                        stv_vdp2_compute_color_offset_UINT32(&pix,stv2_current_tilemap.fade_control & 2);
4992
4993                     line[hcnt] = stv_add_blend( line[hcnt], pix );
4994                  }
4995                  break;
4996            }
4997         }
4998      }
4999   }
5000}
5001
5002void saturn_state::stv_vdp2_draw_NBG0(bitmap_rgb32 &bitmap, const rectangle &cliprect)
5003{
5004   UINT32 base_mask;
5005
5006   base_mask = STV_VDP2_VRAMSZ ? 0x7ffff : 0x3ffff;
5007
5008   /*
5009      Colours           : 16, 256, 2048, 32768, 16770000
5010      Char Size         : 1x1 cells, 2x2 cells
5011      Pattern Data Size : 1 word, 2 words
5012      Plane Layouts     : 1 x 1, 2 x 1, 2 x 2
5013      Planes            : 4
5014      Bitmap            : Possible
5015      Bitmap Sizes      : 512 x 256, 512 x 512, 1024 x 256, 1024 x 512
5016      Scale             : 0.25 x - 256 x
5017      Rotation          : No
5018      Linescroll        : Yes
5019      Column Scroll     : Yes
5020      Mosaic            : Yes
5021   */
5022
5023   stv2_current_tilemap.enabled = STV_VDP2_N0ON | STV_VDP2_R1ON;
5024
5025//  if (!stv2_current_tilemap.enabled) return; // stop right now if its disabled ...
5026
5027   //stv2_current_tilemap.trans_enabled = STV_VDP2_N0TPON;
5028   if ( STV_VDP2_N0CCEN )
5029   {
5030      stv2_current_tilemap.colour_calculation_enabled = 1;
5031      stv2_current_tilemap.alpha = ((UINT16)(0x1f-STV_VDP2_N0CCRT)*0xff)/0x1f;
5032   }
5033   else
5034   {
5035      stv2_current_tilemap.colour_calculation_enabled = 0;
5036   }
5037   if ( STV_VDP2_N0TPON == 0 )
5038   {
5039      stv2_current_tilemap.transparency = STV_TRANSPARENCY_PEN;
5040   }
5041   else
5042   {
5043      stv2_current_tilemap.transparency = STV_TRANSPARENCY_NONE;
5044   }
5045   stv2_current_tilemap.colour_depth = STV_VDP2_N0CHCN;
5046   stv2_current_tilemap.tile_size = STV_VDP2_N0CHSZ;
5047   stv2_current_tilemap.bitmap_enable = STV_VDP2_N0BMEN;
5048   stv2_current_tilemap.bitmap_size = STV_VDP2_N0BMSZ;
5049   stv2_current_tilemap.bitmap_palette_number = STV_VDP2_N0BMP;
5050   stv2_current_tilemap.bitmap_map = STV_VDP2_N0MP_;
5051   stv2_current_tilemap.map_offset[0] = STV_VDP2_N0MPA | (STV_VDP2_N0MP_ << 6);
5052   stv2_current_tilemap.map_offset[1] = STV_VDP2_N0MPB | (STV_VDP2_N0MP_ << 6);
5053   stv2_current_tilemap.map_offset[2] = STV_VDP2_N0MPC | (STV_VDP2_N0MP_ << 6);
5054   stv2_current_tilemap.map_offset[3] = STV_VDP2_N0MPD | (STV_VDP2_N0MP_ << 6);
5055   stv2_current_tilemap.map_count = 4;
5056
5057   stv2_current_tilemap.pattern_data_size = STV_VDP2_N0PNB;
5058   stv2_current_tilemap.character_number_supplement = STV_VDP2_N0CNSM;
5059   stv2_current_tilemap.special_priority_register = STV_VDP2_N0SPR;
5060   stv2_current_tilemap.special_colour_control_register = STV_VDP2_PNCN0;
5061   stv2_current_tilemap.supplementary_palette_bits = STV_VDP2_N0SPLT;
5062   stv2_current_tilemap.supplementary_character_bits = STV_VDP2_N0SPCN;
5063
5064   stv2_current_tilemap.scrollx = STV_VDP2_SCXIN0;
5065   stv2_current_tilemap.scrolly = STV_VDP2_SCYIN0;
5066   stv2_current_tilemap.incx = STV_VDP2_ZMXN0;
5067   stv2_current_tilemap.incy = STV_VDP2_ZMYN0;
5068
5069   stv2_current_tilemap.linescroll_enable = STV_VDP2_N0LSCX;
5070   stv2_current_tilemap.linescroll_interval = (((STV_VDP2_LSMD & 3) == 2) ? (2) : (1)) << (STV_VDP2_N0LSS);
5071   stv2_current_tilemap.linescroll_table_address = (((STV_VDP2_LSTA0U << 16) | STV_VDP2_LSTA0L) & base_mask) * 2;
5072   stv2_current_tilemap.vertical_linescroll_enable = STV_VDP2_N0LSCY;
5073   stv2_current_tilemap.linezoom_enable = STV_VDP2_N0LZMX;
5074
5075   stv2_current_tilemap.plane_size = (STV_VDP2_R1ON) ? STV_VDP2_RBPLSZ : STV_VDP2_N0PLSZ;
5076   stv2_current_tilemap.colour_ram_address_offset = STV_VDP2_N0CAOS;
5077   stv2_current_tilemap.fade_control = (STV_VDP2_N0COEN * 1) | (STV_VDP2_N0COSL * 2);
5078   stv_vdp2_check_fade_control_for_layer();
5079   stv2_current_tilemap.window_control = (STV_VDP2_N0LOG << 0) |
5080                                 (STV_VDP2_N0W0E << 1) |
5081                                 (STV_VDP2_N0W1E << 2) |
5082                                 (STV_VDP2_N0SWE << 3) |
5083                                 (STV_VDP2_N0W0A << 4) |
5084                                 (STV_VDP2_N0W1A << 5) |
5085                                 (STV_VDP2_N0SWA << 6);
5086
5087   stv2_current_tilemap.line_screen_enabled = STV_VDP2_N0LCEN;
5088   stv2_current_tilemap.mosaic_screen_enabled = STV_VDP2_N0MZE;
5089
5090   stv2_current_tilemap.layer_name=(STV_VDP2_R1ON) ? 0x81 : 0;
5091
5092   if ( stv2_current_tilemap.enabled && (!(STV_VDP2_R1ON))) /* TODO: check cycle pattern for RBG1 */
5093   {
5094      stv2_current_tilemap.enabled = stv_vdp2_check_vram_cycle_pattern_registers( STV_VDP2_CP_NBG0_PNMDR, STV_VDP2_CP_NBG0_CPDR, stv2_current_tilemap.bitmap_enable );
5095   }
5096
5097   if(STV_VDP2_R1ON)
5098      stv_vdp2_draw_rotation_screen(bitmap, cliprect, 2 );
5099   else
5100      stv_vdp2_check_tilemap(bitmap, cliprect);
5101}
5102
5103void saturn_state::stv_vdp2_draw_NBG1(bitmap_rgb32 &bitmap, const rectangle &cliprect)
5104{
5105   UINT32 base_mask;
5106
5107   base_mask = STV_VDP2_VRAMSZ ? 0x7ffff : 0x3ffff;
5108
5109   /*
5110      Colours           : 16, 256, 2048, 32768
5111      Char Size         : 1x1 cells, 2x2 cells
5112      Pattern Data Size : 1 word, 2 words
5113      Plane Layouts     : 1 x 1, 2 x 1, 2 x 2
5114      Planes            : 4
5115      Bitmap            : Possible
5116      Bitmap Sizes      : 512 x 256, 512 x 512, 1024 x 256, 1024 x 512
5117      Scale             : 0.25 x - 256 x
5118      Rotation          : No
5119      Linescroll        : Yes
5120      Column Scroll     : Yes
5121      Mosaic            : Yes
5122   */
5123   stv2_current_tilemap.enabled = STV_VDP2_N1ON;
5124
5125//  if (!stv2_current_tilemap.enabled) return; // stop right now if its disabled ...
5126
5127   //stv2_current_tilemap.trans_enabled = STV_VDP2_N1TPON;
5128   if ( STV_VDP2_N1CCEN )
5129   {
5130      stv2_current_tilemap.colour_calculation_enabled = 1;
5131      stv2_current_tilemap.alpha = ((UINT16)(0x1f-STV_VDP2_N1CCRT)*0xff)/0x1f;
5132   }
5133   else
5134   {
5135      stv2_current_tilemap.colour_calculation_enabled = 0;
5136   }
5137   if ( STV_VDP2_N1TPON == 0 )
5138   {
5139      stv2_current_tilemap.transparency = STV_TRANSPARENCY_PEN;
5140   }
5141   else
5142   {
5143      stv2_current_tilemap.transparency = STV_TRANSPARENCY_NONE;
5144   }
5145   stv2_current_tilemap.colour_depth = STV_VDP2_N1CHCN;
5146   stv2_current_tilemap.tile_size = STV_VDP2_N1CHSZ;
5147   stv2_current_tilemap.bitmap_enable = STV_VDP2_N1BMEN;
5148   stv2_current_tilemap.bitmap_size = STV_VDP2_N1BMSZ;
5149   stv2_current_tilemap.bitmap_palette_number = STV_VDP2_N1BMP;
5150   stv2_current_tilemap.bitmap_map = STV_VDP2_N1MP_;
5151   stv2_current_tilemap.map_offset[0] = STV_VDP2_N1MPA | (STV_VDP2_N1MP_ << 6);
5152   stv2_current_tilemap.map_offset[1] = STV_VDP2_N1MPB | (STV_VDP2_N1MP_ << 6);
5153   stv2_current_tilemap.map_offset[2] = STV_VDP2_N1MPC | (STV_VDP2_N1MP_ << 6);
5154   stv2_current_tilemap.map_offset[3] = STV_VDP2_N1MPD | (STV_VDP2_N1MP_ << 6);
5155   stv2_current_tilemap.map_count = 4;
5156
5157   stv2_current_tilemap.pattern_data_size = STV_VDP2_N1PNB;
5158   stv2_current_tilemap.character_number_supplement = STV_VDP2_N1CNSM;
5159   stv2_current_tilemap.special_priority_register = STV_VDP2_N1SPR;
5160   stv2_current_tilemap.special_colour_control_register = STV_VDP2_PNCN1;
5161   stv2_current_tilemap.supplementary_palette_bits = STV_VDP2_N1SPLT;
5162   stv2_current_tilemap.supplementary_character_bits = STV_VDP2_N1SPCN;
5163
5164   stv2_current_tilemap.scrollx = STV_VDP2_SCXIN1;
5165   stv2_current_tilemap.scrolly = STV_VDP2_SCYIN1;
5166   stv2_current_tilemap.incx = STV_VDP2_ZMXN1;
5167   stv2_current_tilemap.incy = STV_VDP2_ZMYN1;
5168
5169   stv2_current_tilemap.linescroll_enable = STV_VDP2_N1LSCX;
5170   stv2_current_tilemap.linescroll_interval = (((STV_VDP2_LSMD & 3) == 2) ? (2) : (1)) << (STV_VDP2_N1LSS);
5171   stv2_current_tilemap.linescroll_table_address = (((STV_VDP2_LSTA1U << 16) | STV_VDP2_LSTA1L) & base_mask) * 2;
5172   stv2_current_tilemap.vertical_linescroll_enable = STV_VDP2_N1LSCY;
5173   stv2_current_tilemap.linezoom_enable = STV_VDP2_N1LZMX;
5174
5175   stv2_current_tilemap.plane_size = STV_VDP2_N1PLSZ;
5176   stv2_current_tilemap.colour_ram_address_offset = STV_VDP2_N1CAOS;
5177   stv2_current_tilemap.fade_control = (STV_VDP2_N1COEN * 1) | (STV_VDP2_N1COSL * 2);
5178   stv_vdp2_check_fade_control_for_layer();
5179   stv2_current_tilemap.window_control = (STV_VDP2_N1LOG << 0) |
5180                                 (STV_VDP2_N1W0E << 1) |
5181                                 (STV_VDP2_N1W1E << 2) |
5182                                 (STV_VDP2_N1SWE << 3) |
5183                                 (STV_VDP2_N1W0A << 4) |
5184                                 (STV_VDP2_N1W1A << 5) |
5185                                 (STV_VDP2_N1SWA << 6);
5186
5187   stv2_current_tilemap.line_screen_enabled = STV_VDP2_N1LCEN;
5188   stv2_current_tilemap.mosaic_screen_enabled = STV_VDP2_N1MZE;
5189
5190   stv2_current_tilemap.layer_name=1;
5191
5192   if ( stv2_current_tilemap.enabled )
5193   {
5194      stv2_current_tilemap.enabled = stv_vdp2_check_vram_cycle_pattern_registers( STV_VDP2_CP_NBG1_PNMDR, STV_VDP2_CP_NBG1_CPDR, stv2_current_tilemap.bitmap_enable );
5195   }
5196
5197   stv_vdp2_check_tilemap(bitmap, cliprect);
5198}
5199
5200void saturn_state::stv_vdp2_draw_NBG2(bitmap_rgb32 &bitmap, const rectangle &cliprect)
5201{
5202   /*
5203      NBG2 is the first of the 2 more basic tilemaps, it has exactly the same capabilities as NBG3
5204
5205      Colours           : 16, 256
5206      Char Size         : 1x1 cells, 2x2 cells
5207      Pattern Data Size : 1 word, 2 words
5208      Plane Layouts     : 1 x 1, 2 x 1, 2 x 2
5209      Planes            : 4
5210      Bitmap            : No
5211      Bitmap Sizes      : N/A
5212      Scale             : No
5213      Rotation          : No
5214      Linescroll        : No
5215      Column Scroll     : No
5216      Mosaic            : Yes
5217   */
5218
5219   stv2_current_tilemap.enabled = STV_VDP2_N2ON;
5220
5221   /* these modes for N0 disable this layer */
5222   if (STV_VDP2_N0CHCN == 0x03) stv2_current_tilemap.enabled = 0;
5223   if (STV_VDP2_N0CHCN == 0x04) stv2_current_tilemap.enabled = 0;
5224
5225//  if (!stv2_current_tilemap.enabled) return; // stop right now if its disabled ...
5226
5227   //stv2_current_tilemap.trans_enabled = STV_VDP2_N2TPON;
5228   if ( STV_VDP2_N2CCEN )
5229   {
5230      stv2_current_tilemap.colour_calculation_enabled = 1;
5231      stv2_current_tilemap.alpha = ((UINT16)(0x1f-STV_VDP2_N2CCRT)*0xff)/0x1f;
5232   }
5233   else
5234   {
5235      stv2_current_tilemap.colour_calculation_enabled = 0;
5236   }
5237   if ( STV_VDP2_N2TPON == 0 )
5238   {
5239      stv2_current_tilemap.transparency = STV_TRANSPARENCY_PEN;
5240   }
5241   else
5242   {
5243      stv2_current_tilemap.transparency = STV_TRANSPARENCY_NONE;
5244   }
5245   stv2_current_tilemap.colour_depth = STV_VDP2_N2CHCN;
5246   stv2_current_tilemap.tile_size = STV_VDP2_N2CHSZ;
5247   /* this layer can't be a bitmap,so ignore these registers*/
5248   stv2_current_tilemap.bitmap_enable = 0;
5249   stv2_current_tilemap.bitmap_size = 0;
5250   stv2_current_tilemap.bitmap_palette_number = 0;
5251   stv2_current_tilemap.bitmap_map = 0;
5252   stv2_current_tilemap.map_offset[0] = STV_VDP2_N2MPA | (STV_VDP2_N2MP_ << 6);
5253   stv2_current_tilemap.map_offset[1] = STV_VDP2_N2MPB | (STV_VDP2_N2MP_ << 6);
5254   stv2_current_tilemap.map_offset[2] = STV_VDP2_N2MPC | (STV_VDP2_N2MP_ << 6);
5255   stv2_current_tilemap.map_offset[3] = STV_VDP2_N2MPD | (STV_VDP2_N2MP_ << 6);
5256   stv2_current_tilemap.map_count = 4;
5257
5258   stv2_current_tilemap.pattern_data_size = STV_VDP2_N2PNB;
5259   stv2_current_tilemap.character_number_supplement = STV_VDP2_N2CNSM;
5260   stv2_current_tilemap.special_priority_register = STV_VDP2_N2SPR;
5261   stv2_current_tilemap.special_colour_control_register = STV_VDP2_PNCN2;
5262   stv2_current_tilemap.supplementary_palette_bits = STV_VDP2_N2SPLT;
5263   stv2_current_tilemap.supplementary_character_bits = STV_VDP2_N2SPCN;
5264
5265   stv2_current_tilemap.scrollx = STV_VDP2_SCXN2;
5266   stv2_current_tilemap.scrolly = STV_VDP2_SCYN2;
5267   /*This layer can't be scaled*/
5268   stv2_current_tilemap.incx = 0x10000;
5269   stv2_current_tilemap.incy = 0x10000;
5270
5271   stv2_current_tilemap.linescroll_enable = 0;
5272   stv2_current_tilemap.linescroll_interval = 0;
5273   stv2_current_tilemap.linescroll_table_address = 0;
5274   stv2_current_tilemap.vertical_linescroll_enable = 0;
5275   stv2_current_tilemap.linezoom_enable = 0;
5276
5277   stv2_current_tilemap.colour_ram_address_offset = STV_VDP2_N2CAOS;
5278   stv2_current_tilemap.fade_control = (STV_VDP2_N2COEN * 1) | (STV_VDP2_N2COSL * 2);
5279   stv_vdp2_check_fade_control_for_layer();
5280   stv2_current_tilemap.window_control = (STV_VDP2_N2LOG << 0) |
5281                                 (STV_VDP2_N2W0E << 1) |
5282                                 (STV_VDP2_N2W1E << 2) |
5283                                 (STV_VDP2_N2SWE << 3) |
5284                                 (STV_VDP2_N2W0A << 4) |
5285                                 (STV_VDP2_N2W1A << 5) |
5286                                 (STV_VDP2_N2SWA << 6);
5287
5288   stv2_current_tilemap.line_screen_enabled = STV_VDP2_N2LCEN;
5289   stv2_current_tilemap.mosaic_screen_enabled = STV_VDP2_N2MZE;
5290
5291   stv2_current_tilemap.layer_name=2;
5292
5293   stv2_current_tilemap.plane_size = STV_VDP2_N2PLSZ;
5294
5295   if ( stv2_current_tilemap.enabled )
5296   {
5297      stv2_current_tilemap.enabled = stv_vdp2_check_vram_cycle_pattern_registers( STV_VDP2_CP_NBG2_PNMDR, STV_VDP2_CP_NBG2_CPDR, stv2_current_tilemap.bitmap_enable );
5298   }
5299
5300   stv_vdp2_check_tilemap(bitmap, cliprect);
5301}
5302
5303void saturn_state::stv_vdp2_draw_NBG3(bitmap_rgb32 &bitmap, const rectangle &cliprect)
5304{
5305   /*
5306      NBG3 is the second of the 2 more basic tilemaps, it has exactly the same capabilities as NBG2
5307
5308      Colours           : 16, 256
5309      Char Size         : 1x1 cells, 2x2 cells
5310      Pattern Data Size : 1 word, 2 words
5311      Plane Layouts     : 1 x 1, 2 x 1, 2 x 2
5312      Planes            : 4
5313      Bitmap            : No
5314      Bitmap Sizes      : N/A
5315      Scale             : No
5316      Rotation          : No
5317      Linescroll        : No
5318      Column Scroll     : No
5319      Mosaic            : Yes
5320   */
5321
5322   stv2_current_tilemap.enabled = STV_VDP2_N3ON;
5323
5324//  if (!stv2_current_tilemap.enabled) return; // stop right now if its disabled ...
5325
5326   /* these modes for N1 disable this layer */
5327   if (STV_VDP2_N1CHCN == 0x03) stv2_current_tilemap.enabled = 0;
5328   if (STV_VDP2_N1CHCN == 0x04) stv2_current_tilemap.enabled = 0;
5329
5330   //stv2_current_tilemap.trans_enabled = STV_VDP2_N3TPON;
5331   if ( STV_VDP2_N3CCEN )
5332   {
5333      stv2_current_tilemap.colour_calculation_enabled = 1;
5334      stv2_current_tilemap.alpha = ((UINT16)(0x1f-STV_VDP2_N3CCRT)*0xff)/0x1f;
5335   }
5336   else
5337   {
5338      stv2_current_tilemap.colour_calculation_enabled = 0;
5339   }
5340   if ( STV_VDP2_N3TPON == 0 )
5341   {
5342      stv2_current_tilemap.transparency = STV_TRANSPARENCY_PEN;
5343   }
5344   else
5345   {
5346      stv2_current_tilemap.transparency = STV_TRANSPARENCY_NONE;
5347   }
5348   stv2_current_tilemap.colour_depth = STV_VDP2_N3CHCN;
5349   stv2_current_tilemap.tile_size = STV_VDP2_N3CHSZ;
5350   /* this layer can't be a bitmap,so ignore these registers*/
5351   stv2_current_tilemap.bitmap_enable = 0;
5352   stv2_current_tilemap.bitmap_size = 0;
5353   stv2_current_tilemap.bitmap_palette_number = 0;
5354   stv2_current_tilemap.bitmap_map = 0;
5355   stv2_current_tilemap.map_offset[0] = STV_VDP2_N3MPA | (STV_VDP2_N3MP_ << 6);
5356   stv2_current_tilemap.map_offset[1] = STV_VDP2_N3MPB | (STV_VDP2_N3MP_ << 6);
5357   stv2_current_tilemap.map_offset[2] = STV_VDP2_N3MPC | (STV_VDP2_N3MP_ << 6);
5358   stv2_current_tilemap.map_offset[3] = STV_VDP2_N3MPD | (STV_VDP2_N3MP_ << 6);
5359   stv2_current_tilemap.map_count = 4;
5360
5361   stv2_current_tilemap.pattern_data_size = STV_VDP2_N3PNB;
5362   stv2_current_tilemap.character_number_supplement = STV_VDP2_N3CNSM;
5363   stv2_current_tilemap.special_priority_register = STV_VDP2_N3SPR;
5364   stv2_current_tilemap.special_colour_control_register = STV_VDP2_N3SCC;
5365   stv2_current_tilemap.supplementary_palette_bits = STV_VDP2_N3SPLT;
5366   stv2_current_tilemap.supplementary_character_bits = STV_VDP2_N3SPCN;
5367
5368   stv2_current_tilemap.scrollx = STV_VDP2_SCXN3;
5369   stv2_current_tilemap.scrolly = STV_VDP2_SCYN3;
5370   /*This layer can't be scaled*/
5371   stv2_current_tilemap.incx = 0x10000;
5372   stv2_current_tilemap.incy = 0x10000;
5373
5374   stv2_current_tilemap.linescroll_enable = 0;
5375   stv2_current_tilemap.linescroll_interval = 0;
5376   stv2_current_tilemap.linescroll_table_address = 0;
5377   stv2_current_tilemap.vertical_linescroll_enable = 0;
5378   stv2_current_tilemap.linezoom_enable = 0;
5379
5380   stv2_current_tilemap.colour_ram_address_offset = STV_VDP2_N3CAOS;
5381   stv2_current_tilemap.fade_control = (STV_VDP2_N3COEN * 1) | (STV_VDP2_N3COSL * 2);
5382   stv_vdp2_check_fade_control_for_layer();
5383   stv2_current_tilemap.window_control = (STV_VDP2_N3LOG << 0) |
5384                                 (STV_VDP2_N3W0E << 1) |
5385                                 (STV_VDP2_N3W1E << 2) |
5386                                 (STV_VDP2_N3SWE << 3) |
5387                                 (STV_VDP2_N3W0A << 4) |
5388                                 (STV_VDP2_N3W1A << 5) |
5389                                 (STV_VDP2_N3SWA << 6);
5390
5391   stv2_current_tilemap.line_screen_enabled = STV_VDP2_N3LCEN;
5392   stv2_current_tilemap.mosaic_screen_enabled = STV_VDP2_N3MZE;
5393
5394   stv2_current_tilemap.layer_name=3;
5395
5396   stv2_current_tilemap.plane_size = STV_VDP2_N3PLSZ;
5397
5398   if ( stv2_current_tilemap.enabled )
5399   {
5400      stv2_current_tilemap.enabled = stv_vdp2_check_vram_cycle_pattern_registers( STV_VDP2_CP_NBG3_PNMDR, STV_VDP2_CP_NBG3_CPDR, stv2_current_tilemap.bitmap_enable );
5401   }
5402
5403   stv_vdp2_check_tilemap(bitmap, cliprect);
5404}
5405
5406
5407void saturn_state::stv_vdp2_draw_rotation_screen(bitmap_rgb32 &bitmap, const rectangle &cliprect, int iRP)
5408{
5409   rectangle roz_clip_rect, mycliprect;
5410   int planesizex = 0, planesizey = 0;
5411   int planerenderedsizex, planerenderedsizey;
5412   UINT8 colour_calculation_enabled;
5413   UINT8 window_control;
5414   UINT8 fade_control;
5415
5416   if ( iRP == 1)
5417   {
5418      stv2_current_tilemap.bitmap_map = STV_VDP2_RAMP_;
5419      stv2_current_tilemap.map_offset[0] = STV_VDP2_RAMPA | (STV_VDP2_RAMP_ << 6);
5420      stv2_current_tilemap.map_offset[1] = STV_VDP2_RAMPB | (STV_VDP2_RAMP_ << 6);
5421      stv2_current_tilemap.map_offset[2] = STV_VDP2_RAMPC | (STV_VDP2_RAMP_ << 6);
5422      stv2_current_tilemap.map_offset[3] = STV_VDP2_RAMPD | (STV_VDP2_RAMP_ << 6);
5423      stv2_current_tilemap.map_offset[4] = STV_VDP2_RAMPE | (STV_VDP2_RAMP_ << 6);
5424      stv2_current_tilemap.map_offset[5] = STV_VDP2_RAMPF | (STV_VDP2_RAMP_ << 6);
5425      stv2_current_tilemap.map_offset[6] = STV_VDP2_RAMPG | (STV_VDP2_RAMP_ << 6);
5426      stv2_current_tilemap.map_offset[7] = STV_VDP2_RAMPH | (STV_VDP2_RAMP_ << 6);
5427      stv2_current_tilemap.map_offset[8] = STV_VDP2_RAMPI | (STV_VDP2_RAMP_ << 6);
5428      stv2_current_tilemap.map_offset[9] = STV_VDP2_RAMPJ | (STV_VDP2_RAMP_ << 6);
5429      stv2_current_tilemap.map_offset[10] = STV_VDP2_RAMPK | (STV_VDP2_RAMP_ << 6);
5430      stv2_current_tilemap.map_offset[11] = STV_VDP2_RAMPL | (STV_VDP2_RAMP_ << 6);
5431      stv2_current_tilemap.map_offset[12] = STV_VDP2_RAMPM | (STV_VDP2_RAMP_ << 6);
5432      stv2_current_tilemap.map_offset[13] = STV_VDP2_RAMPN | (STV_VDP2_RAMP_ << 6);
5433      stv2_current_tilemap.map_offset[14] = STV_VDP2_RAMPO | (STV_VDP2_RAMP_ << 6);
5434      stv2_current_tilemap.map_offset[15] = STV_VDP2_RAMPP | (STV_VDP2_RAMP_ << 6);
5435      stv2_current_tilemap.map_count = 16;
5436   }
5437   else
5438   {
5439      stv2_current_tilemap.bitmap_map = STV_VDP2_RBMP_;
5440      stv2_current_tilemap.map_offset[0] = STV_VDP2_RBMPA | (STV_VDP2_RBMP_ << 6);
5441      stv2_current_tilemap.map_offset[1] = STV_VDP2_RBMPB | (STV_VDP2_RBMP_ << 6);
5442      stv2_current_tilemap.map_offset[2] = STV_VDP2_RBMPC | (STV_VDP2_RBMP_ << 6);
5443      stv2_current_tilemap.map_offset[3] = STV_VDP2_RBMPD | (STV_VDP2_RBMP_ << 6);
5444      stv2_current_tilemap.map_offset[4] = STV_VDP2_RBMPE | (STV_VDP2_RBMP_ << 6);
5445      stv2_current_tilemap.map_offset[5] = STV_VDP2_RBMPF | (STV_VDP2_RBMP_ << 6);
5446      stv2_current_tilemap.map_offset[6] = STV_VDP2_RBMPG | (STV_VDP2_RBMP_ << 6);
5447      stv2_current_tilemap.map_offset[7] = STV_VDP2_RBMPH | (STV_VDP2_RBMP_ << 6);
5448      stv2_current_tilemap.map_offset[8] = STV_VDP2_RBMPI | (STV_VDP2_RBMP_ << 6);
5449      stv2_current_tilemap.map_offset[9] = STV_VDP2_RBMPJ | (STV_VDP2_RBMP_ << 6);
5450      stv2_current_tilemap.map_offset[10] = STV_VDP2_RBMPK | (STV_VDP2_RBMP_ << 6);
5451      stv2_current_tilemap.map_offset[11] = STV_VDP2_RBMPL | (STV_VDP2_RBMP_ << 6);
5452      stv2_current_tilemap.map_offset[12] = STV_VDP2_RBMPM | (STV_VDP2_RBMP_ << 6);
5453      stv2_current_tilemap.map_offset[13] = STV_VDP2_RBMPN | (STV_VDP2_RBMP_ << 6);
5454      stv2_current_tilemap.map_offset[14] = STV_VDP2_RBMPO | (STV_VDP2_RBMP_ << 6);
5455      stv2_current_tilemap.map_offset[15] = STV_VDP2_RBMPP | (STV_VDP2_RBMP_ << 6);
5456      stv2_current_tilemap.map_count = 16;
5457   }
5458
5459   stv_vdp2_fill_rotation_parameter_table(iRP);
5460
5461   if ( iRP == 1 )
5462   {
5463      stv2_current_tilemap.plane_size = STV_VDP2_RAPLSZ;
5464   }
5465   else
5466   {
5467      stv2_current_tilemap.plane_size = STV_VDP2_RBPLSZ;
5468   }
5469
5470   if (stv2_current_tilemap.bitmap_enable)
5471   {
5472      switch (stv2_current_tilemap.bitmap_size)
5473      {
5474         case 0: planesizex=512; planesizey=256; break;
5475         case 1: planesizex=512; planesizey=512; break;
5476         case 2: planesizex=1024; planesizey=256; break;
5477         case 3: planesizex=1024; planesizey=512; break;
5478      }
5479   }
5480   else
5481   {
5482      switch( stv2_current_tilemap.plane_size )
5483      {
5484      case 0:
5485         planesizex = planesizey = 2048;
5486         break;
5487      case 1:
5488         planesizex = 4096;
5489         planesizey = 2048;
5490         break;
5491      case 2:
5492         planesizex = 0;
5493         planesizey = 0;
5494         break;
5495      case 3:
5496         planesizex = planesizey = 4096;
5497         break;
5498      }
5499   }
5500
5501   if ( stv_vdp2_is_rotation_applied() == 0 )
5502   {
5503      stv2_current_tilemap.scrollx = stv_current_rotation_parameter_table.mx >> 16;
5504      stv2_current_tilemap.scrolly = stv_current_rotation_parameter_table.my >> 16;
5505
5506      stv_vdp2_check_tilemap(bitmap,cliprect);
5507   }
5508   else
5509   {
5510      if ( !m_vdp2.roz_bitmap[iRP-1].valid() )
5511         m_vdp2.roz_bitmap[iRP-1].allocate(4096, 4096);
5512
5513      roz_clip_rect.min_x = roz_clip_rect.min_y = 0;
5514      if ( (iRP == 1 && STV_VDP2_RAOVR == 3) ||
5515            (iRP == 2 && STV_VDP2_RBOVR == 3) )
5516      {
5517         roz_clip_rect.max_x = roz_clip_rect.max_y = 511;
5518         planerenderedsizex = planerenderedsizey = 512;
5519      }
5520      else if (stv_vdp2_are_map_registers_equal() &&
5521               !stv2_current_tilemap.bitmap_enable)
5522      {
5523         roz_clip_rect.max_x = (planesizex / 4) - 1;
5524         roz_clip_rect.max_y = (planesizey / 4) - 1;
5525         planerenderedsizex = planesizex / 4;
5526         planerenderedsizey = planesizey / 4;
5527      }
5528      else
5529      {
5530         roz_clip_rect.max_x = planesizex - 1;
5531         roz_clip_rect.max_y = planesizey - 1;
5532         planerenderedsizex = planesizex;
5533         planerenderedsizey = planesizey;
5534      }
5535
5536
5537      colour_calculation_enabled = stv2_current_tilemap.colour_calculation_enabled;
5538      stv2_current_tilemap.colour_calculation_enabled = 0;
5539      window_control = stv2_current_tilemap.window_control;
5540      stv2_current_tilemap.window_control = 0;
5541      fade_control = stv2_current_tilemap.fade_control;
5542      stv2_current_tilemap.fade_control = 0;
5543      g_profiler.start(PROFILER_USER1);
5544      if ( LOG_VDP2 ) logerror( "Checking for cached RBG bitmap, cache_dirty = %d, memcmp() = %d\n", stv_rbg_cache_data.is_cache_dirty, memcmp(&stv_rbg_cache_data.layer_data[iRP-1],&stv2_current_tilemap,sizeof(stv2_current_tilemap)));
5545      if ( (stv_rbg_cache_data.is_cache_dirty & iRP) ||
5546         memcmp(&stv_rbg_cache_data.layer_data[iRP-1],&stv2_current_tilemap,sizeof(stv2_current_tilemap)) != 0 )
5547      {
5548         m_vdp2.roz_bitmap[iRP-1].fill(get_black_pen(machine()), roz_clip_rect );
5549         stv_vdp2_check_tilemap(m_vdp2.roz_bitmap[iRP-1], roz_clip_rect);
5550         // prepare cache data
5551         stv_rbg_cache_data.watch_vdp2_vram_writes |= iRP;
5552         stv_rbg_cache_data.is_cache_dirty &= ~iRP;
5553         memcpy(&stv_rbg_cache_data.layer_data[iRP-1], &stv2_current_tilemap, sizeof(stv2_current_tilemap));
5554         stv_rbg_cache_data.map_offset_min[iRP-1] = stv_vdp2_layer_data_placement.map_offset_min;
5555         stv_rbg_cache_data.map_offset_max[iRP-1] = stv_vdp2_layer_data_placement.map_offset_max;
5556         stv_rbg_cache_data.tile_offset_min[iRP-1] = stv_vdp2_layer_data_placement.tile_offset_min;
5557         stv_rbg_cache_data.tile_offset_max[iRP-1] = stv_vdp2_layer_data_placement.tile_offset_max;
5558         if ( LOG_VDP2 ) logerror( "Cache watch: map = %06X - %06X, tile = %06X - %06X\n", stv_rbg_cache_data.map_offset_min[iRP-1],
5559            stv_rbg_cache_data.map_offset_max[iRP-1], stv_rbg_cache_data.tile_offset_min[iRP-1], stv_rbg_cache_data.tile_offset_max[iRP-1] );
5560      }
5561
5562      g_profiler.stop();
5563
5564      stv2_current_tilemap.colour_calculation_enabled = colour_calculation_enabled;
5565      if ( colour_calculation_enabled )
5566      {
5567         stv2_current_tilemap.transparency = STV_TRANSPARENCY_ALPHA;
5568      }
5569
5570      mycliprect = cliprect;
5571
5572      if ( window_control )
5573      {
5574         stv2_current_tilemap.window_control = window_control;
5575         stv_vdp2_apply_window_on_layer(mycliprect);
5576      }
5577
5578      stv2_current_tilemap.fade_control = fade_control;
5579
5580      g_profiler.start(PROFILER_USER2);
5581      stv_vdp2_copy_roz_bitmap(bitmap, m_vdp2.roz_bitmap[iRP-1], mycliprect, iRP, planesizex, planesizey, planerenderedsizex, planerenderedsizey );
5582      g_profiler.stop();
5583   }
5584
5585}
5586
5587void saturn_state::stv_vdp2_draw_RBG0(bitmap_rgb32 &bitmap, const rectangle &cliprect)
5588{
5589   /*
5590      Colours           : 16, 256, 2048, 32768, 16770000
5591      Char Size         : 1x1 cells, 2x2 cells
5592      Pattern Data Size : 1 word, 2 words
5593      Plane Layouts     : 1 x 1, 2 x 1, 2 x 2
5594      Planes            : 4
5595      Bitmap            : Possible
5596      Bitmap Sizes      : 512 x 256, 512 x 512, 1024 x 256, 1024 x 512
5597      Scale             : 0.25 x - 256 x
5598      Rotation          : Yes
5599      Linescroll        : Yes
5600      Column Scroll     : Yes
5601      Mosaic            : Yes
5602   */
5603
5604   stv2_current_tilemap.enabled = STV_VDP2_R0ON;
5605
5606//  if (!stv2_current_tilemap.enabled) return; // stop right now if its disabled ...
5607
5608   //stv2_current_tilemap.trans_enabled = STV_VDP2_R0TPON;
5609   if ( STV_VDP2_R0CCEN )
5610   {
5611      stv2_current_tilemap.colour_calculation_enabled = 1;
5612      stv2_current_tilemap.alpha = ((UINT16)(0x1f-STV_VDP2_R0CCRT)*0xff)/0x1f;
5613   }
5614   else
5615   {
5616      stv2_current_tilemap.colour_calculation_enabled = 0;
5617   }
5618   if ( STV_VDP2_R0TPON == 0 )
5619   {
5620      stv2_current_tilemap.transparency = STV_TRANSPARENCY_PEN;
5621   }
5622   else
5623   {
5624      stv2_current_tilemap.transparency = STV_TRANSPARENCY_NONE;
5625   }
5626   stv2_current_tilemap.colour_depth = STV_VDP2_R0CHCN;
5627   stv2_current_tilemap.tile_size = STV_VDP2_R0CHSZ;
5628   stv2_current_tilemap.bitmap_enable = STV_VDP2_R0BMEN;
5629   stv2_current_tilemap.bitmap_size = STV_VDP2_R0BMSZ;
5630   stv2_current_tilemap.bitmap_palette_number = STV_VDP2_R0BMP;
5631
5632   stv2_current_tilemap.pattern_data_size = STV_VDP2_R0PNB;
5633   stv2_current_tilemap.character_number_supplement = STV_VDP2_R0CNSM;
5634   stv2_current_tilemap.special_priority_register = STV_VDP2_R0SPR;
5635   stv2_current_tilemap.special_colour_control_register = STV_VDP2_R0SCC;
5636   stv2_current_tilemap.supplementary_palette_bits = STV_VDP2_R0SPLT;
5637   stv2_current_tilemap.supplementary_character_bits = STV_VDP2_R0SPCN;
5638
5639   stv2_current_tilemap.colour_ram_address_offset = STV_VDP2_R0CAOS;
5640   stv2_current_tilemap.fade_control = (STV_VDP2_R0COEN * 1) | (STV_VDP2_R0COSL * 2);
5641   stv_vdp2_check_fade_control_for_layer();
5642   stv2_current_tilemap.window_control = (STV_VDP2_R0LOG << 0) |
5643                                 (STV_VDP2_R0W0E << 1) |
5644                                 (STV_VDP2_R0W1E << 2) |
5645                                 (STV_VDP2_R0SWE << 3) |
5646                                 (STV_VDP2_R0W0A << 4) |
5647                                 (STV_VDP2_R0W1A << 5) |
5648                                 (STV_VDP2_R0SWA << 6);
5649
5650   stv2_current_tilemap.scrollx = 0;
5651   stv2_current_tilemap.scrolly = 0;
5652   stv2_current_tilemap.incx = 0x10000;
5653   stv2_current_tilemap.incy = 0x10000;
5654
5655   stv2_current_tilemap.linescroll_enable = 0;
5656   stv2_current_tilemap.linescroll_interval = 0;
5657   stv2_current_tilemap.linescroll_table_address = 0;
5658   stv2_current_tilemap.vertical_linescroll_enable = 0;
5659   stv2_current_tilemap.linezoom_enable = 0;
5660
5661   stv2_current_tilemap.line_screen_enabled = STV_VDP2_R0LCEN;
5662   stv2_current_tilemap.mosaic_screen_enabled = STV_VDP2_R0MZE;
5663
5664   /*Use 0x80 as a normal/rotate switch*/
5665   stv2_current_tilemap.layer_name=0x80;
5666
5667   if ( !stv2_current_tilemap.enabled ) return;
5668
5669   switch(STV_VDP2_RPMD)
5670   {
5671      case 0://Rotation Parameter A
5672         stv_vdp2_draw_rotation_screen(bitmap, cliprect, 1 );
5673         break;
5674      case 1://Rotation Parameter B
5675      //case 2:
5676         stv_vdp2_draw_rotation_screen(bitmap, cliprect, 2 );
5677         break;
5678      case 2://Rotation Parameter A & B CKTE
5679         stv_vdp2_draw_rotation_screen(bitmap, cliprect, 2 );
5680         stv_vdp2_draw_rotation_screen(bitmap, cliprect, 1 );
5681         break;
5682      case 3://Rotation Parameter A & B Window (wrong)
5683         stv_vdp2_draw_rotation_screen(bitmap, cliprect, 1 );
5684         break;
5685   }
5686
5687}
5688
5689void saturn_state::stv_vdp2_draw_back(bitmap_rgb32 &bitmap, const rectangle &cliprect)
5690{
5691   int x,y;
5692   UINT8* gfxdata = m_vdp2.gfx_decode;
5693   UINT32 base_offs,base_mask;
5694   UINT8 interlace;
5695
5696   interlace = (STV_VDP2_LSMD == 3)+1;
5697
5698//  popmessage("Back screen %08x %08x %08x",STV_VDP2_BDCLMD,STV_VDP2_BKCLMD,STV_VDP2_BKTA);
5699
5700   /* draw black if BDCLMD and DISP are cleared */
5701   if(!(STV_VDP2_BDCLMD) && !(STV_VDP2_DISP))
5702      bitmap.fill(get_black_pen(machine()), cliprect);
5703   else
5704   {
5705      base_mask = STV_VDP2_VRAMSZ ? 0x7ffff : 0x3ffff;
5706
5707      for(y=cliprect.min_y;y<=cliprect.max_y;y++)
5708      {
5709         base_offs = ((STV_VDP2_BKTA ) & base_mask) << 1;
5710         if(STV_VDP2_BKCLMD)
5711            base_offs += ((y / interlace) << 1);
5712
5713         for(x=cliprect.min_x;x<=cliprect.max_x;x++)
5714         {
5715            int r,g,b;
5716            UINT16 dot;
5717
5718            dot = (gfxdata[base_offs+0]<<8)|gfxdata[base_offs+1];
5719            b = pal5bit((dot & 0x7c00) >> 10);
5720            g = pal5bit((dot & 0x03e0) >> 5);
5721            r = pal5bit( dot & 0x001f);
5722            if(STV_VDP2_BKCOEN)
5723               stv_vdp2_compute_color_offset( &r, &g, &b, STV_VDP2_BKCOSL );
5724
5725            bitmap.pix32(y, x) = MAKE_RGB(r, g, b);
5726         }
5727      }
5728   }
5729}
5730
5731READ32_MEMBER ( saturn_state::saturn_vdp2_vram_r )
5732{
5733   return m_vdp2_vram[offset];
5734}
5735
5736WRITE32_MEMBER ( saturn_state::saturn_vdp2_vram_w )
5737{
5738   UINT8* gfxdata = m_vdp2.gfx_decode;
5739
5740   COMBINE_DATA(&m_vdp2_vram[offset]);
5741
5742   data = m_vdp2_vram[offset];
5743   /* put in gfx region for easy decoding */
5744   gfxdata[offset*4+0] = (data & 0xff000000) >> 24;
5745   gfxdata[offset*4+1] = (data & 0x00ff0000) >> 16;
5746   gfxdata[offset*4+2] = (data & 0x0000ff00) >> 8;
5747   gfxdata[offset*4+3] = (data & 0x000000ff) >> 0;
5748
5749   space.machine().gfx[0]->mark_dirty(offset/8);
5750   space.machine().gfx[1]->mark_dirty(offset/8);
5751   space.machine().gfx[2]->mark_dirty(offset/8);
5752   space.machine().gfx[3]->mark_dirty(offset/8);
5753
5754   /* 8-bit tiles overlap, so this affects the previous one as well */
5755   if (offset/8 != 0)
5756   {
5757      space.machine().gfx[2]->mark_dirty(offset/8 - 1);
5758      space.machine().gfx[3]->mark_dirty(offset/8 - 1);
5759   }
5760
5761   if ( stv_rbg_cache_data.watch_vdp2_vram_writes )
5762   {
5763      if ( stv_rbg_cache_data.watch_vdp2_vram_writes & STV_VDP2_RBG_ROTATION_PARAMETER_A )
5764      {
5765         if ( (offset >= stv_rbg_cache_data.map_offset_min[0] &&
5766               offset < stv_rbg_cache_data.map_offset_max[0]) ||
5767               (offset >= stv_rbg_cache_data.tile_offset_min[0] &&
5768               offset < stv_rbg_cache_data.tile_offset_max[0]) )
5769         {
5770            if ( LOG_VDP2 ) logerror( "RBG Cache: dirtying for RP = 1, write at offset = %06X\n", offset );
5771            stv_rbg_cache_data.is_cache_dirty |= STV_VDP2_RBG_ROTATION_PARAMETER_A;
5772            stv_rbg_cache_data.watch_vdp2_vram_writes &= ~STV_VDP2_RBG_ROTATION_PARAMETER_A;
5773         }
5774      }
5775      if ( stv_rbg_cache_data.watch_vdp2_vram_writes & STV_VDP2_RBG_ROTATION_PARAMETER_B )
5776      {
5777         if ( (offset >= stv_rbg_cache_data.map_offset_min[1] &&
5778               offset < stv_rbg_cache_data.map_offset_max[1]) ||
5779               (offset >= stv_rbg_cache_data.tile_offset_min[1] &&
5780               offset < stv_rbg_cache_data.tile_offset_max[1]) )
5781         {
5782            if ( LOG_VDP2 ) logerror( "RBG Cache: dirtying for RP = 2, write at offset = %06X\n", offset );
5783            stv_rbg_cache_data.is_cache_dirty |= STV_VDP2_RBG_ROTATION_PARAMETER_B;
5784            stv_rbg_cache_data.watch_vdp2_vram_writes &= ~STV_VDP2_RBG_ROTATION_PARAMETER_B;
5785         }
5786      }
5787
5788   }
5789
5790}
5791
5792READ16_MEMBER ( saturn_state::saturn_vdp2_regs_r )
5793{
5794   switch(offset)
5795   {
5796      case 0x002/2:
5797      {
5798         /* latch h/v signals through HV latch*/
5799         if(!STV_VDP2_EXLTEN)
5800         {
5801            /* TODO: handle various h/v settings. */
5802            if(!space.debugger_access())
5803            {
5804               m_vdp2.h_count = space.machine().primary_screen->hpos() & 0x3ff;
5805               m_vdp2.v_count = space.machine().primary_screen->vpos() & (STV_VDP2_LSMD == 3 ? 0x7ff : 0x3ff);
5806               /* latch flag */
5807               m_vdp2.exltfg |= 1;
5808            }
5809         }
5810
5811         break;
5812      }
5813      case 0x004/2:
5814      {
5815         /*Screen Status Register*/
5816                              /*VBLANK              HBLANK            ODD               PAL    */
5817         m_vdp2_regs[offset] = (m_vdp2.exltfg<<9) |
5818                                 (m_vdp2.exsyfg<<8) |
5819                                 (get_vblank() << 3) |
5820                                 (get_hblank() << 2) |
5821                                 (get_odd_bit() << 1) |
5822                                 (m_vdp2.pal << 0);
5823
5824         /* vblank bit is always 1 if DISP bit is disabled */
5825         if(!STV_VDP2_DISP)
5826            m_vdp2_regs[offset] |= 1 << 3;
5827
5828         /* HV latches clears if this register is read */
5829         if(!space.debugger_access())
5830         {
5831            m_vdp2.exltfg &= ~1;
5832            m_vdp2.exsyfg &= ~1;
5833         }
5834         break;
5835      }
5836      case 0x006/2:
5837      {
5838         m_vdp2_regs[offset] = (STV_VDP2_VRAMSZ << 15) |
5839                                 ((0 << 0) & 0xf); // VDP2 version
5840
5841         if(!space.debugger_access())
5842            printf("Warning: VDP2 version read\n");
5843         break;
5844      }
5845
5846      /* HCNT */
5847      case 0x008/2:
5848      {
5849         m_vdp2_regs[offset] = (m_vdp2.h_count);
5850         break;
5851      }
5852
5853      /* VCNT */
5854      case 0x00a/2:
5855      {
5856         m_vdp2_regs[offset] = (m_vdp2.v_count);
5857         break;
5858      }
5859
5860      default:
5861         //if(!space.debugger_access())
5862         //  printf("VDP2: read from register %08x %08x\n",offset*4,mem_mask);
5863         break;
5864   }
5865
5866   return m_vdp2_regs[offset];
5867}
5868
5869READ32_MEMBER ( saturn_state::saturn_vdp2_cram_r )
5870{
5871   offset &= (0xfff) >> (2);
5872   return m_vdp2_cram[offset];
5873}
5874
5875
5876
5877
5878WRITE32_MEMBER ( saturn_state::saturn_vdp2_cram_w )
5879{
5880   int r,g,b;
5881   UINT8 cmode0;
5882
5883   cmode0 = (STV_VDP2_CRMD & 3) == 0;
5884
5885   offset &= (0xfff) >> (2);
5886   COMBINE_DATA(&m_vdp2_cram[offset]);
5887
5888   switch( STV_VDP2_CRMD )
5889   {
5890      /*Mode 2/3*/
5891      case 2:
5892      case 3:
5893      {
5894         //offset &= (0xfff) >> 2;
5895
5896         b = ((m_vdp2_cram[offset] & 0x00ff0000) >> 16);
5897         g = ((m_vdp2_cram[offset] & 0x0000ff00) >> 8);
5898         r = ((m_vdp2_cram[offset] & 0x000000ff) >> 0);
5899         palette_set_color(space.machine(),offset,MAKE_RGB(r,g,b));
5900         palette_set_color(space.machine(),offset^0x400,MAKE_RGB(r,g,b));
5901      }
5902      break;
5903      /*Mode 0*/
5904      case 0:
5905      case 1:
5906      {
5907         offset &= (0xfff) >> (cmode0+2);
5908
5909         b = ((m_vdp2_cram[offset] & 0x00007c00) >> 10);
5910         g = ((m_vdp2_cram[offset] & 0x000003e0) >> 5);
5911         r = ((m_vdp2_cram[offset] & 0x0000001f) >> 0);
5912         palette_set_color_rgb(space.machine(),(offset*2)+1,pal5bit(r),pal5bit(g),pal5bit(b));
5913         if(cmode0)
5914            palette_set_color_rgb(space.machine(),((offset*2)+1)^0x400,pal5bit(r),pal5bit(g),pal5bit(b));
5915
5916         b = ((m_vdp2_cram[offset] & 0x7c000000) >> 26);
5917         g = ((m_vdp2_cram[offset] & 0x03e00000) >> 21);
5918         r = ((m_vdp2_cram[offset] & 0x001f0000) >> 16);
5919         palette_set_color_rgb(space.machine(),offset*2,pal5bit(r),pal5bit(g),pal5bit(b));
5920         if(cmode0)
5921            palette_set_color_rgb(space.machine(),(offset*2)^0x400,pal5bit(r),pal5bit(g),pal5bit(b));
5922      }
5923      break;
5924   }
5925}
5926
5927void saturn_state::refresh_palette_data( void )
5928{
5929   int r,g,b;
5930   int c_i;
5931   UINT8 bank;
5932
5933   switch( STV_VDP2_CRMD )
5934   {
5935      case 2:
5936      case 3:
5937      {
5938         for(c_i=0;c_i<0x400;c_i++)
5939         {
5940            b = ((m_vdp2_cram[c_i] & 0x00ff0000) >> 16);
5941            g = ((m_vdp2_cram[c_i] & 0x0000ff00) >> 8);
5942            r = ((m_vdp2_cram[c_i] & 0x000000ff) >> 0);
5943            palette_set_color(machine(),c_i,MAKE_RGB(r,g,b));
5944            palette_set_color(machine(),c_i+0x400,MAKE_RGB(r,g,b));
5945         }
5946      }
5947      break;
5948      case 0:
5949      {
5950         for(bank=0;bank<2;bank++)
5951         {
5952            for(c_i=0;c_i<0x400;c_i++)
5953            {
5954               b = ((m_vdp2_cram[c_i] & 0x00007c00) >> 10);
5955               g = ((m_vdp2_cram[c_i] & 0x000003e0) >> 5);
5956               r = ((m_vdp2_cram[c_i] & 0x0000001f) >> 0);
5957               palette_set_color_rgb(machine(),(c_i*2)+1+bank*0x400,pal5bit(r),pal5bit(g),pal5bit(b));
5958               b = ((m_vdp2_cram[c_i] & 0x7c000000) >> 26);
5959               g = ((m_vdp2_cram[c_i] & 0x03e00000) >> 21);
5960               r = ((m_vdp2_cram[c_i] & 0x001f0000) >> 16);
5961               palette_set_color_rgb(machine(),c_i*2+bank*0x400,pal5bit(r),pal5bit(g),pal5bit(b));
5962            }
5963         }
5964      }
5965      break;
5966      case 1:
5967      {
5968         for(c_i=0;c_i<0x800;c_i++)
5969         {
5970            b = ((m_vdp2_cram[c_i] & 0x00007c00) >> 10);
5971            g = ((m_vdp2_cram[c_i] & 0x000003e0) >> 5);
5972            r = ((m_vdp2_cram[c_i] & 0x0000001f) >> 0);
5973            palette_set_color_rgb(machine(),(c_i*2)+1,pal5bit(r),pal5bit(g),pal5bit(b));
5974            b = ((m_vdp2_cram[c_i] & 0x7c000000) >> 26);
5975            g = ((m_vdp2_cram[c_i] & 0x03e00000) >> 21);
5976            r = ((m_vdp2_cram[c_i] & 0x001f0000) >> 16);
5977            palette_set_color_rgb(machine(),c_i*2,pal5bit(r),pal5bit(g),pal5bit(b));
5978         }
5979      }
5980      break;
5981   }
5982}
5983
5984WRITE16_MEMBER ( saturn_state::saturn_vdp2_regs_w )
5985{
5986   COMBINE_DATA(&m_vdp2_regs[offset]);
5987
5988   if(m_vdp2.old_crmd != STV_VDP2_CRMD)
5989   {
5990      m_vdp2.old_crmd = STV_VDP2_CRMD;
5991      refresh_palette_data();
5992   }
5993   if(m_vdp2.old_tvmd != STV_VDP2_TVMD)
5994   {
5995      m_vdp2.old_tvmd = STV_VDP2_TVMD;
5996      stv_vdp2_dynamic_res_change();
5997   }
5998
5999   if(STV_VDP2_VRAMSZ)
6000      printf("VDP2 sets up 8 Mbit VRAM!\n");
6001}
6002
6003int saturn_state::get_hblank_duration( void )
6004{
6005   int res;
6006
6007   res = (STV_VDP2_HRES & 1) ? 455 : 427;
6008
6009   /* double pump horizontal max res */
6010   if(STV_VDP2_HRES & 2)
6011      res<<=1;
6012
6013   return res;
6014}
6015
6016/*some vblank lines measurements (according to Charles MacDonald)*/
6017/* TODO: interlace mode "eats" one line, should be 262.5 */
6018int saturn_state::get_vblank_duration( void )
6019{
6020   int res;
6021
6022   res = (m_vdp2.pal) ? 313 : 263;
6023
6024   /* compensate for interlacing */
6025   if((STV_VDP2_LSMD & 3) == 3)
6026      res<<=1;
6027
6028   if(STV_VDP2_HRES & 4)
6029      res = (STV_VDP2_HRES & 1) ? 561 : 525;  //Hi-Vision / 31kHz Monitor
6030
6031   return res;
6032}
6033
6034int saturn_state::get_pixel_clock( void )
6035{
6036   int res,divider;
6037
6038   res = m_vdp2.dotsel ? MASTER_CLOCK_352 : MASTER_CLOCK_320;
6039   /* TODO: divider is ALWAYS 8, this thing is just to over-compensate for MAME framework faults ... */
6040   divider = 8;
6041
6042   if(STV_VDP2_HRES & 2)
6043      divider>>=1;
6044
6045   if((STV_VDP2_LSMD & 3) == 3)
6046      divider>>=1;
6047
6048   if(STV_VDP2_HRES & 4) //TODO
6049      divider>>=1;
6050
6051   return res/divider;
6052}
6053
6054UINT8 saturn_state::get_hblank( void )
6055{
6056   const rectangle &visarea = machine().primary_screen->visible_area();
6057   int cur_h = machine().primary_screen->hpos();
6058
6059   if (cur_h > visarea.max_x) //TODO
6060      return 1;
6061
6062   return 0;
6063}
6064
6065UINT8 saturn_state::get_vblank( void )
6066{
6067   int cur_v,vblank;
6068   cur_v = machine().primary_screen->vpos();
6069
6070   vblank = (m_vdp2.pal) ? 288 : 240;
6071
6072   if((STV_VDP2_LSMD & 3) == 3)
6073      vblank<<=1;
6074
6075   if (cur_v >= vblank)
6076      return 1;
6077
6078   return 0;
6079}
6080
6081UINT8 saturn_state::get_odd_bit( void )
6082{
6083   int cur_v;
6084   cur_v = machine().primary_screen->vpos();
6085
6086   if(STV_VDP2_HRES & 4) //exclusive monitor mode makes this bit to be always 1
6087      return 1;
6088
6089   if(STV_VDP2_LSMD == 0) // same for non-interlace mode
6090      return 1;
6091
6092   if(cur_v % 2)
6093      return 1;
6094
6095   return 0;
6096}
6097
6098void saturn_state::stv_vdp2_state_save_postload( void )
6099{
6100   UINT8 *gfxdata = m_vdp2.gfx_decode;
6101   int offset;
6102   UINT32 data;
6103
6104   for ( offset = 0; offset < 0x100000/4; offset++ )
6105   {
6106      data = m_vdp2_vram[offset];
6107      /* put in gfx region for easy decoding */
6108      gfxdata[offset*4+0] = (data & 0xff000000) >> 24;
6109      gfxdata[offset*4+1] = (data & 0x00ff0000) >> 16;
6110      gfxdata[offset*4+2] = (data & 0x0000ff00) >> 8;
6111      gfxdata[offset*4+3] = (data & 0x000000ff) >> 0;
6112
6113      machine().gfx[0]->mark_dirty(offset/8);
6114      machine().gfx[1]->mark_dirty(offset/8);
6115      machine().gfx[2]->mark_dirty(offset/8);
6116      machine().gfx[3]->mark_dirty(offset/8);
6117
6118      /* 8-bit tiles overlap, so this affects the previous one as well */
6119      if (offset/8 != 0)
6120      {
6121         machine().gfx[2]->mark_dirty(offset/8 - 1);
6122         machine().gfx[3]->mark_dirty(offset/8 - 1);
6123      }
6124
6125   }
6126
6127   memset( &stv_rbg_cache_data, 0, sizeof(stv_rbg_cache_data));
6128   stv_rbg_cache_data.is_cache_dirty = 3;
6129   memset( &stv_vdp2_layer_data_placement, 0, sizeof(stv_vdp2_layer_data_placement));
6130
6131   refresh_palette_data();
6132}
6133
6134void saturn_state::stv_vdp2_exit ( void )
6135{
6136   m_vdp2.roz_bitmap[0].reset();
6137   m_vdp2.roz_bitmap[1].reset();
6138}
6139
6140int saturn_state::stv_vdp2_start ( void )
6141{
6142   machine().add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(saturn_state::stv_vdp2_exit), this));
6143
6144   m_vdp2_regs = auto_alloc_array_clear(machine(), UINT16, 0x040000/2 );
6145   m_vdp2_vram = auto_alloc_array_clear(machine(), UINT32, 0x100000/4 );
6146   m_vdp2_cram = auto_alloc_array_clear(machine(), UINT32, 0x080000/4 );
6147   m_vdp2.gfx_decode = auto_alloc_array(machine(), UINT8, 0x100000 );
6148
6149//  machine().gfx[0]->granularity()=4;
6150//  machine().gfx[1]->granularity()=4;
6151
6152   memset( &stv_rbg_cache_data, 0, sizeof(stv_rbg_cache_data));
6153   stv_rbg_cache_data.is_cache_dirty = 3;
6154   memset( &stv_vdp2_layer_data_placement, 0, sizeof(stv_vdp2_layer_data_placement));
6155
6156   state_save_register_global_pointer(machine(), m_vdp2_regs, 0x040000/2);
6157   state_save_register_global_pointer(machine(), m_vdp2_vram, 0x100000/4);
6158   state_save_register_global_pointer(machine(), m_vdp2_cram, 0x080000/4);
6159   machine().save().register_postload(save_prepost_delegate(FUNC(saturn_state::stv_vdp2_state_save_postload), this));
6160
6161   return 0;
6162}
6163
6164/* maybe we should move this to video/stv.c */
6165VIDEO_START_MEMBER(saturn_state,stv_vdp2)
6166{
6167   machine().primary_screen->register_screen_bitmap(m_tmpbitmap);
6168   stv_vdp2_start();
6169   stv_vdp1_start();
6170   m_vdpdebug_roz = 0;
6171   machine().gfx[0]->set_source(m_vdp2.gfx_decode);
6172   machine().gfx[1]->set_source(m_vdp2.gfx_decode);
6173   machine().gfx[2]->set_source(m_vdp2.gfx_decode);
6174   machine().gfx[3]->set_source(m_vdp2.gfx_decode);
6175}
6176
6177void saturn_state::stv_vdp2_dynamic_res_change( void )
6178{
6179   const int d_vres[4] = { 224, 240, 256, 256 };
6180   const int d_hres[4] = { 320, 352, 640, 704 };
6181   int horz_res,vert_res;
6182   int vres_mask;
6183
6184   vres_mask = (m_vdp2.pal << 1)|1; //PAL uses mask 3, NTSC uses mask 1
6185   vert_res = d_vres[STV_VDP2_VRES & vres_mask];
6186
6187   if((STV_VDP2_VRES & 3) == 3)
6188      popmessage("Illegal VRES MODE, contact MAMEdev");
6189
6190   /*Double-density interlace mode,doubles the vertical res*/
6191   if((STV_VDP2_LSMD & 3) == 3) { vert_res*=2;  }
6192
6193   horz_res = d_hres[STV_VDP2_HRES & 3];
6194   /*Exclusive modes,they sets the Vertical Resolution without considering the
6195     VRES register.*/
6196   if(STV_VDP2_HRES & 4)
6197      vert_res = 480;
6198
6199   {
6200      int vblank_period,hblank_period;
6201      attoseconds_t refresh;;
6202      rectangle visarea(0, horz_res-1, 0, vert_res-1);
6203
6204      vblank_period = get_vblank_duration();
6205      hblank_period = get_hblank_duration();
6206      refresh  = HZ_TO_ATTOSECONDS(get_pixel_clock()) * (hblank_period) * vblank_period;
6207      //printf("%d %d %d %d\n",horz_res,vert_res,horz_res+hblank_period,vblank_period);
6208
6209      machine().primary_screen->configure((hblank_period), (vblank_period), visarea, refresh );
6210   }
6211//  machine().primary_screen->set_visible_area(0*8, horz_res-1,0*8, vert_res-1);
6212}
6213
6214/*This is for calculating the rgb brightness*/
6215/*TODO: Optimize this...*/
6216void saturn_state::stv_vdp2_fade_effects( void )
6217{
6218   /*
6219   Note:We have to use temporary storages because palette_get_color must use
6220   variables setted with unsigned int8
6221   */
6222   INT16 t_r,t_g,t_b;
6223   UINT8 r,g,b;
6224   rgb_t color;
6225   int i;
6226   //popmessage("%04x %04x",STV_VDP2_CLOFEN,STV_VDP2_CLOFSL);
6227   for(i=0;i<2048;i++)
6228   {
6229      /*Fade A*/
6230      color = palette_get_color(machine(), i);
6231      t_r = (STV_VDP2_COAR & 0x100) ? (RGB_RED(color) - (0x100 - (STV_VDP2_COAR & 0xff))) : ((STV_VDP2_COAR & 0xff) + RGB_RED(color));
6232      t_g = (STV_VDP2_COAG & 0x100) ? (RGB_GREEN(color) - (0x100 - (STV_VDP2_COAG & 0xff))) : ((STV_VDP2_COAG & 0xff) + RGB_GREEN(color));
6233      t_b = (STV_VDP2_COAB & 0x100) ? (RGB_BLUE(color) - (0x100 - (STV_VDP2_COAB & 0xff))) : ((STV_VDP2_COAB & 0xff) + RGB_BLUE(color));
6234      if(t_r < 0)     { t_r = 0; }
6235      if(t_r > 0xff)  { t_r = 0xff; }
6236      if(t_g < 0)     { t_g = 0; }
6237      if(t_g > 0xff)  { t_g = 0xff; }
6238      if(t_b < 0)     { t_b = 0; }
6239      if(t_b > 0xff)  { t_b = 0xff; }
6240      r = t_r;
6241      g = t_g;
6242      b = t_b;
6243      palette_set_color(machine(),i+(2048*1),MAKE_RGB(r,g,b));
6244
6245      /*Fade B*/
6246      color = palette_get_color(machine(), i);
6247      t_r = (STV_VDP2_COBR & 0x100) ? (RGB_RED(color) - (0xff - (STV_VDP2_COBR & 0xff))) : ((STV_VDP2_COBR & 0xff) + RGB_RED(color));
6248      t_g = (STV_VDP2_COBG & 0x100) ? (RGB_GREEN(color) - (0xff - (STV_VDP2_COBG & 0xff))) : ((STV_VDP2_COBG & 0xff) + RGB_GREEN(color));
6249      t_b = (STV_VDP2_COBB & 0x100) ? (RGB_BLUE(color) - (0xff - (STV_VDP2_COBB & 0xff))) : ((STV_VDP2_COBB & 0xff) + RGB_BLUE(color));
6250      if(t_r < 0)     { t_r = 0; }
6251      if(t_r > 0xff)  { t_r = 0xff; }
6252      if(t_g < 0)     { t_g = 0; }
6253      if(t_g > 0xff)  { t_g = 0xff; }
6254      if(t_b < 0)     { t_b = 0; }
6255      if(t_b > 0xff)  { t_b = 0xff; }
6256      r = t_r;
6257      g = t_g;
6258      b = t_b;
6259      palette_set_color(machine(),i+(2048*2),MAKE_RGB(r,g,b));
6260   }
6261   //popmessage("%04x %04x %04x %04x %04x %04x",STV_VDP2_COAR,STV_VDP2_COAG,STV_VDP2_COAB,STV_VDP2_COBR,STV_VDP2_COBG,STV_VDP2_COBB);
6262}
6263
6264/******************************************************************************************
6265
6266ST-V VDP2 window effect function version 0.04
6267
6268How it works: returns 0 if the requested pixel is drawnable,1 if it isn't.
6269For tilemap and sprite layer, clipping rectangle is changed.
6270
6271Done:
6272-Basic support(w0 or w1),bitmaps only.
6273-W0 (outside) for tilemaps and sprite layer.
6274-Window logic.
6275
6276Not Done:
6277-Complete Windows on cells.A split between cells and bitmaps is in progress...
6278-w0 & w1 at the same time.
6279-Line window.
6280-Color Calculation.
6281-Rotation parameter Window (already done?).
6282
6283Window Registers are hooked up like this ATM:
6284    x--- ---- UNUSED
6285    -x-- ---- Sprite Window Area
6286    --x- ---- Window 1 Area
6287    ---x ---- Window 0 Area
6288                  (0 = Inside,1 = Outside)
6289    ---- x--- Sprite Window Enable
6290    ---- -x-- Window 1 Enable
6291    ---- --x- Window 0 Enable
6292                  (0 = Disabled,1 = Enabled)
6293    ---- ---x Window Logic
6294                  (0 = OR,1 = AND)
6295******************************************************************************************/
6296
6297void saturn_state::stv_vdp2_get_window0_coordinates(UINT16 *s_x, UINT16 *e_x, UINT16 *s_y, UINT16 *e_y)
6298{
6299   /*W0*/
6300   switch(STV_VDP2_LSMD & 3)
6301   {
6302      case 0:
6303      case 1:
6304      case 2:
6305         *s_y = ((STV_VDP2_W0SY & 0x3ff) >> 0);
6306         *e_y = ((STV_VDP2_W0EY & 0x3ff) >> 0);
6307         break;
6308      case 3:
6309         *s_y = ((STV_VDP2_W0SY & 0x7ff) >> 0);
6310         *e_y = ((STV_VDP2_W0EY & 0x7ff) >> 0);
6311         break;
6312   }
6313   switch(STV_VDP2_HRES & 6)
6314   {
6315      /*Normal*/
6316      case 0:
6317         *s_x = ((STV_VDP2_W0SX & 0x3fe) >> 1);
6318         *e_x = ((STV_VDP2_W0EX & 0x3fe) >> 1);
6319         break;
6320      /*Hi-Res*/
6321      case 2:
6322         *s_x = ((STV_VDP2_W0SX & 0x3ff) >> 0);
6323         *e_x = ((STV_VDP2_W0EX & 0x3ff) >> 0);
6324         break;
6325      /*Exclusive Normal*/
6326      case 4:
6327         *s_x = ((STV_VDP2_W0SX & 0x1ff) >> 0);
6328         *e_x = ((STV_VDP2_W0EX & 0x1ff) >> 0);
6329         *s_y = ((STV_VDP2_W0SY & 0x3ff) >> 0);
6330         *e_y = ((STV_VDP2_W0EY & 0x3ff) >> 0);
6331         break;
6332      /*Exclusive Hi-Res*/
6333      case 6:
6334         *s_x = ((STV_VDP2_W0SX & 0x1ff) << 1);
6335         *e_x = ((STV_VDP2_W0EX & 0x1ff) << 1);
6336         *s_y = ((STV_VDP2_W0SY & 0x3ff) >> 0);
6337         *e_y = ((STV_VDP2_W0EY & 0x3ff) >> 0);
6338         break;
6339   }
6340}
6341
6342void saturn_state::stv_vdp2_get_window1_coordinates(UINT16 *s_x, UINT16 *e_x, UINT16 *s_y, UINT16 *e_y)
6343{
6344   /*W1*/
6345   switch(STV_VDP2_LSMD & 3)
6346   {
6347      case 0:
6348      case 1:
6349      case 2:
6350         *s_y = ((STV_VDP2_W1SY & 0x3ff) >> 0);
6351         *e_y = ((STV_VDP2_W1EY & 0x3ff) >> 0);
6352         break;
6353      case 3:
6354         *s_y = ((STV_VDP2_W1SY & 0x7ff) >> 0);
6355         *e_y = ((STV_VDP2_W1EY & 0x7ff) >> 0);
6356         break;
6357   }
6358   switch(STV_VDP2_HRES & 6)
6359   {
6360      /*Normal*/
6361      case 0:
6362         *s_x = ((STV_VDP2_W1SX & 0x3fe) >> 1);
6363         *e_x = ((STV_VDP2_W1EX & 0x3fe) >> 1);
6364         break;
6365      /*Hi-Res*/
6366      case 2:
6367         *s_x = ((STV_VDP2_W1SX & 0x3ff) >> 0);
6368         *e_x = ((STV_VDP2_W1EX & 0x3ff) >> 0);
6369         break;
6370      /*Exclusive Normal*/
6371      case 4:
6372         *s_x = ((STV_VDP2_W1SX & 0x1ff) >> 0);
6373         *e_x = ((STV_VDP2_W1EX & 0x1ff) >> 0);
6374         *s_y = ((STV_VDP2_W1SY & 0x3ff) >> 0);
6375         *e_y = ((STV_VDP2_W1EY & 0x3ff) >> 0);
6376         break;
6377      /*Exclusive Hi-Res*/
6378      case 6:
6379         *s_x = ((STV_VDP2_W1SX & 0x1ff) << 1);
6380         *e_x = ((STV_VDP2_W1EX & 0x1ff) << 1);
6381         *s_y = ((STV_VDP2_W1SY & 0x3ff) >> 0);
6382         *e_y = ((STV_VDP2_W1EY & 0x3ff) >> 0);
6383         break;
6384   }
6385
6386}
6387
6388int saturn_state::get_window_pixel(UINT16 s_x,UINT16 e_x,UINT16 s_y,UINT16 e_y,int x, int y,UINT8 win_num)
6389{
6390   if(stv2_current_tilemap.window_control & (2 << win_num))
6391   {
6392      /*Outside Area*/
6393      if(stv2_current_tilemap.window_control & (0x10 << win_num))
6394      {
6395         if(y < s_y || y > e_y)
6396            return 1;
6397         else
6398         {
6399            if(x < s_x || x > e_x)
6400               return 1;
6401            //else
6402            //  return 0;
6403         }
6404      }
6405      /*Inside Area*/
6406      else
6407      {
6408         if(y > s_y && y < e_y)
6409         {
6410            if(x > s_x && x < e_x)
6411               return 1;
6412         }
6413         //else
6414         //  return 0;
6415      }
6416   }
6417
6418   return 0;
6419}
6420
6421int saturn_state::stv_vdp2_window_process(int x,int y)
6422{
6423   UINT16 s_x=0,e_x=0,s_y=0,e_y=0;
6424   UINT8 w0_pix, w1_pix;
6425
6426   if ((stv2_current_tilemap.window_control & 6) == 0)
6427      return 0;
6428
6429   stv_vdp2_get_window0_coordinates(&s_x, &e_x, &s_y, &e_y);
6430   w0_pix = get_window_pixel(s_x,e_x,s_y,e_y,x,y,0);
6431
6432   stv_vdp2_get_window1_coordinates(&s_x, &e_x, &s_y, &e_y);
6433   w1_pix = get_window_pixel(s_x,e_x,s_y,e_y,x,y,1);
6434
6435   return stv2_current_tilemap.window_control & 1 ? (w0_pix & w1_pix) : (w0_pix | w1_pix);
6436}
6437
6438int saturn_state::stv_vdp2_apply_window_on_layer(rectangle &cliprect)
6439{
6440   UINT16 s_x=0,e_x=0,s_y=0,e_y=0;
6441
6442   if ( stv2_current_tilemap.window_control == 0x12 )
6443   {
6444      /* w0, transparent outside supported */
6445      stv_vdp2_get_window0_coordinates(&s_x, &e_x, &s_y, &e_y);
6446
6447      if ( s_x > cliprect.min_x ) cliprect.min_x = s_x;
6448      if ( e_x < cliprect.max_x ) cliprect.max_x = e_x;
6449      if ( s_y > cliprect.min_y ) cliprect.min_y = s_y;
6450      if ( e_y < cliprect.max_y ) cliprect.max_y = e_y;
6451
6452      return 1;
6453   }
6454   else if ( stv2_current_tilemap.window_control == 0x24 )
6455   {
6456      /* w1, transparent outside supported */
6457      stv_vdp2_get_window1_coordinates(&s_x, &e_x, &s_y, &e_y);
6458
6459      if ( s_x > cliprect.min_x ) cliprect.min_x = s_x;
6460      if ( e_x < cliprect.max_x ) cliprect.max_x = e_x;
6461      if ( s_y > cliprect.min_y ) cliprect.min_y = s_y;
6462      if ( e_y < cliprect.max_y ) cliprect.max_y = e_y;
6463
6464      return 1;
6465   }
6466   else
6467   {
6468      return 0;
6469   }
6470}
6471
6472void saturn_state::draw_sprites(bitmap_rgb32 &bitmap, const rectangle &cliprect, UINT8 pri)
6473{
6474   int x,y,r,g,b;
6475   int i;
6476   UINT16 pix;
6477   UINT16 *framebuffer_line;
6478   UINT32 *bitmap_line, *bitmap_line2 = NULL;
6479   UINT8  interlace_framebuffer;
6480   UINT8  double_x;
6481   static const UINT16 sprite_colormask_table[] = {
6482      0x07ff, 0x07ff, 0x07ff, 0x07ff, 0x03ff, 0x07ff, 0x03ff, 0x01ff,
6483      0x007f, 0x003f, 0x003f, 0x003f, 0x00ff, 0x00ff, 0x00ff, 0x00ff
6484   };
6485   static const UINT16 priority_shift_table[] = { 14, 13, 14, 13, 13, 12, 12, 12, 7, 7, 6, 0, 7, 7, 6, 0 };
6486   static const UINT16 priority_mask_table[]  = {  3,  7,  1,  3,  3,  7,  7,  7, 1, 1, 3, 0, 1, 1, 3, 0 };
6487   static const UINT16 ccrr_shift_table[] =     { 11, 11, 11, 11, 10, 11, 10,  9, 0, 6, 0, 6, 0, 6, 0, 6 };
6488   static const UINT16 ccrr_mask_table[] =      {  7,  3,  7,  3,  7,  1,  3,  7, 0, 1, 0, 3, 0, 1, 0, 3 };
6489   static const UINT16 shadow_mask_table[] = { 0, 0, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0, 0, 0, 0, 0, 0, 0, 0 };
6490   UINT16 alpha_enabled;
6491
6492   int sprite_type;
6493   int sprite_colormask;
6494   int color_offset_pal;
6495   int sprite_shadow;
6496   UINT16 sprite_priority_shift, sprite_priority_mask, sprite_ccrr_shift, sprite_ccrr_mask;
6497   UINT8   priority;
6498   UINT8   ccr = 0;
6499   UINT8 sprite_priorities[8];
6500   UINT8 sprite_ccr[8];
6501   int sprite_color_mode = STV_VDP2_SPCLMD;
6502   rectangle mycliprect;
6503
6504   if ( (stv_sprite_priorities_usage_valid == 1) && (stv_sprite_priorities_used[pri] == 0) )
6505      return;
6506
6507   sprite_priorities[0] = STV_VDP2_S0PRIN;
6508   sprite_priorities[1] = STV_VDP2_S1PRIN;
6509   sprite_priorities[2] = STV_VDP2_S2PRIN;
6510   sprite_priorities[3] = STV_VDP2_S3PRIN;
6511   sprite_priorities[4] = STV_VDP2_S4PRIN;
6512   sprite_priorities[5] = STV_VDP2_S5PRIN;
6513   sprite_priorities[6] = STV_VDP2_S6PRIN;
6514   sprite_priorities[7] = STV_VDP2_S7PRIN;
6515
6516   sprite_ccr[0] = STV_VDP2_S0CCRT;
6517   sprite_ccr[1] = STV_VDP2_S1CCRT;
6518   sprite_ccr[2] = STV_VDP2_S2CCRT;
6519   sprite_ccr[3] = STV_VDP2_S3CCRT;
6520   sprite_ccr[4] = STV_VDP2_S4CCRT;
6521   sprite_ccr[5] = STV_VDP2_S5CCRT;
6522   sprite_ccr[6] = STV_VDP2_S6CCRT;
6523   sprite_ccr[7] = STV_VDP2_S7CCRT;
6524
6525   sprite_type = STV_VDP2_SPTYPE;
6526   sprite_colormask = sprite_colormask_table[sprite_type];
6527   sprite_priority_shift = priority_shift_table[sprite_type];
6528   sprite_priority_mask = priority_mask_table[sprite_type];
6529   sprite_ccrr_shift = ccrr_shift_table[sprite_type];
6530   sprite_ccrr_mask = ccrr_mask_table[sprite_type];
6531   sprite_shadow = shadow_mask_table[sprite_type];
6532
6533   for ( i = 0; i < (sprite_priority_mask+1); i++ ) if ( sprite_priorities[i] == pri ) break;
6534   if ( i == (sprite_priority_mask+1) ) return;
6535
6536   /* color offset (RGB brightness) */
6537   color_offset_pal = 0;
6538   if ( STV_VDP2_SPCOEN )
6539   {
6540      if ( STV_VDP2_SPCOSL == 0 )
6541      { color_offset_pal = 2048; }
6542      else
6543      { color_offset_pal = 2048*2; }
6544   }
6545
6546   /* color calculation (alpha blending)*/
6547   if ( STV_VDP2_SPCCEN )
6548   {
6549      alpha_enabled = 0;
6550      switch( STV_VDP2_SPCCCS )
6551      {
6552         case 0x0: if ( pri <= STV_VDP2_SPCCN ) alpha_enabled = 1; break;
6553         case 0x1: if ( pri == STV_VDP2_SPCCN ) alpha_enabled = 1; break;
6554         case 0x2: if ( pri >= STV_VDP2_SPCCN ) alpha_enabled = 1; break;
6555         case 0x3: alpha_enabled = 2; sprite_shadow = 0; break;
6556      }
6557   }
6558   else
6559   {
6560      alpha_enabled = 0;
6561   }
6562
6563   /* framebuffer interlace */
6564   if ( (STV_VDP2_LSMD == 3) && m_vdp1.framebuffer_double_interlace == 0 )
6565      interlace_framebuffer = 1;
6566   else
6567      interlace_framebuffer = 0;
6568
6569   /*Guess:Some games needs that the horizontal sprite size to be doubled
6570     (TODO: understand the proper settings,it might not work like this)*/
6571   if(STV_VDP1_TVM == 0 && STV_VDP2_HRES & 2) // astrass & findlove
6572      double_x = 1;
6573   else
6574      double_x = 0;
6575
6576   /* window control */
6577   stv2_current_tilemap.window_control = (STV_VDP2_SPLOG * 0x01) |
6578                                 (STV_VDP2_SPW0E * 0x02) |
6579                                 (STV_VDP2_SPW1E * 0x04) |
6580                                 (STV_VDP2_SPSWE * 0x08) |
6581                                 (STV_VDP2_SPW0A * 0x10) |
6582                                 (STV_VDP2_SPW1A * 0x20) |
6583                                 (STV_VDP2_SPSWA * 0x40);
6584   mycliprect = cliprect;
6585
6586   stv_vdp2_apply_window_on_layer(mycliprect);
6587
6588   if (interlace_framebuffer == 0 && double_x == 0 )
6589   {
6590      if ( alpha_enabled == 0 )
6591      {
6592         for ( y = mycliprect.min_y; y <= mycliprect.max_y; y++ )
6593         {
6594            if ( stv_sprite_priorities_usage_valid )
6595               if (stv_sprite_priorities_in_fb_line[y][pri] == 0)
6596                  continue;
6597
6598            framebuffer_line = m_vdp1.framebuffer_display_lines[y];
6599            bitmap_line = &bitmap.pix32(y);
6600
6601            for ( x = mycliprect.min_x; x <= mycliprect.max_x; x++ )
6602            {
6603               pix = framebuffer_line[x];
6604               if ( (pix & 0x8000) && sprite_color_mode)
6605               {
6606                  if ( sprite_priorities[0] != pri )
6607                  {
6608                     stv_sprite_priorities_used[sprite_priorities[0]] = 1;
6609                     stv_sprite_priorities_in_fb_line[y][sprite_priorities[0]] = 1;
6610                     continue;
6611                  };
6612
6613                  if(STV_VDP2_SPWINEN && pix == 0x8000) /* Pukunpa */
6614                     continue;
6615
6616                  b = pal5bit((pix & 0x7c00) >> 10);
6617                  g = pal5bit((pix & 0x03e0) >> 5);
6618                  r = pal5bit( pix & 0x001f);
6619                  if ( color_offset_pal )
6620                  {
6621                     stv_vdp2_compute_color_offset( &r, &g, &b, STV_VDP2_SPCOSL );
6622                  }
6623
6624                  bitmap_line[x] = MAKE_RGB(r, g, b);
6625               }
6626               else
6627               {
6628                  priority = sprite_priorities[(pix >> sprite_priority_shift) & sprite_priority_mask];
6629                  if ( priority != pri )
6630                  {
6631                     stv_sprite_priorities_used[priority] = 1;
6632                     stv_sprite_priorities_in_fb_line[y][priority] = 1;
6633                     continue;
6634                  };
6635
6636                  {
6637                     pix &= sprite_colormask;
6638                     if ( pix == (sprite_colormask - 1) )
6639                     {
6640                        /*shadow - in reality, we should check from what layer pixel beneath comes...*/
6641                        if ( STV_VDP2_SDCTL & 0x3f )
6642                        {
6643                           UINT32 p = bitmap_line[x];
6644                           bitmap_line[x] = MAKE_RGB(RGB_RED(p) >> 1, RGB_GREEN(p) >> 1, RGB_BLUE(p) >> 1);
6645                        }
6646                        /* note that when shadows are disabled, "shadow" palette entries are not drawn */
6647                     }
6648                     else if ( pix )
6649                     {
6650                        pix += (STV_VDP2_SPCAOS << 8);
6651                        pix &= 0x7ff;
6652                        pix += color_offset_pal;
6653                        bitmap_line[x] = machine().pens[ pix ];
6654                     }
6655                  }
6656
6657                  /* TODO: I don't think this one makes much logic ... (1) */
6658                  if ( pix & sprite_shadow )
6659                  {
6660                     if ( pix & ~sprite_shadow )
6661                     {
6662                        UINT32 p = bitmap_line[x];
6663                        bitmap_line[x] = MAKE_RGB(RGB_RED(p) >> 1, RGB_GREEN(p) >> 1, RGB_BLUE(p) >> 1);
6664                     }
6665                  }
6666               }
6667            }
6668         }
6669      }
6670      else //alpha_enabled == 1
6671      {
6672         for ( y = mycliprect.min_y; y <= mycliprect.max_y; y++ )
6673         {
6674            if ( stv_sprite_priorities_usage_valid )
6675               if (stv_sprite_priorities_in_fb_line[y][pri] == 0)
6676                  continue;
6677
6678            framebuffer_line = m_vdp1.framebuffer_display_lines[y];
6679            bitmap_line = &bitmap.pix32(y);
6680
6681            for ( x = mycliprect.min_x; x <= mycliprect.max_x; x++ )
6682            {
6683               pix = framebuffer_line[x];
6684               if ( (pix & 0x8000) && sprite_color_mode)
6685               {
6686                  if ( sprite_priorities[0] != pri )
6687                  {
6688                     stv_sprite_priorities_used[sprite_priorities[0]] = 1;
6689                     stv_sprite_priorities_in_fb_line[y][sprite_priorities[0]] = 1;
6690                     continue;
6691                  };
6692
6693                  b = pal5bit((pix & 0x7c00) >> 10);
6694                  g = pal5bit((pix & 0x03e0) >> 5);
6695                  r = pal5bit( pix & 0x001f);
6696                  if ( color_offset_pal )
6697                  {
6698                     stv_vdp2_compute_color_offset( &r, &g, &b, STV_VDP2_SPCOSL );
6699                  }
6700                  ccr = sprite_ccr[0];
6701                  if ( STV_VDP2_CCMD )
6702                  {
6703                     bitmap_line[x] = stv_add_blend( bitmap_line[x], MAKE_RGB(r, g, b));
6704                  }
6705                  else
6706                  {
6707                     bitmap_line[x] = alpha_blend_r32( bitmap_line[x], MAKE_RGB(r, g ,b), ((UINT16)(0x1f-ccr)*0xff)/0x1f);
6708                  }
6709               }
6710               else
6711               {
6712                  priority = sprite_priorities[(pix >> sprite_priority_shift) & sprite_priority_mask];
6713                  if ( priority != pri )
6714                  {
6715                     stv_sprite_priorities_used[priority] = 1;
6716                     stv_sprite_priorities_in_fb_line[y][priority] = 1;
6717                     continue;
6718                  };
6719
6720                  ccr = sprite_ccr[ (pix >> sprite_ccrr_shift) & sprite_ccrr_mask ];
6721                  if ( alpha_enabled == 2 )
6722                  {
6723                     if ( ( pix & 0x8000 ) == 0 )
6724                     {
6725                        ccr = 0;
6726                     }
6727                  }
6728
6729
6730                  {
6731                     pix &= sprite_colormask;
6732                     if ( pix == (sprite_colormask - 1) )
6733                     {
6734                        /*shadow - in reality, we should check from what layer pixel beneath comes...*/
6735                        if ( STV_VDP2_SDCTL & 0x3f )
6736                        {
6737                           UINT32 p = bitmap_line[x];
6738                           bitmap_line[x] = MAKE_RGB(RGB_RED(p) >> 1, RGB_GREEN(p) >> 1, RGB_BLUE(p) >> 1);
6739                        }
6740                        /* note that when shadows are disabled, "shadow" palette entries are not drawn */
6741                     } else if ( pix )
6742                     {
6743                        pix += (STV_VDP2_SPCAOS << 8);
6744                        pix &= 0x7ff;
6745                        pix += color_offset_pal;
6746                        if ( ccr > 0 )
6747                        {
6748                           if ( STV_VDP2_CCMD )
6749                           {
6750                              bitmap_line[x] = stv_add_blend( bitmap_line[x], machine().pens[pix] );
6751                           }
6752                           else
6753                           {
6754                              bitmap_line[x] = alpha_blend_r32( bitmap_line[x], machine().pens[pix], ((UINT16)(0x1f-ccr)*0xff)/0x1f );
6755                           }
6756                        }
6757                        else
6758                           bitmap_line[x] = machine().pens[pix];
6759                     }
6760                  }
6761
6762                  /* TODO: (1) */
6763                  if ( pix & sprite_shadow )
6764                  {
6765                     if ( pix & ~sprite_shadow )
6766                     {
6767                        UINT32 p = bitmap_line[x];
6768                        bitmap_line[x] = MAKE_RGB(RGB_RED(p) >> 1, RGB_GREEN(p) >> 1, RGB_BLUE(p) >> 1);
6769                     }
6770                  }
6771               }
6772            }
6773         }
6774      }
6775   }
6776   else
6777   {
6778      for ( y = mycliprect.min_y; y <= mycliprect.max_y / (interlace_framebuffer+1); y++ )
6779      {
6780         if ( stv_sprite_priorities_usage_valid )
6781            if (stv_sprite_priorities_in_fb_line[y][pri] == 0)
6782               continue;
6783
6784         framebuffer_line = m_vdp1.framebuffer_display_lines[y];
6785         if ( interlace_framebuffer == 0 )
6786         {
6787            bitmap_line = &bitmap.pix32(y);
6788         }
6789         else
6790         {
6791            bitmap_line = &bitmap.pix32(2*y);
6792            bitmap_line2 = &bitmap.pix32(2*y + 1);
6793         }
6794
6795         for ( x = mycliprect.min_x; x <= mycliprect.max_x /(double_x+1) ; x++ )
6796         {
6797            pix = framebuffer_line[x];
6798            if ( (pix & 0x8000) && sprite_color_mode)
6799            {
6800               if ( sprite_priorities[0] != pri )
6801               {
6802                  stv_sprite_priorities_used[sprite_priorities[0]] = 1;
6803                  stv_sprite_priorities_in_fb_line[y][sprite_priorities[0]] = 1;
6804                  continue;
6805               };
6806
6807               b = pal5bit((pix & 0x7c00) >> 10);
6808               g = pal5bit((pix & 0x03e0) >> 5);
6809               r = pal5bit( pix & 0x001f);
6810               if ( color_offset_pal )
6811               {
6812                  stv_vdp2_compute_color_offset( &r, &g, &b, STV_VDP2_SPCOSL );
6813               }
6814               if ( alpha_enabled == 0 )
6815               {
6816                  if(double_x)
6817                  {
6818                     bitmap_line[x*2] = MAKE_RGB(r, g, b);
6819                     if ( interlace_framebuffer == 1 ) bitmap_line2[x*2] = MAKE_RGB(r, g, b);
6820                     bitmap_line[x*2+1] = MAKE_RGB(r, g, b);
6821                     if ( interlace_framebuffer == 1 ) bitmap_line2[x*2+1] = MAKE_RGB(r, g, b);
6822                  }
6823                  else
6824                  {
6825                     bitmap_line[x] = MAKE_RGB(r, g, b);
6826                     if ( interlace_framebuffer == 1 ) bitmap_line2[x] = MAKE_RGB(r, g, b);
6827                  }
6828               }
6829               else // alpha_blend == 1
6830               {
6831                  ccr = sprite_ccr[0];
6832
6833                  if ( STV_VDP2_CCMD )
6834                  {
6835                     if(double_x)
6836                     {
6837                        bitmap_line[x*2] = stv_add_blend( bitmap_line[x*2], MAKE_RGB(r, g, b) );
6838                        if ( interlace_framebuffer == 1 ) bitmap_line2[x*2] = stv_add_blend( bitmap_line2[x*2], MAKE_RGB(r, g, b) );
6839                        bitmap_line[x*2+1] = stv_add_blend( bitmap_line[x*2+1], MAKE_RGB(r, g, b) );
6840                        if ( interlace_framebuffer == 1 ) bitmap_line2[x*2+1] = stv_add_blend( bitmap_line2[x*2+1], MAKE_RGB(r, g, b) );
6841                     }
6842                     else
6843                     {
6844                        bitmap_line[x] = stv_add_blend( bitmap_line[x], MAKE_RGB(r, g, b) );
6845                        if ( interlace_framebuffer == 1 ) bitmap_line2[x] = stv_add_blend( bitmap_line2[x], MAKE_RGB(r, g, b) );
6846                     }
6847                  }
6848                  else
6849                  {
6850                     if(double_x)
6851                     {
6852                        bitmap_line[x*2] = alpha_blend_r32( bitmap_line[x*2], MAKE_RGB(r, g, b), ((UINT16)(0x1f-ccr)*0xff)/0x1f );
6853                        if ( interlace_framebuffer == 1 ) bitmap_line2[x*2] = alpha_blend_r32( bitmap_line2[x*2], MAKE_RGB(r, g, b), ((UINT16)(0x1f-ccr)*0xff)/0x1f );
6854                        bitmap_line[x*2+1] = alpha_blend_r32( bitmap_line[x*2+1], MAKE_RGB(r, g, b), ((UINT16)(0x1f-ccr)*0xff)/0x1f );
6855                        if ( interlace_framebuffer == 1 ) bitmap_line2[x*2+1] = alpha_blend_r32( bitmap_line2[x*2+1], MAKE_RGB(r, g, b), ((UINT16)(0x1f-ccr)*0xff)/0x1f);
6856                     }
6857                     else
6858                     {
6859                        bitmap_line[x] = alpha_blend_r32( bitmap_line[x], MAKE_RGB(r, g, b), ((UINT16)(0x1f-ccr)*0xff)/0x1f);
6860                        if ( interlace_framebuffer == 1 ) bitmap_line2[x] = alpha_blend_r32( bitmap_line2[x], MAKE_RGB(r, g, b), ((UINT16)(0x1f-ccr)*0xff)/0x1f);
6861                     }
6862                  }
6863               }
6864            }
6865            else
6866            {
6867               priority = sprite_priorities[(pix >> sprite_priority_shift) & sprite_priority_mask];
6868               if ( priority != pri )
6869               {
6870                  stv_sprite_priorities_used[priority] = 1;
6871                  stv_sprite_priorities_in_fb_line[y][priority] = 1;
6872                  continue;
6873               };
6874
6875               if ( alpha_enabled )
6876                  ccr = sprite_ccr[ (pix >> sprite_ccrr_shift) & sprite_ccrr_mask ];
6877
6878               if ( alpha_enabled == 2 )
6879               {
6880                  if ( ( pix & 0x8000 ) == 0 )
6881                  {
6882                     ccr = 0;
6883                  }
6884               }
6885
6886               {
6887                  pix &= sprite_colormask;
6888                  if ( pix == (sprite_colormask - 1) )
6889                  {
6890                     /*shadow - in reality, we should check from what layer pixel beneath comes...*/
6891                     if ( STV_VDP2_SDCTL & 0x3f )
6892                     {
6893                        UINT32 p = bitmap_line[x];
6894                        if(double_x)
6895                        {
6896                           p = bitmap_line[x*2];
6897                           bitmap_line[x*2] = MAKE_RGB(RGB_RED(p) >> 1, RGB_GREEN(p) >> 1, RGB_BLUE(p) >> 1);
6898                           p = bitmap_line[x*2+1];
6899                           bitmap_line[x*2+1] = MAKE_RGB(RGB_RED(p) >> 1, RGB_GREEN(p) >> 1, RGB_BLUE(p) >> 1);
6900                        }
6901                        else
6902                           bitmap_line[x] = MAKE_RGB(RGB_RED(p) >> 1, RGB_GREEN(p) >> 1, RGB_BLUE(p) >> 1);
6903                     }
6904                     /* note that when shadows are disabled, "shadow" palette entries are not drawn */
6905                  } else if ( pix )
6906                  {
6907                     pix += (STV_VDP2_SPCAOS << 8);
6908                     pix &= 0x7ff;
6909                     pix += color_offset_pal;
6910                     if ( alpha_enabled == 0 )
6911                     {
6912                        if(double_x)
6913                        {
6914                           bitmap_line[x*2] = machine().pens[ pix ];
6915                           if ( interlace_framebuffer == 1 ) bitmap_line2[x*2] = machine().pens[ pix ];
6916                           bitmap_line[x*2+1] = machine().pens[ pix ];
6917                           if ( interlace_framebuffer == 1 ) bitmap_line2[x*2+1] = machine().pens[ pix ];
6918                        }
6919                        else
6920                        {
6921                           bitmap_line[x] = machine().pens[ pix ];
6922                           if ( interlace_framebuffer == 1 ) bitmap_line2[x] = machine().pens[ pix ];
6923                        }
6924                     }
6925                     else // alpha_blend == 1
6926                     {
6927                        if ( STV_VDP2_CCMD )
6928                        {
6929                           if(double_x)
6930                           {
6931                              bitmap_line[x*2] = stv_add_blend( bitmap_line[x*2], machine().pens[pix] );
6932                              if ( interlace_framebuffer == 1 ) bitmap_line2[x*2] = stv_add_blend( bitmap_line2[x], machine().pens[pix] );
6933                              bitmap_line[x*2+1] = stv_add_blend( bitmap_line[x*2+1], machine().pens[pix] );
6934                              if ( interlace_framebuffer == 1 ) bitmap_line2[x*2+1] = stv_add_blend( bitmap_line2[x], machine().pens[pix] );
6935                           }
6936                           else
6937                           {
6938                              bitmap_line[x] = stv_add_blend( bitmap_line[x], machine().pens[pix] );
6939                              if ( interlace_framebuffer == 1 ) bitmap_line2[x] = stv_add_blend( bitmap_line2[x], machine().pens[pix] );
6940                           }
6941                        }
6942                        else
6943                        {
6944                           if(double_x)
6945                           {
6946                              bitmap_line[x*2] = alpha_blend_r32( bitmap_line[x*2], machine().pens[pix], ((UINT16)(0x1f-ccr)*0xff)/0x1f );
6947                              if ( interlace_framebuffer == 1 ) bitmap_line2[x*2] = alpha_blend_r32( bitmap_line2[x], machine().pens[pix], ((UINT16)(0x1f-ccr)*0xff)/0x1f );
6948                              bitmap_line[x*2+1] = alpha_blend_r32( bitmap_line[x*2+1], machine().pens[pix], ((UINT16)(0x1f-ccr)*0xff)/0x1f );
6949                              if ( interlace_framebuffer == 1 ) bitmap_line2[x*2+1] = alpha_blend_r32( bitmap_line2[x], machine().pens[pix], ((UINT16)(0x1f-ccr)*0xff)/0x1f );
6950                           }
6951                           else
6952                           {
6953                              bitmap_line[x] = alpha_blend_r32( bitmap_line[x], machine().pens[pix], ((UINT16)(0x1f-ccr)*0xff)/0x1f );
6954                              if ( interlace_framebuffer == 1 ) bitmap_line2[x] = alpha_blend_r32( bitmap_line2[x], machine().pens[pix], ((UINT16)(0x1f-ccr)*0xff)/0x1f );
6955                           }
6956                        }
6957                     }
6958                  }
6959               }
6960
6961               /* TODO: (1) */
6962               if ( pix & sprite_shadow )
6963               {
6964                  if ( pix & ~sprite_shadow )
6965                  {
6966                     UINT32 p = bitmap_line[x];
6967                     if(double_x)
6968                     {
6969                        p = bitmap_line[x*2];
6970                        bitmap_line[x*2] = MAKE_RGB(RGB_RED(p) >> 1, RGB_GREEN(p) >> 1, RGB_BLUE(p) >> 1);
6971                        p = bitmap_line[x*2+1];
6972                        bitmap_line[x*2+1] = MAKE_RGB(RGB_RED(p) >> 1, RGB_GREEN(p) >> 1, RGB_BLUE(p) >> 1);
6973                     }
6974                     else
6975                        bitmap_line[x] = MAKE_RGB(RGB_RED(p) >> 1, RGB_GREEN(p) >> 1, RGB_BLUE(p) >> 1);
6976                  }
6977               }
6978            }
6979         }
6980      }
6981   }
6982
6983   stv_sprite_priorities_usage_valid = 1;
6984}
6985
6986UINT32 saturn_state::screen_update_stv_vdp2(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
6987{
6988   stv_vdp2_fade_effects();
6989
6990   stv_vdp2_draw_back(m_tmpbitmap,cliprect);
6991
6992   if(STV_VDP2_DISP)
6993   {
6994      UINT8 pri;
6995
6996      stv_sprite_priorities_usage_valid = 0;
6997      memset(stv_sprite_priorities_used, 0, sizeof(stv_sprite_priorities_used));
6998      memset(stv_sprite_priorities_in_fb_line, 0, sizeof(stv_sprite_priorities_in_fb_line));
6999
7000      /*If a plane has a priority value of zero it isn't shown at all.*/
7001      for(pri=1;pri<8;pri++)
7002      {
7003         if(pri==STV_VDP2_N3PRIN) { stv_vdp2_draw_NBG3(m_tmpbitmap,cliprect); }
7004         if(pri==STV_VDP2_N2PRIN) { stv_vdp2_draw_NBG2(m_tmpbitmap,cliprect); }
7005         if(pri==STV_VDP2_N1PRIN) { stv_vdp2_draw_NBG1(m_tmpbitmap,cliprect); }
7006         if(pri==STV_VDP2_N0PRIN) { stv_vdp2_draw_NBG0(m_tmpbitmap,cliprect); }
7007         if(pri==STV_VDP2_R0PRIN) { stv_vdp2_draw_RBG0(m_tmpbitmap,cliprect); }
7008         { draw_sprites(m_tmpbitmap,cliprect,pri); }
7009      }
7010   }
7011
7012   copybitmap(bitmap, m_tmpbitmap, 0, 0, 0, 0, cliprect);
7013
7014   #if 0
7015   /* Do NOT remove me, used to test video code performance. */
7016   if(machine().input().code_pressed(KEYCODE_Q))
7017   {
7018      popmessage("Halt CPUs");
7019      m_maincpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
7020      m_slave->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
7021      m_audiocpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
7022   }
7023   #endif
7024   return 0;
7025}

Previous 199869 Revisions Next


© 1997-2024 The MAME Team