Previous 199869 Revisions Next

r22918 Sunday 19th May, 2013 at 11:37:30 UTC by Fabio Priuli
(MESS) lynx.c: modernized sound emulation, slightly simplified blitter
functions and added save state to the driver. [Fabio Priuli]

out of whatsnew: as with gb and nes, I plan to add the support save flag before 0.149 after some more testing

and, for the record, this driver would really need a volunteer willing to make devices out of the
code for mikey and suzy chips, which is currently spread in multiple source files...
[src/mess/audio]lynx.c
[src/mess/drivers]lynx.c
[src/mess/includes]lynx.h
[src/mess/machine]lynx.c

trunk/src/mess/drivers/lynx.c
r22917r22918
88
99#include "emu.h"
1010#include "cpu/m6502/m65sc02.h"
11#include "audio/lynx.h"
1112#include "includes/lynx.h"
1213
1314#include "imagedev/snapquik.h"
r22917r22918
6364   return 0;
6465}
6566
67// callback for Mikey call of shift(3) which shall act on the lynx_timer_count_down
68void lynx_state::sound_cb()
69{
70   lynx_timer_count_down(1);
71}
72
73
6674static MACHINE_CONFIG_START( lynx, lynx_state )
6775   /* basic machine hardware */
6876   MCFG_CPU_ADD("maincpu", M65SC02, 4000000)        /* vti core, integrated in vlsi, stz, but not bbr bbs */
r22917r22918
8391
8492   /* sound hardware */
8593   MCFG_SPEAKER_STANDARD_MONO("mono")
86   MCFG_SOUND_ADD("custom", LYNX, 0)
94   MCFG_SOUND_ADD("custom", LYNX_SND, 0)
95   MCFG_LYNX_SND_SET_TIMER(lynx_state, sound_cb)
8796   MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
8897
8998   /* devices */
r22917r22918
99108   MCFG_DEVICE_REMOVE("mono")
100109   MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
101110   MCFG_DEVICE_REMOVE("lynx")
102   MCFG_SOUND_ADD("custom", LYNX2, 0)
111   MCFG_SOUND_ADD("custom", LYNX2_SND, 0)
112   MCFG_LYNX_SND_SET_TIMER(lynx_state, sound_cb)
103113   MCFG_SOUND_ROUTE(0, "lspeaker", 0.50)
104114   MCFG_SOUND_ROUTE(1, "rspeaker", 0.50)
105115MACHINE_CONFIG_END
trunk/src/mess/audio/lynx.c
r22917r22918
33******************************************************************************/
44
55#include "emu.h"
6#include "includes/lynx.h"
6#include "audio/lynx.h"
77
88
99/* accordingly to atari's reference manual
r22917r22918
8181
8282#define LYNX_AUDIO_CHANNELS 4
8383
84struct LYNX_AUDIO {
85   struct {
86      INT8 volume;
87      UINT8 feedback;
88      INT8 output;
89      UINT8 shifter;
90      UINT8 bakup;
91      UINT8 control1;
92      UINT8 counter;
93      UINT8 control2;
94   } reg;
95   UINT8 attenuation;
96   UINT16 mask; // 12-bit
97   UINT16 shifter; // 12-bit
98   float ticks;
99   int count;
100};
10184
102struct lynx_sound_state
85// device type definition
86const device_type LYNX_SND = &device_creator<lynx_sound_device>;
87const device_type LYNX2_SND = &device_creator<lynx2_sound_device>;
88
89//**************************************************************************
90//  LIVE DEVICE
91//**************************************************************************
92
93//-------------------------------------------------
94//  lynx_sound_device - constructor
95//-------------------------------------------------
96
97lynx_sound_device::lynx_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
98               : device_t(mconfig, LYNX_SND, "Mikey", tag, owner, clock, "lynx_sound", __FILE__),
99                  device_sound_interface(mconfig, *this)
100{   
101   m_timer_delegate = lynx_sound_timer_delegate();
102}
103
104lynx_sound_device::lynx_sound_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source)
105               : device_t(mconfig, type, name, tag, owner, clock, shortname, source),
106                  device_sound_interface(mconfig, *this)
103107{
104   sound_stream *mixer_channel;
105   float usec_per_sample;
106   int *shift_mask;
107   int *shift_xor;
108   UINT8 attenuation_enable;
109   UINT8 master_enable;
110   LYNX_AUDIO audio[4];
111};
108}
112109
113INLINE lynx_sound_state *get_safe_token(device_t *device)
110
111lynx2_sound_device::lynx2_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
112               : lynx_sound_device(mconfig, LYNX2_SND, "Mikey (Lynx II)", tag, owner, clock, "lynx2_sound", __FILE__)
114113{
115   assert(device != NULL);
116   assert(device->type() == LYNX || device->type() == LYNX2);
117   return (lynx_sound_state *)downcast<lynx_sound_device *>(device)->token();
118114}
119115
120static void lynx_audio_reset_channel(LYNX_AUDIO *This)
116//-------------------------------------------------
117//  device_config_complete - perform any
118//  operations now that the configuration is
119//  complete
120//-------------------------------------------------
121
122void lynx_sound_device::set_timer_delegate(device_t &device, lynx_sound_timer_delegate cb)
121123{
122   This->reg.volume = 0;
123   This->reg.feedback = 0;
124   This->reg.output = 0;
125   This->reg.shifter = 0;
126   This->reg.bakup = 0;
127   This->reg.control1 = 0;
128   This->reg.counter = 0;
129   This->reg.control2 = 0;
124   lynx_sound_device &dev = downcast<lynx_sound_device &>(device);
125   dev.m_timer_delegate = cb;
126}
130127
131   This->attenuation = 0;
132   This->mask = 0;
133   This->shifter = 0;
134   This->ticks = 0;
135   This->count = 0;
128void lynx_sound_device::device_config_complete()
129{
136130}
137131
138void lynx_audio_count_down(device_t *device, int nr)
132//-------------------------------------------------
133//  device_start - device-specific startup
134//-------------------------------------------------
135
136void lynx_sound_device::register_save()
139137{
140   lynx_sound_state *state = get_safe_token(device);
141   LYNX_AUDIO *This=state->audio+nr;
142   if (This->reg.control1&8 && (This->reg.control1&7)!=7) return;
143   if (nr==0) state->mixer_channel->update();
144   //if ((This->reg.control1&0x0f)==0x0f) //count down if linking enabled and count enabled
145      This->count--;
138   save_item(NAME(m_attenuation_enable));
139   save_item(NAME(m_master_enable));
140   for (int chan = 0; chan < LYNX_AUDIO_CHANNELS; chan++)
141   {
142      state_save_register_item(machine(), "Lynx sound", NULL, chan, m_audio[chan].reg.volume);
143      state_save_register_item(machine(), "Lynx sound", NULL, chan, m_audio[chan].reg.feedback);
144      state_save_register_item(machine(), "Lynx sound", NULL, chan, m_audio[chan].reg.output);
145      state_save_register_item(machine(), "Lynx sound", NULL, chan, m_audio[chan].reg.shifter);
146      state_save_register_item(machine(), "Lynx sound", NULL, chan, m_audio[chan].reg.bakup);
147      state_save_register_item(machine(), "Lynx sound", NULL, chan, m_audio[chan].reg.control1);
148      state_save_register_item(machine(), "Lynx sound", NULL, chan, m_audio[chan].reg.counter);
149      state_save_register_item(machine(), "Lynx sound", NULL, chan, m_audio[chan].reg.control2);
150      state_save_register_item(machine(), "Lynx sound", NULL, chan, m_audio[chan].attenuation);
151      state_save_register_item(machine(), "Lynx sound", NULL, chan, m_audio[chan].mask);
152      state_save_register_item(machine(), "Lynx sound", NULL, chan, m_audio[chan].shifter);
153      state_save_register_item(machine(), "Lynx sound", NULL, chan, m_audio[chan].ticks);
154      state_save_register_item(machine(), "Lynx sound", NULL, chan, m_audio[chan].count);
155/*      save_item(NAME(m_audio[chan].reg.volume));
156      save_item(NAME(m_audio[chan].reg.feedback));
157      save_item(NAME(m_audio[chan].reg.output));
158      save_item(NAME(m_audio[chan].reg.shifter));
159      save_item(NAME(m_audio[chan].reg.bakup));
160      save_item(NAME(m_audio[chan].reg.control1));
161      save_item(NAME(m_audio[chan].reg.counter));
162      save_item(NAME(m_audio[chan].reg.control2));
163      save_item(NAME(m_audio[chan].attenuation));
164      save_item(NAME(m_audio[chan].mask));
165      save_item(NAME(m_audio[chan].shifter));
166      save_item(NAME(m_audio[chan].ticks));
167      save_item(NAME(m_audio[chan].count));*/
168   }
146169}
147170
148static void lynx_audio_shift(device_t *device, LYNX_AUDIO *channel)
171void lynx_sound_device::init()
172{   
173   m_shift_mask = auto_alloc_array_clear(machine(), int, 512);
174   m_shift_xor = auto_alloc_array_clear(machine(), int, 4096);
175   
176   for (int i = 0; i < 512; i++)
177   {
178      m_shift_mask[i] = 0;
179      if (i & 1) m_shift_mask[i] |= 1;
180      if (i & 2) m_shift_mask[i] |= 2;
181      if (i & 4) m_shift_mask[i] |= 4;
182      if (i & 8) m_shift_mask[i] |= 8;
183      if (i & 0x10) m_shift_mask[i] |= 0x10;
184      if (i & 0x20) m_shift_mask[i] |= 0x20;
185      if (i & 0x40) m_shift_mask[i] |= 0x400;
186      if (i & 0x80) m_shift_mask[i] |= 0x800;
187      if (i & 0x100) m_shift_mask[i] |= 0x80;
188   }
189   
190   for (int i = 0; i < 4096; i++)
191   {
192      m_shift_xor[i] = 1;
193      for (int j = 4096/2; j > 0; j >>= 1)
194      {
195         if (i & j)
196            m_shift_xor[i] ^= 1;
197      }
198   }   
199}
200
201void lynx_sound_device::device_start()
149202{
150   lynx_sound_state *state = get_safe_token(device);
203   m_mixer_channel = machine().sound().stream_alloc(*this, 0, 1, machine().sample_rate(), this);
204   m_usec_per_sample = 1000000 / machine().sample_rate();
205   m_timer_delegate.bind_relative_to(*owner());
206   init();
207   register_save();
208}
209
210
211void lynx2_sound_device::device_start()
212{
213   m_mixer_channel = machine().sound().stream_alloc(*this, 0, 2, machine().sample_rate(), this);
214   m_usec_per_sample = 1000000 / machine().sample_rate();
215   m_timer_delegate.bind_relative_to(*owner());
216   init();
217   register_save();
218}
219
220//-------------------------------------------------
221//  device_reset - device-specific reset
222//-------------------------------------------------
223
224void lynx_sound_device::device_reset()
225{
226   for (int i = 0; i < LYNX_AUDIO_CHANNELS; i++)
227   {
228      reset_channel(&m_audio[i]);
229   }
230}
231
232
233void lynx_sound_device::reset_channel(LYNX_AUDIO *channel)
234{
235   channel->reg.volume = 0;
236   channel->reg.feedback = 0;
237   channel->reg.output = 0;
238   channel->reg.shifter = 0;
239   channel->reg.bakup = 0;
240   channel->reg.control1 = 0;
241   channel->reg.counter = 0;
242   channel->reg.control2 = 0;
243
244   channel->attenuation = 0;
245   channel->mask = 0;
246   channel->shifter = 0;
247   channel->ticks = 0;
248   channel->count = 0;
249}
250
251void lynx_sound_device::count_down(int nr)
252{
253   LYNX_AUDIO *channel = &m_audio[nr];
254   if (channel->reg.control1 & 8 && (channel->reg.control1 & 7) != 7)
255      return;
256   if (nr == 0)
257      m_mixer_channel->update();
258   //if ((channel->reg.control1 & 0x0f) == 0x0f) //count down if linking enabled and count enabled
259      channel->count--;
260}
261
262void lynx_sound_device::shift(int chan_nr)
263{
151264   INT16 out_temp;
152   UINT8 channel_number = (UINT8)(channel - state->audio);
265   LYNX_AUDIO *channel;
266   
267   assert(chan_nr < 4);
153268
154   //channel->shifter = ((channel->shifter<<1)&0xffe) | (state->shift_xor[ channel->shifter & channel->mask ]&1);
269   channel = &m_audio[chan_nr];   
270   //channel->shifter = ((channel->shifter<<1)&0xffe) | (m_shift_xor[ channel->shifter & channel->mask ]&1);
155271
156      // alternative method (functionally the same as above)
157   UINT8 xor_out=0;
158   for(int bit=0;bit<12;bit++)
272   // alternative method (functionally the same as above)
273   UINT8 xor_out = 0;
274   for (int bit = 0; bit < 12; bit++)
159275   {
160      if((channel->mask>>bit)&1) xor_out ^= (channel->shifter>>bit)&1;
276      if ((channel->mask >> bit) & 1)
277         xor_out ^= (channel->shifter >> bit) & 1;
161278   }
162   channel->shifter = ((channel->shifter<<1)&0xffe) | (xor_out ^ 1); // output of xor is inverted
279   channel->shifter = ((channel->shifter << 1) & 0xffe) | (xor_out ^ 1); // output of xor is inverted
163280
164281
165   if (channel->reg.control1&0x20) // integrate mode enabled
282   if (channel->reg.control1 & 0x20) // integrate mode enabled
166283   {
167      if (channel->shifter&1)
168      {
284      if (channel->shifter & 1)
169285         out_temp = channel->reg.output + channel->reg.volume;
170      }
171286      else
172      {
173287         out_temp = channel->reg.output - channel->reg.volume;
174      }
175288
176289      // clipping
177      if(out_temp > 127) out_temp = 127;
178      if(out_temp < -128) out_temp = -128;
290      if (out_temp > 127) out_temp = 127;
291      if (out_temp < -128) out_temp = -128;
179292      channel->reg.output = (INT16)out_temp;
180293   }
181   lynx_state *drvstate = device->machine().driver_data<lynx_state>();
182   switch (channel_number)
294
295   switch (chan_nr)
183296   {
184      case 0: lynx_audio_count_down(device, 1); break;
185      case 1: lynx_audio_count_down(device, 2); break;
186      case 2: lynx_audio_count_down(device, 3); break;
187      case 3: drvstate->lynx_timer_count_down(1); break;
188      default: logerror("Invalid channel number %d\n", channel_number); break;
297      case 0: count_down(1); break;
298      case 1: count_down(2); break;
299      case 2: count_down(3); break;
300      case 3:
301         if (!m_timer_delegate.isnull())
302            m_timer_delegate();
303         break;
189304   }
190305}
191306
192static void lynx_audio_execute(device_t *device, LYNX_AUDIO *channel)
307void lynx_sound_device::execute(int chan_nr)
193308{
194   lynx_sound_state *state = get_safe_token(device);
195   if (channel->reg.control1&8) // count enable
309   LYNX_AUDIO *channel;
310   
311   assert(chan_nr < 4);
312   
313   channel = &m_audio[chan_nr];   
314
315   if (channel->reg.control1 & 8) // count enable
196316   {
197      channel->ticks+=state->usec_per_sample;
198      if ((channel->reg.control1&7)==7) // link
317      channel->ticks += m_usec_per_sample;
318      if ((channel->reg.control1 & 7) == 7) // link
199319      {
200         if (channel->count<0) // counter finished
320         if (channel->count < 0) // counter finished
201321         {
202322            //channel->count+=channel->reg.counter; // reload (wrong?)
203            if (channel->reg.control1&0x10)
323            if (channel->reg.control1 & 0x10)
204324               channel->count = channel->reg.bakup;
205            lynx_audio_shift(device, channel);
325            shift(chan_nr);
206326         }
207327      }
208328      else
209329      {
210         int t=1<<(channel->reg.control1&7); // microseconds per count
330         int t = 1 << (channel->reg.control1 & 7); // microseconds per count
211331         for (;;)
212332         {
213            for (;(channel->ticks >= t) && (channel->count >= 0); channel->ticks-=t) // at least one sampled worth of time left, timer not expired
214            {
333            for (; (channel->ticks >= t) && (channel->count >= 0); channel->ticks -= t) // at least one sampled worth of time left, timer not expired
215334               channel->count--;
216            }
217            if (channel->ticks<t) break;
218            if (channel->count<0)
335
336            if (channel->ticks < t)
337               break;
338
339            if (channel->count < 0)
219340            {
220               lynx_audio_shift(device, channel);
221               if (channel->reg.control1&0x10)
341               shift(chan_nr);
342               if (channel->reg.control1 & 0x10)
222343                  channel->count = channel->reg.bakup;
223344               else
224345                  break;
225346            }
226347         }
227348      }
228      if (!(channel->reg.control1&0x20)) // normal mode
349
350      if (!(channel->reg.control1 & 0x20)) // normal mode
229351      {
230352         channel->reg.output = (channel->shifter & 1) ? channel->reg.volume : -channel->reg.volume;
231353      }
232354   }
233355   else
234356   {
235      channel->ticks=0;
236      channel->count=0;
357      channel->ticks = 0;
358      channel->count = 0;
237359   }
238360}
239361
240
241UINT8 lynx_audio_read(device_t *device, int offset)
362READ8_MEMBER(lynx_sound_device::read)
242363{
243   lynx_sound_state *state = get_safe_token(device);
244   UINT8 value=0;
245   LYNX_AUDIO *channel=&state->audio[(offset>>3)&3];
246   state->mixer_channel->update();
364   UINT8 value = 0;
365   LYNX_AUDIO *channel = &m_audio[(offset >> 3) & 3];
366
367   m_mixer_channel->update();
368
247369   if (offset < 0x40)
248370   {
249      switch (offset&7) {
371      switch (offset & 7)
372      {
250373         case 0:
251374            value = channel->reg.volume;
252375            break;
r22917r22918
258381            break;
259382         case 3:
260383            // current shifter state (lower 8 bits)
261            value = channel->shifter&0xff;
384            value = channel->shifter & 0xff;
262385            break;
263386         case 4:
264387            value = channel->reg.bakup;
r22917r22918
275398            break;
276399         case 7:
277400            // current shifter state (upper 4 bits), status bits
278            value = (channel->shifter>>4)&0xf0;
279            value |= channel->reg.control2&0x0f;
401            value = (channel->shifter >> 4) & 0xf0;
402            value |= channel->reg.control2 & 0x0f;
280403            break;
281404      }
282405   }
r22917r22918
285408      switch (offset) // Lynx II stereo control registers
286409      {
287410         case 0x40: case 0x41: case 0x42: case 0x43:
288            value = state->audio[offset&3].attenuation;
411            value = m_audio[offset & 3].attenuation;
289412            break;
290413         case 0x44:
291            value = state->attenuation_enable;
414            value = m_attenuation_enable;
292415            break;
293416         case 0x50:
294            value = state->master_enable;
417            value = m_master_enable;
295418            break;
296419      }
297420
r22917r22918
299422   return value;
300423}
301424
302void lynx_audio_write(device_t *device, int offset, UINT8 data)
425WRITE8_MEMBER(lynx_sound_device::write)
303426{
304   lynx_sound_state *state = get_safe_token(device);
305427   //logerror("audio write %.2x %.2x\n", offset, data);
306   LYNX_AUDIO *channel=&state->audio[(offset>>3)&3];
307   state->mixer_channel->update();
428   LYNX_AUDIO *channel = &m_audio[(offset >> 3) & 3];
429
430   m_mixer_channel->update();
431
308432   if (offset < 0x40)
309433   {
310      switch (offset & 0x07) {
434      switch (offset & 0x07)
435      {
311436         // Volume control (signed)
312437         case 0:
313438            channel->reg.volume = data;
r22917r22918
356481      switch (offset) // Stereo Registers
357482      {
358483         case 0x40: case 0x41: case 0x42: case 0x43:
359            state->audio[offset&3].attenuation=data;
484            m_audio[offset&3].attenuation = data;
360485            break;
361486         case 0x44:
362            state->attenuation_enable=data;
487            m_attenuation_enable = data;
363488            break;
364489         case 0x50:
365            state->master_enable=data;
490            m_master_enable = data;
366491            break;
367492      }
368493   }
369494}
370495
371/************************************/
372/* Sound handler update             */
373/************************************/
374static STREAM_UPDATE( lynx_update )
496
497//-------------------------------------------------
498//  sound_stream_update - handle a stream update
499//-------------------------------------------------
500
501void lynx_sound_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
375502{
376   lynx_sound_state *state = get_safe_token(device);
377   int i, channel;
378   //LYNX_AUDIO *channel;
379503   int v;
380504   stream_sample_t *buffer = outputs[0];
381
382   for (i = 0; i < samples; i++, buffer++)
505   
506   for (int i = 0; i < samples; i++, buffer++)
383507   {
384508      *buffer = 0;
385      for (channel=0; channel<LYNX_AUDIO_CHANNELS; channel++)
509      for (int channel = 0; channel < LYNX_AUDIO_CHANNELS; channel++)
386510      {
387         lynx_audio_execute(device, &state->audio[channel]);
388         v=state->audio[channel].reg.output;
389         *buffer+=v*15; // where does the *15 come from?
511         execute(channel);
512         v = m_audio[channel].reg.output;
513         *buffer += v * 15; // where does the *15 come from?
390514      }
391515   }
392516}
393517
394static STREAM_UPDATE( lynx2_update )
518//-------------------------------------------------
519//  sound_stream_update - handle a stream update
520//-------------------------------------------------
521
522void lynx2_sound_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
395523{
396   lynx_sound_state *state = get_safe_token(device);
397524   stream_sample_t *left=outputs[0], *right=outputs[1];
398   int i, j;
399   LYNX_AUDIO *channel;
400525   int v;
401
402   for (i = 0; i < samples; i++, left++, right++)
526   
527   for (int i = 0; i < samples; i++, left++, right++)
403528   {
404529      *left = 0;
405530      *right= 0;
406      for (channel=state->audio, j=0; j<ARRAY_LENGTH(state->audio); j++, channel++)
531      for (int channel = 0; channel < LYNX_AUDIO_CHANNELS; channel++)
407532      {
408         lynx_audio_execute(device, channel);
409         v=channel->reg.output;
410         if (!(state->master_enable&(0x10<<j)))
533         execute(channel);
534         v = m_audio[channel].reg.output;
535         if (!(m_master_enable & (0x10 << channel)))
411536         {
412            if (state->attenuation_enable&(0x10<<j)) {
413               *left+=v*(channel->attenuation>>4);
414            } else {
415               *left+=v*15;
416            }
537            if (m_attenuation_enable & (0x10 << channel))
538               *left += v * (m_audio[channel].attenuation >> 4);
539            else
540               *left += v * 15;
417541         }
418         if (!(state->master_enable&(1<<j)))
542         if (!(m_master_enable & (1 << channel)))
419543         {
420            if (state->attenuation_enable&(1<<j)) {
421               *right+=v*(channel->attenuation&0xf);
422            } else {
423               *right+=v*15;
424            }
544            if (m_attenuation_enable & (1 << channel))
545               *right += v * (m_audio[channel].attenuation & 0xf);
546            else
547               *right += v * 15;
425548         }
426549      }
427550   }
428551}
429
430static void lynx_audio_init(device_t *device)
431{
432   lynx_sound_state *state = get_safe_token(device);
433   int i;
434   state->shift_mask = auto_alloc_array(device->machine(), int, 512);
435   assert(state->shift_mask);
436
437   state->shift_xor = auto_alloc_array(device->machine(), int, 4096);
438   assert(state->shift_xor);
439
440   for (i=0; i<512; i++)
441   {
442      state->shift_mask[i]=0;
443      if (i&1) state->shift_mask[i]|=1;
444      if (i&2) state->shift_mask[i]|=2;
445      if (i&4) state->shift_mask[i]|=4;
446      if (i&8) state->shift_mask[i]|=8;
447      if (i&0x10) state->shift_mask[i]|=0x10;
448      if (i&0x20) state->shift_mask[i]|=0x20;
449      if (i&0x40) state->shift_mask[i]|=0x400;
450      if (i&0x80) state->shift_mask[i]|=0x800;
451      if (i&0x100) state->shift_mask[i]|=0x80;
452   }
453   for (i=0; i<4096; i++)
454   {
455      int j;
456      state->shift_xor[i]=1;
457      for (j=4096/2; j>0; j>>=1)
458      {
459         if (i & j)
460            state->shift_xor[i] ^= 1;
461      }
462   }
463}
464
465static DEVICE_RESET( lynx_sound )
466{
467   lynx_sound_state *state = get_safe_token(device);
468   int i;
469   for (i=0; i<ARRAY_LENGTH(state->audio); i++)
470   {
471      lynx_audio_reset_channel(state->audio+i);
472   }
473}
474
475
476
477/************************************/
478/* Sound handler start              */
479/************************************/
480
481static DEVICE_START(lynx_sound)
482{
483   lynx_sound_state *state = get_safe_token(device);
484   state->mixer_channel = device->machine().sound().stream_alloc(*device, 0, 1, device->machine().sample_rate(), 0, lynx_update);
485
486   state->usec_per_sample = 1000000 / device->machine().sample_rate();
487
488   lynx_audio_init(device);
489}
490
491
492static DEVICE_START(lynx2_sound)
493{
494   lynx_sound_state *state = get_safe_token(device);
495   state->mixer_channel = device->machine().sound().stream_alloc(*device, 0, 2, device->machine().sample_rate(), 0, lynx2_update);
496
497   state->usec_per_sample = 1000000 / device->machine().sample_rate();
498
499   lynx_audio_init(device);
500}
501
502
503const device_type LYNX = &device_creator<lynx_sound_device>;
504
505lynx_sound_device::lynx_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
506   : device_t(mconfig, LYNX, "Mikey", tag, owner, clock),
507      device_sound_interface(mconfig, *this)
508{
509   m_token = global_alloc_clear(lynx_sound_state);
510}
511
512lynx_sound_device::lynx_sound_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source)
513   : device_t(mconfig, type, name, tag, owner, clock, shortname, source),
514      device_sound_interface(mconfig, *this)
515{
516   m_token = global_alloc_clear(lynx_sound_state);
517}
518
519//-------------------------------------------------
520//  device_config_complete - perform any
521//  operations now that the configuration is
522//  complete
523//-------------------------------------------------
524
525void lynx_sound_device::device_config_complete()
526{
527}
528
529//-------------------------------------------------
530//  device_start - device-specific startup
531//-------------------------------------------------
532
533void lynx_sound_device::device_start()
534{
535   DEVICE_START_NAME( lynx_sound )(this);
536}
537
538//-------------------------------------------------
539//  device_reset - device-specific reset
540//-------------------------------------------------
541
542void lynx_sound_device::device_reset()
543{
544   DEVICE_RESET_NAME( lynx_sound )(this);
545}
546
547//-------------------------------------------------
548//  sound_stream_update - handle a stream update
549//-------------------------------------------------
550
551void lynx_sound_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
552{
553   // should never get here
554   fatalerror("sound_stream_update called; not applicable to legacy sound devices\n");
555}
556
557
558const device_type LYNX2 = &device_creator<lynx2_sound_device>;
559
560lynx2_sound_device::lynx2_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
561   : lynx_sound_device(mconfig, LYNX2, "Mikey (Lynx II)", tag, owner, clock, "lynx2_sound", __FILE__)
562{
563}
564
565void lynx2_sound_device::device_start()
566{
567   DEVICE_START_NAME( lynx2_sound )(this);
568}
569
570//-------------------------------------------------
571//  sound_stream_update - handle a stream update
572//-------------------------------------------------
573
574void lynx2_sound_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
575{
576   // should never get here
577   fatalerror("sound_stream_update called; not applicable to legacy sound devices\n");
578}
trunk/src/mess/machine/lynx.c
r22917r22918
2020
2121****************************************/
2222
23/*
242008-10 FP:
25Current implementation: lynx_blitter reads what will be drawn and sets which line_functions to use.
26It then calls lynx_blit_lines which sets the various flip bits (horizontal and vertical) and calls
27the chosen line_function. These functions (available in various versions, depending on how many
28color bits are to be used) finally call lynx_plot_pixel which draws the sprite.
29
30Notice however that, based on the problems in Electrocop, Jimmy Connors Tennis and Switchblade II
31(among the others), it clearly seems that something is being lost in some of the passages. From
32my partial understanding while comparing the code with the manual, I would suspect the loops in
33the line_functions to be not completely correct.
34
35This whole part will be eventually moved to video/ once I'm satisfied (or I give up).
36*/
37
3823/* modes from blitter command */
3924enum {
4025   BACKGROUND = 0,
r22917r22918
413398   }
414399}
415400
416static void lynx_blit_2color_line(lynx_state *state, const int y, const int xdir) {state->lynx_blit_do_work(y, xdir, 1, 0x01);}
417static void lynx_blit_4color_line(lynx_state *state, const int y, const int xdir) {state->lynx_blit_do_work(y, xdir, 2, 0x03);}
418static void lynx_blit_8color_line(lynx_state *state, const int y, const int xdir) {state->lynx_blit_do_work(y, xdir, 3, 0x07);}
419static void lynx_blit_16color_line(lynx_state *state, const int y, const int xdir) {state->lynx_blit_do_work(y, xdir, 4, 0x0f);}
420
421401void lynx_state::lynx_blit_rle_do_work( const INT16 y, const int xdir, const int bits_per_pixel, const int mask )
422402{
423403   int i;
r22917r22918
491471         for ( ; count>=0; count--)
492472         {
493473            width_accum += m_blitter.width;
494            for (i = 0; i < (width_accum>>8); i++, xi += xdir)
474            for (i = 0; i < (width_accum >> 8); i++, xi += xdir)
495475            {
496476               if ((xi >= 0) && (xi < 160))
497477                  lynx_plot_pixel(m_blitter.mode, xi, y, color);
r22917r22918
502482   }
503483}
504484
505static void lynx_blit_2color_rle_line(lynx_state *state, const int y, const int xdir) {state->lynx_blit_rle_do_work(y, xdir, 1, 0x01);}
506static void lynx_blit_4color_rle_line(lynx_state *state, const int y, const int xdir) {state->lynx_blit_rle_do_work(y, xdir, 2, 0x03);}
507static void lynx_blit_8color_rle_line(lynx_state *state, const int y, const int xdir) {state->lynx_blit_rle_do_work(y, xdir, 3, 0x07);}
508static void lynx_blit_16color_rle_line(lynx_state *state, const int y, const int xdir) {state->lynx_blit_rle_do_work(y, xdir, 4, 0x0f);}
509
510485void lynx_state::lynx_blit_lines()
511486{
487   static const int lynx_color_masks[4] = { 0x01, 0x03, 0x07, 0x0f };
488   INT16 y;
512489   int i;
513   INT16 y;
514490   int ydir = 0, xdir = 0;
515491   int flip = 0;
516492
r22917r22918
580556         continue;
581557      }
582558
583
584559      m_blitter.height_accumulator += m_blitter.height;
585      for (int i=0; i < (m_blitter.height_accumulator>>8); i++, y += ydir)
586      {
560      for (int j = 0; j < (m_blitter.height_accumulator >> 8); j++, y += ydir)
561      {           
587562         if (y >= 0 && y < 102)
588            m_blitter.line_function(this, y, xdir);
563         {
564            if (m_blitter.use_rle)
565               lynx_blit_rle_do_work(y, xdir, m_blitter.line_color + 1, lynx_color_masks[m_blitter.line_color]);
566            else
567               lynx_blit_do_work(y, xdir, m_blitter.line_color + 1, lynx_color_masks[m_blitter.line_color]);
568         }
589569         m_blitter.width += (INT16)m_blitter.stretch;
590570         if (m_blitter.vstretch) // doesn't seem to be used
591571         {
r22917r22918
681661
682662void lynx_state::lynx_blitter()
683663{
684   static const int lynx_colors[4]={2,4,8,16};
664   static const int lynx_colors[4] = { 2, 4, 8, 16 };
685665   UINT8 palette_offset;
686666   UINT8 coldep;
667   int colors;
687668
688   static void (* const blit_line[4])(lynx_state *state, const int y, const int xdir)= {
689   lynx_blit_2color_line,
690   lynx_blit_4color_line,
691   lynx_blit_8color_line,
692   lynx_blit_16color_line
693   };
694
695   static void (* const blit_rle_line[4])(lynx_state *state, const int y, const int xdir)= {
696   lynx_blit_2color_rle_line,
697   lynx_blit_4color_rle_line,
698   lynx_blit_8color_rle_line,
699   lynx_blit_16color_rle_line
700   };
701
702   int i; int colors;
703
704   m_blitter.mem = (UINT8*)m_maincpu->space(AS_PROGRAM).get_read_ptr(0x0000);
705
706669   m_blitter.busy = 1; // blitter working
707670   m_blitter.memory_accesses = 0;
708671
r22917r22918
750713
751714            colors = lynx_colors[m_blitter.spr_ctl0 >> 6];
752715
753            for (i = 0; i < colors / 2; i++)
716            for (int i = 0; i < colors / 2; i++)
754717            {
755718               m_blitter.color[i * 2]      = lynx_read_ram(m_blitter.scb + palette_offset + i) >> 4;
756719               m_blitter.color[i * 2 + 1 ] = lynx_read_ram(m_blitter.scb + palette_offset + i) & 0x0f;
r22917r22918
764727      {
765728         m_blitter.colpos = m_blitter.scb + (m_suzy.data[COLLOFFL] | (m_suzy.data[COLLOFFH]<<8));
766729         m_blitter.mode = m_blitter.spr_ctl0 & 0x07;
767
768         if (m_blitter.spr_ctl1 & 0x80) // totally literal sprite
769            m_blitter.line_function = blit_line[m_blitter.spr_ctl0 >> 6];
770         else
771            m_blitter.line_function = blit_rle_line[m_blitter.spr_ctl0 >> 6];
772
730         m_blitter.use_rle = m_blitter.spr_ctl1 & 0x80 ? 0 : 1;
731         m_blitter.line_color = (m_blitter.spr_ctl0 >> 6) & 0x03;
732         
773733         m_blitter.sprite_collide = !(m_blitter.spr_coll & 0x20);
774734         m_blitter.spritenr = m_blitter.spr_coll & 0x0f;
775735         m_blitter.fred = 0;
r22917r22918
13951355
13961356void lynx_state::lynx_timer_init(int which)
13971357{
1398   memset( &m_timer[which], 0, sizeof(LYNX_TIMER) );
1358   memset(&m_timer[which], 0, sizeof(LYNX_TIMER));
13991359   m_timer[which].timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(lynx_state::lynx_timer_shot),this));
1360
1361   state_save_register_item(machine(), "Lynx", NULL, which, m_timer[which].bakup);
1362   state_save_register_item(machine(), "Lynx", NULL, which, m_timer[which].cntrl1);
1363   state_save_register_item(machine(), "Lynx", NULL, which, m_timer[which].cntrl2);
1364   state_save_register_item(machine(), "Lynx", NULL, which, m_timer[which].counter);
1365   state_save_register_item(machine(), "Lynx", NULL, which, m_timer[which].timer_active);
14001366}
14011367
14021368void lynx_state::lynx_timer_signal_irq(int which)
14031369{
1404   if ( ( m_timer[which].cntrl1 & 0x80 ) && ( which != 4 ) ) // if interrupts are enabled and timer != 4
1370   if ((m_timer[which].cntrl1 & 0x80) && (which != 4)) // if interrupts are enabled and timer != 4
14051371   {
1406      m_mikey.data[0x81] |= ( 1 << which ); // set interupt poll register
1372      m_mikey.data[0x81] |= (1 << which); // set interupt poll register
14071373      m_maincpu->set_input_line(INPUT_LINE_HALT, CLEAR_LINE);
14081374      m_maincpu->set_input_line(M65SC02_IRQ_LINE, ASSERT_LINE);
14091375   }
1410   switch ( which ) // count down linked timers
1376   switch (which) // count down linked timers
14111377   {
14121378   case 0:
14131379      switch (m_timer[2].counter)
r22917r22918
14271393         default:
14281394            lynx_draw_line();
14291395      }
1430      lynx_timer_count_down( 2 );
1396      lynx_timer_count_down(2);
14311397      break;
14321398   case 2:
14331399      copybitmap(m_bitmap, m_bitmap_temp, 0, 0, 0, 0, machine().primary_screen->cliprect());
1434      lynx_timer_count_down( 4 );
1400      lynx_timer_count_down(4);
14351401      break;
14361402   case 1:
1437      lynx_timer_count_down( 3 );
1403      lynx_timer_count_down(3);
14381404      break;
14391405   case 3:
1440      lynx_timer_count_down( 5 );
1406      lynx_timer_count_down(5);
14411407      break;
14421408   case 5:
1443      lynx_timer_count_down( 7 );
1409      lynx_timer_count_down(7);
14441410      break;
14451411   case 7:
1446      lynx_audio_count_down( m_audio, 0 );
1412      m_sound->count_down(0);
14471413      break;
14481414   }
14491415}
14501416
14511417void lynx_state::lynx_timer_count_down(int which)
14521418{
1453   if ( ( m_timer[which].cntrl1 & 0x0f ) == 0x0f ) // count and linking enabled
1419   if ((m_timer[which].cntrl1 & 0x0f) == 0x0f) // count and linking enabled
14541420   {
1455      if ( m_timer[which].counter > 0 )
1421      if (m_timer[which].counter > 0)
14561422      {
14571423         m_timer[which].counter--;
14581424         //m_timer[which].borrow_in = 1;
14591425         return;
14601426      }
1461      if ( m_timer[which].counter == 0 )
1427      if (m_timer[which].counter == 0)
14621428      {
14631429         if (m_timer[which].cntrl2 & 0x01) // borrow out
14641430         {
14651431            lynx_timer_signal_irq(which);
1466            if ( m_timer[which].cntrl1 & 0x10 ) // if reload enabled
1432            if (m_timer[which].cntrl1 & 0x10) // if reload enabled
14671433            {
14681434               m_timer[which].counter = m_timer[which].bakup;
14691435            }
r22917r22918
15021468
15031469TIMER_CALLBACK_MEMBER(lynx_state::lynx_timer_shot)
15041470{
1505   lynx_timer_signal_irq( param );
1506   if ( ! ( m_timer[param].cntrl1 & 0x10 ) ) // if reload not enabled
1471   lynx_timer_signal_irq(param);
1472   if (!(m_timer[param].cntrl1 & 0x10)) // if reload not enabled
15071473   {
15081474      m_timer[param].timer_active = 0;
15091475      m_timer[param].cntrl2 |= 8; // set timer done
r22917r22918
17221688   case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
17231689   case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f:
17241690   case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x50:
1725      value = lynx_audio_read(m_audio, offset);
1691      value = m_sound->read(space, offset);
17261692      break;
17271693
17281694   case 0x80:
r22917r22918
17891755   case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
17901756   case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f:
17911757   case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x50:
1792      lynx_audio_write(m_audio, offset, data);
1758      m_sound->write(space, offset, data);
17931759      return;
17941760
17951761   case 0x80:
r22917r22918
18951861    * when these are safe in the cpu */
18961862   m_memory_config = data;
18971863
1898   if (data & 1) {
1864   if (data & 1)
1865   {
18991866      space.install_readwrite_bank(0xfc00, 0xfcff, "bank1");
1900   } else {
1867      membank("bank1")->set_base(m_mem_fc00);
1868   }
1869   else
19011870      space.install_readwrite_handler(0xfc00, 0xfcff, read8_delegate(FUNC(lynx_state::suzy_read),this), write8_delegate(FUNC(lynx_state::suzy_write),this));
1871
1872   if (data & 2)
1873   {
1874      space.install_readwrite_bank(0xfd00, 0xfdff, "bank2");
1875      membank("bank2")->set_base(m_mem_fd00);
19021876   }
1903   if (data & 2) {
1904      space.install_readwrite_bank(0xfd00, 0xfdff, "bank2");
1905   } else {
1877   else
19061878      space.install_readwrite_handler(0xfd00, 0xfdff, read8_delegate(FUNC(lynx_state::mikey_read),this), write8_delegate(FUNC(lynx_state::mikey_write),this));
1907   }
19081879
1909   if (data & 1)
1910      membank("bank1")->set_base(m_mem_fc00);
1911   if (data & 2)
1912      membank("bank2")->set_base(m_mem_fd00);
19131880   membank("bank3")->set_entry((data & 4) ? 1 : 0);
19141881   membank("bank4")->set_entry((data & 8) ? 1 : 0);
19151882}
r22917r22918
19581925{
19591926   m_bitmap_temp.allocate(160,102,0,0);
19601927
1961   int i;
1928   // save driver variables
19621929   save_item(NAME(m_memory_config));
1963   save_pointer(NAME(m_mem_fe00.target()), m_mem_fe00.bytes());
1930   save_item(NAME(m_sign_AB));
1931   save_item(NAME(m_sign_CD));
1932   save_item(NAME(m_palette));
1933   save_item(NAME(m_rotate));
1934   // save blitter variables
1935   save_item(NAME(m_blitter.screen));
1936   save_item(NAME(m_blitter.colbuf));
1937   save_item(NAME(m_blitter.colpos));
1938   save_item(NAME(m_blitter.xoff));
1939   save_item(NAME(m_blitter.yoff));
1940   save_item(NAME(m_blitter.mode));
1941   save_item(NAME(m_blitter.spr_coll));
1942   save_item(NAME(m_blitter.spritenr));
1943   save_item(NAME(m_blitter.x_pos));
1944   save_item(NAME(m_blitter.y_pos));
1945   save_item(NAME(m_blitter.width));
1946   save_item(NAME(m_blitter.height));
1947   save_item(NAME(m_blitter.tilt_accumulator));
1948   save_item(NAME(m_blitter.width_accumulator));
1949   save_item(NAME(m_blitter.height_accumulator));
1950   save_item(NAME(m_blitter.width_offset));
1951   save_item(NAME(m_blitter.height_offset));
1952   save_item(NAME(m_blitter.stretch));
1953   save_item(NAME(m_blitter.tilt));
1954   save_item(NAME(m_blitter.color));
1955   save_item(NAME(m_blitter.bitmap));
1956   save_item(NAME(m_blitter.use_rle));
1957   save_item(NAME(m_blitter.line_color));
1958   save_item(NAME(m_blitter.spr_ctl0));
1959   save_item(NAME(m_blitter.spr_ctl1));
1960   save_item(NAME(m_blitter.scb));
1961   save_item(NAME(m_blitter.scb_next));
1962   save_item(NAME(m_blitter.sprite_collide));
1963   save_item(NAME(m_blitter.everon));
1964   save_item(NAME(m_blitter.fred));
1965   save_item(NAME(m_blitter.memory_accesses));
1966   save_item(NAME(m_blitter.no_collide));
1967   save_item(NAME(m_blitter.vstretch));
1968   save_item(NAME(m_blitter.lefthanded));
1969   save_item(NAME(m_blitter.busy));
1970   // save suzy variables
1971   save_item(NAME(m_suzy.data));
1972   save_item(NAME(m_suzy.high));
1973   save_item(NAME(m_suzy.low));
1974   save_item(NAME(m_suzy.signed_math));
1975   save_item(NAME(m_suzy.accumulate));
1976   save_item(NAME(m_suzy.accumulate_overflow));
1977   // save mikey variables
1978   save_item(NAME(m_mikey.data));
1979   save_item(NAME(m_mikey.disp_addr));
1980   save_item(NAME(m_mikey.vb_rest));
1981   // save uart variables
1982   save_item(NAME(m_uart.serctl));
1983   save_item(NAME(m_uart.data_received));
1984   save_item(NAME(m_uart.data_to_send));
1985   save_item(NAME(m_uart.buffer));
1986   save_item(NAME(m_uart.received));
1987   save_item(NAME(m_uart.sending));
1988   save_item(NAME(m_uart.buffer_loaded));
1989   
19641990   machine().save().register_postload(save_prepost_delegate(FUNC(lynx_state::lynx_postload), this));
19651991
19661992   membank("bank3")->configure_entry(0, memregion("maincpu")->base() + 0x0000);
r22917r22918
19681994   membank("bank4")->configure_entry(0, memregion("maincpu")->base() + 0x01fa);
19691995   membank("bank4")->configure_entry(1, m_mem_fffa);
19701996
1971   m_audio = machine().device("custom");
1972
1973   memset(&m_suzy, 0, sizeof(m_suzy));
1974
1975   for (i = 0; i < NR_LYNX_TIMERS; i++)
1997   for (int i = 0; i < NR_LYNX_TIMERS; i++)
19761998      lynx_timer_init(i);
19771999}
19782000
trunk/src/mess/includes/lynx.h
r22917r22918
77#ifndef LYNX_H_
88#define LYNX_H_
99
10#include "audio/lynx.h"
1011#include "imagedev/cartslot.h"
1112#include "imagedev/snapquik.h"
1213
r22917r22918
1415#define LYNX_QUICKLOAD  1
1516
1617
17class lynx_state;
1818struct BLITTER
1919{
20   UINT8 *mem;
2120   // global
2221   UINT16 screen;
2322   UINT16 colbuf;
r22917r22918
3433   UINT16 width_offset, height_offset;
3534   INT16 stretch, tilt;
3635   UINT8 color[16]; // or stored
37   void (*line_function)(lynx_state *state, const int y, const int xdir);
3836   UINT16 bitmap;
37   int use_rle;
38   int line_color;
3939
4040   UINT8 spr_ctl0;
4141   UINT8 spr_ctl1;
r22917r22918
102102      m_mem_fd00(*this, "mem_fd00"),
103103      m_mem_fe00(*this, "mem_fe00"),
104104      m_mem_fffa(*this, "mem_fffa"),
105      m_maincpu(*this, "maincpu") { }
105      m_maincpu(*this, "maincpu"),
106      m_sound(*this, "custom") { }
106107
107108   virtual void video_start();
108109
r22917r22918
113114   required_shared_ptr<UINT8> m_mem_fd00;
114115   required_shared_ptr<UINT8> m_mem_fe00;
115116   required_shared_ptr<UINT8> m_mem_fffa;
117   required_device<cpu_device> m_maincpu;
118   required_device<lynx_sound_device> m_sound;
119   
116120   UINT16 m_granularity;
117121   int m_sign_AB;
118122   int m_sign_CD;
119123   UINT32 m_palette[0x10];
120124   int m_rotate;
121   device_t *m_audio;
122   SUZY m_suzy;
123   BLITTER m_blitter;
124125   UINT8 m_memory_config;
126
127   BLITTER m_blitter;
128   SUZY m_suzy;
125129   MIKEY m_mikey;
126   LYNX_TIMER m_timer[NR_LYNX_TIMERS];
127130   UART m_uart;
131   LYNX_TIMER m_timer[NR_LYNX_TIMERS];
132
128133   bitmap_ind16 m_bitmap;
129134   bitmap_ind16 m_bitmap_temp;
130135   DECLARE_READ8_MEMBER(suzy_read);
r22917r22918
142147   virtual void machine_start();
143148   virtual void machine_reset();
144149   virtual void palette_init();
150   void sound_cb();
145151   TIMER_CALLBACK_MEMBER(lynx_blitter_timer);
146152   TIMER_CALLBACK_MEMBER(lynx_timer_shot);
147153   TIMER_CALLBACK_MEMBER(lynx_uart_loopback_timer);
148154   TIMER_CALLBACK_MEMBER(lynx_uart_timer);
149155   void lynx_postload();
150156   DECLARE_DEVICE_IMAGE_LOAD_MEMBER( lynx_cart );
151   required_device<cpu_device> m_maincpu;
152157   UINT8 lynx_read_ram(UINT16 address);
153158   void lynx_write_ram(UINT16 address, UINT8 data);
154159   inline void lynx_plot_pixel(const int mode, const INT16 x, const int y, const int color);
r22917r22918
171176
172177MACHINE_CONFIG_EXTERN( lynx_cartslot );
173178
174
175/*----------- defined in audio/lynx.c -----------*/
176
177class lynx_sound_device : public device_t,
178                           public device_sound_interface
179{
180public:
181   lynx_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
182   lynx_sound_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source);
183   ~lynx_sound_device() { global_free(m_token); }
184
185   // access to legacy token
186   void *token() const { assert(m_token != NULL); return m_token; }
187protected:
188   // device-level overrides
189   virtual void device_config_complete();
190   virtual void device_start();
191   virtual void device_reset();
192
193   // sound stream update overrides
194   virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
195private:
196   // internal state
197   void *m_token;
198};
199
200extern const device_type LYNX;
201
202class lynx2_sound_device : public lynx_sound_device
203{
204public:
205   lynx2_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
206
207protected:
208   // device-level overrides
209   virtual void device_start();
210
211   // sound stream update overrides
212   virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
213};
214
215extern const device_type LYNX2;
216
217
218void lynx_audio_write(device_t *device, int offset, UINT8 data);
219UINT8 lynx_audio_read(device_t *device, int offset);
220void lynx_audio_count_down(device_t *device, int nr);
221
222179/*---------- suzy registers ------------- */
223180#define TMPADRL 0x00    // Temporary address (not sure what this is used for)
224181#define TMPADRH 0x01

Previous 199869 Revisions Next


© 1997-2024 The MAME Team