Previous 199869 Revisions Next

r17576 Thursday 30th August, 2012 at 08:44:11 UTC by Miodrag Milanović
Removed files in MESS that are not used anymore and cleaned mess.mak of duplicated files (nw)
[src/mess]mess.mak
[src/mess/audio]ted7360.c ted7360.h
[src/mess/devices]kermit.c kermit.h xmodem.c xmodem.h
[src/mess/drivers]c16.c
[src/mess/machine]ap2_lang.c ap2_lang.h ap2_slot.c ap2_slot.h c16.c jupiter.c ti85_ser.c ti85_ser.h

trunk/src/mess/devices/xmodem.h
r17575r17576
1/* XMODEM protocol implementation.
2
3   Transfer between an emulated machine and an image using the XMODEM protocol.
4
5   Used in the HP48 G/GX emulation.
6
7   Author: Antoine Mine'
8   Date: 29/03/2008
9 */
10
11#include "timer.h"
12#include "image.h"
13
14
15DECLARE_LEGACY_IMAGE_DEVICE(XMODEM, xmodem);
16
17
18typedef struct {
19
20   /* called by XMODEM when it wants to send a byte to the emulated machine */
21   void (*send)( running_machine &machine, UINT8 data );
22
23} xmodem_config;
24
25
26#define MCFG_XMODEM_ADD(_tag, _intrf) \
27   MCFG_DEVICE_ADD(_tag, XMODEM, 0)         \
28   MCFG_DEVICE_CONFIG(_intrf)
29
30
31
32/* call when the emulated machine has read the last byte sent by
33   XMODEM through the send call-back */
34extern void xmodem_byte_transmitted( device_t *device );
35
36/* call when the emulated machine sends a byte to XMODEM */
37extern void xmodem_receive_byte( device_t *device, UINT8 data );
trunk/src/mess/devices/kermit.h
r17575r17576
1/* Kermit protocol implementation.
2
3   Transfer between an emulated machine and an image using the kermit protocol.
4
5   Used in the HP48 S/SX/G/GX emulation.
6
7   Author: Antoine Mine'
8   Date: 29/03/2008
9 */
10
11#include "timer.h"
12#include "image.h"
13
14
15DECLARE_LEGACY_IMAGE_DEVICE(KERMIT, kermit);
16
17
18typedef struct {
19
20   /* called by Kermit when it wants to send a byte to the emulated machine */
21   void (*send)( running_machine &machine, UINT8 data );
22
23} kermit_config;
24
25
26#define MCFG_KERMIT_ADD(_tag, _intrf) \
27   MCFG_DEVICE_ADD(_tag, KERMIT, 0)         \
28   MCFG_DEVICE_CONFIG(_intrf)
29
30
31/* call this when the emulated machine has read the last byte sent by
32   Kermit through the send call-back */
33extern void kermit_byte_transmitted( device_t *device );
34
35/* call this when the emulated machine sends a byte to Kermit */
36extern void kermit_receive_byte( device_t *device, UINT8 data );
trunk/src/mess/devices/xmodem.c
r17575r17576
1   /* XMODEM protocol implementation.
2
3   Transfer between an emulated machine and an image using the XMODEM protocol.
4
5   Used in the HP48 G/GX emulation.
6
7   Based on the "Xmodem protol specification" by Ward Christensen.
8
9   Does not support any extension (such as 16-bit CRC, 1K packet size,
10   batchs, YMODEM, ZMODEM).
11
12   Author: Antoine Mine'
13   Date: 29/03/2008
14 */
15
16#include "emu.h"
17#include "xmodem.h"
18
19
20/* debugging */
21#define VERBOSE          0
22
23#define LOG(x)  do { if (VERBOSE) logerror x; } while (0)
24
25
26/* XMODEM protocol bytes */
27#define XMODEM_SOH 0x01  /* data packet header */
28#define XMODEM_EOT 0x04  /* end of transmission */
29#define XMODEM_ACK 0x06  /* acknowledge (packet received) */
30#define XMODEM_NAK 0x15  /* not-acknowledge (10-second timeout) */
31#define XMODEM_CAN 0x18  /* cancel */
32
33/* XMODEM protocol is:
34
35   sender        receiver
36
37            <--   <NAK>
38   packet   -->
39            <--   <ACK>
40            ...
41   packet   -->
42            <--   <ACK>
43   <EOT>    -->
44            <--   <ACK>
45
46   and packet is:  <SOH> <id> <0xff-id> <data0> ... <data127> <checksum>
47
48   <id> is 1 for the first packet, 2 for the 2d, etc...
49   <checksum> is the sum of <data0> to <data127> modulo 256
50
51   there are always 128 bytes of data in a packet, so, any file transfered is
52   rounded to a multiple of 128 bytes, using 0-filler
53*/
54
55
56/* our state */
57#define XMODEM_NOIMAGE    0
58#define XMODEM_IDLE       1
59#define XMODEM_SENDING    2 /* image to emulated machine */
60#define XMODEM_RECEIVING  3 /* emulated machine to image */
61
62typedef struct {
63
64   UINT8   m_block[132];          /* 3-byte header + 128-byte block + checksum */
65   UINT32  m_id;                  /* block id, starting at 1 */
66   UINT16  m_pos;                 /* position in block, including header */
67   UINT8   m_state;               /* one of XMODEM_ */
68
69   device_image_interface* m_image;  /* underlying image */
70
71   emu_timer* m_timer;            /* used to send periodic NAKs */
72
73   running_machine *m_machine;
74
75   xmodem_config* m_conf;
76
77} xmodem;
78
79INLINE xmodem *get_safe_token(device_t *device)
80{
81   assert(device != NULL);
82   assert(device->type() == XMODEM);
83
84   return (xmodem*)downcast<legacy_device_base *>(device)->token();
85}
86
87/* compute checksum of the data part of the packet, i.e., sum modulo 256 */
88static UINT8 xmodem_chksum( xmodem* state )
89{
90   UINT8 sum = 0;
91   int i;
92   for ( i = 0; i < 128; i++ ) sum += state->m_block[ i + 3 ];
93   return sum;
94}
95
96/* fills state->m_block with the data for packet number state->m_id
97   returns != 0 if fail or end of file
98*/
99static int xmodem_make_send_block( xmodem* state )
100{
101   if ( ! state->m_image ) return -1;
102   memset( state->m_block + 3, 0, 128 );
103   if ( state->m_image->fseek( (state->m_id - 1) * 128, SEEK_SET ) ) return -1;
104   if ( state->m_image->fread( state->m_block + 3, 128 ) <= 0 ) return -1;
105   state->m_block[0] = XMODEM_SOH;
106   state->m_block[1] = state->m_id & 0xff;
107   state->m_block[2] = 0xff - state->m_block[1];
108   state->m_block[131] = xmodem_chksum( state );
109   return 0;
110}
111
112/* checks the received state->m_block packet and stores the data in the image
113   returns != 0 if fail (bad packet or bad image)
114 */
115static int xmodem_get_receive_block( xmodem* state )
116{
117   int next_id = state->m_id + 1;
118   if ( ! state->m_image ) return -1;
119   if ( state->m_image->is_readonly() ) return -1;
120   if ( state->m_block[0] != XMODEM_SOH ) return -1;
121   if ( state->m_block[1] != 0xff - state->m_block[2] ) return -1;
122   if ( state->m_block[131] != xmodem_chksum( state ) ) return -1;
123   if ( state->m_block[1] != (next_id & 0xff) ) return -1;
124   if ( state->m_image->fseek( (next_id - 1) * 128, SEEK_SET ) ) return -1;
125   if ( state->m_image->fwrite( state->m_block + 3, 128 ) != 128 ) return -1;
126   return 0;
127}
128
129/* the outside (us) sends a byte to the emulated machine */
130static void xmodem_send_byte( xmodem* state, UINT8 data )
131{
132   if ( state->m_conf && state->m_conf->send )
133   {
134      state->m_conf->send(*state->m_machine, data );
135   }
136}
137
138static void xmodem_send_packet_byte( xmodem* state )
139{
140   assert( state->m_pos < 132 );
141   xmodem_send_byte( state, state->m_block[ state->m_pos ] );
142   state->m_pos++;
143}
144
145
146static TIMER_CALLBACK( xmodem_nak_cb )
147{
148   xmodem* state = (xmodem*) ptr;
149   if ( state->m_state != XMODEM_IDLE ) return;
150   LOG(( "xmodem: sending NAK keep-alive\n" ));
151   xmodem_send_byte( state, XMODEM_NAK );
152}
153
154static void xmodem_make_idle( xmodem* state )
155{
156   LOG(( "xmodem: entering idle state\n" ));
157   state->m_state = XMODEM_IDLE;
158   state->m_id = 0;
159   state->m_pos = 0;
160        /* When idle, we send NAK periodically to tell the emulated machine that we are
161       always ready to receive.
162       The 2 sec start time is here so that the machine does not get NAK instead of
163       ACK or EOT as the last byte of a transfer.
164     */
165   state->m_timer->adjust( attotime::from_seconds( 2 ), 0, attotime::from_seconds( 2 ) );
166}
167
168/* emulated machine has read the last byte we sent */
169void xmodem_byte_transmitted( device_t *device )
170{
171   xmodem* state = get_safe_token(device);
172   if ( (state->m_state == XMODEM_SENDING) && (state->m_pos < 132) )
173   {
174      /* send next byte */
175      xmodem_send_packet_byte( state );
176   }
177}
178
179/* emulated machine sends a byte to the outside (us) */
180void xmodem_receive_byte( device_t *device, UINT8 data )
181{
182   xmodem* state = get_safe_token(device);
183   switch ( state->m_state )
184   {
185
186   case XMODEM_NOIMAGE:
187      break;
188
189   case XMODEM_IDLE:
190      if ( data == XMODEM_NAK )
191      {
192         /* start sending */
193         LOG(( "xmodem: got NAK, start sending\n" ));
194         state->m_id = 1;
195         if ( xmodem_make_send_block( state ) )
196         {
197            /* error */
198            LOG(( "xmodem: nothing to send, sending NAK\n" ));
199            xmodem_send_byte( state, XMODEM_NAK );
200            xmodem_make_idle( state );
201         }
202         else
203         {
204            /* send first packet */
205            state->m_state = XMODEM_SENDING;
206            state->m_pos = 0;
207            xmodem_send_packet_byte( state );
208         }
209         break;
210      }
211      else if ( data == XMODEM_SOH )
212      {
213         /* start receiving */
214         LOG(( "xmodem: got SOH, start receiving\n" ));
215         state->m_state = XMODEM_RECEIVING;
216         state->m_block[ 0 ] = data;
217         state->m_pos = 1;
218         state->m_id = 0;
219      }
220      else
221      {
222         LOG(( "xmodem: ignored data %02x while idle\n", data ));
223      }
224      break;
225
226   case XMODEM_SENDING:
227      if ( (data != XMODEM_NAK) && (data != XMODEM_ACK) )
228      {
229         /* error */
230         LOG(( "xmodem: invalid date %02x while sending, sending CAN\n", data ));
231         xmodem_send_byte( state, XMODEM_CAN );
232         xmodem_make_idle( state );
233         break;
234      }
235      if ( data == XMODEM_ACK )
236      {
237         /* send next packet */
238         state->m_id++;
239         LOG(( "xmodem: got ACK, sending next packet (%i)\n", state->m_id ));
240         if ( xmodem_make_send_block( state ) )
241         {
242            /* end of file */
243            LOG(( "xmodem: no more packet, sending EOT\n" ));
244            xmodem_send_byte( state, XMODEM_EOT );
245            xmodem_make_idle( state );
246            break;
247         }
248
249      }
250      else
251      {
252         /* empty - resend last packet */
253         LOG(( "xmodem: got NAK, resending packet %i\n", state->m_id ));
254      }
255      state->m_pos = 0;
256      xmodem_send_packet_byte( state );
257      break;
258
259
260   case XMODEM_RECEIVING:
261      assert( state->m_pos < 132 );
262      state->m_block[ state->m_pos ] = data;
263      state->m_pos++;
264      if ( state->m_pos == 1 )
265      {
266         /* header byte */
267         if ( data == XMODEM_EOT )
268         {
269            /* end of file */
270            LOG(( "xmodem: got EOT, stop receiving\n" ));
271            xmodem_send_byte( state, XMODEM_ACK );
272            xmodem_make_idle( state );
273            break;
274         }
275      }
276      else if ( state->m_pos == 132 )
277      {
278         LOG(( "xmodem: received packet %i\n", state->m_id ));
279         /* end of block */
280         if ( xmodem_get_receive_block( state ) )
281         {
282            /* error */
283            LOG(( "xmodem: packet is invalid, sending NAK\n" ));
284            xmodem_send_byte( state, XMODEM_NAK );
285         }
286         else
287         {
288            /* ok */
289            LOG(( "xmodem: packet is valid, sending ACK\n" ));
290            xmodem_send_byte( state, XMODEM_ACK );
291            state->m_id++;
292         }
293         state->m_pos = 0;
294      }
295      break;
296
297   }
298}
299
300static DEVICE_START( xmodem )
301{
302   xmodem* state = get_safe_token(device);
303   LOG(( "xmodem: start\n" ));
304   state->m_state = XMODEM_NOIMAGE;
305   state->m_image = NULL;
306   state->m_conf = (xmodem_config*) device->static_config();
307   state->m_machine = &device->machine();
308   state->m_timer = device->machine().scheduler().timer_alloc(FUNC(xmodem_nak_cb), state );
309}
310
311static DEVICE_RESET( xmodem )
312{
313   xmodem* state = get_safe_token(device);
314   LOG(( "xmodem: reset\n" ));
315   if ( state->m_state != XMODEM_NOIMAGE ) xmodem_make_idle( state );
316}
317
318static DEVICE_IMAGE_LOAD( xmodem )
319{
320   xmodem* state = get_safe_token(&image.device());
321   LOG(( "xmodem: image load\n" ));
322   state->m_image = &image;
323   xmodem_make_idle( state );
324   return IMAGE_INIT_PASS;
325}
326
327static DEVICE_IMAGE_CREATE( xmodem )
328{
329   xmodem* state = get_safe_token(&image.device());
330   LOG(( "xmodem: image create\n" ));
331   state->m_image = &image;
332   xmodem_make_idle( state );
333   return IMAGE_INIT_PASS;
334}
335
336static DEVICE_IMAGE_UNLOAD( xmodem )
337{
338   xmodem* state = get_safe_token(&image.device());
339   LOG(( "xmodem: image unload\n" ));
340   state->m_state = XMODEM_NOIMAGE;
341   state->m_image = NULL;
342}
343
344DEVICE_GET_INFO( xmodem )
345
346{
347   switch ( state ) {
348   case DEVINFO_INT_TOKEN_BYTES:               info->i = sizeof( xmodem );                              break;
349   case DEVINFO_INT_INLINE_CONFIG_BYTES:       info->i = 0;                                             break;
350   case DEVINFO_INT_IMAGE_TYPE:               info->i = IO_SERIAL;                                     break;
351   case DEVINFO_INT_IMAGE_READABLE:            info->i = 1;                                             break;
352   case DEVINFO_INT_IMAGE_WRITEABLE:       info->i = 1;                                             break;
353   case DEVINFO_INT_IMAGE_CREATABLE:       info->i = 1;                                             break;
354   case DEVINFO_FCT_START:                       info->start = DEVICE_START_NAME( xmodem );               break;
355   case DEVINFO_FCT_RESET:                       info->reset = DEVICE_RESET_NAME( xmodem );               break;
356   case DEVINFO_FCT_IMAGE_LOAD:          info->f = (genf *) DEVICE_IMAGE_LOAD_NAME( xmodem );     break;
357   case DEVINFO_FCT_IMAGE_UNLOAD:          info->f = (genf *) DEVICE_IMAGE_UNLOAD_NAME( xmodem );   break;
358   case DEVINFO_FCT_IMAGE_CREATE:          info->f = (genf *) DEVICE_IMAGE_CREATE_NAME( xmodem );   break;
359   case DEVINFO_STR_IMAGE_BRIEF_INSTANCE_NAME: strcpy(info->s, "x");                                        break;
360   case DEVINFO_STR_IMAGE_INSTANCE_NAME:
361   case DEVINFO_STR_NAME:                  strcpy(info->s, "Xmodem");                                        break;
362   case DEVINFO_STR_FAMILY:                    strcpy(info->s, "Serial protocol");                        break;
363   case DEVINFO_STR_SOURCE_FILE:          strcpy(info->s, __FILE__);                                      break;
364   case DEVINFO_STR_IMAGE_FILE_EXTENSIONS:       strcpy(info->s, "");                                            break;
365   }
366}
367
368DEFINE_LEGACY_IMAGE_DEVICE(XMODEM, xmodem);
trunk/src/mess/devices/kermit.c
r17575r17576
1/* Kermit protocol implementation.
2
3   Transfer between an emulated machine and an image using the kermit protocol.
4
5   Used in the HP48 S/SX/G/GX emulation.
6
7   Based on the 'KERMIT PROTOCOL MANUAL', Sixth Edition, by Frank da Cruz,
8   Columbia University Center for Computing Activities, New York, June 1986.
9   Available at: http://www-vs.informatik.uni-ulm.de/teach/ws05/rn1/Kermit%20Protocol.pdf
10
11   Used in the HP48 S/SX/G/GX emulation.
12   For HP48 specific kermit notes, see http://www.columbia.edu/kermit/hp48.html
13
14   Only the basic protocol is implemented.
15   The following features are NOT supported:
16   - 8-bit quoting (QBIN)
17   - 2- or 3-byte checksums (only 1-byte supported)
18   - repeat count
19   - file attribute packets
20   - sliding window
21   - extended length packets
22   - server mode
23
24   Author: Antoine Mine'
25   Date: 29/03/2008
26 */
27
28
29#include "emu.h"
30#include "kermit.h"
31
32
33/* debugging */
34#define VERBOSE          0
35
36#define LOG(x)  do { if (VERBOSE) logerror x; } while (0)
37
38/* protocol bytes */
39#define KERMIT_SOH 0x01 /* (default) start of header */
40
41/* packet types */
42#define KERMIT_DATA 'D'  /* data packet */
43#define KERMIT_ACK  'Y'  /* acknowledge */
44#define KERMIT_NAK  'N'  /* negative acknowledge */
45#define KERMIT_SEND 'S'  /* send initiate (exchange parameters) */
46#define KERMIT_EOT  'B'  /* break transmission */
47#define KERMIT_FILE 'F'  /* file header */
48#define KERMIT_EOF  'Z'  /* end of file */
49#define KERMIT_ERR  'E'  /* error */
50
51#define KERMIT_QCTL  '#' /* default escape character */
52#define KERMIT_EOL   15  /* default terminator: carriage-return  */
53#define KERMIT_MAXL  80  /* default maximum packet length */
54
55/* protocol state, to drive action */
56#define KERMIT_IDLE       0  /* nothing to do */
57#define KERMIT_RESET      1  /* reset after sending the last packet */
58#define KERMIT_RECEIVE    2  /* receiving */
59#define KERMIT_SEND_DATA  3  /* sending data */
60#define KERMIT_SEND_EOF   4  /* sending EOF */
61#define KERMIT_SEND_EOT   5  /* sendinf EOT */
62
63/* packet retry parameters */
64#define KERMIT_MAX_RETRIES  5
65#define KERMIT_RETRY_DELAY  attotime::from_seconds( 10 )
66
67
68/* packet format is:
69
70   <mark> <len> <seq> <type> <data0> ... <datan> <check>
71
72   - <mark>  KERMIT_SOH
73   - <len>   number of bytes after <len> (max=94), plus 32
74   - <seq>   sequence number, modulo 63, plus 32
75   - <type>  one of KERMIT_ packet types
76   - <data>  payload, with control characters escaped with KERMIT_QCTL
77   - <check> checksum, from <len> to <datan>, excluding <mark>
78
79   the packet may be followed by arbitrary (non KERMIT_SOH) data, not counted
80   in <len>, <check>, and not interpreted
81   there is generally at least one KERMIT_EOL
82*/
83
84typedef struct {
85
86   UINT8   pin[1024];     /* packet received */
87   UINT8   pout[1024];    /* packet sent */
88   UINT32  seq;           /* sequence number, starting at 0 */
89   UINT16  posin;         /* position in pin */
90   UINT16  posout;        /* position in pout */
91   UINT16  nbout;         /* size of pout */
92
93   UINT8   state;         /* current protocol state */
94   UINT8   retries;       /* packet retries remaining */
95
96   /* (relevant) configuration information, sent in S and D packet */
97   UINT8   maxl; /* max packet length (value of <len>) */
98   UINT8   npad; /* number of padding characters before packet */
99   UINT8   padc; /* padding character */
100   UINT8   eol;  /* character to add after packet */
101   UINT8   qctl; /* escape character */
102
103   emu_timer* resend;           /* auto-resend packet */
104
105   device_image_interface* image;  /* underlying image */
106
107   running_machine *machine;
108   kermit_config* conf;
109
110} kermit;
111
112
113INLINE kermit *get_safe_token(device_t *device)
114{
115   assert(device != NULL);
116   assert(device->type() == KERMIT);
117
118   return (kermit*)downcast<legacy_device_base *>(device)->token();
119}
120
121static int kermit_is_char( UINT8 data )
122{
123   return data >= 32 && data <= 126;
124}
125
126
127static  UINT8 kermit_tochar( UINT8 data )
128{
129   if ( data > 94 )
130   {
131      logerror( "kermit: tochar: %i not in the range 0-94\n", data );
132   }
133   return data + 32;
134}
135
136static UINT8 kermit_unchar( UINT8 data )
137{
138   if ( data < 32 || data > 126 )
139   {
140      logerror( "kermit: unchar: %i not in the range 32-126\n", data );
141   }
142   return data - 32;
143}
144
145#define kermit_ctl(x) ((x) ^ 0x40)
146
147static int kermit_is_ctl( UINT8 x )
148{
149   x &= 0x7f;
150   return (x < 32) || (x == 127);
151}
152
153static UINT8 kermit_checksum( UINT8* packet )
154{
155   int i, len = kermit_unchar( packet[1] );
156   UINT8 sum = 0;
157   for ( i = 0; i < len; i++ )
158      sum += packet[ i + 1 ];
159   sum = kermit_tochar( (sum + (sum >> 6)) & 63 );
160   return sum;
161}
162
163/* starts sending a new packet */
164static void kermit_start_sending( kermit* state )
165{
166   int i;
167
168   for (i=1;i<state->nbout;i++)
169      if (kermit_is_ctl(state->pout[i]))
170         logerror( "send: not char %i at pos %i\n", state->pout[i], i  );
171
172   if ( state->nbout <= 0 ) return;
173
174   /* prepend padding and append eol */
175   if ( state->npad > 0 )
176   {
177      memmove( state->pout + state->npad, state->pout, state->nbout );
178      memset( state->pout, state->padc, state->npad );
179      state->nbout += state->npad;
180   }
181   state->pout[ state->nbout ] = state->eol;
182   state->nbout++;
183
184   if ( state->conf && state->conf->send )
185   {
186      state->conf->send( *state->machine, state->pout[ 0 ] );
187   }
188   state->posout = 1;
189
190   state->retries = KERMIT_MAX_RETRIES;
191   state->resend->adjust( KERMIT_RETRY_DELAY, 0, KERMIT_RETRY_DELAY );
192}
193
194static void kermit_reset( kermit* state );
195
196static void kermit_resend( kermit* state )
197{
198   if ( state->conf && state->conf->send )
199   {
200      /* retry */
201      if ( state->nbout == 0 ) return;
202      if ( state->retries <= 0 )
203      {
204         kermit_reset( state );
205         return;
206      }
207
208      state->conf->send( *state->machine, state->pout[ 0 ] );
209
210      state->posout = 1;
211      state->retries--;
212      LOG(( "kermit: resend packet (%i tries left)\n", state->retries ));
213   }
214}
215
216/* resend packet periodically */
217static TIMER_CALLBACK( kermit_resend_cb )
218{
219   kermit* state = (kermit*) ptr;
220   if ( state->posout >= state->nbout)
221   {
222      kermit_resend( state );
223   }
224}
225
226/* fetches image data and wrap it into a kermit data packet */
227static void kermit_send_data_packet( kermit* state )
228{
229   int len;
230   LOG(( "kermit: send data packet\n" ));
231   for ( len = 2; len < state->maxl-2; len++ )
232   {
233      UINT8 c;
234      if ( state->image->image_feof() ) break;
235      c = state->image->fgetc();
236      if ( kermit_is_ctl( c ) )
237      {
238         /* escape control char */
239         state->pout[ 2 + len ] = state->qctl;
240         len++;
241         state->pout[ 2 + len ] = kermit_ctl( c );
242      }
243      else if ( (c & 0x7f) == state->qctl )
244      {
245         /* escape escape char */
246         state->pout[ 2 + len ] = state->qctl;
247         len++;
248         state->pout[ 2 + len ] = c;
249      }
250      else
251      {
252         state->pout[ 2 + len ] = c;
253      }
254   }
255   state->pout[ 0 ] = KERMIT_SOH;
256   state->pout[ 1 ] = kermit_tochar( len + 1 );
257   state->pout[ 2 ] = kermit_tochar( state->seq & 63 );
258   state->pout[ 3 ] = KERMIT_DATA;
259   state->pout[ 2 + len ] = kermit_checksum( state->pout );
260   state->nbout = len + 3;
261   kermit_start_sending( state );
262}
263
264/* write data from packet to the image */
265static void kermit_write_data_packet( kermit* state )
266{
267   int i, len = kermit_unchar( state->pin[1] );
268   LOG(( "kermit: received data pack, len=%i\n", len ));
269   for ( i = 4; i <= len; i++ )
270   {
271      UINT8 c = state->pin[i];
272      if ( (c /*& 0x7f*/) == state->qctl )
273      {
274         /* unescape */
275         i++;
276         c = state->pin[i];
277         if ( kermit_is_ctl( kermit_ctl( c ) ) )
278         {
279            c = kermit_ctl( c );
280         }
281      }
282      state->image->fwrite(&c, 1 );
283   }
284}
285
286/* validate received packet and acquire seq number, <0 if error */
287static int kermit_validate_packet( kermit* state )
288{
289   int len;
290   if ( state->pin[ 0 ] != KERMIT_SOH ) return -1;
291   if ( !kermit_is_char( state->pin[1] ) ) return -1;
292   if ( !kermit_is_char( state->pin[2] ) ) return -1;
293   len = kermit_unchar( state->pin[1] );
294   if ( state->pin[ 1 + len ] != kermit_checksum( state->pin ) ) return -1;
295   return 0;
296}
297
298/* interpret configuration packet, <0 if error */
299static int kermit_get_conf( kermit* state )
300{
301   int len = kermit_unchar( state->pin[1] );
302   if ( len >= 4 ) state->maxl = kermit_unchar( state->pin[ 4 ] );
303   if ( len >= 6 ) state->npad = kermit_unchar( state->pin[ 6 ] );
304   if ( len >= 7 ) state->padc = kermit_ctl( state->pin[ 7 ] );
305   if ( len >= 8 ) state->eol  = kermit_unchar( state->pin[ 8 ] );
306   if ( len >= 9 ) state->qctl = state->pin[ 9 ];
307
308   LOG(( "kermit: get conf: len=%i, maxl=%i, npad=%i, padc=%i, eol=%i, qctl=%i\n",
309         len, state->maxl, state->npad, state->padc, state->eol, state->qctl ));
310
311   /* validation */
312   if ( state->maxl < 10 || state->maxl > 94 ) return -1;
313   return 0;
314}
315
316/* create a configuration packet, with header h */
317static void kermit_send_conf_packet( kermit* state, UINT8 h )
318{
319   LOG(( "kermit: send conf packet of type %c\n", h ));
320   state->seq = 0;
321   state->pout[  0 ] = KERMIT_SOH;
322   state->pout[  1 ] = kermit_tochar( 13 );
323   state->pout[  2 ] = kermit_tochar( state->seq & 63 );
324   state->pout[  3 ] = h;
325   state->pout[  4 ] = kermit_tochar( state->maxl );   /* maxl */
326   state->pout[  5 ] = kermit_tochar( 1 );             /* time: 1 sec */
327   state->pout[  6 ] = kermit_tochar( state->npad );   /* npad */
328   state->pout[  7 ] = kermit_ctl( state->padc );      /* padc */
329   state->pout[  8 ] = kermit_tochar( state->eol );    /* eol */
330   state->pout[  9 ] = state->qctl;                    /* qtcl */
331   state->pout[ 10 ] = 'N';                            /* qbin: no 8-bit quoting */
332   state->pout[ 11 ] = '1';                            /* chkt: single character checksum */
333   state->pout[ 12 ] = ' ';                            /* rept: no repeat count */
334   state->pout[ 13 ] = kermit_tochar( 0 );             /* capas: no capabilities */
335   state->pout[ 14 ] = kermit_checksum( state->pout );
336   state->nbout = 15;
337   kermit_start_sending( state );
338}
339
340/* sends a packet with no data */
341static void kermit_send_simple_packet( kermit* state, UINT8 h  )
342{
343   LOG(( "kermit: send empty packet of type %c, seq=%i\n", h, state->seq & 63 ));
344   state->pout[ 0 ] = KERMIT_SOH;
345   state->pout[ 1 ] = kermit_tochar( 3 );
346   state->pout[ 2 ] = kermit_tochar( state->seq & 63 );
347   state->pout[ 3 ] = h;
348   state->pout[ 4 ] = kermit_checksum( state->pout );
349   state->nbout = 5;
350   kermit_start_sending( state );
351}
352
353/* sends a packet with string data */
354static void kermit_send_string_packet( kermit* state, UINT8 h, const char* data )
355{
356   int i, len;
357   LOG(( "kermit: send string packet of type %c, data=%s, seq=%i\n", h, data, state->seq & 63 ));
358   for ( len = i = 0; (len < state->maxl - 5) && data[i]; i++  )
359   {
360      char c = data[i];
361      if ( kermit_is_char( c ) && ( c != '_' ) && ( c != ' ' ) )
362      {
363         state->pout[ 4 + len ] = c;
364         len++;
365      }
366   }
367   state->pout[ 0 ] = KERMIT_SOH;
368   state->pout[ 1 ] = kermit_tochar( len + 3 );
369   state->pout[ 2 ] = kermit_tochar( state->seq & 63 );
370   state->pout[ 3 ] = h;
371   state->pout[ 4 + len ] = kermit_checksum( state->pout );
372   state->nbout = len + 5;
373   kermit_start_sending( state );
374}
375
376/* extract the string contained in received packet */
377static char* kermit_string_in_packet( kermit* state )
378{
379   int len = kermit_unchar( state->pin[1] );
380   state->pin[ len + 1 ] = 0;
381   return (char*) state->pin + 4;
382}
383
384static void kermit_reset( kermit* state )
385{
386   /* default config */
387   state->maxl = KERMIT_MAXL;
388   state->npad = 0;
389   state->padc = 0;
390   state->eol  = KERMIT_EOL;
391   state->qctl = KERMIT_QCTL;
392
393   state->retries = KERMIT_MAX_RETRIES;
394   state->posin   = 0;
395   state->posout  = 0;
396   state->nbout   = 0;
397   state->state   = KERMIT_IDLE;
398   state->seq     = 0;
399
400   if ( state->image )
401   {
402      state->image->fseek( SEEK_SET, 0 );
403   }
404
405   state->resend->adjust( attotime::never, 0, attotime::never );
406}
407
408
409/* emulated machine sends a byte to the outside (us) */
410void kermit_receive_byte( device_t *device, UINT8 data )
411{
412   kermit* state = get_safe_token(device);
413
414   LOG(( "get %i %2x %c (%i)\n", data, data, data, state->posin ));
415
416   /* get SOH */
417   if ( (data == KERMIT_SOH) && (state->posin <= 1) )
418   {
419      state->pin[ 0 ] = data;
420      state->posin = 1;
421   }
422
423   /* get packet contents */
424   else if ( state->posin > 0 )
425   {
426      if ( state->posin >= sizeof( state->pout ) )
427      {
428         LOG(( "kermit: too many bytes received\n" ));
429         state->posin = 0;
430         kermit_send_simple_packet( state, KERMIT_NAK );
431         return;
432      }
433
434      if (kermit_is_ctl(data))
435         logerror( "received: not char %i at pos %i\n", data, state->posin  );
436
437      state->pin[ state->posin ] = data;
438      state->posin++;
439
440      if ( state->posin > 5 )
441      {
442         int len, seq, typ;
443         if ( !kermit_is_char( state->pin[1] ) ||
444              (kermit_unchar( state->pin[1] ) < 3) ||
445              (kermit_unchar( state->pin[1] ) > state->maxl) )
446         {
447            LOG(( "kermit: invalid packet size %i-32, not in 3-%i\n", state->pin[1], state->maxl ));
448            kermit_resend( state );
449            return;
450         }
451
452         len = kermit_unchar( state->pin[1] );
453
454         if ( state->posin >= len + 2 )
455         {
456            /* got packet! */
457            state->posin = 0;
458            if ( kermit_validate_packet( state ) )
459            {
460               LOG(( "kermit: invalid packet\n" ));
461               kermit_resend( state );
462               return;
463            }
464
465            typ = state->pin[3];
466            seq = kermit_unchar( state->pin[2] );
467
468            LOG(( "kermit: received packet type=%c, seq=%i, len=%i\n",  typ, seq, len ));
469
470            if ( !state->image )
471            {
472               kermit_send_string_packet( state, KERMIT_ERR, "NO IMAGE" );
473               return;
474            }
475
476
477            switch ( typ )
478            {
479
480            /* receiving */
481
482            case KERMIT_SEND:
483               kermit_get_conf( state );
484               if ( state->maxl >= KERMIT_MAXL )
485               {
486                  state->maxl = KERMIT_MAXL;
487               }
488               kermit_send_conf_packet( state, KERMIT_ACK );
489               state->state = KERMIT_RECEIVE;
490               break;
491
492            case KERMIT_FILE:
493               LOG(( "kermit: got file name '%s'\n", kermit_string_in_packet( state ) ));
494               state->seq = seq;
495               kermit_send_simple_packet( state, KERMIT_ACK );
496               break;
497
498            case KERMIT_DATA:
499            case KERMIT_EOF:
500               if ( seq == ((state->seq + 1) & 63) )
501               {
502                  /* next packet */
503                  if ( typ == KERMIT_DATA )
504                  {
505                     kermit_write_data_packet( state );
506                  }
507                  state->seq = seq;
508                  kermit_send_simple_packet( state, KERMIT_ACK );
509               }
510               else if ( seq == (state->seq & 63) )
511               {
512                  /* same packet */
513                  kermit_send_simple_packet( state, KERMIT_ACK );
514               }
515               else
516               {
517                  /* unexpected sequence number */
518                  LOG(( "kermit: got seq=%i, expected %i\n", seq, (state->seq + 1) & 63 ));
519                  state->seq++;
520                  kermit_send_simple_packet( state, KERMIT_NAK );
521                  state->seq--;
522               }
523               break;
524
525            case KERMIT_EOT:
526               /* send ack and reset */
527               state->seq = seq;
528               kermit_send_simple_packet( state, KERMIT_ACK );
529               state->state = KERMIT_RESET;
530               break;
531
532
533                                /* sending */
534
535            case KERMIT_NAK:
536            case KERMIT_ACK:
537
538               if ( (typ == KERMIT_NAK) && (seq == 0) && (state->state == KERMIT_IDLE) )
539               {
540                  /* transfer start */
541                  kermit_send_conf_packet( state, KERMIT_SEND );
542                  break;
543               }
544
545               if ( ((seq == (state->seq & 63)) && (typ == KERMIT_ACK)) ||
546                    ((seq == ((state->seq + 1) & 63)) && (typ == KERMIT_NAK)) )
547               {
548                  /* send next packet */
549
550                  state->seq = state->seq + 1;
551
552                  switch ( state->state )
553                  {
554                  case KERMIT_IDLE:
555                     /* get conf & send file name */
556                     kermit_get_conf( state );
557                     kermit_send_string_packet( state, KERMIT_FILE, state->image->basename() );
558                     state->state = KERMIT_SEND_DATA;
559                     break;
560
561                  case KERMIT_SEND_DATA:
562                     /* send next data packet or EOF */
563                     if ( state->image->image_feof() )
564                     {
565                        kermit_send_simple_packet( state, KERMIT_EOF );
566                        state->state = KERMIT_SEND_EOF;
567                     }
568                     else
569                     {
570                        kermit_send_data_packet( state );
571                     }
572                     break;
573
574                  case KERMIT_SEND_EOF:
575                          /* send EOT */
576                     kermit_send_simple_packet( state, KERMIT_EOT );
577                     state->state = KERMIT_SEND_EOT;
578                     break;
579
580                  case KERMIT_SEND_EOT:
581                     /* reset */
582                     kermit_reset( state );
583                     state->state = KERMIT_RESET;
584                     break;
585
586                  }
587               }
588
589               else if ( (seq == (state->seq & 63)) && (typ == KERMIT_NAK) )
590               {
591                  /* resend last packet */
592                  kermit_resend( state );
593               }
594               else
595               {
596                  /* bad */
597                  LOG(( "kermit: expected to send %i, got seq=%i\n", (state->seq + 1) & 63, seq ));
598                  kermit_reset( state );
599               }
600               break;
601
602                                /* errors */
603
604            case KERMIT_ERR:
605               LOG(( "kermit: got error '%s'\n", kermit_string_in_packet( state ) ));
606               state->seq = seq;
607               kermit_reset( state );
608               break;
609
610            default:
611               LOG(( "kermit: ignoring packet type %c\n", state->pin[ 3 ] ));
612               /* no abort, just ignoring */
613            }
614         }
615      }
616   }
617}
618
619void kermit_byte_transmitted( device_t *device )
620{
621   kermit* state = get_safe_token(device);
622
623   LOG(( "transmitted %i %2x %c, %i / %i\n", state->pout[ state->posout-1 ], state->pout[ state->posout-1 ], state->pout[ state->posout-1 ], state->posout - 1, state->nbout - 1 ));
624
625   /* at end of packet */
626   if ( state->posout >= state->nbout )
627   {
628      if ( state->state == KERMIT_RESET )
629      {
630         kermit_reset( state );
631      }
632      return;
633   }
634
635   if ( state->conf && state->conf->send )
636   {
637      state->conf->send(*state->machine, state->pout[ state->posout ] );
638   }
639   state->posout++;
640}
641
642static DEVICE_START( kermit )
643{
644   kermit* state = get_safe_token(device);
645   LOG(( "kermit: start\n" ));
646   state->image = NULL;
647   state->conf = (kermit_config*) device->static_config();
648   state->machine = &device->machine();
649   state->resend = device->machine().scheduler().timer_alloc(FUNC(kermit_resend_cb), state );
650   kermit_reset( state );
651}
652
653static DEVICE_RESET( kermit )
654{
655   kermit* state = get_safe_token(device);
656   LOG(( "kermit: reset\n" ));
657   kermit_reset( state );
658}
659
660static DEVICE_IMAGE_LOAD( kermit )
661{
662   kermit* state = get_safe_token(&image.device());
663   LOG(( "kermit: image load\n" ));
664   state->image = &image;
665   kermit_reset( state );
666   return IMAGE_INIT_PASS;
667}
668
669static DEVICE_IMAGE_CREATE( kermit )
670{
671   kermit* state = get_safe_token(&image.device());
672   LOG(( "kermit: image create\n" ));
673   state->image = &image;
674   kermit_reset( state );
675   return IMAGE_INIT_PASS;
676}
677
678static DEVICE_IMAGE_UNLOAD( kermit )
679{
680   kermit* state = get_safe_token(&image.device());
681   LOG(( "kermit: image unload\n" ));
682   state->image = NULL;
683   kermit_reset( state );
684}
685
686DEVICE_GET_INFO( kermit )
687
688{
689   switch ( state ) {
690   case DEVINFO_INT_TOKEN_BYTES:               info->i = sizeof( kermit );                              break;
691   case DEVINFO_INT_INLINE_CONFIG_BYTES:       info->i = 0;                                             break;
692   case DEVINFO_INT_IMAGE_TYPE:               info->i = IO_SERIAL;                                     break;
693   case DEVINFO_INT_IMAGE_READABLE:            info->i = 1;                                             break;
694   case DEVINFO_INT_IMAGE_WRITEABLE:       info->i = 1;                                             break;
695   case DEVINFO_INT_IMAGE_CREATABLE:       info->i = 1;                                             break;
696   case DEVINFO_FCT_START:                       info->start = DEVICE_START_NAME( kermit );               break;
697   case DEVINFO_FCT_RESET:                       info->reset = DEVICE_RESET_NAME( kermit );               break;
698   case DEVINFO_FCT_IMAGE_LOAD:          info->f = (genf *) DEVICE_IMAGE_LOAD_NAME( kermit );     break;
699   case DEVINFO_FCT_IMAGE_UNLOAD:          info->f = (genf *) DEVICE_IMAGE_UNLOAD_NAME( kermit );   break;
700   case DEVINFO_FCT_IMAGE_CREATE:          info->f = (genf *) DEVICE_IMAGE_CREATE_NAME( kermit );   break;
701   case DEVINFO_STR_IMAGE_BRIEF_INSTANCE_NAME: strcpy(info->s, "k");                                        break;
702   case DEVINFO_STR_IMAGE_INSTANCE_NAME:
703   case DEVINFO_STR_NAME:                  strcpy(info->s, "Kermit");                                        break;
704   case DEVINFO_STR_FAMILY:                    strcpy(info->s, "Serial protocol");                        break;
705   case DEVINFO_STR_SOURCE_FILE:          strcpy(info->s, __FILE__);                                      break;
706   case DEVINFO_STR_IMAGE_FILE_EXTENSIONS:       strcpy(info->s, "");                                            break;
707   }
708}
709
710DEFINE_LEGACY_IMAGE_DEVICE(KERMIT, kermit);
trunk/src/mess/audio/ted7360.c
r17575r17576
1/***************************************************************************
2
3    TExt Display 7360
4    PeT mess@utanet.at
5
6
7    2010-02: Converted to be a device and merged video/audio emulation
8
9    TODO:
10      - Plenty of clean-ups
11
12***************************************************************************/
13/*
14Metal Oxid Semicontuctor MOS
15Commodore Business Machine CBM
16Textured Display Ted7360
17------------------------
18
197360/8360 (NTSC-M, PAL-B by same chip ?)
208365 PAL-N
218366 PAL-M
22
23Ted7360 used in Commodore C16
24Ted8360 used in Commodore C116/Plus4
25 should be 100% software compatible with Ted7360
26
27video unit (without sprites), dram controller seams to be much like vic6567
28
29PAL/NTSC variants
30
31functions of this chip:
32 memory controller
33 dram controller
34 cpu clock generation with single and double clock switching
35 3 timer
36 1 8bit latched input
37 2 channel sound/noise generator
38 video controller
39 interrupt controller for timer and video
40
41Reasons for this document:
42 document state in mess c16/plus4 emulator
43 base to discuss ted7360 with others (i have no c16 computer anymore)
44
45pal:
46 clock 17734470
47 divided by 5 for base clock (pixel clock changing edges?)
48 312 lines
49 50 hertz vertical refresh
50
51ntsc:
52 clock 14318180
53 divided by 4 for base clock (pixel clock changing edges?)
54 262 lines
55 60 hertz vertical refresh
56
57registers:
58 0xff00 timer 1 low byte
59 0xff01 timer 1 high byte
60 0xff02 timer 2 low byte
61 0xff03 timer 2 high byte
62 0xff04 timer 3 low byte
63 0xff05 timer 3 high byte
64 0xff06
65  bit 7 test?
66  bit 6 ecm on
67  bit 5 hires on
68  bit 4 screen on
69  bit 3 25 raws (0 24 raws)
70  bit 2-0 vertical position
71 0xff07
72  bit 7 reverse off (0 on)
73  bit 6 read only NTSC (0 PAL)
74  bit 5 freeze horicontal position?
75  bit 4 multicolor on
76  bit 3 40 columns (0 38 columns)
77  bit 2-0 horicontal pos
78 0xff08 input latch (0 input low), write reloads latch
79 0xff09 interrupt request
80  7: interrupt
81  6: timer 3
82  5: ?
83  4: timer 2
84  3: timer 1
85  2: lightpen
86  1: rasterline
87  0: 1 (asl quitting)
88 0xff0a interrupt enable
89  7: ?
90  6: timer 3
91  5: ?
92  4: timer 2
93  3: timer 1
94  2: lightpen
95  1: rasterline
96  0: irq rasterline bit 8
97 0xff0b
98  7-0: irq rasterline 7-0
99 0xff0c
100  7-2: 1?
101  1,0: cursorpos bit 9,8
102 0xff0d cursorpos bit 7-0
103 0xff0e tone channel 1: frequency 7-0
104 0xff0f tone channel 2: frequency 7-0
105 0xff10
106  7-2: ?
107  1,0: tone channel 2 bit 9,8
108 0xff11
109  7: sound reload
110  6: tone 2 noise on (tone 2 must be off for noise)
111  5: tone 2 tone on
112  4: tone 1 on
113  3-0: volume 8?-0
114 0xff12
115  7,6: ?
116  5-3: bitmap address bit 15-13
117  2: bitmapmemory?, charactermemory in rom (0 ram)
118  1,0: tone 1 frequency bit 9,8
119 0xff13
120  7-2: chargen address bit 15-11
121  2: chargen address bit 10 (only used when reverse is off)
122  1: single clock in overscan area (0 double clock)
123  0: ram (0)/rom status
124 0xff14
125  7-2: video address bit 15-10
126  1,0: ?
127 0xff15
128  7: ?
129  6-0: backgroundcolor
130 0xff16
131  7: ?
132  6-0: color1
133 0xff17
134  7: ?
135  6-0: color2
136 0xff18
137  7: ?
138  6-0: color3
139 0xff19
140  7: ?
141  6-0: framecolor
142 0xff1a
143  7-2: ?
144  1,0: bitmap reload(cursorpos2) bit 9-8
145 0xff1b bitmap reload bit 7-0
146 0xff1c
147  7-1: 1? (matrix expects this)
148  0: current rasterline bit 8
149 0xff1d current rasterline bit 7-0
150 0xff1e
151  7-0: current rastercolumn /2 (0 begin visible area?)
152 0xff1f cursorblink?
153  7: ?
154  6-3: blink counter
155  2-0: vsub
156 0xff3e write switches to rom
157 0xff3f write switches to dram
158
159memory controller
160 0x8000-0xfcff, 0xff20-0xffff
161  read selection between dram and rom
162 0xff3e-0xff3f write nothing (would change main memory in 16k ram c16)
163
164clock generator
165 in displayed area ted need 3 memory cycles to get data for video chip
166 memory system runs at approximately 4 megahertz
167 so only 1 megahertz is available for the cpu
168 in the other area the clock can be doubled for the cpu
169
170dram controller
171 generator of refresh cycles
172 when are these occuring?
173 vic6567 in each rasterline reads 5 refresh addresses
174
175sound generator
176 2 channels
177 channel 2 can be switched to generate noise
178 volume control (0-8?)
179 tone reload bit?
180 samples ton/noise?
181 frequency=(base clock/32)/(1024-value)
182
183timer
184 timer count down
185 when reaching 0
186  they restart from 0xffff
187  set the interrupt request flag
188 writing to low byte stops timer
189 writing to high byte restarts timer with current value
190
191interrupt controller
192 interrupt sources must be enabled in the enable register to generate
193 an interrupt
194 request flag are set also when not enabled
195 interrupt is generated when rising edge on request and enable
196 quitting of interrupt is done via writing 1 to the request bit
197 what happens with request interrupts when the are enabled?
198
199Video part
200 colors
201  bit 3-0 color
202   black, white, red, cyan
203   purple, green, blue, yellow
204   orange, light orange, pink, light cyan,
205   light violett, light green, light blue, light yellow
206  bit 6-4 luminance (0 dark)
207  r,g,b values from 0 to 127
208   taken from digitized tv screen shot
209   0x06,0x01,0x03, 0x2b,0x2b,0x2b, 0x67,0x0e,0x0f, 0x00,0x3f,0x42,
210   0x57,0x00,0x6d, 0x00,0x4e,0x00, 0x19,0x1c,0x94, 0x38,0x38,0x00,
211   0x56,0x20,0x00, 0x4b,0x28,0x00, 0x16,0x48,0x00, 0x69,0x07,0x2f,
212   0x00,0x46,0x26, 0x06,0x2a,0x80, 0x2a,0x14,0x9b, 0x0b,0x49,0x00,
213
214   0x00,0x03,0x02, 0x3d,0x3d,0x3d, 0x75,0x1e,0x20, 0x00,0x50,0x4f,
215   0x6a,0x10,0x78, 0x04,0x5c,0x00, 0x2a,0x2a,0xa3, 0x4c,0x47,0x00,
216   0x69,0x2f,0x00, 0x59,0x38,0x00, 0x26,0x56,0x00, 0x75,0x15,0x41,
217   0x00,0x58,0x3d, 0x15,0x3d,0x8f, 0x39,0x22,0xae, 0x19,0x59,0x00,
218
219   0x00,0x03,0x04, 0x42,0x42,0x42, 0x7b,0x28,0x20, 0x02,0x56,0x59,
220   0x6f,0x1a,0x82, 0x0a,0x65,0x09, 0x30,0x34,0xa7, 0x50,0x51,0x00,
221   0x6e,0x36,0x00, 0x65,0x40,0x00, 0x2c,0x5c,0x00, 0x7d,0x1e,0x45,
222   0x01,0x61,0x45, 0x1c,0x45,0x99, 0x42,0x2d,0xad, 0x1d,0x62,0x00,
223
224   0x05,0x00,0x02, 0x56,0x55,0x5a, 0x90,0x3c,0x3b, 0x17,0x6d,0x72,
225   0x87,0x2d,0x99, 0x1f,0x7b,0x15, 0x46,0x49,0xc1, 0x66,0x63,0x00,
226   0x84,0x4c,0x0d, 0x73,0x55,0x00, 0x40,0x72,0x00, 0x91,0x33,0x5e,
227   0x19,0x74,0x5c, 0x32,0x59,0xae, 0x59,0x3f,0xc3, 0x32,0x76,0x00,
228
229   0x02,0x01,0x06, 0x84,0x7e,0x85, 0xbb,0x67,0x68, 0x45,0x96,0x96,
230   0xaf,0x58,0xc3, 0x4a,0xa7,0x3e, 0x73,0x73,0xec, 0x92,0x8d,0x11,
231   0xaf,0x78,0x32, 0xa1,0x80,0x20, 0x6c,0x9e,0x12, 0xba,0x5f,0x89,
232   0x46,0x9f,0x83, 0x61,0x85,0xdd, 0x84,0x6c,0xef, 0x5d,0xa3,0x29,
233
234   0x02,0x00,0x0a, 0xb2,0xac,0xb3, 0xe9,0x92,0x92, 0x6c,0xc3,0xc1,
235   0xd9,0x86,0xf0, 0x79,0xd1,0x76, 0x9d,0xa1,0xff, 0xbd,0xbe,0x40,
236   0xdc,0xa2,0x61, 0xd1,0xa9,0x4c, 0x93,0xc8,0x3d, 0xe9,0x8a,0xb1,
237   0x6f,0xcd,0xab, 0x8a,0xb4,0xff, 0xb2,0x9a,0xff, 0x88,0xcb,0x59,
238
239   0x02,0x00,0x0a, 0xc7,0xca,0xc9, 0xff,0xac,0xac, 0x85,0xd8,0xe0,
240   0xf3,0x9c,0xff, 0x92,0xea,0x8a, 0xb7,0xba,0xff, 0xd6,0xd3,0x5b,
241   0xf3,0xbe,0x79, 0xe6,0xc5,0x65, 0xb0,0xe0,0x57, 0xff,0xa4,0xcf,
242   0x89,0xe5,0xc8, 0xa4,0xca,0xff, 0xca,0xb3,0xff, 0xa2,0xe5,0x7a,
243
244   0x01,0x01,0x01, 0xff,0xff,0xff, 0xff,0xf6,0xf2, 0xd1,0xff,0xff,
245   0xff,0xe9,0xff, 0xdb,0xff,0xd3, 0xfd,0xff,0xff, 0xff,0xff,0xa3,
246   0xff,0xff,0xc1, 0xff,0xff,0xb2, 0xfc,0xff,0xa2, 0xff,0xee,0xff,
247   0xd1,0xff,0xff, 0xeb,0xff,0xff, 0xff,0xf8,0xff, 0xed,0xff,0xbc
248
249 video generation
250  column counter from 0 to 39
251  line counter from 0 to 199
252
253  character pointer position/hires: color 0-15 position
254   videoaddr+0x400+(line/8)*40+column
255  color position/hires: color luminance position
256   videoaddr+(line/8)*40+column
257  character bitmap position
258   chargenaddr+(character pointer)+(line&7)
259  bitmap position
260   bitmapaddr+(line/8)*40+column+(line&7)
261
262 normal text mode (reverse off, ecm off, multicolor off, hires off)
263  character pointer based
264   fetch character pointer, fetch character bitmap, fetch color
265  pixel on color (color)&0x7f
266  pixel off color backgroundcolor
267  blinking (synchron to cursor) (color&0x80)
268 reverse text mode (reverse on, ecm off, multicolor off, hires off)
269  character pointer &0x7f
270  character pointer bit 7
271   set
272    pixel off color attribut &0x7f
273    pixel on color backgroundcolor
274   clear
275    like normal text mode
276  blinking (synchron to cursor) (color&0x80)
277 multicolor text mode (ecm off, multicolor on, hires off)
278  reverse ?
279  attribut bit 3 character in multicolor (else monocolor character)
280  pixel on color attribut 0x77
281  0 backgroundcolor
282  1 color1
283  2 color2
284  3 attribut &0x77
285  (color&0x80) ?
286 ecm text mode (ecm on)
287  reverse ?
288  multicolor ? (c64/vic6567 black display?)
289  hires ? (c64/vic6567 black display?)
290  character pointer &0x3f
291  character pointer bit 7,6 select pixel off color
292   0 backgroundcolor ?
293   1 color1?
294   2 color2?
295   3 color3?
296  (color&0x80)?
297 hires (ecm off, multicolor off, hires on)
298  bitmap based
299   fetch bitmap, fetch color, fetch color luminance
300  reverse ?
301  pixel on color
302   6-4: (color luminance) bit 2-0
303   3-0: (color) bit 7-4
304  pixel off color
305   6-4: (color luminance) bit 6-4
306   3-0: (color) bit 3-0
307  (color) bit 7?
308  (color luminance) bit 7?
309 hires multicolor (ecm off, multicolor on, hires on)
310  reverse ?
311  0 backgroundcolor
312  1
313   6-4: (color luminance) bit 2-0
314   3-0: (color) bit 7-4
315  2
316   6-4: (color luminance) bit 6-4
317   3-0: (color) bit 3-0
318  3 color1
319  (color) bit 7?
320  (color luminance) bit 7?
321 scrolling support
322  visible part of the display in fixed position
323  columns 38 mode left 7 and right 9 pixel less displayed
324   but line generation start at the same position as in columns 40 mode
325  lines25 flag top and bottom 4 pixel less displayed ?
326  horicontal scrolling support
327   in columns 38 mode
328    horicontal position 1-7: pixel later started line generation
329    horicontal position 0: 8 pixels later started line generation
330   in columns 40 mode ?
331  vertical scrolling support
332   in lines 24 mode
333    vertical position 1-7: lines later started line generation
334    vertical position 0: 8 lines later started line generation
335   in lines 25 mode?
336    vertial position 3: for correct display
337
338 hardware cursor
339  full 8x8 in (color) color
340  flashing when in multicolor, hires ?
341  flashes with about 1 hertz
342  bitmap reload?
343
344 rasterline/rastercolumn
345  values in registers begin visible area 0
346  vic 6567
347   pal line 0 beginning of vertical refresh
348   ntsc line 0 in bottom frame
349    beginning of 25 lines screen 0x33 (24 lines screen 0x37)
350    beginning of 40 columns line 0x18 (38 columns 0x1f)
351
352 lightpen
353  (where to store values?)
354  i found a lightpen hardware description with a demo and drawing program
355  lightpen must be connected to joy0 (button)
356  demo program:
357   disables interrupt, polles joy0 button (0xfd0d? plus 4 related???)
358   and reads the rasterline value!
359   so i no exact column value reachable!
360*/
361#include "emu.h"
362#include "audio/ted7360.h"
363
364
365typedef struct _ted7360_state ted7360_state;
366struct _ted7360_state
367{
368   ted_type  type;
369
370   screen_device *screen;         // screen which sets bitmap properties
371
372   UINT8 reg[0x20];
373
374   bitmap_ind16 *bitmap;
375
376   int rom;
377
378   int frame_count;
379
380   int lines;
381   int timer1_active, timer2_active, timer3_active;
382   emu_timer *timer1, *timer2, *timer3;
383   int cursor1;
384
385   ted7360_dma_read         dma_read;
386   ted7360_dma_read_rom     dma_read_rom;
387   ted7360_irq              interrupt;      // c16_interrupt
388   ted7360_key_cb           keyboard_cb;   // c16_read_keyboard
389
390   int chargenaddr, bitmapaddr, videoaddr;
391
392   int x_begin, x_end;
393   int y_begin, y_end;
394
395   UINT16 c16_bitmap[2], bitmapmulti[4], mono[2], monoinversed[2], multi[4], ecmcolor[2], colors[5];
396
397   int rasterline, lastline;
398   double rastertime;
399
400
401   /* sound part */
402   int tone1pos, tone2pos,
403   tone1samples, tone2samples,
404   noisesize,        /* number of samples */
405   noisepos,         /* pos of tone */
406   noisesamples;     /* count of samples to give out per tone */
407
408   sound_stream *channel;
409   UINT8 *noise;
410};
411
412/*****************************************************************************
413    CONSTANTS
414*****************************************************************************/
415
416
417#define VERBOSE_LEVEL 0
418#define DBG_LOG(N,M,A) \
419   do { \
420      if(VERBOSE_LEVEL >= N) \
421      { \
422         if( M ) \
423            logerror("%11.6f: %-24s", device->machine().time().as_double(), (char*) M ); \
424         logerror A; \
425      } \
426   } while(0)
427
428
429#define VREFRESHINLINES 28
430
431#define TIMER1HELPER (ted7360->reg[0] | (ted7360->reg[1] << 8))
432#define TIMER2HELPER (ted7360->reg[2] | (ted7360->reg[3] << 8))
433#define TIMER3HELPER (ted7360->reg[4] | (ted7360->reg[5] << 8))
434#define TIMER1 (TIMER1HELPER ? TIMER1HELPER : 0x10000)
435#define TIMER2 (TIMER2HELPER ? TIMER2HELPER : 0x10000)
436#define TIMER3 (TIMER3HELPER ? TIMER3HELPER : 0x10000)
437
438#define TED7360_YPOS            40
439#define RASTERLINE_2_C16(a)    ((a + ted7360->lines - TED7360_YPOS - 5) % ted7360->lines)
440#define C16_2_RASTERLINE(a)    ((a + TED7360_YPOS + 5) % ted7360->lines)
441#define XPOS 8
442#define YPOS 8
443
444#define SCREENON               (ted7360->reg[6] & 0x10)
445#define TEST                   (ted7360->reg[6] & 0x80)
446#define VERTICALPOS            (ted7360->reg[6] & 0x07)
447#define HORICONTALPOS          (ted7360->reg[7] & 0x07)
448#define ECMON                  (ted7360->reg[6] & 0x40)
449#define HIRESON                (ted7360->reg[6] & 0x20)
450#define MULTICOLORON           (ted7360->reg[7] & 0x10)
451#define REVERSEON              (!(ted7360->reg[7] & 0x80))
452
453/* hardware inverts character when bit 7 set (character taken &0x7f) */
454/* instead of fetching character with higher number! */
455#define LINES25     (ted7360->reg[6] & 0x08)     /* else 24 Lines */
456#define LINES       (LINES25 ? 25 : 24)
457#define YSIZE       (LINES * 8)
458#define COLUMNS40   (ted7360->reg[7] & 0x08)     /* else 38 Columns */
459#define COLUMNS     (COLUMNS40 ? 40 : 38)
460#define XSIZE       (COLUMNS * 8)
461
462#define INROM       (ted7360->reg[0x12] & 0x04)
463#define CHARGENADDR (REVERSEON && !HIRESON && !MULTICOLORON ? ((ted7360->reg[0x13] & 0xfc) << 8) : ((ted7360->reg[0x13] & 0xf8) << 8))
464#define BITMAPADDR  ((ted7360->reg[0x12] & 0x38) << 10)
465#define VIDEOADDR   ((ted7360->reg[0x14] & 0xf8) << 8)
466
467#define RASTERLINE  (((ted7360->reg[0xa] & 0x01) << 8) | ted7360->reg[0xb])
468#define CURSOR1POS  (ted7360->reg[0xd] | ((ted7360->reg[0xc] & 0x03) << 8))
469#define CURSOR2POS  (ted7360->reg[0x1b] | ((ted7360->reg[0x1a] & 0x03) << 8))
470#define CURSORRATE  ((ted7360->reg[0x1f] & 0x7c) >> 2)
471
472#define BACKGROUNDCOLOR (ted7360->reg[0x15] & 0x7f)
473#define FOREGROUNDCOLOR (ted7360->reg[0x16] & 0x7f)
474#define MULTICOLOR1     (ted7360->reg[0x17] & 0x7f)
475#define MULTICOLOR2     (ted7360->reg[0x18] & 0x7f)
476#define FRAMECOLOR      (ted7360->reg[0x19] & 0x7f)
477
478#define TED7360_VRETRACERATE ((ted7360->type == TED7360_PAL) ? TED7360PAL_VRETRACERATE : TED7360NTSC_VRETRACERATE)
479#define TED7360_CLOCK        (((ted7360->type == TED7360_PAL) ? TED7360PAL_CLOCK : TED7360NTSC_CLOCK) / 4)
480#define TED7360_LINES        ((ted7360->type == TED7360_PAL) ? TED7360PAL_LINES : TED7360NTSC_LINES)
481
482static attotime TEDTIME_IN_CYCLES(int pal, int cycles)
483{
484   double d = (double)(cycles) / (pal ? TED7360PAL_CLOCK : TED7360NTSC_CLOCK);
485   return attotime::from_double(d);
486}
487
488static int TEDTIME_TO_CYCLES(int pal, attotime t)
489{
490   double d = t.as_double();
491   return (int)((d) * (pal ? TED7360PAL_CLOCK : TED7360NTSC_CLOCK));
492}
493
494/*****************************************************************************
495    INLINE FUNCTIONS
496*****************************************************************************/
497
498INLINE ted7360_state *get_safe_token( device_t *device )
499{
500   assert(device != NULL);
501   assert(device->type() == TED7360);
502
503   return (ted7360_state *)downcast<legacy_device_base *>(device)->token();
504}
505
506INLINE const ted7360_interface *get_interface( device_t *device )
507{
508   assert(device != NULL);
509   assert(device->type() == TED7360);
510
511   return (const ted7360_interface *) device->static_config();
512}
513
514/*****************************************************************************
515    IMPLEMENTATION
516*****************************************************************************/
517
518static void ted7360_soundport_w( device_t *device, int offset, int data );
519
520static void ted7360_set_interrupt( running_machine &machine, int mask, ted7360_state *ted7360 )
521{
522   /* kernel itself polls for timer 2 shot (interrupt disabled!) when cassette loading */
523   ted7360->reg[9] |= mask;
524   if ((ted7360->reg[0xa] & ted7360->reg[9] & 0x5e))
525   {
526      if (!(ted7360->reg[9] & 0x80))
527      {
528         //DBG_LOG(1, "ted7360", ("irq start %.2x\n", mask));
529         ted7360->reg[9] |= 0x80;
530         ted7360->interrupt(machine, 1);
531      }
532   }
533   ted7360->reg[9] |= mask;
534}
535
536static void ted7360_clear_interrupt( device_t *device, int mask )
537{
538   ted7360_state *ted7360 = get_safe_token(device);
539
540   ted7360->reg[9] &= ~mask;
541   if ((ted7360->reg[9] & 0x80) && !(ted7360->reg[9] & ted7360->reg[0xa] & 0x5e))
542   {
543      DBG_LOG(1, "ted7360", ("irq end %.2x\n", mask));
544      ted7360->reg[9] &= ~0x80;
545      ted7360->interrupt(device->machine(), 0);
546   }
547}
548
549static int ted7360_rastercolumn( device_t *device )
550{
551   ted7360_state *ted7360 = get_safe_token(device);
552   return (int) ((device->machine().time().as_double() - ted7360->rastertime) * TED7360_VRETRACERATE * ted7360->lines * 57 * 8 + 0.5);
553}
554
555static TIMER_CALLBACK(ted7360_timer_timeout)
556{
557   ted7360_state *ted7360 = (ted7360_state *)ptr;
558   int which = param;
559
560   //DBG_LOG(3, "ted7360 ", ("timer %d timeout\n", which));
561   switch (which)
562   {
563   case 1:
564      // proved by digisound of several intros like eoroidpro
565      ted7360->timer1->adjust(TEDTIME_IN_CYCLES((ted7360->type == TED7360_PAL), TIMER1), 1);
566      ted7360->timer1_active = 1;
567      ted7360_set_interrupt(machine, 0x08, ted7360);
568      break;
569   case 2:
570      ted7360->timer2->adjust(TEDTIME_IN_CYCLES((ted7360->type == TED7360_PAL), 0x10000), 2);
571      ted7360->timer2_active = 1;
572      ted7360_set_interrupt(machine, 0x10, ted7360);
573      break;
574   case 3:
575      ted7360->timer3->adjust(TEDTIME_IN_CYCLES((ted7360->type == TED7360_PAL), 0x10000), 3);
576      ted7360->timer3_active = 1;
577      ted7360_set_interrupt(machine, 0x40, ted7360);
578      break;
579   }
580}
581
582static void ted7360_draw_character( device_t *device, int ybegin, int yend, int ch, int yoff, int xoff, UINT16 *color )
583{
584   ted7360_state *ted7360 = get_safe_token(device);
585   int y, code;
586
587   for (y = ybegin; y <= yend; y++)
588   {
589      if (INROM)
590         code = ted7360->dma_read_rom(device->machine(), ted7360->chargenaddr + ch * 8 + y);
591      else
592         code = ted7360->dma_read(device->machine(), ted7360->chargenaddr + ch * 8 + y);
593
594      ted7360->bitmap->pix16(y + yoff, 0 + xoff) = color[code >> 7];
595      ted7360->bitmap->pix16(y + yoff, 1 + xoff) = color[(code >> 6) & 1];
596      ted7360->bitmap->pix16(y + yoff, 2 + xoff) = color[(code >> 5) & 1];
597      ted7360->bitmap->pix16(y + yoff, 3 + xoff) = color[(code >> 4) & 1];
598      ted7360->bitmap->pix16(y + yoff, 4 + xoff) = color[(code >> 3) & 1];
599      ted7360->bitmap->pix16(y + yoff, 5 + xoff) = color[(code >> 2) & 1];
600      ted7360->bitmap->pix16(y + yoff, 6 + xoff) = color[(code >> 1) & 1];
601      ted7360->bitmap->pix16(y + yoff, 7 + xoff) = color[code & 1];
602   }
603}
604
605static void ted7360_draw_character_multi( device_t *device, int ybegin, int yend, int ch, int yoff, int xoff )
606{
607   ted7360_state *ted7360 = get_safe_token(device);
608   int y, code;
609
610   for (y = ybegin; y <= yend; y++)
611   {
612      if (INROM)
613         code = ted7360->dma_read_rom(device->machine(), ted7360->chargenaddr + ch * 8 + y);
614      else
615         code = ted7360->dma_read(device->machine(), ted7360->chargenaddr + ch * 8 + y);
616
617      ted7360->bitmap->pix16(y + yoff, 0 + xoff) =
618         ted7360->bitmap->pix16(y + yoff, 1 + xoff) = ted7360->multi[code >> 6];
619      ted7360->bitmap->pix16(y + yoff, 2 + xoff) =
620         ted7360->bitmap->pix16(y + yoff, 3 + xoff) = ted7360->multi[(code >> 4) & 3];
621      ted7360->bitmap->pix16(y + yoff, 4 + xoff) =
622         ted7360->bitmap->pix16(y + yoff, 5 + xoff) = ted7360->multi[(code >> 2) & 3];
623      ted7360->bitmap->pix16(y + yoff, 6 + xoff) =
624         ted7360->bitmap->pix16(y + yoff, 7 + xoff) = ted7360->multi[code & 3];
625   }
626}
627
628static void ted7360_draw_bitmap( device_t *device, int ybegin, int yend, int ch, int yoff, int xoff )
629{
630   ted7360_state *ted7360 = get_safe_token(device);
631   int y, code;
632
633   for (y = ybegin; y <= yend; y++)
634   {
635      code = ted7360->dma_read(device->machine(), ted7360->bitmapaddr + ch * 8 + y);
636      ted7360->bitmap->pix16(y + yoff, 0 + xoff) = ted7360->c16_bitmap[code >> 7];
637      ted7360->bitmap->pix16(y + yoff, 1 + xoff) = ted7360->c16_bitmap[(code >> 6) & 1];
638      ted7360->bitmap->pix16(y + yoff, 2 + xoff) = ted7360->c16_bitmap[(code >> 5) & 1];
639      ted7360->bitmap->pix16(y + yoff, 3 + xoff) = ted7360->c16_bitmap[(code >> 4) & 1];
640      ted7360->bitmap->pix16(y + yoff, 4 + xoff) = ted7360->c16_bitmap[(code >> 3) & 1];
641      ted7360->bitmap->pix16(y + yoff, 5 + xoff) = ted7360->c16_bitmap[(code >> 2) & 1];
642      ted7360->bitmap->pix16(y + yoff, 6 + xoff) = ted7360->c16_bitmap[(code >> 1) & 1];
643      ted7360->bitmap->pix16(y + yoff, 7 + xoff) = ted7360->c16_bitmap[code & 1];
644   }
645}
646
647static void ted7360_draw_bitmap_multi( device_t *device, int ybegin, int yend, int ch, int yoff, int xoff )
648{
649   ted7360_state *ted7360 = get_safe_token(device);
650   int y, code;
651
652   for (y = ybegin; y <= yend; y++)
653   {
654      code = ted7360->dma_read(device->machine(), ted7360->bitmapaddr + ch * 8 + y);
655
656      ted7360->bitmap->pix16(y + yoff, 0 + xoff) =
657         ted7360->bitmap->pix16(y + yoff, 1 + xoff) = ted7360->bitmapmulti[code >> 6];
658      ted7360->bitmap->pix16(y + yoff, 2 + xoff) =
659         ted7360->bitmap->pix16(y + yoff, 3 + xoff) = ted7360->bitmapmulti[(code >> 4) & 3];
660      ted7360->bitmap->pix16(y + yoff, 4 + xoff) =
661         ted7360->bitmap->pix16(y + yoff, 5 + xoff) = ted7360->bitmapmulti[(code >> 2) & 3];
662      ted7360->bitmap->pix16(y + yoff, 6 + xoff) =
663         ted7360->bitmap->pix16(y + yoff, 7 + xoff) = ted7360->bitmapmulti[code & 3];
664   }
665}
666
667#ifndef memset16
668static void *memset16 (void *dest, int value, size_t size)
669{
670   register int i;
671
672   for (i = 0; i < size; i++)
673      ((short *) dest)[i] = value;
674   return dest;
675}
676#endif
677
678static void ted7360_draw_cursor( device_t *device, int ybegin, int yend, int yoff, int xoff, int color )
679{
680   ted7360_state *ted7360 = get_safe_token(device);
681   int y;
682
683   for (y = ybegin; y <= yend; y++)
684   {
685      memset16(&ted7360->bitmap->pix16(yoff + y, xoff), color, 8);
686   }
687}
688
689static void ted7360_drawlines( device_t *device, int first, int last )
690{
691   ted7360_state *ted7360 = get_safe_token(device);
692   int line, vline, end;
693   int attr, ch, c1, c2, ecm;
694   int offs, yoff, xoff, ybegin, yend, xbegin, xend;
695   int i;
696
697   ted7360->lastline = last;
698
699   /* top part of display not rastered */
700   first -= TED7360_YPOS;
701   last -= TED7360_YPOS;
702   if ((first >= last) || (last <= 0))
703      return;
704   if (first < 0)
705      first = 0;
706
707   if (!SCREENON)
708   {
709      for (line = first; (line < last) && (line < ted7360->bitmap->height()); line++)
710         memset16(&ted7360->bitmap->pix16(line), 0, ted7360->bitmap->width());
711      return;
712   }
713
714   if (COLUMNS40)
715      xbegin = XPOS, xend = xbegin + 320;
716   else
717      xbegin = XPOS + 7, xend = xbegin + 304;
718
719   if (last < ted7360->y_begin)
720      end = last;
721   else
722      end = ted7360->y_begin + YPOS;
723   {
724      for (line = first; line < end; line++)
725         memset16(&ted7360->bitmap->pix16(line), FRAMECOLOR, ted7360->bitmap->width());
726   }
727   if (LINES25)
728      vline = line - ted7360->y_begin - YPOS;
729   else
730      vline = line - ted7360->y_begin - YPOS + 8 - VERTICALPOS;
731
732   if (last < ted7360->y_end + YPOS)
733      end = last;
734   else
735      end = ted7360->y_end + YPOS;
736
737   for (; line < end; vline = (vline + 8) & ~7, line = line + 1 + yend - ybegin)
738   {
739      offs = (vline >> 3) * 40;
740      ybegin = vline & 7;
741      yoff = line - ybegin;
742      yend = (yoff + 7 < end) ? 7 : (end - yoff - 1);
743      /* rendering 39 characters */
744      /* left and right borders are overwritten later */
745
746      for (xoff = ted7360->x_begin + XPOS; xoff < ted7360->x_end + XPOS; xoff += 8, offs++)
747      {
748         if (HIRESON)
749         {
750            ch = ted7360->dma_read(device->machine(), (ted7360->videoaddr | 0x400) + offs);
751            attr = ted7360->dma_read(device->machine(), ted7360->videoaddr + offs);
752            c1 = ((ch >> 4) & 0xf) | (attr << 4);
753            c2 = (ch & 0xf) | (attr & 0x70);
754            ted7360->bitmapmulti[1] = ted7360->c16_bitmap[1] = c1 & 0x7f;
755            ted7360->bitmapmulti[2] = ted7360->c16_bitmap[0] = c2 & 0x7f;
756            if (MULTICOLORON)
757            {
758               ted7360_draw_bitmap_multi(device, ybegin, yend, offs, yoff, xoff);
759            }
760            else
761            {
762               ted7360_draw_bitmap(device, ybegin, yend, offs, yoff, xoff);
763            }
764         }
765         else
766         {
767            ch = ted7360->dma_read(device->machine(), (ted7360->videoaddr | 0x400) + offs);
768            attr = ted7360->dma_read(device->machine(), ted7360->videoaddr + offs);
769            // levente harsfalvi's docu says cursor off in ecm and multicolor
770            if (ECMON)
771            {
772               // hardware reverse off
773               ecm = ch >> 6;
774               ted7360->ecmcolor[0] = ted7360->colors[ecm];
775               ted7360->ecmcolor[1] = attr & 0x7f;
776               ted7360_draw_character(device, ybegin, yend, ch & ~0xc0, yoff, xoff, ted7360->ecmcolor);
777            }
778            else if (MULTICOLORON)
779            {
780               // hardware reverse off
781               if (attr & 8)
782               {
783                  ted7360->multi[3] = attr & 0x77;
784                  ted7360_draw_character_multi(device, ybegin, yend, ch, yoff, xoff);
785               }
786               else
787               {
788                  ted7360->mono[1] = attr & 0x7f;
789                  ted7360_draw_character(device, ybegin, yend, ch, yoff, xoff, ted7360->mono);
790               }
791            }
792            else if (ted7360->cursor1 && (offs == CURSOR1POS))
793            {
794               ted7360_draw_cursor(device, ybegin, yend, yoff, xoff, attr & 0x7f);
795            }
796            else if (REVERSEON && (ch & 0x80))
797            {
798               ted7360->monoinversed[0] = attr & 0x7f;
799               if (ted7360->cursor1 && (attr & 0x80))
800                  ted7360_draw_cursor(device, ybegin, yend, yoff, xoff, ted7360->monoinversed[0]);
801               else
802                  ted7360_draw_character(device, ybegin, yend, ch & ~0x80, yoff, xoff, ted7360->monoinversed);
803            }
804            else
805            {
806               ted7360->mono[1] = attr & 0x7f;
807               if (ted7360->cursor1 && (attr & 0x80))
808                  ted7360_draw_cursor(device, ybegin, yend, yoff, xoff, ted7360->mono[0]);
809               else
810                  ted7360_draw_character(device, ybegin, yend, ch, yoff, xoff, ted7360->mono);
811            }
812         }
813      }
814
815      for (i = ybegin; i <= yend; i++)
816      {
817         memset16(&ted7360->bitmap->pix16(yoff + i), FRAMECOLOR, xbegin);
818         memset16(&ted7360->bitmap->pix16(yoff + i, xend), FRAMECOLOR, ted7360->bitmap->width() - xend);
819      }
820   }
821
822   if (last < ted7360->bitmap->height())
823      end = last;
824   else
825      end = ted7360->bitmap->height();
826
827   for (; line < end; line++)
828   {
829      memset16(&ted7360->bitmap->pix16(line), FRAMECOLOR, ted7360->bitmap->width());
830   }
831}
832
833
834WRITE8_DEVICE_HANDLER( ted7360_port_w )
835{
836   ted7360_state *ted7360 = get_safe_token(device);
837   int old;
838
839   if ((offset != 8) && ((offset < 0x15) || (offset > 0x19)))
840   {
841      DBG_LOG(1, "ted7360_port_w", ("%.2x:%.2x\n", offset, data));
842   }
843
844   switch (offset)
845   {
846   case 0xe:
847   case 0xf:
848   case 0x10:
849   case 0x11:
850   case 0x12:
851      ted7360_soundport_w(device, offset, data);
852      break;
853   }
854   switch (offset)
855   {
856   case 0:                     /* stop timer 1 */
857      ted7360->reg[offset] = data;
858
859      if (ted7360->timer1_active)
860      {
861         ted7360->reg[1] = TEDTIME_TO_CYCLES((ted7360->type == TED7360_PAL), ted7360->timer1->remaining()) >> 8;
862         ted7360->timer1->reset();
863         ted7360->timer1_active = 0;
864      }
865      break;
866   case 1:                     /* start timer 1 */
867      ted7360->reg[offset] = data;
868      ted7360->timer1->adjust(TEDTIME_IN_CYCLES((ted7360->type == TED7360_PAL), TIMER1), 1);
869      ted7360->timer1_active = 1;
870      break;
871   case 2:                     /* stop timer 2 */
872      ted7360->reg[offset] = data;
873      if (ted7360->timer2_active)
874      {
875         ted7360->reg[3] = TEDTIME_TO_CYCLES((ted7360->type == TED7360_PAL), ted7360->timer2->remaining()) >> 8;
876         ted7360->timer2->reset();
877         ted7360->timer2_active = 0;
878      }
879      break;
880   case 3:                     /* start timer 2 */
881      ted7360->reg[offset] = data;
882      ted7360->timer2->adjust(TEDTIME_IN_CYCLES((ted7360->type == TED7360_PAL), TIMER2), 2);
883      ted7360->timer2_active = 1;
884      break;
885   case 4:                     /* stop timer 3 */
886      ted7360->reg[offset] = data;
887      if (ted7360->timer3_active)
888      {
889         ted7360->reg[5] = TEDTIME_TO_CYCLES((ted7360->type == TED7360_PAL), ted7360->timer3->remaining()) >> 8;
890         ted7360->timer3->reset();
891         ted7360->timer3_active = 0;
892      }
893      break;
894   case 5:                     /* start timer 3 */
895      ted7360->reg[offset] = data;
896      ted7360->timer3->adjust(TEDTIME_IN_CYCLES((ted7360->type == TED7360_PAL), TIMER3), 3);
897      ted7360->timer3_active = 1;
898      break;
899   case 6:
900      if (ted7360->reg[offset] != data)
901      {
902         ted7360_drawlines(device, ted7360->lastline, ted7360->rasterline);
903         ted7360->reg[offset] = data;
904         if (LINES25)
905         {
906            ted7360->y_begin = 0;
907            ted7360->y_end = ted7360->y_begin + 200;
908         }
909         else
910         {
911            ted7360->y_begin = 4;
912            ted7360->y_end = ted7360->y_begin + 192;
913         }
914         ted7360->chargenaddr = CHARGENADDR;
915      }
916      break;
917   case 7:
918      if (ted7360->reg[offset] != data)
919      {
920         ted7360_drawlines(device, ted7360->lastline, ted7360->rasterline);
921         ted7360->reg[offset] = data;
922         if (COLUMNS40)
923         {
924            ted7360->x_begin = 0;
925            ted7360->x_end = ted7360->x_begin + 320;
926         }
927         else
928         {
929            ted7360->x_begin = HORICONTALPOS;
930            ted7360->x_end = ted7360->x_begin + 320;
931         }
932         DBG_LOG(3, "ted7360_port_w", ("%s %s\n", data & 0x40 ? "ntsc" : "pal", data & 0x20 ? "hori freeze" : ""));
933         ted7360->chargenaddr = CHARGENADDR;
934      }
935      break;
936   case 8:
937      ted7360->reg[offset] = ted7360->keyboard_cb(device->machine(), data);
938      break;
939   case 9:
940      if (data & 0x08)
941         ted7360_clear_interrupt(device, 8);
942      if (data & 0x10)
943         ted7360_clear_interrupt(device, 0x10);
944      if (data & 0x40)
945         ted7360_clear_interrupt(device, 0x40);
946      if (data & 0x02)
947         ted7360_clear_interrupt(device, 2);
948      break;
949   case 0xa:
950      old = data;
951      ted7360->reg[offset] = data | 0xa0;
952#if 0
953      ted7360->reg[9] = (ted7360->reg[9] & 0xa1) | (ted7360->reg[9] & data & 0x5e);
954      if (ted7360->reg[9] & 0x80)
955         ted7360_clear_interrupt(device, 0);
956#endif
957      if ((data ^ old) & 1)
958      {
959         /* DBG_LOG(1,"set rasterline hi",("soll:%d\n",RASTERLINE)); */
960      }
961      break;
962   case 0xb:
963      if (data != ted7360->reg[offset])
964      {
965         ted7360_drawlines(device, ted7360->lastline, ted7360->rasterline);
966         ted7360->reg[offset] = data;
967         /*  DBG_LOG(1,"set rasterline lo",("soll:%d\n",RASTERLINE)); */
968      }
969      break;
970   case 0xc:
971   case 0xd:
972      if (ted7360->reg[offset] != data)
973      {
974         ted7360_drawlines(device, ted7360->lastline, ted7360->rasterline);
975         ted7360->reg[offset] = data;
976      }
977      break;
978   case 0x12:
979      if (ted7360->reg[offset] != data)
980      {
981         ted7360_drawlines(device, ted7360->lastline, ted7360->rasterline);
982         ted7360->reg[offset] = data;
983         ted7360->bitmapaddr = BITMAPADDR;
984         ted7360->chargenaddr = CHARGENADDR;
985         DBG_LOG(3, "ted7360_port_w", ("bitmap %.4x %s\n",  BITMAPADDR, INROM ? "rom" : "ram"));
986      }
987      break;
988   case 0x13:
989      if (ted7360->reg[offset] != data)
990      {
991         ted7360_drawlines(device, ted7360->lastline, ted7360->rasterline);
992         ted7360->reg[offset] = data;
993         ted7360->chargenaddr = CHARGENADDR;
994         DBG_LOG(3, "ted7360_port_w", ("chargen %.4x %s %d\n", CHARGENADDR, data & 2 ? "" : "doubleclock", data & 1));
995      }
996      break;
997   case 0x14:
998      if (ted7360->reg[offset] != data)
999      {
1000         ted7360_drawlines(device, ted7360->lastline, ted7360->rasterline);
1001         ted7360->reg[offset] = data;
1002         ted7360->videoaddr = VIDEOADDR;
1003         DBG_LOG(3, "ted7360_port_w", ("videoram %.4x\n", VIDEOADDR));
1004      }
1005      break;
1006   case 0x15:                     /* backgroundcolor */
1007      if (ted7360->reg[offset] != data)
1008      {
1009         ted7360_drawlines(device, ted7360->lastline, ted7360->rasterline);
1010         ted7360->reg[offset] = data;
1011         ted7360->monoinversed[1] = ted7360->mono[0] = ted7360->bitmapmulti[0] = ted7360->multi[0] = ted7360->colors[0] = BACKGROUNDCOLOR;
1012      }
1013      break;
1014   case 0x16:                     /* foregroundcolor */
1015      if (ted7360->reg[offset] != data)
1016      {
1017         ted7360_drawlines(device, ted7360->lastline, ted7360->rasterline);
1018         ted7360->reg[offset] = data;
1019         ted7360->bitmapmulti[3] = ted7360->multi[1] = ted7360->colors[1] = FOREGROUNDCOLOR;
1020      }
1021      break;
1022   case 0x17:                     /* multicolor 1 */
1023      if (ted7360->reg[offset] != data)
1024      {
1025         ted7360_drawlines(device, ted7360->lastline, ted7360->rasterline);
1026         ted7360->reg[offset] = data;
1027         ted7360->multi[2] = ted7360->colors[2] = MULTICOLOR1;
1028      }
1029      break;
1030   case 0x18:                     /* multicolor 2 */
1031      if (ted7360->reg[offset] != data)
1032      {
1033         ted7360_drawlines(device, ted7360->lastline, ted7360->rasterline);
1034         ted7360->reg[offset] = data;
1035         ted7360->colors[3] = MULTICOLOR2;
1036      }
1037      break;
1038   case 0x19:                     /* framecolor */
1039      if (ted7360->reg[offset] != data)
1040      {
1041         ted7360_drawlines(device, ted7360->lastline, ted7360->rasterline);
1042         ted7360->reg[offset] = data;
1043         ted7360->colors[4] = FRAMECOLOR;
1044      }
1045      break;
1046   case 0x1c:
1047      ted7360->reg[offset] = data;         /*? */
1048      DBG_LOG(1, "ted7360_port_w", ("write to rasterline high %.2x\n",
1049                              data));
1050      break;
1051   case 0x1f:
1052      ted7360->reg[offset] = data;
1053      DBG_LOG(1, "ted7360_port_w", ("write to cursorblink %.2x\n", data));
1054      break;
1055   default:
1056      ted7360->reg[offset] = data;
1057      break;
1058   }
1059}
1060
1061READ8_DEVICE_HANDLER( ted7360_port_r )
1062{
1063   ted7360_state *ted7360 = get_safe_token(device);
1064   int val = 0;
1065
1066   switch (offset)
1067   {
1068   case 0:
1069      if (ted7360->timer1)
1070         val = TEDTIME_TO_CYCLES((ted7360->type == TED7360_PAL), ted7360->timer1->remaining()) & 0xff;
1071      else
1072         val = ted7360->reg[offset];
1073      break;
1074   case 1:
1075      if (ted7360->timer1)
1076         val = TEDTIME_TO_CYCLES((ted7360->type == TED7360_PAL), ted7360->timer1->remaining()) >> 8;
1077      else
1078         val = ted7360->reg[offset];
1079      break;
1080   case 2:
1081      if (ted7360->timer2)
1082         val = TEDTIME_TO_CYCLES((ted7360->type == TED7360_PAL), ted7360->timer2->remaining()) & 0xff;
1083      else
1084         val = ted7360->reg[offset];
1085      break;
1086   case 3:
1087      if (ted7360->timer2)
1088         val = TEDTIME_TO_CYCLES((ted7360->type == TED7360_PAL), ted7360->timer2->remaining()) >> 8;
1089      else
1090         val = ted7360->reg[offset];
1091      break;
1092   case 4:
1093      if (ted7360->timer3)
1094         val = TEDTIME_TO_CYCLES((ted7360->type == TED7360_PAL), ted7360->timer3->remaining()) & 0xff;
1095      else
1096         val = ted7360->reg[offset];
1097      break;
1098   case 5:
1099      if (ted7360->timer3)
1100         val = TEDTIME_TO_CYCLES((ted7360->type == TED7360_PAL), ted7360->timer3->remaining()) >> 8;
1101      else
1102         val = ted7360->reg[offset];
1103      break;
1104   case 7:
1105      val = (ted7360->reg[offset] & ~0x40);
1106      if (ted7360->type == TED7360_NTSC)
1107         val |= 0x40;
1108      break;
1109   case 9:
1110      val = ted7360->reg[offset] | 1;
1111      break;
1112   case 0xa:
1113      val = ted7360->reg[offset];
1114      break;
1115   case 0xb:
1116      val = ted7360->reg[offset];
1117      break;
1118   case 0x0c:
1119      val = ted7360->reg[offset] |= 0xfc;
1120      break;
1121   case 0x13:
1122      val = ted7360->reg[offset] & ~1;
1123      if (ted7360->rom)
1124         val |= 1;
1125      break;
1126   case 0x1c:                     /*rasterline */
1127      ted7360_drawlines(device, ted7360->lastline, ted7360->rasterline);
1128      val = ((RASTERLINE_2_C16(ted7360->rasterline) & 0x100) >> 8) | 0xfe;   /* expected by matrix */
1129      break;
1130   case 0x1d:                     /*rasterline */
1131      ted7360_drawlines(device, ted7360->lastline, ted7360->rasterline);
1132      val = RASTERLINE_2_C16(ted7360->rasterline) & 0xff;
1133      break;
1134   case 0x1e:                     /*rastercolumn */
1135      val = ted7360_rastercolumn(device) / 2;   /* pengo >=0x99 */
1136      break;
1137   case 0x1f:
1138      val = ((ted7360->rasterline & 7) << 4) | (ted7360->reg[offset] & 0x0f);
1139      DBG_LOG(1, "ted7360_port_w", ("read from cursorblink %.2x\n", val));
1140      break;
1141   default:
1142      val = ted7360->reg[offset];
1143      break;
1144   }
1145
1146   if ((offset != 8) && (offset >= 6) && (offset != 0x1c) && (offset != 0x1d) && (offset != 9) && ((offset < 0x15) || (offset > 0x19)))
1147   {
1148      DBG_LOG(1, "ted7360_port_r", ("%.2x:%.2x\n", offset, val));
1149   }
1150
1151   return val;
1152}
1153
1154WRITE_LINE_DEVICE_HANDLER( ted7360_rom_switch_w )
1155{
1156   ted7360_state *ted7360 = get_safe_token(device);
1157   ted7360->rom = state;
1158}
1159
1160READ_LINE_DEVICE_HANDLER( ted7360_rom_switch_r )
1161{
1162   ted7360_state *ted7360 = get_safe_token(device);
1163   return ted7360->rom;
1164}
1165
1166void ted7360_frame_interrupt_gen( device_t *device )
1167{
1168   ted7360_state *ted7360 = get_safe_token(device);
1169
1170   if ((ted7360->reg[0x1f] & 0xf) >= 0x0f)
1171   {
1172      /*  if (ted7360->frame_count >= CURSORRATE) */
1173      ted7360->cursor1 ^= 1;
1174      ted7360->reg[0x1f] &= ~0xf;
1175      ted7360->frame_count = 0;
1176   }
1177   else
1178      ted7360->reg[0x1f]++;
1179}
1180
1181void ted7360_raster_interrupt_gen( device_t *device )
1182{
1183   ted7360_state *ted7360 = get_safe_token(device);
1184
1185   ted7360->rasterline++;
1186   ted7360->rastertime = device->machine().time().as_double();
1187   if (ted7360->rasterline >= ted7360->lines)
1188   {
1189      ted7360->rasterline = 0;
1190      ted7360_drawlines(device, ted7360->lastline, TED7360_LINES);
1191      ted7360->lastline = 0;
1192   }
1193
1194   if (ted7360->rasterline == C16_2_RASTERLINE(RASTERLINE))
1195   {
1196      ted7360_drawlines(device, ted7360->lastline, ted7360->rasterline);
1197      ted7360_set_interrupt(device->machine(), 2, ted7360);
1198   }
1199}
1200
1201UINT32 ted7360_video_update( device_t *device, bitmap_ind16 &bitmap, const rectangle &cliprect )
1202{
1203   ted7360_state *ted7360 = get_safe_token(device);
1204
1205   copybitmap(bitmap, *ted7360->bitmap, 0, 0, 0, 0, cliprect);
1206   return 0;
1207}
1208
1209
1210/* Sound emulation */
1211
1212#define NOISE_BUFFER_SIZE_SEC 5
1213
1214#define TONE_ON         (!(ted7360->reg[0x11] & 0x80))      /* or tone update!? */
1215#define TONE1_ON        ((ted7360->reg[0x11] & 0x10))
1216#define TONE1_VALUE     (ted7360->reg[0x0e] | ((ted7360->reg[0x12] & 3) << 8))
1217#define TONE2_ON        ((ted7360->reg[0x11] & 0x20))
1218#define TONE2_VALUE     (ted7360->reg[0x0f] | ((ted7360->reg[0x10] & 3) << 8))
1219#define VOLUME          (ted7360->reg[0x11] & 0x0f)
1220#define NOISE_ON        (ted7360->reg[0x11] & 0x40)
1221
1222/*
1223 * pal 111860.781
1224 * ntsc 111840.45
1225 */
1226#define TONE_FREQUENCY(reg)         ((TED7360_CLOCK >> 3) / (1024 - reg))
1227#define TONE_FREQUENCY_MIN          (TONE_FREQUENCY(0))
1228#define NOISE_FREQUENCY             (TED7360_CLOCK / 8 / (1024 - TONE2_VALUE))
1229#define NOISE_FREQUENCY_MAX         (TED7360_CLOCK / 8)
1230
1231
1232static void ted7360_soundport_w( device_t *device, int offset, int data )
1233{
1234   ted7360_state *ted7360 = get_safe_token(device);
1235
1236   // int old = ted7360->reg[offset];
1237   ted7360->channel->update();
1238
1239   switch (offset)
1240   {
1241   case 0x0e:
1242   case 0x12:
1243      if (offset == 0x12)
1244         ted7360->reg[offset] = (ted7360->reg[offset] & ~3) | (data & 3);
1245      else
1246         ted7360->reg[offset] = data;
1247
1248      ted7360->tone1samples = device->machine().sample_rate() / TONE_FREQUENCY (TONE1_VALUE);
1249      DBG_LOG(1, "ted7360", ("tone1 %d %d sample:%d\n", TONE1_VALUE, TONE_FREQUENCY(TONE1_VALUE), ted7360->tone1samples));
1250      break;
1251
1252   case 0xf:
1253   case 0x10:
1254      ted7360->reg[offset] = data;
1255
1256      ted7360->tone2samples = device->machine().sample_rate() / TONE_FREQUENCY (TONE2_VALUE);
1257      DBG_LOG (1, "ted7360", ("tone2 %d %d sample:%d\n", TONE2_VALUE, TONE_FREQUENCY(TONE2_VALUE), ted7360->tone2samples));
1258
1259      ted7360->noisesamples = (int) ((double) NOISE_FREQUENCY_MAX * device->machine().sample_rate() * NOISE_BUFFER_SIZE_SEC / NOISE_FREQUENCY);
1260      DBG_LOG (1, "ted7360", ("noise %d sample:%d\n", NOISE_FREQUENCY, ted7360->noisesamples));
1261
1262      if (!NOISE_ON || ((double) ted7360->noisepos / ted7360->noisesamples >= 1.0))
1263         ted7360->noisepos = 0;
1264      break;
1265
1266   case 0x11:
1267      ted7360->reg[offset] = data;
1268      DBG_LOG(1, "ted7360", ("%s volume %d, %s %s %s\n", TONE_ON?"on":"off",
1269                   VOLUME, TONE1_ON?"tone1":"", TONE2_ON?"tone2":"", NOISE_ON?"noise":""));
1270
1271      if (!TONE_ON||!TONE1_ON) ted7360->tone1pos = 0;
1272      if (!TONE_ON||!TONE2_ON) ted7360->tone2pos = 0;
1273      if (!TONE_ON||!NOISE_ON) ted7360->noisepos = 0;
1274      break;
1275   }
1276}
1277
1278
1279/************************************/
1280/* Sound handler update             */
1281/************************************/
1282
1283static STREAM_UPDATE( ted7360_update )
1284{
1285   ted7360_state *ted7360 = get_safe_token(device);
1286   int i, v, a;
1287   stream_sample_t *buffer = outputs[0];
1288
1289   for (i = 0; i < samples; i++)
1290   {
1291      v = 0;
1292
1293      if (TONE1_ON)
1294      {
1295         if (ted7360->tone1pos <= ted7360->tone1samples / 2 || !TONE_ON)
1296            v += 0x2ff; // depends on the volume between sound and noise
1297
1298         ted7360->tone1pos++;
1299
1300         if (ted7360->tone1pos > ted7360->tone1samples)
1301            ted7360->tone1pos = 0;
1302      }
1303
1304      if (TONE2_ON || NOISE_ON )
1305      {
1306         if (TONE2_ON)
1307         {                     /*higher priority ?! */
1308            if (ted7360->tone2pos <= ted7360->tone2samples / 2 || !TONE_ON)
1309               v += 0x2ff;
1310
1311            ted7360->tone2pos++;
1312
1313            if (ted7360->tone2pos > ted7360->tone2samples)
1314               ted7360->tone2pos = 0;
1315         }
1316         else
1317         {
1318            v += ted7360->noise[(int) ((double) ted7360->noisepos * ted7360->noisesize / ted7360->noisesamples)];
1319            ted7360->noisepos++;
1320
1321            if ((double) ted7360->noisepos / ted7360->noisesamples >= 1.0)
1322               ted7360->noisepos = 0;
1323         }
1324      }
1325
1326      a = VOLUME;
1327      if (a > 8)
1328         a = 8;
1329
1330      v = v * a;
1331
1332      buffer[i] = v;
1333   }
1334}
1335
1336/*****************************************************************************
1337    DEVICE INTERFACE
1338*****************************************************************************/
1339
1340/************************************/
1341/* Sound handler start              */
1342/************************************/
1343
1344static void ted7360_sound_start( device_t *device )
1345{
1346   ted7360_state *ted7360 = get_safe_token(device);
1347   int i;
1348
1349   ted7360->channel = device->machine().sound().stream_alloc(*device, 0, 1, device->machine().sample_rate(), 0, ted7360_update);
1350
1351   /* buffer for fastest played sample for 5 second so we have enough data for min 5 second */
1352   ted7360->noisesize = NOISE_FREQUENCY_MAX * NOISE_BUFFER_SIZE_SEC;
1353   ted7360->noise = auto_alloc_array(device->machine(), UINT8, ted7360->noisesize);
1354
1355   {
1356      int noiseshift = 0x7ffff8;
1357      UINT8 data;
1358
1359      for (i = 0; i < ted7360->noisesize; i++)
1360      {
1361         data = 0;
1362         if (noiseshift & 0x400000)
1363            data |= 0x80;
1364         if (noiseshift & 0x100000)
1365            data |= 0x40;
1366         if (noiseshift & 0x010000)
1367            data |= 0x20;
1368         if (noiseshift & 0x002000)
1369            data |= 0x10;
1370         if (noiseshift & 0x000800)
1371            data |= 0x08;
1372         if (noiseshift & 0x000080)
1373            data |= 0x04;
1374         if (noiseshift & 0x000010)
1375            data |= 0x02;
1376         if (noiseshift & 0x000004)
1377            data |= 0x01;
1378         ted7360->noise[i] = data;
1379         if (((noiseshift & 0x400000) == 0) != ((noiseshift & 0x002000) == 0))
1380            noiseshift = (noiseshift << 1) | 1;
1381         else
1382            noiseshift <<= 1;
1383      }
1384   }
1385}
1386
1387static DEVICE_START( ted7360 )
1388{
1389   ted7360_state *ted7360 = get_safe_token(device);
1390   const ted7360_interface *intf = (ted7360_interface *)device->static_config();
1391   int width, height;
1392
1393   ted7360->screen = device->machine().device<screen_device>(intf->screen);
1394   width = ted7360->screen->width();
1395   height = ted7360->screen->height();
1396
1397   ted7360->bitmap = auto_bitmap_ind16_alloc(device->machine(), width, height);
1398
1399   ted7360->type = intf->type;
1400
1401   ted7360->dma_read = intf->dma_read;
1402   ted7360->dma_read_rom = intf->dma_read_rom;
1403   ted7360->interrupt = intf->irq;
1404
1405   ted7360->keyboard_cb = intf->keyb_cb;
1406
1407   ted7360->timer1 = device->machine().scheduler().timer_alloc(FUNC(ted7360_timer_timeout), ted7360);
1408   ted7360->timer2 = device->machine().scheduler().timer_alloc(FUNC(ted7360_timer_timeout), ted7360);
1409   ted7360->timer3 = device->machine().scheduler().timer_alloc(FUNC(ted7360_timer_timeout), ted7360);
1410
1411   ted7360_sound_start(device);
1412
1413   device->save_item(NAME(ted7360->reg));
1414
1415   device->save_item(NAME(*ted7360->bitmap));
1416
1417   device->save_item(NAME(ted7360->rom));
1418   device->save_item(NAME(ted7360->lines));
1419   device->save_item(NAME(ted7360->chargenaddr));
1420   device->save_item(NAME(ted7360->bitmapaddr));
1421   device->save_item(NAME(ted7360->videoaddr));
1422   device->save_item(NAME(ted7360->timer1_active));
1423   device->save_item(NAME(ted7360->timer2_active));
1424   device->save_item(NAME(ted7360->timer3_active));
1425   device->save_item(NAME(ted7360->cursor1));
1426   device->save_item(NAME(ted7360->rasterline));
1427   device->save_item(NAME(ted7360->lastline));
1428   device->save_item(NAME(ted7360->rastertime));
1429   device->save_item(NAME(ted7360->frame_count));
1430   device->save_item(NAME(ted7360->x_begin));
1431   device->save_item(NAME(ted7360->x_end));
1432   device->save_item(NAME(ted7360->y_begin));
1433   device->save_item(NAME(ted7360->y_end));
1434
1435   device->save_item(NAME(ted7360->c16_bitmap));
1436   device->save_item(NAME(ted7360->bitmapmulti));
1437   device->save_item(NAME(ted7360->mono));
1438   device->save_item(NAME(ted7360->monoinversed));
1439   device->save_item(NAME(ted7360->multi));
1440   device->save_item(NAME(ted7360->ecmcolor));
1441   device->save_item(NAME(ted7360->colors));
1442
1443   device->save_item(NAME(ted7360->tone1pos));
1444   device->save_item(NAME(ted7360->tone2pos));
1445   device->save_item(NAME(ted7360->tone1samples));
1446   device->save_item(NAME(ted7360->tone2samples));
1447   device->save_item(NAME(ted7360->noisepos));
1448   device->save_item(NAME(ted7360->noisesamples));
1449}
1450
1451static DEVICE_RESET( ted7360 )
1452{
1453   ted7360_state *ted7360 = get_safe_token(device);
1454
1455   memset(ted7360->reg, 0, ARRAY_LENGTH(ted7360->reg));
1456
1457   ted7360->rom = 1;   // FIXME: at start should be RAM or ROM? old c16 code set it to ROM at init: is it correct?
1458
1459   ted7360->lines = TED7360_LINES;
1460   ted7360->chargenaddr = ted7360->bitmapaddr = ted7360->videoaddr = 0;
1461   ted7360->timer1_active = ted7360->timer2_active = ted7360->timer3_active = 0;
1462   ted7360->cursor1 = 0;
1463
1464   ted7360->rasterline = 0;
1465   ted7360->lastline = 0;
1466
1467   ted7360->rastertime = 0.0;
1468
1469   ted7360->frame_count = 0;
1470
1471   ted7360->x_begin = 0;
1472   ted7360->x_end = 0;
1473   ted7360->y_begin = 0;
1474   ted7360->y_end = 0;
1475
1476   memset(ted7360->c16_bitmap, 0, ARRAY_LENGTH(ted7360->c16_bitmap));
1477   memset(ted7360->bitmapmulti, 0, ARRAY_LENGTH(ted7360->bitmapmulti));
1478   memset(ted7360->mono, 0, ARRAY_LENGTH(ted7360->mono));
1479   memset(ted7360->monoinversed, 0, ARRAY_LENGTH(ted7360->monoinversed));
1480   memset(ted7360->multi, 0, ARRAY_LENGTH(ted7360->multi));
1481   memset(ted7360->ecmcolor, 0, ARRAY_LENGTH(ted7360->ecmcolor));
1482   memset(ted7360->colors, 0, ARRAY_LENGTH(ted7360->colors));
1483
1484   ted7360->tone1pos = 0;
1485   ted7360->tone2pos = 0;
1486   ted7360->tone1samples = 1;
1487   ted7360->tone2samples = 1;
1488   ted7360->noisepos = 0;
1489   ted7360->noisesamples = 1;
1490}
1491
1492
1493/*-------------------------------------------------
1494    device definition
1495-------------------------------------------------*/
1496
1497static const char DEVTEMPLATE_SOURCE[] = __FILE__;
1498
1499#define DEVTEMPLATE_ID(p,s)            p##ted7360##s
1500#define DEVTEMPLATE_FEATURES         DT_HAS_START | DT_HAS_RESET
1501#define DEVTEMPLATE_NAME            "CBM TED 7360"
1502#define DEVTEMPLATE_FAMILY            "CBM Text Display Video Chip"
1503#include "devtempl.h"
1504
1505DEFINE_LEGACY_SOUND_DEVICE(TED7360, ted7360);
trunk/src/mess/audio/ted7360.h
r17575r17576
1/*****************************************************************************
2 *
3 * audio/ted7360.h
4 *
5 *
6 ****************************************************************************/
7
8#ifndef __TED7360_H__
9#define __TED7360_H__
10
11#include "devcb.h"
12
13
14/***************************************************************************
15    TYPE DEFINITIONS
16***************************************************************************/
17
18typedef int (*ted7360_dma_read)(running_machine &machine, int);
19typedef int (*ted7360_dma_read_rom)(running_machine &machine, int);
20typedef void (*ted7360_irq) (running_machine &, int);
21typedef UINT8 (*ted7360_key_cb) (running_machine &, int);
22
23typedef enum
24{
25   TED7360_NTSC,
26   TED7360_PAL
27} ted_type;
28
29typedef struct _ted7360_interface ted7360_interface;
30struct _ted7360_interface
31{
32   const char             *screen;
33
34   ted_type               type;
35
36   ted7360_dma_read       dma_read;
37   ted7360_dma_read_rom   dma_read_rom;
38
39   ted7360_irq            irq;
40
41   ted7360_key_cb         keyb_cb;
42};
43
44/***************************************************************************
45    CONSTANTS
46***************************************************************************/
47
48
49#define TED7360NTSC_VRETRACERATE 60
50#define TED7360PAL_VRETRACERATE 50
51#define TED7360_HRETRACERATE 15625
52
53/* the following values depend on the VIC clock,
54 * but to achieve TV-frequency the clock must have a fix frequency */
55#define TED7360_HSIZE   320
56#define TED7360_VSIZE   200
57
58/* of course you clock select an other clock, but for accurate */
59/* video timing (these are used in c16/c116/plus4) */
60#define TED7360NTSC_CLOCK   (14318180/4)
61#define TED7360PAL_CLOCK   (17734470/5)
62
63/* pal 50 Hz vertical screen refresh, screen consists of 312 lines
64 * ntsc 60 Hz vertical screen refresh, screen consists of 262 lines */
65#define TED7360NTSC_LINES 261
66#define TED7360PAL_LINES 312
67
68/***************************************************************************
69    DEVICE CONFIGURATION MACROS
70***************************************************************************/
71
72DECLARE_LEGACY_SOUND_DEVICE(TED7360, ted7360);
73
74#define MCFG_TED7360_ADD(_tag, _interface) \
75   MCFG_SOUND_ADD(_tag, TED7360, 0) \
76   MCFG_DEVICE_CONFIG(_interface)
77
78
79/*----------- defined in audio/ted7360.c -----------*/
80
81WRITE8_DEVICE_HANDLER( ted7360_port_w );
82READ8_DEVICE_HANDLER( ted7360_port_r );
83
84WRITE_LINE_DEVICE_HANDLER( ted7360_rom_switch_w );
85READ_LINE_DEVICE_HANDLER( ted7360_rom_switch_r );
86
87void ted7360_frame_interrupt_gen(device_t *device);
88void ted7360_raster_interrupt_gen(device_t *device);
89UINT32 ted7360_video_update(device_t *device, bitmap_ind16 &bitmap, const rectangle &cliprect);
90
91
92#endif /* __TED7360_H__ */
trunk/src/mess/machine/ap2_lang.c
r17575r17576
1/*********************************************************************
2
3    ap2_lang.c
4
5    Implementation of the Apple II Language Card
6
7*********************************************************************/
8
9#include "emu.h"
10#include "includes/apple2.h"
11#include "ap2_lang.h"
12
13
14/***************************************************************************
15    PARAMETERS
16***************************************************************************/
17
18#define LOG_LANGCARD   0
19
20
21
22/***************************************************************************
23    CORE IMPLEMENTATION
24***************************************************************************/
25
26/*-------------------------------------------------
27    apple2_langcard_touch - device read callback
28-------------------------------------------------*/
29
30static void apple2_langcard_touch(device_t *device, offs_t offset)
31{
32   UINT32 val, mask;
33
34   if (LOG_LANGCARD)
35      logerror("language card bankswitch read, offset: $c08%0x\n", offset);
36
37   /* determine which flags to change */
38   mask = VAR_LCWRITE | VAR_LCRAM | VAR_LCRAM2;
39   val = 0;
40
41   if (offset & 0x01)
42      val |= VAR_LCWRITE;
43
44   switch(offset & 0x03)
45   {
46      case 0x03:
47      case 0x00:
48         val |= VAR_LCRAM;
49         break;
50   }
51
52   if ((offset & 0x08) == 0)
53      val |= VAR_LCRAM2;
54
55   /* change the flags */
56   apple2_setvar(device->machine(), val, mask);
57}
58
59
60
61/*-------------------------------------------------
62    apple2_langcard_r - device read callback
63-------------------------------------------------*/
64
65READ8_DEVICE_HANDLER(apple2_langcard_r)
66{
67   apple2_langcard_touch(device, offset);
68   return 0x00;
69}
70
71
72
73/*-------------------------------------------------
74    apple2_langcard_w - device read callback
75-------------------------------------------------*/
76
77WRITE8_DEVICE_HANDLER(apple2_langcard_w)
78{
79   apple2_langcard_touch(device, offset);
80}
81
82
83
84/*-------------------------------------------------
85    DEVICE_START(apple2_langcard) - device start
86    function
87-------------------------------------------------*/
88
89static DEVICE_START(apple2_langcard)
90{
91   /* nothing to do */
92}
93
94
95
96/*-------------------------------------------------
97    DEVICE_GET_INFO(apple2_langcard) - device get info
98    function
99-------------------------------------------------*/
100
101DEVICE_GET_INFO(apple2_langcard)
102{
103   switch (state)
104   {
105      /* --- the following bits of info are returned as 64-bit signed integers --- */
106      case DEVINFO_INT_TOKEN_BYTES:               info->i = 1;                        break;
107      case DEVINFO_INT_INLINE_CONFIG_BYTES:         info->i = 0;                        break;
108
109      /* --- the following bits of info are returned as pointers to data or functions --- */
110      case DEVINFO_FCT_START:                     info->start = DEVICE_START_NAME(apple2_langcard);   break;
111      case DEVINFO_FCT_STOP:                     /* Nothing */                        break;
112      case DEVINFO_FCT_RESET:                     /* Nothing */                        break;
113
114      /* --- the following bits of info are returned as NULL-terminated strings --- */
115      case DEVINFO_STR_NAME:                     strcpy(info->s, "Apple II Language Card");         break;
116      case DEVINFO_STR_FAMILY:                  strcpy(info->s, "Apple II Language Card");         break;
117      case DEVINFO_STR_VERSION:                  strcpy(info->s, "1.0");                     break;
118      case DEVINFO_STR_SOURCE_FILE:               strcpy(info->s, __FILE__);                     break;
119   }
120}
121
122DEFINE_LEGACY_DEVICE(APPLE2_LANGCARD, apple2_langcard);
trunk/src/mess/machine/ap2_lang.h
r17575r17576
1/*********************************************************************
2
3    ap2_lang.h
4
5    Implementation of the Apple II Language Card
6
7*********************************************************************/
8
9#ifndef __AP2_LANG__
10#define __AP2_LANG__
11
12#include "emu.h"
13
14
15/***************************************************************************
16    CONSTANTS
17***************************************************************************/
18
19DECLARE_LEGACY_DEVICE(APPLE2_LANGCARD, apple2_langcard);
20
21#define MCFG_APPLE2_LANGCARD_ADD(_tag)   \
22   MCFG_DEVICE_ADD((_tag), APPLE2_LANGCARD, 0)
23
24
25
26/***************************************************************************
27    FUNCTION PROTOTYPES
28***************************************************************************/
29/* slot read function */
30READ8_DEVICE_HANDLER(apple2_langcard_r);
31
32/* slot write function */
33WRITE8_DEVICE_HANDLER(apple2_langcard_w);
34
35#endif /* __AP2_LANG__ */
trunk/src/mess/machine/c16.c
r17575r17576
1/***************************************************************************
2
3    commodore c16 home computer
4
5    peter.trauner@jk.uni-linz.ac.at
6    documentation
7     www.funet.fi
8
9***************************************************************************/
10
11#include "emu.h"
12#include "audio/ted7360.h"
13#include "cpu/m6502/m6502.h"
14#include "imagedev/cassette.h"
15#include "imagedev/cartslot.h"
16#include "machine/ram.h"
17#include "includes/c16.h"
18#include "machine/cbmiec.h"
19#include "sound/sid6581.h"
20
21#define VERBOSE_LEVEL 0
22#define DBG_LOG( MACHINE, N, M, A ) \
23   do { \
24      if(VERBOSE_LEVEL >= N) \
25      { \
26         if( M ) \
27            logerror("%11.6f: %-24s", MACHINE.time().as_double(), (char*) M ); \
28         logerror A; \
29      } \
30   } while (0)
31
32
33/*
34 * tia6523
35 *
36 * connector to floppy c1551 (delivered with c1551 as c16 expansion)
37 * port a for data read/write
38 * port b
39 * 0 status 0
40 * 1 status 1
41 * port c
42 * 6 dav output edge data on port a available
43 * 7 ack input edge ready for next datum
44 */
45
46/*
47  ddr bit 1 port line is output
48  port bit 1 port line is high
49
50  serial bus
51  1 serial srq in (ignored)
52  2 gnd
53  3 atn out (pull up)
54  4 clock in/out (pull up)
55  5 data in/out (pull up)
56  6 /reset (pull up) hardware
57
58
59  p0 negated serial bus pin 5 /data out
60  p1 negated serial bus pin 4 /clock out, cassette write
61  p2 negated serial bus pin 3 /atn out
62  p3 cassette motor out
63
64  p4 cassette read
65  p5 not connected (or not available on MOS7501?)
66  p6 serial clock in
67  p7 serial data in, serial bus 5
68*/
69
70WRITE8_DEVICE_HANDLER(c16_m7501_port_write)
71{
72   c16_state *state = device->machine().driver_data<c16_state>();
73
74   /* bit zero then output 0 */
75   state->m_iec->atn_w(!BIT(data, 2));
76   state->m_iec->clk_w(!BIT(data, 1));
77   state->m_iec->data_w(!BIT(data, 0));
78
79   state->m_cassette->output(!BIT(data, 1) ? -(0x5a9e >> 1) : +(0x5a9e >> 1));
80
81   state->m_cassette->change_state(BIT(data, 7) ? CASSETTE_MOTOR_DISABLED : CASSETTE_MOTOR_ENABLED, CASSETTE_MASK_MOTOR);
82}
83
84READ8_DEVICE_HANDLER(c16_m7501_port_read)
85{
86   c16_state *state = device->machine().driver_data<c16_state>();
87   UINT8 data = 0xff;
88   UINT8 c16_port7501 = m6510_get_port(state->m_maincpu);
89
90   if (BIT(c16_port7501, 0) || !state->m_iec->data_r())
91      data &= ~0x80;
92
93   if (BIT(c16_port7501, 1) || !state->m_iec->clk_r())
94      data &= ~0x40;
95
96//  data &= ~0x20; // port bit not in pinout
97
98   if (state->m_cassette->input() > +0.0)
99      data |=  0x10;
100   else
101      data &= ~0x10;
102
103   return data;
104}
105
106static void c16_bankswitch( running_machine &machine )
107{
108   c16_state *state = machine.driver_data<c16_state>();
109   UINT8 *rom = state->memregion("maincpu")->base();
110   state->membank("bank9")->set_base(state->m_messram->pointer());
111
112   switch (state->m_lowrom)
113   {
114   case 0:
115      state->membank("bank2")->set_base(rom + 0x10000);
116      break;
117   case 1:
118      state->membank("bank2")->set_base(rom + 0x18000);
119      break;
120   case 2:
121      state->membank("bank2")->set_base(rom + 0x20000);
122      break;
123   case 3:
124      state->membank("bank2")->set_base(rom + 0x28000);
125      break;
126   }
127
128   switch (state->m_highrom)
129   {
130   case 0:
131      state->membank("bank3")->set_base(rom + 0x14000);
132      state->membank("bank8")->set_base(rom + 0x17f20);
133      break;
134   case 1:
135      state->membank("bank3")->set_base(rom + 0x1c000);
136      state->membank("bank8")->set_base(rom + 0x1ff20);
137      break;
138   case 2:
139      state->membank("bank3")->set_base(rom + 0x24000);
140      state->membank("bank8")->set_base(rom + 0x27f20);
141      break;
142   case 3:
143      state->membank("bank3")->set_base(rom + 0x2c000);
144      state->membank("bank8")->set_base(rom + 0x2ff20);
145      break;
146   }
147   state->membank("bank4")->set_base(rom + 0x17c00);
148}
149
150WRITE8_HANDLER( c16_switch_to_rom )
151{
152   c16_state *state = space->machine().driver_data<c16_state>();
153
154   ted7360_rom_switch_w(state->m_ted7360, 1);
155   c16_bankswitch(space->machine());
156}
157
158/* write access to fddX load data flipflop
159 * and selects roms
160 * a0 a1
161 * 0  0  basic
162 * 0  1  plus4 low
163 * 1  0  c1 low
164 * 1  1  c2 low
165 *
166 * a2 a3
167 * 0  0  kernal
168 * 0  1  plus4 hi
169 * 1  0  c1 high
170 * 1  1  c2 high */
171WRITE8_HANDLER( c16_select_roms )
172{
173   c16_state *state = space->machine().driver_data<c16_state>();
174
175   state->m_lowrom = offset & 0x03;
176   state->m_highrom = (offset & 0x0c) >> 2;
177   if (ted7360_rom_switch_r(state->m_ted7360))
178      c16_bankswitch(space->machine());
179}
180
181WRITE8_HANDLER( c16_switch_to_ram )
182{
183   c16_state *state = space->machine().driver_data<c16_state>();
184   UINT8 *ram = state->m_messram->pointer();
185   UINT32 ram_size = state->m_messram->size();
186
187   ted7360_rom_switch_w(state->m_ted7360, 0);
188
189   state->membank("bank2")->set_base(ram + (0x8000 % ram_size));
190   state->membank("bank3")->set_base(ram + (0xc000 % ram_size));
191   state->membank("bank4")->set_base(ram + (0xfc00 % ram_size));
192   state->membank("bank8")->set_base(ram + (0xff20 % ram_size));
193}
194
195UINT8 c16_read_keyboard( running_machine &machine, int databus )
196{
197   c16_state *state = machine.driver_data<c16_state>();
198   UINT8 value = 0xff;
199   int i;
200
201   for (i = 0; i < 8; i++)
202   {
203      if (!BIT(state->m_port6529, i))
204         value &= state->m_keyline[i];
205   }
206
207   /* looks like joy 0 needs dataline2 low
208     * and joy 1 needs dataline1 low
209     * write to 0xff08 (value on databus) reloads latches */
210   if (!BIT(databus, 2))
211      value &= state->m_keyline[8];
212
213   if (!BIT(databus, 1))
214      value &= state->m_keyline[9];
215
216   return value;
217}
218
219/*
220 * mos 6529
221 * simple 1 port 8bit input output
222 * output with pull up resistors, 0 means low
223 * input, 0 means low
224 */
225/*
226 * ic used as output,
227 * output low means keyboard line selected
228 * keyboard line is then read into the ted7360 latch
229 */
230WRITE8_HANDLER( c16_6529_port_w )
231{
232   c16_state *state = space->machine().driver_data<c16_state>();
233   state->m_port6529 = data;
234}
235
236READ8_HANDLER( c16_6529_port_r )
237{
238   c16_state *state = space->machine().driver_data<c16_state>();
239   return state->m_port6529 & (c16_read_keyboard (space->machine(), 0xff /*databus */ ) | (state->m_port6529 ^ 0xff));
240}
241
242/*
243 * p0 Userport b
244 * p1 Userport k
245 * p2 Userport 4, cassette sense
246 * p3 Userport 5
247 * p4 Userport 6
248 * p5 Userport 7
249 * p6 Userport j
250 * p7 Userport f
251 */
252WRITE8_HANDLER( plus4_6529_port_w )
253{
254}
255
256READ8_HANDLER( plus4_6529_port_r )
257{
258   c16_state *state = space->machine().driver_data<c16_state>();
259   int data = 0x00;
260
261   if ((state->m_cassette->get_state() & CASSETTE_MASK_UISTATE) != CASSETTE_STOPPED)
262      data &= ~0x04;
263   else
264      data |=  0x04;
265
266   return data;
267}
268
269READ8_HANDLER( c16_fd1x_r )
270{
271   c16_state *state = space->machine().driver_data<c16_state>();
272   int data = 0x00;
273
274   if ((state->m_cassette->get_state() & CASSETTE_MASK_UISTATE) != CASSETTE_STOPPED)
275      data &= ~0x04;
276   else
277      data |=  0x04;
278
279   return data;
280}
281
282/**
283 0 write: transmit data
284 0 read: receiver data
285 1 write: programmed rest (data is dont care)
286 1 read: status register
287 2 command register
288 3 control register
289 control register (offset 3)
290  cleared by hardware reset, not changed by programmed reset
291  7: 2 stop bits (0 1 stop bit)
292  6,5: data word length
293   00 8 bits
294   01 7
295   10 6
296   11 5
297  4: ?? clock source
298   0 external receiver clock
299   1 baud rate generator
300  3-0: baud rate generator
301   0000 use external clock
302   0001 60
303   0010 75
304   0011
305   0100
306   0101
307   0110 300
308   0111 600
309   1000 1200
310   1001
311   1010 2400
312   1011 3600
313   1100 4800
314   1101 7200
315   1110 9600
316   1111 19200
317 control register
318  */
319WRITE8_HANDLER( c16_6551_port_w )
320{
321   c16_state *state = space->machine().driver_data<c16_state>();
322
323   offset &= 0x03;
324   DBG_LOG(space->machine(), 3, "6551", ("port write %.2x %.2x\n", offset, data));
325   state->m_port6529 = data;
326}
327
328READ8_HANDLER( c16_6551_port_r )
329{
330   int data = 0x00;
331
332   offset &= 0x03;
333   DBG_LOG(space->machine(), 3, "6551", ("port read %.2x %.2x\n", offset, data));
334   return data;
335}
336
337int c16_dma_read( running_machine &machine, int offset )
338{
339   c16_state *state = machine.driver_data<c16_state>();
340   return state->m_messram->pointer()[offset % state->m_messram->size()];
341}
342
343int c16_dma_read_rom( running_machine &machine, int offset )
344{
345   c16_state *state = machine.driver_data<c16_state>();
346
347   /* should read real c16 system bus from 0xfd00 -ff1f */
348   if (offset >= 0xc000)
349   {                           /* rom address in rom */
350      if ((offset >= 0xfc00) && (offset < 0xfd00))
351         return state->m_mem10000[offset];
352
353      switch (state->m_highrom)
354      {
355         case 0:
356            return state->m_mem10000[offset & 0x7fff];
357         case 1:
358            return state->m_mem18000[offset & 0x7fff];
359         case 2:
360            return state->m_mem20000[offset & 0x7fff];
361         case 3:
362            return state->m_mem28000[offset & 0x7fff];
363      }
364   }
365
366   if (offset >= 0x8000)
367   {                           /* rom address in rom */
368      switch (state->m_lowrom)
369      {
370         case 0:
371            return state->m_mem10000[offset & 0x7fff];
372         case 1:
373            return state->m_mem18000[offset & 0x7fff];
374         case 2:
375            return state->m_mem20000[offset & 0x7fff];
376         case 3:
377            return state->m_mem28000[offset & 0x7fff];
378      }
379   }
380
381   return state->m_messram->pointer()[offset % state->m_messram->size()];
382}
383
384void c16_interrupt( running_machine &machine, int level )
385{
386   c16_state *state = machine.driver_data<c16_state>();
387
388   if (level != state->m_old_level)
389   {
390      DBG_LOG(machine, 3, "mos7501", ("irq %s\n", level ? "start" : "end"));
391      device_set_input_line(state->m_maincpu, M6510_IRQ_LINE, level);
392      state->m_old_level = level;
393   }
394}
395
396static void c16_common_driver_init( running_machine &machine )
397{
398   c16_state *state = machine.driver_data<c16_state>();
399   UINT8 *rom = state->memregion("maincpu")->base();
400
401   /* initial bankswitch (notice that TED7360 is init to ROM) */
402   state->membank("bank2")->set_base(rom + 0x10000);
403   state->membank("bank3")->set_base(rom + 0x14000);
404   state->membank("bank4")->set_base(rom + 0x17c00);
405   state->membank("bank8")->set_base(rom + 0x17f20);
406
407   state->m_mem10000 = rom + 0x10000;
408   state->m_mem14000 = rom + 0x14000;
409   state->m_mem18000 = rom + 0x18000;
410   state->m_mem1c000 = rom + 0x1c000;
411   state->m_mem20000 = rom + 0x20000;
412   state->m_mem24000 = rom + 0x24000;
413   state->m_mem28000 = rom + 0x28000;
414   state->m_mem2c000 = rom + 0x2c000;
415}
416
417DRIVER_INIT_MEMBER(c16_state,c16)
418{
419   c16_common_driver_init(machine());
420
421   m_sidcard = 0;
422   m_pal = 1;
423}
424
425DRIVER_INIT_MEMBER(c16_state,plus4)
426{
427   c16_common_driver_init(machine());
428
429   m_sidcard = 0;
430   m_pal = 0;
431}
432
433DRIVER_INIT_MEMBER(c16_state,c16sid)
434{
435   c16_common_driver_init(machine());
436
437   m_sidcard = 1;
438   m_pal = 1;
439}
440
441DRIVER_INIT_MEMBER(c16_state,plus4sid)
442{
443   c16_common_driver_init(machine());
444
445   m_sidcard = 1;
446   m_pal = 0;
447}
448
449MACHINE_RESET( c16 )
450{
451   address_space *space = machine.device("maincpu")->memory().space(AS_PROGRAM);
452   c16_state *state = machine.driver_data<c16_state>();
453   UINT8 *ram = state->m_messram->pointer();
454   UINT32 ram_size = state->m_messram->size();
455
456   memset(state->m_keyline, 0xff, ARRAY_LENGTH(state->m_keyline));
457
458   state->m_lowrom = 0;
459   state->m_highrom = 0;
460   state->m_old_level = 0;
461   state->m_port6529 = 0;
462
463   if (state->m_pal)
464   {
465      state->membank("bank1")->set_base(ram + (0x4000 % ram_size));
466
467      state->membank("bank5")->set_base(ram + (0x4000 % ram_size));
468      state->membank("bank6")->set_base(ram + (0x8000 % ram_size));
469      state->membank("bank7")->set_base(ram + (0xc000 % ram_size));
470
471      space->install_write_bank(0xff20, 0xff3d,"bank10");
472      space->install_write_bank(0xff40, 0xffff, "bank11");
473      state->membank("bank10")->set_base(ram + (0xff20 % ram_size));
474      state->membank("bank11")->set_base(ram + (0xff40 % ram_size));
475   }
476   else
477   {
478      space->install_write_bank(0x4000, 0xfcff, "bank10");
479      state->membank("bank10")->set_base(ram + (0x4000 % ram_size));
480   }
481}
482
483#if 0
484// FIXME
485// in very old MESS versions, we had these handlers to enable SID writes to 0xd400.
486// would a real SID Card allow for this? If not, this should be removed completely
487static WRITE8_HANDLER( c16_sidcart_16k )
488{
489   c16_state *state = space->machine().driver_data<c16_state>();
490   UINT8 *ram = state->m_messram->pointer();
491
492   ram[0x1400 + offset] = data;
493   ram[0x5400 + offset] = data;
494   ram[0x9400 + offset] = data;
495   ram[0xd400 + offset] = data;
496
497   sid6581_w(state->m_sid, offset, data);
498}
499
500static WRITE8_HANDLER( c16_sidcart_64k )
501{
502   c16_state *state = space->machine().driver_data<c16_state>();
503
504   state->m_messram->pointer()[0xd400 + offset] = data;
505
506   sid6581_w(state->m_sid, offset, data);
507}
508
509static TIMER_CALLBACK( c16_sidhack_tick )
510{
511   address_space *space = machine.device("maincpu")->memory().space(AS_PROGRAM);
512   c16_state *state = space->machine().driver_data<c16_state>();
513
514   if (machine.root_device().ioport("SID")->read_safe(0x00) & 0x02)
515   {
516      if (state->m_pal)
517         space->install_legacy_write_handler(0xd400, 0xd41f, FUNC(c16_sidcart_16k));
518      else
519         space->install_legacy_write_handler(0xd400, 0xd41f, FUNC(c16_sidcart_64k));
520   }
521   else
522   {
523      space->unmap_write(0xd400, 0xd41f);
524   }
525}
526#endif
527
528static TIMER_CALLBACK( c16_sidcard_tick )
529{
530   c16_state *state = machine.driver_data<c16_state>();
531   address_space *space = state->m_maincpu->memory().space(AS_PROGRAM);
532
533   if (machine.root_device().ioport("SID")->read_safe(0x00) & 0x01)
534      space->install_legacy_readwrite_handler(*state->m_sid, 0xfe80, 0xfe9f, FUNC(sid6581_r), FUNC(sid6581_w));
535   else
536      space->install_legacy_readwrite_handler(*state->m_sid, 0xfd40, 0xfd5f, FUNC(sid6581_r), FUNC(sid6581_w));
537}
538
539INTERRUPT_GEN( c16_frame_interrupt )
540{
541   c16_state *state = device->machine().driver_data<c16_state>();
542   int value, i;
543   static const char *const c16ports[] = { "ROW0", "ROW1", "ROW2", "ROW3", "ROW4", "ROW5", "ROW6", "ROW7" };
544
545   /* Lines 0-7 : common keyboard */
546   for (i = 0; i < 8; i++)
547   {
548      value = 0xff;
549      value &= ~device->machine().root_device().ioport(c16ports[i])->read();
550
551      /* Shift Lock is mapped on Left/Right Shift */
552      if ((i == 1) && (device->machine().root_device().ioport("SPECIAL")->read() & 0x80))
553         value &= ~0x80;
554
555      state->m_keyline[i] = value;
556   }
557
558   if (device->machine().root_device().ioport("CTRLSEL")->read() & 0x01)
559   {
560      value = 0xff;
561      if (device->machine().root_device().ioport("JOY0")->read() & 0x10)         /* Joypad1_Button */
562         {
563            if (device->machine().root_device().ioport("SPECIAL")->read() & 0x40)
564               value &= ~0x80;
565            else
566               value &= ~0x40;
567         }
568
569      value &= ~(device->machine().root_device().ioport("JOY0")->read() & 0x0f);   /* Other Inputs Joypad1 */
570
571      if (device->machine().root_device().ioport("SPECIAL")->read() & 0x40)
572         state->m_keyline[9] = value;
573      else
574         state->m_keyline[8] = value;
575   }
576
577   if (device->machine().root_device().ioport("CTRLSEL")->read() & 0x10)
578   {
579      value = 0xff;
580      if (device->machine().root_device().ioport("JOY1")->read() & 0x10)         /* Joypad2_Button */
581         {
582            if (device->machine().root_device().ioport("SPECIAL")->read() & 0x40)
583               value &= ~0x40;
584            else
585               value &= ~0x80;
586         }
587
588      value &= ~(device->machine().root_device().ioport("JOY1")->read() & 0x0f);   /* Other Inputs Joypad2 */
589
590      if (device->machine().root_device().ioport("SPECIAL")->read() & 0x40)
591         state->m_keyline[8] = value;
592      else
593         state->m_keyline[9] = value;
594   }
595
596   ted7360_frame_interrupt_gen(state->m_ted7360);
597
598   if (state->m_sidcard)
599   {
600      /* if we are emulating the SID card, check which memory area should be accessed */
601      device->machine().scheduler().timer_set(attotime::zero, FUNC(c16_sidcard_tick));
602#if 0
603      /* if we are emulating the SID card, check if writes to 0xd400 have been enabled */
604      device->machine().scheduler().timer_set(attotime::zero, FUNC(c16_sidhack_tick));
605#endif
606   }
607
608   set_led_status(device->machine(), 1, device->machine().root_device().ioport("SPECIAL")->read() & 0x80 ? 1 : 0);      /* Shift Lock */
609   set_led_status(device->machine(), 0, device->machine().root_device().ioport("SPECIAL")->read() & 0x40 ? 1 : 0);      /* Joystick Swap */
610}
611
612
613/***********************************************
614
615    C16 Cartridges
616
617***********************************************/
618
619static void plus4_software_list_cartridge_load(device_image_interface &image)
620{
621   UINT8 *mem = image.device().machine().root_device().memregion("maincpu")->base();
622
623   size_t size = image.get_software_region_length("c1l");
624   if (size)
625      memcpy(mem + 0x20000, image.get_software_region("c1l"), size);
626
627   size = image.get_software_region_length("c1h");
628   if (size)
629      memcpy(mem + 0x24000, image.get_software_region("c1h"), size);
630
631   size = image.get_software_region_length("c2l");
632   if (size)
633      memcpy(mem + 0x28000, image.get_software_region("c2l"), size);
634
635   size = image.get_software_region_length("c2h");
636   if (size)
637      memcpy(mem + 0x2c000, image.get_software_region("c2h"), size);
638}
639
640static int plus4_crt_load( device_image_interface &image )
641{
642   UINT8 *mem = image.device().machine().root_device().memregion("maincpu")->base();
643   int size = image.length(), test;
644   const char *filetype;
645   int address = 0;
646
647   /* magic lowrom at offset 7: $43 $42 $4d */
648   /* if at offset 6 stands 1 it will immediatly jumped to offset 0 (0x8000) */
649   static const unsigned char magic[] = {0x43, 0x42, 0x4d};
650   unsigned char buffer[sizeof (magic)];
651
652   image.fseek(7, SEEK_SET);
653   image.fread( buffer, sizeof (magic));
654   image.fseek(0, SEEK_SET);
655
656   /* Check if our cart has the magic string, and set its loading address */
657   if (!memcmp(buffer, magic, sizeof (magic)))
658      address = 0x20000;
659
660   /* Give a loading address to non .bin / non .rom carts as well */
661   filetype = image.filetype();
662
663   /* We would support .hi and .lo files, but currently I'm not sure where to load them.
664       We simply load them at 0x20000 at this stage, even if it's probably wrong!
665       It could also well be that they both need to be loaded at the same time, but this
666       is now impossible since I reduced to 1 the number of cart slots.
667       More investigations are in order if any .hi, .lo dump would surface!              */
668   if (!mame_stricmp(filetype, "hi"))
669      address = 0x20000;   /* FIX ME! */
670
671   else if (!mame_stricmp(filetype, "lo"))
672      address = 0x20000;   /* FIX ME! */
673
674   /* As a last try, give a reasonable loading address also to .bin/.rom without the magic string */
675   else if (!address)
676   {
677      logerror("Cart %s does not contain the magic string: it may be loaded at the wrong memory address!\n", image.filename());
678      address = 0x20000;
679   }
680
681   logerror("Loading cart %s at %.5x size:%.4x\n", image.filename(), address, size);
682
683   /* Finally load the cart */
684   test = image.fread( mem + address, size);
685
686   if (test != size)
687      return IMAGE_INIT_FAIL;
688
689   return IMAGE_INIT_PASS;
690}
691
692static DEVICE_IMAGE_LOAD( c16_cart )
693{
694   int result = IMAGE_INIT_PASS;
695
696   if (image.software_entry() != NULL)
697   {
698      plus4_software_list_cartridge_load(image);
699   }
700   else
701   {
702      result = plus4_crt_load(image);
703   }
704
705   return result;
706}
707
708MACHINE_CONFIG_FRAGMENT( c16_cartslot )
709   MCFG_CARTSLOT_ADD("cart")
710   MCFG_CARTSLOT_EXTENSION_LIST("bin,rom,hi,lo")
711   MCFG_CARTSLOT_NOT_MANDATORY
712   MCFG_CARTSLOT_INTERFACE("plus4_cart")
713   MCFG_CARTSLOT_LOAD(c16_cart)
714   MCFG_SOFTWARE_LIST_ADD("cart_list", "plus4_cart")
715MACHINE_CONFIG_END
trunk/src/mess/machine/ti85_ser.c
r17575r17576
1
2#include "emu.h"
3#include "emuopts.h"
4#include "ti85_ser.h"
5
6enum
7{
8   TI85_SEND_STOP,
9   TI85_SEND_HEADER,
10   TI85_RECEIVE_OK_1,
11   TI85_RECEIVE_ANSWER_1,
12   TI85_RECEIVE_ANSWER_2,
13   TI85_RECEIVE_ANSWER_3,
14   TI85_SEND_OK,
15   TI85_SEND_DATA,
16   TI85_RECEIVE_OK_2,
17   TI85_SEND_END,
18   TI85_RECEIVE_OK_3,
19   TI85_RECEIVE_HEADER_1,
20   TI85_PREPARE_VARIABLE_DATA,
21   TI85_RECEIVE_HEADER_2,
22   TI85_SEND_OK_1,
23   TI85_SEND_CONTINUE,
24   TI85_RECEIVE_OK,
25   TI85_RECEIVE_DATA,
26   TI85_SEND_OK_2,
27   TI85_RECEIVE_END_OR_HEADER_1,
28   TI85_SEND_OK_3,
29   TI85_PREPARE_SCREEN_REQUEST,
30   TI85_SEND_SCREEN_REQUEST
31};
32
33//supported image formats
34enum
35{
36   TI_FILE_UNK,
37   TI_FILE_V1,   //used for TI-85 and TI-86 image
38   TI_FILE_V2,   //used for TI-82, TI-83 and TI-73 image
39   TI_FILE_V3   //used for TI-83+ and TI-84+ image
40};
41
42#define TI85_HEADER_SIZE      0x37
43
44#define TI85_SEND_VARIABLES      1
45#define TI85_SEND_BACKUP      2
46#define TI85_RECEIVE_BACKUP      3
47#define TI85_RECEIVE_VARIABLES   4
48#define TI85_RECEIVE_SCREEN      5
49
50#define TI85_PC_OK_PACKET_SIZE   4
51#define TI85_PC_END_PACKET_SIZE   4
52
53#define TI82_BACKUP_ID      0x0f   //used by the TI-82
54#define TI85_BACKUP_ID      0x1d   //used by the TI-85 and TI-86
55#define TI83_BACKUP_ID      0x13   //used by the TI-73, TI-83 and TI-83+
56
57//known tranfer ID
58#define TI_TRANFER_ID_TI73      0x07
59#define TI_TRANFER_ID_TI82      0x02
60#define TI_TRANFER_ID_TI83      0x03
61#define TI_TRANFER_ID_TI83P      0x23
62#define TI_TRANFER_ID_TI85      0x05
63#define TI_TRANFER_ID_TI86      0x06
64
65//packet type
66#define   TI_OK_PACKET            0x56
67#define   TI_CONTINUE_PACKET         0x09
68#define   TI_SCREEN_REQUEST_PACKET   0x6d
69#define   TI_END_PACKET            0x92
70
71static const UINT8 ti73_file_signature[] = {0x2a, 0x2a, 0x54, 0x49, 0x37, 0x33, 0x2a, 0x2a, 0x1a, 0x0a, 0x00};
72static const UINT8 ti85_file_signature[] = {0x2a, 0x2a, 0x54, 0x49, 0x38, 0x35, 0x2a, 0x2a, 0x1a, 0x0c, 0x00};
73static const UINT8 ti82_file_signature[] = {0x2a, 0x2a, 0x54, 0x49, 0x38, 0x32, 0x2a, 0x2a, 0x1a, 0x0a, 0x00};
74static const UINT8 ti83_file_signature[] = {0x2a, 0x2a, 0x54, 0x49, 0x38, 0x33, 0x2a, 0x2a, 0x1a, 0x0a, 0x00};
75static const UINT8 ti83p_file_signature[]= {0x2a, 0x2a, 0x54, 0x49, 0x38, 0x33, 0x46, 0x2a, 0x1a, 0x0a, 0x00};
76static const UINT8 ti86_file_signature[] = {0x2a, 0x2a, 0x54, 0x49, 0x38, 0x36, 0x2a, 0x2a, 0x1a, 0x0a, 0x00};
77
78typedef struct {
79   UINT16 head_size;
80   UINT16 data_size;
81   unsigned char type;
82   unsigned char name_size;
83   unsigned int offset;
84} ti85_entry;
85
86
87typedef struct {
88   UINT8* header;
89   UINT16 header_size;
90   UINT8* ok;
91   UINT16 ok_size;
92   UINT8* data;
93   UINT32 data_size;
94} ti85_serial_variable;
95
96
97typedef struct {
98   ti85_serial_variable * variables;
99   UINT8* end;
100   UINT16 end_size;
101   UINT16 number_of_variables;
102} ti85_serial_data;
103
104
105typedef struct
106{
107   UINT8   status;
108   int      transfer_type;
109   UINT8   image_type;
110   UINT8   send_id;         /* ID used for PC to TI transfer */
111   UINT8   receive_id;         /* ID used for TI to PC transfer */
112   UINT8   red_out;         /* signal line from machine */
113   UINT8   white_out;         /* signal line from machine */
114   UINT8   red_in;            /* signal line to machine */
115   UINT8   white_in;         /* signal line to machine */
116   UINT8   *receive_buffer;
117   UINT8   *receive_data;
118   ti85_serial_data   stream;
119   /* receive_data_counter and send_data_counter can be combined? */
120   UINT32   receive_data_counter;         /* from ti85_receive_serial */
121   UINT32   send_data_counter;            /* from ti85_send_serial */
122   /* variables_variable_number, send_backup_variable_number, and backup_variable_number can be combined? */
123   UINT16   variables_variable_number;      /* from ti85_send_variables */
124   UINT16   send_backup_variable_number;   /* from ti85_send_backup */
125   int      variable_number;            /* from ti85_receive_variables */
126   UINT8   *var_data;                  /* from ti85_receive_variables */
127   UINT32   var_file_number;            /* from ti85_receive_variables */
128   UINT8   *var_file_data;               /* from ti85_receive_variables */
129   int      var_file_size;               /* from ti85_receive_variables */
130   int      backup_variable_number;         /* from ti85_receive_backup */
131   int      backup_data_size[3];         /* from ti85_receive_backup */
132   UINT8   *backup_file_data;            /* from ti85_receive_backup */
133   UINT32   backup_file_number;            /* from ti85_receive_backup */
134   UINT32   image_file_number;            /* from ti85_receive_screen */
135} ti85serial_state;
136
137
138INLINE ti85serial_state *get_token(device_t *device)
139{
140   assert(device != NULL);
141   assert((device->type() == TI82SERIAL) ||
142         (device->type() == TI73SERIAL) ||
143         (device->type() == TI83PSERIAL) ||
144         (device->type() == TI85SERIAL) ||
145         (device->type() == TI86SERIAL));
146   return (ti85serial_state *) downcast<legacy_device_base *>(device)->token();
147}
148
149
150static UINT16 ti85_calculate_checksum(const UINT8* data, unsigned int size)
151{
152   UINT16 checksum = 0;
153   unsigned int i;
154
155   for (i = 0; i<size; i++)
156      checksum += data[i];
157   return checksum;
158}
159
160
161static UINT16 ti85_variables_count (const UINT8 * ti85_data, unsigned int ti85_data_size)
162{
163   unsigned int pos, head_size, var_size;
164   UINT16 number_of_entries = 0;
165   pos = TI85_HEADER_SIZE;
166   while (pos < ti85_data_size-2)
167   {
168      head_size = ti85_data[pos+0x00] + ti85_data[pos+0x01]*256;
169      var_size = ti85_data[pos+0x02] + ti85_data[pos+0x03]*256;
170      pos += head_size+var_size+4;
171      number_of_entries++;
172   }
173   return number_of_entries;
174}
175
176
177static void ti85_free_serial_data_memory (device_t *device)
178{
179   ti85serial_state *ti85serial = get_token( device );
180
181   if (ti85serial->receive_buffer)
182   {
183      free (ti85serial->receive_buffer);
184      ti85serial->receive_buffer = NULL;
185   }
186   if (ti85serial->receive_data)
187   {
188      free (ti85serial->receive_data);
189      ti85serial->receive_data = NULL;
190   }
191}
192
193
194static int ti85_alloc_serial_data_memory (device_t *device, UINT32 size)
195{
196   ti85serial_state *ti85serial = get_token( device );
197
198   if (!ti85serial->receive_buffer)
199   {
200      ti85serial->receive_buffer = (UINT8*) malloc (8*size*sizeof(UINT8));
201      if (!ti85serial->receive_buffer)
202         return 0;
203   }
204
205   if (!ti85serial->receive_data)
206   {
207      ti85serial->receive_data = (UINT8*) malloc (size * sizeof(UINT8));
208      if (!ti85serial->receive_data)
209      {
210         free (ti85serial->receive_buffer);
211         ti85serial->receive_buffer = NULL;
212         return 0;
213      }
214   }
215   return 1;
216}
217
218
219static void ti85_backup_read (const UINT8 * ti85_data, unsigned int ti85_data_size, ti85_entry * ti85_entries)
220{
221   unsigned int pos = 0x42+2;
222
223   ti85_entries[0].head_size = 0x09;
224   ti85_entries[0].data_size = ti85_data[0x39] + ti85_data[0x3a]*256;
225   ti85_entries[0].offset = pos;
226   pos += ti85_entries[0].data_size + 2;
227   ti85_entries[1].head_size = 0;
228   ti85_entries[1].data_size = ti85_data[0x3c] + ti85_data[0x3d]*256;
229   ti85_entries[1].offset = pos;
230   pos += ti85_entries[1].data_size + 2;
231   ti85_entries[2].head_size = 0;
232   ti85_entries[2].data_size = ti85_data[0x3e] + ti85_data[0x3f]*256;
233   ti85_entries[2].offset = pos;
234}
235
236
237static void ti85_variables_read (device_t *device, const UINT8 * ti85_data, unsigned int ti85_data_size, ti85_entry * ti85_entries)
238{
239   ti85serial_state *ti85serial = get_token( device );
240   unsigned int pos, i=0;
241
242   pos = TI85_HEADER_SIZE;
243   while (pos < ti85_data_size-2)
244   {
245      ti85_entries[i].head_size = ti85_data[pos+0x00] + ti85_data[pos+0x01]*256;
246      ti85_entries[i].data_size = ti85_data[pos+0x02] + ti85_data[pos+0x03]*256;
247      ti85_entries[i].type = ti85_data[pos+0x04];
248      ti85_entries[i].name_size = (ti85serial->image_type != TI_FILE_V1) ? 8 : ti85_data[pos+0x05];
249      ti85_entries[i].offset = pos;
250      pos += ti85_entries[i].head_size+ti85_entries[i].data_size+4;
251      i++;
252   }
253}
254
255
256static int ti85_receive_serial (device_t *device, UINT8* received_data, UINT32 received_data_size)
257{
258   ti85serial_state *ti85serial = get_token( device );
259
260   if (ti85serial->receive_data_counter >= received_data_size)
261   {
262      if (!ti85serial->red_out && !ti85serial->white_out)
263      {
264         ti85serial->red_in = ti85serial->white_in = 1;
265         ti85serial->receive_data_counter = 0;
266         return 0;
267      }
268      return 1;
269   }
270
271   if (ti85serial->red_in && ti85serial->white_in && (ti85serial->red_out!=ti85serial->white_out))
272   {
273      ti85serial->white_in = ti85serial->white_out;
274      ti85serial->red_in = ti85serial->red_out;
275      received_data[ti85serial->receive_data_counter] = ti85serial->white_out;
276      return 1;
277   }
278
279   if (ti85serial->red_in!=ti85serial->white_in && !ti85serial->red_out && !ti85serial->white_out)
280   {
281      ti85serial->red_in = ti85serial->white_in = 1;
282      ti85serial->receive_data_counter ++;
283      return 1;
284   }
285   return 1;
286}
287
288
289static int ti85_send_serial(device_t *device, UINT8* serial_data, UINT32 serial_data_size)
290{
291   ti85serial_state *ti85serial = get_token( device );
292
293   if (ti85serial->send_data_counter>=serial_data_size)
294   {
295      if (!ti85serial->red_out && !ti85serial->white_out)
296      {
297         ti85serial->red_in = ti85serial->white_in = 1;
298         ti85serial->send_data_counter = 0;
299         return 0;
300      }
301      ti85serial->red_in = ti85serial->white_in = 1;
302      return 1;
303   }
304
305   if (ti85serial->red_in && ti85serial->white_in && !ti85serial->red_out && !ti85serial->white_out)
306   {
307      ti85serial->red_in =  serial_data[ti85serial->send_data_counter] ? 1 : 0;
308      ti85serial->white_in = serial_data[ti85serial->send_data_counter] ? 0 : 1;
309      return 1;
310   }
311
312   if ((ti85serial->red_in == ti85serial->red_out) && (ti85serial->white_in == ti85serial->white_out))
313   {
314      ti85serial->red_in = ti85serial->white_in = 1;
315      ti85serial->send_data_counter++;
316      return 1;
317   }
318   return 1;
319}
320
321
322static void ti85_convert_data_to_stream (const UINT8* file_data, unsigned int size, UINT8* serial_data)
323{
324   unsigned int i, bits;
325
326   for (i=0; i<size; i++)
327      for (bits = 0; bits < 8; bits++)
328         serial_data[i*8+bits] = (file_data[i]>>bits) & 0x01;
329}
330
331
332static void ti85_append_head_to_stream (UINT8 transfer_id, UINT8 tranfer_type, UINT8* serial_data)
333{
334   UINT8 tmp_data[4];
335
336   tmp_data[0] = transfer_id;
337   tmp_data[1] = tranfer_type;
338   tmp_data[2] = 0;
339   tmp_data[3] = 0;
340
341   ti85_convert_data_to_stream(tmp_data, sizeof(tmp_data), serial_data);
342}
343
344
345static void ti85_convert_stream_to_data (const UINT8* serial_data, UINT32 size, UINT8* data)
346{
347   UINT32 i;
348   UINT8 bits;
349
350   size = size/8;
351
352   for (i=0; i<size; i++)
353   {
354      data[i] = 0;
355      for (bits = 0; bits < 8; bits++)
356         data[i] |= serial_data[i*8+bits]<<bits;
357   }
358}
359
360
361static int ti85_convert_file_data_to_serial_stream (device_t *device, const UINT8* file_data, unsigned int file_size, ti85_serial_data*  serial_data)
362{
363   ti85serial_state *ti85serial = get_token( device );
364   UINT16 i;
365   UINT16 number_of_entries;
366   UINT8 backup_id = (ti85serial->image_type == TI_FILE_V1) ? TI85_BACKUP_ID : ((device->type() == TI82SERIAL) ? TI82_BACKUP_ID : TI83_BACKUP_ID);
367
368   ti85_entry* ti85_entries = NULL;
369
370   UINT8* temp_data_to_convert = NULL;
371   UINT16 checksum;
372
373   //verify that the provided file is compatible with the model
374   if (device->type() == TI73SERIAL)
375      if (strncmp((char *) file_data, (char *) ti73_file_signature, 11))
376         return 0;
377   if (device->type() == TI85SERIAL)
378      if (strncmp((char *) file_data, (char *) ti85_file_signature, 11))
379         return 0;
380   if (device->type() == TI82SERIAL)
381      if (strncmp((char *) file_data, (char *) ti82_file_signature, 11))
382         return 0;
383   if (device->type() == TI83PSERIAL)   //TI-83+ is compatible with TI-83 and TI-82 file
384      if (strncmp((char *) file_data, (char *) ti83p_file_signature, 10) && strncmp((char *) file_data, (char *) ti83_file_signature, 11)
385         && strncmp((char *) file_data, (char *) ti82_file_signature, 11))
386         return 0;
387   if (device->type() == TI86SERIAL)   //TI-86 is compatible with TI-85 file
388      if (strncmp((char *) file_data, (char *) ti86_file_signature, 11) && strncmp((char *) file_data, (char *) ti85_file_signature, 11))
389         return 0;
390
391   //identify the image
392   if (!strncmp((char *) file_data, (char *) ti73_file_signature, 11))
393   {
394      ti85serial->send_id = TI_TRANFER_ID_TI73;
395      ti85serial->image_type = TI_FILE_V2;
396   }
397   else if (!strncmp((char *) file_data, (char *) ti85_file_signature, 11))
398   {
399      ti85serial->send_id = TI_TRANFER_ID_TI85;
400      ti85serial->image_type = TI_FILE_V1;
401   }
402   else if (!strncmp((char *) file_data, (char *) ti82_file_signature, 11))
403   {
404      ti85serial->send_id = TI_TRANFER_ID_TI82;
405      ti85serial->image_type = TI_FILE_V2;
406   }
407   else if (!strncmp((char *) file_data, (char *) ti83_file_signature, 11))
408   {
409      ti85serial->send_id = TI_TRANFER_ID_TI83;
410      ti85serial->image_type = TI_FILE_V2;
411   }
412   else if (!strncmp((char *) file_data, (char *) ti83p_file_signature, 11))
413   {
414      ti85serial->send_id = TI_TRANFER_ID_TI83P;
415      ti85serial->image_type = TI_FILE_V3;
416   }
417   else if (!strncmp((char *) file_data, (char *) ti86_file_signature, 11))
418   {
419      ti85serial->send_id = TI_TRANFER_ID_TI86;
420      ti85serial->image_type = TI_FILE_V1;
421   }
422
423   logerror("Image ID: 0x%02x, version: 0x%02x\n", ti85serial->send_id, ti85serial->image_type);
424
425   /*Serial stream preparing*/
426   serial_data->end = NULL;
427
428   number_of_entries = (file_data[0x3b]==backup_id) ? 3 : ti85_variables_count(file_data, file_size);
429   if (!number_of_entries) return 0;
430
431   serial_data->variables = (ti85_serial_variable*)malloc(sizeof(ti85_serial_variable)*number_of_entries);
432   if (!serial_data->variables) return 0;
433
434   for (i=0; i<number_of_entries; i++)
435   {
436      serial_data->variables[i].header = NULL;
437      serial_data->variables[i].ok = NULL;
438      serial_data->variables[i].data = NULL;
439   }
440
441   serial_data->number_of_variables = number_of_entries;
442
443   ti85_entries = (ti85_entry*) malloc (sizeof(ti85_entry)*number_of_entries);
444   if (!ti85_entries) return 0;
445
446   if (file_data[0x3b]==backup_id)
447   {
448      ti85serial->transfer_type = TI85_SEND_BACKUP;
449      ti85_backup_read (file_data, file_size, ti85_entries);
450   }
451   else
452   {
453      ti85serial->transfer_type = TI85_SEND_VARIABLES;
454      ti85_variables_read (device, file_data, file_size, ti85_entries);
455   }
456   for (i=0; i<number_of_entries; i++)
457   {
458      /*Header packet*/
459      if (file_data[0x3b]==backup_id)
460      {
461         if (!i)
462         {
463            temp_data_to_convert = (UINT8*) malloc (0x0f);
464            if (!temp_data_to_convert)
465            {
466               free (ti85_entries);
467               return 0;
468            }
469            serial_data->variables[i].header = (UINT8*) malloc (0x0f*8);
470
471            if (!serial_data->variables[i].header)
472            {
473               free (ti85_entries);
474               free (temp_data_to_convert);
475               return 0;
476            }
477            serial_data->variables[i].header_size = 0x0f*8;
478            temp_data_to_convert[0] = ti85serial->send_id;   //PC sends
479            temp_data_to_convert[1] = 0x06;   //header
480            memcpy(   temp_data_to_convert+0x02, file_data+0x37, 0x0b);
481            checksum = ti85_calculate_checksum(temp_data_to_convert+4, 0x09);
482            temp_data_to_convert[13] = checksum&0x00ff;
483            temp_data_to_convert[14] = (checksum&0xff00)>>8;
484            ti85_convert_data_to_stream(temp_data_to_convert, 0x0f, serial_data->variables[i].header);
485            free(temp_data_to_convert);
486         }
487         else
488         {
489            serial_data->variables[i].header = NULL;
490            serial_data->variables[i].header_size = 0;
491         }
492      }
493      else
494      {
495         temp_data_to_convert = (UINT8*) malloc (10+ti85_entries[i].name_size);
496         if (!temp_data_to_convert)
497         {
498            free (ti85_entries);
499            return 0;
500         }
501         serial_data->variables[i].header = (UINT8*) malloc ((10+ti85_entries[i].name_size)*8);
502         if (!serial_data->variables[i].header)
503         {
504            free (temp_data_to_convert);
505            free (ti85_entries);
506            return 0;
507         }
508
509         if (ti85serial->image_type == TI_FILE_V1)
510         {
511            serial_data->variables[i].header_size = (10+ti85_entries[i].name_size)*8;
512
513            temp_data_to_convert[0] = ti85serial->send_id;
514            temp_data_to_convert[1] = 0x06;   //header
515            temp_data_to_convert[2] = (4+ti85_entries[i].name_size)&0x00ff;
516            temp_data_to_convert[3] = ((4+ti85_entries[i].name_size)&0xff00)>>8;
517            temp_data_to_convert[4] = (ti85_entries[i].data_size)&0x00ff;
518            temp_data_to_convert[5] = ((ti85_entries[i].data_size)&0xff00)>>8;
519            temp_data_to_convert[6] = ti85_entries[i].type;
520            temp_data_to_convert[7] = ti85_entries[i].name_size;
521            memcpy(temp_data_to_convert+8, file_data+ti85_entries[i].offset+0x06, ti85_entries[i].name_size);
522            checksum = ti85_calculate_checksum(temp_data_to_convert+4,ti85_entries[i].name_size+4);
523            temp_data_to_convert[10+ti85_entries[i].name_size-2] = checksum&0x00ff;
524            temp_data_to_convert[10+ti85_entries[i].name_size-1] = (checksum&0xff00)>>8;
525            ti85_convert_data_to_stream(temp_data_to_convert, 10+ti85_entries[i].name_size, serial_data->variables[i].header);
526         }
527
528         if (ti85serial->image_type == TI_FILE_V2 || ti85serial->image_type == TI_FILE_V3)
529         {
530            serial_data->variables[i].header_size = (9+ti85_entries[i].name_size)*8;
531
532            temp_data_to_convert[0] = ti85serial->send_id;
533            temp_data_to_convert[1] = 0x06;   //header
534            temp_data_to_convert[2] = (3+ti85_entries[i].name_size)&0x00ff;
535            temp_data_to_convert[3] = ((3+ti85_entries[i].name_size)&0xff00)>>8;
536            temp_data_to_convert[4] = (ti85_entries[i].data_size)&0x00ff;
537            temp_data_to_convert[5] = ((ti85_entries[i].data_size)&0xff00)>>8;
538            temp_data_to_convert[6] = ti85_entries[i].type;
539            memcpy(temp_data_to_convert+7, file_data+ti85_entries[i].offset+0x05, ti85_entries[i].name_size);
540            checksum = ti85_calculate_checksum(temp_data_to_convert+4,ti85_entries[i].name_size+3);
541            temp_data_to_convert[9+ti85_entries[i].name_size-2] = checksum&0x00ff;
542            temp_data_to_convert[9+ti85_entries[i].name_size-1] = (checksum&0xff00)>>8;
543            ti85_convert_data_to_stream(temp_data_to_convert, 9+ti85_entries[i].name_size, serial_data->variables[i].header);
544         }
545
546         free(temp_data_to_convert);
547      }
548
549      /*OK packet*/
550      serial_data->variables[i].ok = (UINT8*) malloc (TI85_PC_OK_PACKET_SIZE*8);
551      if (!serial_data->variables[i].ok)
552      {
553         free (ti85_entries);
554         return 0;
555      }
556      ti85_append_head_to_stream(ti85serial->send_id, TI_OK_PACKET, serial_data->variables[i].ok);
557      serial_data->variables[i].ok_size = TI85_PC_OK_PACKET_SIZE*8;
558
559      /*Data packet*/
560      temp_data_to_convert = (UINT8*) malloc (6+ti85_entries[i].data_size);
561      if (!temp_data_to_convert)
562      {
563         free (ti85_entries);
564         return 0;
565      }
566      serial_data->variables[i].data = (UINT8*) malloc ((6+ti85_entries[i].data_size)*8);
567      if (!serial_data->variables[i].data)
568      {
569         free (temp_data_to_convert);
570         free (ti85_entries);
571         return 0;
572      }
573      serial_data->variables[i].data_size = (6+ti85_entries[i].data_size)*8;
574
575      temp_data_to_convert[0] = ti85serial->send_id;
576      temp_data_to_convert[1] = 0x15;   //data
577      temp_data_to_convert[2] = (ti85_entries[i].data_size)&0x00ff;
578      temp_data_to_convert[3] = ((ti85_entries[i].data_size)&0xff00)>>8;
579
580      UINT8 name_start = (ti85serial->image_type != TI_FILE_V1) ? 5 : 6;
581
582      //TI-83+ files have two additional byte used for the file's version and flag
583      if (ti85serial->image_type == TI_FILE_V3)
584         name_start += 2;
585
586      if (file_data[0x3b]==backup_id)
587         memcpy(temp_data_to_convert+4, file_data+ti85_entries[i].offset, ti85_entries[i].data_size);
588      else
589         memcpy(temp_data_to_convert+4, file_data+ti85_entries[i].offset+name_start+ti85_entries[i].name_size+0x02, ti85_entries[i].data_size);
590
591      checksum = ti85_calculate_checksum(temp_data_to_convert+4,ti85_entries[i].data_size);
592      temp_data_to_convert[6+ti85_entries[i].data_size-2] = checksum&0x00ff;
593      temp_data_to_convert[6+ti85_entries[i].data_size-1] = (checksum&0xff00)>>8;
594      ti85_convert_data_to_stream(temp_data_to_convert, 6+ti85_entries[i].data_size, serial_data->variables[i].data);
595      free(temp_data_to_convert);
596   }
597
598
599   /*END packet*/
600   serial_data->end = (UINT8*) malloc (TI85_PC_END_PACKET_SIZE*8);
601   if (!serial_data->end)
602   {
603      free (ti85_entries);
604      return 0;
605   }
606   ti85_append_head_to_stream(ti85serial->send_id, TI_END_PACKET, serial_data->end);
607   serial_data->end_size = TI85_PC_END_PACKET_SIZE*8;
608
609   free (ti85_entries);
610
611   return 1;
612}
613
614
615static void ti85_free_serial_stream (ti85_serial_data*  serial_data)
616{
617   UINT16 i;
618   if (serial_data->variables)
619   {
620      for (i=0; i<serial_data->number_of_variables; i++)
621      {
622         if (serial_data->variables[i].header) free (serial_data->variables[i].header);
623         if (serial_data->variables[i].ok) free (serial_data->variables[i].ok);
624         if (serial_data->variables[i].data) free (serial_data->variables[i].data);
625      }
626      free (serial_data->variables);
627      serial_data->variables = NULL;
628   }
629   serial_data->number_of_variables = 0;
630   if (serial_data->end)
631   {
632      free (serial_data->end);
633      serial_data->end = NULL;
634   }
635}
636
637
638static void ti85_send_variables (device_t *device)
639{
640   ti85serial_state *ti85serial = get_token( device );
641
642   if (!ti85_alloc_serial_data_memory(device, 7))
643      ti85serial->status = TI85_SEND_STOP;
644
645   switch (ti85serial->status)
646   {
647      case TI85_SEND_HEADER:
648         if(!ti85_send_serial(device, ti85serial->stream.variables[ti85serial->variables_variable_number].header,ti85serial->stream.variables[ti85serial->variables_variable_number].header_size))
649         {
650            ti85serial->status = TI85_RECEIVE_OK_1;
651            memset (ti85serial->receive_data, 0, 7);
652            logerror ("Header sent\n");
653         }
654         break;
655      case TI85_RECEIVE_OK_1:
656         if(!ti85_receive_serial (device, ti85serial->receive_buffer, 4*8))
657         {
658            ti85_convert_stream_to_data (ti85serial->receive_buffer, 4*8, ti85serial->receive_data);
659            ti85serial->status = TI85_RECEIVE_ANSWER_1;
660            logerror ("OK received\n");
661         }
662         break;
663      case TI85_RECEIVE_ANSWER_1:
664         if(!ti85_receive_serial (device, ti85serial->receive_buffer, 4*8))
665         {
666            ti85_convert_stream_to_data (ti85serial->receive_buffer, 4*8, ti85serial->receive_data);
667            switch (ti85serial->receive_data[1])
668            {
669               case 0x09:   //continue
670                  ti85serial->status = TI85_SEND_OK;
671                  logerror ("Continue received\n");
672                  break;
673               case 0x36:      //out of memory, skip or exit
674                  ti85serial->status = TI85_RECEIVE_ANSWER_2;
675                  break;
676            }
677         }
678         break;
679      case TI85_RECEIVE_ANSWER_2:
680         if(!ti85_receive_serial (device, ti85serial->receive_buffer+4*8, 1*8))
681         {
682            ti85_convert_stream_to_data (ti85serial->receive_buffer, 5*8, ti85serial->receive_data);
683            switch (ti85serial->receive_data[4])
684            {
685               case 0x01:   //exit
686               case 0x02:   //skip
687                  ti85serial->status = TI85_RECEIVE_ANSWER_3;
688                  break;
689               case 0x03:   //out of memory
690                  ti85serial->variables_variable_number = 0;
691                  ti85_free_serial_data_memory(device);
692                  ti85serial->status = TI85_SEND_STOP;
693                  break;
694            }
695         }
696         break;
697      case TI85_RECEIVE_ANSWER_3:
698         if(!ti85_receive_serial (device, ti85serial->receive_buffer+5*8, 2*8))
699         {
700            ti85_convert_stream_to_data (ti85serial->receive_buffer, 7*8, ti85serial->receive_data);
701            switch (ti85serial->receive_data[4])
702            {
703               case 0x01:   //exit
704                  ti85serial->variables_variable_number = 0;
705                  ti85_free_serial_data_memory(device);
706                  ti85serial->status = TI85_SEND_STOP;
707                  break;
708               case 0x02:   //skip
709                  ti85serial->variables_variable_number++;
710                  ti85serial->status = TI85_SEND_OK;
711                  break;
712            }
713         }
714         break;
715      case TI85_SEND_OK:
716         if(!ti85_send_serial(device, ti85serial->stream.variables[ti85serial->variables_variable_number].ok,ti85serial->stream.variables[ti85serial->variables_variable_number].ok_size))
717         {
718            ti85serial->status = (ti85serial->receive_data[4]==0x02) ?  ((ti85serial->variables_variable_number < ti85serial->stream.number_of_variables) ? TI85_SEND_HEADER : TI85_SEND_END) : TI85_SEND_DATA;
719            memset(ti85serial->receive_data, 0, 7);
720         }
721         break;
722      case TI85_SEND_DATA:
723         if(!ti85_send_serial(device, ti85serial->stream.variables[ti85serial->variables_variable_number].data,ti85serial->stream.variables[ti85serial->variables_variable_number].data_size))
724            ti85serial->status = TI85_RECEIVE_OK_2;
725         break;
726      case TI85_RECEIVE_OK_2:
727         if(!ti85_receive_serial (device, ti85serial->receive_buffer, 4*8))
728         {
729            ti85serial->variables_variable_number++;
730            ti85_convert_stream_to_data (ti85serial->receive_buffer, 4*8, ti85serial->receive_data);
731            ti85serial->status = (ti85serial->variables_variable_number < ti85serial->stream.number_of_variables) ? TI85_SEND_HEADER : TI85_SEND_END;
732         }
733         break;
734      case TI85_SEND_END:
735         if(!ti85_send_serial(device, ti85serial->stream.end,ti85serial->stream.end_size))
736         {
737            logerror ("End sent\n");
738            ti85serial->variables_variable_number = 0;
739            ti85serial->status = TI85_RECEIVE_OK_3;
740         }
741         break;
742      case TI85_RECEIVE_OK_3:
743         if(!ti85_receive_serial (device, ti85serial->receive_buffer, 4*8))
744         {
745            logerror ("OK received\n");
746            ti85_convert_stream_to_data (ti85serial->receive_buffer, 4*8, ti85serial->receive_data);
747            ti85_free_serial_data_memory(device);
748            ti85serial->status = TI85_SEND_STOP;
749         }
750         break;
751   }
752}
753
754
755static void ti85_send_backup (device_t *device)
756{
757   ti85serial_state *ti85serial = get_token( device );
758
759   if (!ti85_alloc_serial_data_memory(device, 7))
760      ti85serial->status = TI85_SEND_STOP;
761
762   switch (ti85serial->status)
763   {
764      case TI85_SEND_HEADER:
765         if(!ti85_send_serial(device, ti85serial->stream.variables[ti85serial->send_backup_variable_number].header,ti85serial->stream.variables[ti85serial->send_backup_variable_number].header_size))
766            ti85serial->status = TI85_RECEIVE_OK_1;
767         break;
768      case TI85_RECEIVE_OK_1:
769         if(!ti85_receive_serial (device, ti85serial->receive_buffer, 4*8))
770         {
771            ti85_convert_stream_to_data (ti85serial->receive_buffer, 4*8, ti85serial->receive_data);
772            ti85serial->status = TI85_RECEIVE_ANSWER_1;
773         }
774         break;
775      case TI85_RECEIVE_ANSWER_1:
776         if(!ti85_receive_serial (device, ti85serial->receive_buffer, 4*8))
777         {
778            ti85_convert_stream_to_data (ti85serial->receive_buffer, 4*8, ti85serial->receive_data);
779            switch (ti85serial->receive_data[1])
780            {
781               case 0x09:   //continue
782                  ti85serial->status = TI85_SEND_OK;
783                  break;
784               case 0x36:      //out of memory, skip or exit
785                  ti85serial->status = TI85_RECEIVE_ANSWER_2;
786                  break;
787            }
788         }
789         break;
790      case TI85_RECEIVE_ANSWER_2:
791         if(!ti85_receive_serial (device, ti85serial->receive_buffer+4*8, 3*8))
792         {
793            ti85_convert_stream_to_data (ti85serial->receive_buffer, 5*8, ti85serial->receive_data);
794            ti85serial->send_backup_variable_number = 0;
795            ti85_free_serial_data_memory(device);
796            ti85serial->status = TI85_SEND_STOP;
797         }
798         break;
799      case TI85_SEND_OK:
800         if(!ti85_send_serial(device, ti85serial->stream.variables[ti85serial->send_backup_variable_number].ok,ti85serial->stream.variables[ti85serial->send_backup_variable_number].ok_size))
801            ti85serial->status = TI85_SEND_DATA;
802         break;
803      case TI85_SEND_DATA:
804         if(!ti85_send_serial(device, ti85serial->stream.variables[ti85serial->send_backup_variable_number].data,ti85serial->stream.variables[ti85serial->send_backup_variable_number].data_size))
805            ti85serial->status = TI85_RECEIVE_OK_2;
806         break;
807      case TI85_RECEIVE_OK_2:
808         if(!ti85_receive_serial (device, ti85serial->receive_buffer, 4*8))
809         {
810            ti85serial->send_backup_variable_number++;
811            ti85_convert_stream_to_data (ti85serial->receive_buffer, 4*8, ti85serial->receive_data);
812            ti85serial->status = (ti85serial->send_backup_variable_number < ti85serial->stream.number_of_variables) ? TI85_SEND_DATA : TI85_SEND_END;
813         }
814         break;
815      case TI85_SEND_END:
816         if(!ti85_send_serial(device, ti85serial->stream.end,ti85serial->stream.end_size))
817         {
818            ti85serial->send_backup_variable_number = 0;
819            ti85_free_serial_data_memory(device);
820            ti85serial->status = TI85_SEND_STOP;
821         }
822         break;
823   }
824}
825
826
827static void ti85_receive_variables (device_t *device)
828{
829   ti85serial_state *ti85serial = get_token( device );
830   char var_file_name[16];
831   UINT8* temp;
832   file_error filerr;
833
834   switch (ti85serial->status)
835   {
836      case TI85_RECEIVE_HEADER_1:
837         if(!ti85_receive_serial(device, ti85serial->receive_buffer+4*8, 3*8))
838         {
839            ti85_convert_stream_to_data (ti85serial->receive_buffer+4*8, 3*8, ti85serial->receive_data+4);
840            ti85serial->status = TI85_PREPARE_VARIABLE_DATA;
841         }
842         break;
843      case TI85_PREPARE_VARIABLE_DATA:
844         ti85serial->var_data = (UINT8*) malloc (ti85serial->receive_data[2]+2+ti85serial->receive_data[4]+ti85serial->receive_data[5]*256+2);
845         if(!ti85serial->var_data)
846            ti85serial->status = TI85_SEND_STOP;
847         memcpy (ti85serial->var_data, ti85serial->receive_data+2, 5);
848         ti85_free_serial_data_memory(device);
849         if (!ti85_alloc_serial_data_memory(device, ti85serial->var_data[0]-1))
850         {
851            free(ti85serial->var_data); ti85serial->var_data = NULL;
852            free(ti85serial->var_file_data); ti85serial->var_file_data = NULL;
853            ti85serial->status = TI85_SEND_STOP;
854            return;
855         }
856         ti85serial->status = TI85_RECEIVE_HEADER_2;
857      case TI85_RECEIVE_HEADER_2:
858         if(!ti85_receive_serial(device, ti85serial->receive_buffer, (ti85serial->var_data[0]-1)*8))
859         {
860            ti85_convert_stream_to_data (ti85serial->receive_buffer, (ti85serial->var_data[0]-1)*8, ti85serial->receive_data);
861            memcpy (ti85serial->var_data+5, ti85serial->receive_data, ti85serial->var_data[0]-3);
862            ti85_free_serial_data_memory(device);
863            if(!ti85_alloc_serial_data_memory (device, 8))
864            {
865               free(ti85serial->var_data); ti85serial->var_data = NULL;
866               free(ti85serial->var_file_data); ti85serial->var_file_data = NULL;
867               ti85serial->status = TI85_SEND_STOP;
868               return;
869            }
870            ti85_append_head_to_stream(ti85serial->receive_id, TI_OK_PACKET, ti85serial->receive_buffer);
871            ti85_append_head_to_stream(ti85serial->receive_id, TI_CONTINUE_PACKET,  ti85serial->receive_buffer+4*8);
872            ti85serial->status = TI85_SEND_OK_1;
873         }
874         break;
875      case TI85_SEND_OK_1:
876         if(!ti85_send_serial(device, ti85serial->receive_buffer, 4*8))
877            ti85serial->status = TI85_SEND_CONTINUE;
878         break;
879      case TI85_SEND_CONTINUE:
880         if(!ti85_send_serial(device, ti85serial->receive_buffer+4*8, 4*8))
881         {
882            ti85_free_serial_data_memory(device);
883            if(!ti85_alloc_serial_data_memory(device, 4))
884            {
885               free(ti85serial->var_data); ti85serial->var_data = NULL;
886               free(ti85serial->var_file_data); ti85serial->var_file_data = NULL;
887               ti85serial->status = TI85_SEND_STOP;
888               return;
889            }
890            ti85serial->status = TI85_RECEIVE_OK;
891         }
892         break;
893      case TI85_RECEIVE_OK:
894         if(!ti85_receive_serial (device, ti85serial->receive_buffer, 4*8))
895         {
896            ti85_convert_stream_to_data (ti85serial->receive_buffer, 4*8, ti85serial->receive_data);
897            ti85_free_serial_data_memory(device);
898            if(!ti85_alloc_serial_data_memory(device, ti85serial->var_data[2]+ti85serial->var_data[3]*256+6))
899            {
900               free(ti85serial->var_data); ti85serial->var_data = NULL;
901               free(ti85serial->var_file_data); ti85serial->var_file_data = NULL;
902               ti85serial->status = TI85_SEND_STOP;
903               return;
904            }
905            ti85serial->status = TI85_RECEIVE_DATA;
906         }
907         break;
908      case TI85_RECEIVE_DATA:
909         if(!ti85_receive_serial (device, ti85serial->receive_buffer, (ti85serial->var_data[2]+ti85serial->var_data[3]*256+6)*8))
910         {
911            ti85_convert_stream_to_data (ti85serial->receive_buffer, (ti85serial->var_data[2]+ti85serial->var_data[3]*256+6)*8, ti85serial->receive_data);
912            memcpy (ti85serial->var_data+ti85serial->var_data[0]+2, ti85serial->receive_data+2, ti85serial->var_data[2]+ti85serial->var_data[3]*256+2);
913            ti85_free_serial_data_memory(device);
914            if(!ti85_alloc_serial_data_memory (device, 4))
915            {
916               free(ti85serial->var_data); ti85serial->var_data = NULL;
917               free(ti85serial->var_file_data); ti85serial->var_file_data = NULL;
918               ti85serial->status = TI85_SEND_STOP;
919               return;
920            }
921            ti85_append_head_to_stream(ti85serial->receive_id, TI_OK_PACKET, ti85serial->receive_buffer);
922            ti85serial->status = TI85_SEND_OK_2;
923         }
924         break;
925      case TI85_SEND_OK_2:
926         if(!ti85_send_serial(device, ti85serial->receive_buffer, 4*8))
927         {
928            ti85_free_serial_data_memory(device);
929            if(!ti85_alloc_serial_data_memory(device, 7))
930            {
931               free(ti85serial->var_data); ti85serial->var_data = NULL;
932               free(ti85serial->var_file_data); ti85serial->var_file_data = NULL;
933               ti85serial->status = TI85_SEND_STOP;
934               return;
935            }
936            ti85serial->status =  TI85_RECEIVE_END_OR_HEADER_1;
937         }
938         break;
939      case TI85_RECEIVE_END_OR_HEADER_1:
940         if(!ti85_receive_serial (device, ti85serial->receive_buffer, 4*8))
941         {
942            if (ti85serial->variable_number == 0)
943            {
944               ti85serial->var_file_data = (UINT8*) malloc (0x39);
945               if (!ti85serial->var_file_data)
946               {
947                  free (ti85serial->var_data); ti85serial->var_data = NULL;
948                  free (ti85serial->var_file_data); ti85serial->var_file_data = NULL;
949                  ti85serial->status = TI85_SEND_STOP;
950               }
951               else
952               {
953                  memcpy(ti85serial->var_file_data, ti85_file_signature, 0x0b);
954                  memcpy(ti85serial->var_file_data+0x0b, "File created by MESS", 0x14);
955                  memset(ti85serial->var_file_data+0x1f, 0, 0x1a);
956                  ti85serial->var_file_size = 0x39;
957               }
958            }
959            temp = (UINT8*)malloc (ti85serial->var_file_size+ti85serial->var_data[0]+2+ti85serial->var_data[2]+ti85serial->var_data[3]*256+2);
960            if (temp)
961            {
962               memcpy (temp, ti85serial->var_file_data, ti85serial->var_file_size);
963               free (ti85serial->var_file_data);
964               ti85serial->var_file_data = temp;
965               memcpy (ti85serial->var_file_data + ti85serial->var_file_size -2, ti85serial->var_data, ti85serial->var_data[0]+2+ti85serial->var_data[2]+ti85serial->var_data[3]*256+2);
966               ti85serial->var_file_size += ti85serial->var_data[0]+2+ti85serial->var_data[2]+ti85serial->var_data[3]*256+2;
967               ti85serial->var_file_data[0x35] = (ti85serial->var_file_size-0x39)&0x00ff;
968               ti85serial->var_file_data[0x36] = ((ti85serial->var_file_size-0x39)&0xff00)>>8;
969               ti85serial->var_file_data[ti85serial->var_file_size-2] = ti85_calculate_checksum(ti85serial->var_file_data+0x37, ti85serial->var_file_size-0x39)&0x00ff;
970               ti85serial->var_file_data[ti85serial->var_file_size-1] = (ti85_calculate_checksum(ti85serial->var_file_data+0x37, ti85serial->var_file_size-0x39)&0xff00)>>8;
971            }
972            free (ti85serial->var_data);
973            ti85serial->var_data = NULL;
974            ti85serial->variable_number ++;
975
976            ti85_convert_stream_to_data (ti85serial->receive_buffer, 4*8, ti85serial->receive_data);
977            if (ti85serial->receive_data[1] == 0x06)
978               ti85serial->status = TI85_RECEIVE_HEADER_1;
979            else
980            {
981               ti85_free_serial_data_memory(device);
982               if(!ti85_alloc_serial_data_memory (device, 4))
983               {
984                  free(ti85serial->var_data); ti85serial->var_data = NULL;
985                  free(ti85serial->var_file_data); ti85serial->var_file_data = NULL;
986                  ti85serial->status = TI85_SEND_STOP;
987                  return;
988               }
989               ti85_append_head_to_stream(ti85serial->receive_id, TI_OK_PACKET, ti85serial->receive_buffer);
990               ti85serial->status = TI85_SEND_OK_3;
991            }
992         }
993         break;
994      case TI85_SEND_OK_3:
995         if(!ti85_send_serial(device, ti85serial->receive_buffer, 4*8))
996         {
997            ti85_free_serial_data_memory(device);
998            ti85serial->variable_number = 0;
999            ti85serial->status =  TI85_SEND_STOP;
1000            sprintf (var_file_name, "%08d.85g", ti85serial->var_file_number);
1001            emu_file var_file(device->machine().options().memcard_directory(), OPEN_FLAG_READ | OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
1002            filerr = var_file.open(var_file_name);
1003
1004            if (filerr == FILERR_NONE)
1005            {
1006               var_file.write(ti85serial->var_file_data, ti85serial->var_file_size);
1007               free (ti85serial->var_file_data);
1008               ti85serial->var_file_data = NULL;
1009               ti85serial->var_file_size = 0;
1010               ti85serial->var_file_number++;
1011            }
1012         }
1013         break;
1014   }
1015}
1016
1017
1018static void ti85_receive_backup (device_t *device)
1019{
1020   ti85serial_state *ti85serial = get_token( device );
1021
1022   file_error filerr;
1023   char backup_file_name[] = "00000000.85b";
1024
1025   switch (ti85serial->status)
1026   {
1027      case TI85_RECEIVE_HEADER_2:
1028         if(!ti85_receive_serial(device, ti85serial->receive_buffer+7*8, 8*8))
1029         {
1030            ti85_convert_stream_to_data (ti85serial->receive_buffer+7*8, 8*8, ti85serial->receive_data+7);
1031            ti85serial->backup_data_size[0] = ti85serial->receive_data[4] + ti85serial->receive_data[5]*256;
1032            ti85serial->backup_data_size[1] = ti85serial->receive_data[7] + ti85serial->receive_data[8]*256;
1033            ti85serial->backup_data_size[2] = ti85serial->receive_data[9] + ti85serial->receive_data[10]*256;
1034            ti85serial->backup_file_data = (UINT8*)malloc (0x42+0x06+ti85serial->backup_data_size[0]+ti85serial->backup_data_size[1]+ti85serial->backup_data_size[2]+0x02);
1035            if(!ti85serial->backup_file_data)
1036            {
1037               ti85serial->backup_variable_number = 0;
1038               ti85serial->status = TI85_SEND_STOP;
1039               return;
1040            }
1041            memcpy(ti85serial->backup_file_data, ti85_file_signature, 0x0b);
1042            memcpy(ti85serial->backup_file_data+0x0b, "File created by MESS", 0x14);
1043            memset(ti85serial->backup_file_data+0x1f, 0, 0x16);
1044            ti85serial->backup_file_data[0x35] = (ti85serial->backup_data_size[0]+ti85serial->backup_data_size[1]+ti85serial->backup_data_size[2]+0x11)&0x00ff;
1045            ti85serial->backup_file_data[0x36] = ((ti85serial->backup_data_size[0]+ti85serial->backup_data_size[1]+ti85serial->backup_data_size[2]+0x11)&0xff00)>>8;
1046            memcpy(ti85serial->backup_file_data+0x37, ti85serial->receive_data+0x02, 0x0b);
1047            ti85_free_serial_data_memory(device);
1048            if(!ti85_alloc_serial_data_memory (device, 8))
1049            {
1050               free(ti85serial->backup_file_data); ti85serial->backup_file_data = NULL;
1051               ti85serial->backup_variable_number = 0;
1052               ti85serial->status = TI85_SEND_STOP;
1053               return;
1054            }
1055            ti85_append_head_to_stream(ti85serial->receive_id, TI_OK_PACKET, ti85serial->receive_buffer);
1056            ti85_append_head_to_stream(ti85serial->receive_id, TI_CONTINUE_PACKET, ti85serial->receive_buffer+4*8);
1057            ti85serial->status = TI85_SEND_OK_1;
1058         }
1059         break;
1060      case TI85_SEND_OK_1:
1061         if(!ti85_send_serial(device, ti85serial->receive_buffer, 4*8))
1062            ti85serial->status = TI85_SEND_CONTINUE;
1063         break;
1064      case TI85_SEND_CONTINUE:
1065         if(!ti85_send_serial(device, ti85serial->receive_buffer+4*8, 4*8))
1066         {
1067            ti85_free_serial_data_memory(device);
1068            if(!ti85_alloc_serial_data_memory(device, 4))
1069            {
1070               free(ti85serial->backup_file_data); ti85serial->backup_file_data = NULL;
1071               ti85serial->backup_variable_number = 0;
1072               ti85serial->status = TI85_SEND_STOP;
1073               return;
1074            }
1075            ti85serial->status = TI85_RECEIVE_OK;
1076         }
1077         break;
1078      case TI85_RECEIVE_OK:
1079         if(!ti85_receive_serial (device, ti85serial->receive_buffer, 4*8))
1080         {
1081            ti85_convert_stream_to_data (ti85serial->receive_buffer, 4*8, ti85serial->receive_data);
1082            ti85_free_serial_data_memory(device);
1083            if(!ti85_alloc_serial_data_memory(device, ti85serial->backup_data_size[ti85serial->backup_variable_number]+6))
1084            {
1085               free(ti85serial->backup_file_data); ti85serial->backup_file_data = NULL;
1086               ti85serial->backup_variable_number = 0;
1087               ti85serial->status = TI85_SEND_STOP;
1088               return;
1089            }
1090            ti85serial->status = TI85_RECEIVE_DATA;
1091         }
1092         break;
1093      case TI85_RECEIVE_DATA:
1094         if(!ti85_receive_serial (device, ti85serial->receive_buffer, (ti85serial->backup_data_size[ti85serial->backup_variable_number]+6)*8))
1095         {
1096            ti85_convert_stream_to_data (ti85serial->receive_buffer, (ti85serial->backup_data_size[ti85serial->backup_variable_number]+6)*8, ti85serial->receive_data);
1097            switch (ti85serial->backup_variable_number)
1098            {
1099               case 0:
1100                  memcpy(ti85serial->backup_file_data+0x42, ti85serial->receive_data+0x02, ti85serial->backup_data_size[0]+0x02);
1101                  break;
1102               case 1:
1103                  memcpy(ti85serial->backup_file_data+0x42+ti85serial->backup_data_size[0]+0x02, ti85serial->receive_data+0x02, ti85serial->backup_data_size[1]+0x02);
1104                  break;
1105               case 2:
1106                  memcpy(ti85serial->backup_file_data+0x42+ti85serial->backup_data_size[0]+ti85serial->backup_data_size[1]+0x04, ti85serial->receive_data+0x02, ti85serial->backup_data_size[2]+0x02);
1107                  break;
1108            }
1109            ti85_free_serial_data_memory(device);
1110            if(!ti85_alloc_serial_data_memory (device, 4))
1111            {
1112               free(ti85serial->backup_file_data); ti85serial->backup_file_data = NULL;
1113               ti85serial->backup_variable_number = 0;
1114               ti85serial->status = TI85_SEND_STOP;
1115               return;
1116            }
1117            ti85_append_head_to_stream(ti85serial->receive_id, TI_OK_PACKET, ti85serial->receive_buffer);
1118            ti85serial->status = TI85_SEND_OK_2;
1119         }
1120         break;
1121      case TI85_SEND_OK_2:
1122         if(!ti85_send_serial(device, ti85serial->receive_buffer, 4*8))
1123         {
1124            ti85_free_serial_data_memory(device);
1125            ti85serial->backup_variable_number++;
1126            if (ti85serial->backup_variable_number<3)
1127            {
1128               if(!ti85_alloc_serial_data_memory(device, ti85serial->backup_data_size[ti85serial->backup_variable_number]+6))
1129               {
1130                  free(ti85serial->backup_file_data); ti85serial->backup_file_data = NULL;
1131                  ti85serial->backup_variable_number = 0;
1132                  ti85serial->status = TI85_SEND_STOP;
1133                  return;
1134               }
1135               ti85serial->status =  TI85_RECEIVE_DATA;
1136            }
1137            else
1138            {
1139               ti85serial->backup_variable_number = 0;
1140               ti85serial->backup_file_data[0x42+0x06+ti85serial->backup_data_size[0]+ti85serial->backup_data_size[1]+ti85serial->backup_data_size[2]] = ti85_calculate_checksum(ti85serial->backup_file_data+0x37, 0x42+ti85serial->backup_data_size[0]+ti85serial->backup_data_size[1]+ti85serial->backup_data_size[2]+0x06-0x37)&0x00ff;
1141               ti85serial->backup_file_data[0x42+0x06+ti85serial->backup_data_size[0]+ti85serial->backup_data_size[1]+ti85serial->backup_data_size[2]+0x01] = (ti85_calculate_checksum(ti85serial->backup_file_data+0x37, 0x42+ti85serial->backup_data_size[0]+ti85serial->backup_data_size[1]+ti85serial->backup_data_size[2]+0x06-0x37)&0xff00)>>8;
1142               sprintf (backup_file_name, "%08d.85b", ti85serial->backup_file_number);
1143
1144               emu_file backup_file(device->machine().options().memcard_directory(), OPEN_FLAG_READ | OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
1145               filerr = backup_file.open(backup_file_name);
1146
1147               if (filerr == FILERR_NONE)
1148               {
1149                  backup_file.write(ti85serial->backup_file_data, 0x42+0x06+ti85serial->backup_data_size[0]+ti85serial->backup_data_size[1]+ti85serial->backup_data_size[2]+0x02);
1150                  ti85serial->backup_file_number++;
1151               }
1152               free(ti85serial->backup_file_data); ti85serial->backup_file_data = NULL;
1153               ti85serial->status =  TI85_SEND_STOP;
1154            }
1155         }
1156         break;
1157   }
1158}
1159
1160static void ti85_receive_screen (device_t *device)
1161{
1162   ti85serial_state *ti85serial = get_token( device );
1163   char image_file_name[] = "00000000.85i";
1164   file_error filerr;
1165   UINT8 * image_file_data;
1166
1167   switch (ti85serial->status)
1168   {
1169      case TI85_PREPARE_SCREEN_REQUEST:
1170         if(!ti85_alloc_serial_data_memory (device, 4))
1171         {
1172            ti85serial->status = TI85_SEND_STOP;
1173            return;
1174         }
1175         ti85_append_head_to_stream(ti85serial->receive_id, TI_SCREEN_REQUEST_PACKET, ti85serial->receive_buffer);
1176         ti85serial->status = TI85_SEND_SCREEN_REQUEST;
1177         break;
1178      case TI85_SEND_SCREEN_REQUEST:
1179         if(!ti85_send_serial(device, ti85serial->receive_buffer, 4*8))
1180         {
1181            ti85_free_serial_data_memory(device);
1182            if(!ti85_alloc_serial_data_memory (device, 4))
1183            {
1184               ti85serial->status = TI85_SEND_STOP;
1185               return;
1186            }
1187            ti85serial->status = TI85_RECEIVE_OK;
1188         }
1189         break;
1190      case TI85_RECEIVE_OK:
1191         if(!ti85_receive_serial (device, ti85serial->receive_buffer, 4*8))
1192         {
1193            ti85_convert_stream_to_data (ti85serial->receive_buffer, 4*8, ti85serial->receive_data);
1194            ti85_free_serial_data_memory(device);
1195            if(!ti85_alloc_serial_data_memory (device, 1030))
1196            {
1197               ti85serial->status = TI85_SEND_STOP;
1198               return;
1199            }
1200            ti85serial->status = TI85_RECEIVE_DATA;
1201         }
1202         break;
1203      case TI85_RECEIVE_DATA:
1204         if(!ti85_receive_serial (device, ti85serial->receive_buffer, 1030*8))
1205         {
1206            ti85_convert_stream_to_data (ti85serial->receive_buffer, 1030*8, ti85serial->receive_data);
1207            sprintf (image_file_name, "%08d.85i", ti85serial->image_file_number);
1208
1209            emu_file image_file(device->machine().options().memcard_directory(), OPEN_FLAG_READ | OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
1210            filerr = image_file.open(image_file_name);
1211
1212            if (filerr == FILERR_NONE)
1213            {
1214               image_file_data = (UINT8*)malloc (0x49+1008);
1215               if(!image_file_data)
1216               {
1217                  ti85_free_serial_data_memory(device);
1218                  ti85serial->status = TI85_SEND_OK;
1219                  return;
1220               }
1221               memcpy(image_file_data, ti85_file_signature, 0x0b);
1222               memcpy(image_file_data+0x0b, "File created by MESS", 0x14);
1223               memset(image_file_data+0x1f, 0, 0x16);
1224               image_file_data[0x35] = 0x00;
1225               image_file_data[0x36] = 0x04;
1226               image_file_data[0x37] = 0x0a; //header size
1227               image_file_data[0x38] = 0x00;
1228               image_file_data[0x39] = 0xf2; //data size
1229               image_file_data[0x3a] = 0x03;
1230               image_file_data[0x3b] = 0x11; //data type
1231               image_file_data[0x3c] = 0x06; //name size
1232               memcpy(image_file_data+0x3d, "Screen", 0x06);
1233               image_file_data[0x43] = 0xf2;
1234               image_file_data[0x44] = 0x03;
1235               image_file_data[0x45] = 0xf0;
1236               image_file_data[0x46] = 0x03;
1237               memcpy(image_file_data+0x47, ti85serial->receive_data+4, 1008);
1238               image_file_data[1008+0x49-2] = ti85_calculate_checksum(image_file_data+0x37, 1008+0x10)&0x00ff;
1239               image_file_data[1008+0x49-1] = (ti85_calculate_checksum(image_file_data+0x37, 1008+0x10)&0xff00)>>8;
1240               image_file.write(image_file_data, 1008+0x49);
1241               free(image_file_data);
1242               ti85serial->image_file_number++;
1243            }
1244            ti85_free_serial_data_memory(device);
1245            if(!ti85_alloc_serial_data_memory (device, 4))
1246            {
1247               ti85serial->status = TI85_SEND_STOP;
1248               return;
1249            }
1250            ti85_append_head_to_stream(ti85serial->receive_id, TI_OK_PACKET, ti85serial->receive_buffer);
1251            ti85serial->status = TI85_SEND_OK;
1252         }
1253         break;
1254      case TI85_SEND_OK:
1255         if(!ti85_send_serial(device, ti85serial->receive_buffer, 4*8))
1256         {
1257            ti85_free_serial_data_memory(device);
1258            ti85serial->status = TI85_SEND_STOP;
1259         }
1260         break;
1261   }
1262}
1263
1264
1265void ti85_update_serial (device_t *device)
1266{
1267   ti85serial_state *ti85serial = get_token( device );
1268
1269   if (ti85serial->status == TI85_SEND_STOP)
1270   {
1271      if (input_port_read(*device, "SERIAL") & 0x01)
1272      {
1273         if(!ti85_alloc_serial_data_memory(device, 15)) return;
1274         if(!ti85_receive_serial (device, ti85serial->receive_buffer, 7*8))
1275         {
1276            ti85_convert_stream_to_data (ti85serial->receive_buffer, 7*8, ti85serial->receive_data);
1277            if (ti85serial->receive_data[0]!=0x85 || ti85serial->receive_data[1]!=0x06)
1278            {
1279               ti85_receive_serial (device, NULL, 0);
1280               return;
1281            }
1282            ti85serial->transfer_type = (ti85serial->receive_data[6]==0x1d) ? TI85_RECEIVE_BACKUP : TI85_RECEIVE_VARIABLES;
1283            ti85serial->status = (ti85serial->receive_data[6]==0x1d) ? TI85_RECEIVE_HEADER_2 : TI85_PREPARE_VARIABLE_DATA;
1284         }
1285      }
1286      else
1287      {
1288         ti85_receive_serial(device, NULL, 0);
1289         ti85_free_serial_data_memory(device);
1290         if (input_port_read(*device, "DUMP") & 0x01)
1291         {
1292            ti85serial->status = TI85_PREPARE_SCREEN_REQUEST;
1293            ti85serial->transfer_type = TI85_RECEIVE_SCREEN;
1294         }
1295         return;
1296      }
1297   }
1298
1299   switch (ti85serial->transfer_type)
1300   {
1301      case TI85_SEND_VARIABLES:
1302         ti85_send_variables(device);
1303         break;
1304      case TI85_SEND_BACKUP:
1305         ti85_send_backup(device);
1306         break;
1307      case TI85_RECEIVE_BACKUP:
1308         ti85_receive_backup(device);
1309         break;
1310      case TI85_RECEIVE_VARIABLES:
1311         ti85_receive_variables(device);
1312         break;
1313      case TI85_RECEIVE_SCREEN:
1314         ti85_receive_screen(device);
1315         break;
1316   }
1317}
1318
1319
1320WRITE8_DEVICE_HANDLER( ti85serial_red_out )
1321{
1322   ti85serial_state *ti85serial = get_token( device );
1323
1324   ti85serial->red_out = data;
1325}
1326
1327
1328WRITE8_DEVICE_HANDLER( ti85serial_white_out )
1329{
1330   ti85serial_state *ti85serial = get_token( device );
1331
1332   ti85serial->white_out = data;
1333}
1334
1335
1336READ8_DEVICE_HANDLER( ti85serial_red_in )
1337{
1338   ti85serial_state *ti85serial = get_token( device );
1339
1340   return ti85serial->red_in;
1341}
1342
1343
1344READ8_DEVICE_HANDLER( ti85serial_white_in )
1345{
1346   ti85serial_state *ti85serial = get_token( device );
1347
1348   return ti85serial->white_in;
1349}
1350
1351
1352static DEVICE_START( ti85serial )
1353{
1354   ti85serial_state *ti85serial = get_token( device );
1355
1356   ti85serial->transfer_type = TI85_SEND_VARIABLES;
1357   ti85serial->receive_buffer = NULL;
1358   ti85serial->receive_data = NULL;
1359   ti85serial->var_file_number = 0;
1360   ti85serial->backup_file_number = 0;
1361   ti85serial->image_file_number = 0;
1362}
1363
1364
1365static DEVICE_STOP( ti85serial )
1366{
1367   ti85serial_state *ti85serial = get_token( device );
1368
1369   ti85_free_serial_data_memory(device);
1370   if (ti85serial->var_data)
1371   {
1372      free(ti85serial->var_data); ti85serial->var_data = NULL;
1373   }
1374   if (ti85serial->var_file_data)
1375   {
1376      free(ti85serial->var_file_data); ti85serial->var_file_data = NULL;
1377   }
1378   if (ti85serial->backup_file_data)
1379   {
1380      free(ti85serial->backup_file_data); ti85serial->backup_file_data = NULL;
1381   }
1382}
1383
1384
1385static DEVICE_RESET( ti85serial )
1386{
1387   ti85serial_state *ti85serial = get_token( device );
1388
1389   ti85serial->receive_data_counter = 0;
1390   ti85serial->send_data_counter = 0;
1391   ti85_free_serial_data_memory(device);
1392   ti85serial->red_in = 0;
1393   ti85serial->white_in = 0;
1394   ti85serial->red_out = 1;
1395   ti85serial->white_out = 1;
1396   ti85serial->variables_variable_number = 0;
1397   ti85serial->send_backup_variable_number = 0;
1398   ti85serial->var_data = NULL;
1399   ti85serial->var_file_data = NULL;
1400   ti85serial->var_file_size = 0;
1401   ti85serial->variable_number = 0;
1402   ti85serial->backup_file_data = NULL;
1403   ti85serial->backup_variable_number = 0;
1404   ti85serial->status = TI85_SEND_STOP;
1405
1406   //initialize the receive_id used for TI to PC transfer
1407   if (device->type() == TI73SERIAL)
1408      ti85serial->receive_id = TI_TRANFER_ID_TI73;
1409   else if (device->type() == TI85SERIAL)
1410      ti85serial->receive_id = TI_TRANFER_ID_TI85;
1411   else if (device->type() == TI82SERIAL)
1412      ti85serial->receive_id = TI_TRANFER_ID_TI82;
1413   else if (device->type() == TI83PSERIAL)
1414      ti85serial->receive_id = TI_TRANFER_ID_TI83P;
1415   else if (device->type() == TI86SERIAL)
1416      ti85serial->receive_id = TI_TRANFER_ID_TI86;
1417
1418   ti85serial->send_id = ti85serial->receive_id;
1419}
1420
1421
1422static DEVICE_IMAGE_LOAD( ti85serial )
1423{
1424   ti85serial_state *ti85serial = get_token( image );
1425   UINT8* file_data;
1426   UINT16 file_size;
1427
1428   if (ti85serial->status != TI85_SEND_STOP) return IMAGE_INIT_FAIL;
1429
1430   file_size = image.length();
1431
1432   if (file_size != 0)
1433   {
1434      file_data = auto_alloc_array(image.device().machine(), UINT8, file_size);
1435      image.fread( file_data, file_size);
1436
1437      if(!ti85_convert_file_data_to_serial_stream(image, file_data, file_size, &ti85serial->stream))
1438      {
1439         ti85_free_serial_stream (&ti85serial->stream);
1440         return IMAGE_INIT_FAIL;
1441      }
1442
1443      ti85serial->status = TI85_SEND_HEADER;
1444   }
1445   else
1446   {
1447      return IMAGE_INIT_FAIL;
1448   }
1449   return IMAGE_INIT_PASS;
1450}
1451
1452
1453static DEVICE_IMAGE_UNLOAD( ti85serial )
1454{
1455   ti85serial_state *ti85serial = get_token( image );
1456
1457   ti85_free_serial_data_memory(image);
1458   ti85serial->status = TI85_SEND_STOP;
1459   ti85_free_serial_stream (&ti85serial->stream);
1460}
1461
1462
1463static INPUT_PORTS_START ( ti85serial )
1464   PORT_START("SERIAL")   /* receive data from calculator */
1465      PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Receive data") PORT_CODE(KEYCODE_R)
1466   PORT_START("DUMP")   /* screen dump requesting */
1467      PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Screen dump request") PORT_CODE(KEYCODE_S)
1468INPUT_PORTS_END
1469
1470
1471DEVICE_GET_INFO( ti85serial )
1472{
1473   switch ( state )
1474   {
1475   case DEVINFO_INT_TOKEN_BYTES:               info->i = sizeof( ti85serial_state );                                 break;
1476   case DEVINFO_INT_INLINE_CONFIG_BYTES:         info->i = 0;                                                   break;
1477   case DEVINFO_INT_IMAGE_TYPE:               info->i = IO_SERIAL;                                             break;
1478   case DEVINFO_INT_IMAGE_READABLE:            info->i = 1;                                                   break;
1479   case DEVINFO_INT_IMAGE_WRITEABLE:            info->i = 0;                                                   break;
1480   case DEVINFO_INT_IMAGE_CREATABLE:            info->i = 0;                                                   break;
1481   case DEVINFO_FCT_START:                     info->start = DEVICE_START_NAME( ti85serial );                           break;
1482   case DEVINFO_FCT_RESET:                     info->reset = DEVICE_RESET_NAME( ti85serial );                           break;
1483   case DEVINFO_FCT_STOP:                     info->stop = DEVICE_STOP_NAME( ti85serial );                           break;
1484   case DEVINFO_FCT_IMAGE_LOAD:               info->f = (genf *) DEVICE_IMAGE_LOAD_NAME( ti85serial );                  break;
1485   case DEVINFO_FCT_IMAGE_UNLOAD:               info->f = (genf *) DEVICE_IMAGE_UNLOAD_NAME( ti85serial );                  break;
1486   case DEVINFO_PTR_INPUT_PORTS:               info->ipt = INPUT_PORTS_NAME( ti85serial );                              break;
1487   case DEVINFO_STR_IMAGE_BRIEF_INSTANCE_NAME:      strcpy(info->s, "ser");                                             break;
1488   case DEVINFO_STR_IMAGE_INSTANCE_NAME:         strcpy(info->s, "serial");                                          break;
1489   case DEVINFO_STR_NAME:                     strcpy(info->s, "TI85 Serial");                                       break;
1490   case DEVINFO_STR_FAMILY:                  strcpy(info->s, "serial protocol");                                    break;
1491   case DEVINFO_STR_SOURCE_FILE:               strcpy(info->s, __FILE__);                                          break;
1492   case DEVINFO_STR_IMAGE_FILE_EXTENSIONS:         strcpy(info->s, "85p,85s,85i,85n,85c,85l,85k,85m,85v,85d,85e,85r,85g,85b");      break;
1493   }
1494}
1495
1496DEVICE_GET_INFO( ti73serial )
1497{
1498   switch ( state )
1499   {
1500   case DEVINFO_STR_NAME:                     strcpy(info->s, "TI73 Serial");                                       break;
1501   case DEVINFO_STR_IMAGE_FILE_EXTENSIONS:         strcpy(info->s, "73p,73s,73i,73n,73c,73l,73k,73m,73v,73d,73e,73r,73g");         break;
1502   default:                              DEVICE_GET_INFO_CALL( ti85serial );
1503   }
1504}
1505
1506DEVICE_GET_INFO( ti82serial )
1507{
1508   switch ( state )
1509   {
1510   case DEVINFO_STR_NAME:                     strcpy(info->s, "TI82 Serial");                                       break;
1511   case DEVINFO_STR_IMAGE_FILE_EXTENSIONS:         strcpy(info->s, "82p,82s,82i,82n,82c,82l,82k,82m,82v,82d,82e,82r,82g");         break;
1512   default:                              DEVICE_GET_INFO_CALL( ti85serial );
1513   }
1514}
1515
1516
1517DEVICE_GET_INFO( ti83pserial )
1518{
1519   switch ( state )
1520   {
1521   case DEVINFO_STR_NAME:                     strcpy(info->s, "TI83 Plus Serial");                                    break;
1522   case DEVINFO_STR_IMAGE_FILE_EXTENSIONS:         strcpy(info->s, "82p,82s,82i,82n,82c,82l,82k,82m,82v,82d,82e,82r,82g,"   //for TI-82 compatibility
1523                                                   "83p,83s,83i,83n,83c,83l,83k,83m,83v,83d,83e,83r,83g,"   //for TI-83 compatibility
1524                                                   "8xc,8xd,8xg,8xi,8xl,8xm,8xn,8xp,8xs,8xt,8xv,8xw,8xy,8xz");   break;
1525   default:                              DEVICE_GET_INFO_CALL( ti85serial );
1526   }
1527}
1528
1529DEVICE_GET_INFO( ti86serial )
1530{
1531   switch ( state )
1532   {
1533   case DEVINFO_STR_NAME:                     strcpy(info->s, "TI86 Serial");                                       break;
1534   case DEVINFO_STR_IMAGE_FILE_EXTENSIONS:         strcpy(info->s, "85p,85s,85i,85n,85c,85l,85k,85m,85v,85d,85e,85r,85g,85b" //for TI-85 compatibility
1535                                                   "86p,86s,86i,86n,86c,86l,86k,86m,86v,86d,86e,86r,86g");         break;
1536   default:                              DEVICE_GET_INFO_CALL( ti85serial );
1537   }
1538}
1539
1540DEFINE_LEGACY_IMAGE_DEVICE(TI85SERIAL, ti85serial);
1541DEFINE_LEGACY_IMAGE_DEVICE(TI73SERIAL, ti73serial);
1542DEFINE_LEGACY_IMAGE_DEVICE(TI82SERIAL, ti82serial);
1543DEFINE_LEGACY_IMAGE_DEVICE(TI83PSERIAL, ti83pserial);
1544DEFINE_LEGACY_IMAGE_DEVICE(TI86SERIAL, ti86serial);
trunk/src/mess/machine/ti85_ser.h
r17575r17576
1
2#ifndef __TI85SERIAL_H_
3#define __TI85SERIAL_H_
4
5
6DECLARE_LEGACY_IMAGE_DEVICE(TI85SERIAL, ti85serial);
7DECLARE_LEGACY_IMAGE_DEVICE(TI73SERIAL, ti73serial);
8DECLARE_LEGACY_IMAGE_DEVICE(TI82SERIAL, ti82serial);
9DECLARE_LEGACY_IMAGE_DEVICE(TI83PSERIAL, ti83pserial);
10DECLARE_LEGACY_IMAGE_DEVICE(TI86SERIAL, ti86serial);
11
12extern void ti85_update_serial(device_t *device);
13
14#define MCFG_TI85SERIAL_ADD( _tag ) \
15      MCFG_DEVICE_ADD( _tag, TI85SERIAL, 0 )
16
17#define MCFG_TI73SERIAL_ADD( _tag ) \
18      MCFG_DEVICE_ADD( _tag, TI73SERIAL, 0 )
19
20#define MCFG_TI82SERIAL_ADD( _tag ) \
21      MCFG_DEVICE_ADD( _tag, TI82SERIAL, 0 )
22
23#define MCFG_TI83PSERIAL_ADD( _tag ) \
24      MCFG_DEVICE_ADD( _tag, TI83PSERIAL, 0 )
25
26#define MCFG_TI86SERIAL_ADD( _tag ) \
27      MCFG_DEVICE_ADD( _tag, TI86SERIAL, 0 )
28
29WRITE8_DEVICE_HANDLER( ti85serial_red_out );
30WRITE8_DEVICE_HANDLER( ti85serial_white_out );
31READ8_DEVICE_HANDLER( ti85serial_red_in );
32READ8_DEVICE_HANDLER( ti85serial_white_in );
33
34#endif
trunk/src/mess/machine/ap2_slot.c
r17575r17576
1/*********************************************************************
2
3    ap2_slot.c
4
5    Implementation of Apple II device slots
6
7*********************************************************************/
8
9#include "ap2_slot.h"
10#include "includes/apple2.h"
11
12/***************************************************************************
13    TYPE DEFINITIONS
14***************************************************************************/
15
16typedef struct _apple2_slot_token apple2_slot_token;
17struct _apple2_slot_token
18{
19   device_t *slot_device;
20};
21
22
23
24/***************************************************************************
25    INLINE FUNCTIONS
26***************************************************************************/
27
28INLINE void assert_valid(device_t *device)
29{
30   assert(device != NULL);
31   assert(device->type() == APPLE2_SLOT);
32}
33
34
35
36INLINE const apple2_slot_config *get_config(device_t *device)
37{
38   assert_valid(device);
39   return (const apple2_slot_config *) downcast<const legacy_device_base *>(device)->inline_config();
40}
41
42
43
44INLINE apple2_slot_token *get_token(device_t *device)
45{
46   assert_valid(device);
47   return (apple2_slot_token *) downcast<legacy_device_base *>(device)->token();
48}
49
50
51
52/***************************************************************************
53    CORE IMPLEMENTATION
54***************************************************************************/
55
56/*-------------------------------------------------
57    apple2_slot - looks up a slot
58-------------------------------------------------*/
59
60device_t *apple2_slot(running_machine &machine, int slotnum)
61{
62   char buffer[7];
63
64   assert((slotnum >= 0) && (slotnum <= 7));
65   snprintf(buffer, ARRAY_LENGTH(buffer), "slot_%d", slotnum);
66
67   return machine.device(buffer);
68}
69
70
71
72/*-------------------------------------------------
73    DEVICE_START(apple2_slot) - device start
74    function
75-------------------------------------------------*/
76
77static DEVICE_START(apple2_slot)
78{
79   const apple2_slot_config *config = get_config(device);
80   apple2_slot_token *token = get_token(device);
81
82   if (config->tag != NULL)
83   {
84      /* locate the device */
85      token->slot_device = device->machine().device(config->tag);
86
87      assert(token->slot_device != NULL);
88   }
89   else
90   {
91      token->slot_device = NULL;
92   }
93}
94
95
96
97/*-------------------------------------------------
98    apple2_slot_r - slot read function
99-------------------------------------------------*/
100
101READ8_DEVICE_HANDLER(apple2_slot_r)
102{
103   UINT8 result = 0x00;
104   const apple2_slot_config *config = get_config(device);
105   apple2_slot_token *token = get_token(device);
106
107   /* do we actually have a device, and can we read? */
108   if ((token->slot_device != NULL) && (config->rh != NULL))
109   {
110      result = (*config->rh)(token->slot_device, offset);
111   }
112
113   return result;
114}
115
116
117
118/*-------------------------------------------------
119    apple2_slot_w - slot write function
120-------------------------------------------------*/
121
122WRITE8_DEVICE_HANDLER(apple2_slot_w)
123{
124   const apple2_slot_config *config = get_config(device);
125   apple2_slot_token *token = get_token(device);
126
127   /* do we actually have a device, and can we read? */
128   if ((token->slot_device != NULL) && (config->wh != NULL))
129   {
130      (*config->wh)(token->slot_device, offset, data);
131   }
132}
133
134/*-------------------------------------------------
135    apple2_c800_slot_r - slot read function
136-------------------------------------------------*/
137
138READ8_DEVICE_HANDLER(apple2_c800_slot_r)
139{
140   UINT8 result = 0x00;
141   const apple2_slot_config *config = get_config(device);
142   apple2_slot_token *token = get_token(device);
143
144   /* do we actually have a device, and can we read? */
145   if ((token->slot_device != NULL) && (config->rhc800 != NULL))
146   {
147      result = (*config->rhc800)(token->slot_device, offset);
148   }
149
150   return result;
151}
152
153/*-------------------------------------------------
154    apple2_c800_slot_w - slot write function
155-------------------------------------------------*/
156
157WRITE8_DEVICE_HANDLER(apple2_c800_slot_w)
158{
159   const apple2_slot_config *config = get_config(device);
160   apple2_slot_token *token = get_token(device);
161
162   /* do we actually have a device, and can we read? */
163   if ((token->slot_device != NULL) && (config->whc800 != NULL))
164   {
165      (*config->whc800)(token->slot_device, offset, data);
166   }
167}
168
169/*-------------------------------------------------
170    apple2_slot_ROM_w - slot ROM read function
171-------------------------------------------------*/
172READ8_DEVICE_HANDLER(apple2_slot_ROM_r)
173{
174   const apple2_slot_config *config = get_config(device);
175   apple2_slot_token *token = get_token(device);
176
177   /* do we actually have a device, and can we read? */
178   if ((token->slot_device != NULL) && (config->rhcnxx != NULL))
179   {
180      return (*config->rhcnxx)(token->slot_device, offset);
181   }
182
183   if (config->slotnum > 0)
184   {
185      return apple2_slotram_r(device->machine(), config->slotnum, offset + ((config->slotnum-1)<<8));
186   }
187
188   return apple2_getfloatingbusvalue(device->machine());
189}
190
191/*-------------------------------------------------
192    apple2_slot_ROM_w - slot ROM write function
193-------------------------------------------------*/
194
195WRITE8_DEVICE_HANDLER(apple2_slot_ROM_w)
196{
197   const apple2_slot_config *config = get_config(device);
198   apple2_slot_token *token = get_token(device);
199
200   /* do we actually have a device, and can we write? */
201   if ((token->slot_device != NULL) && (config->whcnxx != NULL))
202   {
203      (*config->whcnxx)(token->slot_device, offset, data);
204   }
205}
206
207/*-------------------------------------------------
208    DEVICE_GET_INFO(apple2_slot) - device get info
209    function
210-------------------------------------------------*/
211
212DEVICE_GET_INFO(apple2_slot)
213{
214   switch (state)
215   {
216      /* --- the following bits of info are returned as 64-bit signed integers --- */
217      case DEVINFO_INT_TOKEN_BYTES:               info->i = sizeof(apple2_slot_token);      break;
218      case DEVINFO_INT_INLINE_CONFIG_BYTES:         info->i = sizeof(apple2_slot_config);      break;
219
220      /* --- the following bits of info are returned as pointers to data or functions --- */
221      case DEVINFO_FCT_START:                     info->start = DEVICE_START_NAME(apple2_slot);   break;
222      case DEVINFO_FCT_STOP:                     /* Nothing */                        break;
223      case DEVINFO_FCT_RESET:                     /* Nothing */                        break;
224
225      /* --- the following bits of info are returned as NULL-terminated strings --- */
226      case DEVINFO_STR_NAME:                     strcpy(info->s, "Apple II Slot");               break;
227      case DEVINFO_STR_FAMILY:                  strcpy(info->s, "Apple II Slot");               break;
228      case DEVINFO_STR_VERSION:                  strcpy(info->s, "1.0");                     break;
229      case DEVINFO_STR_SOURCE_FILE:               strcpy(info->s, __FILE__);                     break;
230   }
231}
232
233DEFINE_LEGACY_DEVICE(APPLE2_SLOT, apple2_slot);
trunk/src/mess/machine/ap2_slot.h
r17575r17576
1/*********************************************************************
2
3    ap2_slot.h
4
5    Implementation of Apple II device slots
6
7*********************************************************************/
8
9#ifndef __AP2_SLOT__
10#define __AP2_SLOT__
11
12#include "emu.h"
13
14/***************************************************************************
15    CONSTANTS
16***************************************************************************/
17
18DECLARE_LEGACY_DEVICE(APPLE2_SLOT, apple2_slot);
19
20
21
22/***************************************************************************
23    TYPE DEFINITIONS
24***************************************************************************/
25
26typedef struct _apple2_slot_config apple2_slot_config;
27struct _apple2_slot_config
28{
29   const char *tag;
30   int slotnum;         // slot number
31
32   read8_device_func rh;      // C0nX I/O space (DEVSEL)
33   write8_device_func wh;
34
35   read8_device_func rhcnxx;   // CnXX ROM space (IOSEL)
36   write8_device_func whcnxx;
37
38   read8_device_func rhc800;   // C800 ROM extension space (IOSTB)
39   write8_device_func whc800;
40};
41
42
43
44/***************************************************************************
45    DEVICE CONFIGURATION MACROS
46***************************************************************************/
47
48#define MCFG_APPLE2_SLOT_ADD(_slot_number, _slot_device_tag, _rh, _wh, _rhc800, _whc800, _rhcnxx, _whcnxx)      \
49   MCFG_DEVICE_ADD("slot_" #_slot_number, APPLE2_SLOT, 0)         \
50   MCFG_DEVICE_CONFIG_DATAPTR(apple2_slot_config, tag, _slot_device_tag)   \
51   MCFG_DEVICE_CONFIG_DATA32(apple2_slot_config, slotnum, _slot_number)      \
52   MCFG_DEVICE_CONFIG_DATAPTR(apple2_slot_config, rh, _rh)      \
53   MCFG_DEVICE_CONFIG_DATAPTR(apple2_slot_config, wh, _wh)      \
54   MCFG_DEVICE_CONFIG_DATAPTR(apple2_slot_config, rhc800, _rhc800)      \
55   MCFG_DEVICE_CONFIG_DATAPTR(apple2_slot_config, whc800, _whc800)      \
56   MCFG_DEVICE_CONFIG_DATAPTR(apple2_slot_config, rhcnxx, _rhcnxx)      \
57   MCFG_DEVICE_CONFIG_DATAPTR(apple2_slot_config, whcnxx, _whcnxx)      \
58
59
60
61/***************************************************************************
62    FUNCTION PROTOTYPES
63***************************************************************************/
64/* slot read function */
65READ8_DEVICE_HANDLER(apple2_slot_r);
66
67/* slot write function */
68WRITE8_DEVICE_HANDLER(apple2_slot_w);
69
70/* slot ROM read function */
71READ8_DEVICE_HANDLER(apple2_slot_ROM_r);
72
73/* slot ROM write function */
74WRITE8_DEVICE_HANDLER(apple2_slot_ROM_w);
75
76/* slot extended ROM read function */
77READ8_DEVICE_HANDLER(apple2_c800_slot_r);
78
79/* slot extended ROM write function */
80WRITE8_DEVICE_HANDLER(apple2_c800_slot_w);
81
82/* slot device lookup */
83device_t *apple2_slot(running_machine &machine, int slotnum);
84
85#endif /* __AP2_SLOT__ */
trunk/src/mess/machine/jupiter.c
r17575r17576
1/***************************************************************************
2
3  machine.c
4
5  Functions to emulate general aspects of the machine (RAM, ROM, interrupts,
6  I/O ports)
7
8***************************************************************************/
9
10#include "emu.h"
11#include "cpu/z80/z80.h"
12#include "imagedev/snapquik.h"
13#include "includes/jupiter.h"
14
15
16
17/* Load in .ace files. These are memory images of 0x2000 to 0x7fff
18   and compressed as follows:
19
20   ED 00        : End marker
21   ED <cnt> <byt>   : repeat <byt> count <cnt:1-240> times
22   <byt>        : <byt>
23*/
24
25
26/******************************************************************************
27 Snapshot Handling
28******************************************************************************/
29
30SNAPSHOT_LOAD(jupiter)
31{
32   UINT8 *RAM = image.device().machine().root_device().memregion("maincpu")->base();
33   device_t *cpu = image.device().machine().device("maincpu");
34   address_space *space = image.device().machine().device("maincpu")->memory().space(AS_PROGRAM);
35   unsigned char jupiter_repeat, jupiter_byte, loop;
36   int done=0, jupiter_index=0x2000;
37
38   if (space->machine().root_device().ioport("CFG")->read()==0)
39   {
40      image.seterror(IMAGE_ERROR_INVALIDIMAGE, "At least 16KB RAM expansion required");
41      image.message("At least 16KB RAM expansion required");
42      return IMAGE_INIT_FAIL;
43   }
44
45   logerror("Loading file %s.\r\n", image.filename());
46   while (!done && (jupiter_index < 0x8001))
47   {
48      image.fread( &jupiter_byte, 1);
49      if (jupiter_byte == 0xed)
50      {
51         image.fread(&jupiter_byte, 1);
52         switch (jupiter_byte)
53         {
54         case 0x00:
55               logerror("File loaded!\r\n");
56               done = 1;
57               break;
58         case 0x01:
59               image.fread(&jupiter_byte, 1);
60               RAM[jupiter_index++] = jupiter_byte;
61               break;
62         default:
63               image.fread(&jupiter_repeat, 1);
64               for (loop = 0; loop < jupiter_byte; loop++)
65                  RAM[jupiter_index++] = jupiter_repeat;
66               break;
67         }
68      }
69      else
70         RAM[jupiter_index++] = jupiter_byte;
71   }
72
73   logerror("Decoded %X bytes.\r\n", jupiter_index-0x2000);
74
75   if (!done)
76   {
77      image.seterror(IMAGE_ERROR_INVALIDIMAGE, "EOF marker not found");
78      image.message("EOF marker not found");
79      return IMAGE_INIT_FAIL;
80   }
81
82        // patch CPU registers
83        // Some games do not follow the standard, and have rubbish in the CPU area. So,
84        // we check that some other bytes are correct.
85        // 2080 = memory size of original machine, should be 0000 or 8000 or C000.
86        // 2118 = new stack pointer, do not use if between 8000 and FF00.
87
88   jupiter_index = RAM[0x2080] | (RAM[0x2081] << 8);
89
90   if ((jupiter_index & 0x3FFF)==0)
91   {
92      cpu_set_reg(cpu, Z80_AF, RAM[0x2100] | (RAM[0x2101] << 8));
93      cpu_set_reg(cpu, Z80_BC, RAM[0x2104] | (RAM[0x2105] << 8));
94      cpu_set_reg(cpu, Z80_DE, RAM[0x2108] | (RAM[0x2109] << 8));
95      cpu_set_reg(cpu, Z80_HL, RAM[0x210c] | (RAM[0x210d] << 8));
96      cpu_set_reg(cpu, Z80_IX, RAM[0x2110] | (RAM[0x2111] << 8));
97      cpu_set_reg(cpu, Z80_IY, RAM[0x2114] | (RAM[0x2115] << 8));
98      cpu_set_reg(cpu, STATE_GENPC, RAM[0x211c] | (RAM[0x211d] << 8));
99      cpu_set_reg(cpu, Z80_AF2, RAM[0x2120] | (RAM[0x2121] << 8));
100      cpu_set_reg(cpu, Z80_BC2, RAM[0x2124] | (RAM[0x2125] << 8));
101      cpu_set_reg(cpu, Z80_DE2, RAM[0x2128] | (RAM[0x2129] << 8));
102      cpu_set_reg(cpu, Z80_HL2, RAM[0x212c] | (RAM[0x212d] << 8));
103      cpu_set_reg(cpu, Z80_IM, RAM[0x2130]);
104      cpu_set_reg(cpu, Z80_IFF1, RAM[0x2134]);
105      cpu_set_reg(cpu, Z80_IFF2, RAM[0x2138]);
106      cpu_set_reg(cpu, Z80_I, RAM[0x213c]);
107      cpu_set_reg(cpu, Z80_R, RAM[0x2140]);
108
109      if ((RAM[0x2119] < 0x80) || !jupiter_index)
110         cpu_set_reg(cpu, STATE_GENSP, RAM[0x2118] | (RAM[0x2119] << 8));
111   }
112
113   /* Copy data to the address space */
114   for (jupiter_index = 0x2000; jupiter_index < 0x8000; jupiter_index++)
115      space->write_byte(jupiter_index, RAM[jupiter_index]);
116
117   return IMAGE_INIT_PASS;
118}
119
trunk/src/mess/drivers/c16.c
r17575r17576
1/***************************************************************************
2    commodore c16 home computer
3
4    PeT mess@utanet.at
5
6    documentation
7     www.funet.fi
8
9***************************************************************************/
10
11/*
12
132008 - Driver Updates
14---------------------
15
16(most of the informations are taken from http://www.zimmers.net/cbmpics/ )
17
18
19[CBM systems which belong to this driver]
20
21* Commodore 116 (1984, Europe only)
22
23  Entry level computer of the Commodore 264 family, it was marketed only
24in Europe. It was impressive for the small size of its case, but it didn't
25meet commercial success
26
27CPU: MOS Technology 7501 (variable clock rate, with max 1.76 MHz)
28RAM: 16 kilobytes (expandable to 64k internally)
29ROM: 32 kilobytes
30Video: MOS Technology 7360 "TED" (5 Video modes; Max. Resolution 320x200;
31    40 columns text; Palette of 16 colors in 8 shades, for 128 colors)
32Sound: MOS Technology 7360 "TED" (2 voice tone-generating sound capabilities)
33Ports: MOS 7360 (2 Joystick/Mouse ports; CBM Serial port; 'TED' port; "TV"
34    Port and switch; CBM Monitor port; Power and reset switches; Power
35    connector)
36Keyboard: QWERTY 62 key "membrane" (8 programmable function keys; 4 direction
37    cursor-pad)
38
39
40* Commodore 16 (1984)
41
42  Redesigned version of the C116, with a different case and a different
43keyboard.
44
45CPU: MOS Technology 7501 (variable clock rate, with max 1.76 MHz)
46RAM: 16 kilobytes (expandable to 64k internally)
47ROM: 32 kilobytes
48Video: MOS Technology 7360 "TED" (5 Video modes; Max. Resolution 320x200;
49    40 columns text; Palette of 16 colors in 8 shades, for 128 colors)
50Sound: MOS Technology 7360 "TED" (2 voice tone-generating sound capabilities)
51Ports: MOS 7360 (2 Joystick/Mouse ports; CBM Serial port; 'TED' port; "TV"
52    Port and switch; CBM Monitor port; Power and reset switches; Power
53    connector)
54Keyboard: QWERTY 66 key typewriter style (8 programmable function keys;
55    4 direction cursor-pad)
56
57
58* Commodore Plus/4 (1984)
59
60  This system became the middle tier of the Commodore 264 family, replacing
61the original Commodore 264. The Plus/4 is basically the same as the C264,
62but the name refers to the four built-in programs which came with the
63machine: Word Processing, Spreadsheet, Database software, Graphing package.
64
65CPU: MOS Technology 7501 (variable clock rate, with max 1.76 MHz)
66RAM: 64 kilobytes (expandable to 64k internally)
67ROM: 64 kilobytes
68Video: MOS Technology 7360 "TED" (5 Video modes; Max. Resolution 320x200;
69    40 columns text; Palette of 16 colors in 8 shades, for 128 colors)
70Sound: MOS Technology 7360 "TED" (2 voice tone-generating sound capabilities)
71Ports: MOS 7360 (2 Joystick/Mouse ports; CBM Serial port; 'TED' port; "TV"
72    Port and switch; CBM Monitor port; Power and reset switches; Power
73    connector)
74Keyboard: Full-sized QWERTY 67 key (8 programmable function keys;
75    4 direction cursor-pad)
76
77
78* Commodore 232 (1984, Prototype)
79
80  This system never reached the production and only few units exist. It is
81in between the C16 and the C264, with its 32 kilobytes of RAM.
82
83
84* Commodore 264 (1984, Prototype)
85
86  Basically the same of a Plus/4 but without the built-in programs.
87
88
89* Commodore V364 (1984, Prototype)
90
91  This system was supposed to become the high-end system of the family,
92featuring 64 kilobytes of RAM, the same technology of the Plus/4, a
93keyboard with numeric keypad and built in voice synthesis capabilities.
94
95[TO DO]
96
97* Supported Systems:
98
99- Once we can add / remove devices, we shall only support c16, c116 and plus/4,
100removing the separated drivers for different floppy drives
101
102* Other Peripherals:
103
104- Lightpen support is unfinished
105- Missing support for (it might or might not be added eventually):
106printers and other devices; most expansion modules; userport; rs232/v.24 interface.
107
108* System Specific
109
110- V364 lacks speech hardware emulation
111
112*/
113
114
115#include "emu.h"
116#include "audio/ted7360.h"
117#include "audio/t6721.h"
118#include "cpu/m6502/m6502.h"
119#include "machine/ram.h"
120#include "formats/cbm_snqk.h"
121#include "includes/cbm.h"
122#include "includes/c16.h"
123#include "machine/c1551.h"
124#include "machine/cbmiec.h"
125#include "machine/cbmipt.h"
126#include "sound/sid6581.h"
127#include "machine/plus4exp.h"
128#include "machine/plus4user.h"
129
130
131/*************************************
132 *
133 *  Main CPU memory handlers
134 *
135 *************************************/
136
137
138/*
139 * commodore c16/c116/plus 4
140 * 16 KByte (C16/C116) or 32 KByte or 64 KByte (plus4) RAM
141 * 32 KByte Rom (C16/C116) 64 KByte Rom (plus4)
142 * availability to append additional 64 KByte Rom
143 *
144 * ports 0xfd00 till 0xff3f are always read/writeable for the cpu
145 * for the video interface chip it seams to read from
146 * ram or from rom in this  area
147 *
148 * writes go always to ram
149 * only 16 KByte Ram mapped to 0x4000,0x8000,0xc000
150 * only 32 KByte Ram mapped to 0x8000
151 *
152 * rom bank at 0x8000: 16K Byte(low bank)
153 * first: basic
154 * second(plus 4 only): plus4 rom low
155 * third: expansion slot
156 * fourth: expansion slot
157 * rom bank at 0xc000: 16K Byte(high bank)
158 * first: kernal
159 * second(plus 4 only): plus4 rom high
160 * third: expansion slot
161 * fourth: expansion slot
162 * writes to 0xfddx select rom banks:
163 * address line 0 and 1: rom bank low
164 * address line 2 and 3: rom bank high
165 *
166 * writes to 0xff3e switches to roms (0x8000 till 0xfd00, 0xff40 till 0xffff)
167 * writes to 0xff3f switches to rams
168 *
169 * at 0xfc00 till 0xfcff is ram or rom kernal readable
170 */
171
172static ADDRESS_MAP_START(c16_map, AS_PROGRAM, 8, c16_state )
173   AM_RANGE(0x0000, 0x3fff) AM_RAMBANK("bank9")
174   AM_RANGE(0x4000, 0x7fff) AM_READ_BANK("bank1") AM_WRITE_BANK("bank5")      /* only ram memory configuration */
175   AM_RANGE(0x8000, 0xbfff) AM_READ_BANK("bank2") AM_WRITE_BANK("bank6")
176   AM_RANGE(0xc000, 0xfbff) AM_READ_BANK("bank3")
177   AM_RANGE(0xfc00, 0xfcff) AM_READ_BANK("bank4")
178   AM_RANGE(0xc000, 0xfcff) AM_WRITE_BANK("bank7")
179   AM_RANGE(0xfd10, 0xfd1f) AM_READ_LEGACY(c16_fd1x_r)
180   AM_RANGE(0xfd30, 0xfd3f) AM_READWRITE_LEGACY(c16_6529_port_r, c16_6529_port_w)      /* 6529 keyboard matrix */
181   AM_RANGE(0xfdd0, 0xfddf) AM_WRITE_LEGACY(c16_select_roms) /* rom chips selection */
182   AM_RANGE(0xff00, 0xff1f) AM_DEVREADWRITE_LEGACY("ted7360", ted7360_port_r, ted7360_port_w)
183   AM_RANGE(0xff20, 0xffff) AM_READ_BANK("bank8")
184   AM_RANGE(0xff3e, 0xff3e) AM_WRITE_LEGACY(c16_switch_to_rom)
185   AM_RANGE(0xff3f, 0xff3f) AM_WRITE_LEGACY(c16_switch_to_ram)
186ADDRESS_MAP_END
187
188static ADDRESS_MAP_START(plus4_map, AS_PROGRAM, 8, c16_state )
189   AM_RANGE(0x0000, 0x7fff) AM_READ_BANK("bank9")
190   AM_RANGE(0x8000, 0xbfff) AM_READ_BANK("bank2")
191   AM_RANGE(0xc000, 0xfbff) AM_READ_BANK("bank3")
192   AM_RANGE(0xfc00, 0xfcff) AM_READ_BANK("bank4")
193   AM_RANGE(0x0000, 0xfcff) AM_WRITE_BANK("bank9")
194   AM_RANGE(0xfd00, 0xfd0f) AM_READWRITE_LEGACY(c16_6551_port_r, c16_6551_port_w)
195   AM_RANGE(0xfd10, 0xfd1f) AM_READWRITE_LEGACY(plus4_6529_port_r, plus4_6529_port_w)
196   AM_RANGE(0xfd30, 0xfd3f) AM_READWRITE_LEGACY(c16_6529_port_r, c16_6529_port_w) /* 6529 keyboard matrix */
197   AM_RANGE(0xfdd0, 0xfddf) AM_WRITE_LEGACY(c16_select_roms) /* rom chips selection */
198   AM_RANGE(0xff00, 0xff1f) AM_DEVREADWRITE_LEGACY("ted7360", ted7360_port_r, ted7360_port_w)
199   AM_RANGE(0xff20, 0xffff) AM_READ_BANK("bank8")
200   AM_RANGE(0xff20, 0xff3d) AM_WRITEONLY
201   AM_RANGE(0xff3e, 0xff3e) AM_WRITE_LEGACY(c16_switch_to_rom)
202   AM_RANGE(0xff3f, 0xff3f) AM_WRITE_LEGACY(c16_switch_to_ram)
203   AM_RANGE(0xff40, 0xffff) AM_WRITEONLY
204ADDRESS_MAP_END
205
206static ADDRESS_MAP_START(c364_map , AS_PROGRAM, 8, c16_state )
207   AM_RANGE(0x0000, 0x7fff) AM_READ_BANK("bank9")
208   AM_RANGE(0x8000, 0xbfff) AM_READ_BANK("bank2")
209   AM_RANGE(0xc000, 0xfbff) AM_READ_BANK("bank3")
210   AM_RANGE(0xfc00, 0xfcff) AM_READ_BANK("bank4")
211   AM_RANGE(0x0000, 0xfcff) AM_WRITE_BANK("bank9")
212   AM_RANGE(0xfd00, 0xfd0f) AM_READWRITE_LEGACY(c16_6551_port_r, c16_6551_port_w)
213   AM_RANGE(0xfd10, 0xfd1f) AM_READWRITE_LEGACY(plus4_6529_port_r, plus4_6529_port_w)
214   AM_RANGE(0xfd20, 0xfd2f) AM_DEVREADWRITE_LEGACY("t6721", t6721_speech_r, t6721_speech_w)
215   AM_RANGE(0xfd30, 0xfd3f) AM_READWRITE_LEGACY(c16_6529_port_r, c16_6529_port_w) /* 6529 keyboard matrix */
216   AM_RANGE(0xfdd0, 0xfddf) AM_WRITE_LEGACY(c16_select_roms) /* rom chips selection */
217   AM_RANGE(0xff00, 0xff1f) AM_DEVREADWRITE_LEGACY("ted7360", ted7360_port_r, ted7360_port_w)
218   AM_RANGE(0xff20, 0xffff) AM_READ_BANK("bank8")
219   AM_RANGE(0xff20, 0xff3d) AM_WRITEONLY
220   AM_RANGE(0xff3e, 0xff3e) AM_WRITE_LEGACY(c16_switch_to_rom)
221   AM_RANGE(0xff3f, 0xff3f) AM_WRITE_LEGACY(c16_switch_to_ram)
222   AM_RANGE(0xff40, 0xffff) AM_WRITEONLY
223ADDRESS_MAP_END
224
225
226/*************************************
227 *
228 *  Input Ports
229 *
230 *************************************/
231
232static INPUT_PORTS_START( c16 )
233   PORT_INCLUDE( common_cbm_keyboard )      /* ROW0 -> ROW7 */
234
235   PORT_MODIFY("ROW0")
236   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("@") PORT_CODE(KEYCODE_OPENBRACE)            PORT_CHAR('@')
237   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F3)                           PORT_CHAR(UCHAR_MAMEKEY(F3)) PORT_CHAR(UCHAR_MAMEKEY(F6))
238   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F2)                           PORT_CHAR(UCHAR_MAMEKEY(F2)) PORT_CHAR(UCHAR_MAMEKEY(F5))
239   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F1)                           PORT_CHAR(UCHAR_MAMEKEY(F1)) PORT_CHAR(UCHAR_MAMEKEY(F4))
240   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("HELP f7") PORT_CODE(KEYCODE_F4)            PORT_CHAR(UCHAR_MAMEKEY(F8)) PORT_CHAR(UCHAR_MAMEKEY(F7))
241   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_INSERT)                        PORT_CHAR(0xA3)
242
243   PORT_MODIFY("ROW1")
244   /* Both Shift keys were mapped to the same bit */
245   PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Shift (Left & Right)") PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT)
246
247   PORT_MODIFY("ROW4")
248   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("0  \xE2\x86\x91") PORT_CODE(KEYCODE_0)      PORT_CHAR('0') PORT_CHAR(0x2191)
249
250   PORT_MODIFY("ROW5")
251   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("-") PORT_CODE(KEYCODE_MINUS)               PORT_CHAR('-')
252   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_BACKSLASH2)                     PORT_CHAR(UCHAR_MAMEKEY(UP))
253   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_PGUP)                           PORT_CHAR(UCHAR_MAMEKEY(DOWN))
254
255   PORT_MODIFY("ROW6")
256   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_CLOSEBRACE)                     PORT_CHAR('+')
257   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("=  Pi  \xE2\x86\x90") PORT_CODE(KEYCODE_PGDN)   PORT_CHAR('=') PORT_CHAR(0x03C0) PORT_CHAR(0x2190)
258   PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_ESC)                           PORT_CHAR(UCHAR_MAMEKEY(ESC))
259   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_EQUALS)                        PORT_CHAR(UCHAR_MAMEKEY(RIGHT))
260   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_BACKSLASH)                        PORT_CHAR('*')
261   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_MINUS)                           PORT_CHAR(UCHAR_MAMEKEY(LEFT))
262
263   PORT_MODIFY("ROW7")
264   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Home Clear") PORT_CODE(KEYCODE_DEL)         PORT_CHAR(UCHAR_MAMEKEY(HOME))
265
266   PORT_INCLUDE( c16_special )            /* SPECIAL */
267
268   PORT_INCLUDE( c16_controls )         /* CTRLSEL, JOY0, JOY1 */
269INPUT_PORTS_END
270
271
272static INPUT_PORTS_START( plus4 )
273   PORT_INCLUDE( c16 )
274
275   PORT_MODIFY( "ROW0" )
276   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_CLOSEBRACE)               PORT_CHAR(0xA3)
277   PORT_MODIFY( "ROW5" )
278   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_EQUALS)                  PORT_CHAR('-')
279   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_UP)                     PORT_CHAR(UCHAR_MAMEKEY(UP))
280   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_DOWN)                     PORT_CHAR(UCHAR_MAMEKEY(DOWN))
281   PORT_MODIFY( "ROW6" )
282   PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_MINUS)                     PORT_CHAR('+')
283   PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("=  Pi  \xE2\x86\x90") PORT_CODE(KEYCODE_BACKSLASH2)   PORT_CHAR('=') PORT_CHAR(0x03C0) PORT_CHAR(0x2190)
284   PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_RIGHT)                     PORT_CHAR(UCHAR_MAMEKEY(RIGHT))
285   PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_INSERT)                  PORT_CHAR('*')
286   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_LEFT)                     PORT_CHAR(UCHAR_MAMEKEY(LEFT))
287INPUT_PORTS_END
288
289static INPUT_PORTS_START( c16sid )
290   PORT_INCLUDE( c16 )
291
292   PORT_START("SID")
293   PORT_CONFNAME( 0x01, 0x00, "SID Card Address")
294   PORT_CONFSETTING(   0x00, "0xfd40" )
295   PORT_CONFSETTING(   0x01, "0xfe80" )
296#if 0
297   PORT_CONFNAME( 0x02, 0x00, "Enable SID writes to 0xd400")
298   PORT_CONFSETTING(   0x00, DEF_STR( No ) )
299   PORT_CONFSETTING(   0x02, DEF_STR( Yes ) )
300#endif
301INPUT_PORTS_END
302
303
304static INPUT_PORTS_START( plus4sid )
305   PORT_INCLUDE( plus4 )
306
307   PORT_START("SID")
308   PORT_CONFNAME( 0x01, 0x00, "SID Card Address")
309   PORT_CONFSETTING(   0x00, "0xfd40" )
310   PORT_CONFSETTING(   0x01, "0xfe80" )
311#if 0
312   PORT_CONFNAME( 0x02, 0x00, "Enable SID writes to 0xd400")
313   PORT_CONFSETTING(   0x00, DEF_STR( No ) )
314   PORT_CONFSETTING(   0x02, DEF_STR( Yes ) )
315#endif
316INPUT_PORTS_END
317
318
319/*************************************
320 *
321 *  Graphics definitions
322 *
323 *************************************/
324
325static const unsigned char ted7360_palette[] =
326{
327/* black, white, red, cyan */
328/* purple, green, blue, yellow */
329/* orange, light orange, pink, light cyan, */
330/* light violett, light green, light blue, light yellow */
331/* these 16 colors are 8 times here in different luminance (dark..light) */
332/* taken from digitized tv screenshot */
333   0x06, 0x01, 0x03, 0x2b, 0x2b, 0x2b, 0x67, 0x0e, 0x0f, 0x00, 0x3f, 0x42,
334   0x57, 0x00, 0x6d, 0x00, 0x4e, 0x00, 0x19, 0x1c, 0x94, 0x38, 0x38, 0x00,
335   0x56, 0x20, 0x00, 0x4b, 0x28, 0x00, 0x16, 0x48, 0x00, 0x69, 0x07, 0x2f,
336   0x00, 0x46, 0x26, 0x06, 0x2a, 0x80, 0x2a, 0x14, 0x9b, 0x0b, 0x49, 0x00,
337
338   0x00, 0x03, 0x02, 0x3d, 0x3d, 0x3d, 0x75, 0x1e, 0x20, 0x00, 0x50, 0x4f,
339   0x6a, 0x10, 0x78, 0x04, 0x5c, 0x00, 0x2a, 0x2a, 0xa3, 0x4c, 0x47, 0x00,
340   0x69, 0x2f, 0x00, 0x59, 0x38, 0x00, 0x26, 0x56, 0x00, 0x75, 0x15, 0x41,
341   0x00, 0x58, 0x3d, 0x15, 0x3d, 0x8f, 0x39, 0x22, 0xae, 0x19, 0x59, 0x00,
342
343   0x00, 0x03, 0x04, 0x42, 0x42, 0x42, 0x7b, 0x28, 0x20, 0x02, 0x56, 0x59,
344   0x6f, 0x1a, 0x82, 0x0a, 0x65, 0x09, 0x30, 0x34, 0xa7, 0x50, 0x51, 0x00,
345   0x6e, 0x36, 0x00, 0x65, 0x40, 0x00, 0x2c, 0x5c, 0x00, 0x7d, 0x1e, 0x45,
346   0x01, 0x61, 0x45, 0x1c, 0x45, 0x99, 0x42, 0x2d, 0xad, 0x1d, 0x62, 0x00,
347
348   0x05, 0x00, 0x02, 0x56, 0x55, 0x5a, 0x90, 0x3c, 0x3b, 0x17, 0x6d, 0x72,
349   0x87, 0x2d, 0x99, 0x1f, 0x7b, 0x15, 0x46, 0x49, 0xc1, 0x66, 0x63, 0x00,
350   0x84, 0x4c, 0x0d, 0x73, 0x55, 0x00, 0x40, 0x72, 0x00, 0x91, 0x33, 0x5e,
351   0x19, 0x74, 0x5c, 0x32, 0x59, 0xae, 0x59, 0x3f, 0xc3, 0x32, 0x76, 0x00,
352
353   0x02, 0x01, 0x06, 0x84, 0x7e, 0x85, 0xbb, 0x67, 0x68, 0x45, 0x96, 0x96,
354   0xaf, 0x58, 0xc3, 0x4a, 0xa7, 0x3e, 0x73, 0x73, 0xec, 0x92, 0x8d, 0x11,
355   0xaf, 0x78, 0x32, 0xa1, 0x80, 0x20, 0x6c, 0x9e, 0x12, 0xba, 0x5f, 0x89,
356   0x46, 0x9f, 0x83, 0x61, 0x85, 0xdd, 0x84, 0x6c, 0xef, 0x5d, 0xa3, 0x29,
357
358   0x02, 0x00, 0x0a, 0xb2, 0xac, 0xb3, 0xe9, 0x92, 0x92, 0x6c, 0xc3, 0xc1,
359   0xd9, 0x86, 0xf0, 0x79, 0xd1, 0x76, 0x9d, 0xa1, 0xff, 0xbd, 0xbe, 0x40,
360   0xdc, 0xa2, 0x61, 0xd1, 0xa9, 0x4c, 0x93, 0xc8, 0x3d, 0xe9, 0x8a, 0xb1,
361   0x6f, 0xcd, 0xab, 0x8a, 0xb4, 0xff, 0xb2, 0x9a, 0xff, 0x88, 0xcb, 0x59,
362
363   0x02, 0x00, 0x0a, 0xc7, 0xca, 0xc9, 0xff, 0xac, 0xac, 0x85, 0xd8, 0xe0,
364   0xf3, 0x9c, 0xff, 0x92, 0xea, 0x8a, 0xb7, 0xba, 0xff, 0xd6, 0xd3, 0x5b,
365   0xf3, 0xbe, 0x79, 0xe6, 0xc5, 0x65, 0xb0, 0xe0, 0x57, 0xff, 0xa4, 0xcf,
366   0x89, 0xe5, 0xc8, 0xa4, 0xca, 0xff, 0xca, 0xb3, 0xff, 0xa2, 0xe5, 0x7a,
367
368   0x01, 0x01, 0x01, 0xff, 0xff, 0xff, 0xff, 0xf6, 0xf2, 0xd1, 0xff, 0xff,
369   0xff, 0xe9, 0xff, 0xdb, 0xff, 0xd3, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xa3,
370   0xff, 0xff, 0xc1, 0xff, 0xff, 0xb2, 0xfc, 0xff, 0xa2, 0xff, 0xee, 0xff,
371   0xd1, 0xff, 0xff, 0xeb, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xed, 0xff, 0xbc
372};
373
374static PALETTE_INIT( c16 )
375{
376   int i;
377
378   for (i = 0; i < sizeof(ted7360_palette) / 3; i++)
379      palette_set_color_rgb(machine, i, ted7360_palette[i * 3], ted7360_palette[i * 3 + 1], ted7360_palette[i * 3 + 2]);
380}
381
382/*************************************
383 *
384 *  TED7360 interfaces
385 *
386 *************************************/
387
388static const ted7360_interface c16_ted7360_intf = {
389   "screen",
390   TED7360_PAL,
391   c16_dma_read,
392   c16_dma_read_rom,
393   c16_interrupt,
394   c16_read_keyboard
395};
396
397static const ted7360_interface plus4_ted7360_intf = {
398   "screen",
399   TED7360_NTSC,
400   c16_dma_read,
401   c16_dma_read_rom,
402   c16_interrupt,
403   c16_read_keyboard
404};
405
406
407/*************************************
408 *
409 *  Machine driver
410 *
411 *************************************/
412
413static const m6502_interface c16_m7501_interface =
414{
415   NULL,               /* read_indexed_func */
416   NULL,               /* write_indexed_func */
417   DEVCB_HANDLER(c16_m7501_port_read),   /* port_read_func */
418   DEVCB_HANDLER(c16_m7501_port_write)   /* port_write_func */
419};
420
421static CBM_IEC_INTERFACE( cbm_iec_intf )
422{
423   DEVCB_NULL,
424   DEVCB_NULL,
425   DEVCB_NULL,
426   DEVCB_NULL,
427   DEVCB_NULL
428};
429
430static PLUS4_EXPANSION_INTERFACE( expansion_intf )
431{
432   DEVCB_NULL,
433   DEVCB_NULL,
434   DEVCB_NULL,
435   DEVCB_NULL,
436   DEVCB_NULL
437};
438
439static PLUS4_USER_PORT_INTERFACE( user_intf )
440{
441   DEVCB_NULL
442};
443
444static SCREEN_UPDATE_IND16( c16 )
445{
446   c16_state *state = screen.machine().driver_data<c16_state>();
447   ted7360_video_update(state->m_ted7360, bitmap, cliprect);
448   return 0;
449}
450
451static INTERRUPT_GEN( c16_raster_interrupt )
452{
453   c16_state *state = device->machine().driver_data<c16_state>();
454   ted7360_raster_interrupt_gen(state->m_ted7360);
455}
456
457
458static MACHINE_START( c16 )
459{
460   c16_state *state = machine.driver_data<c16_state>();
461
462   state->m_maincpu = machine.device<legacy_cpu_device>("maincpu");
463   state->m_ted7360 = machine.device("ted7360");
464   state->m_cassette = machine.device<cassette_image_device>(CASSETTE_TAG);
465   state->m_messram = machine.device<ram_device>(RAM_TAG);
466   state->m_sid = machine.device("sid");
467
468   state->save_item(NAME(state->m_old_level));
469   state->save_item(NAME(state->m_lowrom));
470   state->save_item(NAME(state->m_highrom));
471   state->save_item(NAME(state->m_port6529));
472   state->save_item(NAME(state->m_keyline));
473}
474
475static MACHINE_CONFIG_START( c16, c16_state )
476   /* basic machine hardware */
477   MCFG_CPU_ADD("maincpu", M7501, XTAL_17_73447MHz/20)
478   MCFG_CPU_PROGRAM_MAP(c16_map)
479   MCFG_CPU_CONFIG( c16_m7501_interface )
480   MCFG_CPU_VBLANK_INT("screen", c16_frame_interrupt)
481   MCFG_CPU_PERIODIC_INT(c16_raster_interrupt, TED7360_HRETRACERATE)
482   MCFG_QUANTUM_TIME(attotime::from_hz(60))
483
484   MCFG_MACHINE_START( c16 )
485   MCFG_MACHINE_RESET( c16 )
486
487   /* video hardware */
488   MCFG_SCREEN_ADD("screen", RASTER)
489   MCFG_SCREEN_REFRESH_RATE(TED7360PAL_VRETRACERATE)
490   MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) /* not accurate */
491   MCFG_SCREEN_SIZE(336, 216)
492   MCFG_SCREEN_VISIBLE_AREA(0, 336 - 1, 0, 216 - 1)
493   MCFG_SCREEN_UPDATE_STATIC( c16 )
494
495   MCFG_PALETTE_LENGTH(ARRAY_LENGTH(ted7360_palette) / 3)
496   MCFG_PALETTE_INIT(c16)
497
498   /* sound hardware */
499   MCFG_SPEAKER_STANDARD_MONO("mono")
500   MCFG_TED7360_ADD("ted7360", c16_ted7360_intf)
501   MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
502
503   /* devices */
504   MCFG_QUICKLOAD_ADD("quickload", cbm_c16, "p00,prg", CBM_QUICKLOAD_DELAY_SECONDS)
505
506   /* cassette */
507   MCFG_CASSETTE_ADD( CASSETTE_TAG, cbm_cassette_interface )
508
509   MCFG_FRAGMENT_ADD(c16_cartslot)
510
511   MCFG_C1551_ADD(C1551_TAG, 8)
512   MCFG_SOFTWARE_LIST_ADD("disk_list", "plus4_flop")
513
514   /* IEC serial bus */
515   MCFG_CBM_IEC_ADD(cbm_iec_intf, NULL)
516
517   MCFG_PLUS4_EXPANSION_SLOT_ADD(PLUS4_EXPANSION_SLOT_TAG, XTAL_17_73447MHz/20, expansion_intf, plus4_expansion_cards, NULL, NULL)
518   MCFG_PLUS4_USER_PORT_ADD(PLUS4_USER_PORT_TAG, user_intf, plus4_user_port_cards, NULL, NULL)
519
520   /* internal ram */
521   MCFG_RAM_ADD(RAM_TAG)
522   MCFG_RAM_DEFAULT_SIZE("64K")
523   MCFG_RAM_EXTRA_OPTIONS("16K,32K")
524MACHINE_CONFIG_END
525
526static MACHINE_CONFIG_DERIVED( plus4, c16 )
527   MCFG_CPU_MODIFY( "maincpu" )
528   MCFG_CPU_CLOCK( XTAL_14_31818MHz/16 )
529   MCFG_CPU_PROGRAM_MAP(plus4_map)
530   MCFG_CPU_CONFIG( c16_m7501_interface )
531
532   MCFG_SCREEN_MODIFY("screen")
533   MCFG_SCREEN_REFRESH_RATE(TED7360NTSC_VRETRACERATE)
534
535   MCFG_DEVICE_REMOVE("ted7360")
536   MCFG_TED7360_ADD("ted7360", plus4_ted7360_intf)
537   MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
538
539   /* internal ram */
540   MCFG_RAM_MODIFY(RAM_TAG)
541   MCFG_RAM_DEFAULT_SIZE("64K")
542MACHINE_CONFIG_END
543
544static MACHINE_CONFIG_DERIVED( c364, plus4 )
545   MCFG_SCREEN_MODIFY("screen")
546   MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) /* not accurate */
547   MCFG_CPU_MODIFY( "maincpu" )
548   MCFG_CPU_PROGRAM_MAP(c364_map)
549
550   MCFG_T6721_ADD("t6721")
551MACHINE_CONFIG_END
552
553static MACHINE_CONFIG_DERIVED( c264, c16 )
554   /* internal ram */
555   MCFG_RAM_MODIFY(RAM_TAG)
556   MCFG_RAM_DEFAULT_SIZE("64K")
557MACHINE_CONFIG_END
558
559static MACHINE_CONFIG_DERIVED( c16sid, c16 )
560
561   MCFG_SOUND_ADD("sid", SID8580, TED7360PAL_CLOCK/4)
562   MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
563MACHINE_CONFIG_END
564
565static MACHINE_CONFIG_DERIVED( plus4sid, plus4 )
566
567   MCFG_SOUND_ADD("sid", SID8580, TED7360NTSC_CLOCK/4)
568   MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
569MACHINE_CONFIG_END
570
571
572/*************************************
573 *
574 *  ROM definition(s)
575 *
576 *************************************/
577ROM_START( c232 )
578   ROM_REGION( 0x40000, "maincpu", 0 )
579   ROM_LOAD( "318006-01.bin", 0x10000, 0x4000, CRC(74eaae87) SHA1(161c96b4ad20f3a4f2321808e37a5ded26a135dd) )
580   ROM_LOAD( "318004-01.bin", 0x14000, 0x4000, CRC(dbdc3319) SHA1(3c77caf72914c1c0a0875b3a7f6935cd30c54201) )
581ROM_END
582
583ROM_START( c264 )
584   ROM_REGION( 0x40000, "maincpu", 0 )
585   ROM_LOAD( "basic-264.bin", 0x10000, 0x4000, CRC(6a2fc8e3) SHA1(473fce23afa07000cdca899fbcffd6961b36a8a0) )
586   ROM_LOAD( "kernal-264.bin", 0x14000, 0x4000, CRC(8f32abe7) SHA1(d481faf5fcbb331878dc7851c642d04f26a32873) )
587ROM_END
588
589ROM_START( c364 )
590   ROM_REGION( 0x40000, "maincpu", 0 )
591   ROM_LOAD( "318006.01", 0x10000, 0x4000, CRC(74eaae87) SHA1(161c96b4ad20f3a4f2321808e37a5ded26a135dd) )
592   ROM_LOAD( "kern364p.bin", 0x14000, 0x4000, CRC(84fd4f7a) SHA1(b9a5b5dacd57ca117ef0b3af29e91998bf4d7e5f) )
593   ROM_LOAD( "317053-01.bin", 0x18000, 0x4000, CRC(4fd1d8cb) SHA1(3b69f6e7cb4c18bb08e203fb18b7dabfa853390f) )
594   ROM_LOAD( "317054-01.bin", 0x1c000, 0x4000, CRC(109de2fc) SHA1(0ad7ac2db7da692d972e586ca0dfd747d82c7693) )
595   /* at address 0x20000 not so good */
596   ROM_LOAD( "spk3cc4.bin", 0x28000, 0x4000, CRC(5227c2ee) SHA1(59af401cbb2194f689898271c6e8aafa28a7af11) )
597ROM_END
598
599
600ROM_START( c16 )
601   ROM_REGION( 0x40000, "maincpu", 0 )
602   ROM_DEFAULT_BIOS("r5")
603   ROM_LOAD( "318006-01.u3", 0x10000, 0x4000, CRC(74eaae87) SHA1(161c96b4ad20f3a4f2321808e37a5ded26a135dd) )
604
605   ROM_SYSTEM_BIOS( 0, "r3", "rev. 3" )
606   ROMX_LOAD( "318004-03.u4", 0x14000, 0x4000, CRC(77bab934) SHA1(97814dab9d757fe5a3a61d357a9a81da588a9783), ROM_BIOS(1) )
607   ROM_SYSTEM_BIOS( 1, "r4", "rev. 4" )
608   ROMX_LOAD( "318004-04.u4", 0x14000, 0x4000, CRC(be54ed79) SHA1(514ad3c29d01a2c0a3b143d9c1d4143b1912b793), ROM_BIOS(2) )
609   ROM_SYSTEM_BIOS( 2, "r5", "rev. 5" )
610   ROMX_LOAD( "318004-05.u4", 0x14000, 0x4000, CRC(71c07bd4) SHA1(7c7e07f016391174a557e790c4ef1cbe33512cdb), ROM_BIOS(3) )
611ROM_END
612
613#define rom_c16c rom_c16
614#define rom_c16v rom_c16
615
616#define rom_c116      rom_c16
617#define rom_c116c      rom_c16c
618#define rom_c116v      rom_c16v
619
620ROM_START( c16hun )
621   ROM_REGION( 0x40000, "maincpu", 0 )
622   ROM_LOAD( "318006-01.u3", 0x10000, 0x4000, CRC(74eaae87) SHA1(161c96b4ad20f3a4f2321808e37a5ded26a135dd) )
623   ROM_LOAD( "hungary.u4",   0x14000, 0x4000, CRC(775f60c5) SHA1(20cf3c4bf6c54ef09799af41887218933f2e27ee) )
624ROM_END
625
626ROM_START( plus4 )
627   ROM_REGION( 0x40000, "maincpu", 0 )
628   ROM_DEFAULT_BIOS("r5")
629   ROM_SYSTEM_BIOS( 0, "r4", "rev. 4" )
630   ROMX_LOAD( "318005-04.u24", 0x14000, 0x4000, CRC(799a633d) SHA1(5df52c693387c0e2b5d682613a3b5a65477311cf), ROM_BIOS(1) )
631   ROM_SYSTEM_BIOS( 1, "r5", "rev. 5" )
632   ROMX_LOAD( "318005-05.u24", 0x14000, 0x4000, CRC(70295038) SHA1(a3d9e5be091b98de39a046ab167fb7632d053682), ROM_BIOS(2) )
633   ROM_SYSTEM_BIOS( 2, "jiffydos", "JiffyDOS v6.01" )
634   ROMX_LOAD( "jiffydos plus4.u24", 0x10000, 0x8000, CRC(818d3f45) SHA1(9bc1b1c3da9ca642deae717905f990d8e36e6c3b), ROM_BIOS(3) )
635
636   ROM_LOAD( "318006-01.u23", 0x10000, 0x4000, CRC(74eaae87) SHA1(161c96b4ad20f3a4f2321808e37a5ded26a135dd) )
637
638   ROM_LOAD( "317053-01.u25", 0x18000, 0x4000, CRC(4fd1d8cb) SHA1(3b69f6e7cb4c18bb08e203fb18b7dabfa853390f) )
639   ROM_LOAD( "317054-01.26", 0x1c000, 0x4000, CRC(109de2fc) SHA1(0ad7ac2db7da692d972e586ca0dfd747d82c7693) )
640ROM_END
641
642#define rom_plus4c rom_plus4
643#define rom_plus4v rom_plus4
644
645#define rom_c16sid      rom_c16
646#define rom_plus4sid      rom_plus4
647
648/***************************************************************************
649
650  Game driver(s)
651
652***************************************************************************/
653
654/*    YEAR  NAME  PARENT COMPAT MACHINE     INPUT      INIT      COMPANY                         FULLNAME            FLAGS */
655
656COMP( 1984, c16,      0,     0,  c16,       c16, c16_state,       c16,      "Commodore Business Machines",  "Commodore 16 (PAL)", 0)
657COMP( 1984, c16hun,   c16,   0,  c16,       c16, c16_state,       c16,      "Commodore Business Machines",  "Commodore 16 Novotrade (PAL, Hungary)", 0)
658
659COMP( 1984, c116,     c16,   0,  c16,       c16, c16_state,       c16,      "Commodore Business Machines",  "Commodore 116 (PAL)", 0)
660
661COMP( 1984, plus4,    c16,   0,  plus4,     plus4, c16_state,     plus4,    "Commodore Business Machines",  "Commodore Plus/4 (NTSC)", 0)
662
663COMP( 1984, c232,     c16,   0,  c16,       c16, c16_state,       c16,      "Commodore Business Machines",  "Commodore 232 (Prototype)", 0)
664COMP( 1984, c264,     c16,   0,  c264,      plus4, c16_state,     plus4,    "Commodore Business Machines",  "Commodore 264 (Prototype)", 0)
665COMP( 1984, c364,     c16,   0,  c364,      plus4, c16_state,     plus4,    "Commodore Business Machines",  "Commodore V364 (Prototype)", GAME_IMPERFECT_SOUND)
666
667COMP( 1984, c16sid,   c16,   0,  c16sid,    c16sid, c16_state,    c16sid,   "Commodore Business Machines",  "Commodore 16 (PAL, SID Card)", GAME_UNOFFICIAL | GAME_IMPERFECT_SOUND)
668COMP( 1984, plus4sid, c16,   0,  plus4sid,  plus4sid, c16_state,  plus4sid, "Commodore Business Machines",  "Commodore Plus/4 (NTSC, SID Card)", GAME_UNOFFICIAL | GAME_IMPERFECT_SOUND)
trunk/src/mess/mess.mak
r17575r17576
303303   $(MESSOBJ)/hp.a \
304304   $(MESSOBJ)/intel.a \
305305   $(MESSOBJ)/intelgnt.a \
306   $(MESSOBJ)/interact.a \
307306   $(MESSOBJ)/interton.a \
308307   $(MESSOBJ)/intv.a \
309308   $(MESSOBJ)/kaypro.a \
r17575r17576
11771176   $(MESS_VIDEO)/hec2video.o   \
11781177   $(MESS_MACHINE)/hecdisk2.o  \
11791178   $(MESS_MACHINE)/hec2hrp.o   \
1180
1181$(MESSOBJ)/interact.a:         \
11821179   $(MESS_DRIVERS)/interact.o   \
1183   $(MESS_VIDEO)/hec2video.o   \
1184   $(MESS_MACHINE)/hec2hrp.o   \
11851180
11861181$(MESSOBJ)/intel.a:            \
11871182   $(MESS_DRIVERS)/basic52.o   \
r17575r17576
15561551   $(MESS_MACHINE)/dccons.o   \
15571552   $(MESS_MACHINE)/sms.o   \
15581553   $(MESS_DRIVERS)/sms.o   \
1559   $(MESS_DRIVERS)/sg1000.o   \
15601554
15611555$(MESSOBJ)/sgi.a:            \
15621556   $(MESS_MACHINE)/sgi.o      \

Previous 199869 Revisions Next


© 1997-2024 The MAME Team