Previous 199869 Revisions Next

r20215 Saturday 12th January, 2013 at 12:09:44 UTC by Wilbert Pol
(MESS) odyssey2, videopac: Updated drivers to use the i8244/i8245 device implementation.  [Wilbert Pol]
[src/mess/drivers]odyssey2.c
[src/mess/includes]odyssey2.h
[src/mess/machine]odyssey2.c
[src/mess/video]odyssey2.c

trunk/src/mess/drivers/odyssey2.c
r20214r20215
4747   AM_RANGE(MCS48_PORT_P2,   MCS48_PORT_P2)   AM_READWRITE(p2_read, p2_write)
4848   AM_RANGE(MCS48_PORT_BUS,  MCS48_PORT_BUS)  AM_READWRITE(bus_read, bus_write)
4949   AM_RANGE(MCS48_PORT_T0,   MCS48_PORT_T0)   AM_READ(t0_read)
50   AM_RANGE(MCS48_PORT_T1,   MCS48_PORT_T1)   AM_READ(t1_read_g7400)
50   AM_RANGE(MCS48_PORT_T1,   MCS48_PORT_T1)   AM_READ(t1_read)
5151   AM_RANGE(MCS48_PORT_PROG, MCS48_PORT_PROG) AM_DEVWRITE("i8243", i8243_device, i8243_prog_w);
5252ADDRESS_MAP_END
5353
r20214r20215
137137}
138138
139139
140WRITE8_MEMBER(odyssey2_state::lum_write)
141{
142   m_lum = ( data & 0x01 ) << 3;
143}
144
145
146140WRITE16_MEMBER(odyssey2_state::scanline_postprocess)
147141{
148142   int vpos = data;
r20214r20215
156150}
157151
158152
159READ8_MEMBER(odyssey2_state::t1_read_g7400)
153READ8_MEMBER(odyssey2_state::t1_read)
160154{
161155   if ( m_i8244->vblank() || m_i8244->hblank() )
162156   {
r20214r20215
166160}
167161
168162
163READ8_MEMBER(odyssey2_state::p1_read)
164{
165   UINT8 data = m_p1;
166
167   logerror("%.9f p1 read %.2x\n", machine().time().as_double(), data);
168   return data;
169}
170
171
172WRITE8_MEMBER(odyssey2_state::p1_write)
173{
174   m_p1 = data;
175   m_lum = ( data & 0x80 ) >> 4;
176
177   switch_banks();
178
179   logerror("%.6f p1 written %.2x\n", machine().time().as_double(), data);
180}
181
182
183READ8_MEMBER(odyssey2_state::p2_read)
184{
185   UINT8 h = 0xFF;
186   int i, j;
187   static const char *const keynames[] = { "KEY0", "KEY1", "KEY2", "KEY3", "KEY4", "KEY5" };
188
189   if (!(m_p1 & P1_KEYBOARD_SCAN_ENABLE))
190   {
191      if ((m_p2 & P2_KEYBOARD_SELECT_MASK) <= 5)  /* read keyboard */
192      {
193         h &= ioport(keynames[m_p2 & P2_KEYBOARD_SELECT_MASK])->read();
194      }
195
196      for (i= 0x80, j = 0; i > 0; i >>= 1, j++)
197      {
198         if (!(h & i))
199         {
200            m_p2 &= ~0x10;                   /* set key was pressed indicator */
201            m_p2 = (m_p2 & ~0xE0) | (j << 5);  /* column that was pressed */
202
203            break;
204         }
205      }
206
207      if (h == 0xFF)  /* active low inputs, so no keypresses */
208      {
209         m_p2 = m_p2 | 0xF0;
210      }
211   }
212   else
213   {
214      m_p2 = m_p2 | 0xF0;
215   }
216
217   logerror("%.6f p2 read %.2x\n", machine().time().as_double(), m_p2);
218   return m_p2;
219}
220
221
222WRITE8_MEMBER(odyssey2_state::p2_write)
223{
224   m_p2 = data;
225
226   if ( m_i8243 )
227   {
228      m_i8243->i8243_p2_w( space, 0, m_p2 & 0x0f );
229   }
230
231   logerror("%.6f p2 written %.2x\n", machine().time().as_double(), data);
232}
233
234
235READ8_MEMBER(odyssey2_state::bus_read)
236{
237   UINT8 data = 0xff;
238
239   if ((m_p2 & P2_KEYBOARD_SELECT_MASK) == 1)
240   {
241      data &= ioport("JOY0")->read();       /* read joystick 1 */
242   }
243
244   if ((m_p2 & P2_KEYBOARD_SELECT_MASK) == 0)
245   {
246      data &= ioport("JOY1")->read();       /* read joystick 2 */
247   }
248
249   logerror("%.6f bus read %.2x\n", machine().time().as_double(), data);
250   return data;
251}
252
253
254WRITE8_MEMBER(odyssey2_state::bus_write)
255{
256   logerror("%.6f bus written %.2x\n", machine().time().as_double(), data);
257}
258
259
260/*
261    i8243 in the g7400
262*/
263
264WRITE8_MEMBER(odyssey2_state::i8243_port_w)
265{
266   switch ( offset & 3 )
267   {
268      case 0: // "port 4"
269         m_g7400_ic674_decode[4] = BIT(data,0);
270         m_g7400_ic674_decode[5] = BIT(data,1);
271         m_g7400_ic674_decode[6] = BIT(data,2);
272         m_g7400_ic674_decode[7] = BIT(data,3);
273         break;
274
275      case 1: // "port 5"
276         m_g7400_ic674_decode[0] = BIT(data,0);
277         m_g7400_ic674_decode[1] = BIT(data,1);
278         m_g7400_ic674_decode[2] = BIT(data,2);
279         m_g7400_ic674_decode[3] = BIT(data,3);
280         break;
281
282      case 2: // "port 6"
283         m_g7400_ic678_decode[4] = BIT(data,0);
284         m_g7400_ic678_decode[5] = BIT(data,1);
285         m_g7400_ic678_decode[6] = BIT(data,2);
286         m_g7400_ic678_decode[7] = BIT(data,3);
287         break;
288
289      case 3: // "port 7"
290         m_g7400_ic678_decode[0] = BIT(data,0);
291         m_g7400_ic678_decode[1] = BIT(data,1);
292         m_g7400_ic678_decode[2] = BIT(data,2);
293         m_g7400_ic678_decode[3] = BIT(data,3);
294         break;
295
296   }
297}
298
299
169300static const gfx_layout odyssey2_graphicslayout =
170301{
171302   8,1,
r20214r20215
234365
235366   /* video hardware */
236367   MCFG_SCREEN_ADD("screen", RASTER)
237   MCFG_SCREEN_RAW_PARAMS( XTAL_7_15909MHz/2, I824X_LINE_CLOCKS, I824X_START_ACTIVE_SCAN, I824X_END_ACTIVE_SCAN, 262, I824X_START_Y, I824X_START_Y + I824X_SCREEN_HEIGHT )
368   MCFG_SCREEN_RAW_PARAMS( XTAL_7_15909MHz/2, i8244_device::LINE_CLOCKS, i8244_device::START_ACTIVE_SCAN, i8244_device::END_ACTIVE_SCAN, i8244_device::LINES, i8244_device::START_Y, i8244_device::START_Y + i8244_device::SCREEN_HEIGHT )
238369   MCFG_SCREEN_UPDATE_DRIVER(odyssey2_state, screen_update_odyssey2)
239370
240371   MCFG_GFXDECODE( odyssey2 )
r20214r20215
242373
243374   /* sound hardware */
244375   MCFG_SPEAKER_STANDARD_MONO("mono")
245   MCFG_SOUND_ADD("custom", ODYSSEY2, XTAL_7_15909MHz/2)
376   MCFG_I8244_ADD( "i8244", XTAL_17_73447MHz/5, "screen", WRITELINE( odyssey2_state, irq_callback ), WRITE16( odyssey2_state, scanline_postprocess ) )
246377   MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.40)
247378
248379   MCFG_SOUND_ADD("sp0256_speech", SP0256, 3120000)
r20214r20215
263394
264395   /* video hardware */
265396   MCFG_SCREEN_ADD("screen", RASTER)
266   MCFG_SCREEN_RAW_PARAMS( XTAL_17_73447MHz/5, I824X_LINE_CLOCKS, I824X_START_ACTIVE_SCAN, I824X_END_ACTIVE_SCAN, 312, I824X_START_Y, I824X_START_Y + I824X_SCREEN_HEIGHT )
397   MCFG_SCREEN_RAW_PARAMS( XTAL_17_73447MHz/5, i8244_device::LINE_CLOCKS, i8244_device::START_ACTIVE_SCAN, i8244_device::END_ACTIVE_SCAN, i8245_device::LINES, i8244_device::START_Y, i8244_device::START_Y + i8244_device::SCREEN_HEIGHT )
267398   MCFG_SCREEN_UPDATE_DRIVER(odyssey2_state, screen_update_odyssey2)
268399
269400   MCFG_GFXDECODE( odyssey2 )
r20214r20215
271402
272403   /* sound hardware */
273404   MCFG_SPEAKER_STANDARD_MONO("mono")
274   MCFG_SOUND_ADD("custom", ODYSSEY2, XTAL_17_73447MHz/5)
405   MCFG_I8245_ADD( "i8244", XTAL_17_73447MHz/5, "screen", WRITELINE( odyssey2_state, irq_callback ), WRITE16( odyssey2_state, scanline_postprocess ) )
275406   MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.40)
276407
277408   MCFG_SOUND_ADD("sp0256_speech", SP0256, 3120000)
r20214r20215
302433   MCFG_I8243_ADD( "i8243", NOOP, WRITE8(odyssey2_state,i8243_port_w))
303434
304435   MCFG_SPEAKER_STANDARD_MONO("mono")
305   MCFG_I8244_ADD( "i8244", 3540000, "screen", WRITELINE( odyssey2_state, irq_callback ), WRITE16( odyssey2_state, scanline_postprocess ) )
436   MCFG_I8245_ADD( "i8244", 3540000, "screen", WRITELINE( odyssey2_state, irq_callback ), WRITE16( odyssey2_state, scanline_postprocess ) )
306437   MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.40)
307438
308439   MCFG_FRAGMENT_ADD(odyssey2_cartslot)
trunk/src/mess/machine/odyssey2.c
r20214r20215
9797
9898void odyssey2_state::machine_reset()
9999{
100   m_lum = 0;
101
100102   /* jump to "last" bank, will work for all sizes due to being mirrored */
101103   m_p1 = 0xFF;
102104   m_p2 = 0xFF;
r20214r20215
115117{
116118   if ((m_p1 & (P1_VDC_COPY_MODE_ENABLE | P1_VDC_ENABLE)) == 0)
117119   {
118      return video_read(space, offset); /* seems to have higher priority than ram??? */
120      return m_i8244->read(space, offset); /* seems to have higher priority than ram??? */
119121   }
120122   if (!(m_p1 & P1_EXT_RAM_ENABLE))
121123   {
r20214r20215
146148   }
147149   else if (!(m_p1 & P1_VDC_ENABLE))
148150   {
149      video_write(space, offset, data);
151      m_i8244->write(space, offset, data);
150152   }
151153}
152154
r20214r20215
186188   }
187189}
188190
189/***** 8048 Ports ************************/
190
191READ8_MEMBER(odyssey2_state::p1_read)
192{
193   UINT8 data = m_p1;
194
195   logerror("%.9f p1 read %.2x\n", machine().time().as_double(), data);
196   return data;
197}
198
199
200WRITE8_MEMBER(odyssey2_state::p1_write)
201{
202   m_p1 = data;
203
204   switch_banks();
205
206   lum_write(space, 0, m_p1 >> 7);
207
208   logerror("%.6f p1 written %.2x\n", machine().time().as_double(), data);
209}
210
211
212READ8_MEMBER(odyssey2_state::p2_read)
213{
214   UINT8 h = 0xFF;
215   int i, j;
216   static const char *const keynames[] = { "KEY0", "KEY1", "KEY2", "KEY3", "KEY4", "KEY5" };
217
218   if (!(m_p1 & P1_KEYBOARD_SCAN_ENABLE))
219   {
220      if ((m_p2 & P2_KEYBOARD_SELECT_MASK) <= 5)  /* read keyboard */
221      {
222         h &= ioport(keynames[m_p2 & P2_KEYBOARD_SELECT_MASK])->read();
223      }
224
225      for (i= 0x80, j = 0; i > 0; i >>= 1, j++)
226      {
227         if (!(h & i))
228         {
229            m_p2 &= ~0x10;                   /* set key was pressed indicator */
230            m_p2 = (m_p2 & ~0xE0) | (j << 5);  /* column that was pressed */
231
232            break;
233         }
234      }
235
236      if (h == 0xFF)  /* active low inputs, so no keypresses */
237      {
238         m_p2 = m_p2 | 0xF0;
239      }
240   }
241   else
242   {
243      m_p2 = m_p2 | 0xF0;
244   }
245
246   logerror("%.6f p2 read %.2x\n", machine().time().as_double(), m_p2);
247   return m_p2;
248}
249
250
251WRITE8_MEMBER(odyssey2_state::p2_write)
252{
253   m_p2 = data;
254
255   if ( m_i8243 )
256   {
257      m_i8243->i8243_p2_w( space, 0, m_p2 & 0x0f );
258   }
259
260   logerror("%.6f p2 written %.2x\n", machine().time().as_double(), data);
261}
262
263
264READ8_MEMBER(odyssey2_state::bus_read)
265{
266   UINT8 data = 0xff;
267
268   if ((m_p2 & P2_KEYBOARD_SELECT_MASK) == 1)
269   {
270      data &= ioport("JOY0")->read();       /* read joystick 1 */
271   }
272
273   if ((m_p2 & P2_KEYBOARD_SELECT_MASK) == 0)
274   {
275      data &= ioport("JOY1")->read();       /* read joystick 2 */
276   }
277
278   logerror("%.6f bus read %.2x\n", machine().time().as_double(), data);
279   return data;
280}
281
282
283WRITE8_MEMBER(odyssey2_state::bus_write)
284{
285   logerror("%.6f bus written %.2x\n", machine().time().as_double(), data);
286}
trunk/src/mess/includes/odyssey2.h
r20214r20215
2020
2121#define P2_KEYBOARD_SELECT_MASK   (0x07)  /* select row to scan */
2222
23#define OLD_VDC_CONTROL_REG_STROBE_XY (0x02)
24
2523#define I824X_START_ACTIVE_SCAN         6
2624#define I824X_END_ACTIVE_SCAN           (6 + 160)
2725#define I824X_START_Y                   1
2826#define I824X_SCREEN_HEIGHT             243
2927#define I824X_LINE_CLOCKS               228
3028
31union o2_vdc_t {
32   UINT8 reg[0x100];
33   struct {
34   struct {
35      UINT8 y,x,color,res;
36   } sprites[4];
37   struct {
38      UINT8 y,x,ptr,color;
39   } foreground[12];
40   struct {
41      struct {
42      UINT8 y,x,ptr,color;
43      } single[4];
44   } quad[4];
45   UINT8 shape[4][8];
46   UINT8 control;
47   UINT8 status;
48   UINT8 collision;
49   UINT8 color;
50   UINT8 y;
51   UINT8 x;
52   UINT8 res;
53   UINT8 shift1,shift2,shift3;
54   UINT8 sound;
55   UINT8 res2[5+0x10];
56   UINT8 hgrid[2][0x10];
57   UINT8 vgrid[0x10];
58   } s;
59};
60
6129struct ef9341_t
6230{
6331   UINT8   TA;
r20214r20215
8957   required_device<cpu_device> m_maincpu;
9058   required_device<screen_device> m_screen;
9159   optional_device<i8243_device> m_i8243;
92   optional_device<i8244_device> m_i8244;
60   required_device<i8244_device> m_i8244;
9361
9462   int m_the_voice_lrq_state;
9563   UINT8 *m_ram;
9664   UINT8 m_p1;
9765   UINT8 m_p2;
9866   size_t m_cart_size;
99   o2_vdc_t m_o2_vdc;
100   UINT32 m_o2_snd_shift[2];
101   UINT8 m_x_beam_pos;
102   UINT8 m_y_beam_pos;
103   UINT8 m_control_status;
104   UINT8 m_collision_status;
105   int m_iff;
10667   bitmap_ind16 m_tmp_bitmap;
10768   int m_start_vpos;
10869   int m_start_vblank;
10970   UINT8 m_lum;
110   sound_stream *m_sh_channel;
111   UINT16 m_sh_count;
11271   DECLARE_READ8_MEMBER(t0_read);
11372   DECLARE_READ8_MEMBER(io_read);
11473   DECLARE_WRITE8_MEMBER(io_write);
r20214r20215
12079   DECLARE_WRITE8_MEMBER(p1_write);
12180   DECLARE_READ8_MEMBER(p2_read);
12281   DECLARE_WRITE8_MEMBER(p2_write);
123   DECLARE_READ8_MEMBER(video_read);
124   DECLARE_WRITE8_MEMBER(video_write);
125   DECLARE_WRITE8_MEMBER(lum_write);
12682   DECLARE_READ8_MEMBER(t1_read);
127   DECLARE_READ8_MEMBER(t1_read_g7400);
12883   DECLARE_DRIVER_INIT(odyssey2);
12984   virtual void machine_start();
13085   virtual void machine_reset();
r20214r20215
156111   // Calculate the external chargen address for a character and slice
157112   inline UINT16 external_chargen_address(UINT8 b, UINT8 slice);
158113
159   void i824x_scanline(int vpos);
160114   void ef9340_scanline(int vpos);
161115
162116   /* timers */
r20214r20215
171125   void switch_banks();
172126};
173127
174
175/*----------- defined in video/odyssey2.c -----------*/
176
177
178STREAM_UPDATE( odyssey2_sh_update );
179
180class odyssey2_sound_device : public device_t,
181                           public device_sound_interface
182{
183public:
184   odyssey2_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
185protected:
186   // device-level overrides
187   virtual void device_config_complete();
188   virtual void device_start();
189
190   // sound stream update overrides
191   virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
192private:
193   // internal state
194};
195
196extern const device_type ODYSSEY2;
197
198
199128#endif /* ODYSSEY2_H_ */
trunk/src/mess/video/odyssey2.c
r20214r20215
7474   0xFF, 0xFF, 0xFF
7575};
7676
77static const UINT8 o2_shape[0x40][8]={
78   { 0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00 }, // 0
79   { 0x18,0x38,0x18,0x18,0x18,0x18,0x3C,0x00 },
80   { 0x3C,0x66,0x0C,0x18,0x30,0x60,0x7E,0x00 },
81   { 0x7C,0xC6,0x06,0x3C,0x06,0xC6,0x7C,0x00 },
82   { 0xCC,0xCC,0xCC,0xFE,0x0C,0x0C,0x0C,0x00 },
83   { 0xFE,0xC0,0xC0,0x7C,0x06,0xC6,0x7C,0x00 },
84   { 0x7C,0xC6,0xC0,0xFC,0xC6,0xC6,0x7C,0x00 },
85   { 0xFE,0x06,0x0C,0x18,0x30,0x60,0xC0,0x00 },
86   { 0x7C,0xC6,0xC6,0x7C,0xC6,0xC6,0x7C,0x00 },
87   { 0x7C,0xC6,0xC6,0x7E,0x06,0xC6,0x7C,0x00 },
88   { 0x00,0x18,0x18,0x00,0x18,0x18,0x00,0x00 },
89   { 0x18,0x7E,0x58,0x7E,0x1A,0x7E,0x18,0x00 },
90   { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
91   { 0x3C,0x66,0x0C,0x18,0x18,0x00,0x18,0x00 },
92   { 0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xFE,0x00 },
93   { 0xFC,0xC6,0xC6,0xFC,0xC0,0xC0,0xC0,0x00 },
94   { 0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00 },
95   { 0xC6,0xC6,0xC6,0xD6,0xFE,0xEE,0xC6,0x00 },
96   { 0xFE,0xC0,0xC0,0xF8,0xC0,0xC0,0xFE,0x00 },
97   { 0xFC,0xC6,0xC6,0xFC,0xD8,0xCC,0xC6,0x00 },
98   { 0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x00 },
99   { 0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00 },
100   { 0x3C,0x18,0x18,0x18,0x18,0x18,0x3C,0x00 },
101   { 0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00 },
102   { 0x7C,0xC6,0xC6,0xC6,0xDE,0xCC,0x76,0x00 },
103   { 0x7C,0xC6,0xC0,0x7C,0x06,0xC6,0x7C,0x00 },
104   { 0xFC,0xC6,0xC6,0xC6,0xC6,0xC6,0xFC,0x00 },
105   { 0xFE,0xC0,0xC0,0xF8,0xC0,0xC0,0xC0,0x00 },
106   { 0x7C,0xC6,0xC0,0xC0,0xCE,0xC6,0x7E,0x00 },
107   { 0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00 },
108   { 0x06,0x06,0x06,0x06,0x06,0xC6,0x7C,0x00 },
109   { 0xC6,0xCC,0xD8,0xF0,0xD8,0xCC,0xC6,0x00 },
110   { 0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0x00 },
111   { 0x7E,0x06,0x0C,0x18,0x30,0x60,0x7E,0x00 },
112   { 0xC6,0xC6,0x6C,0x38,0x6C,0xC6,0xC6,0x00 },
113   { 0x7C,0xC6,0xC0,0xC0,0xC0,0xC6,0x7C,0x00 },
114   { 0xC6,0xC6,0xC6,0xC6,0xC6,0x6C,0x38,0x00 },
115   { 0xFC,0xC6,0xC6,0xFC,0xC6,0xC6,0xFC,0x00 },
116   { 0xC6,0xEE,0xFE,0xD6,0xC6,0xC6,0xC6,0x00 },
117   { 0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00 },
118   { 0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00 },
119   { 0x00,0x66,0x3C,0x18,0x3C,0x66,0x00,0x00 },
120   { 0x00,0x18,0x00,0x7E,0x00,0x18,0x00,0x00 },
121   { 0x00,0x00,0x7E,0x00,0x7E,0x00,0x00,0x00 },
122   { 0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x00 },
123   { 0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0x00 },
124   { 0x03,0x06,0x0C,0x18,0x30,0x60,0xC0,0x00 },
125   { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00 },
126   { 0xCE,0xDB,0xDB,0xDB,0xDB,0xDB,0xCE,0x00 },
127   { 0x00,0x00,0x3C,0x7E,0x7E,0x7E,0x3C,0x00 },
128   { 0x1C,0x1C,0x18,0x1E,0x18,0x18,0x1C,0x00 },
129   { 0x1C,0x1C,0x18,0x1E,0x18,0x34,0x26,0x00 },
130   { 0x38,0x38,0x18,0x78,0x18,0x2C,0x64,0x00 },
131   { 0x38,0x38,0x18,0x78,0x18,0x18,0x38,0x00 },
132   { 0x00,0x18,0x0C,0xFE,0x0C,0x18,0x00,0x00 },
133   { 0x18,0x3C,0x7E,0xFF,0xFF,0x18,0x18,0x00 },
134   { 0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF,0x00 },
135   { 0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF,0x00 },
136   { 0x38,0x38,0x12,0xFE,0xB8,0x28,0x6C,0x00 },
137   { 0xC0,0x60,0x30,0x18,0x0C,0x06,0x03,0x00 },
138   { 0x00,0x00,0x0C,0x08,0x08,0x7F,0x3E,0x00 },
139   { 0x00,0x03,0x63,0xFF,0xFF,0x18,0x08,0x00 },
140   { 0x00,0x00,0x00,0x10,0x38,0xFF,0x7E,0x00 }
141};
14277
143
14478void odyssey2_state::palette_init()
14579{
14680   int i;
r20214r20215
15286}
15387
15488
155READ8_MEMBER(odyssey2_state::video_read)
156{
157   UINT8 data = 0;
158
159   switch (offset)
160   {
161      case 0xa1:
162         data = m_control_status;
163         m_iff = 0;
164         m_maincpu->set_input_line(0, CLEAR_LINE);
165         m_control_status &= ~ 0x08;
166         if ( m_screen->hpos() < I824X_START_ACTIVE_SCAN || m_screen->hpos() > I824X_END_ACTIVE_SCAN )
167         {
168            data |= 1;
169         }
170         break;
171
172      case 0xa2:
173         data = m_collision_status;
174         m_collision_status = 0;
175         break;
176
177      case 0xa4:
178         if (m_o2_vdc.s.control & OLD_VDC_CONTROL_REG_STROBE_XY)
179         {
180            m_y_beam_pos = m_screen->vpos() - m_start_vpos;
181         }
182
183         data = m_y_beam_pos;
184
185         break;
186
187
188      case 0xa5:
189
190         if ((m_o2_vdc.s.control & OLD_VDC_CONTROL_REG_STROBE_XY))
191         {
192            m_x_beam_pos = m_screen->hpos();
193            if ( m_x_beam_pos < I824X_START_ACTIVE_SCAN )
194            {
195               m_x_beam_pos = m_x_beam_pos - I824X_START_ACTIVE_SCAN + I824X_LINE_CLOCKS;
196            }
197            else
198            {
199               m_x_beam_pos = m_x_beam_pos - I824X_START_ACTIVE_SCAN;
200            }
201         }
202
203         data = m_x_beam_pos;
204
205         break;
206
207      default:
208         data = m_o2_vdc.reg[offset];
209   }
210
211   return data;
212}
213
214
215WRITE8_MEMBER(odyssey2_state::video_write)
216{
217   /* Update the sound */
218   if( offset >= 0xa7 && offset <= 0xaa )
219      m_sh_channel->update();
220
221   if (offset == 0xa0) {
222      if (    m_o2_vdc.s.control & OLD_VDC_CONTROL_REG_STROBE_XY
223            && !(data & OLD_VDC_CONTROL_REG_STROBE_XY))
224      {
225         /* Toggling strobe bit, tuck away values */
226         m_x_beam_pos = m_screen->hpos();
227         if ( m_x_beam_pos < I824X_START_ACTIVE_SCAN )
228         {
229            m_x_beam_pos = m_x_beam_pos - I824X_START_ACTIVE_SCAN + 228;
230         }
231         else
232         {
233            m_x_beam_pos = m_x_beam_pos - I824X_START_ACTIVE_SCAN;
234         }
235
236         m_y_beam_pos = m_screen->vpos() - m_start_vpos;
237      }
238   }
239
240   m_o2_vdc.reg[offset] = data;
241}
242
243
244READ8_MEMBER(odyssey2_state::t1_read)
245{
246   if ( m_screen->vpos() > m_start_vpos && m_screen->vpos() < m_start_vblank )
247   {
248      if ( m_screen->hpos() >= I824X_START_ACTIVE_SCAN && m_screen->hpos() < I824X_END_ACTIVE_SCAN )
249      {
250         return 1;
251      }
252   }
253   return 0;
254}
255
256
257void odyssey2_state::i824x_scanline(int vpos)
258{
259   UINT8   collision_map[160];
260
261   if ( vpos < m_start_vpos )
262      return;
263
264   if ( vpos == m_start_vpos )
265   {
266      m_control_status &= ~0x08;
267   }
268
269   if ( vpos < m_start_vblank )
270   {
271      rectangle rect;
272      //static const int sprite_width[4] = { 8, 8, 8, 8 };
273      int i;
274
275      m_control_status &= ~ 0x01;
276
277      /* Draw a line */
278      rect.set(I824X_START_ACTIVE_SCAN, I824X_END_ACTIVE_SCAN - 1, vpos, vpos);
279      m_tmp_bitmap.fill(( (m_o2_vdc.s.color >> 3) & 0x7 ) | ( ( m_lum << 3 ) ^ 0x08 ), rect );
280
281      /* Clear collision map */
282      memset( collision_map, 0, sizeof( collision_map ) );
283
284      /* Display grid if enabled */
285      if ( m_o2_vdc.s.control & 0x08 )
286      {
287         UINT16  color = ( m_o2_vdc.s.color & 7 ) | ( ( m_o2_vdc.s.color >> 3 ) & 0x08 ) | ( ( m_lum << 3 ) ^ 0x08 );
288         int     x_grid_offset = 8;
289         int     y_grid_offset = 24;
290         int     width = 16;
291         int     height = 24;
292         int     w = ( m_o2_vdc.s.control & 0x80 ) ? width : 2;
293         int     j, k, y;
294
295         /* Draw horizontal part of grid */
296         for ( j = 1, y = 0; y < 9; y++, j <<= 1 )
297         {
298            if ( y_grid_offset + y * height <= ( vpos - m_start_vpos ) && ( vpos - m_start_vpos ) < y_grid_offset + y * height + 3 )
299            {
300               for ( i = 0; i < 9; i++ )
301               {
302                  if ( ( m_o2_vdc.s.hgrid[0][i] & j ) || ( m_o2_vdc.s.hgrid[1][i] & ( j >> 8 ) ) )
303                  {
304                     for ( k = 0; k < width + 2; k++ )
305                     {
306                        int px = x_grid_offset + i * width + k;
307                        collision_map[ px ] |= COLLISION_HORIZ_GRID_DOTS;
308                        m_tmp_bitmap.pix16(vpos, I824X_START_ACTIVE_SCAN + px ) = color;
309                     }
310                  }
311               }
312            }
313         }
314
315         /* Draw vertical part of grid */
316         for( j = 1, y = 0; y < 8; y++, j <<= 1 )
317         {
318            if ( y_grid_offset + y * height <= ( vpos - m_start_vpos ) && ( vpos - m_start_vpos ) < y_grid_offset + ( y + 1 ) * height )
319            {
320               for ( i = 0; i < 10; i++ )
321               {
322                  if ( m_o2_vdc.s.vgrid[i] & j )
323                  {
324                     for ( k = 0; k < w; k++ )
325                     {
326                        int px = x_grid_offset + i * width + k;
327
328                        /* Check if we collide with an already drawn source object */
329                        if ( collision_map[ px ] & m_o2_vdc.s.collision )
330                        {
331                           m_collision_status |= COLLISION_VERTICAL_GRID;
332                        }
333                        /* Check if an already drawn object would collide with us */
334                        if ( COLLISION_VERTICAL_GRID & m_o2_vdc.s.collision && collision_map[ px ] )
335                        {
336                           m_collision_status |= collision_map[ px ];
337                        }
338                        collision_map[ px ] |= COLLISION_VERTICAL_GRID;
339                        m_tmp_bitmap.pix16(vpos, I824X_START_ACTIVE_SCAN + px ) = color;
340                     }
341                  }
342               }
343            }
344         }
345      }
346
347      /* Display objects if enabled */
348      if ( m_o2_vdc.s.control & 0x20 )
349      {
350         /* Regular foreground objects */
351         for ( i = 0; i < ARRAY_LENGTH( m_o2_vdc.s.foreground ); i++ )
352         {
353            int y = m_o2_vdc.s.foreground[i].y;
354            int height = 8 - ( ( ( y >> 1 ) + m_o2_vdc.s.foreground[i].ptr ) & 7 );
355
356            if ( y <= ( vpos - m_start_vpos ) && ( vpos - m_start_vpos ) < y + height * 2 )
357            {
358               UINT16  color = 16 + ( ( m_o2_vdc.s.foreground[i].color & 0x0E ) >> 1 );
359               int     offset = ( m_o2_vdc.s.foreground[i].ptr | ( ( m_o2_vdc.s.foreground[i].color & 0x01 ) << 8 ) ) + ( y >> 1 ) + ( ( vpos - m_start_vpos - y ) >> 1 );
360               UINT8   chr = ((char*)o2_shape)[ offset & 0x1FF ];
361               int     x = m_o2_vdc.s.foreground[i].x;
362               UINT8   m;
363
364               for ( m = 0x80; m > 0; m >>= 1, x++ )
365               {
366                  if ( chr & m )
367                  {
368                     if ( x >= 0 && x < 160 )
369                     {
370                        /* Check if we collide with an already drawn source object */
371                        if ( collision_map[ x ] & m_o2_vdc.s.collision )
372                        {
373                           m_collision_status |= COLLISION_CHARACTERS;
374                        }
375                        /* Check if an already drawn object would collide with us */
376                        if ( COLLISION_CHARACTERS & m_o2_vdc.s.collision && collision_map[ x ] )
377                        {
378                           m_collision_status |= collision_map[ x ];
379                        }
380                        collision_map[ x ] |= COLLISION_CHARACTERS;
381                        m_tmp_bitmap.pix16(vpos, I824X_START_ACTIVE_SCAN + x ) = color;
382                     }
383                  }
384               }
385            }
386         }
387
388         /* Quad objects */
389         for ( i = 0; i < ARRAY_LENGTH( m_o2_vdc.s.quad ); i++ )
390         {
391            int y = m_o2_vdc.s.quad[i].single[0].y;
392            int height = 8;
393
394            if ( y <= ( vpos - m_start_vpos ) && ( vpos - m_start_vpos ) < y + height * 2 )
395            {
396               int x = m_o2_vdc.s.quad[i].single[0].x;
397               int j;
398
399               // Charaecter height is always determined by the height of the 4th character
400               int char_height = 8 - ( ( ( y >> 1 ) + m_o2_vdc.s.quad[i].single[3].ptr ) & 7 );
401
402               for ( j = 0; j < ARRAY_LENGTH( m_o2_vdc.s.quad[0].single ); j++, x += 8 )
403               {
404                  if ( y <= ( vpos - m_start_vpos ) && ( vpos - m_start_vpos ) < y + char_height * 2 )
405                  {
406                  UINT16 color = 16 + ( ( m_o2_vdc.s.quad[i].single[j].color & 0x0E ) >> 1 );
407
408
409                     int offset = ( m_o2_vdc.s.quad[i].single[j].ptr | ( ( m_o2_vdc.s.quad[i].single[j].color & 0x01 ) << 8 ) ) + ( y >> 1 ) + ( ( vpos - m_start_vpos - y ) >> 1 );
410
411                     UINT8   chr = ((char*)o2_shape)[ offset & 0x1FF ];
412
413                     UINT8   m;
414                     for ( m = 0x80; m > 0; m >>= 1, x++ )
415                     {
416                        if ( chr & m )
417                        {
418                           if ( x >= 0 && x < 160 )
419                           {
420                              /* Check if we collide with an already drawn source object */
421                              if ( collision_map[ x ] & m_o2_vdc.s.collision )
422                              {
423                                 m_collision_status |= COLLISION_CHARACTERS;
424                              }
425                              /* Check if an already drawn object would collide with us */
426                              if ( COLLISION_CHARACTERS & m_o2_vdc.s.collision && collision_map[ x ] )
427                              {
428                                 m_collision_status |= collision_map[ x ];
429                              }
430                              collision_map[ x ] |= COLLISION_CHARACTERS;
431                              m_tmp_bitmap.pix16(vpos, I824X_START_ACTIVE_SCAN + x ) = color;
432                           }
433                        }
434                     }
435                  }
436                  else
437                  {
438                     x += 8;
439                  }
440               }
441            }
442         }
443
444         /* Sprites */
445         for ( i = 0; i < ARRAY_LENGTH( m_o2_vdc.s.sprites ); i++ )
446         {
447            int y = m_o2_vdc.s.sprites[i].y;
448            int height = 8;
449            if ( m_o2_vdc.s.sprites[i].color & 4 )
450            {
451               /* Zoomed sprite */
452               //sprite_width[i] = 16;
453               if ( y <= ( vpos - m_start_vpos ) && ( vpos - m_start_vpos ) < y + height * 4 )
454               {
455                  UINT16 color = 16 + ( ( m_o2_vdc.s.sprites[i].color >> 3 ) & 0x07 );
456                  UINT8   chr = m_o2_vdc.s.shape[i][ ( ( vpos - m_start_vpos - y ) >> 2 ) ];
457                  int     x = m_o2_vdc.s.sprites[i].x;
458                  UINT8   m;
459
460                  for ( m = 0x01; m > 0; m <<= 1, x += 2 )
461                  {
462                     if ( chr & m )
463                     {
464                        if ( x >= 0 && x < 160 )
465                        {
466                           /* Check if we collide with an already drawn source object */
467                           if ( collision_map[ x ] & m_o2_vdc.s.collision )
468                           {
469                              m_collision_status |= ( 1 << i );
470                           }
471                           /* Check if an already drawn object would collide with us */
472                           if ( ( 1 << i ) & m_o2_vdc.s.collision && collision_map[ x ] )
473                           {
474                              m_collision_status |= collision_map[ x ];
475                           }
476                           collision_map[ x ] |= ( 1 << i );
477                           m_tmp_bitmap.pix16(vpos, I824X_START_ACTIVE_SCAN + x ) = color;
478                        }
479                        if ( x >= -1 && x < 159 )
480                        {
481                           /* Check if we collide with an already drawn source object */
482                           if ( collision_map[ x ] & m_o2_vdc.s.collision )
483                           {
484                              m_collision_status |= ( 1 << i );
485                           }
486                           /* Check if an already drawn object would collide with us */
487                           if ( ( 1 << i ) & m_o2_vdc.s.collision && collision_map[ x ] )
488                           {
489                              m_collision_status |= collision_map[ x ];
490                           }
491                           collision_map[ x ] |= ( 1 << i );
492                           m_tmp_bitmap.pix16(vpos, I824X_START_ACTIVE_SCAN + x + 1 ) = color;
493                        }
494                     }
495                  }
496               }
497            }
498            else
499            {
500               /* Regular sprite */
501               if ( y <= ( vpos - m_start_vpos ) && ( vpos - m_start_vpos ) < y + height * 2 )
502               {
503                  UINT16 color = 16 + ( ( m_o2_vdc.s.sprites[i].color >> 3 ) & 0x07 );
504                  UINT8   chr = m_o2_vdc.s.shape[i][ ( ( vpos - m_start_vpos - y ) >> 1 ) ];
505                  int     x = m_o2_vdc.s.sprites[i].x;
506                  UINT8   m;
507
508                  for ( m = 0x01; m > 0; m <<= 1, x++ )
509                  {
510                     if ( chr & m )
511                     {
512                        if ( x >= 0 && x < 160 )
513                        {
514                           /* Check if we collide with an already drawn source object */
515                           if ( collision_map[ x ] & m_o2_vdc.s.collision )
516                           {
517                              m_collision_status |= ( 1 << i );
518                           }
519                           /* Check if an already drawn object would collide with us */
520                           if ( ( 1 << i ) & m_o2_vdc.s.collision && collision_map[ x ] )
521                           {
522                              m_collision_status |= collision_map[ x ];
523                           }
524                           collision_map[ x ] |= ( 1 << i );
525                           m_tmp_bitmap.pix16(vpos, I824X_START_ACTIVE_SCAN + x ) = color;
526                        }
527                     }
528                  }
529               }
530            }
531         }
532      }
533   }
534
535   /* Check for start of VBlank */
536   if ( vpos == m_start_vblank )
537   {
538      m_control_status |= 0x08;
539      if ( ! m_iff )
540      {
541         m_maincpu->set_input_line(0, ASSERT_LINE);
542         m_iff = 1;
543      }
544   }
545}
546
547
54889void odyssey2_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
54990{
55091   int vpos = m_screen->vpos();
r20214r20215
55293   switch ( id )
55394   {
55495      case TIMER_LINE:
555         // handle i824x line timer
556         i824x_scanline(vpos);
55796         if ( m_g7400 )
55897         {
55998            ef9340_scanline(vpos);
r20214r20215
561100         break;
562101
563102      case TIMER_HBLANK:
564         // handle i824x HBlank timer
565         if ( vpos < m_start_vpos - 1 )
566         {
567            return;
568         }
569
570         if ( vpos < m_start_vblank - 1 )
571         {
572            m_control_status |= 0x01;
573         }
574103         break;
575104   }
576105}
r20214r20215
584113
585114void odyssey2_state::video_start()
586115{
587   memset(m_o2_vdc.reg, 0, 0x100);
588
589   m_o2_snd_shift[0] = m_o2_snd_shift[1] = 0;
590   m_x_beam_pos = 0;
591   m_y_beam_pos = 0;
592   m_control_status = 0;
593   m_collision_status = 0;
594   m_iff = 0;
595   m_start_vpos = 0;
596   m_start_vblank = 0;
597   m_lum = 0;
598
599   m_o2_snd_shift[0] = machine().sample_rate() / 983;
600   m_o2_snd_shift[1] = machine().sample_rate() / 3933;
601
602116   m_start_vpos = I824X_START_Y;
603117   m_start_vblank = I824X_START_Y + I824X_SCREEN_HEIGHT;
604   m_control_status = 0;
605   m_iff = 0;
606118
607119   m_screen->register_screen_bitmap(m_tmp_bitmap);
608120
r20214r20215
639151
640152UINT32 odyssey2_state::screen_update_odyssey2(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
641153{
642   copybitmap( bitmap, m_tmp_bitmap, 0, 0, 0, 0, cliprect );
643
644   if ( m_i8244 )
645   {
646      return m_i8244->screen_update(screen, bitmap, cliprect);
647   }
648   return 0;
154   return m_i8244->screen_update(screen, bitmap, cliprect);
649155}
650156
651static DEVICE_START( odyssey2_sound )
652{
653   odyssey2_state *state = device->machine().driver_data<odyssey2_state>();
654   state->m_sh_channel = device->machine().sound().stream_alloc(*device, 0, 1, device->clock()/(I824X_LINE_CLOCKS*4), 0, odyssey2_sh_update );
655}
656157
657
658STREAM_UPDATE( odyssey2_sh_update )
659{
660   odyssey2_state *state = device->machine().driver_data<odyssey2_state>();
661   UINT32 old_signal, signal;
662   int ii;
663   int period;
664   stream_sample_t *buffer = outputs[0];
665
666   /* Generate the signal */
667   old_signal = signal = state->m_o2_vdc.s.shift3 | (state->m_o2_vdc.s.shift2 << 8) | (state->m_o2_vdc.s.shift1 << 16);
668
669   if( state->m_o2_vdc.s.sound & 0x80 )    /* Sound is enabled */
670   {
671      for( ii = 0; ii < samples; ii++, buffer++ )
672      {
673         *buffer = 0;
674         *buffer = signal & 0x1;
675         period = (state->m_o2_vdc.s.sound & 0x20) ? 1 : 4;
676         if( ++state->m_sh_count >= period )
677         {
678            state->m_sh_count = 0;
679            signal >>= 1;
680            /* Loop sound */
681            signal |= *buffer << 23;
682            /* Check if noise should be applied */
683            if ( state->m_o2_vdc.s.sound & 0x10 )
684            {
685               /* Noise tap is on bits 0 and 5 and fed back to bits 15 (and 23!) */
686               UINT32 new_bit = ( ( old_signal ) ^ ( old_signal >> 5 ) ) & 0x01;
687               signal = ( old_signal & 0xFF0000 ) | ( ( old_signal & 0xFFFF ) >> 1 ) | ( new_bit << 15 ) | ( new_bit << 23 );
688            }
689            state->m_o2_vdc.s.shift3 = signal & 0xFF;
690            state->m_o2_vdc.s.shift2 = ( signal >> 8 ) & 0xFF;
691            state->m_o2_vdc.s.shift1 = ( signal >> 16 ) & 0xFF;
692            old_signal = signal;
693         }
694
695         /* Throw an interrupt if enabled */
696         if( state->m_o2_vdc.s.control & 0x4 )
697         {
698            state->m_maincpu->set_input_line(1, HOLD_LINE); /* Is this right? */
699         }
700
701         /* Adjust volume */
702         *buffer *= state->m_o2_vdc.s.sound & 0xf;
703         /* Pump the volume up */
704         *buffer <<= 10;
705      }
706   }
707   else
708   {
709      /* Sound disabled, so clear the buffer */
710      for( ii = 0; ii < samples; ii++, buffer++ )
711         *buffer = 0;
712   }
713}
714
715158/*
716    i8243 in the g7400
717*/
718
719WRITE8_MEMBER(odyssey2_state::i8243_port_w)
720{
721   switch ( offset & 3 )
722   {
723      case 0: // "port 4"
724         m_g7400_ic674_decode[4] = BIT(data,0);
725         m_g7400_ic674_decode[5] = BIT(data,1);
726         m_g7400_ic674_decode[6] = BIT(data,2);
727         m_g7400_ic674_decode[7] = BIT(data,3);
728         break;
729
730      case 1: // "port 5"
731         m_g7400_ic674_decode[0] = BIT(data,0);
732         m_g7400_ic674_decode[1] = BIT(data,1);
733         m_g7400_ic674_decode[2] = BIT(data,2);
734         m_g7400_ic674_decode[3] = BIT(data,3);
735         break;
736
737      case 2: // "port 6"
738         m_g7400_ic678_decode[4] = BIT(data,0);
739         m_g7400_ic678_decode[5] = BIT(data,1);
740         m_g7400_ic678_decode[6] = BIT(data,2);
741         m_g7400_ic678_decode[7] = BIT(data,3);
742         break;
743
744      case 3: // "port 7"
745         m_g7400_ic678_decode[0] = BIT(data,0);
746         m_g7400_ic678_decode[1] = BIT(data,1);
747         m_g7400_ic678_decode[2] = BIT(data,2);
748         m_g7400_ic678_decode[3] = BIT(data,3);
749         break;
750
751   }
752}
753
754
755/*
756159    Thomson EF9340/EF9341 extra chips in the g7400
757160 */
758161
r20214r20215
1007410   }
1008411}
1009412
1010
1011const device_type ODYSSEY2 = &device_creator<odyssey2_sound_device>;
1012
1013odyssey2_sound_device::odyssey2_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
1014   : device_t(mconfig, ODYSSEY2, "P8244/P8245", tag, owner, clock),
1015      device_sound_interface(mconfig, *this)
1016{
1017}
1018
1019//-------------------------------------------------
1020//  device_config_complete - perform any
1021//  operations now that the configuration is
1022//  complete
1023//-------------------------------------------------
1024
1025void odyssey2_sound_device::device_config_complete()
1026{
1027}
1028
1029//-------------------------------------------------
1030//  device_start - device-specific startup
1031//-------------------------------------------------
1032
1033void odyssey2_sound_device::device_start()
1034{
1035   DEVICE_START_NAME( odyssey2_sound )(this);
1036}
1037
1038//-------------------------------------------------
1039//  sound_stream_update - handle a stream update
1040//-------------------------------------------------
1041
1042void odyssey2_sound_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
1043{
1044   // should never get here
1045   fatalerror("sound_stream_update called; not applicable to legacy sound devices\n");
1046}

Previous 199869 Revisions Next


© 1997-2024 The MAME Team