Previous 199869 Revisions Next

r21331 Friday 22nd February, 2013 at 19:58:27 UTC by smf
split mame/drivers/saturn.c into emu/machine/saturn.c and mess/drivers/saturn.c, so mame doesn't have to compile and link the unused code. [smf]
[src/emu]emu.mak
[src/emu/machine]saturn.c*
[src/mame]mame.mak
[src/mame/drivers]saturn.c
[src/mess]mess.mak
[src/mess/drivers]saturn.c*

trunk/src/emu/emu.mak
r21330r21331
255255   $(EMUMACHINE)/s3c2410.o     \
256256   $(EMUMACHINE)/s3c2440.o     \
257257   $(EMUMACHINE)/s3520cf.o     \
258   $(EMUMACHINE)/saturn.o      \
258259   $(EMUMACHINE)/scsibus.o     \
259260   $(EMUMACHINE)/scsicb.o      \
260261   $(EMUMACHINE)/scsicd.o      \
r21330r21331
265266   $(EMUMACHINE)/secflash.o    \
266267   $(EMUMACHINE)/seibu_cop.o   \
267268   $(EMUMACHINE)/smc91c9x.o    \
268   $(EMUMACHINE)/smpc.o      \
269   $(EMUMACHINE)/smpc.o        \
269270   $(EMUMACHINE)/stvcd.o       \
270271   $(EMUMACHINE)/tc009xlvc.o   \
271272   $(EMUMACHINE)/timekpr.o     \
trunk/src/emu/machine/saturn.c
r0r21331
1#include "emu.h"
2#include "includes/stv.h"
3#include "machine/scudsp.h"
4#include "cpu/sh2/sh2.h"
5
6/* TODO: do this in a verboselog style */
7#define LOG_CDB  0
8#define LOG_SCU  1
9#define LOG_IRQ  0
10#define LOG_IOGA 0
11
12int saturn_state::DectoBCD(int num)
13{
14   int i, cnt = 0, tmp, res = 0;
15
16   while (num > 0) {
17      tmp = num;
18      while (tmp >= 10) tmp %= 10;
19      for (i=0; i<cnt; i++)
20         tmp *= 16;
21      res += tmp;
22      cnt++;
23      num /= 10;
24   }
25
26   return res;
27}
28
29/**************************************************************************************/
30
31/*
32
33SCU Handling
34
35*/
36
37/**********************************************************************************
38SCU Register Table
39offset,relative address
40Registers are in long words.
41===================================================================================
420     0000  Level 0 DMA Set Register
431     0004
442     0008
453     000c
464     0010
475     0014
486     0018
497     001c
508     0020  Level 1 DMA Set Register
519     0024
5210    0028
5311    002c
5412    0030
5513    0034
5614    0038
5715    003c
5816    0040  Level 2 DMA Set Register
5917    0044
6018    0048
6119    004c
6220    0050
6321    0054
6422    0058
6523    005c
6624    0060  DMA Forced Stop
6725    0064
6826    0068
6927    006c
7028    0070  <Free>
7129    0074
7230    0078
7331    007c  DMA Status Register
7432    0080  DSP Program Control Port
7533    0084  DSP Program RAM Data Port
7634    0088  DSP Data RAM Address Port
7735    008c  DSP Data RAM Data Port
7836    0090  Timer 0 Compare Register
7937    0094  Timer 1 Set Data Register
8038    0098  Timer 1 Mode Register
8139    009c  <Free>
8240    00a0  Interrupt Mask Register
8341    00a4  Interrupt Status Register
8442    00a8  A-Bus Interrupt Acknowledge
8543    00ac  <Free>
8644    00b0  A-Bus Set Register
8745    00b4
8846    00b8  A-Bus Refresh Register
8947    00bc  <Free>
9048    00c0
9149    00c4  SCU SDRAM Select Register
9250    00c8  SCU Version Register
9351    00cc  <Free>
9452    00cf
95===================================================================================
96DMA Status Register(32-bit):
97xxxx xxxx x--- xx-- xx-- xx-- xx-- xx-- UNUSED
98---- ---- -x-- ---- ---- ---- ---- ---- DMA DSP-Bus access
99---- ---- --x- ---- ---- ---- ---- ---- DMA B-Bus access
100---- ---- ---x ---- ---- ---- ---- ---- DMA A-Bus access
101---- ---- ---- --x- ---- ---- ---- ---- DMA lv 1 interrupt
102---- ---- ---- ---x ---- ---- ---- ---- DMA lv 0 interrupt
103---- ---- ---- ---- --x- ---- ---- ---- DMA lv 2 in stand-by
104---- ---- ---- ---- ---x ---- ---- ---- DMA lv 2 in operation
105---- ---- ---- ---- ---- --x- ---- ---- DMA lv 1 in stand-by
106---- ---- ---- ---- ---- ---x ---- ---- DMA lv 1 in operation
107---- ---- ---- ---- ---- ---- --x- ---- DMA lv 0 in stand-by
108---- ---- ---- ---- ---- ---- ---x ---- DMA lv 0 in operation
109---- ---- ---- ---- ---- ---- ---- --x- DSP side DMA in stand-by
110---- ---- ---- ---- ---- ---- ---- ---x DSP side DMA in operation
111
112**********************************************************************************/
113/*
114DMA TODO:
115-Remove CD transfer DMA hack (tied with CD block bug(s)?)
116-Add timings(but how fast are each DMA?).
117-Add level priority & DMA status register.
118*/
119
120#define DIRECT_MODE(_lv_)           (!(m_scu_regs[5+(_lv_*8)] & 0x01000000))
121#define INDIRECT_MODE(_lv_)           (m_scu_regs[5+(_lv_*8)] & 0x01000000)
122#define DRUP(_lv_)                    (m_scu_regs[5+(_lv_*8)] & 0x00010000)
123#define DWUP(_lv_)                    (m_scu_regs[5+(_lv_*8)] & 0x00000100)
124
125/*These macros sets the various DMA status flags.*/
126#define DnMV_1(_ch_) m_scu.status|=(0x10 << 4 * _ch_)
127#define DnMV_0(_ch_) m_scu.status&=~(0x10 << 4 * _ch_)
128
129/*For area checking*/
130#define BIOS_BUS(var)   (var & 0x07000000) == 0
131#define ABUS(_lv_)       ((m_scu.src[_lv_] & 0x07000000) >= 0x02000000) && ((m_scu.src[_lv_] & 0x07000000) <= 0x04000000)
132#define BBUS(_lv_)       ((scu_##_lv_ & 0x07ffffff) >= 0x05a00000) && ((scu_##_lv_ & 0x07ffffff) <= 0x05ffffff)
133#define VDP1_REGS(_lv_)  ((scu_##_lv_ & 0x07ffffff) >= 0x05d00000) && ((scu_##_lv_ & 0x07ffffff) <= 0x05dfffff)
134#define VDP2(_lv_)       ((scu_##_lv_ & 0x07ffffff) >= 0x05e00000) && ((scu_##_lv_ & 0x07ffffff) <= 0x05fdffff)
135#define WORK_RAM_L(_lv_) ((scu_##_lv_ & 0x07ffffff) >= 0x00200000) && ((scu_##_lv_ & 0x07ffffff) <= 0x002fffff)
136#define WORK_RAM_H(var) (var & 0x07000000) == 0x06000000
137#define SOUND_RAM(_lv_)  ((scu_##_lv_ & 0x07ffffff) >= 0x05a00000) && ((scu_##_lv_ & 0x07ffffff) <= 0x05afffff)
138
139void saturn_state::scu_do_transfer(UINT8 event)
140{
141   address_space &space = machine().device("maincpu")->memory().space(AS_PROGRAM);
142   int i;
143
144   for(i=0;i<3;i++)
145   {
146      if(m_scu.enable_mask[i] && m_scu.start_factor[i] == event)
147      {
148         if(DIRECT_MODE(i))      { scu_dma_direct(space,i);   }
149         else                    { scu_dma_indirect(space,i); }
150      }
151   }
152}
153
154/* test pending irqs */
155void saturn_state::scu_test_pending_irq()
156{
157   int i;
158   const int irq_level[32] = { 0xf, 0xe, 0xd, 0xc,
159                        0xb, 0xa, 0x9, 0x8,
160                        0x8, 0x6, 0x6, 0x5,
161                        0x3, 0x2,  -1,  -1,
162                        0x7, 0x7, 0x7, 0x7,
163                        0x4, 0x4, 0x4, 0x4,
164                        0x1, 0x1, 0x1, 0x1,
165                        0x1, 0x1, 0x1, 0x1  };
166
167   for(i=0;i<32;i++)
168   {
169      if((!(m_scu.ism & 1 << i)) && (m_scu.ist & 1 << i))
170      {
171         if(irq_level[i] != -1) /* TODO: cheap check for undefined irqs */
172         {
173            m_maincpu->set_input_line_and_vector(irq_level[i], HOLD_LINE, 0x40 + i);
174            m_scu.ist &= ~(1 << i);
175            return; /* avoid spurious irqs, correct? */
176         }
177      }
178   }
179}
180
181READ32_MEMBER(saturn_state::saturn_scu_r)
182{
183   UINT32 res;
184
185   /*TODO: write only registers must return 0 or open bus */
186   switch(offset)
187   {
188      case 0x5c/4:
189      //  Super Major League and Shin Megami Tensei - Akuma Zensho reads from there (undocumented), DMA status mirror?
190         if(LOG_SCU && !space.debugger_access()) logerror("(PC=%08x) DMA status reg read\n",space.device().safe_pc());
191         res = m_scu.status;
192         break;
193      case 0x7c/4:
194         if(LOG_SCU && !space.debugger_access()) logerror("(PC=%08x) DMA status reg read\n",space.device().safe_pc());
195         res = m_scu.status;
196         break;
197      case 0x80/4:
198         res = dsp_prg_ctrl_r(space);
199         break;
200      case 0x8c/4:
201         if(LOG_SCU && !space.debugger_access()) logerror( "DSP mem read at %08X\n", m_scu_regs[34]);
202         res = dsp_ram_addr_r();
203         break;
204      case 0xa0/4:
205         if(LOG_SCU && !space.debugger_access()) logerror("(PC=%08x) IRQ mask reg read %08x MASK=%08x\n",space.device().safe_pc(),mem_mask,m_scu_regs[0xa0/4]);
206         res = m_scu.ism;
207         break;
208      case 0xa4/4:
209         if(LOG_SCU && !space.debugger_access()) logerror("(PC=%08x) IRQ status reg read MASK=%08x IST=%08x | ISM=%08x\n",space.device().safe_pc(),mem_mask,m_scu.ist,m_scu.ism);
210         /* TODO: Bug! trips an HW fault. Basically, it tries to read the IST bit 1 with that irq enabled.
211             Densetsu no Ogre Battle doesn't like this, so it needs investigation ...
212         */
213//         res = m_scu.ist | ~m_scu.ism;
214         res = m_scu.ist;
215         break;
216      case 0xc8/4:
217         if(LOG_SCU && !space.debugger_access()) logerror("(PC=%08x) SCU version reg read\n",space.device().safe_pc());
218         res = 0x00000004;/*SCU Version 4, OK? */
219         break;
220      default:
221         if(LOG_SCU && !space.debugger_access()) logerror("(PC=%08x) SCU reg read at %d = %08x\n",space.device().safe_pc(),offset,m_scu_regs[offset]);
222         res = m_scu_regs[offset];
223         break;
224   }
225
226   return res;
227}
228
229#define DMA_CH ((offset & 0x18) / 8)
230
231WRITE32_MEMBER(saturn_state::saturn_scu_w)
232{
233   COMBINE_DATA(&m_scu_regs[offset]);
234
235   switch(offset)
236   {
237      /*LV 0 DMA*/
238      case 0x00/4: case 0x20/4: case 0x40/4:  m_scu.src[DMA_CH]  = ((m_scu_regs[offset] & 0x07ffffff) >> 0); break;
239      case 0x04/4: case 0x24/4: case 0x44/4:  m_scu.dst[DMA_CH]  = ((m_scu_regs[offset] & 0x07ffffff) >> 0); break;
240      case 0x08/4: case 0x28/4: case 0x48/4:  m_scu.size[DMA_CH] = ((m_scu_regs[offset] & ((offset == 2) ? 0x000fffff : 0xfff)) >> 0); break;
241      case 0x0c/4: case 0x2c/4: case 0x4c/4:
242         m_scu.src_add[DMA_CH] = (m_scu_regs[offset] & 0x100) ? 4 : 0;
243         m_scu.dst_add[DMA_CH] = 1 << (m_scu_regs[offset] & 7);
244         if(m_scu.dst_add[DMA_CH] == 1) { m_scu.dst_add[DMA_CH] = 0; }
245         break;
246      case 0x10/4: case 0x30/4: case 0x50/4:
247         m_scu.enable_mask[DMA_CH] = (data & 0x100) >> 8;
248         if(m_scu.enable_mask[DMA_CH] && m_scu.start_factor[DMA_CH] == 7 && m_scu_regs[offset] & 1)
249         {
250            if(DIRECT_MODE(DMA_CH)) { scu_dma_direct(space,DMA_CH);   }
251            else                    { scu_dma_indirect(space,DMA_CH); }
252            m_scu_regs[offset]&=~1;//disable starting bit.
253         }
254         break;
255      case 0x14/4: case 0x34/4: case 0x54/4:
256         if(INDIRECT_MODE(DMA_CH))
257         {
258            //if(LOG_SCU) logerror("Indirect Mode DMA lv %d set\n",DMA_CH);
259            if(!DWUP(DMA_CH)) m_scu.index[DMA_CH] = m_scu.dst[DMA_CH];
260         }
261
262         m_scu.start_factor[DMA_CH] = m_scu_regs[offset] & 7;
263         break;
264
265      case 0x60/4:
266         if(LOG_SCU) logerror("DMA Forced Stop Register set = %02x\n",m_scu_regs[24]);
267         break;
268      case 0x7c/4: if(LOG_SCU) logerror("Warning: DMA status WRITE! Offset %02x(%d)\n",offset*4,offset); break;
269      /*DSP section*/
270      case 0x80/4:
271         /* TODO: you can't overwrite some flags with this */
272         dsp_prg_ctrl_w(space, m_scu_regs[offset]);
273         if(LOG_SCU) logerror("SCU DSP: Program Control Port Access %08x\n",data);
274         break;
275      case 0x84/4:
276         dsp_prg_data(m_scu_regs[offset]);
277         if(LOG_SCU) logerror("SCU DSP: Program RAM Data Port Access %08x\n",data);
278         break;
279      case 0x88/4:
280         dsp_ram_addr_ctrl(m_scu_regs[offset]);
281         if(LOG_SCU) logerror("SCU DSP: Data RAM Address Port Access %08x\n",data);
282         break;
283      case 0x8c/4:
284         dsp_ram_addr_w(m_scu_regs[offset]);
285         if(LOG_SCU) logerror("SCU DSP: Data RAM Data Port Access %08x\n",data);
286         break;
287      case 0x90/4: /*if(LOG_SCU) logerror("timer 0 compare data = %03x\n",m_scu_regs[36]);*/ break;
288      case 0x94/4: /*if(LOG_SCU) logerror("timer 1 set data = %08x\n",m_scu_regs[37]);*/ break;
289      case 0x98/4: /*if(LOG_SCU) logerror("timer 1 mode data = %08x\n",m_scu_regs[38]);*/ break;
290      case 0xa0/4: /* IRQ mask */
291         m_scu.ism = m_scu_regs[0xa0/4];
292         scu_test_pending_irq();
293         break;
294      case 0xa4/4: /* IRQ control */
295         if(LOG_SCU) logerror("PC=%08x IRQ status reg set:%08x %08x\n",space.device().safe_pc(),m_scu_regs[41],mem_mask);
296         m_scu.ist &= m_scu_regs[offset];
297         scu_test_pending_irq();
298         break;
299      case 0xa8/4:
300         /* This sends an irq signal to the extra devices connected to the A-Bus, not really needed for now. */
301         //if(LOG_SCU) logerror("A-Bus IRQ ACK %08x\n",m_scu_regs[42]);
302         break;
303      case 0xc4/4: if(LOG_SCU) logerror("SCU SDRAM set: %02x\n",m_scu_regs[49]); break;
304      default: if(LOG_SCU) logerror("Warning: unused SCU reg set %d = %08x\n",offset,data);
305   }
306}
307
308/*Lv 0 DMA end irq*/
309TIMER_CALLBACK_MEMBER(saturn_state::dma_lv0_ended )
310{
311   if(!(m_scu.ism & IRQ_DMALV0))
312      m_maincpu->set_input_line_and_vector(5, HOLD_LINE, 0x4b);
313   else
314      m_scu.ist |= (IRQ_DMALV0);
315
316   DnMV_0(0);
317}
318
319/*Lv 1 DMA end irq*/
320TIMER_CALLBACK_MEMBER(saturn_state::dma_lv1_ended)
321{
322   if(!(m_scu.ism & IRQ_DMALV1))
323      m_maincpu->set_input_line_and_vector(6, HOLD_LINE, 0x4a);
324   else
325      m_scu.ist |= (IRQ_DMALV1);
326
327   DnMV_0(1);
328}
329
330/*Lv 2 DMA end irq*/
331TIMER_CALLBACK_MEMBER(saturn_state::dma_lv2_ended)
332{
333   if(!(m_scu.ism & IRQ_DMALV2))
334      m_maincpu->set_input_line_and_vector(6, HOLD_LINE, 0x49);
335   else
336      m_scu.ist |= (IRQ_DMALV2);
337
338   DnMV_0(2);
339}
340
341void saturn_state::scu_single_transfer(address_space &space, UINT32 src, UINT32 dst,UINT8 *src_shift)
342{
343   UINT32 src_data;
344
345   if(src & 1)
346   {
347      /* Road Blaster does a work ram h to color ram with offsetted source address, do some data rotation */
348      src_data = ((space.read_dword(src & 0x07fffffc) & 0x00ffffff)<<8);
349      src_data |= ((space.read_dword((src & 0x07fffffc)+4) & 0xff000000) >> 24);
350      src_data >>= (*src_shift)*16;
351   }
352   else
353      src_data = space.read_dword(src & 0x07fffffc) >> (*src_shift)*16;
354
355   space.write_word(dst,src_data);
356
357   *src_shift ^= 1;
358}
359
360void saturn_state::scu_dma_direct(address_space &space, UINT8 dma_ch)
361{
362   UINT32 tmp_src,tmp_dst,total_size;
363   UINT8 cd_transfer_flag;
364
365   if(m_scu.src_add[dma_ch] == 0 || (m_scu.dst_add[dma_ch] != 2 && m_scu.dst_add[dma_ch] != 4))
366   {
367   if(LOG_SCU) printf("DMA lv %d transfer START\n"
368                     "Start %08x End %08x Size %04x\n",dma_ch,m_scu.src[dma_ch],m_scu.dst[dma_ch],m_scu.size[dma_ch]);
369   if(LOG_SCU) printf("Start Add %04x Destination Add %04x\n",m_scu.src_add[dma_ch],m_scu.dst_add[dma_ch]);
370   }
371
372   /* TODO: Game Basic and World Cup 98 trips this, according to the docs the SCU can't transfer from BIOS area (can't communicate from/to that bus) */
373   if(BIOS_BUS(m_scu.src[dma_ch]))
374   {
375      popmessage("Warning: SCU transfer from BIOS area, contact MAMEdev");
376      if(!(m_scu.ism & IRQ_DMAILL))
377         m_maincpu->set_input_line_and_vector(3, HOLD_LINE, 0x4c);
378      else
379         m_scu.ist |= (IRQ_DMAILL);
380      return;
381   }
382
383   DnMV_1(dma_ch);
384
385   /* max size */
386   if(m_scu.size[dma_ch] == 0) { m_scu.size[dma_ch] = (dma_ch == 0) ? 0x00100000 : 0x1000; }
387
388   tmp_src = tmp_dst = 0;
389
390   total_size = m_scu.size[dma_ch];
391   if(!(DRUP(dma_ch))) tmp_src = m_scu.src[dma_ch];
392   if(!(DWUP(dma_ch))) tmp_dst = m_scu.dst[dma_ch];
393
394   cd_transfer_flag = m_scu.src_add[dma_ch] == 0 && m_scu.src[dma_ch] == 0x05818000;
395
396   /* TODO: Many games directly accesses CD-ROM register 0x05818000, it must be a dword access with current implementation otherwise it won't work */
397   if(cd_transfer_flag)
398   {
399      int i;
400      if(WORK_RAM_H(m_scu.dst[dma_ch]))
401         m_scu.dst_add[dma_ch] = 4;
402      else
403         m_scu.dst_add[dma_ch] <<= 1;
404
405      for (i = 0; i < m_scu.size[dma_ch];i+=m_scu.dst_add[dma_ch])
406      {
407         space.write_dword(m_scu.dst[dma_ch],space.read_dword(m_scu.src[dma_ch]));
408         if(m_scu.dst_add[dma_ch] == 8)
409            space.write_dword(m_scu.dst[dma_ch]+4,space.read_dword(m_scu.src[dma_ch]));
410
411         m_scu.src[dma_ch]+=m_scu.src_add[dma_ch];
412         m_scu.dst[dma_ch]+=m_scu.dst_add[dma_ch];
413      }
414   }
415   else
416   {
417      int i;
418      UINT8  src_shift;
419
420      src_shift = ((m_scu.src[dma_ch] & 2) >> 1) ^ 1;
421
422      for (i = 0; i < m_scu.size[dma_ch];i+=2)
423      {
424         scu_single_transfer(space,m_scu.src[dma_ch],m_scu.dst[dma_ch],&src_shift);
425
426         if(src_shift)
427            m_scu.src[dma_ch]+=m_scu.src_add[dma_ch];
428
429         /* if target is Work RAM H, the add value is fixed, behaviour confirmed by Final Romance 2, Virtual Mahjong and Burning Rangers */
430         m_scu.dst[dma_ch]+=(WORK_RAM_H(m_scu.dst[dma_ch])) ? 2 : m_scu.dst_add[dma_ch];
431      }
432   }
433
434   /* Burning Rangers doesn't agree with this. */
435//   m_scu.size[dma_ch] = 0;
436   if(!(DRUP(dma_ch))) m_scu.src[dma_ch] = tmp_src;
437   if(!(DWUP(dma_ch))) m_scu.dst[dma_ch] = tmp_dst;
438
439   {
440      /*TODO: change DMA into DRQ model. Timing is a guess.  */
441      switch(dma_ch)
442      {
443         case 0: machine().scheduler().timer_set(m_maincpu->cycles_to_attotime(total_size/4), timer_expired_delegate(FUNC(saturn_state::dma_lv0_ended),this)); break;
444         case 1: machine().scheduler().timer_set(m_maincpu->cycles_to_attotime(total_size/4), timer_expired_delegate(FUNC(saturn_state::dma_lv1_ended),this)); break;
445         case 2: machine().scheduler().timer_set(m_maincpu->cycles_to_attotime(total_size/4), timer_expired_delegate(FUNC(saturn_state::dma_lv2_ended),this)); break;
446      }
447   }
448}
449
450void saturn_state::scu_dma_indirect(address_space &space,UINT8 dma_ch)
451{
452   /*Helper to get out of the cycle*/
453   UINT8 job_done = 0;
454   /*temporary storage for the transfer data*/
455   UINT32 tmp_src;
456   UINT32 indirect_src,indirect_dst;
457   INT32 indirect_size;
458   UINT32 total_size = 0;
459
460   DnMV_1(dma_ch);
461
462   m_scu.index[dma_ch] = m_scu.dst[dma_ch];
463
464   do{
465      tmp_src = m_scu.index[dma_ch];
466
467      indirect_size = space.read_dword(m_scu.index[dma_ch]);
468      indirect_src  = space.read_dword(m_scu.index[dma_ch]+8);
469      indirect_dst  = space.read_dword(m_scu.index[dma_ch]+4);
470
471      /*Indirect Mode end factor*/
472      if(indirect_src & 0x80000000)
473         job_done = 1;
474
475      if(m_scu.src_add[dma_ch] == 0 || (m_scu.dst_add[dma_ch] != 2))
476      {
477         if(LOG_SCU) printf("DMA lv %d indirect mode transfer START\n"
478                        "Index %08x Start %08x End %08x Size %04x\n",dma_ch,tmp_src,indirect_src,indirect_dst,indirect_size);
479         if(LOG_SCU) printf("Start Add %04x Destination Add %04x\n",m_scu.src_add[dma_ch],m_scu.dst_add[dma_ch]);
480      }
481
482      indirect_src &=0x07ffffff;
483      indirect_dst &=0x07ffffff;
484      indirect_size &= ((dma_ch == 0) ? 0xfffff : 0x3ffff); //TODO: Guardian Heroes sets up a 0x23000 transfer for the FMV?
485
486      if(indirect_size == 0) { indirect_size = (dma_ch == 0) ? 0x00100000 : 0x2000; }
487
488      {
489         int i;
490         UINT8  src_shift;
491
492         src_shift = ((indirect_src & 2) >> 1) ^ 1;
493
494         for (i = 0; i < indirect_size;i+=2)
495         {
496            scu_single_transfer(space,indirect_src,indirect_dst,&src_shift);
497
498            if(src_shift)
499               indirect_src+=m_scu.src_add[dma_ch];
500
501            indirect_dst+= (WORK_RAM_H(indirect_dst)) ? 2 : m_scu.dst_add[dma_ch];
502         }
503      }
504
505      /* Guess: Size + data acquire (1 cycle for src/dst/size) */
506      total_size += indirect_size + 3*4;
507
508      //if(DRUP(0)) space.write_dword(tmp_src+8,m_scu.src[0]|job_done ? 0x80000000 : 0);
509      //if(DWUP(0)) space.write_dword(tmp_src+4,m_scu.dst[0]);
510
511      m_scu.index[dma_ch] = tmp_src+0xc;
512
513   }while(job_done == 0);
514
515   {
516      /*TODO: change DMA into DRQ model. Timing is a guess.  */
517      switch(dma_ch)
518      {
519         case 0: machine().scheduler().timer_set(m_maincpu->cycles_to_attotime(total_size/4), timer_expired_delegate(FUNC(saturn_state::dma_lv0_ended),this)); break;
520         case 1: machine().scheduler().timer_set(m_maincpu->cycles_to_attotime(total_size/4), timer_expired_delegate(FUNC(saturn_state::dma_lv1_ended),this)); break;
521         case 2: machine().scheduler().timer_set(m_maincpu->cycles_to_attotime(total_size/4), timer_expired_delegate(FUNC(saturn_state::dma_lv2_ended),this)); break;
522      }
523   }
524}
525
526
527/**************************************************************************************/
528
529WRITE16_MEMBER(saturn_state::saturn_soundram_w)
530{
531   //machine().scheduler().synchronize(); // force resync
532
533   COMBINE_DATA(&m_sound_ram[offset]);
534}
535
536READ16_MEMBER(saturn_state::saturn_soundram_r)
537{
538   //machine().scheduler().synchronize(); // force resync
539
540   return m_sound_ram[offset];
541}
542
543/* communication,SLAVE CPU acquires data from the MASTER CPU and triggers an irq.  */
544WRITE32_MEMBER(saturn_state::minit_w)
545{
546   //logerror("cpu %s (PC=%08X) MINIT write = %08x\n", space.device().tag(), space.device().safe_pc(),data);
547   machine().scheduler().boost_interleave(m_minit_boost_timeslice, attotime::from_usec(m_minit_boost));
548   machine().scheduler().trigger(1000);
549   machine().scheduler().synchronize(); // force resync
550   sh2_set_frt_input(m_slave, PULSE_LINE);
551}
552
553WRITE32_MEMBER(saturn_state::sinit_w)
554{
555   //logerror("cpu %s (PC=%08X) SINIT write = %08x\n", space.device().tag(), space.device().safe_pc(),data);
556   machine().scheduler().boost_interleave(m_sinit_boost_timeslice, attotime::from_usec(m_sinit_boost));
557   machine().scheduler().synchronize(); // force resync
558   sh2_set_frt_input(m_maincpu, PULSE_LINE);
559}
560
561/*
562TODO:
563Some games seems to not like either MAME's interleave system and/or SH-2 DRC, causing an hard crash.
564Reported games are:
565Blast Wind (before FMV)
566Choro Q Park (car selection)
567060311E4: MOV.L R14,@-SP ;R14 = 0x60ffba0 / R15 = 0x60ffba0
568060311E6: MOV SP,R14 ;R14 = 0x60ffba0 / R15 = 0x60ffb9c / [0x60ffb9c] <- 0x60ffba0
569060311E8: MOV.L @SP+,R14 ;R14 = 0x60ffb9c / R15 = 0x60ffb9c / [0x60ffb9c] -> R14
570060311EA: RTS ;R14 = 0x60ffba0 / R15 = 0x60ffba0
571060311EC: NOP
57206031734: MULS.W R9, R8 ;R14 = 0x60ffba0 / R15 = 0x60ffba0 / EA = 0x60311E4
573on DRC this becomes:
574R14 0x6031b78 (cause of the crash later on), R15 = 0x60ffba4 and EA = 0
575
576Shinrei Jusatsushi Taromaru (options menu)
577
578*/
579
580WRITE32_MEMBER(saturn_state::saturn_minit_w)
581{
582   //logerror("cpu %s (PC=%08X) MINIT write = %08x\n", space.device().tag(), space.device().safe_pc(),data);
583   if(m_fake_comms->read() & 1)
584      machine().scheduler().synchronize(); // force resync
585   else
586   {
587      machine().scheduler().boost_interleave(m_minit_boost_timeslice, attotime::from_usec(m_minit_boost));
588      machine().scheduler().trigger(1000);
589   }
590
591   sh2_set_frt_input(m_slave, PULSE_LINE);
592}
593
594WRITE32_MEMBER(saturn_state::saturn_sinit_w)
595{
596   //logerror("cpu %s (PC=%08X) SINIT write = %08x\n", space.device().tag(), space.device().safe_pc(),data);
597   if(m_fake_comms->read() & 1)
598      machine().scheduler().synchronize(); // force resync
599   else
600      machine().scheduler().boost_interleave(m_sinit_boost_timeslice, attotime::from_usec(m_sinit_boost));
601
602   sh2_set_frt_input(m_maincpu, PULSE_LINE);
603}
604
605
606READ8_MEMBER(saturn_state::saturn_backupram_r)
607{
608   if(!(offset & 1))
609      return 0; // yes, it makes sure the "holes" are there.
610
611   return m_backupram[offset >> 1] & 0xff;
612}
613
614WRITE8_MEMBER(saturn_state::saturn_backupram_w)
615{
616   if(!(offset & 1))
617      return;
618
619   m_backupram[offset >> 1] = data;
620}
621
622void saturn_state::scu_reset(void)
623{
624   m_scu.ism = 0xbfff;
625   m_scu.ist = 0;
626   m_scu.start_factor[0] = 7;
627   m_scu.start_factor[1] = 7;
628   m_scu.start_factor[2] = 7;
629   m_scu.status = 0;
630}
631
632TIMER_CALLBACK_MEMBER(saturn_state::stv_rtc_increment)
633{
634   static const UINT8 dpm[12] = { 0x31, 0x28, 0x31, 0x30, 0x31, 0x30, 0x31, 0x31, 0x30, 0x31, 0x30, 0x31 };
635   static int year_num, year_count;
636
637   /*
638       m_smpc.rtc_data[0] = DectoBCD(systime.local_time.year /100);
639       m_smpc.rtc_data[1] = DectoBCD(systime.local_time.year %100);
640       m_smpc.rtc_data[2] = (systime.local_time.weekday << 4) | (systime.local_time.month+1);
641       m_smpc.rtc_data[3] = DectoBCD(systime.local_time.mday);
642       m_smpc.rtc_data[4] = DectoBCD(systime.local_time.hour);
643       m_smpc.rtc_data[5] = DectoBCD(systime.local_time.minute);
644       m_smpc.rtc_data[6] = DectoBCD(systime.local_time.second);
645   */
646
647   m_smpc.rtc_data[6]++;
648
649   /* seconds from 9 -> 10*/
650   if((m_smpc.rtc_data[6] & 0x0f) >= 0x0a)         { m_smpc.rtc_data[6]+=0x10; m_smpc.rtc_data[6]&=0xf0; }
651   /* seconds from 59 -> 0 */
652   if((m_smpc.rtc_data[6] & 0xf0) >= 0x60)         { m_smpc.rtc_data[5]++;     m_smpc.rtc_data[6] = 0; }
653   /* minutes from 9 -> 10 */
654   if((m_smpc.rtc_data[5] & 0x0f) >= 0x0a)         { m_smpc.rtc_data[5]+=0x10; m_smpc.rtc_data[5]&=0xf0; }
655   /* minutes from 59 -> 0 */
656   if((m_smpc.rtc_data[5] & 0xf0) >= 0x60)         { m_smpc.rtc_data[4]++;     m_smpc.rtc_data[5] = 0; }
657   /* hours from 9 -> 10 */
658   if((m_smpc.rtc_data[4] & 0x0f) >= 0x0a)         { m_smpc.rtc_data[4]+=0x10; m_smpc.rtc_data[4]&=0xf0; }
659   /* hours from 23 -> 0 */
660   if((m_smpc.rtc_data[4] & 0xff) >= 0x24)             { m_smpc.rtc_data[3]++; m_smpc.rtc_data[2]+=0x10; m_smpc.rtc_data[4] = 0; }
661   /* week day name sunday -> monday */
662   if((m_smpc.rtc_data[2] & 0xf0) >= 0x70)             { m_smpc.rtc_data[2]&=0x0f; }
663   /* day number 9 -> 10 */
664   if((m_smpc.rtc_data[3] & 0x0f) >= 0x0a)             { m_smpc.rtc_data[3]+=0x10; m_smpc.rtc_data[3]&=0xf0; }
665
666   // year BCD to dec conversion (for the leap year stuff)
667   {
668      year_num = (m_smpc.rtc_data[1] & 0xf);
669
670      for(year_count = 0; year_count < (m_smpc.rtc_data[1] & 0xf0); year_count += 0x10)
671         year_num += 0xa;
672
673      year_num += (m_smpc.rtc_data[0] & 0xf)*0x64;
674
675      for(year_count = 0; year_count < (m_smpc.rtc_data[0] & 0xf0); year_count += 0x10)
676         year_num += 0x3e8;
677   }
678
679   /* month +1 check */
680   /* the RTC have a range of 1980 - 2100, so we don't actually need to support the leap year special conditions */
681   if(((year_num % 4) == 0) && (m_smpc.rtc_data[2] & 0xf) == 2)
682   {
683      if((m_smpc.rtc_data[3] & 0xff) >= dpm[(m_smpc.rtc_data[2] & 0xf)-1]+1+1)
684         { m_smpc.rtc_data[2]++; m_smpc.rtc_data[3] = 0x01; }
685   }
686   else if((m_smpc.rtc_data[3] & 0xff) >= dpm[(m_smpc.rtc_data[2] & 0xf)-1]+1){ m_smpc.rtc_data[2]++; m_smpc.rtc_data[3] = 0x01; }
687   /* year +1 check */
688   if((m_smpc.rtc_data[2] & 0x0f) > 12)                { m_smpc.rtc_data[1]++;  m_smpc.rtc_data[2] = (m_smpc.rtc_data[2] & 0xf0) | 0x01; }
689   /* year from 9 -> 10 */
690   if((m_smpc.rtc_data[1] & 0x0f) >= 0x0a)             { m_smpc.rtc_data[1]+=0x10; m_smpc.rtc_data[1]&=0xf0; }
691   /* year from 99 -> 100 */
692   if((m_smpc.rtc_data[1] & 0xf0) >= 0xa0)             { m_smpc.rtc_data[0]++; m_smpc.rtc_data[1] = 0; }
693
694   // probably not SO precise, here just for reference ...
695   /* year from 999 -> 1000 */
696   //if((m_smpc.rtc_data[0] & 0x0f) >= 0x0a)               { m_smpc.rtc_data[0]+=0x10; m_smpc.rtc_data[0]&=0xf0; }
697   /* year from 9999 -> 0 */
698   //if((m_smpc.rtc_data[0] & 0xf0) >= 0xa0)               { m_smpc.rtc_data[0] = 0; } //roll over
699}
700
701/* Official documentation says that the "RESET/TAS opcodes aren't supported", but Out Run definitely contradicts with it.
702   Since that m68k can't reset itself via the RESET opcode I suppose that the SMPC actually do it by reading an i/o
703   connected to this opcode. */
704void saturn_state::m68k_reset_callback(device_t *device)
705{
706   saturn_state *state = device->machine().driver_data<saturn_state>();
707   device->machine().scheduler().timer_set(attotime::from_usec(100), timer_expired_delegate(FUNC(saturn_state::smpc_audio_reset_line_pulse), state));
708
709   printf("m68k RESET opcode triggered\n");
710}
711
712void scsp_irq(device_t *device, int irq)
713{
714   saturn_state *state = device->machine().driver_data<saturn_state>();
715
716   // don't bother the 68k if it's off
717   if (!state->m_en_68k)
718   {
719      return;
720   }
721
722   if (irq > 0)
723   {
724      state->m_scsp_last_line = irq;
725      device->machine().device("audiocpu")->execute().set_input_line(irq, ASSERT_LINE);
726   }
727   else if (irq < 0)
728   {
729      device->machine().device("audiocpu")->execute().set_input_line(-irq, CLEAR_LINE);
730   }
731   else
732   {
733      device->machine().device("audiocpu")->execute().set_input_line(state->m_scsp_last_line, CLEAR_LINE);
734   }
735}
736
737WRITE_LINE_MEMBER(saturn_state::scsp_to_main_irq)
738{
739   if(state)
740   {
741      if(!(m_scu.ism & IRQ_SOUND_REQ))
742      {
743         m_maincpu->set_input_line_and_vector(9, HOLD_LINE, 0x46);
744         scu_do_transfer(5);
745      }
746      else
747         m_scu.ist |= (IRQ_SOUND_REQ);
748   }
749}
750
751
752
753/*
754(Preliminary) explanation about this:
755VBLANK-OUT is used at the start of the vblank period.It also sets the timer zero
756variable to 0.
757If the Timer Compare register is zero too,the Timer 0 irq is triggered.
758
759HBLANK-IN is used at the end of each scanline except when in VBLANK-IN/OUT periods.
760
761The timer 0 is also incremented by one at each HBLANK and checked with the value
762of the Timer Compare register;if equal,the timer 0 irq is triggered here too.
763Notice that the timer 0 compare register can be more than the VBLANK maximum range,in
764this case the timer 0 irq is simply never triggered.This is a known Sega Saturn/ST-V "bug".
765
766VBLANK-IN is used at the end of the vblank period.
767
768SCU register[36] is the timer zero compare register.
769SCU register[40] is for IRQ masking.
770
771TODO:
772- VDP1 timing and CEF emulation isn't accurate at all.
773*/
774
775
776TIMER_DEVICE_CALLBACK_MEMBER(saturn_state::saturn_scanline)
777{
778   int scanline = param;
779   int y_step,vblank_line;
780
781   vblank_line = get_vblank_start_position();
782   y_step = get_ystep_count();
783
784   //popmessage("%08x %d T0 %d T1 %d %08x",m_scu.ism ^ 0xffffffff,max_y,m_scu_regs[36],m_scu_regs[37],m_scu_regs[38]);
785
786   if(scanline == (0)*y_step)
787   {
788      video_update_vdp1();
789
790      if(STV_VDP1_VBE)
791         m_vdp1.framebuffer_clear_on_next_frame = 1;
792
793      if(!(m_scu.ism & IRQ_VDP1_END))
794      {
795         m_maincpu->set_input_line_and_vector(0x2, HOLD_LINE, 0x4d);
796         scu_do_transfer(6);
797      }
798      else
799         m_scu.ist |= (IRQ_VDP1_END);
800   }
801
802   if(scanline == 0*y_step)
803   {
804      if(!(m_scu.ism & IRQ_VBLANK_OUT))
805      {
806         m_maincpu->set_input_line_and_vector(0xe, HOLD_LINE, 0x41);
807         scu_do_transfer(1);
808      }
809      else
810         m_scu.ist |= (IRQ_VBLANK_OUT);
811
812   }
813   else if(scanline == vblank_line*y_step)
814   {
815      if(!(m_scu.ism & IRQ_VBLANK_IN))
816      {
817         m_maincpu->set_input_line_and_vector(0xf, HOLD_LINE ,0x40);
818         scu_do_transfer(0);
819      }
820      else
821         m_scu.ist |= (IRQ_VBLANK_IN);
822   }
823   else if((scanline % y_step) == 0 && scanline < vblank_line*y_step)
824   {
825      if(!(m_scu.ism & IRQ_HBLANK_IN))
826      {
827         m_maincpu->set_input_line_and_vector(0xd, HOLD_LINE, 0x42);
828         scu_do_transfer(2);
829      }
830      else
831         m_scu.ist |= (IRQ_HBLANK_IN);
832   }
833
834   if(scanline == (m_scu_regs[36] & 0x3ff)*y_step)
835   {
836      if(!(m_scu.ism & IRQ_TIMER_0))
837      {
838         m_maincpu->set_input_line_and_vector(0xc, HOLD_LINE, 0x43 );
839         scu_do_transfer(3);
840      }
841      else
842         m_scu.ist |= (IRQ_TIMER_0);
843   }
844
845   /* TODO: this isn't completely correct */
846   if(m_scu_regs[38] & 0x1)
847   {
848      if((!(m_scu_regs[38] & 0x100) && (scanline % y_step) == 0) ||
849         ((m_scu_regs[38] & 0x100) && (scanline == (m_scu_regs[36] & 0x3ff)*y_step)))
850      {
851         if(!(m_scu.ism & IRQ_TIMER_1))
852         {
853            m_maincpu->set_input_line_and_vector(0xb, HOLD_LINE, 0x44 );
854            scu_do_transfer(4);
855         }
856         else
857            m_scu.ist |= (IRQ_TIMER_1);
858      }
859   }
860}
861
862TIMER_DEVICE_CALLBACK_MEMBER(saturn_state::saturn_slave_scanline )
863{
864   int scanline = param;
865   int y_step,vblank_line;
866
867   vblank_line = get_vblank_start_position();
868   y_step = get_ystep_count();
869
870   if(scanline == vblank_line*y_step)
871      m_slave->set_input_line_and_vector(0x6, HOLD_LINE, 0x43);
872   else if((scanline % y_step) == 0 && scanline < vblank_line*y_step)
873      m_slave->set_input_line_and_vector(0x2, HOLD_LINE, 0x41);
874}
875
876static const gfx_layout tiles8x8x4_layout =
877{
878   8,8,
879   0x100000/(32*8/8),
880   4,
881   { 0, 1, 2, 3 },
882   { 0, 4, 8, 12, 16, 20, 24, 28 },
883   { 0*32, 1*32, 2*32, 3*32, 4*32, 5*32, 6*32, 7*32 },
884   32*8
885};
886
887static const gfx_layout tiles16x16x4_layout =
888{
889   16,16,
890   0x100000/(32*32/8),
891   4,
892   { 0, 1, 2, 3 },
893   { 0, 4, 8, 12, 16, 20, 24, 28,
894      32*8+0, 32*8+4, 32*8+8, 32*8+12, 32*8+16, 32*8+20, 32*8+24, 32*8+28,
895
896      },
897   { 0*32, 1*32, 2*32, 3*32, 4*32, 5*32, 6*32, 7*32,
898      32*16, 32*17,32*18, 32*19,32*20,32*21,32*22,32*23
899
900      },
901   32*32
902};
903
904static const gfx_layout tiles8x8x8_layout =
905{
906   8,8,
907   0x100000/(32*8/8),
908   8,
909   { 0, 1, 2, 3, 4, 5, 6, 7 },
910   { 0, 8, 16, 24, 32, 40, 48, 56 },
911   { 0*64, 1*64, 2*64, 3*64, 4*64, 5*64, 6*64, 7*64 },
912   32*8    /* really 64*8, but granularity is 32 bytes */
913};
914
915static const gfx_layout tiles16x16x8_layout =
916{
917   16,16,
918   0x100000/(64*16/8),
919   8,
920   { 0, 1, 2, 3, 4, 5, 6, 7 },
921   { 0, 8, 16, 24, 32, 40, 48, 56,
922   64*8+0, 65*8, 66*8, 67*8, 68*8, 69*8, 70*8, 71*8
923
924   },
925   { 0*64, 1*64, 2*64, 3*64, 4*64, 5*64, 6*64, 7*64,
926   64*16, 64*17, 64*18, 64*19, 64*20, 64*21, 64*22, 64*23
927   },
928   64*16   /* really 128*16, but granularity is 32 bytes */
929};
930
931
932
933
934GFXDECODE_START( stv )
935   GFXDECODE_ENTRY( NULL, 0, tiles8x8x4_layout,   0x00, (0x80*(2+1))  )
936   GFXDECODE_ENTRY( NULL, 0, tiles16x16x4_layout, 0x00, (0x80*(2+1))  )
937   GFXDECODE_ENTRY( NULL, 0, tiles8x8x8_layout,   0x00, (0x08*(2+1))  )
938   GFXDECODE_ENTRY( NULL, 0, tiles16x16x8_layout, 0x00, (0x08*(2+1))  )
939GFXDECODE_END
Property changes on: trunk/src/emu/machine/saturn.c
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/mess/drivers/saturn.c
r0r21331
1/**************************************************************************************************
2
3    Sega Saturn & Sega ST-V (Sega Titan Video) HW (c) 1994 Sega
4
5    Driver by David Haywood, Angelo Salese, Olivier Galibert & Mariusz Wojcieszek
6    SCSP driver provided by R.Belmont, based on ElSemi's SCSP sound chip emulator
7    CD Block driver provided by ANY, based on sthief original emulator
8    Many thanks to Guru, Fabien, Runik and Charles MacDonald for the help given.
9
10===================================================================================================
11
12Notes:
13-To enter into an Advanced Test Mode,keep pressed the Test Button (F2) on the start-up.
14-Memo: Some tests done on the original & working PCB,to be implemented:
15 -The AD-Stick returns 0x00 or a similar value.
16 -The Ports E,F & G must return 0xff
17
18TODO:
19(Main issues)
20- decap the SH-1, used for CD block (needed especially for Sega Saturn)
21- IRQs: some games have some issues with timing accurate IRQs, check/fix all of them.
22- The Cart-Dev mode hangs even with the -dev bios,I would like to see what it does on the real HW.
23- IC13 games on the dev bios doesn't even load the cartridge / crashes the emulation at start-up,
24  rom rearrange needed?
25- SCU DSP still has its fair share of issues, it also needs to be converted to CPU structure;
26- Add the RS232c interface (serial port), needed by fhboxers (accesses some ports in the a-bus dummy range).
27- Video emulation is nowhere near perfection.
28- Reimplement the idle skip if possible.
29- Properly emulate the protection chips, used by several games (check stvprot.c for more info)
30- Move SCU device into its respective file;
31- Split ST-V and Saturn files properly;
32
33(per-game issues)
34- stress: accesses the Sound Memory Expansion Area (0x05a80000-0x05afffff), unknown purpose;
35
36- smleague / finlarch: it randomly hangs / crashes,it works if you use a ridiculous MCFG_INTERLEAVE number,might need strict
37  SH-2 synching or it's actually a m68k comms issue.
38
39- groovef: ugly back screen color, caused by incorrect usage of the Color Calculation function.
40
41- myfairld: Apparently this game gives a black screen (either test mode and in-game mode),but let it wait for about
42  10 seconds and the game will load everything. This is because of a hellishly slow m68k sub-routine located at 54c2.
43  Likely to not be a bug but an in-game design issue.
44
45- danchih / danchiq: currently hangs randomly (regression).
46
47- batmanfr: Missing sound,caused by an extra ADSP chip which is on the cart.The CPU is a
48  ADSP-2181,and it's the same used by NBA Jam Extreme (ZN game).
49
50- vfremix: when you play as Akira, there is a problem with third match: game doesn't upload all textures
51  and tiles and doesn't enable display, although gameplay is normal - wait a while to get back
52  to title screen after losing a match
53
54- vfremix: various problems with SCU DSP: Jeffry causes a black screen hang. Akira's kick sometimes
55  sends the opponent out of the ring from whatever position.
56
57
58****************************************************************************************************/
59
60#include "emu.h"
61#include "cpu/m68000/m68000.h"
62#include "machine/eeprom.h"
63#include "cpu/sh2/sh2.h"
64#include "machine/scudsp.h"
65#include "sound/scsp.h"
66#include "sound/cdda.h"
67#include "machine/smpc.h"
68#include "includes/stv.h"
69#include "imagedev/chd_cd.h"
70#include "imagedev/cartslot.h"
71#include "coreutil.h"
72
73
74
75/* TODO: if you change the driver configuration then NVRAM contents gets screwed, needs mods in MAME framework */
76static NVRAM_HANDLER(saturn)
77{
78   saturn_state *state = machine.driver_data<saturn_state>();
79   static const UINT32 BUP_SIZE = 32*1024;
80   static const UINT32 EBUP_SIZE = 0;//0x100000; // TODO: can't support more than 8 Mbit
81   UINT8 backup_file[(BUP_SIZE)+EBUP_SIZE+4];
82   static const UINT8 init[16] =
83   {
84      'B', 'a', 'c', 'k', 'U', 'p', 'R', 'a', 'm', ' ', 'F', 'o', 'r', 'm', 'a', 't'
85   };
86   UINT32 i;
87
88   if (read_or_write)
89   {
90      for(i=0;i<BUP_SIZE;i++)
91         backup_file[i] = state->m_backupram[i];
92      #if 0
93      for(i=0;i<EBUP_SIZE;i++)
94         backup_file[i+BUP_SIZE] = state->m_cart_backupram[i];
95      #endif
96      for(i=0;i<4;i++)
97         backup_file[i+(BUP_SIZE)+EBUP_SIZE] = state->m_smpc.SMEM[i];
98
99      file->write(backup_file, (BUP_SIZE)+EBUP_SIZE+4);
100   }
101   else
102   {
103      if (file)
104      {
105         file->read(backup_file, (BUP_SIZE)+EBUP_SIZE+4);
106
107         for(i=0;i<BUP_SIZE;i++)
108            state->m_backupram[i] = backup_file[i];
109         #if 0
110         for(i=0;i<EBUP_SIZE;i++)
111            state->m_cart_backupram[i] = backup_file[i+BUP_SIZE];
112         #endif
113         for(i=0;i<4;i++)
114            state->m_smpc.SMEM[i] = backup_file[i+BUP_SIZE+EBUP_SIZE];
115      }
116      else
117      {
118         UINT8 j;
119         memset(state->m_backupram, 0, BUP_SIZE);
120         for (i = 0; i < 4; i++)
121         {
122            for(j=0;j<16;j++)
123               state->m_backupram[i*16+j] = init[j];
124         }
125         #if 0
126         memset(state->m_cart_backupram, 0, EBUP_SIZE);
127         for (i = 0; i < 32; i++)
128         {
129            for(j=0;j<16;j++)
130               state->m_cart_backupram[i*16+j] = init[j];
131         }
132         #endif
133         memset(state->m_smpc.SMEM, 0, 4); // TODO: default for each region
134      }
135   }
136}
137
138READ8_MEMBER(saturn_state::saturn_cart_type_r)
139{
140   const int cart_ram_header[7] = { 0xff, 0x21, 0x22, 0x23, 0x24, 0x5a, 0x5c };
141
142   return cart_ram_header[m_cart_type];
143}
144
145/* TODO: Bug! accesses this one, if returning 0 the SH-2 hard-crashes. Might be an actual bug with the CD block. */
146READ32_HANDLER( saturn_state::abus_dummy_r )
147{
148   logerror("A-Bus Dummy access %08x\n",offset*4);
149   return -1;
150}
151
152static ADDRESS_MAP_START( saturn_mem, AS_PROGRAM, 32, saturn_state )
153   AM_RANGE(0x00000000, 0x0007ffff) AM_ROM AM_SHARE("share6")  // bios
154   AM_RANGE(0x00100000, 0x0010007f) AM_READWRITE8(saturn_SMPC_r, saturn_SMPC_w,0xffffffff)
155   AM_RANGE(0x00180000, 0x0018ffff) AM_READWRITE8(saturn_backupram_r, saturn_backupram_w,0xffffffff) AM_SHARE("share1")
156   AM_RANGE(0x00200000, 0x002fffff) AM_RAM AM_MIRROR(0x20100000) AM_SHARE("workram_l")
157   AM_RANGE(0x01000000, 0x017fffff) AM_WRITE(saturn_minit_w)
158   AM_RANGE(0x01800000, 0x01ffffff) AM_WRITE(saturn_sinit_w)
159   AM_RANGE(0x02000000, 0x023fffff) AM_ROM AM_SHARE("share7") AM_REGION("maincpu", 0x80000)    // cartridge space
160//  AM_RANGE(0x02400000, 0x027fffff) AM_RAM //cart RAM area, dynamically allocated
161//  AM_RANGE(0x04000000, 0x047fffff) AM_RAM //backup RAM area, dynamically allocated
162   AM_RANGE(0x04fffffc, 0x04ffffff) AM_READ8(saturn_cart_type_r,0x000000ff)
163   AM_RANGE(0x05000000, 0x057fffff) AM_READ(abus_dummy_r)
164   AM_RANGE(0x05800000, 0x0589ffff) AM_READWRITE(stvcd_r, stvcd_w)
165   /* Sound */
166   AM_RANGE(0x05a00000, 0x05a7ffff) AM_READWRITE16(saturn_soundram_r, saturn_soundram_w,0xffffffff)
167   AM_RANGE(0x05b00000, 0x05b00fff) AM_DEVREADWRITE16_LEGACY("scsp", scsp_r, scsp_w, 0xffffffff)
168   /* VDP1 */
169   AM_RANGE(0x05c00000, 0x05c7ffff) AM_READWRITE(saturn_vdp1_vram_r, saturn_vdp1_vram_w)
170   AM_RANGE(0x05c80000, 0x05cbffff) AM_READWRITE(saturn_vdp1_framebuffer0_r, saturn_vdp1_framebuffer0_w)
171   AM_RANGE(0x05d00000, 0x05d0001f) AM_READWRITE16(saturn_vdp1_regs_r, saturn_vdp1_regs_w,0xffffffff)
172   AM_RANGE(0x05e00000, 0x05e7ffff) AM_MIRROR(0x80000) AM_READWRITE(saturn_vdp2_vram_r, saturn_vdp2_vram_w)
173   AM_RANGE(0x05f00000, 0x05f7ffff) AM_READWRITE(saturn_vdp2_cram_r, saturn_vdp2_cram_w)
174   AM_RANGE(0x05f80000, 0x05fbffff) AM_READWRITE16(saturn_vdp2_regs_r, saturn_vdp2_regs_w,0xffffffff)
175   AM_RANGE(0x05fe0000, 0x05fe00cf) AM_READWRITE(saturn_scu_r, saturn_scu_w)
176   AM_RANGE(0x06000000, 0x060fffff) AM_RAM AM_MIRROR(0x21f00000) AM_SHARE("workram_h")
177   AM_RANGE(0x20000000, 0x2007ffff) AM_ROM AM_SHARE("share6")  // bios mirror
178   AM_RANGE(0x22000000, 0x24ffffff) AM_ROM AM_SHARE("share7")  // cart mirror
179   AM_RANGE(0x45000000, 0x46ffffff) AM_WRITENOP
180   AM_RANGE(0x60000000, 0x600003ff) AM_WRITENOP // cache address array
181   AM_RANGE(0xc0000000, 0xc00007ff) AM_RAM // cache data array, Dragon Ball Z sprites relies on this
182ADDRESS_MAP_END
183
184static ADDRESS_MAP_START( sound_mem, AS_PROGRAM, 16, saturn_state )
185   AM_RANGE(0x000000, 0x0fffff) AM_RAM AM_SHARE("sound_ram")
186   AM_RANGE(0x100000, 0x100fff) AM_DEVREADWRITE_LEGACY("scsp", scsp_r, scsp_w)
187ADDRESS_MAP_END
188
189
190/* keyboard code */
191/* TODO: needs a proper keycode table */
192INPUT_CHANGED_MEMBER(saturn_state::key_stroke)
193{
194   if(newval && !oldval)
195   {
196      m_keyb.data = ((UINT8)(FPTR)(param) & 0xff);
197      m_keyb.status |= 8;
198   }
199
200   if(oldval && !newval)
201   {
202      //m_keyb.status &= ~8;
203      m_keyb.data = 0;
204   }
205}
206
207/* Note: unused bits must stay high, Bug 2 relies on this. */
208#define SATURN_PAD_P1(_mask_, _val_) \
209   PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
210   PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
211   PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
212   PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
213   PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
214   PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("P1 A") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
215   PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("P1 C") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
216   PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("P1 B") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
217   PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_BUTTON8 ) PORT_NAME("P1 R") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
218   PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("P1 X") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
219   PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_NAME("P1 Y") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
220   PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_NAME("P1 Z") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
221   PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_BUTTON7 ) PORT_NAME("P1 L") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
222   PORT_BIT( 0x0007, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_)
223
224#define SATURN_PAD_P2(_mask_, _val_) \
225   PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
226   PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
227   PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
228   PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
229   PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
230   PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("P2 A") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
231   PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("P2 C") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
232   PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("P2 B") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
233   PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_BUTTON8 ) PORT_NAME("P2 R") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
234   PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("P2 X") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
235   PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_NAME("P2 Y") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
236   PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_NAME("P2 Z") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
237   PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_BUTTON7 ) PORT_NAME("P2 L") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
238   PORT_BIT( 0x0007, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_)
239
240#define MD_PAD_P1(_mask_, _val_) \
241   PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
242   PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
243   PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
244   PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
245   PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
246   PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("P1 A") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
247   PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("P1 C") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
248   PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("P1 B") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
249   PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_BUTTON8 ) PORT_NAME("P1 Mode") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
250   PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("P1 X") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
251   PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_NAME("P1 Y") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
252   PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_NAME("P1 Z") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
253   PORT_BIT( 0x000f, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) //read '1' when direct mode is polled
254
255#define MD_PAD_P2(_mask_, _val_) \
256   PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
257   PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
258   PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
259   PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
260   PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
261   PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("P2 A") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
262   PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("P2 C") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
263   PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("P2 B") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
264   PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_BUTTON8 ) PORT_NAME("P2 Mode") PORT_PLAYER(2)  PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
265   PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("P2 X") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
266   PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_NAME("P2 Y") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
267   PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_NAME("P2 Z") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
268   PORT_BIT( 0x000f, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) //read '1' when direct mode is polled
269
270#define SATURN_KEYBOARD PORT_CONDITION("INPUT_TYPE", 0x0f, EQUALS, 0x05)
271
272INPUT_CHANGED_MEMBER(saturn_state::nmi_reset)
273{
274   /* TODO: correct? */
275   if(!m_NMI_reset)
276      return;
277
278   /* TODO: NMI doesn't stay held on SH-2 core so we can't use ASSERT_LINE/CLEAR_LINE with that yet */
279   if(newval)
280      m_maincpu->set_input_line(INPUT_LINE_NMI, PULSE_LINE);
281}
282
283INPUT_CHANGED_MEMBER(saturn_state::tray_open)
284{
285   if(newval)
286      stvcd_set_tray_open();
287}
288
289INPUT_CHANGED_MEMBER(saturn_state::tray_close)
290{
291   if(newval)
292      stvcd_set_tray_close();
293}
294
295static INPUT_PORTS_START( saturn )
296   PORT_START("RESET") /* hardwired buttons */
297   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, nmi_reset,0) PORT_NAME("Reset Button")
298   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, tray_open,0) PORT_NAME("Tray Open Button")
299   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, tray_close,0) PORT_NAME("Tray Close")
300
301   PORT_START("JOY1")
302   SATURN_PAD_P1(0x0f, 0)
303
304   PORT_START("JOY2")
305   SATURN_PAD_P2(0xf0, 0)
306
307   /* TODO: there's no info about the keycode used on Saturn keyboard, following is trial & error with Game Basic software */
308   PORT_START("KEY0") // 0x00 - 0x07
309   PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_UNUSED) SATURN_KEYBOARD
310   PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F1") /*PORT_CODE(KEYCODE_F1)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x01) PORT_PLAYER(1) SATURN_KEYBOARD
311   PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("0-3") /*PORT_CODE(KEYCODE_2) PORT_CHAR('2')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x02) PORT_PLAYER(1) SATURN_KEYBOARD
312   PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F2") /*PORT_CODE(KEYCODE_F2)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x03) PORT_PLAYER(1) SATURN_KEYBOARD // RUN
313   PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F3") /*PORT_CODE(KEYCODE_F3)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x04) PORT_PLAYER(1) SATURN_KEYBOARD // LIST
314   PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F4") /*PORT_CODE(KEYCODE_F4)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x05) PORT_PLAYER(1) SATURN_KEYBOARD // EDIT
315   PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F5") /*PORT_CODE(KEYCODE_F5)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x06) PORT_PLAYER(1) SATURN_KEYBOARD
316   PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("CLR SCR") PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x07) PORT_PLAYER(1) SATURN_KEYBOARD
317
318   PORT_START("KEY1") // 0x08 - 0x0f
319   PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("1-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x08) PORT_PLAYER(1) SATURN_KEYBOARD
320   PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F6") /*PORT_CODE(KEYCODE_F6)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x09) PORT_PLAYER(1) SATURN_KEYBOARD
321   PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F7") /*PORT_CODE(KEYCODE_F7)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x0a) PORT_PLAYER(1) SATURN_KEYBOARD
322   PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F8") /*PORT_CODE(KEYCODE_F8)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x0b) PORT_PLAYER(1) SATURN_KEYBOARD
323   PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F9") /*PORT_CODE(KEYCODE_F9)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x0c) PORT_PLAYER(1) SATURN_KEYBOARD // LIST again
324   PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("1-6") /*PORT_CODE(KEYCODE_5) PORT_CHAR('5')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x0d) PORT_PLAYER(1) SATURN_KEYBOARD
325   PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("1-7") /*PORT_CODE(KEYCODE_6) PORT_CHAR('6')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x0e) PORT_PLAYER(1) SATURN_KEYBOARD
326   PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("1-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x0f) PORT_PLAYER(1) SATURN_KEYBOARD
327
328   PORT_START("KEY2") // 0x10 - 0x17
329   PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("2-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x10) PORT_PLAYER(1) SATURN_KEYBOARD
330   PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("2-2") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x11) PORT_PLAYER(1) SATURN_KEYBOARD
331   /* TODO: break codes! */
332   PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("SHIFT") /*PORT_CODE(KEYCODE_2) PORT_CHAR('2')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x12) PORT_PLAYER(1) SATURN_KEYBOARD
333   PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("KANA SHIFT") /*PORT_CODE(KEYCODE_3) PORT_CHAR('3')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x13) PORT_PLAYER(1) SATURN_KEYBOARD
334   PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("(special keys)") /*PORT_CODE(KEYCODE_4) PORT_CHAR('4')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x14) PORT_PLAYER(1) SATURN_KEYBOARD
335
336   PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Q") PORT_CODE(KEYCODE_Q) PORT_CHAR('Q') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x15) PORT_PLAYER(1) SATURN_KEYBOARD
337   PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("1") PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x16) PORT_PLAYER(1) SATURN_KEYBOARD
338   PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("2-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x17) PORT_PLAYER(1) SATURN_KEYBOARD
339
340   PORT_START("KEY3") // 0x18 - 0x1f
341   PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("3-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x18) PORT_PLAYER(1) SATURN_KEYBOARD
342   PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("3-2") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x19) PORT_PLAYER(1) SATURN_KEYBOARD
343   PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Z") PORT_CODE(KEYCODE_Z) PORT_CHAR('Z') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x1a) PORT_PLAYER(1) SATURN_KEYBOARD
344   PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("S") PORT_CODE(KEYCODE_S) PORT_CHAR('S') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x1b) PORT_PLAYER(1) SATURN_KEYBOARD
345   PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("A") PORT_CODE(KEYCODE_A) PORT_CHAR('A') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x1c) PORT_PLAYER(1) SATURN_KEYBOARD
346   PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("W") PORT_CODE(KEYCODE_W) PORT_CHAR('W') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x1d) PORT_PLAYER(1) SATURN_KEYBOARD
347   PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("2") PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x1e) PORT_PLAYER(1) SATURN_KEYBOARD
348   PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("3-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x1f) PORT_PLAYER(1) SATURN_KEYBOARD
349
350   PORT_START("KEY4") // 0x20 - 0x27
351   PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("4-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x20) PORT_PLAYER(1) SATURN_KEYBOARD
352   PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("C") PORT_CODE(KEYCODE_C) PORT_CHAR('C') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x21) PORT_PLAYER(1) SATURN_KEYBOARD
353   PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("X") PORT_CODE(KEYCODE_X) PORT_CHAR('X') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x22) PORT_PLAYER(1) SATURN_KEYBOARD
354   PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("D") PORT_CODE(KEYCODE_D) PORT_CHAR('D') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x23) PORT_PLAYER(1) SATURN_KEYBOARD
355   PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("E") PORT_CODE(KEYCODE_E) PORT_CHAR('E') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x24) PORT_PLAYER(1) SATURN_KEYBOARD
356   PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("4") PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x25) PORT_PLAYER(1) SATURN_KEYBOARD
357   PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("3") PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x26) PORT_PLAYER(1) SATURN_KEYBOARD
358   PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("4-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x27) PORT_PLAYER(1) SATURN_KEYBOARD
359
360   PORT_START("KEY5") // 0x28 - 0x2f
361   PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("5-1") /*PORT_CODE(KEYCODE_F) PORT_CHAR('F')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x28) PORT_PLAYER(1) SATURN_KEYBOARD // another F?
362   PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("SPACE") PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x29) PORT_PLAYER(1) SATURN_KEYBOARD
363   PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("V") PORT_CODE(KEYCODE_V) PORT_CHAR('V') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x2a) PORT_PLAYER(1) SATURN_KEYBOARD
364   PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F") PORT_CODE(KEYCODE_F) PORT_CHAR('F') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x2b) PORT_PLAYER(1) SATURN_KEYBOARD
365   PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("T") PORT_CODE(KEYCODE_T) PORT_CHAR('T') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x2c) PORT_PLAYER(1) SATURN_KEYBOARD
366   PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("R") PORT_CODE(KEYCODE_R) PORT_CHAR('R') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x2d) PORT_PLAYER(1) SATURN_KEYBOARD
367   PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("5") PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x2e) PORT_PLAYER(1) SATURN_KEYBOARD
368   PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("5-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x2f) PORT_PLAYER(1) SATURN_KEYBOARD
369
370   PORT_START("KEY6") // 0x30 - 0x37
371   PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("6-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x30) PORT_PLAYER(1) SATURN_KEYBOARD
372   PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("N") PORT_CODE(KEYCODE_N) PORT_CHAR('N') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x31) PORT_PLAYER(1) SATURN_KEYBOARD
373   PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("B") PORT_CODE(KEYCODE_B) PORT_CHAR('B') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x32) PORT_PLAYER(1) SATURN_KEYBOARD
374   PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("H") PORT_CODE(KEYCODE_H) PORT_CHAR('H') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x33) PORT_PLAYER(1) SATURN_KEYBOARD
375   PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("G") PORT_CODE(KEYCODE_G) PORT_CHAR('G') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x34) PORT_PLAYER(1) SATURN_KEYBOARD
376   PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Y") PORT_CODE(KEYCODE_Y) PORT_CHAR('Y') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x35) PORT_PLAYER(1) SATURN_KEYBOARD
377   PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("6") PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x36) PORT_PLAYER(1) SATURN_KEYBOARD
378   PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("6-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x37) PORT_PLAYER(1) SATURN_KEYBOARD
379
380   PORT_START("KEY7") // 0x38 - 0x3f
381   PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("7-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x38) PORT_PLAYER(1) SATURN_KEYBOARD
382   PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("7-2") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x39) PORT_PLAYER(1) SATURN_KEYBOARD
383   PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("M") PORT_CODE(KEYCODE_M) PORT_CHAR('M') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x3a) PORT_PLAYER(1) SATURN_KEYBOARD
384   PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("J") PORT_CODE(KEYCODE_J) PORT_CHAR('J') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x3b) PORT_PLAYER(1) SATURN_KEYBOARD
385   PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("U") PORT_CODE(KEYCODE_U) PORT_CHAR('U') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x3c) PORT_PLAYER(1) SATURN_KEYBOARD
386   PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("7") PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x3d) PORT_PLAYER(1) SATURN_KEYBOARD
387   PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("8") PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x3e) PORT_PLAYER(1) SATURN_KEYBOARD
388   PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("7-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x3f) PORT_PLAYER(1) SATURN_KEYBOARD
389
390   PORT_START("KEY8") // 0x40 - 0x47
391   PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("8-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x40) PORT_PLAYER(1) SATURN_KEYBOARD
392   PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME(",") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x41) PORT_PLAYER(1) SATURN_KEYBOARD
393   PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("K") PORT_CODE(KEYCODE_K) PORT_CHAR('K') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x42) PORT_PLAYER(1) SATURN_KEYBOARD
394   PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("I") PORT_CODE(KEYCODE_I) PORT_CHAR('I') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x43) PORT_PLAYER(1) SATURN_KEYBOARD
395   PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("O") PORT_CODE(KEYCODE_O) PORT_CHAR('O') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x44) PORT_PLAYER(1) SATURN_KEYBOARD
396   PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("0") PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x45) PORT_PLAYER(1) SATURN_KEYBOARD
397   PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("9") PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x46) PORT_PLAYER(1) SATURN_KEYBOARD
398   PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("8-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x47) PORT_PLAYER(1) SATURN_KEYBOARD
399
400   PORT_START("KEY9") // 0x48 - 0x4f
401   PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("9-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x48) PORT_PLAYER(1) SATURN_KEYBOARD
402   PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME(".") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x49) PORT_PLAYER(1) SATURN_KEYBOARD
403   PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("/") /*PORT_CODE(KEYCODE_2) PORT_CHAR('2')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x4a) PORT_PLAYER(1) SATURN_KEYBOARD
404   PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("L") PORT_CODE(KEYCODE_L) PORT_CHAR('L') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x4b) PORT_PLAYER(1) SATURN_KEYBOARD
405   PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME(";") /*PORT_CODE(KEYCODE_4) PORT_CHAR('4')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x4c) PORT_PLAYER(1) SATURN_KEYBOARD
406   PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("P") PORT_CODE(KEYCODE_P) PORT_CHAR('P') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x4d) PORT_PLAYER(1) SATURN_KEYBOARD
407   PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("- / =") PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x4e) PORT_PLAYER(1) SATURN_KEYBOARD
408   PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("9-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x4f) PORT_PLAYER(1) SATURN_KEYBOARD
409
410   PORT_START("KEYA") // 0x50 - 0x57
411   PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("A-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x50) PORT_PLAYER(1) SATURN_KEYBOARD
412   PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("\xC2\xA5") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x51) PORT_PLAYER(1) SATURN_KEYBOARD
413   PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME(":") /*PORT_CODE(KEYCODE_2) PORT_CHAR('2')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x52) PORT_PLAYER(1) SATURN_KEYBOARD
414   PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("A-4") /*PORT_CODE(KEYCODE_3) PORT_CHAR('3')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x53) PORT_PLAYER(1) SATURN_KEYBOARD
415   PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("@") /*PORT_CODE(KEYCODE_4) PORT_CHAR('4')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x54) PORT_PLAYER(1) SATURN_KEYBOARD
416   PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("^") /*PORT_CODE(KEYCODE_5) PORT_CHAR(0xd)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x55) PORT_PLAYER(1) SATURN_KEYBOARD
417   PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("A-7") /*PORT_CODE(KEYCODE_6) PORT_CHAR('6')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x56) PORT_PLAYER(1) SATURN_KEYBOARD
418   PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("A-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x57) PORT_PLAYER(1) SATURN_KEYBOARD
419
420   PORT_START("KEYB") // 0x58 - 0x5f
421   PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("B-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x58) PORT_PLAYER(1) SATURN_KEYBOARD
422   PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("B-2") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x59) PORT_PLAYER(1) SATURN_KEYBOARD
423   PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("ENTER") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(0x0d) PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x5a) PORT_PLAYER(1) SATURN_KEYBOARD
424   PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("[") /*PORT_CODE(KEYCODE_3) PORT_CHAR('3')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x5b) PORT_PLAYER(1) SATURN_KEYBOARD // {
425   PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("B-5") /*PORT_CODE(KEYCODE_4) PORT_CHAR('4')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x5c) PORT_PLAYER(1) SATURN_KEYBOARD
426   PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("]") /*PORT_CODE(KEYCODE_5) PORT_CHAR(0xd)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x5d) PORT_PLAYER(1) SATURN_KEYBOARD // }
427   PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("B-7") /*PORT_CODE(KEYCODE_6) PORT_CHAR('6')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x5e) PORT_PLAYER(1) SATURN_KEYBOARD
428   PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("B-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x5f) PORT_PLAYER(1) SATURN_KEYBOARD
429
430   PORT_START("KEYC") // 0x60 - 0x67
431   PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("C-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x60) PORT_PLAYER(1) SATURN_KEYBOARD
432   PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("C-2") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x61) PORT_PLAYER(1) SATURN_KEYBOARD
433   PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("C-3") /*PORT_CODE(KEYCODE_2) PORT_CHAR('2')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x62) PORT_PLAYER(1) SATURN_KEYBOARD
434   PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("C-4") /*PORT_CODE(KEYCODE_3) PORT_CHAR('3')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x63) PORT_PLAYER(1) SATURN_KEYBOARD
435   PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("C-5") /*PORT_CODE(KEYCODE_4) PORT_CHAR('4')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x64) PORT_PLAYER(1) SATURN_KEYBOARD
436   PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("C-6") /*PORT_CODE(KEYCODE_5) PORT_CHAR(0xd)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x65) PORT_PLAYER(1) SATURN_KEYBOARD
437   PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("BACKSPACE") PORT_CODE(KEYCODE_BACKSPACE) /* PORT_CHAR('6')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x66) PORT_PLAYER(1) SATURN_KEYBOARD
438   PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("C-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x67) PORT_PLAYER(1) SATURN_KEYBOARD
439
440   PORT_START("KEYD") // 0x68 - 0x6f
441   PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("D-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x68) PORT_PLAYER(1) SATURN_KEYBOARD
442   PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("D-2") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x69) PORT_PLAYER(1) SATURN_KEYBOARD
443   PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("D-3") /*PORT_CODE(KEYCODE_2) PORT_CHAR('2')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x6a) PORT_PLAYER(1) SATURN_KEYBOARD
444   PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("D-4") /*PORT_CODE(KEYCODE_3) PORT_CHAR('3')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x6b) PORT_PLAYER(1) SATURN_KEYBOARD
445   PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("D-5") /*PORT_CODE(KEYCODE_4) PORT_CHAR('4')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x6c) PORT_PLAYER(1) SATURN_KEYBOARD
446   PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("D-6") /*PORT_CODE(KEYCODE_5) PORT_CHAR(0xd)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x6d) PORT_PLAYER(1) SATURN_KEYBOARD
447   PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("D-7") /*PORT_CODE(KEYCODE_6) PORT_CHAR('6')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x6e) PORT_PLAYER(1) SATURN_KEYBOARD
448   PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("D-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x6f) PORT_PLAYER(1) SATURN_KEYBOARD
449
450   PORT_START("KEYE") // 0x70 - 0x77
451   PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("E-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x70) PORT_PLAYER(1) SATURN_KEYBOARD
452   PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("E-2") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x71) PORT_PLAYER(1) SATURN_KEYBOARD
453   PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("E-3") /*PORT_CODE(KEYCODE_2) PORT_CHAR('2')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x72) PORT_PLAYER(1) SATURN_KEYBOARD
454   PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("E-4") /*PORT_CODE(KEYCODE_3) PORT_CHAR('3')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x73) PORT_PLAYER(1) SATURN_KEYBOARD
455   PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("E-5") /*PORT_CODE(KEYCODE_4) PORT_CHAR('4')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x74) PORT_PLAYER(1) SATURN_KEYBOARD
456   PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("E-6") /*PORT_CODE(KEYCODE_5) PORT_CHAR(0xd)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x75) PORT_PLAYER(1) SATURN_KEYBOARD
457   PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("E-7") /*PORT_CODE(KEYCODE_6) PORT_CHAR('6')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x76) PORT_PLAYER(1) SATURN_KEYBOARD
458   PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("E-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x77) PORT_PLAYER(1) SATURN_KEYBOARD
459
460   PORT_START("KEYF") // 0x78 - 0x7f
461   PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x78) PORT_PLAYER(1) SATURN_KEYBOARD
462   PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F-2") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x79) PORT_PLAYER(1) SATURN_KEYBOARD
463   PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F-3") /*PORT_CODE(KEYCODE_2) PORT_CHAR('2')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x7a) PORT_PLAYER(1) SATURN_KEYBOARD
464   PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F-4") /*PORT_CODE(KEYCODE_3) PORT_CHAR('3')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x7b) PORT_PLAYER(1) SATURN_KEYBOARD
465   PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F-5") /*PORT_CODE(KEYCODE_4) PORT_CHAR('4')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x7c) PORT_PLAYER(1) SATURN_KEYBOARD
466   PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F-6") /*PORT_CODE(KEYCODE_5) PORT_CHAR(0xd)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x7d) PORT_PLAYER(1) SATURN_KEYBOARD
467   PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F-7") /*PORT_CODE(KEYCODE_6) PORT_CHAR('6')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x7e) PORT_PLAYER(1) SATURN_KEYBOARD
468   PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("ESC") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x7f) PORT_PLAYER(1) SATURN_KEYBOARD //SYSTEM CONFIGURATION
469
470   PORT_START("KEYS_1") // special keys
471   PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("UP") PORT_CODE(KEYCODE_UP) /*PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x78) PORT_PLAYER(1) SATURN_KEYBOARD
472   PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("DOWN") PORT_CODE(KEYCODE_DOWN) /*PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x79) PORT_PLAYER(1) SATURN_KEYBOARD
473   PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("LEFT") PORT_CODE(KEYCODE_LEFT) /*PORT_CHAR('2')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x7a) PORT_PLAYER(1) SATURN_KEYBOARD
474   PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("RIGHT") PORT_CODE(KEYCODE_RIGHT) /*PORT_CHAR('3')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x7b) PORT_PLAYER(1) SATURN_KEYBOARD
475
476   PORT_START("MOUSEB1")
477   PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P1 Pointer Left Button") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", 0x0f, EQUALS, 0x04)
478   PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P1 Pointer Right Button") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", 0x0f, EQUALS, 0x04)
479   PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("P1 Pointer Middle Button") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", 0x0f, EQUALS, 0x04)
480   PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_START ) PORT_NAME("P1 Pointer Start Button") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", 0x0f, EQUALS, 0x04)
481   PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P1 Mouse Left Button") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", 0x0f, EQUALS, 0x08)
482   PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P1 Mouse Right Button") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", 0x0f, EQUALS, 0x08)
483   PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("P1 Mouse Middle Button") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", 0x0f, EQUALS, 0x08)
484   PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_START ) PORT_NAME("P1 Mouse Start Button") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", 0x0f, EQUALS, 0x08)
485
486   PORT_START("MOUSEX1")
487   PORT_BIT(0xffff, 0x00, IPT_MOUSE_X) PORT_SENSITIVITY(100) PORT_MINMAX(0x000, 0xffff) PORT_KEYDELTA(2) PORT_RESET PORT_NAME("P1 Pointer X") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", 0x0f, EQUALS, 0x04)
488   PORT_BIT(0xffff, 0x00, IPT_MOUSE_X) PORT_SENSITIVITY(100) PORT_MINMAX(0x000, 0xffff) PORT_KEYDELTA(2) PORT_RESET PORT_NAME("P1 Mouse X") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", 0x0f, EQUALS, 0x08)
489
490   PORT_START("MOUSEY1")
491   PORT_BIT(0xffff, 0x00, IPT_MOUSE_Y) PORT_SENSITIVITY(100) PORT_MINMAX(0x000, 0xffff) PORT_KEYDELTA(2) PORT_RESET PORT_REVERSE PORT_NAME("P1 Pointer Y") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", 0x0f, EQUALS, 0x04)
492   PORT_BIT(0xffff, 0x00, IPT_MOUSE_Y) PORT_SENSITIVITY(100) PORT_MINMAX(0x000, 0xffff) PORT_KEYDELTA(2) PORT_RESET PORT_REVERSE PORT_NAME("P1 Mouse Y") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", 0x0f, EQUALS, 0x08)
493
494   PORT_START("MOUSEB2")
495   PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P2 Pointer Left Button") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", 0xf0, EQUALS, 0x40)
496   PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P2 Pointer Right Button") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", 0xf0, EQUALS, 0x40)
497   PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("P2 Pointer Middle Button") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", 0xf0, EQUALS, 0x40)
498   PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_START ) PORT_NAME("P2 Pointer Start Button") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", 0xf0, EQUALS, 0x40)
499   PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P2 Mouse Left Button") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", 0xf0, EQUALS, 0x80)
500   PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P2 Mouse Right Button") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", 0xf0, EQUALS, 0x80)
501   PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("P2 Mouse Middle Button") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", 0xf0, EQUALS, 0x80)
502   PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_START ) PORT_NAME("P2 Mouse Start Button") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", 0xf0, EQUALS, 0x80)
503
504   PORT_START("MOUSEX2")
505   PORT_BIT(0xffff, 0x00, IPT_MOUSE_X) PORT_SENSITIVITY(100) PORT_MINMAX(0x000, 0xffff) PORT_KEYDELTA(2) PORT_RESET PORT_NAME("P2 Pointer X") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", 0xf0, EQUALS, 0x40)
506   PORT_BIT(0xffff, 0x00, IPT_MOUSE_X) PORT_SENSITIVITY(100) PORT_MINMAX(0x000, 0xffff) PORT_KEYDELTA(2) PORT_RESET PORT_NAME("P2 Mouse X") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", 0xf0, EQUALS, 0x80)
507
508   PORT_START("MOUSEY2")
509   PORT_BIT(0xffff, 0x00, IPT_MOUSE_Y) PORT_SENSITIVITY(100) PORT_MINMAX(0x000, 0xffff) PORT_KEYDELTA(2) PORT_RESET PORT_REVERSE PORT_NAME("P2 Pointer Y") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", 0xf0, EQUALS, 0x40)
510   PORT_BIT(0xffff, 0x00, IPT_MOUSE_Y) PORT_SENSITIVITY(100) PORT_MINMAX(0x000, 0xffff) PORT_KEYDELTA(2) PORT_RESET PORT_REVERSE PORT_NAME("P2 Mouse Y") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", 0xf0, EQUALS, 0x80)
511
512   PORT_START("AN_JOY1")
513   SATURN_PAD_P1(0x0f, 0x01)   // racing device
514   SATURN_PAD_P1(0x0f, 0x02)   // analog controller
515
516   PORT_START("AN_JOY2")
517   SATURN_PAD_P2(0xf0, 0x10)   // racing device
518   SATURN_PAD_P2(0xf0, 0x20)   // analog controller
519
520   PORT_START("AN_X1")
521   PORT_BIT( 0xff, 0x80, IPT_AD_STICK_X ) PORT_MINMAX(0x00, 0xff) PORT_SENSITIVITY(25) PORT_KEYDELTA(200) PORT_PLAYER(1) PORT_NAME("P1 Racing Stick X") PORT_CONDITION("INPUT_TYPE", 0x0f, EQUALS, 0x01)
522   PORT_BIT( 0xff, 0x80, IPT_AD_STICK_X ) PORT_MINMAX(0x00, 0xff) PORT_SENSITIVITY(25) PORT_KEYDELTA(200) PORT_PLAYER(1) PORT_NAME("P1 AD Stick X") PORT_CONDITION("INPUT_TYPE", 0x0f, EQUALS, 0x02)
523
524   PORT_START("AN_Y1")
525   PORT_BIT( 0xff, 0x80, IPT_AD_STICK_Y ) PORT_MINMAX(0x00, 0xff) PORT_SENSITIVITY(25) PORT_KEYDELTA(200) PORT_PLAYER(1) PORT_NAME("P1 Racing Stick Y") PORT_CONDITION("INPUT_TYPE", 0x0f, EQUALS, 0x01)
526   PORT_BIT( 0xff, 0x80, IPT_AD_STICK_Y ) PORT_MINMAX(0x00, 0xff) PORT_SENSITIVITY(25) PORT_KEYDELTA(200) PORT_PLAYER(1) PORT_NAME("P1 AD Stick Y") PORT_CONDITION("INPUT_TYPE", 0x0f, EQUALS, 0x02)
527
528   PORT_START("AN_Z1")
529   PORT_BIT( 0xff, 0x00, IPT_AD_STICK_Z ) PORT_MINMAX(0x00, 0xff) PORT_SENSITIVITY(25) PORT_KEYDELTA(200) PORT_PLAYER(1) PORT_NAME("P1 Racing Stick Z") PORT_CONDITION("INPUT_TYPE", 0x0f, EQUALS, 0x01)
530   PORT_BIT( 0xff, 0x00, IPT_AD_STICK_Z ) PORT_MINMAX(0x00, 0xff) PORT_SENSITIVITY(25) PORT_KEYDELTA(200) PORT_PLAYER(1) PORT_NAME("P1 AD Stick Z") PORT_CONDITION("INPUT_TYPE", 0x0f, EQUALS, 0x02)
531
532   PORT_START("AN_X2")
533   PORT_BIT( 0xff, 0x80, IPT_AD_STICK_X ) PORT_MINMAX(0x00, 0xff) PORT_SENSITIVITY(25) PORT_KEYDELTA(200) PORT_PLAYER(2) PORT_NAME("P2 Racing Stick X") PORT_CONDITION("INPUT_TYPE", 0xf0, EQUALS, 0x10)
534   PORT_BIT( 0xff, 0x80, IPT_AD_STICK_X ) PORT_MINMAX(0x00, 0xff) PORT_SENSITIVITY(25) PORT_KEYDELTA(200) PORT_PLAYER(2) PORT_NAME("P2 AD Stick X") PORT_CONDITION("INPUT_TYPE", 0xf0, EQUALS, 0x20)
535
536   PORT_START("AN_Y2")
537   PORT_BIT( 0xff, 0x80, IPT_AD_STICK_Y ) PORT_MINMAX(0x00, 0xff) PORT_SENSITIVITY(25) PORT_KEYDELTA(200) PORT_PLAYER(2) PORT_NAME("P2 Racing Stick Y") PORT_CONDITION("INPUT_TYPE", 0xf0, EQUALS, 0x10)
538   PORT_BIT( 0xff, 0x80, IPT_AD_STICK_Y ) PORT_MINMAX(0x00, 0xff) PORT_SENSITIVITY(25) PORT_KEYDELTA(200) PORT_PLAYER(2) PORT_NAME("P2 AD Stick Y") PORT_CONDITION("INPUT_TYPE", 0xf0, EQUALS, 0x20)
539
540   PORT_START("AN_Z2")
541   PORT_BIT( 0xff, 0x00, IPT_AD_STICK_Z ) PORT_MINMAX(0x00, 0xff) PORT_SENSITIVITY(25) PORT_KEYDELTA(200) PORT_PLAYER(2) PORT_NAME("P2 Racing Stick Z") PORT_CONDITION("INPUT_TYPE", 0xf0, EQUALS, 0x10)
542   PORT_BIT( 0xff, 0x00, IPT_AD_STICK_Z ) PORT_MINMAX(0x00, 0xff) PORT_SENSITIVITY(25) PORT_KEYDELTA(200) PORT_PLAYER(2) PORT_NAME("P2 AD Stick Z") PORT_CONDITION("INPUT_TYPE", 0xf0, EQUALS, 0x20)
543
544   PORT_START("MD_JOY1")
545   MD_PAD_P1(0x0f, 0x06)   // MD 3 buttons pad
546   MD_PAD_P1(0x0f, 0x07)   // MD 6 buttons pad
547
548   PORT_START("MD_JOY2")
549   MD_PAD_P2(0xf0, 0x60)   // MD 3 buttons pad
550   MD_PAD_P2(0xf0, 0x70)   // MD 6 buttons pad
551
552   PORT_START("CART_AREA")
553   PORT_CONFNAME( 0x07, 0x06, "Cart Type" )
554   PORT_CONFSETTING( 0x00, "None" )
555//  PORT_CONFSETTING( 0x01, "4 Mbit backup RAM" )
556//  PORT_CONFSETTING( 0x02, "8 Mbit backup RAM" )
557//  PORT_CONFSETTING( 0x03, "16 Mbit backup RAM" )
558//  PORT_CONFSETTING( 0x04, "32 Mbit backup RAM" )
559   PORT_CONFSETTING( 0x05, "8 Mbit Cart RAM" )
560   PORT_CONFSETTING( 0x06, "32 Mbit Cart RAM" )
561
562   PORT_START("INPUT_TYPE")
563   PORT_CONFNAME(0x0f,0x00,"Controller Port 1")
564   PORT_CONFSETTING(0x00,"Digital Device (standard Saturn pad)")
565   PORT_CONFSETTING(0x01,"Racing Device") /* steering wheel only */
566   PORT_CONFSETTING(0x02,"Analog Device") //Nights pad?
567//  PORT_CONFSETTING(0x03,"Lightgun Device")
568   PORT_CONFSETTING(0x04,"Trackball") // TODO: according to the docs this ID is labeled "Pointing Device"
569   PORT_CONFSETTING(0x05,"Keyboard Device")
570   PORT_CONFSETTING(0x06,"Megadrive 3B Pad")
571   PORT_CONFSETTING(0x07,"Megadrive 6B Pad")
572   PORT_CONFSETTING(0x08,"Saturn Mouse")
573//  PORT_CONFSETTING(0x09,"<unconnected>")
574   PORT_CONFNAME(0xf0,0x00,"Controller Port 2")
575   PORT_CONFSETTING(0x00,"Digital Device (standard Saturn pad)")
576   PORT_CONFSETTING(0x10,"Racing Device")
577   PORT_CONFSETTING(0x20,"Analog Device") //Nights pad?
578//  PORT_CONFSETTING(0x30,"Lightgun Device")
579   PORT_CONFSETTING(0x40,"Pointing Device")
580//  PORT_CONFSETTING(0x50,"Keyboard Device")
581   PORT_CONFSETTING(0x60,"Megadrive 3B Pad")
582   PORT_CONFSETTING(0x70,"Megadrive 6B Pad")
583   PORT_CONFSETTING(0x80,"Saturn Mouse")
584   PORT_CONFSETTING(0x90,"<unconnected>")
585
586   PORT_START("fake")
587   PORT_CONFNAME(0x01,0x00,"Master-Slave Comms")
588   PORT_CONFSETTING(0x00,"Normal (400 cycles)")
589   PORT_CONFSETTING(0x01,"One Shot (Hack)")
590INPUT_PORTS_END
591
592static const sh2_cpu_core sh2_conf_master = { 0, NULL };
593static const sh2_cpu_core sh2_conf_slave  = { 1, NULL };
594
595static const scsp_interface scsp_config =
596{
597   0,
598   scsp_irq,
599   DEVCB_DRIVER_LINE_MEMBER(saturn_state, scsp_to_main_irq)
600};
601
602MACHINE_START_MEMBER(saturn_state,saturn)
603{
604   system_time systime;
605   machine().base_datetime(systime);
606
607   m_maincpu = downcast<legacy_cpu_device*>( machine().device<cpu_device>("maincpu") );
608   m_slave = downcast<legacy_cpu_device*>( machine().device("slave") );
609   m_audiocpu = downcast<legacy_cpu_device*>( machine().device<cpu_device>("audiocpu") );
610
611   scsp_set_ram_base(machine().device("scsp"), m_sound_ram);
612
613   // save states
614   state_save_register_global_pointer(machine(), m_scu_regs, 0x100/4);
615   state_save_register_global_pointer(machine(), m_scsp_regs,  0x1000/2);
616   state_save_register_global(machine(), m_NMI_reset);
617   state_save_register_global(machine(), m_en_68k);
618   state_save_register_global(machine(), m_smpc.IOSEL1);
619   state_save_register_global(machine(), m_smpc.IOSEL2);
620   state_save_register_global(machine(), m_smpc.EXLE1);
621   state_save_register_global(machine(), m_smpc.EXLE2);
622   state_save_register_global(machine(), m_smpc.PDR1);
623   state_save_register_global(machine(), m_smpc.PDR2);
624//  state_save_register_global(machine(), m_port_sel);
625//  state_save_register_global(machine(), mux_data);
626   state_save_register_global(machine(), m_scsp_last_line);
627   state_save_register_global(machine(), m_smpc.intback_stage);
628   state_save_register_global(machine(), m_smpc.pmode);
629   state_save_register_global(machine(), m_smpc.SR);
630   state_save_register_global_array(machine(), m_smpc.SMEM);
631   state_save_register_global_pointer(machine(), m_cart_dram, 0x400000/4);
632
633   machine().add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(saturn_state::stvcd_exit), this));
634
635   m_smpc.rtc_data[0] = DectoBCD(systime.local_time.year /100);
636   m_smpc.rtc_data[1] = DectoBCD(systime.local_time.year %100);
637   m_smpc.rtc_data[2] = (systime.local_time.weekday << 4) | (systime.local_time.month+1);
638   m_smpc.rtc_data[3] = DectoBCD(systime.local_time.mday);
639   m_smpc.rtc_data[4] = DectoBCD(systime.local_time.hour);
640   m_smpc.rtc_data[5] = DectoBCD(systime.local_time.minute);
641   m_smpc.rtc_data[6] = DectoBCD(systime.local_time.second);
642
643   m_stv_rtc_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(saturn_state::stv_rtc_increment),this));
644
645   m68k_set_reset_callback(m_audiocpu, &saturn_state::m68k_reset_callback);
646}
647
648/* Die Hard Trilogy tests RAM address 0x25e7ffe bit 2 with Slave during FRT minit irq, in-development tool for breaking execution of it? */
649READ32_MEMBER(saturn_state::saturn_null_ram_r)
650{
651   return 0xffffffff;
652}
653
654WRITE32_MEMBER(saturn_state::saturn_null_ram_w)
655{
656}
657
658READ32_MEMBER(saturn_state::saturn_cart_dram0_r)
659{
660   return m_cart_dram[offset];
661}
662
663WRITE32_MEMBER(saturn_state::saturn_cart_dram0_w)
664{
665   COMBINE_DATA(&m_cart_dram[offset]);
666}
667
668READ32_MEMBER(saturn_state::saturn_cart_dram1_r)
669{
670   return m_cart_dram[offset+0x200000/4];
671}
672
673WRITE32_MEMBER(saturn_state::saturn_cart_dram1_w)
674{
675   COMBINE_DATA(&m_cart_dram[offset+0x200000/4]);
676}
677
678READ32_MEMBER(saturn_state::saturn_cs1_r)
679{
680   UINT32 res;
681
682   res = 0;
683   //res  = m_cart_backupram[offset*4+0] << 24;
684   res |= m_cart_backupram[offset*2+0] << 16;
685   //res |= m_cart_backupram[offset*4+2] << 8;
686   res |= m_cart_backupram[offset*2+1] << 0;
687
688   return res;
689}
690
691WRITE32_MEMBER(saturn_state::saturn_cs1_w)
692{
693   if(ACCESSING_BITS_16_23)
694      m_cart_backupram[offset*2+0] = (data & 0x00ff0000) >> 16;
695   if(ACCESSING_BITS_0_7)
696      m_cart_backupram[offset*2+1] = (data & 0x000000ff) >> 0;
697}
698
699MACHINE_RESET_MEMBER(saturn_state,saturn)
700{
701   m_scsp_last_line = 0;
702
703   // don't let the slave cpu and the 68k go anywhere
704   machine().device("slave")->execute().set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
705   machine().device("audiocpu")->execute().set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
706
707   m_smpc.SR = 0x40;   // this bit is always on according to docs
708
709   scu_reset();
710
711   m_en_68k = 0;
712   m_NMI_reset = 0;
713   m_smpc.slave_on = 0;
714
715
716   //memset(stv_m_workram_l, 0, 0x100000);
717   //memset(stv_m_workram_h, 0, 0x100000);
718
719   machine().device("maincpu")->set_unscaled_clock(MASTER_CLOCK_320/2);
720   machine().device("slave")->set_unscaled_clock(MASTER_CLOCK_320/2);
721
722   stvcd_reset();
723
724   m_cart_type = ioport("CART_AREA")->read() & 7;
725
726   machine().device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x02400000, 0x027fffff, read32_delegate(FUNC(saturn_state::saturn_null_ram_r),this), write32_delegate(FUNC(saturn_state::saturn_null_ram_w),this));
727   machine().device("slave")->memory().space(AS_PROGRAM).install_readwrite_handler(0x02400000, 0x027fffff, read32_delegate(FUNC(saturn_state::saturn_null_ram_r),this), write32_delegate(FUNC(saturn_state::saturn_null_ram_w),this));
728
729   if(m_cart_type == 5)
730   {
731      //  AM_RANGE(0x02400000, 0x027fffff) AM_RAM //cart RAM area, dynamically allocated
732      machine().device("maincpu")->memory().space(AS_PROGRAM).nop_readwrite(0x02400000, 0x027fffff);
733      machine().device("slave")->memory().space(AS_PROGRAM).nop_readwrite(0x02400000, 0x027fffff);
734
735      machine().device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x02400000, 0x0247ffff, read32_delegate(FUNC(saturn_state::saturn_cart_dram0_r),this), write32_delegate(FUNC(saturn_state::saturn_cart_dram0_w),this));
736      machine().device("slave")->memory().space(AS_PROGRAM).install_readwrite_handler(0x02400000, 0x0247ffff, read32_delegate(FUNC(saturn_state::saturn_cart_dram0_r),this), write32_delegate(FUNC(saturn_state::saturn_cart_dram0_w),this));
737      machine().device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x02600000, 0x0267ffff, read32_delegate(FUNC(saturn_state::saturn_cart_dram1_r),this), write32_delegate(FUNC(saturn_state::saturn_cart_dram1_w),this));
738      machine().device("slave")->memory().space(AS_PROGRAM).install_readwrite_handler(0x02600000, 0x0267ffff, read32_delegate(FUNC(saturn_state::saturn_cart_dram1_r),this), write32_delegate(FUNC(saturn_state::saturn_cart_dram1_w),this));
739   }
740
741   if(m_cart_type == 6)
742   {
743      //  AM_RANGE(0x02400000, 0x027fffff) AM_RAM //cart RAM area, dynamically allocated
744      machine().device("maincpu")->memory().space(AS_PROGRAM).nop_readwrite(0x02400000, 0x027fffff);
745      machine().device("slave")->memory().space(AS_PROGRAM).nop_readwrite(0x02400000, 0x027fffff);
746
747      machine().device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x02400000, 0x025fffff, read32_delegate(FUNC(saturn_state::saturn_cart_dram0_r),this), write32_delegate(FUNC(saturn_state::saturn_cart_dram0_w),this));
748      machine().device("slave")->memory().space(AS_PROGRAM).install_readwrite_handler(0x02400000, 0x025fffff, read32_delegate(FUNC(saturn_state::saturn_cart_dram0_r),this), write32_delegate(FUNC(saturn_state::saturn_cart_dram0_w),this));
749      machine().device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x02600000, 0x027fffff, read32_delegate(FUNC(saturn_state::saturn_cart_dram1_r),this), write32_delegate(FUNC(saturn_state::saturn_cart_dram1_w),this));
750      machine().device("slave")->memory().space(AS_PROGRAM).install_readwrite_handler(0x02600000, 0x027fffff, read32_delegate(FUNC(saturn_state::saturn_cart_dram1_r),this), write32_delegate(FUNC(saturn_state::saturn_cart_dram1_w),this));
751   }
752
753   machine().device("maincpu")->memory().space(AS_PROGRAM).nop_readwrite(0x04000000, 0x047fffff);
754   machine().device("slave")->memory().space(AS_PROGRAM).nop_readwrite(0x04000000, 0x047fffff);
755
756   if(m_cart_type > 0 && m_cart_type < 5)
757   {
758   //  AM_RANGE(0x04000000, 0x047fffff) AM_RAM //backup RAM area, dynamically allocated
759      UINT32 mask;
760      mask = 0x7fffff >> (4-m_cart_type);
761      //mask = 0x7fffff >> 4-4 = 0x7fffff 32mbit
762      //mask = 0x7fffff >> 4-3 = 0x3fffff 16mbit
763      //mask = 0x7fffff >> 4-2 = 0x1fffff 8mbit
764      //mask = 0x7fffff >> 4-1 = 0x0fffff 4mbit
765      machine().device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x04000000, 0x04000000 | mask, read32_delegate(FUNC(saturn_state::saturn_cs1_r),this), write32_delegate(FUNC(saturn_state::saturn_cs1_w),this));
766      machine().device("slave")->memory().space(AS_PROGRAM).install_readwrite_handler(0x04000000, 0x04000000 | mask, read32_delegate(FUNC(saturn_state::saturn_cs1_r),this), write32_delegate(FUNC(saturn_state::saturn_cs1_w),this));
767   }
768
769   m_vdp2.old_crmd = -1;
770   m_vdp2.old_tvmd = -1;
771
772   m_stv_rtc_timer->adjust(attotime::zero, 0, attotime::from_seconds(1));
773}
774
775
776struct cdrom_interface saturn_cdrom =
777{
778   "sat_cdrom",
779   NULL
780};
781
782
783
784
785DEVICE_IMAGE_LOAD_MEMBER( saturn_state, sat_cart )
786{
787   UINT8 *ROM = image.device().memregion("maincpu")->base()+0x080000;
788   UINT32 length;
789
790   if (image.software_entry() != NULL)
791   {
792      length = image.get_software_region_length("cart");
793      UINT8* imagex =  image.get_software_region("cart");
794
795      memcpy(ROM, imagex, length);
796   }
797   else
798   {
799      length = image.fread( ROM, 0x400000);
800   }
801
802   // fix endianness....
803   for (int i=0;i<length;i+=4)
804   {
805      UINT8 tempa = ROM[i+0];
806      UINT8 tempb = ROM[i+1];
807      ROM[i+1] = ROM[i+2];
808      ROM[i+0] = ROM[i+3];
809      ROM[i+3] = tempa;
810      ROM[i+2] = tempb;
811   }
812
813   return IMAGE_INIT_PASS;
814}
815
816static MACHINE_CONFIG_START( saturn, saturn_state )
817
818   /* basic machine hardware */
819   MCFG_CPU_ADD("maincpu", SH2, MASTER_CLOCK_352/2) // 28.6364 MHz
820   MCFG_CPU_PROGRAM_MAP(saturn_mem)
821   MCFG_CPU_CONFIG(sh2_conf_master)
822   MCFG_TIMER_DRIVER_ADD_SCANLINE("scantimer", saturn_state, saturn_scanline, "screen", 0, 1)
823
824   MCFG_CPU_ADD("slave", SH2, MASTER_CLOCK_352/2) // 28.6364 MHz
825   MCFG_CPU_PROGRAM_MAP(saturn_mem)
826   MCFG_CPU_CONFIG(sh2_conf_slave)
827   MCFG_TIMER_DRIVER_ADD_SCANLINE("slave_scantimer", saturn_state, saturn_slave_scanline, "screen", 0, 1)
828
829   MCFG_CPU_ADD("audiocpu", M68000, 11289600) //256 x 44100 Hz = 11.2896 MHz
830   MCFG_CPU_PROGRAM_MAP(sound_mem)
831
832   MCFG_MACHINE_START_OVERRIDE(saturn_state,saturn)
833   MCFG_MACHINE_RESET_OVERRIDE(saturn_state,saturn)
834
835   MCFG_NVRAM_HANDLER(saturn)
836
837   MCFG_TIMER_DRIVER_ADD("sector_timer", saturn_state, stv_sector_cb)
838   MCFG_TIMER_DRIVER_ADD("sh1_cmd", saturn_state, stv_sh1_sim)
839
840   /* video hardware */
841   MCFG_SCREEN_ADD("screen", RASTER)
842   MCFG_SCREEN_RAW_PARAMS(MASTER_CLOCK_320/8, 427, 0, 320, 263, 0, 224)
843   MCFG_SCREEN_UPDATE_DRIVER(saturn_state, screen_update_stv_vdp2)
844   MCFG_PALETTE_LENGTH(2048+(2048*2))//standard palette + extra memory for rgb brightness.
845
846   MCFG_GFXDECODE(stv)
847
848   MCFG_VIDEO_START_OVERRIDE(saturn_state,stv_vdp2)
849
850   MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
851
852   MCFG_SOUND_ADD("scsp", SCSP, 0)
853   MCFG_SOUND_CONFIG(scsp_config)
854   MCFG_SOUND_ROUTE(0, "lspeaker", 1.0)
855   MCFG_SOUND_ROUTE(1, "rspeaker", 1.0)
856
857   MCFG_SOUND_ADD("cdda", CDDA, 0)
858   MCFG_SOUND_ROUTE(0, "lspeaker", 1.0)
859   MCFG_SOUND_ROUTE(1, "rspeaker", 1.0)
860MACHINE_CONFIG_END
861
862MACHINE_CONFIG_DERIVED( saturnus, saturn )
863   MCFG_CDROM_ADD( "cdrom",saturn_cdrom )
864   MCFG_SOFTWARE_LIST_ADD("cd_list","saturn")
865   MCFG_SOFTWARE_LIST_FILTER("cd_list","NTSC-U")
866
867   MCFG_CARTSLOT_ADD("cart")
868   MCFG_CARTSLOT_INTERFACE("sat_cart")
869   MCFG_CARTSLOT_LOAD(saturn_state, sat_cart)
870   MCFG_SOFTWARE_LIST_ADD("cart_list","sat_cart")
871
872MACHINE_CONFIG_END
873
874MACHINE_CONFIG_DERIVED( saturneu, saturn )
875   MCFG_CDROM_ADD( "cdrom",saturn_cdrom )
876   MCFG_SOFTWARE_LIST_ADD("cd_list","saturn")
877   MCFG_SOFTWARE_LIST_FILTER("cd_list","PAL")
878
879   MCFG_CARTSLOT_ADD("cart")
880   MCFG_CARTSLOT_INTERFACE("sat_cart")
881   MCFG_CARTSLOT_LOAD(saturn_state, sat_cart)
882   MCFG_SOFTWARE_LIST_ADD("cart_list","sat_cart")
883
884MACHINE_CONFIG_END
885
886MACHINE_CONFIG_DERIVED( saturnjp, saturn )
887   MCFG_CDROM_ADD( "cdrom",saturn_cdrom )
888   MCFG_SOFTWARE_LIST_ADD("cd_list","saturn")
889   MCFG_SOFTWARE_LIST_FILTER("cd_list","NTSC-J")
890
891   MCFG_CARTSLOT_ADD("cart")
892   MCFG_CARTSLOT_INTERFACE("sat_cart")
893   MCFG_CARTSLOT_LOAD(saturn_state, sat_cart)
894   MCFG_SOFTWARE_LIST_ADD("cart_list","sat_cart")
895
896MACHINE_CONFIG_END
897
898
899void saturn_state::saturn_init_driver(int rgn)
900{
901   m_saturn_region = rgn;
902   m_vdp2.pal = (rgn == 12) ? 1 : 0;
903
904   // set compatible options
905   sh2drc_set_options(machine().device("maincpu"), SH2DRC_STRICT_VERIFY|SH2DRC_STRICT_PCREL);
906   sh2drc_set_options(machine().device("slave"), SH2DRC_STRICT_VERIFY|SH2DRC_STRICT_PCREL);
907
908   /* amount of time to boost interleave for on MINIT / SINIT, needed for communication to work */
909   m_minit_boost = 400;
910   m_sinit_boost = 400;
911   m_minit_boost_timeslice = attotime::zero;
912   m_sinit_boost_timeslice = attotime::zero;
913
914   m_scu_regs = auto_alloc_array_clear(machine(), UINT32, 0x100/4);
915   m_scsp_regs = auto_alloc_array_clear(machine(), UINT16, 0x1000/2);
916   m_cart_dram = auto_alloc_array_clear(machine(), UINT32, 0x400000/4);
917   m_backupram = auto_alloc_array_clear(machine(), UINT8, 0x8000);
918   m_cart_backupram = auto_alloc_array_clear(machine(), UINT8, 0x400000);
919}
920
921DRIVER_INIT_MEMBER(saturn_state,saturnus)
922{
923   saturn_init_driver(4);
924}
925
926DRIVER_INIT_MEMBER(saturn_state,saturneu)
927{
928   saturn_init_driver(12);
929}
930
931DRIVER_INIT_MEMBER(saturn_state,saturnjp)
932{
933   saturn_init_driver(1);
934}
935
936
937/* Japanese Saturn */
938ROM_START(saturnjp)
939   ROM_REGION( 0x480000, "maincpu", ROMREGION_ERASEFF ) /* SH2 code */
940   ROM_SYSTEM_BIOS(0, "101", "Japan v1.01 (941228)")
941   ROMX_LOAD("sega_101.bin", 0x00000000, 0x00080000, CRC(224b752c) SHA1(df94c5b4d47eb3cc404d88b33a8fda237eaf4720), ROM_BIOS(1))
942   ROM_SYSTEM_BIOS(1, "1003", "Japan v1.003 (941012)")
943   ROMX_LOAD("sega1003.bin", 0x00000000, 0x00080000, CRC(b3c63c25) SHA1(7b23b53d62de0f29a23e423d0fe751dfb469c2fa), ROM_BIOS(2))
944   ROM_SYSTEM_BIOS(2, "100", "Japan v1.00 (940921)")
945   ROMX_LOAD("sega_100.bin", 0x00000000, 0x00080000, CRC(2aba43c2) SHA1(2b8cb4f87580683eb4d760e4ed210813d667f0a2), ROM_BIOS(3))
946//  ROM_CART_LOAD("cart", 0x080000, 0x400000, ROM_NOMIRROR | ROM_OPTIONAL)
947   ROM_REGION( 0x080000, "slave", 0 ) /* SH2 code */
948   ROM_COPY( "maincpu",0,0,0x080000)
949ROM_END
950
951/* Overseas Saturn */
952ROM_START(saturn)
953   ROM_REGION( 0x480000, "maincpu", ROMREGION_ERASEFF ) /* SH2 code */
954   ROM_SYSTEM_BIOS(0, "101a", "Overseas v1.01a (941115)")
955   /* Confirmed by ElBarto */
956   ROMX_LOAD("mpr-17933.bin", 0x00000000, 0x00080000, CRC(4afcf0fa) SHA1(faa8ea183a6d7bbe5d4e03bb1332519800d3fbc3), ROM_BIOS(1))
957   ROM_SYSTEM_BIOS(1, "100a", "Overseas v1.00a (941115)")
958   ROMX_LOAD("sega_100a.bin", 0x00000000, 0x00080000, CRC(f90f0089) SHA1(3bb41feb82838ab9a35601ac666de5aacfd17a58), ROM_BIOS(2))
959//  ROM_CART_LOAD("cart", 0x080000, 0x400000, ROM_NOMIRROR | ROM_OPTIONAL)
960   ROM_REGION( 0x080000, "slave", 0 ) /* SH2 code */
961   ROM_COPY( "maincpu",0,0,0x080000)
962ROM_END
963
964ROM_START(saturneu)
965   ROM_REGION( 0x480000, "maincpu", ROMREGION_ERASEFF ) /* SH2 code */
966   ROM_SYSTEM_BIOS(0, "101a", "Overseas v1.01a (941115)")
967   /* Confirmed by ElBarto */
968   ROMX_LOAD("mpr-17933.bin", 0x00000000, 0x00080000, CRC(4afcf0fa) SHA1(faa8ea183a6d7bbe5d4e03bb1332519800d3fbc3), ROM_BIOS(1))
969   ROM_SYSTEM_BIOS(1, "100a", "Overseas v1.00a (941115)")
970   ROMX_LOAD("sega_100a.bin", 0x00000000, 0x00080000, CRC(f90f0089) SHA1(3bb41feb82838ab9a35601ac666de5aacfd17a58), ROM_BIOS(2))
971//  ROM_CART_LOAD("cart", 0x080000, 0x400000, ROM_NOMIRROR | ROM_OPTIONAL)
972   ROM_REGION( 0x080000, "slave", 0 ) /* SH2 code */
973   ROM_COPY( "maincpu",0,0,0x080000)
974ROM_END
975
976ROM_START(vsaturn)
977   ROM_REGION( 0x480000, "maincpu", ROMREGION_ERASEFF ) /* SH2 code */
978   ROM_LOAD("vsaturn.bin", 0x00000000, 0x00080000, CRC(e4d61811) SHA1(4154e11959f3d5639b11d7902b3a393a99fb5776))
979//  ROM_CART_LOAD("cart", 0x080000, 0x400000, ROM_NOMIRROR | ROM_OPTIONAL)
980   ROM_REGION( 0x080000, "slave", 0 ) /* SH2 code */
981   ROM_COPY( "maincpu",0,0,0x080000)
982ROM_END
983
984ROM_START(hisaturn)
985   ROM_REGION( 0x480000, "maincpu", ROMREGION_ERASEFF ) /* SH2 code */
986   ROM_LOAD("hisaturn.bin", 0x00000000, 0x00080000, CRC(721e1b60) SHA1(49d8493008fa715ca0c94d99817a5439d6f2c796))
987//  ROM_CART_LOAD("cart", 0x080000, 0x400000, ROM_NOMIRROR | ROM_OPTIONAL)
988   ROM_REGION( 0x080000, "slave", 0 ) /* SH2 code */
989   ROM_COPY( "maincpu",0,0,0x080000)
990ROM_END
991
992/*    YEAR  NAME        PARENT  COMPAT  MACHINE INPUT   INIT        COMPANY     FULLNAME            FLAGS */
993CONS( 1994, saturn,     0,      0,      saturnus, saturn, saturn_state, saturnus,   "Sega",     "Saturn (USA)",     GAME_NOT_WORKING )
994CONS( 1994, saturnjp,   saturn, 0,      saturnjp, saturn, saturn_state, saturnjp,   "Sega",     "Saturn (Japan)",   GAME_NOT_WORKING )
995CONS( 1994, saturneu,   saturn, 0,      saturneu, saturn, saturn_state, saturneu,   "Sega",     "Saturn (PAL)",     GAME_NOT_WORKING )
996CONS( 1995, vsaturn,    saturn, 0,      saturnjp, saturn, saturn_state, saturnjp,   "JVC",      "V-Saturn",         GAME_NOT_WORKING )
997CONS( 1995, hisaturn,   saturn, 0,      saturnjp, saturn, saturn_state, saturnjp,   "Hitachi",  "HiSaturn",         GAME_NOT_WORKING )
Property changes on: trunk/src/mess/drivers/saturn.c
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/mess/mess.mak
r21330r21331
16431643   $(MESS_DRIVERS)/dccons.o    \
16441644   $(MAME_MACHINE)/gdrom.o     \
16451645   $(MESS_MACHINE)/dccons.o    \
1646   $(MAME_DRIVERS)/saturn.o    \
1646   $(MESS_DRIVERS)/saturn.o    \
16471647   $(MESS_MACHINE)/sms.o       \
16481648   $(MESS_DRIVERS)/sms.o       \
16491649   $(MESS_DRIVERS)/svmu.o      \
trunk/src/mame/drivers/saturn.c
r21330r21331
1/**************************************************************************************************
2
3    Sega Saturn & Sega ST-V (Sega Titan Video) HW (c) 1994 Sega
4
5    Driver by David Haywood, Angelo Salese, Olivier Galibert & Mariusz Wojcieszek
6    SCSP driver provided by R.Belmont, based on ElSemi's SCSP sound chip emulator
7    CD Block driver provided by ANY, based on sthief original emulator
8    Many thanks to Guru, Fabien, Runik and Charles MacDonald for the help given.
9
10===================================================================================================
11
12Notes:
13-To enter into an Advanced Test Mode,keep pressed the Test Button (F2) on the start-up.
14-Memo: Some tests done on the original & working PCB,to be implemented:
15 -The AD-Stick returns 0x00 or a similar value.
16 -The Ports E,F & G must return 0xff
17
18TODO:
19(Main issues)
20- decap the SH-1, used for CD block (needed especially for Sega Saturn)
21- IRQs: some games have some issues with timing accurate IRQs, check/fix all of them.
22- The Cart-Dev mode hangs even with the -dev bios,I would like to see what it does on the real HW.
23- IC13 games on the dev bios doesn't even load the cartridge / crashes the emulation at start-up,
24  rom rearrange needed?
25- SCU DSP still has its fair share of issues, it also needs to be converted to CPU structure;
26- Add the RS232c interface (serial port), needed by fhboxers (accesses some ports in the a-bus dummy range).
27- Video emulation is nowhere near perfection.
28- Reimplement the idle skip if possible.
29- Properly emulate the protection chips, used by several games (check stvprot.c for more info)
30- Move SCU device into its respective file;
31- Split ST-V and Saturn files properly;
32
33(per-game issues)
34- stress: accesses the Sound Memory Expansion Area (0x05a80000-0x05afffff), unknown purpose;
35
36- smleague / finlarch: it randomly hangs / crashes,it works if you use a ridiculous MCFG_INTERLEAVE number,might need strict
37  SH-2 synching or it's actually a m68k comms issue.
38
39- groovef: ugly back screen color, caused by incorrect usage of the Color Calculation function.
40
41- myfairld: Apparently this game gives a black screen (either test mode and in-game mode),but let it wait for about
42  10 seconds and the game will load everything. This is because of a hellishly slow m68k sub-routine located at 54c2.
43  Likely to not be a bug but an in-game design issue.
44
45- danchih / danchiq: currently hangs randomly (regression).
46
47- batmanfr: Missing sound,caused by an extra ADSP chip which is on the cart.The CPU is a
48  ADSP-2181,and it's the same used by NBA Jam Extreme (ZN game).
49
50- vfremix: when you play as Akira, there is a problem with third match: game doesn't upload all textures
51  and tiles and doesn't enable display, although gameplay is normal - wait a while to get back
52  to title screen after losing a match
53
54- vfremix: various problems with SCU DSP: Jeffry causes a black screen hang. Akira's kick sometimes
55  sends the opponent out of the ring from whatever position.
56
57
58****************************************************************************************************/
59
60#include "emu.h"
61#include "cpu/m68000/m68000.h"
62#include "machine/eeprom.h"
63#include "cpu/sh2/sh2.h"
64#include "machine/scudsp.h"
65#include "sound/scsp.h"
66#include "sound/cdda.h"
67#include "machine/smpc.h"
68#include "includes/stv.h"
69#include "imagedev/chd_cd.h"
70#include "imagedev/cartslot.h"
71#include "coreutil.h"
72
73
74/* TODO: do this in a verboselog style */
75#define LOG_CDB  0
76#define LOG_SCU  1
77#define LOG_IRQ  0
78#define LOG_IOGA 0
79
80int saturn_state::DectoBCD(int num)
81{
82   int i, cnt = 0, tmp, res = 0;
83
84   while (num > 0) {
85      tmp = num;
86      while (tmp >= 10) tmp %= 10;
87      for (i=0; i<cnt; i++)
88         tmp *= 16;
89      res += tmp;
90      cnt++;
91      num /= 10;
92   }
93
94   return res;
95}
96
97/**************************************************************************************/
98
99/*
100
101SCU Handling
102
103*/
104
105/**********************************************************************************
106SCU Register Table
107offset,relative address
108Registers are in long words.
109===================================================================================
1100     0000  Level 0 DMA Set Register
1111     0004
1122     0008
1133     000c
1144     0010
1155     0014
1166     0018
1177     001c
1188     0020  Level 1 DMA Set Register
1199     0024
12010    0028
12111    002c
12212    0030
12313    0034
12414    0038
12515    003c
12616    0040  Level 2 DMA Set Register
12717    0044
12818    0048
12919    004c
13020    0050
13121    0054
13222    0058
13323    005c
13424    0060  DMA Forced Stop
13525    0064
13626    0068
13727    006c
13828    0070  <Free>
13929    0074
14030    0078
14131    007c  DMA Status Register
14232    0080  DSP Program Control Port
14333    0084  DSP Program RAM Data Port
14434    0088  DSP Data RAM Address Port
14535    008c  DSP Data RAM Data Port
14636    0090  Timer 0 Compare Register
14737    0094  Timer 1 Set Data Register
14838    0098  Timer 1 Mode Register
14939    009c  <Free>
15040    00a0  Interrupt Mask Register
15141    00a4  Interrupt Status Register
15242    00a8  A-Bus Interrupt Acknowledge
15343    00ac  <Free>
15444    00b0  A-Bus Set Register
15545    00b4
15646    00b8  A-Bus Refresh Register
15747    00bc  <Free>
15848    00c0
15949    00c4  SCU SDRAM Select Register
16050    00c8  SCU Version Register
16151    00cc  <Free>
16252    00cf
163===================================================================================
164DMA Status Register(32-bit):
165xxxx xxxx x--- xx-- xx-- xx-- xx-- xx-- UNUSED
166---- ---- -x-- ---- ---- ---- ---- ---- DMA DSP-Bus access
167---- ---- --x- ---- ---- ---- ---- ---- DMA B-Bus access
168---- ---- ---x ---- ---- ---- ---- ---- DMA A-Bus access
169---- ---- ---- --x- ---- ---- ---- ---- DMA lv 1 interrupt
170---- ---- ---- ---x ---- ---- ---- ---- DMA lv 0 interrupt
171---- ---- ---- ---- --x- ---- ---- ---- DMA lv 2 in stand-by
172---- ---- ---- ---- ---x ---- ---- ---- DMA lv 2 in operation
173---- ---- ---- ---- ---- --x- ---- ---- DMA lv 1 in stand-by
174---- ---- ---- ---- ---- ---x ---- ---- DMA lv 1 in operation
175---- ---- ---- ---- ---- ---- --x- ---- DMA lv 0 in stand-by
176---- ---- ---- ---- ---- ---- ---x ---- DMA lv 0 in operation
177---- ---- ---- ---- ---- ---- ---- --x- DSP side DMA in stand-by
178---- ---- ---- ---- ---- ---- ---- ---x DSP side DMA in operation
179
180**********************************************************************************/
181/*
182DMA TODO:
183-Remove CD transfer DMA hack (tied with CD block bug(s)?)
184-Add timings(but how fast are each DMA?).
185-Add level priority & DMA status register.
186*/
187
188#define DIRECT_MODE(_lv_)           (!(m_scu_regs[5+(_lv_*8)] & 0x01000000))
189#define INDIRECT_MODE(_lv_)           (m_scu_regs[5+(_lv_*8)] & 0x01000000)
190#define DRUP(_lv_)                    (m_scu_regs[5+(_lv_*8)] & 0x00010000)
191#define DWUP(_lv_)                    (m_scu_regs[5+(_lv_*8)] & 0x00000100)
192
193/*These macros sets the various DMA status flags.*/
194#define DnMV_1(_ch_) m_scu.status|=(0x10 << 4 * _ch_)
195#define DnMV_0(_ch_) m_scu.status&=~(0x10 << 4 * _ch_)
196
197/*For area checking*/
198#define BIOS_BUS(var)   (var & 0x07000000) == 0
199#define ABUS(_lv_)       ((m_scu.src[_lv_] & 0x07000000) >= 0x02000000) && ((m_scu.src[_lv_] & 0x07000000) <= 0x04000000)
200#define BBUS(_lv_)       ((scu_##_lv_ & 0x07ffffff) >= 0x05a00000) && ((scu_##_lv_ & 0x07ffffff) <= 0x05ffffff)
201#define VDP1_REGS(_lv_)  ((scu_##_lv_ & 0x07ffffff) >= 0x05d00000) && ((scu_##_lv_ & 0x07ffffff) <= 0x05dfffff)
202#define VDP2(_lv_)       ((scu_##_lv_ & 0x07ffffff) >= 0x05e00000) && ((scu_##_lv_ & 0x07ffffff) <= 0x05fdffff)
203#define WORK_RAM_L(_lv_) ((scu_##_lv_ & 0x07ffffff) >= 0x00200000) && ((scu_##_lv_ & 0x07ffffff) <= 0x002fffff)
204#define WORK_RAM_H(var) (var & 0x07000000) == 0x06000000
205#define SOUND_RAM(_lv_)  ((scu_##_lv_ & 0x07ffffff) >= 0x05a00000) && ((scu_##_lv_ & 0x07ffffff) <= 0x05afffff)
206
207void saturn_state::scu_do_transfer(UINT8 event)
208{
209   address_space &space = machine().device("maincpu")->memory().space(AS_PROGRAM);
210   int i;
211
212   for(i=0;i<3;i++)
213   {
214      if(m_scu.enable_mask[i] && m_scu.start_factor[i] == event)
215      {
216         if(DIRECT_MODE(i))      { scu_dma_direct(space,i);   }
217         else                    { scu_dma_indirect(space,i); }
218      }
219   }
220}
221
222/* test pending irqs */
223void saturn_state::scu_test_pending_irq()
224{
225   int i;
226   const int irq_level[32] = { 0xf, 0xe, 0xd, 0xc,
227                        0xb, 0xa, 0x9, 0x8,
228                        0x8, 0x6, 0x6, 0x5,
229                        0x3, 0x2,  -1,  -1,
230                        0x7, 0x7, 0x7, 0x7,
231                        0x4, 0x4, 0x4, 0x4,
232                        0x1, 0x1, 0x1, 0x1,
233                        0x1, 0x1, 0x1, 0x1  };
234
235   for(i=0;i<32;i++)
236   {
237      if((!(m_scu.ism & 1 << i)) && (m_scu.ist & 1 << i))
238      {
239         if(irq_level[i] != -1) /* TODO: cheap check for undefined irqs */
240         {
241            m_maincpu->set_input_line_and_vector(irq_level[i], HOLD_LINE, 0x40 + i);
242            m_scu.ist &= ~(1 << i);
243            return; /* avoid spurious irqs, correct? */
244         }
245      }
246   }
247}
248
249READ32_MEMBER(saturn_state::saturn_scu_r)
250{
251   UINT32 res;
252
253   /*TODO: write only registers must return 0 or open bus */
254   switch(offset)
255   {
256      case 0x5c/4:
257      //  Super Major League and Shin Megami Tensei - Akuma Zensho reads from there (undocumented), DMA status mirror?
258         if(LOG_SCU && !space.debugger_access()) logerror("(PC=%08x) DMA status reg read\n",space.device().safe_pc());
259         res = m_scu.status;
260         break;
261      case 0x7c/4:
262         if(LOG_SCU && !space.debugger_access()) logerror("(PC=%08x) DMA status reg read\n",space.device().safe_pc());
263         res = m_scu.status;
264         break;
265      case 0x80/4:
266         res = dsp_prg_ctrl_r(space);
267         break;
268      case 0x8c/4:
269         if(LOG_SCU && !space.debugger_access()) logerror( "DSP mem read at %08X\n", m_scu_regs[34]);
270         res = dsp_ram_addr_r();
271         break;
272      case 0xa0/4:
273         if(LOG_SCU && !space.debugger_access()) logerror("(PC=%08x) IRQ mask reg read %08x MASK=%08x\n",space.device().safe_pc(),mem_mask,m_scu_regs[0xa0/4]);
274         res = m_scu.ism;
275         break;
276      case 0xa4/4:
277         if(LOG_SCU && !space.debugger_access()) logerror("(PC=%08x) IRQ status reg read MASK=%08x IST=%08x | ISM=%08x\n",space.device().safe_pc(),mem_mask,m_scu.ist,m_scu.ism);
278         /* TODO: Bug! trips an HW fault. Basically, it tries to read the IST bit 1 with that irq enabled.
279             Densetsu no Ogre Battle doesn't like this, so it needs investigation ...
280         */
281//         res = m_scu.ist | ~m_scu.ism;
282         res = m_scu.ist;
283         break;
284      case 0xc8/4:
285         if(LOG_SCU && !space.debugger_access()) logerror("(PC=%08x) SCU version reg read\n",space.device().safe_pc());
286         res = 0x00000004;/*SCU Version 4, OK? */
287         break;
288      default:
289         if(LOG_SCU && !space.debugger_access()) logerror("(PC=%08x) SCU reg read at %d = %08x\n",space.device().safe_pc(),offset,m_scu_regs[offset]);
290         res = m_scu_regs[offset];
291         break;
292   }
293
294   return res;
295}
296
297#define DMA_CH ((offset & 0x18) / 8)
298
299WRITE32_MEMBER(saturn_state::saturn_scu_w)
300{
301   COMBINE_DATA(&m_scu_regs[offset]);
302
303   switch(offset)
304   {
305      /*LV 0 DMA*/
306      case 0x00/4: case 0x20/4: case 0x40/4:  m_scu.src[DMA_CH]  = ((m_scu_regs[offset] & 0x07ffffff) >> 0); break;
307      case 0x04/4: case 0x24/4: case 0x44/4:  m_scu.dst[DMA_CH]  = ((m_scu_regs[offset] & 0x07ffffff) >> 0); break;
308      case 0x08/4: case 0x28/4: case 0x48/4:  m_scu.size[DMA_CH] = ((m_scu_regs[offset] & ((offset == 2) ? 0x000fffff : 0xfff)) >> 0); break;
309      case 0x0c/4: case 0x2c/4: case 0x4c/4:
310         m_scu.src_add[DMA_CH] = (m_scu_regs[offset] & 0x100) ? 4 : 0;
311         m_scu.dst_add[DMA_CH] = 1 << (m_scu_regs[offset] & 7);
312         if(m_scu.dst_add[DMA_CH] == 1) { m_scu.dst_add[DMA_CH] = 0; }
313         break;
314      case 0x10/4: case 0x30/4: case 0x50/4:
315         m_scu.enable_mask[DMA_CH] = (data & 0x100) >> 8;
316         if(m_scu.enable_mask[DMA_CH] && m_scu.start_factor[DMA_CH] == 7 && m_scu_regs[offset] & 1)
317         {
318            if(DIRECT_MODE(DMA_CH)) { scu_dma_direct(space,DMA_CH);   }
319            else                    { scu_dma_indirect(space,DMA_CH); }
320            m_scu_regs[offset]&=~1;//disable starting bit.
321         }
322         break;
323      case 0x14/4: case 0x34/4: case 0x54/4:
324         if(INDIRECT_MODE(DMA_CH))
325         {
326            //if(LOG_SCU) logerror("Indirect Mode DMA lv %d set\n",DMA_CH);
327            if(!DWUP(DMA_CH)) m_scu.index[DMA_CH] = m_scu.dst[DMA_CH];
328         }
329
330         m_scu.start_factor[DMA_CH] = m_scu_regs[offset] & 7;
331         break;
332
333      case 0x60/4:
334         if(LOG_SCU) logerror("DMA Forced Stop Register set = %02x\n",m_scu_regs[24]);
335         break;
336      case 0x7c/4: if(LOG_SCU) logerror("Warning: DMA status WRITE! Offset %02x(%d)\n",offset*4,offset); break;
337      /*DSP section*/
338      case 0x80/4:
339         /* TODO: you can't overwrite some flags with this */
340         dsp_prg_ctrl_w(space, m_scu_regs[offset]);
341         if(LOG_SCU) logerror("SCU DSP: Program Control Port Access %08x\n",data);
342         break;
343      case 0x84/4:
344         dsp_prg_data(m_scu_regs[offset]);
345         if(LOG_SCU) logerror("SCU DSP: Program RAM Data Port Access %08x\n",data);
346         break;
347      case 0x88/4:
348         dsp_ram_addr_ctrl(m_scu_regs[offset]);
349         if(LOG_SCU) logerror("SCU DSP: Data RAM Address Port Access %08x\n",data);
350         break;
351      case 0x8c/4:
352         dsp_ram_addr_w(m_scu_regs[offset]);
353         if(LOG_SCU) logerror("SCU DSP: Data RAM Data Port Access %08x\n",data);
354         break;
355      case 0x90/4: /*if(LOG_SCU) logerror("timer 0 compare data = %03x\n",m_scu_regs[36]);*/ break;
356      case 0x94/4: /*if(LOG_SCU) logerror("timer 1 set data = %08x\n",m_scu_regs[37]);*/ break;
357      case 0x98/4: /*if(LOG_SCU) logerror("timer 1 mode data = %08x\n",m_scu_regs[38]);*/ break;
358      case 0xa0/4: /* IRQ mask */
359         m_scu.ism = m_scu_regs[0xa0/4];
360         scu_test_pending_irq();
361         break;
362      case 0xa4/4: /* IRQ control */
363         if(LOG_SCU) logerror("PC=%08x IRQ status reg set:%08x %08x\n",space.device().safe_pc(),m_scu_regs[41],mem_mask);
364         m_scu.ist &= m_scu_regs[offset];
365         scu_test_pending_irq();
366         break;
367      case 0xa8/4:
368         /* This sends an irq signal to the extra devices connected to the A-Bus, not really needed for now. */
369         //if(LOG_SCU) logerror("A-Bus IRQ ACK %08x\n",m_scu_regs[42]);
370         break;
371      case 0xc4/4: if(LOG_SCU) logerror("SCU SDRAM set: %02x\n",m_scu_regs[49]); break;
372      default: if(LOG_SCU) logerror("Warning: unused SCU reg set %d = %08x\n",offset,data);
373   }
374}
375
376/*Lv 0 DMA end irq*/
377TIMER_CALLBACK_MEMBER(saturn_state::dma_lv0_ended )
378{
379   if(!(m_scu.ism & IRQ_DMALV0))
380      m_maincpu->set_input_line_and_vector(5, HOLD_LINE, 0x4b);
381   else
382      m_scu.ist |= (IRQ_DMALV0);
383
384   DnMV_0(0);
385}
386
387/*Lv 1 DMA end irq*/
388TIMER_CALLBACK_MEMBER(saturn_state::dma_lv1_ended)
389{
390   if(!(m_scu.ism & IRQ_DMALV1))
391      m_maincpu->set_input_line_and_vector(6, HOLD_LINE, 0x4a);
392   else
393      m_scu.ist |= (IRQ_DMALV1);
394
395   DnMV_0(1);
396}
397
398/*Lv 2 DMA end irq*/
399TIMER_CALLBACK_MEMBER(saturn_state::dma_lv2_ended)
400{
401   if(!(m_scu.ism & IRQ_DMALV2))
402      m_maincpu->set_input_line_and_vector(6, HOLD_LINE, 0x49);
403   else
404      m_scu.ist |= (IRQ_DMALV2);
405
406   DnMV_0(2);
407}
408
409void saturn_state::scu_single_transfer(address_space &space, UINT32 src, UINT32 dst,UINT8 *src_shift)
410{
411   UINT32 src_data;
412
413   if(src & 1)
414   {
415      /* Road Blaster does a work ram h to color ram with offsetted source address, do some data rotation */
416      src_data = ((space.read_dword(src & 0x07fffffc) & 0x00ffffff)<<8);
417      src_data |= ((space.read_dword((src & 0x07fffffc)+4) & 0xff000000) >> 24);
418      src_data >>= (*src_shift)*16;
419   }
420   else
421      src_data = space.read_dword(src & 0x07fffffc) >> (*src_shift)*16;
422
423   space.write_word(dst,src_data);
424
425   *src_shift ^= 1;
426}
427
428void saturn_state::scu_dma_direct(address_space &space, UINT8 dma_ch)
429{
430   UINT32 tmp_src,tmp_dst,total_size;
431   UINT8 cd_transfer_flag;
432
433   if(m_scu.src_add[dma_ch] == 0 || (m_scu.dst_add[dma_ch] != 2 && m_scu.dst_add[dma_ch] != 4))
434   {
435   if(LOG_SCU) printf("DMA lv %d transfer START\n"
436                     "Start %08x End %08x Size %04x\n",dma_ch,m_scu.src[dma_ch],m_scu.dst[dma_ch],m_scu.size[dma_ch]);
437   if(LOG_SCU) printf("Start Add %04x Destination Add %04x\n",m_scu.src_add[dma_ch],m_scu.dst_add[dma_ch]);
438   }
439
440   /* TODO: Game Basic and World Cup 98 trips this, according to the docs the SCU can't transfer from BIOS area (can't communicate from/to that bus) */
441   if(BIOS_BUS(m_scu.src[dma_ch]))
442   {
443      popmessage("Warning: SCU transfer from BIOS area, contact MAMEdev");
444      if(!(m_scu.ism & IRQ_DMAILL))
445         m_maincpu->set_input_line_and_vector(3, HOLD_LINE, 0x4c);
446      else
447         m_scu.ist |= (IRQ_DMAILL);
448      return;
449   }
450
451   DnMV_1(dma_ch);
452
453   /* max size */
454   if(m_scu.size[dma_ch] == 0) { m_scu.size[dma_ch] = (dma_ch == 0) ? 0x00100000 : 0x1000; }
455
456   tmp_src = tmp_dst = 0;
457
458   total_size = m_scu.size[dma_ch];
459   if(!(DRUP(dma_ch))) tmp_src = m_scu.src[dma_ch];
460   if(!(DWUP(dma_ch))) tmp_dst = m_scu.dst[dma_ch];
461
462   cd_transfer_flag = m_scu.src_add[dma_ch] == 0 && m_scu.src[dma_ch] == 0x05818000;
463
464   /* TODO: Many games directly accesses CD-ROM register 0x05818000, it must be a dword access with current implementation otherwise it won't work */
465   if(cd_transfer_flag)
466   {
467      int i;
468      if(WORK_RAM_H(m_scu.dst[dma_ch]))
469         m_scu.dst_add[dma_ch] = 4;
470      else
471         m_scu.dst_add[dma_ch] <<= 1;
472
473      for (i = 0; i < m_scu.size[dma_ch];i+=m_scu.dst_add[dma_ch])
474      {
475         space.write_dword(m_scu.dst[dma_ch],space.read_dword(m_scu.src[dma_ch]));
476         if(m_scu.dst_add[dma_ch] == 8)
477            space.write_dword(m_scu.dst[dma_ch]+4,space.read_dword(m_scu.src[dma_ch]));
478
479         m_scu.src[dma_ch]+=m_scu.src_add[dma_ch];
480         m_scu.dst[dma_ch]+=m_scu.dst_add[dma_ch];
481      }
482   }
483   else
484   {
485      int i;
486      UINT8  src_shift;
487
488      src_shift = ((m_scu.src[dma_ch] & 2) >> 1) ^ 1;
489
490      for (i = 0; i < m_scu.size[dma_ch];i+=2)
491      {
492         scu_single_transfer(space,m_scu.src[dma_ch],m_scu.dst[dma_ch],&src_shift);
493
494         if(src_shift)
495            m_scu.src[dma_ch]+=m_scu.src_add[dma_ch];
496
497         /* if target is Work RAM H, the add value is fixed, behaviour confirmed by Final Romance 2, Virtual Mahjong and Burning Rangers */
498         m_scu.dst[dma_ch]+=(WORK_RAM_H(m_scu.dst[dma_ch])) ? 2 : m_scu.dst_add[dma_ch];
499      }
500   }
501
502   /* Burning Rangers doesn't agree with this. */
503//   m_scu.size[dma_ch] = 0;
504   if(!(DRUP(dma_ch))) m_scu.src[dma_ch] = tmp_src;
505   if(!(DWUP(dma_ch))) m_scu.dst[dma_ch] = tmp_dst;
506
507   {
508      /*TODO: change DMA into DRQ model. Timing is a guess.  */
509      switch(dma_ch)
510      {
511         case 0: machine().scheduler().timer_set(m_maincpu->cycles_to_attotime(total_size/4), timer_expired_delegate(FUNC(saturn_state::dma_lv0_ended),this)); break;
512         case 1: machine().scheduler().timer_set(m_maincpu->cycles_to_attotime(total_size/4), timer_expired_delegate(FUNC(saturn_state::dma_lv1_ended),this)); break;
513         case 2: machine().scheduler().timer_set(m_maincpu->cycles_to_attotime(total_size/4), timer_expired_delegate(FUNC(saturn_state::dma_lv2_ended),this)); break;
514      }
515   }
516}
517
518void saturn_state::scu_dma_indirect(address_space &space,UINT8 dma_ch)
519{
520   /*Helper to get out of the cycle*/
521   UINT8 job_done = 0;
522   /*temporary storage for the transfer data*/
523   UINT32 tmp_src;
524   UINT32 indirect_src,indirect_dst;
525   INT32 indirect_size;
526   UINT32 total_size = 0;
527
528   DnMV_1(dma_ch);
529
530   m_scu.index[dma_ch] = m_scu.dst[dma_ch];
531
532   do{
533      tmp_src = m_scu.index[dma_ch];
534
535      indirect_size = space.read_dword(m_scu.index[dma_ch]);
536      indirect_src  = space.read_dword(m_scu.index[dma_ch]+8);
537      indirect_dst  = space.read_dword(m_scu.index[dma_ch]+4);
538
539      /*Indirect Mode end factor*/
540      if(indirect_src & 0x80000000)
541         job_done = 1;
542
543      if(m_scu.src_add[dma_ch] == 0 || (m_scu.dst_add[dma_ch] != 2))
544      {
545         if(LOG_SCU) printf("DMA lv %d indirect mode transfer START\n"
546                        "Index %08x Start %08x End %08x Size %04x\n",dma_ch,tmp_src,indirect_src,indirect_dst,indirect_size);
547         if(LOG_SCU) printf("Start Add %04x Destination Add %04x\n",m_scu.src_add[dma_ch],m_scu.dst_add[dma_ch]);
548      }
549
550      indirect_src &=0x07ffffff;
551      indirect_dst &=0x07ffffff;
552      indirect_size &= ((dma_ch == 0) ? 0xfffff : 0x3ffff); //TODO: Guardian Heroes sets up a 0x23000 transfer for the FMV?
553
554      if(indirect_size == 0) { indirect_size = (dma_ch == 0) ? 0x00100000 : 0x2000; }
555
556      {
557         int i;
558         UINT8  src_shift;
559
560         src_shift = ((indirect_src & 2) >> 1) ^ 1;
561
562         for (i = 0; i < indirect_size;i+=2)
563         {
564            scu_single_transfer(space,indirect_src,indirect_dst,&src_shift);
565
566            if(src_shift)
567               indirect_src+=m_scu.src_add[dma_ch];
568
569            indirect_dst+= (WORK_RAM_H(indirect_dst)) ? 2 : m_scu.dst_add[dma_ch];
570         }
571      }
572
573      /* Guess: Size + data acquire (1 cycle for src/dst/size) */
574      total_size += indirect_size + 3*4;
575
576      //if(DRUP(0)) space.write_dword(tmp_src+8,m_scu.src[0]|job_done ? 0x80000000 : 0);
577      //if(DWUP(0)) space.write_dword(tmp_src+4,m_scu.dst[0]);
578
579      m_scu.index[dma_ch] = tmp_src+0xc;
580
581   }while(job_done == 0);
582
583   {
584      /*TODO: change DMA into DRQ model. Timing is a guess.  */
585      switch(dma_ch)
586      {
587         case 0: machine().scheduler().timer_set(m_maincpu->cycles_to_attotime(total_size/4), timer_expired_delegate(FUNC(saturn_state::dma_lv0_ended),this)); break;
588         case 1: machine().scheduler().timer_set(m_maincpu->cycles_to_attotime(total_size/4), timer_expired_delegate(FUNC(saturn_state::dma_lv1_ended),this)); break;
589         case 2: machine().scheduler().timer_set(m_maincpu->cycles_to_attotime(total_size/4), timer_expired_delegate(FUNC(saturn_state::dma_lv2_ended),this)); break;
590      }
591   }
592}
593
594
595/**************************************************************************************/
596
597WRITE16_MEMBER(saturn_state::saturn_soundram_w)
598{
599   //machine().scheduler().synchronize(); // force resync
600
601   COMBINE_DATA(&m_sound_ram[offset]);
602}
603
604READ16_MEMBER(saturn_state::saturn_soundram_r)
605{
606   //machine().scheduler().synchronize(); // force resync
607
608   return m_sound_ram[offset];
609}
610
611/* communication,SLAVE CPU acquires data from the MASTER CPU and triggers an irq.  */
612WRITE32_MEMBER(saturn_state::minit_w)
613{
614   //logerror("cpu %s (PC=%08X) MINIT write = %08x\n", space.device().tag(), space.device().safe_pc(),data);
615   machine().scheduler().boost_interleave(m_minit_boost_timeslice, attotime::from_usec(m_minit_boost));
616   machine().scheduler().trigger(1000);
617   machine().scheduler().synchronize(); // force resync
618   sh2_set_frt_input(m_slave, PULSE_LINE);
619}
620
621WRITE32_MEMBER(saturn_state::sinit_w)
622{
623   //logerror("cpu %s (PC=%08X) SINIT write = %08x\n", space.device().tag(), space.device().safe_pc(),data);
624   machine().scheduler().boost_interleave(m_sinit_boost_timeslice, attotime::from_usec(m_sinit_boost));
625   machine().scheduler().synchronize(); // force resync
626   sh2_set_frt_input(m_maincpu, PULSE_LINE);
627}
628
629/*
630TODO:
631Some games seems to not like either MAME's interleave system and/or SH-2 DRC, causing an hard crash.
632Reported games are:
633Blast Wind (before FMV)
634Choro Q Park (car selection)
635060311E4: MOV.L R14,@-SP ;R14 = 0x60ffba0 / R15 = 0x60ffba0
636060311E6: MOV SP,R14 ;R14 = 0x60ffba0 / R15 = 0x60ffb9c / [0x60ffb9c] <- 0x60ffba0
637060311E8: MOV.L @SP+,R14 ;R14 = 0x60ffb9c / R15 = 0x60ffb9c / [0x60ffb9c] -> R14
638060311EA: RTS ;R14 = 0x60ffba0 / R15 = 0x60ffba0
639060311EC: NOP
64006031734: MULS.W R9, R8 ;R14 = 0x60ffba0 / R15 = 0x60ffba0 / EA = 0x60311E4
641on DRC this becomes:
642R14 0x6031b78 (cause of the crash later on), R15 = 0x60ffba4 and EA = 0
643
644Shinrei Jusatsushi Taromaru (options menu)
645
646*/
647
648WRITE32_MEMBER(saturn_state::saturn_minit_w)
649{
650   //logerror("cpu %s (PC=%08X) MINIT write = %08x\n", space.device().tag(), space.device().safe_pc(),data);
651   if(m_fake_comms->read() & 1)
652      machine().scheduler().synchronize(); // force resync
653   else
654   {
655      machine().scheduler().boost_interleave(m_minit_boost_timeslice, attotime::from_usec(m_minit_boost));
656      machine().scheduler().trigger(1000);
657   }
658
659   sh2_set_frt_input(m_slave, PULSE_LINE);
660}
661
662WRITE32_MEMBER(saturn_state::saturn_sinit_w)
663{
664   //logerror("cpu %s (PC=%08X) SINIT write = %08x\n", space.device().tag(), space.device().safe_pc(),data);
665   if(m_fake_comms->read() & 1)
666      machine().scheduler().synchronize(); // force resync
667   else
668      machine().scheduler().boost_interleave(m_sinit_boost_timeslice, attotime::from_usec(m_sinit_boost));
669
670   sh2_set_frt_input(m_maincpu, PULSE_LINE);
671}
672
673
674READ8_MEMBER(saturn_state::saturn_backupram_r)
675{
676   if(!(offset & 1))
677      return 0; // yes, it makes sure the "holes" are there.
678
679   return m_backupram[offset >> 1] & 0xff;
680}
681
682WRITE8_MEMBER(saturn_state::saturn_backupram_w)
683{
684   if(!(offset & 1))
685      return;
686
687   m_backupram[offset >> 1] = data;
688}
689
690/* TODO: if you change the driver configuration then NVRAM contents gets screwed, needs mods in MAME framework */
691static NVRAM_HANDLER(saturn)
692{
693   saturn_state *state = machine.driver_data<saturn_state>();
694   static const UINT32 BUP_SIZE = 32*1024;
695   static const UINT32 EBUP_SIZE = 0;//0x100000; // TODO: can't support more than 8 Mbit
696   UINT8 backup_file[(BUP_SIZE)+EBUP_SIZE+4];
697   static const UINT8 init[16] =
698   {
699      'B', 'a', 'c', 'k', 'U', 'p', 'R', 'a', 'm', ' ', 'F', 'o', 'r', 'm', 'a', 't'
700   };
701   UINT32 i;
702
703   if (read_or_write)
704   {
705      for(i=0;i<BUP_SIZE;i++)
706         backup_file[i] = state->m_backupram[i];
707      #if 0
708      for(i=0;i<EBUP_SIZE;i++)
709         backup_file[i+BUP_SIZE] = state->m_cart_backupram[i];
710      #endif
711      for(i=0;i<4;i++)
712         backup_file[i+(BUP_SIZE)+EBUP_SIZE] = state->m_smpc.SMEM[i];
713
714      file->write(backup_file, (BUP_SIZE)+EBUP_SIZE+4);
715   }
716   else
717   {
718      if (file)
719      {
720         file->read(backup_file, (BUP_SIZE)+EBUP_SIZE+4);
721
722         for(i=0;i<BUP_SIZE;i++)
723            state->m_backupram[i] = backup_file[i];
724         #if 0
725         for(i=0;i<EBUP_SIZE;i++)
726            state->m_cart_backupram[i] = backup_file[i+BUP_SIZE];
727         #endif
728         for(i=0;i<4;i++)
729            state->m_smpc.SMEM[i] = backup_file[i+BUP_SIZE+EBUP_SIZE];
730      }
731      else
732      {
733         UINT8 j;
734         memset(state->m_backupram, 0, BUP_SIZE);
735         for (i = 0; i < 4; i++)
736         {
737            for(j=0;j<16;j++)
738               state->m_backupram[i*16+j] = init[j];
739         }
740         #if 0
741         memset(state->m_cart_backupram, 0, EBUP_SIZE);
742         for (i = 0; i < 32; i++)
743         {
744            for(j=0;j<16;j++)
745               state->m_cart_backupram[i*16+j] = init[j];
746         }
747         #endif
748         memset(state->m_smpc.SMEM, 0, 4); // TODO: default for each region
749      }
750   }
751}
752
753READ8_MEMBER(saturn_state::saturn_cart_type_r)
754{
755   const int cart_ram_header[7] = { 0xff, 0x21, 0x22, 0x23, 0x24, 0x5a, 0x5c };
756
757   return cart_ram_header[m_cart_type];
758}
759
760/* TODO: Bug! accesses this one, if returning 0 the SH-2 hard-crashes. Might be an actual bug with the CD block. */
761READ32_HANDLER( saturn_state::abus_dummy_r )
762{
763   logerror("A-Bus Dummy access %08x\n",offset*4);
764   return -1;
765}
766
767static ADDRESS_MAP_START( saturn_mem, AS_PROGRAM, 32, saturn_state )
768   AM_RANGE(0x00000000, 0x0007ffff) AM_ROM AM_SHARE("share6")  // bios
769   AM_RANGE(0x00100000, 0x0010007f) AM_READWRITE8(saturn_SMPC_r, saturn_SMPC_w,0xffffffff)
770   AM_RANGE(0x00180000, 0x0018ffff) AM_READWRITE8(saturn_backupram_r, saturn_backupram_w,0xffffffff) AM_SHARE("share1")
771   AM_RANGE(0x00200000, 0x002fffff) AM_RAM AM_MIRROR(0x20100000) AM_SHARE("workram_l")
772   AM_RANGE(0x01000000, 0x017fffff) AM_WRITE(saturn_minit_w)
773   AM_RANGE(0x01800000, 0x01ffffff) AM_WRITE(saturn_sinit_w)
774   AM_RANGE(0x02000000, 0x023fffff) AM_ROM AM_SHARE("share7") AM_REGION("maincpu", 0x80000)    // cartridge space
775//  AM_RANGE(0x02400000, 0x027fffff) AM_RAM //cart RAM area, dynamically allocated
776//  AM_RANGE(0x04000000, 0x047fffff) AM_RAM //backup RAM area, dynamically allocated
777   AM_RANGE(0x04fffffc, 0x04ffffff) AM_READ8(saturn_cart_type_r,0x000000ff)
778   AM_RANGE(0x05000000, 0x057fffff) AM_READ(abus_dummy_r)
779   AM_RANGE(0x05800000, 0x0589ffff) AM_READWRITE(stvcd_r, stvcd_w)
780   /* Sound */
781   AM_RANGE(0x05a00000, 0x05a7ffff) AM_READWRITE16(saturn_soundram_r, saturn_soundram_w,0xffffffff)
782   AM_RANGE(0x05b00000, 0x05b00fff) AM_DEVREADWRITE16_LEGACY("scsp", scsp_r, scsp_w, 0xffffffff)
783   /* VDP1 */
784   AM_RANGE(0x05c00000, 0x05c7ffff) AM_READWRITE(saturn_vdp1_vram_r, saturn_vdp1_vram_w)
785   AM_RANGE(0x05c80000, 0x05cbffff) AM_READWRITE(saturn_vdp1_framebuffer0_r, saturn_vdp1_framebuffer0_w)
786   AM_RANGE(0x05d00000, 0x05d0001f) AM_READWRITE16(saturn_vdp1_regs_r, saturn_vdp1_regs_w,0xffffffff)
787   AM_RANGE(0x05e00000, 0x05e7ffff) AM_MIRROR(0x80000) AM_READWRITE(saturn_vdp2_vram_r, saturn_vdp2_vram_w)
788   AM_RANGE(0x05f00000, 0x05f7ffff) AM_READWRITE(saturn_vdp2_cram_r, saturn_vdp2_cram_w)
789   AM_RANGE(0x05f80000, 0x05fbffff) AM_READWRITE16(saturn_vdp2_regs_r, saturn_vdp2_regs_w,0xffffffff)
790   AM_RANGE(0x05fe0000, 0x05fe00cf) AM_READWRITE(saturn_scu_r, saturn_scu_w)
791   AM_RANGE(0x06000000, 0x060fffff) AM_RAM AM_MIRROR(0x21f00000) AM_SHARE("workram_h")
792   AM_RANGE(0x20000000, 0x2007ffff) AM_ROM AM_SHARE("share6")  // bios mirror
793   AM_RANGE(0x22000000, 0x24ffffff) AM_ROM AM_SHARE("share7")  // cart mirror
794   AM_RANGE(0x45000000, 0x46ffffff) AM_WRITENOP
795   AM_RANGE(0x60000000, 0x600003ff) AM_WRITENOP // cache address array
796   AM_RANGE(0xc0000000, 0xc00007ff) AM_RAM // cache data array, Dragon Ball Z sprites relies on this
797ADDRESS_MAP_END
798
799static ADDRESS_MAP_START( sound_mem, AS_PROGRAM, 16, saturn_state )
800   AM_RANGE(0x000000, 0x0fffff) AM_RAM AM_SHARE("sound_ram")
801   AM_RANGE(0x100000, 0x100fff) AM_DEVREADWRITE_LEGACY("scsp", scsp_r, scsp_w)
802ADDRESS_MAP_END
803
804
805/* keyboard code */
806/* TODO: needs a proper keycode table */
807INPUT_CHANGED_MEMBER(saturn_state::key_stroke)
808{
809   if(newval && !oldval)
810   {
811      m_keyb.data = ((UINT8)(FPTR)(param) & 0xff);
812      m_keyb.status |= 8;
813   }
814
815   if(oldval && !newval)
816   {
817      //m_keyb.status &= ~8;
818      m_keyb.data = 0;
819   }
820}
821
822/* Note: unused bits must stay high, Bug 2 relies on this. */
823#define SATURN_PAD_P1(_mask_, _val_) \
824   PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
825   PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
826   PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
827   PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
828   PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
829   PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("P1 A") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
830   PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("P1 C") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
831   PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("P1 B") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
832   PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_BUTTON8 ) PORT_NAME("P1 R") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
833   PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("P1 X") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
834   PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_NAME("P1 Y") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
835   PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_NAME("P1 Z") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
836   PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_BUTTON7 ) PORT_NAME("P1 L") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
837   PORT_BIT( 0x0007, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_)
838
839#define SATURN_PAD_P2(_mask_, _val_) \
840   PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
841   PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
842   PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
843   PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
844   PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
845   PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("P2 A") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
846   PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("P2 C") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
847   PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("P2 B") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
848   PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_BUTTON8 ) PORT_NAME("P2 R") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
849   PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("P2 X") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
850   PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_NAME("P2 Y") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
851   PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_NAME("P2 Z") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
852   PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_BUTTON7 ) PORT_NAME("P2 L") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
853   PORT_BIT( 0x0007, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_)
854
855#define MD_PAD_P1(_mask_, _val_) \
856   PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
857   PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
858   PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
859   PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
860   PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
861   PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("P1 A") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
862   PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("P1 C") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
863   PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("P1 B") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
864   PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_BUTTON8 ) PORT_NAME("P1 Mode") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
865   PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("P1 X") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
866   PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_NAME("P1 Y") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
867   PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_NAME("P1 Z") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
868   PORT_BIT( 0x000f, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) //read '1' when direct mode is polled
869
870#define MD_PAD_P2(_mask_, _val_) \
871   PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
872   PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
873   PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
874   PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
875   PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
876   PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("P2 A") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
877   PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("P2 C") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
878   PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("P2 B") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
879   PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_BUTTON8 ) PORT_NAME("P2 Mode") PORT_PLAYER(2)  PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
880   PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("P2 X") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
881   PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_NAME("P2 Y") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
882   PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_NAME("P2 Z") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) \
883   PORT_BIT( 0x000f, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("INPUT_TYPE", _mask_, EQUALS, _val_) //read '1' when direct mode is polled
884
885#define SATURN_KEYBOARD PORT_CONDITION("INPUT_TYPE", 0x0f, EQUALS, 0x05)
886
887INPUT_CHANGED_MEMBER(saturn_state::nmi_reset)
888{
889   /* TODO: correct? */
890   if(!m_NMI_reset)
891      return;
892
893   /* TODO: NMI doesn't stay held on SH-2 core so we can't use ASSERT_LINE/CLEAR_LINE with that yet */
894   if(newval)
895      m_maincpu->set_input_line(INPUT_LINE_NMI, PULSE_LINE);
896}
897
898INPUT_CHANGED_MEMBER(saturn_state::tray_open)
899{
900   if(newval)
901      stvcd_set_tray_open();
902}
903
904INPUT_CHANGED_MEMBER(saturn_state::tray_close)
905{
906   if(newval)
907      stvcd_set_tray_close();
908}
909
910static INPUT_PORTS_START( saturn )
911   PORT_START("RESET") /* hardwired buttons */
912   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, nmi_reset,0) PORT_NAME("Reset Button")
913   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, tray_open,0) PORT_NAME("Tray Open Button")
914   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, tray_close,0) PORT_NAME("Tray Close")
915
916   PORT_START("JOY1")
917   SATURN_PAD_P1(0x0f, 0)
918
919   PORT_START("JOY2")
920   SATURN_PAD_P2(0xf0, 0)
921
922   /* TODO: there's no info about the keycode used on Saturn keyboard, following is trial & error with Game Basic software */
923   PORT_START("KEY0") // 0x00 - 0x07
924   PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_UNUSED) SATURN_KEYBOARD
925   PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F1") /*PORT_CODE(KEYCODE_F1)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x01) PORT_PLAYER(1) SATURN_KEYBOARD
926   PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("0-3") /*PORT_CODE(KEYCODE_2) PORT_CHAR('2')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x02) PORT_PLAYER(1) SATURN_KEYBOARD
927   PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F2") /*PORT_CODE(KEYCODE_F2)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x03) PORT_PLAYER(1) SATURN_KEYBOARD // RUN
928   PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F3") /*PORT_CODE(KEYCODE_F3)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x04) PORT_PLAYER(1) SATURN_KEYBOARD // LIST
929   PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F4") /*PORT_CODE(KEYCODE_F4)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x05) PORT_PLAYER(1) SATURN_KEYBOARD // EDIT
930   PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F5") /*PORT_CODE(KEYCODE_F5)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x06) PORT_PLAYER(1) SATURN_KEYBOARD
931   PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("CLR SCR") PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x07) PORT_PLAYER(1) SATURN_KEYBOARD
932
933   PORT_START("KEY1") // 0x08 - 0x0f
934   PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("1-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x08) PORT_PLAYER(1) SATURN_KEYBOARD
935   PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F6") /*PORT_CODE(KEYCODE_F6)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x09) PORT_PLAYER(1) SATURN_KEYBOARD
936   PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F7") /*PORT_CODE(KEYCODE_F7)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x0a) PORT_PLAYER(1) SATURN_KEYBOARD
937   PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F8") /*PORT_CODE(KEYCODE_F8)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x0b) PORT_PLAYER(1) SATURN_KEYBOARD
938   PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F9") /*PORT_CODE(KEYCODE_F9)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x0c) PORT_PLAYER(1) SATURN_KEYBOARD // LIST again
939   PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("1-6") /*PORT_CODE(KEYCODE_5) PORT_CHAR('5')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x0d) PORT_PLAYER(1) SATURN_KEYBOARD
940   PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("1-7") /*PORT_CODE(KEYCODE_6) PORT_CHAR('6')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x0e) PORT_PLAYER(1) SATURN_KEYBOARD
941   PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("1-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x0f) PORT_PLAYER(1) SATURN_KEYBOARD
942
943   PORT_START("KEY2") // 0x10 - 0x17
944   PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("2-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x10) PORT_PLAYER(1) SATURN_KEYBOARD
945   PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("2-2") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x11) PORT_PLAYER(1) SATURN_KEYBOARD
946   /* TODO: break codes! */
947   PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("SHIFT") /*PORT_CODE(KEYCODE_2) PORT_CHAR('2')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x12) PORT_PLAYER(1) SATURN_KEYBOARD
948   PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("KANA SHIFT") /*PORT_CODE(KEYCODE_3) PORT_CHAR('3')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x13) PORT_PLAYER(1) SATURN_KEYBOARD
949   PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("(special keys)") /*PORT_CODE(KEYCODE_4) PORT_CHAR('4')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x14) PORT_PLAYER(1) SATURN_KEYBOARD
950
951   PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Q") PORT_CODE(KEYCODE_Q) PORT_CHAR('Q') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x15) PORT_PLAYER(1) SATURN_KEYBOARD
952   PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("1") PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x16) PORT_PLAYER(1) SATURN_KEYBOARD
953   PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("2-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x17) PORT_PLAYER(1) SATURN_KEYBOARD
954
955   PORT_START("KEY3") // 0x18 - 0x1f
956   PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("3-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x18) PORT_PLAYER(1) SATURN_KEYBOARD
957   PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("3-2") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x19) PORT_PLAYER(1) SATURN_KEYBOARD
958   PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Z") PORT_CODE(KEYCODE_Z) PORT_CHAR('Z') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x1a) PORT_PLAYER(1) SATURN_KEYBOARD
959   PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("S") PORT_CODE(KEYCODE_S) PORT_CHAR('S') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x1b) PORT_PLAYER(1) SATURN_KEYBOARD
960   PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("A") PORT_CODE(KEYCODE_A) PORT_CHAR('A') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x1c) PORT_PLAYER(1) SATURN_KEYBOARD
961   PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("W") PORT_CODE(KEYCODE_W) PORT_CHAR('W') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x1d) PORT_PLAYER(1) SATURN_KEYBOARD
962   PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("2") PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x1e) PORT_PLAYER(1) SATURN_KEYBOARD
963   PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("3-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x1f) PORT_PLAYER(1) SATURN_KEYBOARD
964
965   PORT_START("KEY4") // 0x20 - 0x27
966   PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("4-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x20) PORT_PLAYER(1) SATURN_KEYBOARD
967   PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("C") PORT_CODE(KEYCODE_C) PORT_CHAR('C') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x21) PORT_PLAYER(1) SATURN_KEYBOARD
968   PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("X") PORT_CODE(KEYCODE_X) PORT_CHAR('X') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x22) PORT_PLAYER(1) SATURN_KEYBOARD
969   PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("D") PORT_CODE(KEYCODE_D) PORT_CHAR('D') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x23) PORT_PLAYER(1) SATURN_KEYBOARD
970   PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("E") PORT_CODE(KEYCODE_E) PORT_CHAR('E') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x24) PORT_PLAYER(1) SATURN_KEYBOARD
971   PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("4") PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x25) PORT_PLAYER(1) SATURN_KEYBOARD
972   PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("3") PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x26) PORT_PLAYER(1) SATURN_KEYBOARD
973   PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("4-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x27) PORT_PLAYER(1) SATURN_KEYBOARD
974
975   PORT_START("KEY5") // 0x28 - 0x2f
976   PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("5-1") /*PORT_CODE(KEYCODE_F) PORT_CHAR('F')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x28) PORT_PLAYER(1) SATURN_KEYBOARD // another F?
977   PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("SPACE") PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x29) PORT_PLAYER(1) SATURN_KEYBOARD
978   PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("V") PORT_CODE(KEYCODE_V) PORT_CHAR('V') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x2a) PORT_PLAYER(1) SATURN_KEYBOARD
979   PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F") PORT_CODE(KEYCODE_F) PORT_CHAR('F') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x2b) PORT_PLAYER(1) SATURN_KEYBOARD
980   PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("T") PORT_CODE(KEYCODE_T) PORT_CHAR('T') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x2c) PORT_PLAYER(1) SATURN_KEYBOARD
981   PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("R") PORT_CODE(KEYCODE_R) PORT_CHAR('R') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x2d) PORT_PLAYER(1) SATURN_KEYBOARD
982   PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("5") PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x2e) PORT_PLAYER(1) SATURN_KEYBOARD
983   PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("5-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x2f) PORT_PLAYER(1) SATURN_KEYBOARD
984
985   PORT_START("KEY6") // 0x30 - 0x37
986   PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("6-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x30) PORT_PLAYER(1) SATURN_KEYBOARD
987   PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("N") PORT_CODE(KEYCODE_N) PORT_CHAR('N') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x31) PORT_PLAYER(1) SATURN_KEYBOARD
988   PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("B") PORT_CODE(KEYCODE_B) PORT_CHAR('B') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x32) PORT_PLAYER(1) SATURN_KEYBOARD
989   PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("H") PORT_CODE(KEYCODE_H) PORT_CHAR('H') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x33) PORT_PLAYER(1) SATURN_KEYBOARD
990   PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("G") PORT_CODE(KEYCODE_G) PORT_CHAR('G') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x34) PORT_PLAYER(1) SATURN_KEYBOARD
991   PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Y") PORT_CODE(KEYCODE_Y) PORT_CHAR('Y') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x35) PORT_PLAYER(1) SATURN_KEYBOARD
992   PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("6") PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x36) PORT_PLAYER(1) SATURN_KEYBOARD
993   PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("6-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x37) PORT_PLAYER(1) SATURN_KEYBOARD
994
995   PORT_START("KEY7") // 0x38 - 0x3f
996   PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("7-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x38) PORT_PLAYER(1) SATURN_KEYBOARD
997   PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("7-2") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x39) PORT_PLAYER(1) SATURN_KEYBOARD
998   PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("M") PORT_CODE(KEYCODE_M) PORT_CHAR('M') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x3a) PORT_PLAYER(1) SATURN_KEYBOARD
999   PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("J") PORT_CODE(KEYCODE_J) PORT_CHAR('J') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x3b) PORT_PLAYER(1) SATURN_KEYBOARD
1000   PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("U") PORT_CODE(KEYCODE_U) PORT_CHAR('U') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x3c) PORT_PLAYER(1) SATURN_KEYBOARD
1001   PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("7") PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x3d) PORT_PLAYER(1) SATURN_KEYBOARD
1002   PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("8") PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x3e) PORT_PLAYER(1) SATURN_KEYBOARD
1003   PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("7-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x3f) PORT_PLAYER(1) SATURN_KEYBOARD
1004
1005   PORT_START("KEY8") // 0x40 - 0x47
1006   PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("8-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x40) PORT_PLAYER(1) SATURN_KEYBOARD
1007   PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME(",") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x41) PORT_PLAYER(1) SATURN_KEYBOARD
1008   PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("K") PORT_CODE(KEYCODE_K) PORT_CHAR('K') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x42) PORT_PLAYER(1) SATURN_KEYBOARD
1009   PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("I") PORT_CODE(KEYCODE_I) PORT_CHAR('I') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x43) PORT_PLAYER(1) SATURN_KEYBOARD
1010   PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("O") PORT_CODE(KEYCODE_O) PORT_CHAR('O') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x44) PORT_PLAYER(1) SATURN_KEYBOARD
1011   PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("0") PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x45) PORT_PLAYER(1) SATURN_KEYBOARD
1012   PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("9") PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x46) PORT_PLAYER(1) SATURN_KEYBOARD
1013   PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("8-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x47) PORT_PLAYER(1) SATURN_KEYBOARD
1014
1015   PORT_START("KEY9") // 0x48 - 0x4f
1016   PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("9-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x48) PORT_PLAYER(1) SATURN_KEYBOARD
1017   PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME(".") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x49) PORT_PLAYER(1) SATURN_KEYBOARD
1018   PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("/") /*PORT_CODE(KEYCODE_2) PORT_CHAR('2')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x4a) PORT_PLAYER(1) SATURN_KEYBOARD
1019   PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("L") PORT_CODE(KEYCODE_L) PORT_CHAR('L') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x4b) PORT_PLAYER(1) SATURN_KEYBOARD
1020   PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME(";") /*PORT_CODE(KEYCODE_4) PORT_CHAR('4')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x4c) PORT_PLAYER(1) SATURN_KEYBOARD
1021   PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("P") PORT_CODE(KEYCODE_P) PORT_CHAR('P') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x4d) PORT_PLAYER(1) SATURN_KEYBOARD
1022   PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("- / =") PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x4e) PORT_PLAYER(1) SATURN_KEYBOARD
1023   PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("9-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x4f) PORT_PLAYER(1) SATURN_KEYBOARD
1024
1025   PORT_START("KEYA") // 0x50 - 0x57
1026   PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("A-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x50) PORT_PLAYER(1) SATURN_KEYBOARD
1027   PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("\xC2\xA5") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x51) PORT_PLAYER(1) SATURN_KEYBOARD
1028   PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME(":") /*PORT_CODE(KEYCODE_2) PORT_CHAR('2')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x52) PORT_PLAYER(1) SATURN_KEYBOARD
1029   PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("A-4") /*PORT_CODE(KEYCODE_3) PORT_CHAR('3')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x53) PORT_PLAYER(1) SATURN_KEYBOARD
1030   PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("@") /*PORT_CODE(KEYCODE_4) PORT_CHAR('4')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x54) PORT_PLAYER(1) SATURN_KEYBOARD
1031   PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("^") /*PORT_CODE(KEYCODE_5) PORT_CHAR(0xd)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x55) PORT_PLAYER(1) SATURN_KEYBOARD
1032   PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("A-7") /*PORT_CODE(KEYCODE_6) PORT_CHAR('6')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x56) PORT_PLAYER(1) SATURN_KEYBOARD
1033   PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("A-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x57) PORT_PLAYER(1) SATURN_KEYBOARD
1034
1035   PORT_START("KEYB") // 0x58 - 0x5f
1036   PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("B-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x58) PORT_PLAYER(1) SATURN_KEYBOARD
1037   PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("B-2") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x59) PORT_PLAYER(1) SATURN_KEYBOARD
1038   PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("ENTER") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(0x0d) PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x5a) PORT_PLAYER(1) SATURN_KEYBOARD
1039   PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("[") /*PORT_CODE(KEYCODE_3) PORT_CHAR('3')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x5b) PORT_PLAYER(1) SATURN_KEYBOARD // {
1040   PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("B-5") /*PORT_CODE(KEYCODE_4) PORT_CHAR('4')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x5c) PORT_PLAYER(1) SATURN_KEYBOARD
1041   PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("]") /*PORT_CODE(KEYCODE_5) PORT_CHAR(0xd)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x5d) PORT_PLAYER(1) SATURN_KEYBOARD // }
1042   PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("B-7") /*PORT_CODE(KEYCODE_6) PORT_CHAR('6')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x5e) PORT_PLAYER(1) SATURN_KEYBOARD
1043   PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("B-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x5f) PORT_PLAYER(1) SATURN_KEYBOARD
1044
1045   PORT_START("KEYC") // 0x60 - 0x67
1046   PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("C-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x60) PORT_PLAYER(1) SATURN_KEYBOARD
1047   PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("C-2") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x61) PORT_PLAYER(1) SATURN_KEYBOARD
1048   PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("C-3") /*PORT_CODE(KEYCODE_2) PORT_CHAR('2')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x62) PORT_PLAYER(1) SATURN_KEYBOARD
1049   PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("C-4") /*PORT_CODE(KEYCODE_3) PORT_CHAR('3')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x63) PORT_PLAYER(1) SATURN_KEYBOARD
1050   PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("C-5") /*PORT_CODE(KEYCODE_4) PORT_CHAR('4')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x64) PORT_PLAYER(1) SATURN_KEYBOARD
1051   PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("C-6") /*PORT_CODE(KEYCODE_5) PORT_CHAR(0xd)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x65) PORT_PLAYER(1) SATURN_KEYBOARD
1052   PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("BACKSPACE") PORT_CODE(KEYCODE_BACKSPACE) /* PORT_CHAR('6')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x66) PORT_PLAYER(1) SATURN_KEYBOARD
1053   PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("C-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x67) PORT_PLAYER(1) SATURN_KEYBOARD
1054
1055   PORT_START("KEYD") // 0x68 - 0x6f
1056   PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("D-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x68) PORT_PLAYER(1) SATURN_KEYBOARD
1057   PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("D-2") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x69) PORT_PLAYER(1) SATURN_KEYBOARD
1058   PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("D-3") /*PORT_CODE(KEYCODE_2) PORT_CHAR('2')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x6a) PORT_PLAYER(1) SATURN_KEYBOARD
1059   PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("D-4") /*PORT_CODE(KEYCODE_3) PORT_CHAR('3')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x6b) PORT_PLAYER(1) SATURN_KEYBOARD
1060   PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("D-5") /*PORT_CODE(KEYCODE_4) PORT_CHAR('4')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x6c) PORT_PLAYER(1) SATURN_KEYBOARD
1061   PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("D-6") /*PORT_CODE(KEYCODE_5) PORT_CHAR(0xd)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x6d) PORT_PLAYER(1) SATURN_KEYBOARD
1062   PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("D-7") /*PORT_CODE(KEYCODE_6) PORT_CHAR('6')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x6e) PORT_PLAYER(1) SATURN_KEYBOARD
1063   PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("D-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x6f) PORT_PLAYER(1) SATURN_KEYBOARD
1064
1065   PORT_START("KEYE") // 0x70 - 0x77
1066   PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("E-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x70) PORT_PLAYER(1) SATURN_KEYBOARD
1067   PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("E-2") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x71) PORT_PLAYER(1) SATURN_KEYBOARD
1068   PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("E-3") /*PORT_CODE(KEYCODE_2) PORT_CHAR('2')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x72) PORT_PLAYER(1) SATURN_KEYBOARD
1069   PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("E-4") /*PORT_CODE(KEYCODE_3) PORT_CHAR('3')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x73) PORT_PLAYER(1) SATURN_KEYBOARD
1070   PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("E-5") /*PORT_CODE(KEYCODE_4) PORT_CHAR('4')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x74) PORT_PLAYER(1) SATURN_KEYBOARD
1071   PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("E-6") /*PORT_CODE(KEYCODE_5) PORT_CHAR(0xd)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x75) PORT_PLAYER(1) SATURN_KEYBOARD
1072   PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("E-7") /*PORT_CODE(KEYCODE_6) PORT_CHAR('6')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x76) PORT_PLAYER(1) SATURN_KEYBOARD
1073   PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("E-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x77) PORT_PLAYER(1) SATURN_KEYBOARD
1074
1075   PORT_START("KEYF") // 0x78 - 0x7f
1076   PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x78) PORT_PLAYER(1) SATURN_KEYBOARD
1077   PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F-2") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x79) PORT_PLAYER(1) SATURN_KEYBOARD
1078   PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F-3") /*PORT_CODE(KEYCODE_2) PORT_CHAR('2')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x7a) PORT_PLAYER(1) SATURN_KEYBOARD
1079   PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F-4") /*PORT_CODE(KEYCODE_3) PORT_CHAR('3')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x7b) PORT_PLAYER(1) SATURN_KEYBOARD
1080   PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F-5") /*PORT_CODE(KEYCODE_4) PORT_CHAR('4')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x7c) PORT_PLAYER(1) SATURN_KEYBOARD
1081   PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F-6") /*PORT_CODE(KEYCODE_5) PORT_CHAR(0xd)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x7d) PORT_PLAYER(1) SATURN_KEYBOARD
1082   PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F-7") /*PORT_CODE(KEYCODE_6) PORT_CHAR('6')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x7e) PORT_PLAYER(1) SATURN_KEYBOARD
1083   PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("ESC") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x7f) PORT_PLAYER(1) SATURN_KEYBOARD //SYSTEM CONFIGURATION
1084
1085   PORT_START("KEYS_1") // special keys
1086   PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("UP") PORT_CODE(KEYCODE_UP) /*PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x78) PORT_PLAYER(1) SATURN_KEYBOARD
1087   PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("DOWN") PORT_CODE(KEYCODE_DOWN) /*PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x79) PORT_PLAYER(1) SATURN_KEYBOARD
1088   PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("LEFT") PORT_CODE(KEYCODE_LEFT) /*PORT_CHAR('2')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x7a) PORT_PLAYER(1) SATURN_KEYBOARD
1089   PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("RIGHT") PORT_CODE(KEYCODE_RIGHT) /*PORT_CHAR('3')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_state, key_stroke, 0x7b) PORT_PLAYER(1) SATURN_KEYBOARD
1090
1091   PORT_START("MOUSEB1")
1092   PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P1 Pointer Left Button") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", 0x0f, EQUALS, 0x04)
1093   PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P1 Pointer Right Button") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", 0x0f, EQUALS, 0x04)
1094   PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("P1 Pointer Middle Button") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", 0x0f, EQUALS, 0x04)
1095   PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_START ) PORT_NAME("P1 Pointer Start Button") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", 0x0f, EQUALS, 0x04)
1096   PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P1 Mouse Left Button") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", 0x0f, EQUALS, 0x08)
1097   PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P1 Mouse Right Button") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", 0x0f, EQUALS, 0x08)
1098   PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("P1 Mouse Middle Button") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", 0x0f, EQUALS, 0x08)
1099   PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_START ) PORT_NAME("P1 Mouse Start Button") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", 0x0f, EQUALS, 0x08)
1100
1101   PORT_START("MOUSEX1")
1102   PORT_BIT(0xffff, 0x00, IPT_MOUSE_X) PORT_SENSITIVITY(100) PORT_MINMAX(0x000, 0xffff) PORT_KEYDELTA(2) PORT_RESET PORT_NAME("P1 Pointer X") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", 0x0f, EQUALS, 0x04)
1103   PORT_BIT(0xffff, 0x00, IPT_MOUSE_X) PORT_SENSITIVITY(100) PORT_MINMAX(0x000, 0xffff) PORT_KEYDELTA(2) PORT_RESET PORT_NAME("P1 Mouse X") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", 0x0f, EQUALS, 0x08)
1104
1105   PORT_START("MOUSEY1")
1106   PORT_BIT(0xffff, 0x00, IPT_MOUSE_Y) PORT_SENSITIVITY(100) PORT_MINMAX(0x000, 0xffff) PORT_KEYDELTA(2) PORT_RESET PORT_REVERSE PORT_NAME("P1 Pointer Y") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", 0x0f, EQUALS, 0x04)
1107   PORT_BIT(0xffff, 0x00, IPT_MOUSE_Y) PORT_SENSITIVITY(100) PORT_MINMAX(0x000, 0xffff) PORT_KEYDELTA(2) PORT_RESET PORT_REVERSE PORT_NAME("P1 Mouse Y") PORT_PLAYER(1) PORT_CONDITION("INPUT_TYPE", 0x0f, EQUALS, 0x08)
1108
1109   PORT_START("MOUSEB2")
1110   PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P2 Pointer Left Button") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", 0xf0, EQUALS, 0x40)
1111   PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P2 Pointer Right Button") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", 0xf0, EQUALS, 0x40)
1112   PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("P2 Pointer Middle Button") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", 0xf0, EQUALS, 0x40)
1113   PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_START ) PORT_NAME("P2 Pointer Start Button") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", 0xf0, EQUALS, 0x40)
1114   PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P2 Mouse Left Button") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", 0xf0, EQUALS, 0x80)
1115   PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P2 Mouse Right Button") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", 0xf0, EQUALS, 0x80)
1116   PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("P2 Mouse Middle Button") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", 0xf0, EQUALS, 0x80)
1117   PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_START ) PORT_NAME("P2 Mouse Start Button") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", 0xf0, EQUALS, 0x80)
1118
1119   PORT_START("MOUSEX2")
1120   PORT_BIT(0xffff, 0x00, IPT_MOUSE_X) PORT_SENSITIVITY(100) PORT_MINMAX(0x000, 0xffff) PORT_KEYDELTA(2) PORT_RESET PORT_NAME("P2 Pointer X") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", 0xf0, EQUALS, 0x40)
1121   PORT_BIT(0xffff, 0x00, IPT_MOUSE_X) PORT_SENSITIVITY(100) PORT_MINMAX(0x000, 0xffff) PORT_KEYDELTA(2) PORT_RESET PORT_NAME("P2 Mouse X") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", 0xf0, EQUALS, 0x80)
1122
1123   PORT_START("MOUSEY2")
1124   PORT_BIT(0xffff, 0x00, IPT_MOUSE_Y) PORT_SENSITIVITY(100) PORT_MINMAX(0x000, 0xffff) PORT_KEYDELTA(2) PORT_RESET PORT_REVERSE PORT_NAME("P2 Pointer Y") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", 0xf0, EQUALS, 0x40)
1125   PORT_BIT(0xffff, 0x00, IPT_MOUSE_Y) PORT_SENSITIVITY(100) PORT_MINMAX(0x000, 0xffff) PORT_KEYDELTA(2) PORT_RESET PORT_REVERSE PORT_NAME("P2 Mouse Y") PORT_PLAYER(2) PORT_CONDITION("INPUT_TYPE", 0xf0, EQUALS, 0x80)
1126
1127   PORT_START("AN_JOY1")
1128   SATURN_PAD_P1(0x0f, 0x01)   // racing device
1129   SATURN_PAD_P1(0x0f, 0x02)   // analog controller
1130
1131   PORT_START("AN_JOY2")
1132   SATURN_PAD_P2(0xf0, 0x10)   // racing device
1133   SATURN_PAD_P2(0xf0, 0x20)   // analog controller
1134
1135   PORT_START("AN_X1")
1136   PORT_BIT( 0xff, 0x80, IPT_AD_STICK_X ) PORT_MINMAX(0x00, 0xff) PORT_SENSITIVITY(25) PORT_KEYDELTA(200) PORT_PLAYER(1) PORT_NAME("P1 Racing Stick X") PORT_CONDITION("INPUT_TYPE", 0x0f, EQUALS, 0x01)
1137   PORT_BIT( 0xff, 0x80, IPT_AD_STICK_X ) PORT_MINMAX(0x00, 0xff) PORT_SENSITIVITY(25) PORT_KEYDELTA(200) PORT_PLAYER(1) PORT_NAME("P1 AD Stick X") PORT_CONDITION("INPUT_TYPE", 0x0f, EQUALS, 0x02)
1138
1139   PORT_START("AN_Y1")
1140   PORT_BIT( 0xff, 0x80, IPT_AD_STICK_Y ) PORT_MINMAX(0x00, 0xff) PORT_SENSITIVITY(25) PORT_KEYDELTA(200) PORT_PLAYER(1) PORT_NAME("P1 Racing Stick Y") PORT_CONDITION("INPUT_TYPE", 0x0f, EQUALS, 0x01)
1141   PORT_BIT( 0xff, 0x80, IPT_AD_STICK_Y ) PORT_MINMAX(0x00, 0xff) PORT_SENSITIVITY(25) PORT_KEYDELTA(200) PORT_PLAYER(1) PORT_NAME("P1 AD Stick Y") PORT_CONDITION("INPUT_TYPE", 0x0f, EQUALS, 0x02)
1142
1143   PORT_START("AN_Z1")
1144   PORT_BIT( 0xff, 0x00, IPT_AD_STICK_Z ) PORT_MINMAX(0x00, 0xff) PORT_SENSITIVITY(25) PORT_KEYDELTA(200) PORT_PLAYER(1) PORT_NAME("P1 Racing Stick Z") PORT_CONDITION("INPUT_TYPE", 0x0f, EQUALS, 0x01)
1145   PORT_BIT( 0xff, 0x00, IPT_AD_STICK_Z ) PORT_MINMAX(0x00, 0xff) PORT_SENSITIVITY(25) PORT_KEYDELTA(200) PORT_PLAYER(1) PORT_NAME("P1 AD Stick Z") PORT_CONDITION("INPUT_TYPE", 0x0f, EQUALS, 0x02)
1146
1147   PORT_START("AN_X2")
1148   PORT_BIT( 0xff, 0x80, IPT_AD_STICK_X ) PORT_MINMAX(0x00, 0xff) PORT_SENSITIVITY(25) PORT_KEYDELTA(200) PORT_PLAYER(2) PORT_NAME("P2 Racing Stick X") PORT_CONDITION("INPUT_TYPE", 0xf0, EQUALS, 0x10)
1149   PORT_BIT( 0xff, 0x80, IPT_AD_STICK_X ) PORT_MINMAX(0x00, 0xff) PORT_SENSITIVITY(25) PORT_KEYDELTA(200) PORT_PLAYER(2) PORT_NAME("P2 AD Stick X") PORT_CONDITION("INPUT_TYPE", 0xf0, EQUALS, 0x20)
1150
1151   PORT_START("AN_Y2")
1152   PORT_BIT( 0xff, 0x80, IPT_AD_STICK_Y ) PORT_MINMAX(0x00, 0xff) PORT_SENSITIVITY(25) PORT_KEYDELTA(200) PORT_PLAYER(2) PORT_NAME("P2 Racing Stick Y") PORT_CONDITION("INPUT_TYPE", 0xf0, EQUALS, 0x10)
1153   PORT_BIT( 0xff, 0x80, IPT_AD_STICK_Y ) PORT_MINMAX(0x00, 0xff) PORT_SENSITIVITY(25) PORT_KEYDELTA(200) PORT_PLAYER(2) PORT_NAME("P2 AD Stick Y") PORT_CONDITION("INPUT_TYPE", 0xf0, EQUALS, 0x20)
1154
1155   PORT_START("AN_Z2")
1156   PORT_BIT( 0xff, 0x00, IPT_AD_STICK_Z ) PORT_MINMAX(0x00, 0xff) PORT_SENSITIVITY(25) PORT_KEYDELTA(200) PORT_PLAYER(2) PORT_NAME("P2 Racing Stick Z") PORT_CONDITION("INPUT_TYPE", 0xf0, EQUALS, 0x10)
1157   PORT_BIT( 0xff, 0x00, IPT_AD_STICK_Z ) PORT_MINMAX(0x00, 0xff) PORT_SENSITIVITY(25) PORT_KEYDELTA(200) PORT_PLAYER(2) PORT_NAME("P2 AD Stick Z") PORT_CONDITION("INPUT_TYPE", 0xf0, EQUALS, 0x20)
1158
1159   PORT_START("MD_JOY1")
1160   MD_PAD_P1(0x0f, 0x06)   // MD 3 buttons pad
1161   MD_PAD_P1(0x0f, 0x07)   // MD 6 buttons pad
1162
1163   PORT_START("MD_JOY2")
1164   MD_PAD_P2(0xf0, 0x60)   // MD 3 buttons pad
1165   MD_PAD_P2(0xf0, 0x70)   // MD 6 buttons pad
1166
1167   PORT_START("CART_AREA")
1168   PORT_CONFNAME( 0x07, 0x06, "Cart Type" )
1169   PORT_CONFSETTING( 0x00, "None" )
1170//  PORT_CONFSETTING( 0x01, "4 Mbit backup RAM" )
1171//  PORT_CONFSETTING( 0x02, "8 Mbit backup RAM" )
1172//  PORT_CONFSETTING( 0x03, "16 Mbit backup RAM" )
1173//  PORT_CONFSETTING( 0x04, "32 Mbit backup RAM" )
1174   PORT_CONFSETTING( 0x05, "8 Mbit Cart RAM" )
1175   PORT_CONFSETTING( 0x06, "32 Mbit Cart RAM" )
1176
1177   PORT_START("INPUT_TYPE")
1178   PORT_CONFNAME(0x0f,0x00,"Controller Port 1")
1179   PORT_CONFSETTING(0x00,"Digital Device (standard Saturn pad)")
1180   PORT_CONFSETTING(0x01,"Racing Device") /* steering wheel only */
1181   PORT_CONFSETTING(0x02,"Analog Device") //Nights pad?
1182//  PORT_CONFSETTING(0x03,"Lightgun Device")
1183   PORT_CONFSETTING(0x04,"Trackball") // TODO: according to the docs this ID is labeled "Pointing Device"
1184   PORT_CONFSETTING(0x05,"Keyboard Device")
1185   PORT_CONFSETTING(0x06,"Megadrive 3B Pad")
1186   PORT_CONFSETTING(0x07,"Megadrive 6B Pad")
1187   PORT_CONFSETTING(0x08,"Saturn Mouse")
1188//  PORT_CONFSETTING(0x09,"<unconnected>")
1189   PORT_CONFNAME(0xf0,0x00,"Controller Port 2")
1190   PORT_CONFSETTING(0x00,"Digital Device (standard Saturn pad)")
1191   PORT_CONFSETTING(0x10,"Racing Device")
1192   PORT_CONFSETTING(0x20,"Analog Device") //Nights pad?
1193//  PORT_CONFSETTING(0x30,"Lightgun Device")
1194   PORT_CONFSETTING(0x40,"Pointing Device")
1195//  PORT_CONFSETTING(0x50,"Keyboard Device")
1196   PORT_CONFSETTING(0x60,"Megadrive 3B Pad")
1197   PORT_CONFSETTING(0x70,"Megadrive 6B Pad")
1198   PORT_CONFSETTING(0x80,"Saturn Mouse")
1199   PORT_CONFSETTING(0x90,"<unconnected>")
1200
1201   PORT_START("fake")
1202   PORT_CONFNAME(0x01,0x00,"Master-Slave Comms")
1203   PORT_CONFSETTING(0x00,"Normal (400 cycles)")
1204   PORT_CONFSETTING(0x01,"One Shot (Hack)")
1205INPUT_PORTS_END
1206
1207static const gfx_layout tiles8x8x4_layout =
1208{
1209   8,8,
1210   0x100000/(32*8/8),
1211   4,
1212   { 0, 1, 2, 3 },
1213   { 0, 4, 8, 12, 16, 20, 24, 28 },
1214   { 0*32, 1*32, 2*32, 3*32, 4*32, 5*32, 6*32, 7*32 },
1215   32*8
1216};
1217
1218static const gfx_layout tiles16x16x4_layout =
1219{
1220   16,16,
1221   0x100000/(32*32/8),
1222   4,
1223   { 0, 1, 2, 3 },
1224   { 0, 4, 8, 12, 16, 20, 24, 28,
1225      32*8+0, 32*8+4, 32*8+8, 32*8+12, 32*8+16, 32*8+20, 32*8+24, 32*8+28,
1226
1227      },
1228   { 0*32, 1*32, 2*32, 3*32, 4*32, 5*32, 6*32, 7*32,
1229      32*16, 32*17,32*18, 32*19,32*20,32*21,32*22,32*23
1230
1231      },
1232   32*32
1233};
1234
1235static const gfx_layout tiles8x8x8_layout =
1236{
1237   8,8,
1238   0x100000/(32*8/8),
1239   8,
1240   { 0, 1, 2, 3, 4, 5, 6, 7 },
1241   { 0, 8, 16, 24, 32, 40, 48, 56 },
1242   { 0*64, 1*64, 2*64, 3*64, 4*64, 5*64, 6*64, 7*64 },
1243   32*8    /* really 64*8, but granularity is 32 bytes */
1244};
1245
1246static const gfx_layout tiles16x16x8_layout =
1247{
1248   16,16,
1249   0x100000/(64*16/8),
1250   8,
1251   { 0, 1, 2, 3, 4, 5, 6, 7 },
1252   { 0, 8, 16, 24, 32, 40, 48, 56,
1253   64*8+0, 65*8, 66*8, 67*8, 68*8, 69*8, 70*8, 71*8
1254
1255   },
1256   { 0*64, 1*64, 2*64, 3*64, 4*64, 5*64, 6*64, 7*64,
1257   64*16, 64*17, 64*18, 64*19, 64*20, 64*21, 64*22, 64*23
1258   },
1259   64*16   /* really 128*16, but granularity is 32 bytes */
1260};
1261
1262
1263
1264
1265GFXDECODE_START( stv )
1266   GFXDECODE_ENTRY( NULL, 0, tiles8x8x4_layout,   0x00, (0x80*(2+1))  )
1267   GFXDECODE_ENTRY( NULL, 0, tiles16x16x4_layout, 0x00, (0x80*(2+1))  )
1268   GFXDECODE_ENTRY( NULL, 0, tiles8x8x8_layout,   0x00, (0x08*(2+1))  )
1269   GFXDECODE_ENTRY( NULL, 0, tiles16x16x8_layout, 0x00, (0x08*(2+1))  )
1270GFXDECODE_END
1271
1272static const sh2_cpu_core sh2_conf_master = { 0, NULL };
1273static const sh2_cpu_core sh2_conf_slave  = { 1, NULL };
1274
1275void scsp_irq(device_t *device, int irq)
1276{
1277   saturn_state *state = device->machine().driver_data<saturn_state>();
1278
1279   // don't bother the 68k if it's off
1280   if (!state->m_en_68k)
1281   {
1282      return;
1283   }
1284
1285   if (irq > 0)
1286   {
1287      state->m_scsp_last_line = irq;
1288      device->machine().device("audiocpu")->execute().set_input_line(irq, ASSERT_LINE);
1289   }
1290   else if (irq < 0)
1291   {
1292      device->machine().device("audiocpu")->execute().set_input_line(-irq, CLEAR_LINE);
1293   }
1294   else
1295   {
1296      device->machine().device("audiocpu")->execute().set_input_line(state->m_scsp_last_line, CLEAR_LINE);
1297   }
1298}
1299
1300WRITE_LINE_MEMBER(saturn_state::scsp_to_main_irq)
1301{
1302   if(state)
1303   {
1304      if(!(m_scu.ism & IRQ_SOUND_REQ))
1305      {
1306         m_maincpu->set_input_line_and_vector(9, HOLD_LINE, 0x46);
1307         scu_do_transfer(5);
1308      }
1309      else
1310         m_scu.ist |= (IRQ_SOUND_REQ);
1311   }
1312}
1313
1314static const scsp_interface scsp_config =
1315{
1316   0,
1317   scsp_irq,
1318   DEVCB_DRIVER_LINE_MEMBER(saturn_state, scsp_to_main_irq)
1319};
1320
1321TIMER_CALLBACK_MEMBER(saturn_state::stv_rtc_increment)
1322{
1323   static const UINT8 dpm[12] = { 0x31, 0x28, 0x31, 0x30, 0x31, 0x30, 0x31, 0x31, 0x30, 0x31, 0x30, 0x31 };
1324   static int year_num, year_count;
1325
1326   /*
1327       m_smpc.rtc_data[0] = DectoBCD(systime.local_time.year /100);
1328       m_smpc.rtc_data[1] = DectoBCD(systime.local_time.year %100);
1329       m_smpc.rtc_data[2] = (systime.local_time.weekday << 4) | (systime.local_time.month+1);
1330       m_smpc.rtc_data[3] = DectoBCD(systime.local_time.mday);
1331       m_smpc.rtc_data[4] = DectoBCD(systime.local_time.hour);
1332       m_smpc.rtc_data[5] = DectoBCD(systime.local_time.minute);
1333       m_smpc.rtc_data[6] = DectoBCD(systime.local_time.second);
1334   */
1335
1336   m_smpc.rtc_data[6]++;
1337
1338   /* seconds from 9 -> 10*/
1339   if((m_smpc.rtc_data[6] & 0x0f) >= 0x0a)         { m_smpc.rtc_data[6]+=0x10; m_smpc.rtc_data[6]&=0xf0; }
1340   /* seconds from 59 -> 0 */
1341   if((m_smpc.rtc_data[6] & 0xf0) >= 0x60)         { m_smpc.rtc_data[5]++;     m_smpc.rtc_data[6] = 0; }
1342   /* minutes from 9 -> 10 */
1343   if((m_smpc.rtc_data[5] & 0x0f) >= 0x0a)         { m_smpc.rtc_data[5]+=0x10; m_smpc.rtc_data[5]&=0xf0; }
1344   /* minutes from 59 -> 0 */
1345   if((m_smpc.rtc_data[5] & 0xf0) >= 0x60)         { m_smpc.rtc_data[4]++;     m_smpc.rtc_data[5] = 0; }
1346   /* hours from 9 -> 10 */
1347   if((m_smpc.rtc_data[4] & 0x0f) >= 0x0a)         { m_smpc.rtc_data[4]+=0x10; m_smpc.rtc_data[4]&=0xf0; }
1348   /* hours from 23 -> 0 */
1349   if((m_smpc.rtc_data[4] & 0xff) >= 0x24)             { m_smpc.rtc_data[3]++; m_smpc.rtc_data[2]+=0x10; m_smpc.rtc_data[4] = 0; }
1350   /* week day name sunday -> monday */
1351   if((m_smpc.rtc_data[2] & 0xf0) >= 0x70)             { m_smpc.rtc_data[2]&=0x0f; }
1352   /* day number 9 -> 10 */
1353   if((m_smpc.rtc_data[3] & 0x0f) >= 0x0a)             { m_smpc.rtc_data[3]+=0x10; m_smpc.rtc_data[3]&=0xf0; }
1354
1355   // year BCD to dec conversion (for the leap year stuff)
1356   {
1357      year_num = (m_smpc.rtc_data[1] & 0xf);
1358
1359      for(year_count = 0; year_count < (m_smpc.rtc_data[1] & 0xf0); year_count += 0x10)
1360         year_num += 0xa;
1361
1362      year_num += (m_smpc.rtc_data[0] & 0xf)*0x64;
1363
1364      for(year_count = 0; year_count < (m_smpc.rtc_data[0] & 0xf0); year_count += 0x10)
1365         year_num += 0x3e8;
1366   }
1367
1368   /* month +1 check */
1369   /* the RTC have a range of 1980 - 2100, so we don't actually need to support the leap year special conditions */
1370   if(((year_num % 4) == 0) && (m_smpc.rtc_data[2] & 0xf) == 2)
1371   {
1372      if((m_smpc.rtc_data[3] & 0xff) >= dpm[(m_smpc.rtc_data[2] & 0xf)-1]+1+1)
1373         { m_smpc.rtc_data[2]++; m_smpc.rtc_data[3] = 0x01; }
1374   }
1375   else if((m_smpc.rtc_data[3] & 0xff) >= dpm[(m_smpc.rtc_data[2] & 0xf)-1]+1){ m_smpc.rtc_data[2]++; m_smpc.rtc_data[3] = 0x01; }
1376   /* year +1 check */
1377   if((m_smpc.rtc_data[2] & 0x0f) > 12)                { m_smpc.rtc_data[1]++;  m_smpc.rtc_data[2] = (m_smpc.rtc_data[2] & 0xf0) | 0x01; }
1378   /* year from 9 -> 10 */
1379   if((m_smpc.rtc_data[1] & 0x0f) >= 0x0a)             { m_smpc.rtc_data[1]+=0x10; m_smpc.rtc_data[1]&=0xf0; }
1380   /* year from 99 -> 100 */
1381   if((m_smpc.rtc_data[1] & 0xf0) >= 0xa0)             { m_smpc.rtc_data[0]++; m_smpc.rtc_data[1] = 0; }
1382
1383   // probably not SO precise, here just for reference ...
1384   /* year from 999 -> 1000 */
1385   //if((m_smpc.rtc_data[0] & 0x0f) >= 0x0a)               { m_smpc.rtc_data[0]+=0x10; m_smpc.rtc_data[0]&=0xf0; }
1386   /* year from 9999 -> 0 */
1387   //if((m_smpc.rtc_data[0] & 0xf0) >= 0xa0)               { m_smpc.rtc_data[0] = 0; } //roll over
1388}
1389
1390/* Official documentation says that the "RESET/TAS opcodes aren't supported", but Out Run definitely contradicts with it.
1391   Since that m68k can't reset itself via the RESET opcode I suppose that the SMPC actually do it by reading an i/o
1392   connected to this opcode. */
1393void saturn_state::m68k_reset_callback(device_t *device)
1394{
1395   saturn_state *state = device->machine().driver_data<saturn_state>();
1396   device->machine().scheduler().timer_set(attotime::from_usec(100), timer_expired_delegate(FUNC(saturn_state::smpc_audio_reset_line_pulse), state));
1397
1398   printf("m68k RESET opcode triggered\n");
1399}
1400
1401MACHINE_START_MEMBER(saturn_state,saturn)
1402{
1403   system_time systime;
1404   machine().base_datetime(systime);
1405
1406   m_maincpu = downcast<legacy_cpu_device*>( machine().device<cpu_device>("maincpu") );
1407   m_slave = downcast<legacy_cpu_device*>( machine().device("slave") );
1408   m_audiocpu = downcast<legacy_cpu_device*>( machine().device<cpu_device>("audiocpu") );
1409
1410   scsp_set_ram_base(machine().device("scsp"), m_sound_ram);
1411
1412   // save states
1413   state_save_register_global_pointer(machine(), m_scu_regs, 0x100/4);
1414   state_save_register_global_pointer(machine(), m_scsp_regs,  0x1000/2);
1415   state_save_register_global(machine(), m_NMI_reset);
1416   state_save_register_global(machine(), m_en_68k);
1417   state_save_register_global(machine(), m_smpc.IOSEL1);
1418   state_save_register_global(machine(), m_smpc.IOSEL2);
1419   state_save_register_global(machine(), m_smpc.EXLE1);
1420   state_save_register_global(machine(), m_smpc.EXLE2);
1421   state_save_register_global(machine(), m_smpc.PDR1);
1422   state_save_register_global(machine(), m_smpc.PDR2);
1423//  state_save_register_global(machine(), m_port_sel);
1424//  state_save_register_global(machine(), mux_data);
1425   state_save_register_global(machine(), m_scsp_last_line);
1426   state_save_register_global(machine(), m_smpc.intback_stage);
1427   state_save_register_global(machine(), m_smpc.pmode);
1428   state_save_register_global(machine(), m_smpc.SR);
1429   state_save_register_global_array(machine(), m_smpc.SMEM);
1430   state_save_register_global_pointer(machine(), m_cart_dram, 0x400000/4);
1431
1432   machine().add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(saturn_state::stvcd_exit), this));
1433
1434   m_smpc.rtc_data[0] = DectoBCD(systime.local_time.year /100);
1435   m_smpc.rtc_data[1] = DectoBCD(systime.local_time.year %100);
1436   m_smpc.rtc_data[2] = (systime.local_time.weekday << 4) | (systime.local_time.month+1);
1437   m_smpc.rtc_data[3] = DectoBCD(systime.local_time.mday);
1438   m_smpc.rtc_data[4] = DectoBCD(systime.local_time.hour);
1439   m_smpc.rtc_data[5] = DectoBCD(systime.local_time.minute);
1440   m_smpc.rtc_data[6] = DectoBCD(systime.local_time.second);
1441
1442   m_stv_rtc_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(saturn_state::stv_rtc_increment),this));
1443
1444   m68k_set_reset_callback(m_audiocpu, &saturn_state::m68k_reset_callback);
1445}
1446
1447
1448/*
1449(Preliminary) explanation about this:
1450VBLANK-OUT is used at the start of the vblank period.It also sets the timer zero
1451variable to 0.
1452If the Timer Compare register is zero too,the Timer 0 irq is triggered.
1453
1454HBLANK-IN is used at the end of each scanline except when in VBLANK-IN/OUT periods.
1455
1456The timer 0 is also incremented by one at each HBLANK and checked with the value
1457of the Timer Compare register;if equal,the timer 0 irq is triggered here too.
1458Notice that the timer 0 compare register can be more than the VBLANK maximum range,in
1459this case the timer 0 irq is simply never triggered.This is a known Sega Saturn/ST-V "bug".
1460
1461VBLANK-IN is used at the end of the vblank period.
1462
1463SCU register[36] is the timer zero compare register.
1464SCU register[40] is for IRQ masking.
1465
1466TODO:
1467- VDP1 timing and CEF emulation isn't accurate at all.
1468*/
1469
1470
1471TIMER_DEVICE_CALLBACK_MEMBER(saturn_state::saturn_scanline)
1472{
1473   int scanline = param;
1474   int y_step,vblank_line;
1475
1476   vblank_line = get_vblank_start_position();
1477   y_step = get_ystep_count();
1478
1479   //popmessage("%08x %d T0 %d T1 %d %08x",m_scu.ism ^ 0xffffffff,max_y,m_scu_regs[36],m_scu_regs[37],m_scu_regs[38]);
1480
1481   if(scanline == (0)*y_step)
1482   {
1483      video_update_vdp1();
1484
1485      if(STV_VDP1_VBE)
1486         m_vdp1.framebuffer_clear_on_next_frame = 1;
1487
1488      if(!(m_scu.ism & IRQ_VDP1_END))
1489      {
1490         m_maincpu->set_input_line_and_vector(0x2, HOLD_LINE, 0x4d);
1491         scu_do_transfer(6);
1492      }
1493      else
1494         m_scu.ist |= (IRQ_VDP1_END);
1495   }
1496
1497   if(scanline == 0*y_step)
1498   {
1499      if(!(m_scu.ism & IRQ_VBLANK_OUT))
1500      {
1501         m_maincpu->set_input_line_and_vector(0xe, HOLD_LINE, 0x41);
1502         scu_do_transfer(1);
1503      }
1504      else
1505         m_scu.ist |= (IRQ_VBLANK_OUT);
1506
1507   }
1508   else if(scanline == vblank_line*y_step)
1509   {
1510      if(!(m_scu.ism & IRQ_VBLANK_IN))
1511      {
1512         m_maincpu->set_input_line_and_vector(0xf, HOLD_LINE ,0x40);
1513         scu_do_transfer(0);
1514      }
1515      else
1516         m_scu.ist |= (IRQ_VBLANK_IN);
1517   }
1518   else if((scanline % y_step) == 0 && scanline < vblank_line*y_step)
1519   {
1520      if(!(m_scu.ism & IRQ_HBLANK_IN))
1521      {
1522         m_maincpu->set_input_line_and_vector(0xd, HOLD_LINE, 0x42);
1523         scu_do_transfer(2);
1524      }
1525      else
1526         m_scu.ist |= (IRQ_HBLANK_IN);
1527   }
1528
1529   if(scanline == (m_scu_regs[36] & 0x3ff)*y_step)
1530   {
1531      if(!(m_scu.ism & IRQ_TIMER_0))
1532      {
1533         m_maincpu->set_input_line_and_vector(0xc, HOLD_LINE, 0x43 );
1534         scu_do_transfer(3);
1535      }
1536      else
1537         m_scu.ist |= (IRQ_TIMER_0);
1538   }
1539
1540   /* TODO: this isn't completely correct */
1541   if(m_scu_regs[38] & 0x1)
1542   {
1543      if((!(m_scu_regs[38] & 0x100) && (scanline % y_step) == 0) ||
1544         ((m_scu_regs[38] & 0x100) && (scanline == (m_scu_regs[36] & 0x3ff)*y_step)))
1545      {
1546         if(!(m_scu.ism & IRQ_TIMER_1))
1547         {
1548            m_maincpu->set_input_line_and_vector(0xb, HOLD_LINE, 0x44 );
1549            scu_do_transfer(4);
1550         }
1551         else
1552            m_scu.ist |= (IRQ_TIMER_1);
1553      }
1554   }
1555}
1556
1557TIMER_DEVICE_CALLBACK_MEMBER(saturn_state::saturn_slave_scanline )
1558{
1559   int scanline = param;
1560   int y_step,vblank_line;
1561
1562   vblank_line = get_vblank_start_position();
1563   y_step = get_ystep_count();
1564
1565   if(scanline == vblank_line*y_step)
1566      m_slave->set_input_line_and_vector(0x6, HOLD_LINE, 0x43);
1567   else if((scanline % y_step) == 0 && scanline < vblank_line*y_step)
1568      m_slave->set_input_line_and_vector(0x2, HOLD_LINE, 0x41);
1569}
1570
1571/* Die Hard Trilogy tests RAM address 0x25e7ffe bit 2 with Slave during FRT minit irq, in-development tool for breaking execution of it? */
1572READ32_MEMBER(saturn_state::saturn_null_ram_r)
1573{
1574   return 0xffffffff;
1575}
1576
1577WRITE32_MEMBER(saturn_state::saturn_null_ram_w)
1578{
1579}
1580
1581READ32_MEMBER(saturn_state::saturn_cart_dram0_r)
1582{
1583   return m_cart_dram[offset];
1584}
1585
1586WRITE32_MEMBER(saturn_state::saturn_cart_dram0_w)
1587{
1588   COMBINE_DATA(&m_cart_dram[offset]);
1589}
1590
1591READ32_MEMBER(saturn_state::saturn_cart_dram1_r)
1592{
1593   return m_cart_dram[offset+0x200000/4];
1594}
1595
1596WRITE32_MEMBER(saturn_state::saturn_cart_dram1_w)
1597{
1598   COMBINE_DATA(&m_cart_dram[offset+0x200000/4]);
1599}
1600
1601READ32_MEMBER(saturn_state::saturn_cs1_r)
1602{
1603   UINT32 res;
1604
1605   res = 0;
1606   //res  = m_cart_backupram[offset*4+0] << 24;
1607   res |= m_cart_backupram[offset*2+0] << 16;
1608   //res |= m_cart_backupram[offset*4+2] << 8;
1609   res |= m_cart_backupram[offset*2+1] << 0;
1610
1611   return res;
1612}
1613
1614WRITE32_MEMBER(saturn_state::saturn_cs1_w)
1615{
1616   if(ACCESSING_BITS_16_23)
1617      m_cart_backupram[offset*2+0] = (data & 0x00ff0000) >> 16;
1618   if(ACCESSING_BITS_0_7)
1619      m_cart_backupram[offset*2+1] = (data & 0x000000ff) >> 0;
1620}
1621
1622void saturn_state::scu_reset(void)
1623{
1624   m_scu.ism = 0xbfff;
1625   m_scu.ist = 0;
1626   m_scu.start_factor[0] = 7;
1627   m_scu.start_factor[1] = 7;
1628   m_scu.start_factor[2] = 7;
1629   m_scu.status = 0;
1630}
1631
1632MACHINE_RESET_MEMBER(saturn_state,saturn)
1633{
1634   m_scsp_last_line = 0;
1635
1636   // don't let the slave cpu and the 68k go anywhere
1637   machine().device("slave")->execute().set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
1638   machine().device("audiocpu")->execute().set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
1639
1640   m_smpc.SR = 0x40;   // this bit is always on according to docs
1641
1642   scu_reset();
1643
1644   m_en_68k = 0;
1645   m_NMI_reset = 0;
1646   m_smpc.slave_on = 0;
1647
1648
1649   //memset(stv_m_workram_l, 0, 0x100000);
1650   //memset(stv_m_workram_h, 0, 0x100000);
1651
1652   machine().device("maincpu")->set_unscaled_clock(MASTER_CLOCK_320/2);
1653   machine().device("slave")->set_unscaled_clock(MASTER_CLOCK_320/2);
1654
1655   stvcd_reset();
1656
1657   m_cart_type = ioport("CART_AREA")->read() & 7;
1658
1659   machine().device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x02400000, 0x027fffff, read32_delegate(FUNC(saturn_state::saturn_null_ram_r),this), write32_delegate(FUNC(saturn_state::saturn_null_ram_w),this));
1660   machine().device("slave")->memory().space(AS_PROGRAM).install_readwrite_handler(0x02400000, 0x027fffff, read32_delegate(FUNC(saturn_state::saturn_null_ram_r),this), write32_delegate(FUNC(saturn_state::saturn_null_ram_w),this));
1661
1662   if(m_cart_type == 5)
1663   {
1664      //  AM_RANGE(0x02400000, 0x027fffff) AM_RAM //cart RAM area, dynamically allocated
1665      machine().device("maincpu")->memory().space(AS_PROGRAM).nop_readwrite(0x02400000, 0x027fffff);
1666      machine().device("slave")->memory().space(AS_PROGRAM).nop_readwrite(0x02400000, 0x027fffff);
1667
1668      machine().device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x02400000, 0x0247ffff, read32_delegate(FUNC(saturn_state::saturn_cart_dram0_r),this), write32_delegate(FUNC(saturn_state::saturn_cart_dram0_w),this));
1669      machine().device("slave")->memory().space(AS_PROGRAM).install_readwrite_handler(0x02400000, 0x0247ffff, read32_delegate(FUNC(saturn_state::saturn_cart_dram0_r),this), write32_delegate(FUNC(saturn_state::saturn_cart_dram0_w),this));
1670      machine().device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x02600000, 0x0267ffff, read32_delegate(FUNC(saturn_state::saturn_cart_dram1_r),this), write32_delegate(FUNC(saturn_state::saturn_cart_dram1_w),this));
1671      machine().device("slave")->memory().space(AS_PROGRAM).install_readwrite_handler(0x02600000, 0x0267ffff, read32_delegate(FUNC(saturn_state::saturn_cart_dram1_r),this), write32_delegate(FUNC(saturn_state::saturn_cart_dram1_w),this));
1672   }
1673
1674   if(m_cart_type == 6)
1675   {
1676      //  AM_RANGE(0x02400000, 0x027fffff) AM_RAM //cart RAM area, dynamically allocated
1677      machine().device("maincpu")->memory().space(AS_PROGRAM).nop_readwrite(0x02400000, 0x027fffff);
1678      machine().device("slave")->memory().space(AS_PROGRAM).nop_readwrite(0x02400000, 0x027fffff);
1679
1680      machine().device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x02400000, 0x025fffff, read32_delegate(FUNC(saturn_state::saturn_cart_dram0_r),this), write32_delegate(FUNC(saturn_state::saturn_cart_dram0_w),this));
1681      machine().device("slave")->memory().space(AS_PROGRAM).install_readwrite_handler(0x02400000, 0x025fffff, read32_delegate(FUNC(saturn_state::saturn_cart_dram0_r),this), write32_delegate(FUNC(saturn_state::saturn_cart_dram0_w),this));
1682      machine().device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x02600000, 0x027fffff, read32_delegate(FUNC(saturn_state::saturn_cart_dram1_r),this), write32_delegate(FUNC(saturn_state::saturn_cart_dram1_w),this));
1683      machine().device("slave")->memory().space(AS_PROGRAM).install_readwrite_handler(0x02600000, 0x027fffff, read32_delegate(FUNC(saturn_state::saturn_cart_dram1_r),this), write32_delegate(FUNC(saturn_state::saturn_cart_dram1_w),this));
1684   }
1685
1686   machine().device("maincpu")->memory().space(AS_PROGRAM).nop_readwrite(0x04000000, 0x047fffff);
1687   machine().device("slave")->memory().space(AS_PROGRAM).nop_readwrite(0x04000000, 0x047fffff);
1688
1689   if(m_cart_type > 0 && m_cart_type < 5)
1690   {
1691   //  AM_RANGE(0x04000000, 0x047fffff) AM_RAM //backup RAM area, dynamically allocated
1692      UINT32 mask;
1693      mask = 0x7fffff >> (4-m_cart_type);
1694      //mask = 0x7fffff >> 4-4 = 0x7fffff 32mbit
1695      //mask = 0x7fffff >> 4-3 = 0x3fffff 16mbit
1696      //mask = 0x7fffff >> 4-2 = 0x1fffff 8mbit
1697      //mask = 0x7fffff >> 4-1 = 0x0fffff 4mbit
1698      machine().device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x04000000, 0x04000000 | mask, read32_delegate(FUNC(saturn_state::saturn_cs1_r),this), write32_delegate(FUNC(saturn_state::saturn_cs1_w),this));
1699      machine().device("slave")->memory().space(AS_PROGRAM).install_readwrite_handler(0x04000000, 0x04000000 | mask, read32_delegate(FUNC(saturn_state::saturn_cs1_r),this), write32_delegate(FUNC(saturn_state::saturn_cs1_w),this));
1700   }
1701
1702   m_vdp2.old_crmd = -1;
1703   m_vdp2.old_tvmd = -1;
1704
1705   m_stv_rtc_timer->adjust(attotime::zero, 0, attotime::from_seconds(1));
1706}
1707
1708
1709struct cdrom_interface saturn_cdrom =
1710{
1711   "sat_cdrom",
1712   NULL
1713};
1714
1715
1716
1717
1718DEVICE_IMAGE_LOAD_MEMBER( saturn_state, sat_cart )
1719{
1720   UINT8 *ROM = image.device().memregion("maincpu")->base()+0x080000;
1721   UINT32 length;
1722
1723   if (image.software_entry() != NULL)
1724   {
1725      length = image.get_software_region_length("cart");
1726      UINT8* imagex =  image.get_software_region("cart");
1727
1728      memcpy(ROM, imagex, length);
1729   }
1730   else
1731   {
1732      length = image.fread( ROM, 0x400000);
1733   }
1734
1735   // fix endianness....
1736   for (int i=0;i<length;i+=4)
1737   {
1738      UINT8 tempa = ROM[i+0];
1739      UINT8 tempb = ROM[i+1];
1740      ROM[i+1] = ROM[i+2];
1741      ROM[i+0] = ROM[i+3];
1742      ROM[i+3] = tempa;
1743      ROM[i+2] = tempb;
1744   }
1745
1746   return IMAGE_INIT_PASS;
1747}
1748
1749static MACHINE_CONFIG_START( saturn, saturn_state )
1750
1751   /* basic machine hardware */
1752   MCFG_CPU_ADD("maincpu", SH2, MASTER_CLOCK_352/2) // 28.6364 MHz
1753   MCFG_CPU_PROGRAM_MAP(saturn_mem)
1754   MCFG_CPU_CONFIG(sh2_conf_master)
1755   MCFG_TIMER_DRIVER_ADD_SCANLINE("scantimer", saturn_state, saturn_scanline, "screen", 0, 1)
1756
1757   MCFG_CPU_ADD("slave", SH2, MASTER_CLOCK_352/2) // 28.6364 MHz
1758   MCFG_CPU_PROGRAM_MAP(saturn_mem)
1759   MCFG_CPU_CONFIG(sh2_conf_slave)
1760   MCFG_TIMER_DRIVER_ADD_SCANLINE("slave_scantimer", saturn_state, saturn_slave_scanline, "screen", 0, 1)
1761
1762   MCFG_CPU_ADD("audiocpu", M68000, 11289600) //256 x 44100 Hz = 11.2896 MHz
1763   MCFG_CPU_PROGRAM_MAP(sound_mem)
1764
1765   MCFG_MACHINE_START_OVERRIDE(saturn_state,saturn)
1766   MCFG_MACHINE_RESET_OVERRIDE(saturn_state,saturn)
1767
1768   MCFG_NVRAM_HANDLER(saturn)
1769
1770   MCFG_TIMER_DRIVER_ADD("sector_timer", saturn_state, stv_sector_cb)
1771   MCFG_TIMER_DRIVER_ADD("sh1_cmd", saturn_state, stv_sh1_sim)
1772
1773   /* video hardware */
1774   MCFG_SCREEN_ADD("screen", RASTER)
1775   MCFG_SCREEN_RAW_PARAMS(MASTER_CLOCK_320/8, 427, 0, 320, 263, 0, 224)
1776   MCFG_SCREEN_UPDATE_DRIVER(saturn_state, screen_update_stv_vdp2)
1777   MCFG_PALETTE_LENGTH(2048+(2048*2))//standard palette + extra memory for rgb brightness.
1778
1779   MCFG_GFXDECODE(stv)
1780
1781   MCFG_VIDEO_START_OVERRIDE(saturn_state,stv_vdp2)
1782
1783   MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
1784
1785   MCFG_SOUND_ADD("scsp", SCSP, 0)
1786   MCFG_SOUND_CONFIG(scsp_config)
1787   MCFG_SOUND_ROUTE(0, "lspeaker", 1.0)
1788   MCFG_SOUND_ROUTE(1, "rspeaker", 1.0)
1789
1790   MCFG_SOUND_ADD("cdda", CDDA, 0)
1791   MCFG_SOUND_ROUTE(0, "lspeaker", 1.0)
1792   MCFG_SOUND_ROUTE(1, "rspeaker", 1.0)
1793MACHINE_CONFIG_END
1794
1795MACHINE_CONFIG_DERIVED( saturnus, saturn )
1796   MCFG_CDROM_ADD( "cdrom",saturn_cdrom )
1797   MCFG_SOFTWARE_LIST_ADD("cd_list","saturn")
1798   MCFG_SOFTWARE_LIST_FILTER("cd_list","NTSC-U")
1799
1800   MCFG_CARTSLOT_ADD("cart")
1801   MCFG_CARTSLOT_INTERFACE("sat_cart")
1802   MCFG_CARTSLOT_LOAD(saturn_state, sat_cart)
1803   MCFG_SOFTWARE_LIST_ADD("cart_list","sat_cart")
1804
1805MACHINE_CONFIG_END
1806
1807MACHINE_CONFIG_DERIVED( saturneu, saturn )
1808   MCFG_CDROM_ADD( "cdrom",saturn_cdrom )
1809   MCFG_SOFTWARE_LIST_ADD("cd_list","saturn")
1810   MCFG_SOFTWARE_LIST_FILTER("cd_list","PAL")
1811
1812   MCFG_CARTSLOT_ADD("cart")
1813   MCFG_CARTSLOT_INTERFACE("sat_cart")
1814   MCFG_CARTSLOT_LOAD(saturn_state, sat_cart)
1815   MCFG_SOFTWARE_LIST_ADD("cart_list","sat_cart")
1816
1817MACHINE_CONFIG_END
1818
1819MACHINE_CONFIG_DERIVED( saturnjp, saturn )
1820   MCFG_CDROM_ADD( "cdrom",saturn_cdrom )
1821   MCFG_SOFTWARE_LIST_ADD("cd_list","saturn")
1822   MCFG_SOFTWARE_LIST_FILTER("cd_list","NTSC-J")
1823
1824   MCFG_CARTSLOT_ADD("cart")
1825   MCFG_CARTSLOT_INTERFACE("sat_cart")
1826   MCFG_CARTSLOT_LOAD(saturn_state, sat_cart)
1827   MCFG_SOFTWARE_LIST_ADD("cart_list","sat_cart")
1828
1829MACHINE_CONFIG_END
1830
1831
1832void saturn_state::saturn_init_driver(int rgn)
1833{
1834   m_saturn_region = rgn;
1835   m_vdp2.pal = (rgn == 12) ? 1 : 0;
1836
1837   // set compatible options
1838   sh2drc_set_options(machine().device("maincpu"), SH2DRC_STRICT_VERIFY|SH2DRC_STRICT_PCREL);
1839   sh2drc_set_options(machine().device("slave"), SH2DRC_STRICT_VERIFY|SH2DRC_STRICT_PCREL);
1840
1841   /* amount of time to boost interleave for on MINIT / SINIT, needed for communication to work */
1842   m_minit_boost = 400;
1843   m_sinit_boost = 400;
1844   m_minit_boost_timeslice = attotime::zero;
1845   m_sinit_boost_timeslice = attotime::zero;
1846
1847   m_scu_regs = auto_alloc_array_clear(machine(), UINT32, 0x100/4);
1848   m_scsp_regs = auto_alloc_array_clear(machine(), UINT16, 0x1000/2);
1849   m_cart_dram = auto_alloc_array_clear(machine(), UINT32, 0x400000/4);
1850   m_backupram = auto_alloc_array_clear(machine(), UINT8, 0x8000);
1851   m_cart_backupram = auto_alloc_array_clear(machine(), UINT8, 0x400000);
1852}
1853
1854DRIVER_INIT_MEMBER(saturn_state,saturnus)
1855{
1856   saturn_init_driver(4);
1857}
1858
1859DRIVER_INIT_MEMBER(saturn_state,saturneu)
1860{
1861   saturn_init_driver(12);
1862}
1863
1864DRIVER_INIT_MEMBER(saturn_state,saturnjp)
1865{
1866   saturn_init_driver(1);
1867}
1868
1869
1870/* Japanese Saturn */
1871ROM_START(saturnjp)
1872   ROM_REGION( 0x480000, "maincpu", ROMREGION_ERASEFF ) /* SH2 code */
1873   ROM_SYSTEM_BIOS(0, "101", "Japan v1.01 (941228)")
1874   ROMX_LOAD("sega_101.bin", 0x00000000, 0x00080000, CRC(224b752c) SHA1(df94c5b4d47eb3cc404d88b33a8fda237eaf4720), ROM_BIOS(1))
1875   ROM_SYSTEM_BIOS(1, "1003", "Japan v1.003 (941012)")
1876   ROMX_LOAD("sega1003.bin", 0x00000000, 0x00080000, CRC(b3c63c25) SHA1(7b23b53d62de0f29a23e423d0fe751dfb469c2fa), ROM_BIOS(2))
1877   ROM_SYSTEM_BIOS(2, "100", "Japan v1.00 (940921)")
1878   ROMX_LOAD("sega_100.bin", 0x00000000, 0x00080000, CRC(2aba43c2) SHA1(2b8cb4f87580683eb4d760e4ed210813d667f0a2), ROM_BIOS(3))
1879//  ROM_CART_LOAD("cart", 0x080000, 0x400000, ROM_NOMIRROR | ROM_OPTIONAL)
1880   ROM_REGION( 0x080000, "slave", 0 ) /* SH2 code */
1881   ROM_COPY( "maincpu",0,0,0x080000)
1882ROM_END
1883
1884/* Overseas Saturn */
1885ROM_START(saturn)
1886   ROM_REGION( 0x480000, "maincpu", ROMREGION_ERASEFF ) /* SH2 code */
1887   ROM_SYSTEM_BIOS(0, "101a", "Overseas v1.01a (941115)")
1888   /* Confirmed by ElBarto */
1889   ROMX_LOAD("mpr-17933.bin", 0x00000000, 0x00080000, CRC(4afcf0fa) SHA1(faa8ea183a6d7bbe5d4e03bb1332519800d3fbc3), ROM_BIOS(1))
1890   ROM_SYSTEM_BIOS(1, "100a", "Overseas v1.00a (941115)")
1891   ROMX_LOAD("sega_100a.bin", 0x00000000, 0x00080000, CRC(f90f0089) SHA1(3bb41feb82838ab9a35601ac666de5aacfd17a58), ROM_BIOS(2))
1892//  ROM_CART_LOAD("cart", 0x080000, 0x400000, ROM_NOMIRROR | ROM_OPTIONAL)
1893   ROM_REGION( 0x080000, "slave", 0 ) /* SH2 code */
1894   ROM_COPY( "maincpu",0,0,0x080000)
1895ROM_END
1896
1897ROM_START(saturneu)
1898   ROM_REGION( 0x480000, "maincpu", ROMREGION_ERASEFF ) /* SH2 code */
1899   ROM_SYSTEM_BIOS(0, "101a", "Overseas v1.01a (941115)")
1900   /* Confirmed by ElBarto */
1901   ROMX_LOAD("mpr-17933.bin", 0x00000000, 0x00080000, CRC(4afcf0fa) SHA1(faa8ea183a6d7bbe5d4e03bb1332519800d3fbc3), ROM_BIOS(1))
1902   ROM_SYSTEM_BIOS(1, "100a", "Overseas v1.00a (941115)")
1903   ROMX_LOAD("sega_100a.bin", 0x00000000, 0x00080000, CRC(f90f0089) SHA1(3bb41feb82838ab9a35601ac666de5aacfd17a58), ROM_BIOS(2))
1904//  ROM_CART_LOAD("cart", 0x080000, 0x400000, ROM_NOMIRROR | ROM_OPTIONAL)
1905   ROM_REGION( 0x080000, "slave", 0 ) /* SH2 code */
1906   ROM_COPY( "maincpu",0,0,0x080000)
1907ROM_END
1908
1909ROM_START(vsaturn)
1910   ROM_REGION( 0x480000, "maincpu", ROMREGION_ERASEFF ) /* SH2 code */
1911   ROM_LOAD("vsaturn.bin", 0x00000000, 0x00080000, CRC(e4d61811) SHA1(4154e11959f3d5639b11d7902b3a393a99fb5776))
1912//  ROM_CART_LOAD("cart", 0x080000, 0x400000, ROM_NOMIRROR | ROM_OPTIONAL)
1913   ROM_REGION( 0x080000, "slave", 0 ) /* SH2 code */
1914   ROM_COPY( "maincpu",0,0,0x080000)
1915ROM_END
1916
1917ROM_START(hisaturn)
1918   ROM_REGION( 0x480000, "maincpu", ROMREGION_ERASEFF ) /* SH2 code */
1919   ROM_LOAD("hisaturn.bin", 0x00000000, 0x00080000, CRC(721e1b60) SHA1(49d8493008fa715ca0c94d99817a5439d6f2c796))
1920//  ROM_CART_LOAD("cart", 0x080000, 0x400000, ROM_NOMIRROR | ROM_OPTIONAL)
1921   ROM_REGION( 0x080000, "slave", 0 ) /* SH2 code */
1922   ROM_COPY( "maincpu",0,0,0x080000)
1923ROM_END
1924
1925/*    YEAR  NAME        PARENT  COMPAT  MACHINE INPUT   INIT        COMPANY     FULLNAME            FLAGS */
1926CONS( 1994, saturn,     0,      0,      saturnus, saturn, saturn_state, saturnus,   "Sega",     "Saturn (USA)",     GAME_NOT_WORKING )
1927CONS( 1994, saturnjp,   saturn, 0,      saturnjp, saturn, saturn_state, saturnjp,   "Sega",     "Saturn (Japan)",   GAME_NOT_WORKING )
1928CONS( 1994, saturneu,   saturn, 0,      saturneu, saturn, saturn_state, saturneu,   "Sega",     "Saturn (PAL)",     GAME_NOT_WORKING )
1929CONS( 1995, vsaturn,    saturn, 0,      saturnjp, saturn, saturn_state, saturnjp,   "JVC",      "V-Saturn",         GAME_NOT_WORKING )
1930CONS( 1995, hisaturn,   saturn, 0,      saturnjp, saturn, saturn_state, saturnjp,   "Hitachi",  "HiSaturn",         GAME_NOT_WORKING )
trunk/src/mame/mame.mak
r21330r21331
12881288   $(DRIVERS)/segaybd.o $(VIDEO)/segaybd.o \
12891289   $(DRIVERS)/sg1000a.o \
12901290   $(DRIVERS)/stactics.o $(VIDEO)/stactics.o \
1291   $(DRIVERS)/stv.o $(DRIVERS)/saturn.o $(MACHINE)/stvprot.o \
1291   $(DRIVERS)/stv.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 \

Previous 199869 Revisions Next


© 1997-2024 The MAME Team