Previous 199869 Revisions Next

r31778 Tuesday 26th August, 2014 at 05:54:24 UTC by Fabio Priuli
(MESS) a7800: split video emulation (Atari MARIA chip) into a
separate device. [Fabio Priuli]
[src/mess]mess.mak
[src/mess/drivers]a7800.c
[src/mess/includes]a7800.h
[src/mess/video]a7800.c maria.c* maria.h*

trunk/src/mess/includes/a7800.h
r31777r31778
1/*****************************************************************************
2 *
3 * includes/a7800.h
4 *
5 ****************************************************************************/
6
7#ifndef A7800_H_
8#define A7800_H_
9
10#include "machine/6532riot.h"
11#include "sound/tiasound.h"
12#include "sound/tiaintf.h"
13#include "bus/a7800/a78_slot.h"
14
15
16class a7800_state : public driver_device
17{
18public:
19   a7800_state(const machine_config &mconfig, device_type type, const char *tag)
20      : driver_device(mconfig, type, tag),
21      m_maincpu(*this, "maincpu"),
22      m_tia(*this, "tia"),
23      m_io_joysticks(*this, "joysticks"),
24      m_io_buttons(*this, "buttons"),
25      m_io_vblank(*this, "vblank"),
26      m_io_console_buttons(*this, "console_buttons"),
27      m_cartslot(*this, "cartslot"),
28      m_screen(*this, "screen") { }
29
30   int m_lines;
31   int m_ispal;
32
33   int m_ctrl_lock;
34   int m_ctrl_reg;
35   int m_maria_flag;
36   int m_p1_one_button;
37   int m_p2_one_button;
38   int m_bios_enabled;
39
40   UINT8 *m_bios;
41
42   int m_maria_palette[32];
43   int m_line_ram[2][160];
44   int m_active_buffer;
45   int m_maria_write_mode;
46   unsigned int m_maria_dll;
47   unsigned int m_maria_dl;
48   int m_maria_holey;
49   int m_maria_offset;
50   int m_maria_vblank;
51   int m_maria_dli;
52   int m_maria_dmaon;
53   int m_maria_dpp;
54   int m_maria_wsync;
55   int m_maria_backcolor;
56   int m_maria_color_kill;
57   int m_maria_cwidth;
58   int m_maria_bcntl;
59   int m_maria_kangaroo;
60   int m_maria_rm;
61   int m_maria_nmi;
62   unsigned int m_maria_charbase;
63   bitmap_ind16 m_bitmap;
64
65   DECLARE_READ8_MEMBER(bios_or_cart_r);
66   DECLARE_WRITE8_MEMBER(ram0_w);
67   DECLARE_READ8_MEMBER(tia_r);
68   DECLARE_WRITE8_MEMBER(tia_w);
69   DECLARE_READ8_MEMBER(maria_r);
70   DECLARE_WRITE8_MEMBER(maria_w);
71   DECLARE_DRIVER_INIT(a7800_pal);
72   DECLARE_DRIVER_INIT(a7800_ntsc);
73   virtual void machine_start();
74   virtual void machine_reset();
75   virtual void video_start();
76   DECLARE_PALETTE_INIT(a7800);
77   DECLARE_PALETTE_INIT(a7800p);
78   UINT32 screen_update_a7800(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
79   TIMER_DEVICE_CALLBACK_MEMBER(a7800_interrupt);
80   TIMER_CALLBACK_MEMBER(a7800_maria_startdma);
81   DECLARE_READ8_MEMBER(riot_joystick_r);
82   DECLARE_READ8_MEMBER(riot_console_button_r);
83   DECLARE_WRITE8_MEMBER(riot_button_pullup_w);
84
85protected:
86   required_device<cpu_device> m_maincpu;
87   required_device<tia_device> m_tia;
88   required_ioport m_io_joysticks;
89   required_ioport m_io_buttons;
90   required_ioport m_io_vblank;
91   required_ioport m_io_console_buttons;
92   required_device<a78_cart_slot_device> m_cartslot;
93   required_device<screen_device> m_screen;
94
95   void maria_draw_scanline();
96   int is_holey(unsigned int addr);
97   int write_line_ram(int addr, UINT8 offset, int pal);
98};
99
100#endif
trunk/src/mess/video/a7800.c
r31777r31778
1/***************************************************************************
2
3  video/a7800.c
4
5  Routines to control the Atari 7800 video hardware
6
7    2014-05-06 Mike Saarna Added interrupts to DMA cycle eating. Updates to
8                LL, OL, and spin accounting for HALT behavior.
9
10    2014-03-24 Mike Saarna Fixed DMA regarding startup, shutdown and
11                            cycle stealing.
12
13    2013-05-08 huygens rewrite to emulate line ram buffers (mostly fixes Kung-Fu Master
14                            Started DMA cycle stealing implementation
15
16    2003-06-23 ericball Kangaroo mode & 320 mode & other stuff
17
18    2002-05-14 kubecj vblank dma stop fix
19
20    2002-05-13 kubecj   fixed 320C mode (displayed 2 pixels instead of one!)
21                            noticed that Jinks uses 0x02-320D mode
22                            implemented the mode - completely unsure if good!
23                            implemented some Maria CTRL variables
24
25    2002-05-12 kubecj added cases for 0x01-160A, 0x05-160B as stated by docs
26
27***************************************************************************/
28
29#include "emu.h"
30#include "cpu/m6502/m6502.h"
31#include "includes/a7800.h"
32
33
34#define TRIGGER_HSYNC   64717
35
36#define READ_MEM(x) space.read_byte(x)
37
38/********** Maria ***********/
39
40/***************************************************************************
41
42  Start the video hardware emulation.
43
44***************************************************************************/
45void a7800_state::video_start()
46{
47   int i,j;
48   for(i=0; i<32; i++)
49   {
50      m_maria_palette[i]=0;
51   }
52
53   for(i=0; i<2; i++)
54   {
55      for(j=0; j<160; j++)
56         m_line_ram[i][j] = 0;
57   }
58
59   m_active_buffer = 0;
60
61   m_maria_write_mode=0;
62   m_maria_dmaon=0;
63   m_maria_vblank=0x80;
64   m_maria_dll=0;
65   m_maria_wsync=0;
66
67   m_maria_color_kill = 0;
68   m_maria_cwidth = 0;
69   m_maria_bcntl = 0;
70   m_maria_kangaroo = 0;
71   m_maria_rm = 0;
72
73   machine().first_screen()->register_screen_bitmap(m_bitmap);
74}
75
76/***************************************************************************
77
78  Stop the video hardware emulation.
79
80***************************************************************************/
81
82int a7800_state::is_holey(unsigned int addr)
83{
84   if (((m_maria_holey & 0x02) && ((addr & 0x9000) == 0x9000)) || ( (m_maria_holey & 0x01) && ((addr & 0x8800) == 0x8800)))
85      return 1;
86   else
87      return 0;
88}
89
90int a7800_state::write_line_ram(int addr, UINT8 offset, int pal)
91{
92   address_space& space = m_maincpu->space(AS_PROGRAM);
93   int data, c;
94
95   data = READ_MEM(addr);
96   pal = pal << 2;
97
98   if (m_maria_write_mode)
99   {
100      c = (pal & 0x10) | (data & 0x0C) | (data >> 6); // P2 D3 D2 D7 D6
101      if (((c & 3) || m_maria_kangaroo) && (offset < 160))
102         m_line_ram[m_active_buffer][offset] = c;
103      offset++;
104      c = (pal & 0x10) | ((data & 0x03) << 2) | ((data & 0x30) >> 4); // P2 D1 D0 D5 D4
105      if (((c & 3) || m_maria_kangaroo) && (offset < 160))
106         m_line_ram[m_active_buffer][offset] = c;
107   }
108   else
109   {
110      for (int i=0; i<4; i++, offset++)
111      {
112         c = pal | ((data >> (6 - 2*i)) & 0x03);
113         if (((c & 3) || m_maria_kangaroo) && (offset < 160))
114            m_line_ram[m_active_buffer][offset] = c;
115      }
116   }
117   return m_maria_write_mode ? 2 : 4;
118}
119
120
121void a7800_state::maria_draw_scanline()
122{
123   address_space& space = m_maincpu->space(AS_PROGRAM);
124   unsigned int graph_adr,data_addr;
125   int width,pal,ind;
126   UINT8 hpos;
127   unsigned int dl;
128   int x, d, c, i, pixel_cell, cells;
129   int maria_cycles;
130
131   if ( m_maria_offset == 0 )
132   {
133      if(READ_MEM(m_maria_dll+3) & 0x80)
134         maria_cycles=40; // DMA + maria interrupt overhead
135      else
136         maria_cycles=19; // DMA
137      }
138      else
139      {
140         maria_cycles = 16; // DMA
141         }
142
143   cells = 0;
144
145   /* Process this DLL entry */
146   dl = m_maria_dl;
147
148   /* DMA */
149   /* Step through DL's */
150   while ((READ_MEM(dl + 1) & 0x5F) != 0)
151   {
152      /* Extended header */
153      if (!(READ_MEM(dl+1) & 0x1F))
154      {
155         graph_adr = (READ_MEM(dl+2) << 8) | READ_MEM(dl);
156         width = ((READ_MEM(dl+3) ^ 0xff) & 0x1F) + 1;
157         hpos = READ_MEM(dl+4);
158         pal = READ_MEM(dl+3) >> 5;
159         m_maria_write_mode = (READ_MEM(dl+1) & 0x80) >> 5;
160         ind = READ_MEM(dl+1) & 0x20;
161         dl+=5;
162         maria_cycles += 10;
163      }
164      /* Normal header */
165      else
166      {
167         graph_adr = (READ_MEM(dl+2) << 8) | READ_MEM(dl);
168         width = ((READ_MEM(dl+1) ^ 0xff) & 0x1F) + 1;
169         hpos = READ_MEM(dl+3);
170         pal = READ_MEM(dl+1) >> 5;
171         ind = 0x00;
172         dl+=4;
173         maria_cycles += 8;
174      }
175
176      /*logerror("%x DL: ADR=%x  width=%x  hpos=%x  pal=%x  mode=%x  ind=%x\n",m_screen->vpos(),graph_adr,width,hpos,pal,m_maria_write_mode,ind );*/
177
178      for (x=0; x<width; x++)
179      {
180         /* Do indirect mode */
181         if (ind)
182         {
183            c = READ_MEM(graph_adr + x) & 0xFF;
184            data_addr = (m_maria_charbase | c) + (m_maria_offset << 8);
185            if (is_holey(data_addr))
186               continue;
187            maria_cycles += 3;
188            if( m_maria_cwidth ) // two data bytes per map byte
189            {
190               cells = write_line_ram(data_addr, hpos, pal);
191               hpos += cells;
192               cells = write_line_ram(data_addr+1, hpos, pal);
193               hpos += cells;
194               maria_cycles += 6;
195            }
196            else
197            {
198               cells = write_line_ram(data_addr, hpos, pal);
199               hpos += cells;
200               maria_cycles += 3;
201            }
202         }
203         else // direct mode
204         {
205            data_addr = graph_adr + x + (m_maria_offset  << 8);
206            if (is_holey(data_addr))
207               continue;
208            cells = write_line_ram(data_addr, hpos, pal);
209            hpos += cells;
210            maria_cycles += 3;
211         }
212      }
213   }
214   // Spin the CPU for Maria DMA, if it's not already spinning for WSYNC.
215   // MARIA generates the 6502 clock by dividing its own clock by 4. It needs to HALT and unHALT
216   // the 6502 on ths same clock phase, so MARIA will wait until its clock divides evenly by 4.
217   // To spin until an even divisor, we just round-up any would-be truncations by adding 3.
218   if ( ! m_maria_wsync )
219      m_maincpu->spin_until_time(m_maincpu->cycles_to_attotime((maria_cycles+3)/4));
220
221   // draw line buffer to screen
222   m_active_buffer = !m_active_buffer; // switch buffers
223   UINT16 *scanline;
224   scanline = &m_bitmap.pix16(m_screen->vpos());
225
226
227   for ( i = 0; i<160; i++ )
228   {
229      switch (m_maria_rm)
230      {
231         case 0x00:  /* 160A, 160B */
232         case 0x01:  /* 160A, 160B */
233            pixel_cell =  m_line_ram[m_active_buffer][i];
234            scanline[2*i] = m_maria_palette[pixel_cell];
235            scanline[2*i+1] = m_maria_palette[pixel_cell];
236            break;
237
238         case 0x02: /* 320B, 320D */
239            pixel_cell = m_line_ram[m_active_buffer][i];
240            d = (pixel_cell & 0x10) | (pixel_cell & 0x02) | ((pixel_cell >> 3) & 1); // b4 0 0 b1 b3
241            scanline[2*i] = m_maria_palette[d];
242            d = (pixel_cell & 0x10) | ((pixel_cell << 1) & 0x02) | ((pixel_cell >> 2) & 1); // b4 0 0 b0 b2
243            scanline[2*i+1] = m_maria_palette[d];
244            break;
245
246         case 0x03:  /* 320A, 320C */
247            pixel_cell = m_line_ram[m_active_buffer][i];
248            d = (pixel_cell & 0x1C) | (pixel_cell & 0x02); // b4 b3 b2 b1 0
249            scanline[2*i] = m_maria_palette[d];
250            d = (pixel_cell & 0x1C) | ((pixel_cell << 1) & 0x02); // b4 b3 b2 b0 0
251            scanline[2*i+1] = m_maria_palette[d];
252            break;
253      }
254   }
255
256   for(i=0; i<160; i++) // buffer automaticaly cleared once displayed
257      m_line_ram[m_active_buffer][i] = 0;
258}
259
260
261
262TIMER_DEVICE_CALLBACK_MEMBER(a7800_state::a7800_interrupt)
263{
264   // DMA Begins 7 cycles after hblank
265   machine().scheduler().timer_set(m_maincpu->cycles_to_attotime(7), timer_expired_delegate(FUNC(a7800_state::a7800_maria_startdma),this));
266   if( m_maria_wsync )
267   {
268      machine().scheduler().trigger( TRIGGER_HSYNC );
269      m_maria_wsync = 0;
270   }
271
272   int frame_scanline = m_screen->vpos() % ( m_lines + 1 );
273   if (frame_scanline == 16)
274      m_maria_vblank = 0x00;
275
276   if ( frame_scanline == ( m_lines - 5 ) )
277   {
278      m_maria_vblank = 0x80;
279   }
280}
281
282
283TIMER_CALLBACK_MEMBER(a7800_state::a7800_maria_startdma)
284{
285   int frame_scanline;
286   address_space& space = m_maincpu->space(AS_PROGRAM);
287   int maria_scanline = m_screen->vpos();
288
289   frame_scanline = maria_scanline % ( m_lines + 1 );
290
291   if( (frame_scanline == 16) && m_maria_dmaon )
292   {
293      /* end of vblank */
294
295      m_maria_dll = m_maria_dpp; // currently only handle changes to dll during vblank
296      m_maria_dl = (READ_MEM(m_maria_dll+1) << 8) | READ_MEM(m_maria_dll+2);
297      m_maria_offset = READ_MEM(m_maria_dll) & 0x0f;
298      m_maria_holey = (READ_MEM(m_maria_dll) & 0x60) >> 5;
299      m_maria_nmi = READ_MEM(m_maria_dll) & 0x80;
300      /*  logerror("DLL=%x\n",m_maria_dll); */
301      maria_draw_scanline();
302   }
303
304
305   if( ( frame_scanline > 16 ) && (frame_scanline < (m_lines - 5)) && m_maria_dmaon )
306   {
307      maria_draw_scanline();
308
309      if( m_maria_offset == 0 )
310      {
311         m_maria_dll+=3;
312         m_maria_dl = (READ_MEM(m_maria_dll+1) << 8) | READ_MEM(m_maria_dll+2);
313         m_maria_offset = READ_MEM(m_maria_dll) & 0x0f;
314         m_maria_holey = (READ_MEM(m_maria_dll) & 0x60) >> 5;
315         if ( READ_MEM(m_maria_dll & 0x10) )
316            logerror("dll bit 5 set!\n");
317         m_maria_nmi = READ_MEM(m_maria_dll) & 0x80;
318      }
319      else
320      {
321         m_maria_offset--;
322      }
323   }
324
325   if( m_maria_nmi )
326   {
327      m_maincpu->set_input_line(INPUT_LINE_NMI, PULSE_LINE);
328      m_maria_nmi = 0;
329   }
330}
331
332/***************************************************************************
333
334  Refresh the video screen
335
336***************************************************************************/
337/* This routine is called at the start of vblank to refresh the screen */
338UINT32 a7800_state::screen_update_a7800(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
339{
340   copybitmap(bitmap, m_bitmap, 0, 0, 0, 0, cliprect);
341   return 0;
342}
343
344
345/****** MARIA ***************************************/
346
347READ8_MEMBER(a7800_state::maria_r)
348{
349   switch (offset)
350   {
351      case 0x08:
352         return m_maria_vblank;
353
354      default:
355         logerror("undefined MARIA read %x\n",offset);
356         return 0x00; // don't know if this should be 0x00 or 0xff
357   }
358}
359
360WRITE8_MEMBER(a7800_state::maria_w)
361{
362   int i;
363
364   if ((offset & 3) != 0)
365      m_maria_palette[offset] = data;
366
367   switch (offset)
368   {
369      case 0x00:
370         // all color ram addresses with 00 for their least significant bits point to the background color
371         for (i = 0; i<8; i++)
372            m_maria_palette[4*i] = data;
373         break;
374      case 0x04:
375         m_maincpu->spin_until_trigger(TRIGGER_HSYNC);
376         m_maria_wsync=1;
377         break;
378      case 0x0C: // DPPH
379         m_maria_dpp = (m_maria_dpp & 0x00ff) | (data << 8);
380         break;
381      case 0x10: // DPPL
382         m_maria_dpp = (m_maria_dpp & 0xff00) | data;
383         break;
384      case 0x14:
385         m_maria_charbase = (data << 8);
386         break;
387      case 0x1C:
388         /*logerror("MARIA CTRL=%x\n",data);*/
389         m_maria_color_kill = data & 0x80;
390         switch ((data >> 5) & 3)
391         {
392            case 0x00: case 01:
393            logerror("dma test mode, do not use.\n");
394            break;
395            case 0x02:
396            m_maria_dmaon = 1;
397            break;
398            case 0x03:
399            m_maria_dmaon = 0;
400            break;
401         }
402         m_maria_cwidth = data & 0x10;
403         m_maria_bcntl = data & 0x08; // Currently unimplemented as we don't display the border
404         m_maria_kangaroo = data & 0x04;
405         m_maria_rm = data & 0x03;
406
407         /*logerror( "MARIA CTRL: CK:%d DMA:%d CW:%d BC:%d KM:%d RM:%d\n",
408                 m_maria_color_kill ? 1 : 0,
409                 ( data & 0x60 ) >> 5,
410                 m_maria_cwidth ? 1 : 0,
411                 m_maria_bcntl ? 1 : 0,
412                 m_maria_kangaroo ? 1 : 0,
413                 m_maria_rm );*/
414
415         break;
416   }
417}
trunk/src/mess/video/maria.c
r0r31778
1/***************************************************************************
2
3  Atari MARIA video emulation
4
5 
6  - some history:
7 
8    2014-08-26 Fabio Priuli Converted to device
9
10    2014-05-06 Mike Saarna Added interrupts to DMA cycle eating. Updates to
11                LL, OL, and spin accounting for HALT behavior.
12
13    2014-03-24 Mike Saarna Fixed DMA regarding startup, shutdown and
14                            cycle stealing.
15
16    2013-05-08 huygens rewrite to emulate line ram buffers (mostly fixes Kung-Fu Master
17                            Started DMA cycle stealing implementation
18
19    2003-06-23 ericball Kangaroo mode & 320 mode & other stuff
20
21    2002-05-14 kubecj vblank dma stop fix
22
23    2002-05-13 kubecj   fixed 320C mode (displayed 2 pixels instead of one!)
24                            noticed that Jinks uses 0x02-320D mode
25                            implemented the mode - completely unsure if good!
26                            implemented some Maria CTRL variables
27
28    2002-05-12 kubecj added cases for 0x01-160A, 0x05-160B as stated by docs
29
30***************************************************************************/
31
32#include "emu.h"
33#include "maria.h"
34
35
36#define TRIGGER_HSYNC   64717
37
38#define READ_MEM(x) space.read_byte(x)
39
40const device_type ATARI_MARIA = &device_creator<atari_maria_device>;
41
42
43
44atari_maria_device::atari_maria_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
45               : device_t(mconfig, ATARI_MARIA, "Atari MARIA", tag, owner, clock, "atari_maria", __FILE__)
46{
47}
48
49
50void atari_maria_device::device_start()
51{   
52   m_cpu = machine().device<cpu_device>(m_cpu_tag);
53   m_screen = machine().first_screen();
54   m_screen->register_screen_bitmap(m_bitmap);
55
56   save_item(NAME(m_maria_palette));
57   save_item(NAME(m_line_ram));
58   save_item(NAME(m_active_buffer));
59   save_item(NAME(m_write_mode));
60   save_item(NAME(m_dll));
61   save_item(NAME(m_dl));
62   save_item(NAME(m_holey));
63   save_item(NAME(m_offset));
64   save_item(NAME(m_vblank));
65   save_item(NAME(m_dmaon));
66   save_item(NAME(m_dpp));
67   save_item(NAME(m_wsync));
68   save_item(NAME(m_color_kill));
69   save_item(NAME(m_cwidth));
70   save_item(NAME(m_bcntl));
71   save_item(NAME(m_kangaroo));
72   save_item(NAME(m_rm));
73   save_item(NAME(m_nmi));
74   save_item(NAME(m_charbase));
75}
76
77void atari_maria_device::device_reset()
78{
79   for (int i = 0; i < 32; i++)
80      m_maria_palette[i] = 0;
81
82   for (int i = 0; i < 2; i++)
83      for (int j = 0; j < 160; j++)
84         m_line_ram[i][j] = 0;
85
86   m_active_buffer = 0;
87
88   m_write_mode = 0;
89   m_dmaon = 0;
90   m_vblank = 0x80;
91   m_dll = 0;
92   m_wsync = 0;
93
94   m_color_kill = 0;
95   m_cwidth = 0;
96   m_bcntl = 0;
97   m_kangaroo = 0;
98   m_rm = 0;
99
100   m_dl = 0;
101   m_holey = 0;
102   m_offset = 0;
103   m_dpp = 0;
104   m_nmi = 0;
105   m_charbase = 0;
106}
107
108/***************************************************************************
109
110  Stop the video hardware emulation.
111
112***************************************************************************/
113
114int atari_maria_device::is_holey(unsigned int addr)
115{
116   if (((m_holey & 0x02) && ((addr & 0x9000) == 0x9000)) || ( (m_holey & 0x01) && ((addr & 0x8800) == 0x8800)))
117      return 1;
118   else
119      return 0;
120}
121
122int atari_maria_device::write_line_ram(int addr, UINT8 offset, int pal)
123{
124   address_space& space = m_cpu->space(AS_PROGRAM);
125   int c;
126
127   int data = READ_MEM(addr);
128   pal <<= 2;
129
130   if (m_write_mode)
131   {
132      c = (pal & 0x10) | (data & 0x0c) | (data >> 6); // P2 D3 D2 D7 D6
133      if (((c & 3) || m_kangaroo) && (offset < 160))
134         m_line_ram[m_active_buffer][offset] = c;
135      offset++;
136
137      c = (pal & 0x10) | ((data & 0x03) << 2) | ((data & 0x30) >> 4); // P2 D1 D0 D5 D4
138      if (((c & 3) || m_kangaroo) && (offset < 160))
139         m_line_ram[m_active_buffer][offset] = c;
140   }
141   else
142   {
143      for (int i = 0; i < 4; i++, offset++)
144      {
145         c = pal | ((data >> (6 - 2 * i)) & 0x03);
146         if (((c & 3) || m_kangaroo) && (offset < 160))
147            m_line_ram[m_active_buffer][offset] = c;
148      }
149   }
150   return m_write_mode ? 2 : 4;
151}
152
153
154void atari_maria_device::draw_scanline()
155{
156   address_space& space = m_cpu->space(AS_PROGRAM);
157   UINT16 graph_adr, data_addr;
158   int width, pal, ind;
159   UINT8 hpos;
160   UINT16 dl;
161   int d, c, pixel_cell, cells;
162   int maria_cycles;
163
164   if (m_offset == 0)
165   {
166      if (READ_MEM(m_dll + 3) & 0x80)
167         maria_cycles = 40; // DMA + maria interrupt overhead
168      else
169         maria_cycles = 19; // DMA
170      }
171      else
172      {
173         maria_cycles = 16; // DMA
174      }
175
176   cells = 0;
177
178   /* Process this DLL entry */
179   dl = m_dl;
180
181   /* DMA */
182   /* Step through DL's */
183   while ((READ_MEM(dl + 1) & 0x5f) != 0)
184   {
185      /* Extended header */
186      if (!(READ_MEM(dl + 1) & 0x1f))
187      {
188         graph_adr = (READ_MEM(dl + 2) << 8) | READ_MEM(dl);
189         width = ((READ_MEM(dl + 3) ^ 0xff) & 0x1f) + 1;
190         hpos = READ_MEM(dl + 4);
191         pal = READ_MEM(dl + 3) >> 5;
192         m_write_mode = (READ_MEM(dl + 1) & 0x80) >> 5;
193         ind = READ_MEM(dl + 1) & 0x20;
194         dl += 5;
195         maria_cycles += 10;
196      }
197      /* Normal header */
198      else
199      {
200         graph_adr = (READ_MEM(dl + 2) << 8) | READ_MEM(dl);
201         width = ((READ_MEM(dl + 1) ^ 0xff) & 0x1f) + 1;
202         hpos = READ_MEM(dl + 3);
203         pal = READ_MEM(dl + 1) >> 5;
204         ind = 0x00;
205         dl += 4;
206         maria_cycles += 8;
207      }
208
209      /*logerror("%x DL: ADR=%x  width=%x  hpos=%x  pal=%x  mode=%x  ind=%x\n", m_screen->vpos(), graph_adr, width, hpos, pal, m_write_mode, ind);*/
210
211      for (int x = 0; x < width; x++)
212      {
213         /* Do indirect mode */
214         if (ind)
215         {
216            c = READ_MEM(graph_adr + x) & 0xff;
217            data_addr = (m_charbase | c) + (m_offset << 8);
218            if (is_holey(data_addr))
219               continue;
220
221            maria_cycles += 3;
222            if (m_cwidth) // two data bytes per map byte
223            {
224               cells = write_line_ram(data_addr, hpos, pal);
225               hpos += cells;
226               cells = write_line_ram(data_addr+1, hpos, pal);
227               hpos += cells;
228               maria_cycles += 6;
229            }
230            else
231            {
232               cells = write_line_ram(data_addr, hpos, pal);
233               hpos += cells;
234               maria_cycles += 3;
235            }
236         }
237         else // direct mode
238         {
239            data_addr = graph_adr + x + (m_offset  << 8);
240            if (is_holey(data_addr))
241               continue;
242            cells = write_line_ram(data_addr, hpos, pal);
243            hpos += cells;
244            maria_cycles += 3;
245         }
246      }
247   }
248   // Spin the CPU for Maria DMA, if it's not already spinning for WSYNC.
249   // MARIA generates the 6502 clock by dividing its own clock by 4. It needs to HALT and unHALT
250   // the 6502 on ths same clock phase, so MARIA will wait until its clock divides evenly by 4.
251   // To spin until an even divisor, we just round-up any would-be truncations by adding 3.
252   if (!m_wsync)
253      m_cpu->spin_until_time(m_cpu->cycles_to_attotime((maria_cycles+3)/4));
254
255   // draw line buffer to screen
256   m_active_buffer = !m_active_buffer; // switch buffers
257   UINT16 *scanline;
258   scanline = &m_bitmap.pix16(m_screen->vpos());
259
260
261   for (int i = 0; i < 160; i++)
262   {
263      switch (m_rm)
264      {
265         case 0x00:  /* 160A, 160B */
266         case 0x01:  /* 160A, 160B */
267            pixel_cell =  m_line_ram[m_active_buffer][i];
268            scanline[2 * i] = m_maria_palette[pixel_cell];
269            scanline[2 * i + 1] = m_maria_palette[pixel_cell];
270            break;
271
272         case 0x02: /* 320B, 320D */
273            pixel_cell = m_line_ram[m_active_buffer][i];
274            d = (pixel_cell & 0x10) | (pixel_cell & 0x02) | ((pixel_cell >> 3) & 1); // b4 0 0 b1 b3
275            scanline[2 * i] = m_maria_palette[d];
276            d = (pixel_cell & 0x10) | ((pixel_cell << 1) & 0x02) | ((pixel_cell >> 2) & 1); // b4 0 0 b0 b2
277            scanline[2 * i + 1] = m_maria_palette[d];
278            break;
279
280         case 0x03:  /* 320A, 320C */
281            pixel_cell = m_line_ram[m_active_buffer][i];
282            d = (pixel_cell & 0x1c) | (pixel_cell & 0x02); // b4 b3 b2 b1 0
283            scanline[2 * i] = m_maria_palette[d];
284            d = (pixel_cell & 0x1c) | ((pixel_cell << 1) & 0x02); // b4 b3 b2 b0 0
285            scanline[2 * i + 1] = m_maria_palette[d];
286            break;
287      }
288   }
289
290   for (int i = 0; i < 160; i++) // buffer automaticaly cleared once displayed
291      m_line_ram[m_active_buffer][i] = 0;
292}
293
294
295void atari_maria_device::interrupt(int lines)
296{
297   if (m_wsync)
298   {
299      machine().scheduler().trigger(TRIGGER_HSYNC);
300      m_wsync = 0;
301   }
302
303   int frame_scanline = m_screen->vpos() % (lines + 1);
304   if (frame_scanline == 16)
305      m_vblank = 0x00;
306
307   if (frame_scanline == (lines - 5))
308      m_vblank = 0x80;
309}
310
311
312void atari_maria_device::startdma(int lines)
313{
314   address_space& space = m_cpu->space(AS_PROGRAM);
315   int maria_scanline = m_screen->vpos();
316   int frame_scanline = maria_scanline % (lines + 1);
317
318   if ((frame_scanline == 16) && m_dmaon)
319   {
320      /* end of vblank */
321      m_dll = m_dpp; // currently only handle changes to dll during vblank
322      m_dl = (READ_MEM(m_dll + 1) << 8) | READ_MEM(m_dll+2);
323      m_offset = READ_MEM(m_dll) & 0x0f;
324      m_holey = (READ_MEM(m_dll) & 0x60) >> 5;
325      m_nmi = READ_MEM(m_dll) & 0x80;
326      /*  logerror("DLL=%x\n",m_dll); */
327      draw_scanline();
328   }
329
330
331   if ((frame_scanline > 16) && (frame_scanline < (lines - 5)) && m_dmaon)
332   {
333      draw_scanline();
334      if (m_offset == 0)
335      {
336         m_dll += 3;
337         m_dl = (READ_MEM(m_dll + 1) << 8) | READ_MEM(m_dll + 2);
338         m_offset = READ_MEM(m_dll) & 0x0f;
339         m_holey = (READ_MEM(m_dll) & 0x60) >> 5;
340         if (READ_MEM(m_dll & 0x10))
341            logerror("dll bit 5 set!\n");
342         m_nmi = READ_MEM(m_dll) & 0x80;
343      }
344      else
345      {
346         m_offset--;
347      }
348   }
349
350   if (m_nmi)
351   {
352      m_cpu->set_input_line(INPUT_LINE_NMI, PULSE_LINE);
353      m_nmi = 0;
354   }
355}
356
357/***************************************************************************
358
359  Refresh the video screen
360
361***************************************************************************/
362
363/* This routine is called at the start of vblank to refresh the screen */
364UINT32 atari_maria_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
365{
366   copybitmap(bitmap, m_bitmap, 0, 0, 0, 0, cliprect);
367   return 0;
368}
369
370
371READ8_MEMBER(atari_maria_device::read)
372{
373   switch (offset)
374   {
375      case 0x08:
376         return m_vblank;
377
378      default:
379         logerror("undefined MARIA read %x\n",offset);
380         return 0x00; // don't know if this should be 0x00 or 0xff
381   }
382}
383
384WRITE8_MEMBER(atari_maria_device::write)
385{
386   if ((offset & 3) != 0)
387      m_maria_palette[offset] = data;
388
389   switch (offset)
390   {
391      case 0x00:
392         // all color ram addresses with 00 for their least significant bits point to the background color
393         for (int i = 0; i < 8; i++)
394            m_maria_palette[4 * i] = data;
395         break;
396      case 0x04:
397         m_cpu->spin_until_trigger(TRIGGER_HSYNC);
398         m_wsync = 1;
399         break;
400      case 0x0C: // DPPH
401         m_dpp = (m_dpp & 0x00ff) | (data << 8);
402         break;
403      case 0x10: // DPPL
404         m_dpp = (m_dpp & 0xff00) | data;
405         break;
406      case 0x14:
407         m_charbase = (data << 8);
408         break;
409      case 0x1C:
410         /*logerror("MARIA CTRL=%x\n",data);*/
411         m_color_kill = data & 0x80;
412         switch ((data >> 5) & 3)
413         {
414            case 0x00:
415            case 01:
416               logerror("dma test mode, do not use.\n");
417               break;
418
419            case 0x02:
420               m_dmaon = 1;
421               break;
422
423            case 0x03:
424               m_dmaon = 0;
425               break;
426         }
427         m_cwidth = data & 0x10;
428         m_bcntl = data & 0x08; // Currently unimplemented as we don't display the border
429         m_kangaroo = data & 0x04;
430         m_rm = data & 0x03;
431
432         /*logerror( "MARIA CTRL: CK:%d DMA:%d CW:%d BC:%d KM:%d RM:%d\n",
433                 m_color_kill ? 1 : 0,
434                 (data & 0x60) >> 5,
435                 m_cwidth ? 1 : 0,
436                 m_bcntl ? 1 : 0,
437                 m_kangaroo ? 1 : 0,
438                 m_rm );*/
439
440         break;
441   }
442}
Property changes on: trunk/src/mess/video/maria.c
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/mess/video/maria.h
r0r31778
1#ifndef __ATARI_MARIA__
2#define __ATARI_MARIA__
3
4#include "emu.h"
5
6// ======================> atari_maria_device
7
8class atari_maria_device :  public device_t
9{
10public:
11   // construction/destruction
12   atari_maria_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
13
14   static void set_cpu_tag(device_t &device, const char *tag) { downcast<atari_maria_device &>(device).m_cpu_tag = tag; }
15   
16   void interrupt(int lines);
17   void startdma(int lines);
18   
19   DECLARE_READ8_MEMBER(read);
20   DECLARE_WRITE8_MEMBER(write);
21
22   UINT32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
23   
24protected:
25   // device-level overrides
26   virtual void device_start();
27   virtual void device_reset();
28
29private:
30   
31   int m_maria_palette[32];
32   int m_line_ram[2][160];
33   int m_active_buffer;
34   int m_write_mode;
35   unsigned int m_dll;
36   unsigned int m_dl;
37   int m_holey;
38   int m_offset;
39   int m_vblank;
40   int m_dmaon;
41   int m_dpp;
42   int m_wsync;
43   int m_color_kill;
44   int m_cwidth;
45   int m_bcntl;
46   int m_kangaroo;
47   int m_rm;
48   int m_nmi;
49   unsigned int m_charbase;
50   bitmap_ind16 m_bitmap;
51
52   void draw_scanline();
53   int is_holey(unsigned int addr);
54   int write_line_ram(int addr, UINT8 offset, int pal);
55
56   const char *m_cpu_tag;
57   cpu_device *m_cpu;   // CPU whose space(AS_PROGRAM) serves as DMA source
58   screen_device *m_screen;
59};
60
61
62// device type definition
63extern const device_type ATARI_MARIA;
64
65
66#define MCFG_MARIA_DMACPU(_tag) \
67   atari_maria_device::set_cpu_tag(*device, _tag);
68
69
70#endif
Property changes on: trunk/src/mess/video/maria.h
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/mess/drivers/a7800.c
r31777r31778
9797#include "emu.h"
9898#include "cpu/m6502/m6502.h"
9999#include "sound/tiaintf.h"
100#include "sound/tiasound.h"
101#include "machine/6532riot.h"
102#include "video/maria.h"
100103#include "bus/a7800/a78_carts.h"
101#include "machine/6532riot.h"
102#include "includes/a7800.h"
103104
104105
105106#define A7800_NTSC_Y1   XTAL_14_31818MHz
106107#define CLK_PAL 1773447
107108
108109
110class a7800_state : public driver_device
111{
112public:
113   a7800_state(const machine_config &mconfig, device_type type, const char *tag)
114   : driver_device(mconfig, type, tag),
115   m_maincpu(*this, "maincpu"),
116   m_tia(*this, "tia"),
117   m_maria(*this, "maria"),
118   m_io_joysticks(*this, "joysticks"),
119   m_io_buttons(*this, "buttons"),
120   m_io_vblank(*this, "vblank"),
121   m_io_console_buttons(*this, "console_buttons"),
122   m_cartslot(*this, "cartslot"),
123   m_screen(*this, "screen") { }
124   
125   int m_lines;
126   int m_ispal;
127   
128   int m_ctrl_lock;
129   int m_ctrl_reg;
130   int m_maria_flag;
131   int m_p1_one_button;
132   int m_p2_one_button;
133   int m_bios_enabled;
134   
135   UINT8 *m_bios;
136   
137   DECLARE_READ8_MEMBER(bios_or_cart_r);
138   DECLARE_WRITE8_MEMBER(ram0_w);
139   DECLARE_READ8_MEMBER(tia_r);
140   DECLARE_WRITE8_MEMBER(tia_w);
141   DECLARE_READ8_MEMBER(maria_r);
142   DECLARE_WRITE8_MEMBER(maria_w);
143   DECLARE_DRIVER_INIT(a7800_pal);
144   DECLARE_DRIVER_INIT(a7800_ntsc);
145   virtual void machine_start();
146   virtual void machine_reset();
147   DECLARE_PALETTE_INIT(a7800);
148   DECLARE_PALETTE_INIT(a7800p);
149   TIMER_DEVICE_CALLBACK_MEMBER(interrupt);
150   TIMER_CALLBACK_MEMBER(maria_startdma);
151   DECLARE_READ8_MEMBER(riot_joystick_r);
152   DECLARE_READ8_MEMBER(riot_console_button_r);
153   DECLARE_WRITE8_MEMBER(riot_button_pullup_w);
154   
155protected:
156   required_device<cpu_device> m_maincpu;
157   required_device<tia_device> m_tia;
158   required_device<atari_maria_device> m_maria;
159   required_ioport m_io_joysticks;
160   required_ioport m_io_buttons;
161   required_ioport m_io_vblank;
162   required_ioport m_io_console_buttons;
163   required_device<a78_cart_slot_device> m_cartslot;
164   required_device<screen_device> m_screen;
165};
166
167
109168/***************************************************************************
110169 MEMORY HANDLERS
111170 ***************************************************************************/
r31777r31778
191250}
192251
193252
253// TIMERS
254
255TIMER_DEVICE_CALLBACK_MEMBER(a7800_state::interrupt)
256{
257   // DMA Begins 7 cycles after hblank
258   machine().scheduler().timer_set(m_maincpu->cycles_to_attotime(7), timer_expired_delegate(FUNC(a7800_state::maria_startdma),this));
259   m_maria->interrupt(m_lines);
260}
261
262TIMER_CALLBACK_MEMBER(a7800_state::maria_startdma)
263{
264   m_maria->startdma(m_lines);
265}
266
267
268
194269// ROM
195270READ8_MEMBER(a7800_state::bios_or_cart_r)
196271{
r31777r31778
206281
207282static ADDRESS_MAP_START( a7800_mem, AS_PROGRAM, 8, a7800_state )
208283   AM_RANGE(0x0000, 0x001f) AM_MIRROR(0x300) AM_READWRITE(tia_r, tia_w)
209   AM_RANGE(0x0020, 0x003f) AM_MIRROR(0x300) AM_READWRITE(maria_r, maria_w)
284   AM_RANGE(0x0020, 0x003f) AM_MIRROR(0x300) AM_DEVREADWRITE("maria", atari_maria_device, read, write)
210285   AM_RANGE(0x0040, 0x00ff) AM_RAMBANK("ram0")     // RAM (6116 block 0)
211286   AM_RANGE(0x0140, 0x01ff) AM_RAMBANK("ram1")     // RAM (6116 block 1)
212287   AM_RANGE(0x0280, 0x02ff) AM_DEVREADWRITE("riot", riot6532_device, read, write)
r31777r31778
12721347   /* basic machine hardware */
12731348   MCFG_CPU_ADD("maincpu", M6502, A7800_NTSC_Y1/8) /* 1.79 MHz (switches to 1.19 MHz on TIA or RIOT access) */
12741349   MCFG_CPU_PROGRAM_MAP(a7800_mem)
1275   MCFG_TIMER_DRIVER_ADD_SCANLINE("scantimer", a7800_state, a7800_interrupt, "screen", 0, 1)
1350   MCFG_TIMER_DRIVER_ADD_SCANLINE("scantimer", a7800_state, interrupt, "screen", 0, 1)
12761351
12771352   /* video hardware */
12781353   MCFG_SCREEN_ADD("screen", RASTER)
12791354   MCFG_SCREEN_RAW_PARAMS( 7159090, 454, 0, 320, 263, 27, 27 + 192 + 32 )
1280   MCFG_SCREEN_UPDATE_DRIVER(a7800_state, screen_update_a7800)
1355   MCFG_SCREEN_UPDATE_DEVICE("maria", atari_maria_device, screen_update)
12811356   MCFG_SCREEN_PALETTE("palette")
12821357
12831358   MCFG_PALETTE_ADD("palette", ARRAY_LENGTH(a7800_palette) / 3)
12841359   MCFG_PALETTE_INIT_OWNER(a7800_state, a7800)
12851360
1361   MCFG_DEVICE_ADD("maria", ATARI_MARIA, 0)
1362   MCFG_MARIA_DMACPU("maincpu")
1363
12861364   /* sound hardware */
12871365   MCFG_SPEAKER_STANDARD_MONO("mono")
12881366   MCFG_SOUND_TIA_ADD("tia", 31400)
trunk/src/mess/mess.mak
r31777r31778
10251025   $(MESS_MACHINE)/atarifdc.o  \
10261026   $(MESS_DRIVERS)/atari400.o  \
10271027   $(MESS_DRIVERS)/a7800.o     \
1028   $(MESS_VIDEO)/a7800.o       \
1028   $(MESS_VIDEO)/maria.o       \
10291029   $(MESS_DRIVERS)/a2600.o     \
10301030   $(MESS_DRIVERS)/atarist.o   \
10311031   $(MESS_VIDEO)/atarist.o     \

Previous 199869 Revisions Next


© 1997-2024 The MAME Team