Previous 15994 Revisions Next

r9501 Monday 1st November, 2010 at 17:32:22 UTC by Michael Zapf
Cleanup of old implementations (now in machine/ti99); removing link to
geneve.h
[src/mess/devices]ti99_peb.c ti99_peb.h ti99cart.c ti99cart.h
[src/mess/drivers]geneve.c
[src/mess/formats]ti99_dsk.c
[src/mess/includes]geneve.h
[src/mess/machine]994x_ser.c 994x_ser.h 99_dsk.c 99_dsk.h 99_hsgpl.c 99_hsgpl.h 99_ide.c 99_ide.h 99_peb.c 99_peb.h 99_usbsm.c 99_usbsm.h geneve.c ti99_4x.c ti99_4x.h ti99pcod.c ti99pcod.h
[src/mess/machine/ti99]genboard.c genboard.h

src/mess/devices/ti99cart.c
r9500r9501
1/**********************************************************************
2
3    ti99cart.c
4
5    TI99 family cartridge management
6
7    Michael Zapf, 2009
8
9Console cartridge port
10
11    Vss  36||35  GND
12  ROMG*  34||33  Vss  ROMG* is low if addr in >6000-7FFF
13    WE*  32||31  GR   High = GROM ready
14     A4  30||29  -5V     
15     A5  28||27  GRC  GROMCLK (or CPUCLK) from the VDP 9918A
16     A6  26||25  DBIN
17     A3  24||23  A14
18     A7  22||21  GS*  Low if addr in >9800-9FFF
19     A8  20||19  +5V
20     A9  18||17  D0
21    A10  16||15  D1
22    A11  14||13  D2   
23    A12  12||11  D3
24    A13  10||9   D4
25 A15/OUT  8||7   D5
26   CRUIN  6||5   D6
27 CRUCLK*  4||3   D7
28     GND  2||1   RESET (Active high)
29
30 1  RESET   <   Resets the system (active high)
31    D0 ... D7:  Data bus (D0 = most significant bit)
32    A3 ... A15: Address bus (A15 shared with CRUOUT signal, A3 most significant)
33 4  CRUCLK* >   Inversion of TMS9900 CRUCLOCK pin
34 6  CRUIN   <   CRU input to TMS9900
3521  GS*     >   Grom select. Active low is addr in >9800-9FFF. Internal 2.2K pull-up to +5V.
3625  DBIN    >   Active high = read memory. Internal 3.3K pull-up to +5V
3727  GRC     >   GROM clock: 447.7 kHz signal from the VPD (or 3.5 MHz, jumper-selected). 1K pull-up to +5V.
3829  VDD         -5 Volts power supply
3931  GR      <   Active high = GROM ready. 4.7K pull-up. Masked by GS* in the console before it reaches the CPU.
4032  WE*     >   Active low = write enable (derived from TMS9900 WE*)
4133  VSS         Pseudo-ground (-0.72 V; purpose unclear)
4234  ROMG*   >   Active low if addr in >6000-7FFF
43
44Notes:
45
46* There is no RESET line from the console to the cartridges. The RESET line used
47  here is intended to reset the console when a cartridge is plugged in
48* The cartridge port's data bus must be connected to the 16/8 databus multiplex
49* GR is connected to the console's READY* line and is used by GROMs which are
50  comparably slow devices. During their processing time the main CPU is
51  suspended. (This is not yet implemented).
52* A3-A15 offer a space for 8 KiB ROM. The ROMG* line gets active (low) when
53  A0-A2 is 011 (bin), so we get addresses 0x6000 - 0x7fff.
54* Some cartridges use special circuitry which allows for more than 8 KiB by
55  switching banks.
56* A15 is shared with the CRUOUT line. During CRUCLK* being active, the line is
57  CRUOUT, else A15.
58* A15 is a constructed signal that is created by the 16/8 databus multiplexer.
59  The 9900 CPU only has a word-oriented addressing and does not offer an A15
60  line.
61
62*********************************************************************/
63#include "emu.h"
64#include "ti99cart.h"
65#include "cartslot.h"
66#include "multcart.h"
67
68typedef int assmfct(running_device *);
69
70DECLARE_LEGACY_CART_SLOT_DEVICE(TI99_CARTRIDGE_PCB_NONE, ti99_cartridge_pcb_none);
71DECLARE_LEGACY_CART_SLOT_DEVICE(TI99_CARTRIDGE_PCB_STD, ti99_cartridge_pcb_std);
72DECLARE_LEGACY_CART_SLOT_DEVICE(TI99_CARTRIDGE_PCB_PAGED, ti99_cartridge_pcb_paged);
73DECLARE_LEGACY_CART_SLOT_DEVICE(TI99_CARTRIDGE_PCB_MINIMEM, ti99_cartridge_pcb_minimem);
74DECLARE_LEGACY_CART_SLOT_DEVICE(TI99_CARTRIDGE_PCB_SUPER, ti99_cartridge_pcb_super);
75DECLARE_LEGACY_CART_SLOT_DEVICE(TI99_CARTRIDGE_PCB_MBX, ti99_cartridge_pcb_mbx);
76DECLARE_LEGACY_CART_SLOT_DEVICE(TI99_CARTRIDGE_PCB_PAGED379I, ti99_cartridge_pcb_paged379i);
77DECLARE_LEGACY_CART_SLOT_DEVICE(TI99_CARTRIDGE_PCB_PAGEDCRU, ti99_cartridge_pcb_pagedcru);
78DECLARE_LEGACY_CART_SLOT_DEVICE(TI99_CARTRIDGE_PCB_GRAMKRACKER, ti99_cartridge_pcb_gramkracker);
79
80DEFINE_LEGACY_CART_SLOT_DEVICE(TI99_CARTRIDGE_PCB_NONE, ti99_cartridge_pcb_none);
81DEFINE_LEGACY_CART_SLOT_DEVICE(TI99_CARTRIDGE_PCB_STD, ti99_cartridge_pcb_std);
82DEFINE_LEGACY_CART_SLOT_DEVICE(TI99_CARTRIDGE_PCB_PAGED, ti99_cartridge_pcb_paged);
83DEFINE_LEGACY_CART_SLOT_DEVICE(TI99_CARTRIDGE_PCB_MINIMEM, ti99_cartridge_pcb_minimem);
84DEFINE_LEGACY_CART_SLOT_DEVICE(TI99_CARTRIDGE_PCB_SUPER, ti99_cartridge_pcb_super);
85DEFINE_LEGACY_CART_SLOT_DEVICE(TI99_CARTRIDGE_PCB_MBX, ti99_cartridge_pcb_mbx);
86DEFINE_LEGACY_CART_SLOT_DEVICE(TI99_CARTRIDGE_PCB_PAGED379I, ti99_cartridge_pcb_paged379i);
87DEFINE_LEGACY_CART_SLOT_DEVICE(TI99_CARTRIDGE_PCB_PAGEDCRU, ti99_cartridge_pcb_pagedcru);
88DEFINE_LEGACY_CART_SLOT_DEVICE(TI99_CARTRIDGE_PCB_GRAMKRACKER, ti99_cartridge_pcb_gramkracker);
89
90/* Generic TI99 cartridge structure. */
91struct _cartridge_t
92{
93   // PCB device associated to this cartridge. If NULL, the slot is empty.
94   running_device *pcb;
95
96   // GROM buffer size.
97   int grom_size;
98
99   // ROM page.
100   int rom_page;
101
102   // RAM page.
103   int ram_page;
104
105   // ROM buffer size. All banks have equal sizes.
106   int rom_size;
107   // RAM buffer size. All banks have equal sizes.
108   int ram_size;
109
110   // pointer to GROM data.
111   UINT8 *grom_ptr;
112
113   // ROM buffer. We are using this for both 16 bit (99/4a) and 8 bit
114   // (99/8) access.
115   void *rom_ptr;
116
117   // ROM buffer for the second bank of paged cartridges. Other cartridges
118   // usually store their ROM in one large file.
119   void *rom2_ptr;
120
121   // RAM buffer. The persistence service is done by the cartridge system.
122   // The RAM space is a consecutive space; all banks are in one buffer.
123   void *ram_ptr;
124};
125typedef struct _cartridge_t cartridge_t;
126
127enum
128{
129   TI99CARTINFO_FCT_6000_R = DEVINFO_FCT_DEVICE_SPECIFIC,      /* read16_device_handler */
130   TI99CARTINFO_FCT_6000_W,               /* write16_device_handler */
131   TI99CARTINFO_FCT_6000_R8,               /* read8_device_handler */
132   TI99CARTINFO_FCT_6000_W8,               /* write16_device_handler */
133   TI99CARTINFO_FCT_CRU_R,
134   TI99CARTINFO_FCT_CRU_W,
135   TI99CART_FCT_ASSM,
136   TI99CART_FCT_DISASSM
137};
138
139typedef enum _legacy_cart_t
140{
141   LEG_CART_NONE,
142   LEG_CART_STD,
143   LEG_CART_EXB,
144   LEG_CART_MINI,
145   LEG_CART_MBX
146} legacy_cart_t;
147
148struct _ti99_multicart_state
149{
150   // Reserves space for all cartridges. This is also used in the legacy
151   // cartridge system, but only for slot 0.
152   cartridge_t cartridge[NUMBER_OF_CARTRIDGE_SLOTS];
153
154   // Determines which slot is currently active. This value is changed when
155   // there are accesses to other GROM base addresses.
156   int active_slot;
157
158   // Used in order to enforce a special slot. This value is retrieved
159   // from the dipswitch setting. A value of -1 means automatic, that is,
160   // the grom base switch is used. Values 0 .. max refer to the
161   // respective slot.
162   int fixed_slot;
163
164   // Contains the slot number of the GRAM Kracker
165   int gk_slot;
166
167   // Contains the slot number of the GK guest (which is the cartridge
168   // plugged into the GK)
169   int gk_guest_slot;
170
171   // Holds the highest index of a cartridge being plugged in plus one.
172   // If we only have one cartridge inserted, we don't want to get a
173   // selection option, so we just mirror the memory contents.
174   int next_free_slot;
175
176   // Counts the number of slots which currently contain legacy format
177   // cartridge images.
178   int legacy_slots;
179
180   // Counts the number of slots which currently contain new format
181   // cartridge images.
182   int multi_slots;
183
184   // Legacy mode. Stores the slot number where the cartridge part is
185   // mounted. Index is from slotc_type_t.
186   int legacy_slotnumber[5];
187
188   // Current address pointer for the active GROM in port (16 bits)
189   UINT16 grom_address;
190
191   // GROM data buffer
192   UINT8 grom_buffer;
193
194   // Hack for GRAM Kracker. Flag to remember whether we switched the
195   // loader area. (The GK utility assumes that it is not important whether
196   // the GROM address is set before or after the loader bank has been
197   // manually switched, but this will fail here.)
198   int loader_on;
199
200   // Internal flip-flops that are set after the first access to the GROM
201   // address so that next access is mapped to the LSB, and cleared after
202   // each data access
203   char raddr_LSB, waddr_LSB;
204};
205typedef struct _ti99_multicart_state ti99_multicart_state;
206
207#define AUTO -1
208
209typedef enum _slotc_type_t
210{
211   SLOTC_EMPTY = -1,
212   SLOTC_GROM = 0,
213   SLOTC_CROM = 1,
214   SLOTC_DROM = 2,
215   SLOTC_MINIMEM = 3,
216   SLOTC_MBX = 4
217} slotc_type_t;
218
219/* Function declaration; the function itself is in the later part of this file. */
220static UINT8 cartridge_grom_read_legacy(running_device *cartsys);
221static void unload_legacy(device_image_interface &image);
222static int load_legacy(device_image_interface &image);
223
224static int cartridge_gram_kracker_readg(running_device *cartsys);
225static void cartridge_gram_kracker_writeg(running_device *cartsys, UINT8 data);
226
227/* Access to the pcb. Contained in the token of the pcb instance. */
228struct _ti99_pcb_t
229{
230   /* Read function for this cartridge. */
231   read16_device_func read;
232
233   /* Write function for this cartridge. */
234   write16_device_func write;
235
236   /* Read function for this cartridge, TI-99/8. */
237   read8_device_func read8;
238
239   /* Write function for this cartridge, TI-99/8. */
240   write8_device_func write8;
241
242   /* Read function for this cartridge, CRU. */
243   read8_device_func cruread;
244
245   /* Write function for this cartridge, CRU. */
246   write8_device_func cruwrite;
247
248   /* Link up to the cartridge structure which contains this pcb. */
249   cartridge_t *cartridge;
250
251   /* Function to assemble this cartridge. */
252   assmfct   *assemble;
253
254   /* Function to disassemble this cartridge. */
255   assmfct   *disassemble;
256};
257typedef struct _ti99_pcb_t ti99_pcb_t;
258
259static int in_legacy_mode(running_device *device)
260{
261   ti99_multicart_state *cartslots = (ti99_multicart_state *)downcast<legacy_device_base *>(device)->token();
262   if ((cartslots->legacy_slots>0) &&  (cartslots->multi_slots==0))
263      return TRUE;
264   return FALSE;
265}
266
267/*
268    Activates a slot in the multi-cartridge extender.
269    Setting the slot is done by accessing the GROM ports using a
270    specific address:
271
272    slot n:  read data (read address, write data, write address)
273
274    slot 0:  0x9800 (0x9802, 0x9c00, 0x9c02)   : cartridge1
275    slot 1:  0x9804 (0x9806, 0x9c04, 0x9c06)   : cartridge2
276    ...
277    slot 15: 0x983c (0x983e, 0x9c3c, 0x9c3e)   : cartridge16
278
279    The following addresses are theoretically available, but the
280    built-in OS does not use them; i.e. cartridges will not be
281    included in the selection list, and their features will not be
282    found by lookup, but they could be accessed directly by user
283    programs.
284    slot 16: 0x9840 (0x9842, 0x9c40, 0x9c42)
285    ...
286    slot 255:  0x9bfc (0x9bfe, 0x9ffc, 0x9ffe)
287
288    Setting the GROM base should select one cartridge, but the ROMs in the
289    CPU space must also be switched. As there is no known special mechanism
290    we assume that by switching the GROM base, the ROM is automatically
291    switched.
292
293    Caution: This means that cartridges which do not have at least one
294    GROM cannot be switched with this mechanism.
295
296    We assume that the slot number is already calculated in the caller:
297    slotnumber>=0 && slotnumber<=255
298
299    NOTE: The OS will stop searching when it finds slots 1 and 2 empty.
300    Interestingly, cartridge subroutines are found nevertheless, even when
301    the cartridge is plugged into a higher slot.
302*/
303static void cartridge_slot_set(running_device *cartsys, int slotnumber)
304{
305   ti99_multicart_state *cartslots = (ti99_multicart_state *)downcast<legacy_device_base *>(cartsys)->token();
306   assert(slotnumber>=0 && slotnumber<=255);
307//  if (cartslots->active_slot != slotnumber) printf("Setting cartslot to %d\n", slotnumber);
308   if (cartslots->fixed_slot==AUTO)
309      cartslots->active_slot = slotnumber;
310   else
311      cartslots->active_slot = cartslots->fixed_slot;
312}
313
314static int slot_is_empty(running_device *cartsys, int slotnumber)
315{
316   cartridge_t *cart;
317   ti99_multicart_state *cartslots = (ti99_multicart_state *)downcast<legacy_device_base *>(cartsys)->token();
318
319   cart = &cartslots->cartridge[slotnumber];
320
321   if ((cart->rom_size==0) && (cart->ram_size==0) && (cart->grom_size==0))
322      return TRUE;
323   return FALSE;
324}
325
326static void clear_slot(running_device *cartsys, int slotnumber)
327{
328   cartridge_t *cart;
329   ti99_multicart_state *cartslots = (ti99_multicart_state *)downcast<legacy_device_base *>(cartsys)->token();
330
331   cart = &cartslots->cartridge[slotnumber];
332
333   cart->rom_size = cart->ram_size = cart->grom_size = 0;
334   cart->rom_ptr = NULL;
335   cart->rom2_ptr = NULL;
336   cart->ram_ptr = NULL;
337   cart->grom_ptr = NULL;
338
339   if (slotnumber==cartslots->gk_guest_slot)
340      cartslots->gk_guest_slot = -1;
341}
342
343static void grom_write_address(ti99_multicart_state *cartslots, UINT8 data)
344{
345   /* We are writing; the read states will automatically fall back to default. */
346   cartslots->raddr_LSB = FALSE;
347
348   /* Fore more comments, see machine/ti99_4x.c */
349   if (cartslots->waddr_LSB)
350   {
351      /* Accept low byte (2nd write) */
352      cartslots->grom_address = (cartslots->grom_address & 0xff00) | (data & 0x00ff);
353      cartslots->waddr_LSB = FALSE;
354   }
355   else
356   {
357      /* Accept high byte (1st write) */
358      cartslots->grom_address = ((data<<8) & 0xff00) | (cartslots->grom_address & 0x00ff);
359      cartslots->waddr_LSB = TRUE;
360   }
361}
362
363/*
364    Set the address pointer value or write to GRAM (if available).
365*/
366WRITE8_DEVICE_HANDLER(ti99_cartridge_grom_w)
367{
368   ti99_multicart_state *cartslots = (ti99_multicart_state *)downcast<legacy_device_base *>(device)->token();
369
370   // Set the cart slot. Note that the port must be adjusted for 16-bit
371   // systems, i.e. it should be shifted left by 1.
372   // 1001 1wbb bbbb bbr0
373
374   cartridge_slot_set(device, (offset>>2) & 0x00ff);
375
376   if (offset & 0x0002)
377      grom_write_address(cartslots, data);
378   else
379   {
380      cartslots->raddr_LSB = cartslots->waddr_LSB = FALSE;
381
382      // Handle the GRAM Kracker
383      if ((cartslots->gk_slot != -1) && (input_port_read(device->machine, "CARTSLOT")==CART_GK))
384         cartridge_gram_kracker_writeg(device,data);
385
386      cartslots->grom_address = ((cartslots->grom_address + 1) & 0x1FFF) | (cartslots->grom_address & 0xE000);
387
388      /* Reset the read and write address flipflops. */
389      cartslots->raddr_LSB = cartslots->waddr_LSB = FALSE;
390   }
391}
392
393/*
394    Deliver the local address pointer value. Note that this must be
395    in sync with the console.
396*/
397static UINT8 grom_read_address(ti99_multicart_state *cartslots)
398{
399   UINT8 reply;
400   // When reading, reset the hi/lo flag byte for writing.
401   // TODO: Verify this with a real machine.
402   cartslots->waddr_LSB = FALSE;
403
404   // Address reading is done in two steps; first, the high byte
405   // is transferred, then the low byte.
406   if (cartslots->raddr_LSB)
407   {
408      /* second pass */
409      reply = cartslots->grom_address & 0x00ff;
410      cartslots->raddr_LSB = FALSE;
411   }
412   else
413   {
414      /* first pass */
415      reply = (cartslots->grom_address>>8) & 0x00ff;
416      cartslots->raddr_LSB = TRUE;
417   }
418   return reply;
419}
420
421/*
422    GROM access. Accesses the GROMs in the cartridge. GROM memory is
423    accessed serially via a set of ports. The GRMWA port (bank 0: 0x9c02)
424    takes two consecutive byte writes which represent the high and low byte
425    of the memory address in the GROM space. Once set, bytes can be read
426    by repeated read accesses on the GRMRD port (bank 0: 0x9800). The
427    address pointer advances on each read. The pointer wraps at the end
428    of each GROM chip memory space, i.e. every 8KiB.
429    This function takes the current GROM address minus 0x6000 which is the
430    lowest address for cartridge GROMs. Lower addresses access GROMs in the
431    console only, which appear in all banks.
432    Note that the GROM access mechanism is identical for all cartridge
433    types.
434*/
435READ8_DEVICE_HANDLER(ti99_cartridge_grom_r)
436{
437   UINT8 value;
438   int slot;
439   cartridge_t *cartridge;
440   ti99_multicart_state *cartslots = (ti99_multicart_state *)downcast<legacy_device_base *>(device)->token();
441
442   // Set the cart slot. Note that the port must be adjusted for 16-bit
443   // systems, i.e. it should be shifted left by 1.
444   // 1001 1wbb bbbb bbr0
445
446   cartridge_slot_set(device, (offset>>2) & 0x00ff);
447
448   if (offset & 0x0002)
449      return grom_read_address(cartslots);
450
451   // Handle the GRAM Kracker
452   if ((cartslots->gk_slot != -1) && (input_port_read(device->machine, "CARTSLOT")==CART_GK))
453      return cartridge_gram_kracker_readg(device);
454
455   /* Handle the legacy mode. */
456   if (in_legacy_mode(device))
457      return cartridge_grom_read_legacy(device);
458
459   slot = cartslots->active_slot;
460
461   // This fixes a minor issue: The selection mechanism of the console
462   // concludes that there are multiple cartridges plugged in when it
463   // checks the different GROM bases and finds different data. Empty
464   // slots should return 0 at all addresses, but when we have only
465   // one cartridge, this entails that the second cartridge is
466   // different (all zeros), and so we get a meaningless selection
467   // option between cartridge 1 and 1 and 1 ...
468   //
469   // So if next_free_slot==1, we have one cartridge in slot 0.
470   // In that case we trick the OS to believe that the addressed
471   // cartridge appears at all locations which causes it to assume a
472   // standard single cartslot.
473
474   if (cartslots->fixed_slot==AUTO && cartslots->next_free_slot==1)
475      slot=0;
476
477   if (slot >= NUMBER_OF_CARTRIDGE_SLOTS)
478      value = 0;
479   else
480   {
481      cartridge = &cartslots->cartridge[slot];
482      if ((cartridge->grom_size>0) && (cartridge->pcb!=NULL))
483      {
484         // This is the reason why we need the image size: Read
485         // access beyond the image size must be detected. */
486         /* TODO: replace this using a bitmap of the available GROMs */
487         if ((cartslots->grom_address < 0x6000) || (cartslots->grom_address > (cartridge->grom_size+0x6000)))
488            value = 0;
489         else
490         {
491            /* Buffered GROM access. We use a (virtual) common buffer to avoid implementing this for each cartridge. */
492            value = (UINT8)cartslots->grom_buffer;
493            /* read ahead */
494            cartslots->grom_buffer = cartridge->grom_ptr[cartslots->grom_address-0x6000];
495         }
496      }
497      else
498      {
499         /* We assume that empty sockets return 0 */
500         value = 0;
501         //printf("Empty socket at address G(%d)>%04x\n", slot, cartslots->grom_address);
502      }
503   }
504   /* The program counter wraps at each GROM chip size (8K), */
505   /* so 0x5fff + 1 = 0x4000. */
506   /* The address must be increased even if there is no cartridge slot */
507   cartslots->grom_address = ((cartslots->grom_address + 1) & 0x1FFF) | (cartslots->grom_address & 0xE000);
508
509   /* Reset the read and write address flipflops. */
510   cartslots->raddr_LSB = cartslots->waddr_LSB = FALSE;
511
512   return value;
513}
514
515/*
516    Find the index of the cartridge name. We assume the format
517    <name><number>, i.e. the number is the longest string from the right
518    which can be interpreted as a number.
519*/
520static int get_index_from_tagname(running_device *image)
521{
522   const char *tag = image->tag();
523   int maxlen = strlen(tag);
524   int i;
525   for (i=maxlen-1; i >=0; i--)
526      if (tag[i] < 48 || tag[i] > 57) break;
527
528   return atoi(tag+i+1);
529}
530
531/*
532    Common routine to assemble cartridges from resources.
533*/
534static cartridge_t *assemble_common(running_device *cartslot)
535{
536   /* Pointer to the cartridge structure. */
537   cartridge_t *cartridge;
538   running_device *cartsys = cartslot->owner();
539   ti99_multicart_state *cartslots = (ti99_multicart_state *)downcast<legacy_device_base *>(cartsys)->token();
540
541   void *socketcont;
542   int reslength;
543   int i;
544
545   int slotnumber = get_index_from_tagname(cartslot)-1;
546   assert(slotnumber>=0 && slotnumber<NUMBER_OF_CARTRIDGE_SLOTS);
547
548   /* There is a cartridge in this slot, check the maximum slot number. */
549   if (cartslots->next_free_slot <= slotnumber)
550   {
551      cartslots->next_free_slot = slotnumber+1;
552   }
553   cartridge = &cartslots->cartridge[slotnumber];
554
555   // Get the socket which is retrieved by the multicart instance in
556   // the state of the cartslot instance.
557   socketcont = cartslot_get_socket(cartslot, "grom_socket");
558   reslength = cartslot_get_resource_length(cartslot, "grom_socket");
559   if (socketcont != NULL)
560   {
561      cartridge->grom_ptr = (UINT8 *)socketcont;
562      cartridge->grom_size = reslength;
563   }
564
565   socketcont = cartslot_get_socket(cartslot, "rom_socket");
566   reslength = cartslot_get_resource_length(cartslot, "rom_socket");
567   if (socketcont != NULL)
568   {
569      cartridge->rom_ptr = socketcont;
570      cartridge->rom_size = reslength;
571      if (!ti99_is_99_8())
572      {
573         /* Big-endianize it for 16 bit access. */
574         UINT16 *cont16b = (UINT16 *)socketcont;
575         for (i = 0; i < cartridge->rom_size/2; i++)
576            cont16b[i] = BIG_ENDIANIZE_INT16(cont16b[i]);
577      }
578   }
579
580   socketcont = cartslot_get_socket(cartslot, "rom2_socket");
581//  reslength = cartslot_get_resource_length(cartslot, "rom2_socket");  /* cannot differ from rom_socket */
582   if (socketcont != NULL)
583   {
584      cartridge->rom2_ptr = (UINT16 *)socketcont;
585      assert(cartridge->rom2_ptr != NULL);
586      if (!ti99_is_99_8())
587      {
588         /* Big-endianize it for 16 bit access. */
589         UINT16 *cont16b = (UINT16 *)socketcont;
590         for (i = 0; i < cartridge->rom_size/2; i++)
591            cont16b[i] = BIG_ENDIANIZE_INT16(cont16b[i]);
592      }
593   }
594
595   socketcont = cartslot_get_socket(cartslot, "ram_socket");
596   reslength = cartslot_get_resource_length(cartslot, "ram_socket");
597   if (socketcont != NULL)
598   {
599      cartridge->ram_ptr = socketcont;
600      cartridge->ram_size = reslength;
601      if (!ti99_is_99_8())
602      {
603         /* Big-endianize it for 16 bit access. */
604         UINT16 *cont16b = (UINT16 *)socketcont;
605         for (i = 0; i < cartridge->ram_size/2; i++)
606            cont16b[i] = BIG_ENDIANIZE_INT16(cont16b[i]);
607      }
608   }
609
610   // If the GRAM Kracker is plugged in, this cartridge may become the
611   // guest
612   if (cartslots->gk_slot != -1)
613   {
614      for (i=0; i < NUMBER_OF_CARTRIDGE_SLOTS; i++)
615      {
616         if (!slot_is_empty(cartsys, i) && (i != cartslots->gk_slot))
617         {
618            cartslots->gk_guest_slot = i;
619            break;
620         }
621      }
622   }
623   return cartridge;
624}
625
626static void set_pointers(running_device *pcb, int index)
627{
628   running_device *cartsys = pcb->owner()->owner();
629   ti99_multicart_state *cartslots = (ti99_multicart_state *)downcast<legacy_device_base *>(cartsys)->token();
630   ti99_pcb_t *pcb_def = (ti99_pcb_t *)downcast<legacy_device_base *>(pcb)->token();
631
632   pcb_def->read = (read16_device_func)downcast<const legacy_cart_slot_device_config_base *>(&pcb->baseconfig())->get_config_fct(TI99CARTINFO_FCT_6000_R);
633   pcb_def->write = (write16_device_func)downcast<const legacy_cart_slot_device_config_base *>(&pcb->baseconfig())->get_config_fct(TI99CARTINFO_FCT_6000_W);
634   pcb_def->read8 = (read8_device_func)downcast<const legacy_cart_slot_device_config_base *>(&pcb->baseconfig())->get_config_fct(TI99CARTINFO_FCT_6000_R8);
635   pcb_def->write8 = (write8_device_func)downcast<const legacy_cart_slot_device_config_base *>(&pcb->baseconfig())->get_config_fct(TI99CARTINFO_FCT_6000_W8);
636   pcb_def->cruread = (read8_device_func)downcast<const legacy_cart_slot_device_config_base *>(&pcb->baseconfig())->get_config_fct(TI99CARTINFO_FCT_CRU_R);
637   pcb_def->cruwrite = (write8_device_func)downcast<const legacy_cart_slot_device_config_base *>(&pcb->baseconfig())->get_config_fct(TI99CARTINFO_FCT_CRU_W);
638
639    pcb_def->assemble = (assmfct *)downcast<const legacy_cart_slot_device_config_base *>(&pcb->baseconfig())->get_config_fct(TI99CART_FCT_ASSM);
640    pcb_def->disassemble = (assmfct *)downcast<const legacy_cart_slot_device_config_base *>(&pcb->baseconfig())->get_config_fct(TI99CART_FCT_DISASSM);
641
642   pcb_def->cartridge = &cartslots->cartridge[index];
643   pcb_def->cartridge->pcb = pcb;
644}
645
646/*****************************************************************************
647  Cartridge type: None
648    This PCB device is just a pseudo device; the legacy mode is handled
649    by dedicated functions.
650******************************************************************************/
651static DEVICE_START(ti99_pcb_none)
652{
653   /* device is ti99_cartslot:cartridge:pcb */
654   set_pointers(device, get_index_from_tagname(device->owner())-1);
655}
656
657/*****************************************************************************
658  Cartridge type: Standard
659    Most cartridges are built in this type. Every cartridge may contain
660    GROM between 0 and 40 KiB, and ROM with 8 KiB length, no banking.
661******************************************************************************/
662
663static DEVICE_START(ti99_pcb_std)
664{
665   /* device is ti99_cartslot:cartridge:pcb */
666   set_pointers(device, get_index_from_tagname(device->owner())-1);
667}
668
669/*
670    Read handler for the CPU address space of the cartridge
671    Images for this area are found in the rom_sockets.
672*/
673static READ16_DEVICE_HANDLER( read_cart_std )
674{
675   /* device is pcb, owner is cartslot */
676   UINT16 value;
677   ti99_pcb_t *pcb = (ti99_pcb_t *)downcast<legacy_device_base *>(device)->token();
678   cartridge_t *cartridge = pcb->cartridge;
679
680   if (cartridge->rom_ptr==NULL)
681   {
682      value = 0;
683   }
684   else
685   {
686      value = ((UINT16 *)cartridge->rom_ptr)[offset];
687   }
688   return value;
689}
690
691static WRITE16_DEVICE_HANDLER( write_cart_std )
692{
693   logerror("Write access to cartridge ROM at address %04x ignored\n", 0x6000 + 2*offset);
694}
695
696/*
697    TI-99/8 support:
698    Read handler for the CPU address space of the cartridge
699    Images for this area are found in the rom_sockets.
700    For comments see the READ16 handler.
701*/
702static READ8_DEVICE_HANDLER( read_cart_std8 )
703{
704   UINT8 value;
705   ti99_pcb_t *pcb = (ti99_pcb_t *)downcast<legacy_device_base *>(device)->token();
706   cartridge_t *cartridge = pcb->cartridge;
707
708   if (cartridge->rom_ptr==NULL)
709      value = 0;
710   else
711      value = ((UINT8 *)cartridge->rom_ptr)[offset];
712   return value;
713}
714
715/*
716    TI-99/8 support:
717    Write handler. No writes are allowed to standard cartridges.
718*/
719static WRITE8_DEVICE_HANDLER( write_cart_std8 )
720{
721   logerror("Write access to cartridge ROM at address %04x ignored", 0x6000 + offset);
722}
723
724/*
725    The standard cartridge assemble routine. We just call the common
726    function here.
727*/
728static int assemble_std(running_device *image)
729{
730   assemble_common(image);
731   return IMAGE_INIT_PASS;
732}
733
734/*
735    Removes pointers and restores the state before plugging in the
736    cartridge.
737    The pointer to the location after the last cartridge is adjusted.
738    As it seems, we can use the same function for the disassembling of all
739    cartridge types.
740*/
741static int disassemble_std(running_device *image)
742{
743   int slotnumber;
744   int i;
745   cartridge_t *cart;
746   running_device *cartsys = image->owner();
747   ti99_multicart_state *cartslots = (ti99_multicart_state *)downcast<legacy_device_base *>(cartsys)->token();
748
749   slotnumber = get_index_from_tagname(image)-1;
750
751   /* Search the highest remaining cartridge. */
752   cartslots->next_free_slot = 0;
753   for (i=NUMBER_OF_CARTRIDGE_SLOTS-1; i >= 0; i--)
754   {
755      if (i != slotnumber)
756      {
757         if (!slot_is_empty(cartsys, i))
758         {
759            cartslots->next_free_slot = i+1;
760            break;
761         }
762      }
763   }
764
765   /* Do we have RAM? If so, swap the bytes (undo the BIG_ENDIANIZE) */
766   cart = &cartslots->cartridge[slotnumber];
767   if (!ti99_is_99_8())
768   {
769      for (i = 0; i < cart->ram_size/2; i++)
770         ((UINT16 *)cart->ram_ptr)[i] = BIG_ENDIANIZE_INT16(((UINT16 *)cart->ram_ptr)[i]);
771   }
772
773   clear_slot(cartsys, slotnumber);
774
775   return IMAGE_INIT_PASS;
776}
777
778/*****************************************************************************
779  Cartridge type: Paged (Extended Basic)
780    This cartridge consists of GROM memory and 2 pages of standard ROM.
781    The page is set by writing any value to a location in
782    the address area, where an even word offset sets the page to 0 and an
783    odd word offset sets the page to 1 (e.g. 6000 = bank 0, and
784    6002 = bank 1).
785******************************************************************************/
786
787static DEVICE_START(ti99_pcb_paged)
788{
789   /* device is ti99_cartslot:cartridge:pcb */
790   set_pointers(device, get_index_from_tagname(device->owner())-1);
791}
792
793/*
794    Read handler for the CPU address space of the cartridge
795    Images for this area are found in the rom_sockets.
796*/
797static READ16_DEVICE_HANDLER( read_cart_paged )
798{
799   /* device is pcb, owner is cartslot */
800   UINT16 value;
801   ti99_pcb_t *pcb = (ti99_pcb_t *)downcast<legacy_device_base *>(device)->token();
802   cartridge_t *cartridge = pcb->cartridge;
803   UINT16 *rombank;
804
805   if (cartridge->rom_page==0)
806      rombank = (UINT16*)cartridge->rom_ptr;
807   else
808      rombank = (UINT16*)cartridge->rom2_ptr;
809
810   if (rombank==NULL)
811   {
812      /* TODO: Check for consistency with the GROM memory handling. */
813      value = 0;
814   }
815   else
816   {
817      value = rombank[offset];
818   }
819   return value;
820}
821
822
823/*
824    Handle paging. Extended Basic switches between ROM banks by
825    using the value of the LSB of the address where any value
826    is written to.
827*/
828static WRITE16_DEVICE_HANDLER( write_cart_paged )
829{
830   ti99_pcb_t *pcb = (ti99_pcb_t *)downcast<legacy_device_base *>(device)->token();
831   cartridge_t *cartridge = pcb->cartridge;
832   cartridge->rom_page = offset & 1;
833}
834
835/*
836    TI-99/8 support:
837    Read handler for the CPU address space of the cartridge.
838    Images for this area are found in the rom_sockets.
839*/
840static READ8_DEVICE_HANDLER( read_cart_paged8 )
841{
842   UINT8 value;
843   ti99_pcb_t *pcb = (ti99_pcb_t *)downcast<legacy_device_base *>(device)->token();
844   cartridge_t *cartridge = pcb->cartridge;
845   UINT8 *rombank;
846
847   if (cartridge->rom_page==0)
848      rombank = (UINT8 *)cartridge->rom_ptr;
849   else
850      rombank = (UINT8 *)cartridge->rom2_ptr;
851
852   if (rombank==NULL)
853      value = 0;
854   else
855      value = rombank[offset];
856
857   return value;
858}
859
860
861/*
862    TI-99/8 support:
863    Handle paging. Extended Basic switches between ROM banks by
864    using the value of the LSB of the address where any value
865    is written to. This is the TI-99/8 support.
866    Note that we need to check whether offset/2 is even or odd.
867
868    FIXME: Extended Basic crashes with TI-99/8 when changing the rom page.
869    This may be an incompatibility of Extended Basic and TI-99/8.
870*/
871static WRITE8_DEVICE_HANDLER( write_cart_paged8 )
872{
873   ti99_pcb_t *pcb = (ti99_pcb_t *)downcast<legacy_device_base *>(device)->token();
874   cartridge_t *cartridge = pcb->cartridge;
875   cartridge->rom_page = (offset>>1) & 1;
876}
877
878/*
879    We require paged modules to have at least those two rom banks.
880*/
881static int assemble_paged(running_device *image)
882{
883   cartridge_t *cart;
884
885   cart = assemble_common(image);
886   if (cart->rom_ptr==NULL)
887   {
888      logerror("Missing ROM for paged cartridge");
889      return IMAGE_INIT_FAIL;
890   }
891   if (cart->rom2_ptr==NULL)
892   {
893      logerror("Missing second ROM for paged cartridge");
894      return IMAGE_INIT_FAIL;
895   }
896
897   return IMAGE_INIT_PASS;
898}
899
900/*****************************************************************************
901  Cartridge type: Mini Memory
902    GROM: 6 KiB (occupies G>6000 to G>7800)
903    ROM: 4 KiB (romfile is actually 8 K long, half with zeros, 0x6000-0x6fff)
904    persistent RAM: 4 KiB (0x7000-0x7fff)
905******************************************************************************/
906
907static DEVICE_START(ti99_pcb_minimem)
908{
909   set_pointers(device, get_index_from_tagname(device->owner())-1);
910}
911
912static READ16_DEVICE_HANDLER( read_cart_minimem )
913{
914   /* device is pcb, owner is cartslot */
915   UINT16 value;
916   ti99_pcb_t *pcb = (ti99_pcb_t *)downcast<legacy_device_base *>(device)->token();
917   cartridge_t *cartridge = pcb->cartridge;
918
919   if (offset < 0x800)
920   {
921      if (cartridge->rom_ptr==NULL)
922      {
923         value = 0;
924      }
925      else
926      {
927         value = ((UINT16 *)cartridge->rom_ptr)[offset];
928      }
929   }
930   else
931   {
932      if (cartridge->ram_ptr==NULL)
933      {
934         value = 0;
935      }
936      else
937      {
938         value = ((UINT16 *)cartridge->ram_ptr)[offset-0x800];
939      }
940   }
941   return value;
942}
943
944/*
945    Mini Memory cartridge write operation. RAM is located at offset + 4 KiB
946*/
947static WRITE16_DEVICE_HANDLER( write_cart_minimem )
948{
949   ti99_pcb_t *pcb = (ti99_pcb_t *)downcast<legacy_device_base *>(device)->token();
950   cartridge_t *cartridge = pcb->cartridge;
951   UINT16 *pos;
952
953   if (offset < 0x800)
954   {
955      logerror("Write access to cartridge ROM at address %04x ignored", 0x6000 + 2*offset);
956   }
957   else
958   {
959      if (cartridge->ram_ptr==NULL)
960      {
961         logerror("No cartridge RAM at address %04x", 0x6000 + 2*offset);
962         /* TODO: Check for consistency with the GROM memory handling. */
963      }
964      else
965      {
966         pos = ((UINT16 *)cartridge->ram_ptr) + offset - 0x800;
967         COMBINE_DATA(pos);
968      }
969   }
970}
971
972/*
973    Read handler for MiniMemory in TI-99/8.
974*/
975static READ8_DEVICE_HANDLER( read_cart_minimem8 )
976{
977   /* device is pcb, owner is cartslot */
978   UINT8 value;
979   ti99_pcb_t *pcb = (ti99_pcb_t *)downcast<legacy_device_base *>(device)->token();
980   cartridge_t *cartridge = pcb->cartridge;
981
982   if (offset < 0x1000)
983   {
984      if (cartridge->rom_ptr==NULL)
985      {
986         value = 0;
987      }
988      else
989      {
990         value = ((UINT8 *)cartridge->rom_ptr)[offset];
991      }
992   }
993   else
994   {
995      if (cartridge->ram_ptr==NULL)
996      {
997         value = 0;
998      }
999      else
1000      {
1001         value = ((UINT8 *)cartridge->ram_ptr)[offset-0x1000];
1002      }
1003   }
1004   return value;
1005}
1006
1007/*
1008    Mini Memory cartridge write operation. RAM is located at offset + 4 KiB.
1009    This is the TI-99/8 support.
1010*/
1011static WRITE8_DEVICE_HANDLER( write_cart_minimem8 )
1012{
1013   ti99_pcb_t *pcb = (ti99_pcb_t *)downcast<legacy_device_base *>(device)->token();
1014   cartridge_t *cartridge = pcb->cartridge;
1015
1016   if (offset < 0x1000)
1017   {
1018      logerror("Write access to cartridge ROM at address %04x ignored", 0x6000 + offset);
1019   }
1020   else
1021   {
1022      if (cartridge->ram_ptr==NULL)
1023      {
1024         logerror("No cartridge RAM at address %04x", 0x6000 + offset);
1025         /* TODO: Check for consistency with the GROM memory handling. */
1026      }
1027      else
1028      {
1029         ((UINT8 *)cartridge->ram_ptr)[offset-0x1000] = data;
1030      }
1031   }
1032}
1033
1034
1035static int assemble_minimem(running_device *image)
1036{
1037   cartridge_t *cart;
1038
1039   cart = assemble_common(image);
1040   if (cart->grom_size==0)
1041   {
1042      logerror("Missing GROM for Mini Memory");
1043      // should not fail here because there may be variations of
1044      // cartridges which do not use all parts
1045//      return IMAGE_INIT_FAIL;
1046   }
1047   if (cart->rom_size==0)
1048   {
1049      logerror("Missing ROM for Mini Memory");
1050//      return IMAGE_INIT_FAIL;
1051   }
1052   if (cart->ram_size==0)
1053   {
1054      logerror("Missing RAM for Mini Memory");
1055//      return IMAGE_INIT_FAIL;
1056   }
1057
1058   return IMAGE_INIT_PASS;
1059}
1060
1061
1062/*****************************************************************************
1063  Cartridge type: SuperSpace II
1064    SuperSpace cartridge type. SuperSpace is intended as a user-definable
1065    blank cartridge containing buffered RAM
1066    It has an Editor/Assembler GROM which helps the user to load
1067    the user program into the cartridge. If the user program has a suitable
1068    header, the console recognizes the cartridge as runnable, and
1069    assigns a number in the selection screen.
1070    Switching the RAM banks in this cartridge is achieved by setting
1071    CRU bits (the system serial interface).
1072
1073    GROM: Editor/Assembler GROM
1074    ROM: none
1075    persistent RAM: 32 KiB (0x6000-0x7fff, 4 banks)
1076    Switching the bank is done via CRU write
1077******************************************************************************/
1078
1079static DEVICE_START(ti99_pcb_super)
1080{
1081   set_pointers(device, get_index_from_tagname(device->owner())-1);
1082}
1083
1084/*
1085    The CRU read handler. The CRU is a serial interface in the console.
1086    Using the CRU we can switch the banks in the SuperSpace cartridge.
1087*/
1088static READ8_DEVICE_HANDLER( read_cart_cru )
1089{
1090   ti99_pcb_t *pcb = (ti99_pcb_t *)downcast<legacy_device_base *>(device)->token();
1091   cartridge_t *cartridge = pcb->cartridge;
1092   // offset is the bit number. The CRU base address is already divided  by 2.
1093   int reply = 0;
1094
1095   // ram_page contains the bank number. We have a maximum of
1096   // 4 banks; the Super Space II manual says:
1097   //
1098   // Banks are selected by writing a bit pattern to CRU address >0800:
1099   //
1100   // Bank #   Value
1101   // 0        >02  = 0000 0010
1102   // 1        >08  = 0000 1000
1103   // 2        >20  = 0010 0000
1104   // 3        >80  = 1000 0000
1105   //
1106   // With the bank number (0, 1, 2, or 3) in R0:
1107   //
1108   // BNKSW   LI    R12,>0800   Set CRU address
1109   //         LI    R1,2        Load Shift Bit
1110   //         SLA   R0,1        Align Bank Number
1111   //         JEQ   BNKS1       Skip shift if Bank 0
1112   //         SLA   R1,0        Align Shift Bit
1113   // BNKS1   LDCR  R1,0        Switch Banks
1114   //         SRL   R0,1        Restore Bank Number (optional)
1115   //         RT
1116
1117   if ((offset & 1) == 0 || offset > 7)
1118      reply = 0;
1119
1120   // CRU addresses are only 1 bit wide. Bytes are transferred from LSB
1121   // to MSB. That is, 8 bit are eight consecutive addresses. */
1122   reply = (cartridge->ram_page == (offset-1)/2);
1123
1124   return reply;
1125}
1126
1127static WRITE8_DEVICE_HANDLER( write_cart_cru )
1128{
1129   ti99_pcb_t *pcb = (ti99_pcb_t *)downcast<legacy_device_base *>(device)->token();
1130   cartridge_t *cartridge = pcb->cartridge;
1131   // data is bit
1132   // offset is address
1133   if (offset < 8)
1134   {
1135      if (data != 0)
1136         cartridge->ram_page = (offset-1)/2;
1137   }
1138}
1139
1140/*
1141    SuperSpace RAM read operation. RAM is located at 0x6000 to 0x7fff
1142    as 4 banks of 8 KiB each
1143*/
1144static READ16_DEVICE_HANDLER( read_cart_super )
1145{
1146   /* device is pcb, owner is cartslot */
1147   UINT16 value;
1148   ti99_pcb_t *pcb = (ti99_pcb_t *)downcast<legacy_device_base *>(device)->token();
1149   cartridge_t *cartridge = pcb->cartridge;
1150   offs_t boffset;
1151
1152   if (cartridge->ram_ptr==NULL)
1153   {
1154      value = 0;
1155   }
1156   else
1157   {
1158      boffset = cartridge->ram_page * 0x1000 + offset;
1159      value = ((UINT16 *)cartridge->ram_ptr)[boffset];
1160   }
1161   return value;
1162}
1163
1164/*
1165    SuperSpace RAM write operation. RAM is located at 0x6000 to 0x7fff
1166    as 4 banks of 8 KiB each
1167*/
1168static WRITE16_DEVICE_HANDLER( write_cart_super )
1169{
1170   ti99_pcb_t *pcb = (ti99_pcb_t *)downcast<legacy_device_base *>(device)->token();
1171   cartridge_t *cartridge = pcb->cartridge;
1172   UINT16 *pos;
1173   offs_t boffset;
1174
1175   if (cartridge->ram_ptr==NULL)
1176   {
1177      logerror("No cartridge RAM at address %04x", 0x6000 + 2*offset);
1178   }
1179   else
1180   {
1181      boffset = cartridge->ram_page * 0x1000 + offset;
1182      pos = ((UINT16 *)cartridge->ram_ptr) + boffset;
1183      COMBINE_DATA(pos);
1184   }
1185}
1186
1187/*
1188    SuperSpace RAM read operation. RAM is located at 0x6000 to 0x7fff
1189    as 4 banks of 8 KiB each. This is the TI-99/8 support.
1190*/
1191static READ8_DEVICE_HANDLER( read_cart_super8 )
1192{
1193   /* device is pcb, owner is cartslot */
1194   UINT8 value;
1195   ti99_pcb_t *pcb = (ti99_pcb_t *)downcast<legacy_device_base *>(device)->token();
1196   cartridge_t *cartridge = pcb->cartridge;
1197   offs_t boffset;
1198
1199   if (cartridge->ram_ptr==NULL)
1200   {
1201      value = 0;
1202   }
1203   else
1204   {
1205      boffset = cartridge->ram_page * 0x2000 + offset;
1206      value = ((UINT8 *)cartridge->ram_ptr)[boffset];
1207   }
1208   return value;
1209}
1210
1211/*
1212    SuperSpace RAM write operation. RAM is located at 0x6000 to 0x7fff
1213    as 4 banks of 8 KiB each. This is the TI-99/8 support.
1214*/
1215static WRITE8_DEVICE_HANDLER( write_cart_super8 )
1216{
1217   ti99_pcb_t *pcb = (ti99_pcb_t *)downcast<legacy_device_base *>(device)->token();
1218   cartridge_t *cartridge = pcb->cartridge;
1219   offs_t boffset;
1220
1221   if (cartridge->ram_ptr==NULL)
1222   {
1223      logerror("No cartridge RAM at address %04x", 0x6000 + offset);
1224   }
1225   else
1226   {
1227      boffset = cartridge->ram_page * 0x2000 + offset;
1228      ((UINT8 *)cartridge->ram_ptr)[boffset] = data;
1229   }
1230}
1231
1232
1233static int assemble_super(running_device *image)
1234{
1235   cartridge_t *cart;
1236
1237   cart = assemble_common(image);
1238   if (cart->ram_size==0)
1239   {
1240      logerror("Missing RAM for SuperSpace");
1241      return IMAGE_INIT_FAIL;
1242   }
1243   return IMAGE_INIT_PASS;
1244}
1245
1246/*****************************************************************************
1247  Cartridge type: MBX
1248    GROM: up to 40 KiB
1249    ROM: up to 16 KiB (in up to 2 banks of 8KiB each)
1250    RAM: 1022 B (0x6c00-0x6ffd, overrides ROM in that area)
1251    ROM mapper: 6ffe
1252
1253    Note that some MBX cartridges assume the presence of the MBX system
1254    (additional console) and will not run without it. The MBX hardware is
1255    not emulated yet.
1256******************************************************************************/
1257
1258static DEVICE_START(ti99_pcb_mbx)
1259{
1260   set_pointers(device, get_index_from_tagname(device->owner())-1);
1261}
1262
1263static READ16_DEVICE_HANDLER( read_cart_mbx )
1264{
1265   /* device is pcb, owner is cartslot */
1266   UINT16 value = 0;
1267   ti99_pcb_t *pcb = (ti99_pcb_t *)downcast<legacy_device_base *>(device)->token();
1268   cartridge_t *cartridge = pcb->cartridge;
1269
1270   if ((offset >= 0x0600) && (offset <= 0x07fe))
1271   {
1272      // This is the RAM area which overrides any ROM. There is no
1273      // known banking behavior for the RAM, so we must assume that
1274      // there is only one bank.
1275      if (cartridge->ram_ptr != NULL)
1276         value = ((UINT16 *)cartridge->ram_ptr)[offset - 0x0600];
1277   }
1278   else
1279   {
1280      if (cartridge->rom_ptr != NULL)
1281         value = ((UINT16 *)cartridge->rom_ptr)[offset + cartridge->rom_page * 0x1000];
1282   }
1283   return value;
1284}
1285
1286/*
1287    MBX write operation.
1288*/
1289static WRITE16_DEVICE_HANDLER( write_cart_mbx )
1290{
1291   ti99_pcb_t *pcb = (ti99_pcb_t *)downcast<legacy_device_base *>(device)->token();
1292   cartridge_t *cartridge = pcb->cartridge;
1293   UINT16 *pos;
1294
1295   if ((offset >= 0x0600) && (offset <= 0x07fe))
1296   {
1297      if (cartridge->ram_ptr == NULL)
1298         return;
1299      pos = ((UINT16 *)cartridge->ram_ptr) + offset - 0x0600;
1300      COMBINE_DATA(pos);
1301   }
1302   else if ((offset == 0x07ff) && ACCESSING_BITS_8_15)
1303   {
1304      if (cartridge->rom_ptr==NULL)
1305         return;
1306      cartridge->rom_page = ((data >> 8) & 1);
1307   }
1308}
1309
1310/*
1311    TI-99/8 support
1312*/
1313static READ8_DEVICE_HANDLER( read_cart_mbx8 )
1314{
1315   /* device is pcb, owner is cartslot */
1316   UINT8 value = 0;
1317   ti99_pcb_t *pcb = (ti99_pcb_t *)downcast<legacy_device_base *>(device)->token();
1318   cartridge_t *cartridge = pcb->cartridge;
1319
1320   if ((offset >= 0x0c00) && (offset <= 0x0ffd))
1321   {
1322      // This is the RAM area which overrides any ROM. There is no
1323      // known banking behavior for the RAM, so we must assume that
1324      // there is only one bank.
1325      if (cartridge->ram_ptr != NULL)
1326         value = ((UINT8 *)cartridge->ram_ptr)[offset - 0x0c00];
1327   }
1328   else
1329   {
1330      if (cartridge->rom_ptr != NULL)
1331         value = ((UINT8 *)cartridge->rom_ptr)[offset + cartridge->rom_page * 0x2000];
1332   }
1333   return value;
1334}
1335
1336/*
1337    MBX write operation (TI-99/8)
1338*/
1339static WRITE8_DEVICE_HANDLER( write_cart_mbx8 )
1340{
1341   ti99_pcb_t *pcb = (ti99_pcb_t *)downcast<legacy_device_base *>(device)->token();
1342   cartridge_t *cartridge = pcb->cartridge;
1343
1344   if ((offset >= 0x0c00) && (offset <= 0x0ffd))
1345   {
1346      if (cartridge->ram_ptr == NULL)
1347         return;
1348      ((UINT8 *)cartridge->ram_ptr)[offset - 0x0c00] = data;
1349   }
1350   else if (offset == 0x0ffe || offset == 0x0fff)
1351   {
1352      if (cartridge->rom_ptr==NULL)
1353         return;
1354      cartridge->rom_page = (data & 1); /* TODO: Check */
1355   }
1356}
1357
1358
1359static int assemble_mbx(running_device *image)
1360{
1361   assemble_common(image);
1362   return IMAGE_INIT_PASS;
1363}
1364
1365/*****************************************************************************
1366  Cartridge type: paged379i
1367    This cartridge consists of one 16 KiB, 32 KiB, 64 KiB, or 128 KiB EEPROM
1368    which is organised in 2, 4, 8, or 16 pages of 8 KiB each. The complete
1369    memory contents must be stored in one dump file.
1370    The pages are selected by writing a value to some memory locations. Due to
1371    using the inverted outputs of the LS379 latch, setting the inputs of the
1372    latch to all 0 selects the highest bank, while setting to all 1 selects the
1373    lowest. There are some cartridges (16 KiB) which are using this scheme, and
1374    there are new hardware developments mainly relying on this scheme.
1375
1376    Writing to       selects page (16K/32K/64K/128K)
1377    >6000            1 / 3 / 7 / 15
1378    >6002            0 / 2 / 6 / 14
1379    >6004            1 / 1 / 5 / 13
1380    >6006            0 / 0 / 4 / 12
1381    >6008            1 / 3 / 3 / 11
1382    >600A            0 / 2 / 2 / 10
1383    >600C            1 / 1 / 1 / 9
1384    >600E            0 / 0 / 0 / 8
1385    >6010            1 / 3 / 7 / 7
1386    >6012            0 / 2 / 6 / 6
1387    >6014            1 / 1 / 5 / 5
1388    >6016            0 / 0 / 4 / 4
1389    >6018            1 / 3 / 3 / 3
1390    >601A            0 / 2 / 2 / 2
1391    >601C            1 / 1 / 1 / 1
1392    >601E            0 / 0 / 0 / 0
1393
1394******************************************************************************/
1395
1396static DEVICE_START(ti99_pcb_paged379i)
1397{
1398   /* device is ti99_cartslot:cartridge:pcb */
1399   set_pointers(device, get_index_from_tagname(device->owner())-1);
1400}
1401
1402/*
1403    Read handler for the CPU address space of the cartridge
1404    Images for this area are found in the rom_sockets.
1405*/
1406static READ16_DEVICE_HANDLER( read_cart_paged379i )
1407{
1408   /* device is pcb, owner is cartslot */
1409   UINT16 value;
1410   ti99_pcb_t *pcb = (ti99_pcb_t *)downcast<legacy_device_base *>(device)->token();
1411   cartridge_t *cartridge = pcb->cartridge;
1412   offs_t boffset;
1413
1414   if (cartridge->rom_ptr==NULL)
1415   {
1416      value = 0;
1417   }
1418   else
1419   {
1420      // rom_page is the stored latch value
1421      // 16bit access -> multiply by 0x1000
1422      boffset = cartridge->rom_page * 0x1000 + offset;
1423      value = ((UINT16 *)cartridge->rom_ptr)[boffset];
1424   }
1425   return value;
1426}
1427
1428static void set_paged379i_bank(cartridge_t *cartridge, int rompage)
1429{
1430   int mask = 0;
1431   if (cartridge->rom_size > 16384)
1432   {
1433      if (cartridge->rom_size > 32768)
1434      {
1435         if (cartridge->rom_size > 65536)
1436            mask = 15;
1437         else
1438            mask = 7;
1439      }
1440      else
1441         mask = 3;
1442   }
1443   else
1444      mask = 1;
1445
1446   cartridge->rom_page = rompage & mask;
1447}
1448
1449/*
1450    Handle paging. We use a LS379 latch for storing the page number. On this
1451    PCB, the inverted output of the latch is used, so the order of pages
1452    is reversed. (No problem as long as the memory dump is kept exactly
1453    in the way it is stored in the EPROM.)
1454    The latch can store a value of 4 bits. We adjust the number of
1455    significant bits by the size of the memory dump (16K, 32K, 64K).
1456*/
1457static WRITE16_DEVICE_HANDLER( write_cart_paged379i )
1458{
1459   ti99_pcb_t *pcb = (ti99_pcb_t *)downcast<legacy_device_base *>(device)->token();
1460   cartridge_t *cartridge = pcb->cartridge;
1461
1462   // Bits: 011x xxxx xxxb bbbx
1463   // x = don't care, bbbb = bank
1464   // 16bit access -> drop rightmost bit
1465   set_paged379i_bank(cartridge, 15 - (offset & 15));
1466}
1467
1468/*
1469    TI-99/8 support:
1470    Read handler for the CPU address space of the cartridge.
1471    Images for this area are found in the rom_sockets.
1472*/
1473static READ8_DEVICE_HANDLER( read_cart_paged379i8 )
1474{
1475   UINT8 value;
1476   ti99_pcb_t *pcb = (ti99_pcb_t *)downcast<legacy_device_base *>(device)->token();
1477   cartridge_t *cartridge = pcb->cartridge;
1478   offs_t boffset;
1479
1480   if (cartridge->rom_ptr==NULL)
1481   {
1482      value = 0;
1483   }
1484   else
1485   {
1486      // rom_page is the stored latch value
1487      // 8bit access -> multiply by 0x2000
1488      boffset = cartridge->rom_page * 0x2000 + offset;
1489      value = ((UINT8 *)cartridge->rom_ptr)[boffset];
1490   }
1491   return value;
1492
1493}
1494
1495/*
1496    TI-99/8 support: Handle paging.
1497*/
1498static WRITE8_DEVICE_HANDLER( write_cart_paged379i8 )
1499{
1500   ti99_pcb_t *pcb = (ti99_pcb_t *)downcast<legacy_device_base *>(device)->token();
1501   cartridge_t *cartridge = pcb->cartridge;
1502
1503   // Bits: 011x xxxx xxxb bbbx
1504   // x = don't care, bbbb = bank
1505   set_paged379i_bank(cartridge, 15 - ((offset>>1) & 15));
1506}
1507
1508/*
1509    Paged379i modules have one EPROM dump.
1510*/
1511static int assemble_paged379i(running_device *image)
1512{
1513   cartridge_t *cart;
1514
1515   cart = assemble_common(image);
1516   if (cart->rom_ptr==NULL)
1517   {
1518      logerror("Missing ROM for paged cartridge");
1519      return IMAGE_INIT_FAIL;
1520   }
1521   set_paged379i_bank(cart, 15);
1522   return IMAGE_INIT_PASS;
1523}
1524
1525/*****************************************************************************
1526  Cartridge type: pagedcru
1527    This cartridge consists of one 16 KiB, 32 KiB, or 64 KiB EEPROM which is
1528    organised in 2, 4, or 8 pages of 8 KiB each. We assume there is only one
1529    dump file of the respective size.
1530    The pages are selected by writing a value to the CRU. This scheme is
1531    similar to the one used for the SuperSpace cartridge, with the exception
1532    that we are using ROM only, and we can have up to 8 pages.
1533
1534    Bank     Value written to CRU>0800
1535    0      >0002  = 0000 0000 0000 0010
1536    1      >0008  = 0000 0000 0000 1000
1537    2      >0020  = 0000 0000 0010 0000
1538    3      >0080  = 0000 0000 1000 0000
1539    4      >0200  = 0000 0010 0000 0000
1540    5      >0800  = 0000 1000 0000 0000
1541    6      >2000  = 0010 0000 0000 0000
1542    7      >8000  = 1000 0000 0000 0000
1543
1544******************************************************************************/
1545
1546static DEVICE_START(ti99_pcb_pagedcru)
1547{
1548   /* device is ti99_cartslot:cartridge:pcb */
1549   set_pointers(device, get_index_from_tagname(device->owner())-1);
1550}
1551
1552/*
1553    Read handler for the CPU address space of the cartridge
1554    Images for this area are found in the rom_sockets.
1555*/
1556static READ16_DEVICE_HANDLER( read_cart_pagedcru )
1557{
1558   /* device is pcb, owner is cartslot */
1559   UINT16 value;
1560   ti99_pcb_t *pcb = (ti99_pcb_t *)downcast<legacy_device_base *>(device)->token();
1561   cartridge_t *cartridge = pcb->cartridge;
1562   offs_t boffset;
1563
1564   if (cartridge->rom_ptr==NULL)
1565   {
1566      value = 0;
1567   }
1568   else
1569   {
1570      // rom_page is the stored latch value
1571      // 16bit access -> multiply by 0x1000
1572      boffset = cartridge->rom_page * 0x1000 + offset;
1573      value = ((UINT16 *)cartridge->rom_ptr)[boffset];
1574   }
1575   return value;
1576}
1577
1578/*
1579    This type of cartridge does not support writing to the EPROM address
1580    space.
1581*/
1582static WRITE16_DEVICE_HANDLER( write_cart_pagedcru )
1583{
1584   return;
1585}
1586
1587/*
1588    TI-99/8 support:
1589    Read handler for the CPU address space of the cartridge.
1590    Images for this area are found in the rom_sockets.
1591*/
1592static READ8_DEVICE_HANDLER( read_cart_pagedcru8 )
1593{
1594   UINT8 value;
1595   ti99_pcb_t *pcb = (ti99_pcb_t *)downcast<legacy_device_base *>(device)->token();
1596   cartridge_t *cartridge = pcb->cartridge;
1597   offs_t boffset;
1598
1599   if (cartridge->rom_ptr==NULL)
1600   {
1601      value = 0;
1602   }
1603   else
1604   {
1605      // rom_page is the stored latch value
1606      // 8bit access -> multiply by 0x2000
1607      boffset = cartridge->rom_page * 0x2000 + offset;
1608      value = ((UINT8 *)cartridge->rom_ptr)[boffset];
1609   }
1610   return value;
1611}
1612
1613/*
1614    TI-99/8 support: This type of cartridge does not support writing to the
1615    EPROM address space.
1616*/
1617static WRITE8_DEVICE_HANDLER( write_cart_pagedcru8 )
1618{
1619   return;
1620}
1621
1622/*
1623    The CRU read handler. The CRU is a serial interface in the console.
1624    Using the CRU we can switch the banks in the SuperSpace cartridge.
1625    For documentation see the corresponding cru function above. Note we are
1626    using rom_page here.
1627*/
1628static READ8_DEVICE_HANDLER( read_cart_cru_paged )
1629{
1630   ti99_pcb_t *pcb = (ti99_pcb_t *)downcast<legacy_device_base *>(device)->token();
1631   cartridge_t *cartridge = pcb->cartridge;
1632   int reply = 0;
1633
1634   if ((offset & 1) == 0 || offset > 15)
1635      reply = 0;
1636
1637   reply = (cartridge->rom_page == (offset-1)/2);
1638
1639   return reply;
1640}
1641
1642static WRITE8_DEVICE_HANDLER( write_cart_cru_paged )
1643{
1644   ti99_pcb_t *pcb = (ti99_pcb_t *)downcast<legacy_device_base *>(device)->token();
1645   cartridge_t *cartridge = pcb->cartridge;
1646   // data is bit
1647   // offset is address
1648
1649   //Note that CRU >0F00 also gets in here ... should check
1650   // whether it is intended to go somewhere else
1651   if (offset < 16)
1652   {
1653      if (data != 0)
1654      {
1655         cartridge->rom_page = (offset-1)/2;
1656      }
1657   }
1658}
1659
1660/*
1661    Pagedcru modules have one EPROM dump.
1662*/
1663static int assemble_pagedcru(running_device *image)
1664{
1665   cartridge_t *cart;
1666
1667   cart = assemble_common(image);
1668   if (cart->rom_ptr==NULL)
1669   {
1670      logerror("Missing ROM for pagedcru cartridge");
1671      return IMAGE_INIT_FAIL;
1672   }
1673   cart->rom_page = 0;
1674   return IMAGE_INIT_PASS;
1675}
1676
1677/*****************************************************************************
1678  Cartridge type: gramkracker
1679******************************************************************************/
1680
1681static DEVICE_START(ti99_pcb_gramkracker)
1682{
1683   /* device is ti99_cartslot:cartridge:pcb */
1684//  printf("DEVICE_START(ti99_pcb_pagedcru), tag of device=%s\n", device->tag());
1685   set_pointers(device, get_index_from_tagname(device->owner())-1);
1686}
1687
1688/*
1689    The GRAM Kracker contains one GROM and several buffered RAM chips
1690*/
1691static int assemble_gramkracker(running_device *image)
1692{
1693   cartridge_t *cart;
1694   int id,i;
1695
1696   running_device *cartsys = image->owner();
1697   ti99_multicart_state *cartslots = (ti99_multicart_state *)downcast<legacy_device_base *>(cartsys)->token();
1698
1699   cart = assemble_common(image);
1700
1701   if (cart->grom_ptr==NULL)
1702   {
1703      logerror("Missing loader GROM for GRAM Kracker system");
1704      return IMAGE_INIT_FAIL;
1705   }
1706
1707   if (cart->ram_size < 81920)
1708   {
1709      logerror("Missing or insufficient RAM for GRAM Kracker system");
1710      return IMAGE_INIT_FAIL;
1711   }
1712
1713   // Caution: We are using the ram_socket for both grom and direct access.
1714   // So we get the GROM (first 64 KiB) contents swapped. Need to undo.
1715   if (!ti99_is_99_8())
1716   {
1717      /* Undo the bigendianization for the GROM area. */
1718      UINT16 *cont16b = (UINT16 *)cart->ram_ptr;
1719      for (i = 0; i < 32768; i++)
1720         cont16b[i] = BIG_ENDIANIZE_INT16(cont16b[i]);
1721   }
1722
1723   // Get slot number
1724   id = get_index_from_tagname(image);
1725   cartslots->gk_slot = id-1;
1726   cartslots->gk_guest_slot = -1;
1727   // The first cartridge that is still plugged in is the "guest" of the
1728   // GRAM Kracker
1729   for (i=0; i < NUMBER_OF_CARTRIDGE_SLOTS; i++)
1730   {
1731      if (!slot_is_empty(cartsys, i) && (i != cartslots->gk_slot))
1732      {
1733         cartslots->gk_guest_slot = i;
1734         break;
1735      }
1736   }
1737   return IMAGE_INIT_PASS;
1738}
1739
1740/*
1741    Unplugs the GRAM Kracker. The "guest" is still plugged in, but will be
1742    treated as normal.
1743*/
1744static int disassemble_gramkracker(running_device *cartslot)
1745{
1746   running_device *cartsys = cartslot->owner();
1747   ti99_multicart_state *cartslots = (ti99_multicart_state *)downcast<legacy_device_base *>(cartsys)->token();
1748   int i;
1749
1750   int slotnumber = get_index_from_tagname(cartslot)-1;
1751   assert(slotnumber>=0 && slotnumber<NUMBER_OF_CARTRIDGE_SLOTS);
1752   cartridge_t *cart = &cartslots->cartridge[slotnumber];
1753
1754   // We'll undo the undo of the bigendianization for saving (only for
1755   // the GROM part)
1756   if (!ti99_is_99_8())
1757   {
1758      /* Undo the bigendianization for the GROM area. */
1759      UINT16 *cont16b = (UINT16 *)cart->ram_ptr;
1760      for (i = 0; i < 32768; i++)
1761         cont16b[i] = BIG_ENDIANIZE_INT16(cont16b[i]);
1762   }
1763
1764   cartslots->gk_slot = -1;
1765   cartslots->gk_guest_slot = -1;
1766
1767   return disassemble_std(cartslot);
1768}
1769
1770
1771/*****************************************************************************
1772  Device metadata
1773******************************************************************************/
1774
1775static DEVICE_GET_INFO(ti99_cart_common)
1776{
1777   switch(state)
1778   {
1779      /* --- the following bits of info are returned as 64-bit signed integers --- */
1780      case DEVINFO_INT_TOKEN_BYTES:
1781         info->i = sizeof(ti99_pcb_t);
1782         break;
1783      case DEVINFO_INT_INLINE_CONFIG_BYTES:
1784         info->i = 0;
1785         break;
1786      /* --- the following bits of info are returned as pointers to functions --- */
1787      case DEVINFO_FCT_START:
1788         info->start = DEVICE_START_NAME(ti99_pcb_std);
1789         break;
1790      case DEVINFO_FCT_STOP:
1791         /* Nothing */
1792         break;
1793      case DEVINFO_FCT_RESET:
1794         /* Nothing */
1795         break;
1796      case TI99CARTINFO_FCT_6000_R:
1797         info->f = (genf *) read_cart_std; break;
1798
1799      case TI99CARTINFO_FCT_6000_W:
1800         info->f = (genf *) write_cart_std; break;
1801
1802      case TI99CARTINFO_FCT_6000_R8:
1803         info->f = (genf *) read_cart_std8; break;
1804
1805      case TI99CARTINFO_FCT_6000_W8:
1806         info->f = (genf *) write_cart_std8; break;
1807
1808      case TI99CARTINFO_FCT_CRU_R:
1809         /* Nothing */
1810         break;
1811
1812      case TI99CARTINFO_FCT_CRU_W:
1813         /* Nothing */
1814         break;
1815
1816      case TI99CART_FCT_ASSM:
1817         info->f = (genf *) assemble_std;
1818         break;
1819
1820      case TI99CART_FCT_DISASSM:
1821         info->f = (genf *) disassemble_std;
1822         break;
1823
1824      /* --- the following bits of info are returned as NULL-terminated strings --- */
1825      case DEVINFO_STR_NAME:
1826         strcpy(info->s, "TI99 standard cartridge pcb");
1827         break;
1828      case DEVINFO_STR_FAMILY:
1829         strcpy(info->s, "TI99 cartridge pcb");
1830         break;
1831      case DEVINFO_STR_VERSION:
1832         strcpy(info->s, "1.0");
1833         break;
1834      case DEVINFO_STR_SOURCE_FILE:
1835         strcpy(info->s, __FILE__);
1836         break;
1837      case DEVINFO_STR_CREDITS:
1838         /* Nothing */
1839         break;
1840   }
1841}
1842
1843DEVICE_GET_INFO(ti99_cartridge_pcb_none)
1844{
1845   switch(state)
1846   {
1847      case DEVINFO_FCT_START:
1848         info->start = DEVICE_START_NAME(ti99_pcb_none);
1849         break;
1850
1851      case DEVINFO_STR_NAME:
1852         strcpy(info->s, "TI99 empty cartridge");
1853         break;
1854
1855      default:
1856         DEVICE_GET_INFO_CALL(ti99_cart_common);
1857         break;
1858   }
1859}
1860
1861DEVICE_GET_INFO(ti99_cartridge_pcb_std)
1862{
1863   DEVICE_GET_INFO_CALL(ti99_cart_common);
1864}
1865
1866DEVICE_GET_INFO(ti99_cartridge_pcb_paged)
1867{
1868   switch(state)
1869   {
1870      case DEVINFO_FCT_START:
1871         info->start = DEVICE_START_NAME(ti99_pcb_paged);
1872         break;
1873
1874      case TI99CART_FCT_ASSM:
1875         info->f = (genf *) assemble_paged; break;
1876
1877      case TI99CARTINFO_FCT_6000_R:
1878         info->f = (genf *) read_cart_paged;
1879         break;
1880
1881      case TI99CARTINFO_FCT_6000_W:
1882         info->f = (genf *) write_cart_paged;
1883         break;
1884
1885      case TI99CARTINFO_FCT_6000_R8:
1886         info->f = (genf *) read_cart_paged8;
1887         break;
1888
1889      case TI99CARTINFO_FCT_6000_W8:
1890         info->f = (genf *) write_cart_paged8;
1891         break;
1892
1893      case DEVINFO_STR_NAME:
1894         strcpy(info->s, "TI99 paged cartridge pcb");
1895         break;
1896
1897      default:
1898         DEVICE_GET_INFO_CALL(ti99_cart_common);
1899         break;
1900   }
1901}
1902
1903DEVICE_GET_INFO(ti99_cartridge_pcb_minimem)
1904{
1905   switch(state)
1906   {
1907      case DEVINFO_FCT_START:
1908         info->start = DEVICE_START_NAME(ti99_pcb_minimem);
1909         break;
1910
1911      case TI99CART_FCT_ASSM:
1912         info->f = (genf *) assemble_minimem;
1913         break;
1914      case TI99CARTINFO_FCT_6000_R:
1915         info->f = (genf *) read_cart_minimem;
1916         break;
1917      case TI99CARTINFO_FCT_6000_W:
1918         info->f = (genf *) write_cart_minimem;
1919         break;
1920      case TI99CARTINFO_FCT_6000_R8:
1921         info->f = (genf *) read_cart_minimem8;
1922         break;
1923      case TI99CARTINFO_FCT_6000_W8:
1924         info->f = (genf *) write_cart_minimem8;
1925         break;
1926
1927      case DEVINFO_STR_NAME:
1928         strcpy(info->s, "TI99 MiniMemory cartridge pcb");
1929         break;
1930
1931      default:
1932         DEVICE_GET_INFO_CALL(ti99_cart_common);
1933         break;
1934   }
1935}
1936
1937DEVICE_GET_INFO(ti99_cartridge_pcb_super)
1938{
1939   switch(state)
1940   {
1941      case DEVINFO_FCT_START:
1942         info->start = DEVICE_START_NAME(ti99_pcb_super);
1943         break;
1944
1945      case TI99CART_FCT_ASSM:
1946         info->f = (genf *) assemble_super;
1947         break;
1948      case TI99CARTINFO_FCT_6000_R:
1949         info->f = (genf *) read_cart_super;
1950         break;
1951      case TI99CARTINFO_FCT_6000_W:
1952         info->f = (genf *) write_cart_super;
1953         break;
1954      case TI99CARTINFO_FCT_6000_R8:
1955         info->f = (genf *) read_cart_super8;
1956         break;
1957      case TI99CARTINFO_FCT_6000_W8:
1958         info->f = (genf *) write_cart_super8;
1959         break;
1960      case TI99CARTINFO_FCT_CRU_R:
1961         info->f = (genf *) read_cart_cru;
1962         break;
1963      case TI99CARTINFO_FCT_CRU_W:
1964         info->f = (genf *) write_cart_cru;
1965         break;
1966
1967      case DEVINFO_STR_NAME:
1968         strcpy(info->s, "TI99 SuperSpace cartridge pcb");
1969         break;
1970
1971      default:
1972         DEVICE_GET_INFO_CALL(ti99_cart_common);
1973         break;
1974   }
1975}
1976
1977DEVICE_GET_INFO(ti99_cartridge_pcb_mbx)
1978{
1979   switch(state)
1980   {
1981      case DEVINFO_FCT_START:
1982         info->start = DEVICE_START_NAME(ti99_pcb_mbx);
1983         break;
1984
1985      case TI99CART_FCT_ASSM:
1986         info->f = (genf *) assemble_mbx;
1987         break;
1988      case TI99CARTINFO_FCT_6000_R:
1989         info->f = (genf *) read_cart_mbx;
1990         break;
1991      case TI99CARTINFO_FCT_6000_W:
1992         info->f = (genf *) write_cart_mbx;
1993         break;
1994      case TI99CARTINFO_FCT_6000_R8:
1995         info->f = (genf *) read_cart_mbx8;
1996         break;
1997      case TI99CARTINFO_FCT_6000_W8:
1998         info->f = (genf *) write_cart_mbx8;
1999         break;
2000
2001
2002      case DEVINFO_STR_NAME:
2003         strcpy(info->s, "TI99 MBX cartridge pcb");
2004         break;
2005
2006      default:
2007         DEVICE_GET_INFO_CALL(ti99_cart_common);
2008         break;
2009   }
2010}
2011
2012DEVICE_GET_INFO(ti99_cartridge_pcb_paged379i)
2013{
2014   switch(state)
2015   {
2016      case DEVINFO_FCT_START:
2017         info->start = DEVICE_START_NAME(ti99_pcb_paged379i);
2018         break;
2019
2020      case TI99CART_FCT_ASSM:
2021         info->f = (genf *) assemble_paged379i; break;
2022
2023      case TI99CARTINFO_FCT_6000_R:
2024         info->f = (genf *) read_cart_paged379i;
2025         break;
2026
2027      case TI99CARTINFO_FCT_6000_W:
2028         info->f = (genf *) write_cart_paged379i;
2029         break;
2030
2031      case TI99CARTINFO_FCT_6000_R8:
2032         info->f = (genf *) read_cart_paged379i8;
2033         break;
2034
2035      case TI99CARTINFO_FCT_6000_W8:
2036         info->f = (genf *) write_cart_paged379i8;
2037         break;
2038
2039      case DEVINFO_STR_NAME:
2040         strcpy(info->s, "TI99 paged379i cartridge pcb");
2041         break;
2042
2043      default:
2044         DEVICE_GET_INFO_CALL(ti99_cart_common);
2045         break;
2046   }
2047}
2048
2049DEVICE_GET_INFO(ti99_cartridge_pcb_pagedcru)
2050{
2051   switch(state)
2052   {
2053      case DEVINFO_FCT_START:
2054         info->start = DEVICE_START_NAME(ti99_pcb_pagedcru);
2055         break;
2056
2057      case TI99CART_FCT_ASSM:
2058         info->f = (genf *) assemble_pagedcru;
2059         break;
2060
2061      case TI99CARTINFO_FCT_6000_R:
2062         info->f = (genf *) read_cart_pagedcru;
2063         break;
2064
2065      case TI99CARTINFO_FCT_6000_W:
2066         info->f = (genf *) write_cart_pagedcru;
2067         break;
2068
2069      case TI99CARTINFO_FCT_6000_R8:
2070         info->f = (genf *) read_cart_pagedcru8;
2071         break;
2072
2073      case TI99CARTINFO_FCT_6000_W8:
2074         info->f = (genf *) write_cart_pagedcru8;
2075         break;
2076
2077      case TI99CARTINFO_FCT_CRU_R:
2078         info->f = (genf *) read_cart_cru_paged;
2079         break;
2080      case TI99CARTINFO_FCT_CRU_W:
2081         info->f = (genf *) write_cart_cru_paged;
2082         break;
2083
2084      case DEVINFO_STR_NAME:
2085         strcpy(info->s, "TI99 pagedcru cartridge pcb");
2086         break;
2087
2088      default:
2089         DEVICE_GET_INFO_CALL(ti99_cart_common);
2090         break;
2091   }
2092}
2093
2094DEVICE_GET_INFO(ti99_cartridge_pcb_gramkracker)
2095{
2096   switch(state)
2097   {
2098      case DEVINFO_FCT_START:
2099         info->start = DEVICE_START_NAME(ti99_pcb_gramkracker);
2100         break;
2101
2102      case TI99CART_FCT_ASSM:
2103         info->f = (genf *) assemble_gramkracker;
2104         break;
2105
2106      case TI99CART_FCT_DISASSM:
2107         info->f = (genf *) disassemble_gramkracker;
2108         break;
2109
2110      case DEVINFO_STR_NAME:
2111         strcpy(info->s, "TI99 GRAM Kracker system");
2112         break;
2113
2114      default:
2115         DEVICE_GET_INFO_CALL(ti99_cart_common);
2116         break;
2117   }
2118}
2119
2120
2121/*****************************************************************************
2122  The cartridge handling of the multi-cartridge system.
2123  Every cartridge contains a PCB device. The memory handlers delegate the calls
2124  to the respective handlers of the cartridges.
2125******************************************************************************/
2126/*
2127    Initialize a cartridge. Each cartridge contains a PCB device.
2128*/
2129static DEVICE_START( ti99_cartridge )
2130{
2131   cartslot_t *cart = (cartslot_t *)downcast<legacy_device_base *>(device)->token();
2132
2133   /* find the PCB device */
2134   cart->pcb_device = device->subdevice(TAG_PCB);
2135}
2136
2137/*
2138    Load the cartridge image files. Apart from reading, we set pointers
2139    to the image files so that during runtime we do not need search
2140    operations.
2141*/
2142static DEVICE_IMAGE_LOAD( ti99_cartridge )
2143{
2144   running_device *pcbdev = cartslot_get_pcb(&image.device());
2145   running_device *cartsys = image.device().owner();
2146   ti99_multicart_state *cartslots = (ti99_multicart_state *)downcast<legacy_device_base *>(cartsys)->token();
2147
2148   int result;
2149
2150   result = load_legacy(image);
2151
2152   if (result != IMAGE_INIT_FAIL)
2153      cartslots->legacy_slots++;
2154   else
2155   {
2156      if (pcbdev != NULL)
2157      {
2158         /* If we are here, we have a multicart. */
2159         ti99_pcb_t *pcb = (ti99_pcb_t *)downcast<legacy_device_base *>(pcbdev)->token();
2160         cartslot_t *cart = (cartslot_t *)downcast<legacy_device_base *>(&image.device())->token();
2161
2162         /* try opening this as a multicart */
2163         // This line requires that cartslot_t be included in cartslot.h,
2164         // otherwise one cannot make use of multicart handling within such a
2165         // custom LOAD function.
2166         multicart_open_error me = multicart_open(image.filename(), image.device().machine->gamedrv->name, MULTICART_FLAGS_LOAD_RESOURCES, &cart->mc);
2167
2168         // Now that we have loaded the image files, let the PCB put them all
2169         // together. This means we put the images in a structure which allows
2170         // for a quick access by the memory handlers. Every PCB defines an
2171         // own assembly method.
2172         if (me == MCERR_NONE)
2173            result = pcb->assemble(image);
2174         else
2175            fatalerror("Error loading multicart: %s", multicart_error_text(me));
2176
2177         // This is for legacy support. If we have no multicart left
2178         // but there are still legacy dumps, we switch to legacy mode.
2179         if (result != IMAGE_INIT_FAIL)
2180            cartslots->multi_slots++;
2181      }
2182      else
2183      {
2184         fatalerror("Error loading multicart: no pcb found.");
2185      }
2186   }
2187   return result;
2188}
2189
2190/*
2191    This is called when the cartridge is unplugged (or the emulator is
2192    stopped).
2193*/
2194static DEVICE_IMAGE_UNLOAD( ti99_cartridge )
2195{
2196   running_device *pcbdev;
2197   ti99_multicart_state *cartslots = (ti99_multicart_state *)downcast<legacy_device_base *>(image.device().owner())->token();
2198
2199   if (downcast<legacy_device_base *>(&image.device())->token() == NULL)
2200   {
2201      // This means something went wrong during the pcb
2202      // identification (e.g. one of the cartridge files was not
2203      // found). We do not need to (and cannot) unload the cartridge.
2204      return;
2205   }
2206   pcbdev = cartslot_get_pcb(image);
2207
2208   if (pcbdev != NULL)
2209   {
2210      ti99_pcb_t *pcb = (ti99_pcb_t *)downcast<legacy_device_base *>(pcbdev)->token();
2211      cartslot_t *cart = (cartslot_t *)downcast<legacy_device_base *>(&image.device())->token();
2212
2213      if (cart->mc != NULL)
2214      {
2215         /* Remove pointers and de-big-endianize RAM contents. */
2216         pcb->disassemble(image);
2217
2218         // Close the multicart; all RAM resources will be
2219         // written to disk
2220         multicart_close(cart->mc);
2221         cart->mc = NULL;
2222
2223         /* See above: Legacy support. */
2224         cartslots->multi_slots--;
2225      }
2226//      else
2227//          fatalerror("Lost pointer to multicart in cartridge. Report bug.");
2228   }
2229   else
2230   {
2231      unload_legacy(image);
2232      cartslots->legacy_slots--;
2233   }
2234}
2235
2236/*****************************************************************************
2237  The legacy cartridge slot system.
2238
2239  This is the system which was used for the TI family until MESS 0.130.
2240  Here, plain ROM dumps were mounted on the slots, e.g. the GROM on slot 1,
2241  ROM on slot 2. No multiple cartridges were supported.
2242
2243  This functionality is deprecated.
2244
2245  In order to allow for a smooth transition, this feature is included in this
2246  version. It is strongly recommmended to create suitable multicart packs.
2247
2248  This implementation tolerates both cartridge systems in the following way:
2249  - If there are only single ROM dumps, the system switched to legacy mode.
2250  - If there is at least one multicart pack in any slot, the system switches
2251    to the multicart mode. All plain dumps become invisible; the slots appear
2252    empty to the system
2253  - Both modes may change on plugging and unplugging.
2254******************************************************************************/
2255
2256static UINT8 cartridge_grom_read_legacy(running_device *cartsys)
2257{
2258   int slot;
2259   cartridge_t *cartridge;
2260   ti99_multicart_state *cartslots = (ti99_multicart_state *)downcast<legacy_device_base *>(cartsys)->token();
2261
2262   UINT8 value;
2263
2264   /* Get the GROM slot number. */
2265   slot = cartslots->legacy_slotnumber[SLOTC_GROM];
2266   if (slot<0)
2267      /* No GROM available. */
2268      return 0;
2269
2270   cartridge = &cartslots->cartridge[slot];
2271
2272   if (cartridge->grom_size>0)
2273   {
2274      // This is the reason why we need the image size: Read
2275      // access beyond the image size must be detected.
2276      if ((cartslots->grom_address < 0x6000) || (cartslots->grom_address > (cartridge->grom_size+0x6000)))
2277         return 0;
2278
2279      value =  (UINT8)cartslots->grom_buffer;
2280      /* read ahead */
2281      cartslots->grom_buffer = cartridge->grom_ptr[cartslots->grom_address-0x6000];
2282      // The program counter wraps at each GROM chip size (8K),
2283      // so 0x5fff + 1 = 0x4000.
2284      cartslots->grom_address = ((cartslots->grom_address + 1) & 0x1FFF) | (cartslots->grom_address & 0xE000);
2285
2286      /* Reset the read and write address flipflops. */
2287      cartslots->raddr_LSB = cartslots->waddr_LSB = FALSE;
2288   }
2289   else
2290   {
2291      /* We assume that empty sockets return 0 */
2292      value = 0;
2293      logerror("Empty socket at address G(%d)>%04x\n", slot, cartslots->grom_address);
2294   }
2295   return value;
2296}
2297
2298static READ16_DEVICE_HANDLER( ti99_cart_r_legacy )
2299{
2300   int slotmbx, slotmini, slotebr2, slotrom;
2301   ti99_multicart_state *cartslots = (ti99_multicart_state *)downcast<legacy_device_base *>(device)->token();
2302
2303   slotmbx = cartslots->legacy_slotnumber[SLOTC_MBX];
2304
2305   if ((slotmbx != -1) && (offset >= 0x0600) && (offset <= 0x07fe))
2306   {
2307      /* We are in the RAM area of MBX cartridges. */
2308      return ((UINT16 *)(cartslots->cartridge[slotmbx].ram_ptr))[offset-0x0600];
2309   }
2310
2311   slotmini = cartslots->legacy_slotnumber[SLOTC_MINIMEM];
2312   if ((slotmini != -1) && (offset >= 0x0800) && (offset <= 0x0fff))
2313   {
2314      /* We are in the RAM area of the Mini Memory cartridge. */
2315      return ((UINT16 *)(cartslots->cartridge[slotmini].ram_ptr))[offset-0x0800];
2316   }
2317
2318   /* Standard */
2319   slotrom = cartslots->legacy_slotnumber[SLOTC_CROM];
2320   if (slotrom < 0)
2321      return 0;
2322
2323   slotebr2 = cartslots->legacy_slotnumber[SLOTC_DROM];
2324   if (slotebr2 < 0)
2325      return (((UINT16 *)cartslots->cartridge[slotrom].rom_ptr)[offset]);
2326   else
2327   {
2328      /* Extended Basic or other paged cartridge */
2329      if (cartslots->cartridge[slotrom].rom_page!=0)
2330         return (((UINT16 *)cartslots->cartridge[slotebr2].rom2_ptr)[offset]);
2331      else
2332         return (((UINT16 *)cartslots->cartridge[slotrom].rom_ptr)[offset]);
2333   }
2334
2335   /* SuperSpace, paged379i, and pagedcru are not supported in legacy mode. */
2336}
2337
2338static WRITE16_DEVICE_HANDLER( ti99_cart_w_legacy )
2339{
2340   int slotmbx, slotmini, slotebr2, slotrom;
2341   ti99_multicart_state *cartslots = (ti99_multicart_state *)downcast<legacy_device_base *>(device)->token();
2342
2343   slotmbx = cartslots->legacy_slotnumber[SLOTC_MBX];
2344   slotrom = cartslots->legacy_slotnumber[SLOTC_CROM];
2345   slotebr2 = cartslots->legacy_slotnumber[SLOTC_DROM];
2346   slotmini = cartslots->legacy_slotnumber[SLOTC_MINIMEM];
2347
2348   if (slotmbx != -1)
2349   {
2350      if ((offset >= 0x0600) && (offset <= 0x07fe))
2351      {
2352         /* We are in the RAM area of MBX cartridges. */
2353         /* RAM in 0x6c00-0x6ffd (presumably non-paged) */
2354         /* mapper at 0x6ffe */
2355         COMBINE_DATA(((UINT16 *)cartslots->cartridge[slotmbx].ram_ptr) + offset - 0x0600);
2356      }
2357      else
2358      {
2359         if ((offset == 0x07ff) && ACCESSING_BITS_8_15)
2360         {
2361            if (slotebr2 < 0 || slotrom < 0)
2362               return; /* just ignore if the cartridge is not paged. */
2363            else
2364               cartslots->cartridge[slotrom].rom_page = ((data >> 8) & 1);
2365         }
2366      }
2367      return;
2368   }
2369   if (slotmini != -1)
2370   {
2371      if ((offset >= 0x0800) && (offset <= 0x0fff))
2372         /* We are in the RAM area of a MiniMemory cartridge. */
2373         COMBINE_DATA(((UINT16 *)cartslots->cartridge[slotmini].ram_ptr) + offset - 0x0800);
2374      return;
2375   }
2376   if (slotebr2 != -1 && slotrom != -1)
2377   {
2378      cartslots->cartridge[slotrom].rom_page = (offset & 1);
2379   }
2380}
2381
2382/*
2383    TI-99/8 support.
2384*/
2385static READ8_DEVICE_HANDLER( ti99_cart_r_legacy8 )
2386{
2387   int slotmbx, slotmini, slotebr2, slotrom;
2388   ti99_multicart_state *cartslots = (ti99_multicart_state *)downcast<legacy_device_base *>(device)->token();
2389
2390   slotmbx = cartslots->legacy_slotnumber[SLOTC_MBX];
2391
2392   if ((slotmbx != -1) && (offset >= 0x0c00) && (offset <= 0x0ffd))
2393   {
2394      /* We are in the RAM area of MBX cartridges. */
2395      return ((UINT8 *)(cartslots->cartridge[slotmbx].ram_ptr))[offset-0x0c00];
2396   }
2397
2398   slotmini = cartslots->legacy_slotnumber[SLOTC_MINIMEM];
2399   if ((slotmini != -1) && (offset >= 0x1000) && (offset <= 0x1fff))
2400   {
2401      /* We are in the RAM area of the Mini Memory cartridge. */
2402      return ((UINT8 *)(cartslots->cartridge[slotmini].ram_ptr))[offset-0x1000];
2403   }
2404
2405   /* Standard */
2406   slotrom = cartslots->legacy_slotnumber[SLOTC_CROM];
2407   if (slotrom < 0)
2408      return 0;
2409
2410   slotebr2 = cartslots->legacy_slotnumber[SLOTC_DROM];
2411   if (slotebr2 < 0)
2412      return (((UINT8 *)cartslots->cartridge[slotrom].rom_ptr)[offset]);
2413   else
2414   {
2415      /* Extended Basic or other paged cartridge */
2416      if (cartslots->cartridge[slotrom].rom_page!=0)
2417         return (((UINT8 *)cartslots->cartridge[slotebr2].rom2_ptr)[offset]);
2418      else
2419         return (((UINT8 *)cartslots->cartridge[slotrom].rom_ptr)[offset]);
2420   }
2421   /* Super Space, paged379i, and pagedcru are not supported in legacy mode. */
2422}
2423
2424/*
2425    TI-99/8 support.
2426*/
2427static WRITE8_DEVICE_HANDLER( ti99_cart_w_legacy8 )
2428{
2429   int slotmbx, slotmini, slotebr2, slotrom;
2430   ti99_multicart_state *cartslots = (ti99_multicart_state *)downcast<legacy_device_base *>(device)->token();
2431
2432   slotmbx = cartslots->legacy_slotnumber[SLOTC_MBX];
2433   slotrom = cartslots->legacy_slotnumber[SLOTC_CROM];
2434   slotebr2 = cartslots->legacy_slotnumber[SLOTC_DROM];
2435   slotmini = cartslots->legacy_slotnumber[SLOTC_MINIMEM];
2436
2437   if (slotmbx != -1)
2438   {
2439      if ((offset >= 0x0c00) && (offset <= 0x0ffd))
2440      {
2441         /* We are in the RAM area of MBX cartridges. */
2442         /* RAM in 0x6c00-0x6ffd (presumably non-paged) */
2443         /* mapper at 0x6ffe */
2444         ((UINT8 *)cartslots->cartridge[slotmbx].ram_ptr)[offset - 0x0c00] = data;
2445      }
2446      else
2447      {
2448         if (offset == 0x0ffe || offset == 0x0fff)
2449         {
2450            if (slotebr2 < 0 || slotrom < 0)
2451               return; /* just ignore if the cartridge is not paged. */
2452            else
2453               cartslots->cartridge[slotrom].rom_page = ((data >> 7) & 1);
2454         }
2455      }
2456      return;
2457   }
2458   if (slotmini != -1)
2459   {
2460      if ((offset >= 0x1000) && (offset <= 0x1fff))
2461         /* We are in the RAM area of a MiniMemory cartridge. */
2462         ((UINT8 *)cartslots->cartridge[slotmini].ram_ptr)[offset - 0x1000] = data;
2463      return;
2464   }
2465   if (slotebr2 != -1 && slotrom != -1)
2466   {
2467      cartslots->cartridge[slotrom].rom_page = (offset & 1);
2468   }
2469}
2470
2471
2472static int load_legacy(device_image_interface &image)
2473{
2474   running_device *cartsys = image.device().owner();
2475   ti99_multicart_state *cartslots = (ti99_multicart_state *)downcast<legacy_device_base *>(cartsys)->token();
2476
2477   /* Some comments originally in machine/ti99_4x.c */
2478
2479   /* We identify file types according to their extension */
2480   // Note that if we do not recognize the extension, we revert to the
2481   // slot location <-> type scheme.
2482   int id = 0;
2483   int i;
2484   int filesize;
2485   int maxrom = 0x2000;
2486   slotc_type_t type;
2487   int savembx;
2488
2489   const char *ch, *ch2;
2490   const char *name = image.filename();
2491
2492   UINT8 *grom = memory_region(image.device().machine, region_grom) + 0x6000;
2493   UINT16 *cartrom = (UINT16 *) (memory_region(image.device().machine, "maincpu") + offset_cart);
2494   UINT16 *cartrom2 = (UINT16 *) (memory_region(image.device().machine, "maincpu") + offset_cart + 0x2000);
2495   UINT8 *cart8rom = memory_region(image.device().machine, "maincpu") + offset_cart_8;
2496   UINT8 *cart8rom2  = memory_region(image.device().machine, "maincpu") + offset_cart_8 + 0x2000;
2497
2498   UINT16 *cartmbx;
2499   UINT8 *cartmbx8;
2500
2501   type = SLOTC_EMPTY;
2502
2503   ch = strrchr(name, '.');
2504   ch2 = (ch-1 >= name) ? ch-1 : "";
2505
2506   if (ch)
2507   {
2508      if (! mame_stricmp(ch2, "g.bin"))
2509      {
2510         /* grom */
2511         type = SLOTC_GROM;
2512      }
2513      else if (! mame_stricmp(ch2, "c.bin"))
2514      {
2515         /* rom first page */
2516         type = SLOTC_CROM;
2517      }
2518      else if (! mame_stricmp(ch2, "d.bin"))
2519      {
2520         /* rom second page */
2521         type = SLOTC_DROM;
2522      }
2523      else if (! mame_stricmp(ch2, "m.bin"))
2524      {
2525         /* rom minimemory  */
2526         type = SLOTC_MINIMEM;
2527      }
2528      else if (! mame_stricmp(ch2, "b.bin"))
2529      {
2530         /* rom MBX  */
2531         type = SLOTC_MBX;
2532      }
2533   }
2534
2535   if (type == SLOTC_EMPTY)
2536   {
2537      return IMAGE_INIT_FAIL;
2538   }
2539
2540   id = get_index_from_tagname(image)-1;
2541
2542   /* Remember where the cartridge part is plugged in. */
2543   cartslots->legacy_slotnumber[type] = id;
2544
2545   savembx = FALSE;
2546
2547   // We will use the already allocated buffers in the memory regions,
2548   // and the pointers in the cartridge structure will point to them.
2549   switch (type)
2550   {
2551      case SLOTC_EMPTY:
2552         break;
2553
2554      case SLOTC_GROM:
2555         filesize = image.fread(grom, 0xA000);
2556         cartslots->cartridge[id].grom_ptr = grom;
2557         cartslots->cartridge[id].grom_size = filesize;
2558         // printf("loaded GROM, size = %d\n", filesize);
2559         break;
2560
2561      case SLOTC_CROM:
2562         maxrom = 0x2000;
2563         if (cartslots->legacy_slotnumber[SLOTC_MINIMEM] != -1)
2564         {
2565            // This means the NVRAM has already been loaded.
2566            // So we just load 4K of ROM to avoid
2567            // overwriting the NVRAM.
2568            maxrom = 0x1000;
2569         }
2570
2571         if (cartslots->legacy_slotnumber[SLOTC_MBX] != -1)
2572         {
2573            // This means the NVRAM has already been loaded.
2574            // We need to temporarily save the RAM contents
2575            // and write them back because the RAM overrides
2576            // the ROM in an intermediate area.
2577            savembx = TRUE;
2578         }
2579
2580         if (ti99_is_99_8())
2581         {
2582            // printf("** is 99/8\n");
2583            if (savembx==TRUE)
2584            {
2585               cartmbx8 = (UINT8*)malloc(0x400);
2586               memcpy(cartmbx8, cart8rom + 0x0c00, 0x400);
2587               filesize = image.fread(cart8rom, maxrom);
2588               memcpy(cart8rom + 0xc00, cartmbx8, 0x400);
2589               free(cartmbx8);
2590            }
2591            else
2592            {
2593               filesize = image.fread(cart8rom, maxrom);
2594            }
2595            cartslots->cartridge[id].rom_ptr = cart8rom;
2596            cartslots->cartridge[id].rom_size = filesize;
2597         }
2598         else
2599         {
2600            if (savembx==TRUE)
2601            {
2602               cartmbx = (UINT16*)malloc(0x400);
2603               memcpy(cartmbx, cartrom + 0x0600, 0x400);
2604               filesize = image.fread(cartrom, maxrom);
2605               memcpy(cartrom + 0x0600, cartmbx, 0x400);
2606               free(cartmbx);
2607            }
2608            filesize = image.fread(cartrom, maxrom);
2609            for (i = 0; i < maxrom/2; i++)
2610               ((UINT16 *)cartrom)[i] = BIG_ENDIANIZE_INT16(((UINT16 *)cartrom)[i]);
2611            cartslots->cartridge[id].rom_ptr = cartrom;
2612            cartslots->cartridge[id].rom_size = filesize;
2613         }
2614         break;
2615
2616      case SLOTC_MINIMEM:
2617         // Load the NVRAM. Need to BIG_ENDIANIZE it.
2618         // MiniMemory has only one cartridge page.
2619         if (ti99_is_99_8())
2620         {
2621            // printf("** is 99/8\n");
2622            image.battery_load(cart8rom+0x1000,0x1000, 0x00);
2623            cartslots->cartridge[id].ram_ptr = cart8rom +  0x1000;
2624         }
2625         else
2626         {
2627            image.battery_load(cartrom+0x800,0x1000, 0x00);
2628            for (i = 0x800; i < 0x1000; i++)
2629               cartrom[i] = BIG_ENDIANIZE_INT16(cartrom[i]);
2630            cartslots->cartridge[id].ram_ptr = (UINT16 *)cartrom +  0x800;
2631         }
2632         cartslots->cartridge[id].ram_size = 0x1000;
2633         break;
2634
2635      case SLOTC_MBX:
2636         /* Load the NVRAM. Need to BIG_ENDIANIZE it. */
2637         if (ti99_is_99_8())
2638         {
2639            // printf("** is 99/8\n");
2640            image.battery_load(cart8rom+0x0c00, 0x0400, 0x00);
2641            cartslots->cartridge[id].ram_ptr = cart8rom +  0xc00;
2642         }
2643         else
2644         {
2645            image.battery_load(cartrom+0x0600, 0x0400, 0x00);
2646            for (i = 0x0600; i < 0x0800; i++)
2647               cartrom[i] = BIG_ENDIANIZE_INT16(cartrom[i]);
2648            cartslots->cartridge[id].ram_ptr = (UINT16 *)cartrom +  0x600;
2649         }
2650         cartslots->cartridge[id].ram_size = 0x0400;
2651         // printf("loaded NVRAM\n");
2652         break;
2653
2654      case SLOTC_DROM:
2655         maxrom = 0x2000;
2656         if (ti99_is_99_8())
2657         {
2658            // printf("** is 99/8\n");
2659            filesize = image.fread(cart8rom2, maxrom);
2660            cartslots->cartridge[id].rom2_ptr = cart8rom2;
2661         }
2662         else
2663         {
2664            filesize = image.fread(cartrom2, maxrom);
2665            for (i = 0; i < maxrom/2; i++)
2666               cartrom2[i] = BIG_ENDIANIZE_INT16(cartrom2[i]);
2667            cartslots->cartridge[id].rom2_ptr = cartrom2;
2668         }
2669         cartslots->cartridge[id].rom_size = filesize;
2670         break;
2671   }
2672   return IMAGE_INIT_PASS;
2673}
2674
2675static void unload_legacy(device_image_interface &image)
2676{
2677   int i;
2678   running_device *cartsys = image.device().owner();
2679
2680   ti99_multicart_state *cartslots = (ti99_multicart_state *)downcast<legacy_device_base *>(cartsys)->token();
2681
2682   slotc_type_t type = SLOTC_EMPTY;
2683   int slot = get_index_from_tagname(image)-1;
2684
2685   // printf("non-rpk unload\n");
2686
2687   for (i=0; (i < 5) && (type==SLOTC_EMPTY); i++)
2688   {
2689      if (cartslots->legacy_slotnumber[i]==slot)
2690      {
2691         cartslots->legacy_slotnumber[i] = -1;
2692         type = (slotc_type_t)i;
2693      }
2694   }
2695
2696   switch (type)
2697   {
2698      case SLOTC_EMPTY:
2699         break;
2700
2701      case SLOTC_GROM:
2702         memset(cartslots->cartridge[slot].grom_ptr, 0, 0xA000);
2703         break;
2704
2705      case SLOTC_MINIMEM:
2706         if (ti99_is_99_8())
2707         {
2708            // printf("** is 99/8\n");
2709            image.battery_save(cartslots->cartridge[slot].ram_ptr, 0x1000);
2710            memset(cartslots->cartridge[slot].ram_ptr, 0, 0x1000);
2711         }
2712         else
2713         {
2714            // We BIG_ENDIANIZE before saving. This is
2715            // consistent with the cartridge save format.
2716            UINT16 *ramcont = (UINT16 *)cartslots->cartridge[slot].ram_ptr;
2717            for (i = 0; i < 0x0800; i++)
2718               ramcont[i] = BIG_ENDIANIZE_INT16(ramcont[i]);
2719            image.battery_save(ramcont, 0x1000);
2720            memset(ramcont, 0, 0x1000);
2721         }
2722         break;
2723      case SLOTC_MBX:
2724         if (ti99_is_99_8())
2725         {
2726            // printf("** is 99/8\n");
2727            image.battery_save(cartslots->cartridge[slot].ram_ptr, 0x0400);
2728            memset(cartslots->cartridge[slot].ram_ptr, 0, 0x0400);
2729         }
2730         else
2731         {
2732            // We BIG_ENDIANIZE before saving. This is
2733            // consistent with the cartridge save format.
2734            UINT16 *ramcont = (UINT16 *)cartslots->cartridge[slot].ram_ptr;
2735            for (i = 0; i < 0x0200; i++)
2736               ramcont[i] = BIG_ENDIANIZE_INT16(ramcont[i]);
2737            image.battery_save(ramcont, 0x0400);
2738            memset(ramcont, 0, 0x0400);
2739         }
2740         break;
2741      case SLOTC_CROM:
2742         if (cartslots->legacy_slotnumber[SLOTC_MINIMEM]!=-1)
2743            /* Don't wipe the RAM before it is saved. */
2744            memset(cartslots->cartridge[slot].rom_ptr, 0, 0x1000);
2745         else
2746            memset(cartslots->cartridge[slot].rom_ptr, 0, 0x2000);
2747         break;
2748
2749      case SLOTC_DROM:
2750         cartslots->cartridge[slot].rom_page = 0;
2751         memset(cartslots->cartridge[slot].rom2_ptr, 0, 0x2000);
2752         break;
2753   }
2754
2755   clear_slot(cartsys, slot);
2756}
2757
2758/*****************************************************************************
2759  The overall multi-cartridge slot system. It contains instances of
2760  cartridges which contain PCB devices. The memory handlers delegate the calls
2761  to the respective handlers of the cartridges.
2762
2763  Note that the term "multi-cartridge system" and "multicart" are not the same:
2764  A "multicart" may contain multiple resources, organized on a PCB. The multi-
2765  cart system may thus host multiple multicarts.
2766
2767  Actually, the name of the device should be changed (however, the device name
2768  length is limited)
2769******************************************************************************/
2770
2771/* GRAM Kracker support */
2772static WRITE16_DEVICE_HANDLER( ti99_cart_w_gk );
2773static READ16_DEVICE_HANDLER( ti99_cart_r_gk );
2774static WRITE16_DEVICE_HANDLER( ti99_cart_w_gk );
2775static READ8_DEVICE_HANDLER( ti99_cart_crur_gk );
2776static WRITE8_DEVICE_HANDLER( ti99_cart_cruw_gk );
2777static READ8_DEVICE_HANDLER( ti99_cart_r_gk8 );
2778static WRITE8_DEVICE_HANDLER( ti99_cart_w_gk8 );
2779
2780/*
2781    Instantiation of a multicart system for the TI family.
2782*/
2783static DEVICE_START(ti99_multicart)
2784{
2785   int i;
2786   ti99_multicart_state *cartslots = (ti99_multicart_state *)downcast<legacy_device_base *>(device)->token();
2787
2788   cartslots->active_slot = 0;
2789   cartslots->next_free_slot = 0;
2790
2791   for (i=0; i < NUMBER_OF_CARTRIDGE_SLOTS; i++)
2792   {
2793      cartslots->cartridge[i].pcb = NULL;
2794      clear_slot(device, i);
2795   }
2796
2797   /* Initialize the legacy system. */
2798   cartslots->legacy_slotnumber[SLOTC_GROM] = -1;
2799   cartslots->legacy_slotnumber[SLOTC_CROM] = -1;
2800   cartslots->legacy_slotnumber[SLOTC_DROM] = -1;
2801   cartslots->legacy_slotnumber[SLOTC_MINIMEM] = -1;
2802   cartslots->legacy_slotnumber[SLOTC_MBX] = -1;
2803
2804   cartslots->legacy_slots = 0;
2805   cartslots->multi_slots = 0;
2806
2807   cartslots->gk_slot = -1;
2808   cartslots->gk_guest_slot = -1;
2809
2810   // The cartslot system is initialized now. The cartridges themselves
2811   // need to check whether their parts are available.
2812}
2813
2814static DEVICE_STOP(ti99_multicart)
2815{
2816//  printf("DEVICE_STOP(ti99_multicart)\n");
2817}
2818
2819static DEVICE_RESET(ti99_multicart)
2820{
2821   // Consider to propagate RESET to cartridges.
2822   // However, schematics do not reveal any pin for resetting a cartridge;
2823   // the reset line is an input used when plugging in a cartridge.
2824
2825   ti99_multicart_state *cartslots = (ti99_multicart_state *)downcast<legacy_device_base *>(device)->token();
2826   int slotnumber = input_port_read(device->machine, "CARTSLOT");
2827   assert(slotnumber>=0 && slotnumber<=255);
2828   cartslots->fixed_slot = slotnumber-1; /* auto = -1 */
2829   cartslots->grom_address = 0x0000;
2830   cartslots->grom_buffer = 0x00;
2831   cartslots->loader_on = FALSE;
2832   cartslots->raddr_LSB = cartslots->waddr_LSB = FALSE;
2833}
2834
2835/*
2836    Accesses the ROM regions of the cartridge for reading.
2837    This is the area from 0x6000 to 0x7fff. Each cartridge is responsible
2838    for all kinds of magic which is done inside this area, like swapping
2839    banks or doing other control actions. These activities beyond simple
2840    reading are cartridge-specific. Each kind of cartridge requires a
2841    new type.
2842    The currently set GROM bank determines which cartridge is actually
2843    accessed, also for ROM reads.
2844*/
2845READ16_DEVICE_HANDLER( ti99_multicart_r )
2846{
2847   ti99_multicart_state *cartslots = (ti99_multicart_state *) downcast<legacy_device_base *>(device)->token();
2848   int slot = cartslots->active_slot;
2849   cartridge_t *cart;
2850
2851   /* Idle the CPU */
2852   cpu_adjust_icount(device->machine->device("maincpu"),-4);
2853   // Alternatively:
2854   // cpu_spinuntil_time(device->machine->firstcpu, ATTOTIME_IN_USEC(6));
2855
2856   // Handle GRAM Kracker
2857   // We could also consider to use a flag, but input_port_read uses
2858   // a hashtable, so this should not be too slow
2859   if ((cartslots->gk_slot != -1) && (input_port_read(device->machine, "CARTSLOT")==CART_GK))
2860      return ti99_cart_r_gk(device, offset, mem_mask);
2861
2862   /* Sanity check. Higher slots are always empty. */
2863   if (slot >= NUMBER_OF_CARTRIDGE_SLOTS)
2864      return 0;
2865
2866   // Same as above (GROM read): If there is only one cartridge there
2867   // is no use of trying other banks. There is one issue with the
2868   // selection mechanism: When the console probes the GROM banks and
2869   // we have a ROM-only cartridge plugged in, it checks bank 0 and bank 1,
2870   // finds no GROM, and then fails to dummy-check bank 0 again which would
2871   // have set our cartridge expander to slot 0. But in slot 1 there is no
2872   // ROM cartridge, so nothing shows up in the selection list. We work
2873   // around this with the following line.
2874   if (cartslots->fixed_slot==AUTO && cartslots->next_free_slot==1)
2875      slot=0;
2876
2877   cart = &cartslots->cartridge[slot];
2878
2879   /* Handle legacy mode. */
2880   if (in_legacy_mode(device))
2881   {
2882      return ti99_cart_r_legacy(device, offset, mem_mask);
2883   }
2884
2885   if (!slot_is_empty(device, slot))
2886   {
2887      //      printf("accessing cartridge in slot %d\n", slot);
2888      ti99_pcb_t *pcbdef = (ti99_pcb_t *)downcast<legacy_device_base *>(cart->pcb)->token();;
2889      //      printf("address=%lx, offset=%lx\n", pcbdef, offset);
2890      return (*pcbdef->read)(cart->pcb, offset, mem_mask);
2891   }
2892   else
2893   {
2894      //      printf("No cartridge in slot %d\n", slot);
2895      return 0;
2896   }
2897}
2898
2899/*
2900    Accesses the ROM regions of the cartridge for writing.
2901    This is the area from 0x6000 to 0x7fff. Each cartridge is responsible
2902    for all kinds of magic which is done inside this area. Specifically,
2903    writing is often used to swap banks for subsequent reads. The actual
2904    effect of writing (beyond setting values in a RAM chip) are
2905    cartridge-specific and must be handled within the cartridge pcb.
2906    The currently set GROM bank determines which cartridge is actually
2907    accessed, also for ROM reads.
2908*/
2909WRITE16_DEVICE_HANDLER( ti99_multicart_w )
2910{
2911   ti99_multicart_state *cartslots = (ti99_multicart_state *) downcast<legacy_device_base *>(device)->token();
2912   int slot = cartslots->active_slot;
2913   cartridge_t *cart;
2914
2915   /* Idle the CPU */
2916   cpu_adjust_icount(device->machine->device("maincpu"),-4);
2917//  cpu_spinuntil_time(device->machine->firstcpu, ATTOTIME_IN_USEC(6));
2918
2919   // Handle GRAM Kracker
2920   if ((cartslots->gk_slot != -1) && (input_port_read(device->machine, "CARTSLOT")==CART_GK))
2921      ti99_cart_w_gk(device, offset, data, mem_mask);
2922
2923   /* Sanity check. Higher slots are always empty. */
2924   if (slot >= NUMBER_OF_CARTRIDGE_SLOTS)
2925      return;
2926
2927   /* Same as above (READ16). */
2928   if (cartslots->fixed_slot==AUTO && cartslots->next_free_slot==1)
2929      slot=0;
2930
2931   cart = &cartslots->cartridge[slot];
2932
2933   /* Handle legacy mode. */
2934   if (in_legacy_mode(device))
2935   {
2936      ti99_cart_w_legacy(device, offset, data, mem_mask);
2937   }
2938   else
2939   {
2940      if (!slot_is_empty(device, slot))
2941      {
2942         ti99_pcb_t *pcbdef = (ti99_pcb_t *)downcast<legacy_device_base *>(cart->pcb)->token();;
2943         (*pcbdef->write)(cart->pcb, offset, data, mem_mask);
2944      }
2945   }
2946}
2947
2948/*
2949    CRU interface to cartridges, used only by SuperSpace and Pagedcru
2950    style cartridges.
2951    The SuperSpace has a CRU-based memory mapper. It is accessed via the
2952    cartridge slot on CRU base >0800.
2953*/
2954READ8_DEVICE_HANDLER( ti99_multicart_cru_r )
2955{
2956   ti99_multicart_state *cartslots = (ti99_multicart_state *) downcast<legacy_device_base *>(device)->token();
2957   cartridge_t *cart;
2958
2959   int slot = cartslots->active_slot;
2960
2961   /* We don't support this cartridge type in the legacy mode. */
2962   if (in_legacy_mode(device))
2963      return 0;
2964
2965   // Handle GRAM Kracker
2966   if ((cartslots->gk_slot != -1) && (input_port_read(device->machine, "CARTSLOT")==CART_GK))
2967      return ti99_cart_crur_gk(device, offset);
2968
2969   /* Sanity check. Higher slots are always empty. */
2970   if (slot >= NUMBER_OF_CARTRIDGE_SLOTS)
2971      return 0;
2972
2973   /* Same as above (READ16). */
2974   if (cartslots->fixed_slot==AUTO && cartslots->next_free_slot==1)
2975      slot=0;
2976
2977   cart = &cartslots->cartridge[slot];
2978
2979   if (!slot_is_empty(device, slot))
2980   {
2981      ti99_pcb_t *pcbdef = (ti99_pcb_t *)downcast<legacy_device_base *>(cart->pcb)->token();;
2982      if (pcbdef->cruread != NULL)
2983         return (*pcbdef->cruread)(cart->pcb, offset);
2984   }
2985   return 0;
2986}
2987
2988/*
2989    Write cartridge mapper CRU interface (SuperSpace, Pagedcru)
2990*/
2991WRITE8_DEVICE_HANDLER( ti99_multicart_cru_w )
2992{
2993   ti99_multicart_state *cartslots = (ti99_multicart_state *) downcast<legacy_device_base *>(device)->token();
2994   cartridge_t *cart;
2995
2996   int slot = cartslots->active_slot;
2997
2998   /* We don't support this cartridge type in the legacy mode. */
2999   if (in_legacy_mode(device))
3000      return;
3001
3002   // Handle GRAM Kracker
3003   if ((cartslots->gk_slot != -1) && (input_port_read(device->machine, "CARTSLOT")==CART_GK))
3004      ti99_cart_cruw_gk(device, offset, data);
3005
3006   /* Sanity check. Higher slots are always empty. */
3007   if (slot >= NUMBER_OF_CARTRIDGE_SLOTS)
3008      return;
3009
3010   /* Same as above (READ16). */
3011   if (cartslots->fixed_slot==AUTO && cartslots->next_free_slot==1)
3012      slot=0;
3013
3014   cart = &cartslots->cartridge[slot];
3015
3016   if (!slot_is_empty(device, slot))
3017   {
3018      ti99_pcb_t *pcbdef = (ti99_pcb_t *)downcast<legacy_device_base *>(cart->pcb)->token();;
3019      if (pcbdef->cruwrite != NULL)
3020         (*pcbdef->cruwrite)(cart->pcb, offset, data);
3021   }
3022}
3023
3024/*
3025    TI-99/8 support. We have only 8 bit memory access, so we adapt all
3026    functions to this width.
3027*/
3028READ8_DEVICE_HANDLER(ti99_multicart8_r)
3029{
3030   ti99_multicart_state *cartslots = (ti99_multicart_state *) downcast<legacy_device_base *>(device)->token();
3031   int slot = cartslots->active_slot;
3032   cartridge_t *cart;
3033
3034   /* Idle the CPU. TODO: Check whether this is correct for this machine. */
3035   cpu_adjust_icount(device->machine->device("maincpu"),-4);
3036
3037   // Handle GRAM Kracker
3038   if ((cartslots->gk_slot != -1) && (input_port_read(device->machine, "CARTSLOT")==CART_GK))
3039      return ti99_cart_r_gk8(device, offset);
3040
3041   /* Sanity check. Higher slots are always empty. */
3042   if (slot >= NUMBER_OF_CARTRIDGE_SLOTS)
3043      return 0;
3044
3045   /* Same as above (READ16). */
3046   if (cartslots->fixed_slot==AUTO && cartslots->next_free_slot==1)
3047      slot=0;
3048
3049   cart = &cartslots->cartridge[slot];
3050
3051   /* Handle legacy mode. */
3052   if (in_legacy_mode(device))
3053   {
3054      return ti99_cart_r_legacy8(device, offset);
3055   }
3056
3057   if (!slot_is_empty(device, slot))
3058   {
3059      ti99_pcb_t *pcbdef = (ti99_pcb_t *)downcast<legacy_device_base *>(cart->pcb)->token();;
3060      return (*pcbdef->read8)(cart->pcb, offset);
3061   }
3062   else
3063   {
3064      return 0;
3065   }
3066}
3067
3068WRITE8_DEVICE_HANDLER(ti99_multicart8_w)
3069{
3070   ti99_multicart_state *cartslots = (ti99_multicart_state *) downcast<legacy_device_base *>(device)->token();
3071   cartridge_t *cart;
3072   int slot = cartslots->active_slot;
3073
3074   /* Idle the CPU. TODO: Check whether this is correct for this machine. */
3075   cpu_adjust_icount(device->machine->device("maincpu"),-4);
3076
3077   // Handle GRAM Kracker
3078   if ((cartslots->gk_slot != -1) && (input_port_read(device->machine, "CARTSLOT")==CART_GK))
3079      ti99_cart_w_gk8(device, offset, data);
3080
3081   /* Sanity check. Higher slots are always empty. */
3082   if (slot >= NUMBER_OF_CARTRIDGE_SLOTS)
3083      return;
3084
3085   /* Same as above (READ16). */
3086   if (cartslots->fixed_slot==AUTO && cartslots->next_free_slot==1)
3087      slot=0;
3088
3089   cart = &cartslots->cartridge[slot];
3090
3091   /* Handle legacy mode. */
3092   if (in_legacy_mode(device))
3093   {
3094      ti99_cart_w_legacy8(device, offset, data);
3095   }
3096   else
3097   {
3098      if (!slot_is_empty(device, slot))
3099      {
3100         ti99_pcb_t *pcbdef = (ti99_pcb_t *)downcast<legacy_device_base *>(cart->pcb)->token();;
3101         (*pcbdef->write8)(cart->pcb, offset, data);
3102      }
3103   }
3104}
3105
3106/*****************************************************************************
3107   GramKracker support
3108   The 80 KiB of the GK are allocated as follows
3109   00000 - 01fff: GRAM 0
3110   02000 - 03fff: GRAM 1  (alternatively, the loader GROM appears here)
3111   04000 - 05fff: GRAM 2
3112   06000 - 0ffff: GRAM 3-7 (alternatively, the guest GROMs appear here)
3113   10000 - 11fff: RAM 1
3114   12000 - 13fff: RAM 2
3115******************************************************************************/
3116/*
3117    Reads from the GRAM space of the GRAM Kracker.
3118*/
3119static int cartridge_gram_kracker_readg(running_device *cartsys)
3120{
3121   // gk_slot is the slot where the GK module is plugged in
3122   // gk_guest_slot is the slot where the cartridge is plugged in
3123   UINT8 value;
3124   cartridge_t *gkcartridge, *gkguestcart;
3125   ti99_multicart_state *cartslots = (ti99_multicart_state *)downcast<legacy_device_base *>(cartsys)->token();
3126
3127   // This is only called when there is really a GK module
3128   gkcartridge = &cartslots->cartridge[cartslots->gk_slot];
3129
3130   // Buffered value
3131   value = (UINT8)cartslots->grom_buffer;
3132
3133   if (cartslots->grom_address >= 0x6000)
3134   {
3135      // When a cartridge is installed, it overrides the GK contents
3136      // but only if it has GROMs
3137      // So we first get the values and then have them replaced if applicable
3138      if (get_gk_switch(1)==GK_NORMAL)
3139      {
3140         // Read ahead
3141         cartslots->grom_buffer = ((UINT8 *)gkcartridge->ram_ptr)[cartslots->grom_address];
3142      }
3143      else
3144      {
3145         // GK is turned off
3146         cartslots->grom_buffer = 0;
3147      }
3148      if (cartslots->gk_guest_slot != -1)
3149      {
3150         gkguestcart = &cartslots->cartridge[cartslots->gk_guest_slot];
3151         // So if the cartridge has GROM, have it overwrite the value
3152         // if it is in its range
3153         if ((gkguestcart->grom_ptr != NULL)
3154            && (cartslots->grom_address < (0x6000 + gkguestcart->grom_size)))
3155            cartslots->grom_buffer = gkguestcart->grom_ptr[cartslots->grom_address-0x6000];
3156      }
3157   }
3158   else
3159   {
3160      if ((cartslots->grom_address >= 0x2000) && (cartslots->grom_address < 0x4000))
3161      {
3162         // Loader area
3163         if (get_gk_switch(5)==GK_LDOFF)
3164         {
3165            // Loader off
3166            cartslots->loader_on = FALSE;
3167            cartslots->grom_buffer = ((UINT8 *)gkcartridge->ram_ptr)[cartslots->grom_address];
3168         }
3169         else
3170         {
3171            // Loader on
3172            if (!cartslots->loader_on)
3173            {
3174               // Hack for GRAM Kracker: The device tells the user to
3175               // turn on the loader, but it sets the GROM address before!
3176               // So we have read the value from the earlier setting.
3177               value = gkcartridge->grom_ptr[cartslots->grom_address-0x2001];
3178               cartslots->loader_on = TRUE;
3179            }
3180            cartslots->grom_buffer = gkcartridge->grom_ptr[cartslots->grom_address-0x2000];
3181         }
3182      }
3183      else
3184      {
3185         // GRAM 0 or GRAM 2. Note that we deliver a value, but the console may
3186         // ignore it according to the switch setting.
3187         cartslots->grom_buffer = ((UINT8 *)gkcartridge->ram_ptr)[cartslots->grom_address];
3188      }
3189   }
3190
3191   // The program counter wraps at each GROM chip size (8K),
3192   // so 0x5fff + 1 = 0x4000.
3193   // The address must be increased even if there is no cartridge slot
3194   cartslots->grom_address = ((cartslots->grom_address + 1) & 0x1FFF) | (cartslots->grom_address & 0xE000);
3195
3196   /* Reset the read and write address flipflops. */
3197   cartslots->raddr_LSB = cartslots->waddr_LSB = FALSE;
3198
3199   return value;
3200}
3201
3202/*
3203    Writes to the GRAM space of the GRAM Kracker.
3204   FIXME: The real GK seems to not wrap at the GROM boundary (at least for
3205   writing). Also check for reading.
3206*/
3207static void cartridge_gram_kracker_writeg(running_device *cartsys, UINT8 data)
3208{
3209   // gk_slot is the slot where the GK module is plugged in
3210   // gk_guest_slot is the slot where the cartridge is plugged in
3211   cartridge_t *gkcartridge;
3212   ti99_multicart_state *cartslots = (ti99_multicart_state *)downcast<legacy_device_base *>(cartsys)->token();
3213
3214   // This is only called when there is really a GK module
3215   gkcartridge = &cartslots->cartridge[cartslots->gk_slot];
3216
3217   // We need to rewind by 1 because the read address has already advanced.
3218   UINT16 write_addr = ((cartslots->grom_address + 0x1fff) & 0x1FFF) | (cartslots->grom_address & 0xE000);
3219
3220   if (get_gk_switch(4)!=GK_WP)
3221   {
3222      // Write protection off
3223      if (((write_addr < 0x2000)
3224            && (get_gk_switch(2)==GK_GRAM0))
3225         || ((write_addr >= 0x2000) && (write_addr < 0x4000)
3226            && (get_gk_switch(3)==GK_GRAM12)
3227            && (get_gk_switch(5)==GK_LDOFF))
3228         || ((write_addr >= 0x4000) && (write_addr < 0x6000)
3229            && (get_gk_switch(3)==GK_GRAM12))
3230         || ((write_addr >= 0x6000) && (cartslots->gk_guest_slot==-1)
3231            && (get_gk_switch(1)==GK_NORMAL)))
3232      {
3233         ((UINT8 *)gkcartridge->ram_ptr)[write_addr] = data;
3234      }
3235      // There is no GRAM in cartridges
3236   }
3237}
3238
3239/*
3240    Reads from the RAM space of the GRAM Kracker.
3241*/
3242static READ16_DEVICE_HANDLER( ti99_cart_r_gk )
3243{
3244   // gk_slot is the slot where the GK module is plugged in
3245   // gk_guest_slot is the slot where the cartridge is plugged in
3246   cartridge_t *gkcartridge, *gkguestcart;
3247   ti99_multicart_state *cartslots = (ti99_multicart_state *)downcast<legacy_device_base *>(device)->token();
3248
3249   gkcartridge = &cartslots->cartridge[cartslots->gk_slot];
3250
3251   if (cartslots->gk_guest_slot != -1)
3252   {
3253      gkguestcart = &cartslots->cartridge[cartslots->gk_guest_slot];
3254      // Legacy mode is not supported with the GK
3255      if (in_legacy_mode(device))
3256      {
3257         return 0;
3258      }
3259      //      printf("accessing cartridge in slot %d\n", slot);
3260      ti99_pcb_t *pcbdef = (ti99_pcb_t *)downcast<legacy_device_base *>(gkguestcart->pcb)->token();
3261      //      printf("address=%lx, offset=%lx\n", pcbdef, offset);
3262      return (*pcbdef->read)(gkguestcart->pcb, offset, mem_mask);
3263   }
3264   else
3265   {
3266      if (get_gk_switch(1)==GK_OFF)
3267         return 0;
3268
3269      if (get_gk_switch(4)==GK_BANK1)
3270         return ((UINT16 *)gkcartridge->ram_ptr)[offset+0x8000];
3271      else
3272      {
3273         if (get_gk_switch(4)==GK_BANK2)
3274            return ((UINT16 *)gkcartridge->ram_ptr)[offset+0x9000];
3275         else
3276         {
3277            // Write protection on
3278            if (gkcartridge->ram_page==0)
3279            {
3280               return ((UINT16 *)gkcartridge->ram_ptr)[offset+0x8000];
3281            }
3282            else
3283            {
3284               return ((UINT16 *)gkcartridge->ram_ptr)[offset+0x9000];
3285            }
3286         }
3287      }
3288   }
3289}
3290
3291/*
3292    Writes to the RAM space of the GRAM Kracker.
3293*/
3294static WRITE16_DEVICE_HANDLER( ti99_cart_w_gk )
3295{
3296   // gk_slot is the slot where the GK module is plugged in
3297   // gk_guest_slot is the slot where the cartridge is plugged in
3298   cartridge_t *gkcartridge, *gkguestcart;
3299   ti99_multicart_state *cartslots = (ti99_multicart_state *)downcast<legacy_device_base *>(device)->token();
3300
3301   gkcartridge = &cartslots->cartridge[cartslots->gk_slot];
3302
3303   if (cartslots->gk_guest_slot != -1)
3304   {
3305      gkguestcart = &cartslots->cartridge[cartslots->gk_guest_slot];
3306      // Legacy mode is not supported with the GK
3307      if (in_legacy_mode(device))
3308      {
3309         return;
3310      }
3311
3312      ti99_pcb_t *pcbdef = (ti99_pcb_t *)downcast<legacy_device_base *>(gkguestcart->pcb)->token();
3313         (*pcbdef->write)(gkguestcart->pcb, offset, data, mem_mask);
3314   }
3315   else
3316   {
3317      if (get_gk_switch(1)==GK_OFF)
3318         return;
3319
3320      if (get_gk_switch(4)==GK_BANK1)
3321      {
3322         UINT16 *pos = ((UINT16 *)gkcartridge->ram_ptr) + offset + 0x8000;
3323         COMBINE_DATA(pos);
3324      }
3325      else
3326      {
3327         if (get_gk_switch(4)==GK_BANK2)
3328         {
3329            UINT16 *pos = ((UINT16 *)gkcartridge->ram_ptr) + offset + 0x9000;
3330            COMBINE_DATA(pos);
3331         }
3332         else
3333         {
3334            // Write protection on
3335            // This is handled like in Extended Basic
3336            gkcartridge->ram_page = offset & 1;
3337         }
3338      }
3339   }
3340}
3341
3342/*
3343    Read cartridge mapper CRU interface (Guest in GRAM Kracker)
3344*/
3345static READ8_DEVICE_HANDLER( ti99_cart_crur_gk )
3346{
3347   ti99_multicart_state *cartslots = (ti99_multicart_state *)downcast<legacy_device_base *>(device)->token();
3348   cartridge_t *gkguestcart;
3349
3350   if (cartslots->gk_guest_slot != -1)
3351   {
3352      gkguestcart = &cartslots->cartridge[cartslots->gk_guest_slot];
3353      ti99_pcb_t *pcbdef = (ti99_pcb_t *)downcast<legacy_device_base *>(gkguestcart->pcb)->token();
3354      if (pcbdef->cruread != NULL)
3355         return (*pcbdef->cruread)(gkguestcart->pcb, offset);
3356   }
3357   return 0;
3358}
3359
3360/*
3361    Write cartridge mapper CRU interface (Guest in GRAM Kracker)
3362*/
3363static WRITE8_DEVICE_HANDLER( ti99_cart_cruw_gk )
3364{
3365   ti99_multicart_state *cartslots = (ti99_multicart_state *)downcast<legacy_device_base *>(device)->token();
3366   cartridge_t *gkguestcart;
3367
3368   if (cartslots->gk_guest_slot != -1)
3369   {
3370      gkguestcart = &cartslots->cartridge[cartslots->gk_guest_slot];
3371      ti99_pcb_t *pcbdef = (ti99_pcb_t *)downcast<legacy_device_base *>(gkguestcart->pcb)->token();
3372      if (pcbdef->cruwrite != NULL)
3373         (*pcbdef->cruwrite)(gkguestcart->pcb, offset, data);
3374   }
3375}
3376
3377/*
3378    TI-99/8 support
3379*/
3380static READ8_DEVICE_HANDLER( ti99_cart_r_gk8 )
3381{
3382   // gk_slot is the slot where the GK module is plugged in
3383   // gk_guest_slot is the slot where the cartridge is plugged in
3384   cartridge_t *gkcartridge, *gkguestcart;
3385   ti99_multicart_state *cartslots = (ti99_multicart_state *)downcast<legacy_device_base *>(device)->token();
3386
3387   gkcartridge = &cartslots->cartridge[cartslots->gk_slot];
3388
3389   if (cartslots->gk_guest_slot != -1)
3390   {
3391      gkguestcart = &cartslots->cartridge[cartslots->gk_guest_slot];
3392      // Legacy mode is not supported with the GK
3393      if (in_legacy_mode(device))
3394      {
3395         return 0;
3396      }
3397      //      printf("accessing cartridge in slot %d\n", slot);
3398      ti99_pcb_t *pcbdef = (ti99_pcb_t *)downcast<legacy_device_base *>(gkguestcart->pcb)->token();
3399      //      printf("address=%lx, offset=%lx\n", pcbdef, offset);
3400      return (*pcbdef->read8)(gkguestcart->pcb, offset);
3401   }
3402   else
3403   {
3404      if (get_gk_switch(1)==GK_OFF)
3405         return 0;
3406
3407      if (get_gk_switch(4)==GK_BANK1)
3408         return ((UINT8 *)gkcartridge->ram_ptr)[offset+0x10000];
3409      else
3410      {
3411         if (get_gk_switch(4)==GK_BANK2)
3412            return ((UINT8 *)gkcartridge->ram_ptr)[offset+0x12000];
3413         else
3414         {
3415            // Write protection on
3416            if (gkcartridge->ram_page==0)
3417               return ((UINT8 *)gkcartridge->ram_ptr)[offset+0x10000];
3418            else
3419               return ((UINT8 *)gkcartridge->ram_ptr)[offset+0x12000];
3420         }
3421      }
3422   }
3423}
3424
3425static WRITE8_DEVICE_HANDLER( ti99_cart_w_gk8 )
3426{
3427   // gk_slot is the slot where the GK module is plugged in
3428   // gk_guest_slot is the slot where the cartridge is plugged in
3429   cartridge_t *gkcartridge, *gkguestcart;
3430   ti99_multicart_state *cartslots = (ti99_multicart_state *)downcast<legacy_device_base *>(device)->token();
3431
3432   gkcartridge = &cartslots->cartridge[cartslots->gk_slot];
3433
3434   if (cartslots->gk_guest_slot != -1)
3435   {
3436      gkguestcart = &cartslots->cartridge[cartslots->gk_guest_slot];
3437      // Legacy mode is not supported with the GK
3438      if (in_legacy_mode(device))
3439      {
3440         return;
3441      }
3442
3443      ti99_pcb_t *pcbdef = (ti99_pcb_t *)downcast<legacy_device_base *>(gkguestcart->pcb)->token();
3444         (*pcbdef->write8)(gkguestcart->pcb, offset, data);
3445   }
3446   else
3447   {
3448      if (get_gk_switch(1)==GK_OFF)
3449         return;
3450
3451      if (get_gk_switch(4)==GK_BANK1)
3452         ((UINT8 *)gkcartridge->ram_ptr)[offset+0x10000] = data;
3453      else
3454      {
3455         if (get_gk_switch(4)==GK_BANK2)
3456            ((UINT8 *)gkcartridge->ram_ptr)[offset+0x12000] = data;
3457         else
3458         {
3459            // Write protection on
3460            // This is handled like in Extended Basic
3461            gkcartridge->ram_page = (offset>>1) & 1;
3462         }
3463      }
3464   }
3465}
3466
3467/*****************************************************************************/
3468#define TI99_CARTRIDGE_SLOT(p)  MDRV_CARTSLOT_ADD(p) \
3469   MDRV_CARTSLOT_EXTENSION_LIST("rpk,bin") \
3470   MDRV_CARTSLOT_PCBTYPE(0, "none", TI99_CARTRIDGE_PCB_NONE) \
3471   MDRV_CARTSLOT_PCBTYPE(1, "standard", TI99_CARTRIDGE_PCB_STD) \
3472   MDRV_CARTSLOT_PCBTYPE(2, "paged", TI99_CARTRIDGE_PCB_PAGED) \
3473   MDRV_CARTSLOT_PCBTYPE(3, "minimem", TI99_CARTRIDGE_PCB_MINIMEM) \
3474   MDRV_CARTSLOT_PCBTYPE(4, "super", TI99_CARTRIDGE_PCB_SUPER) \
3475   MDRV_CARTSLOT_PCBTYPE(5, "mbx", TI99_CARTRIDGE_PCB_MBX) \
3476   MDRV_CARTSLOT_PCBTYPE(6, "paged379i", TI99_CARTRIDGE_PCB_PAGED379I) \
3477   MDRV_CARTSLOT_PCBTYPE(7, "pagedcru", TI99_CARTRIDGE_PCB_PAGEDCRU) \
3478   MDRV_CARTSLOT_PCBTYPE(8, "gramkracker", TI99_CARTRIDGE_PCB_GRAMKRACKER) \
3479   MDRV_CARTSLOT_START(ti99_cartridge) \
3480   MDRV_CARTSLOT_LOAD(ti99_cartridge) \
3481   MDRV_CARTSLOT_UNLOAD(ti99_cartridge)
3482
3483static MACHINE_CONFIG_FRAGMENT(ti99_multicart)
3484   TI99_CARTRIDGE_SLOT("cartridge1")
3485   TI99_CARTRIDGE_SLOT("cartridge2")
3486   TI99_CARTRIDGE_SLOT("cartridge3")
3487   TI99_CARTRIDGE_SLOT("cartridge4")
3488MACHINE_CONFIG_END
3489
3490static const char DEVTEMPLATE_SOURCE[] = __FILE__;
3491
3492#define DEVTEMPLATE_ID(p,s)             p##ti99_multicart##s
3493#define DEVTEMPLATE_FEATURES            DT_HAS_START | DT_HAS_STOP | DT_HAS_RESET | DT_HAS_MACHINE_CONFIG
3494#define DEVTEMPLATE_NAME                "TI99 Multi-Cartridge Extender"
3495#define DEVTEMPLATE_FAMILY              "Multi-cartridge system"
3496#include "devtempl.h"
3497
3498DEFINE_LEGACY_CART_SLOT_DEVICE(TI99_MULTICART, ti99_multicart);
src/mess/devices/ti99cart.h
r9500r9501
1/*********************************************************************
2
3    ti99cart.h
4
5    TI99 family cartridge management
6
7*********************************************************************/
8
9#ifndef __TI99CART_H__
10#define __TI99CART_H__
11
12#include "cartslot.h"
13
14DECLARE_LEGACY_CART_SLOT_DEVICE(TI99_MULTICART, ti99_multicart);
15
16/* We set the number of slots to 8, although we may have up to 16. From a
17   logical point of view we could have 256, but the operating system only checks
18   the first 16 banks. */
19#define NUMBER_OF_CARTRIDGE_SLOTS 8
20
21READ8_DEVICE_HANDLER(ti99_cartridge_grom_r);
22WRITE8_DEVICE_HANDLER(ti99_cartridge_grom_w);
23
24READ16_DEVICE_HANDLER(ti99_multicart_r);
25WRITE16_DEVICE_HANDLER(ti99_multicart_w);
26
27/* Support for TI-99/8 */
28READ8_DEVICE_HANDLER(ti99_multicart8_r);
29WRITE8_DEVICE_HANDLER(ti99_multicart8_w);
30
31/* CRU handlers for SuperSpace and Pagedcru cartridge */
32READ8_DEVICE_HANDLER( ti99_multicart_cru_r );
33WRITE8_DEVICE_HANDLER( ti99_multicart_cru_w );
34
35#define MDRV_TI99_CARTRIDGE_ADD(_tag) \
36   MDRV_DEVICE_ADD(_tag, TI99_MULTICART, 0)
37
38#define MDRV_TI99_GROMPORT_ADD(_tag, _databus, _crubus, _ready) \
39   MDRV_DEVICE_ADD(_tag, TI99_MULTICART, 0)
40
41#endif /* __TI99CART_H__ */
src/mess/devices/ti99_peb.c
r9500r9501
1/*
2    Peripheral expansion bus support.
3
4    The ti-99/4, ti-99/4a, ti computer 99/8, myarc geneve, and snug sgcpu
5    99/4p systems all feature a bus connector that enables the connection of
6    extension cards.  (Although the hexbus is the preferred bus to add
7    additional peripherals to a ti-99/8, ti-99/8 is believed to be compatible
8    with the older PEB system.)  In the case of the TI consoles, this bus
9    connector is located on the right side of the console.
10
11    While a few extension cards connect to the side bus connector of the
12    ti-99/4(a) console directly, most extension cards were designed to be
13    inserted in a PEB instead.  The PEB (Peripheral Expansion Box) is a big box
14    with an alimentation, a few bus drivers, and several card slots, that
15    connects to the ti-99/4(a) side port.  The reason for using a PEB is that
16    daisy-chaining many modules caused the system to be unreliable due to the
17    noise produced by the successive contacts.  (As a matter of fact, TI
18    initially released most of its extension cards as side bus units, but when
19    the design proved to be unreliable, the PEB was introduced.  The TI speech
20    synthesizer was the only TI extension that remained on the side bus after
21    the introduction of the PEB, probably because TI wanted the speech
22    synthesizer to be a cheap extension, and the PEB was not cheap.)
23
24    The third-party myarc geneve and snug sgcpu computers are actually cards
25    to be inserted into a PEB: they have a PC keyboard connector, and replace
26    the original ti-99 console completely.
27
28    Each expansion card is assigned to one of 16 CRU address ranges.
29    I appended the names of known TI peripherals that use each port (I appended
30    '???' when I don't know what the peripheral is :-) ).
31    * 0x1000-0x10FE "For test equipment use on production line"
32    * 0x1100-0x11FE disk controller
33    * 0x1200-0x12FE modem???
34    * 0x1300-0x13FE RS232 1&2, PIO 1
35    * 0x1400-0x14FE unassigned
36    * 0x1500-0x15FE RS232 3&4, PIO 2
37    * 0x1600-0x16FE unassigned
38    * 0x1700-0x17FE hex-bus (prototypes)
39    * 0x1800-0x18FE thermal printer (early peripheral)
40    * 0x1900-0x19FE EPROM programmer??? (Mezzanine board in July 1981's TI99/7
41        prototype)
42    * 0x1A00-0x1AFE unassigned
43    * 0x1B00-0x1BFE TI GPL debugger card
44    * 0x1C00-0x1CFE Video Controller Card (Possibly the weirdest device.  This
45        card is connected to the video output of the computer, to a VCR, and a
46        video monitor.  It can control the VCR, connect the display to either
47        VCR output or computer video output, and it can read or save binary
48        data to video tape.  I think it can act as a genlock interface (i.e.
49        TMS9918 transparent background shows the video signal), too, but I am
50        not sure about this.)
51    * 0x1D00-0x1DFE IEEE 488 Controller Card ('intelligent' parallel bus,
52        schematics on ftp.whtech.com)
53    * 0x1E00-0x1EFE unassigned
54    * 0x1F00-0x1FFE P-code card (part of a complete development system)
55
56    The ti-99/8 implements 16 extra ports:
57    * 0x2000-0x26ff and 0x2800-0x2fff: reserved for future expansion?
58    * 0x2700-0x27ff: internal DSR
59
60    The snug sgcpu 99/4p implements 12 extra ports:
61    * 0x0400-0x0eff: free
62    * 0x0f00-0x0fff: internal DSR
63
64    Known mappings for 3rd party cards:
65    * Horizon RAMdisk: any ports from 0 to 7 (port 0 is most common).
66    * Myarc 128k/512k (RAM and DSR ROM): port 0 (0x1000-0x11FE)
67    * Corcomp 512k (RAM and DSR ROM): port unknown
68    * Super AMS 128k/512k: port 14 (0x1E00-0x1EFE)
69    * Foundation 128k/512k: port 14 (0x1E00-0x1EFE)
70    * Gram Karte: any port (0-15)
71    * EVPC (video card): 0x1400-0x14FE
72    * HSGPL (GROM replacement): 0x1B00-0x1BFE
73
74    Of course, these devices additionally need some support routines, and
75    possibly memory-mapped I/O registers.  To do so, memory range 0x4000-5FFF
76    is shared by all cards.  The system enables each card as needed by writing
77    a 1 to the first CRU bit: when this happens the card can safely enable its
78    ROM, RAM, memory-mapped registers, etc.  Provided the ROM uses the proper
79    ROM header, the system will recognize and call peripheral I/O functions,
80    interrupt service routines, and startup routines.  (All these routines are
81    generally called DSR = Device Service Routine.)
82
83    Also, the cards can trigger level-1 ("INTA") interrupts.  A LOAD interrupt
84    is present on the side port of the ti-99/4(a), too, but it was never used
85    by TI, AFAIK.  Also, an interrupt line called "INTB" is found on several
86    cards built by TI, but it is not connected: I am quite unsure whether it
87    was intended to be connected to the LOAD line, to the INT2 line of TMS9985,
88    or it was only to be used with the ti-99/4(a) development system running on
89    a TI990/10.  This is not the only unused feature: cards built by TI support
90    sensing of an interrupt status register and 19-bit addressing, even though
91    ti-99/4(A) does not take advantage of these features.  TI documentation
92    tells that some of these features are "defined by the Personal Computer PCC
93    at Texas Instrument", which is not very explicit (What on earth does "PCC"
94    stand for?).  Maybe it refers to the ti-99/4(a) development system running
95    on a TI990/10, or to the ti-99/7 and ti-99/8 prototypes.
96
97    Note that I use 8-bit RAM handlers.  Obviously, using 16-bit handlers would
98    be equivalent and faster on a ti-99/4(a), but we need to interface the
99    extension cards not only to the ti-99/4(a), but to the geneve and ti-99/8
100    emulators as well.
101
102    June 2010: Reimplemented using device structure (MZ) (obsoletes 99_peb.c)
103*/
104
105#include "emu.h"
106#include "ti99_peb.h"
107
108enum width_t {
109   width_8bit = 0,
110   width_16bit
111};
112/* expansion card structure for the snug sgcpu 99/4p system, which supports
113dynamical 16-bit accesses (TI did not design this!) */
114typedef struct ti99_4p_peb_card_handlers_t
115{
116   cru_read_handler cru_read;      /* card CRU read handler */
117   cru_write_handler cru_write;   /* card CRU handler */
118
119   width_t width;
120   union
121   {
122      struct
123      {
124         read8_space_func mem_read;      /* card mem read handler (8 bits) */
125         write8_space_func mem_write;   /* card mem write handler (8 bits) */
126      } width_8bit;
127      struct
128      {
129         read16_space_func mem_read;   /* card mem read handler (16 bits) */
130         write16_space_func mem_write;   /* card mem write handler (16 bits) */
131      } width_16bit;
132   } w;
133} ti99_4p_peb_card_handlers_t;
134
135typedef struct _ti99_peb_state
136{
137   /* TRUE if we are using the snug sgcpu 99/4p 16-bit extensions */
138   int has_16bit_peb;
139
140   /* handlers for each of 28 slots */
141   ti99_4p_peb_card_handlers_t ti99_4p_expansion_ports[28];
142
143   /* handlers for each of 16 slots + 16 extra slots for ti-99/8 */
144   ti99_peb_card_handlers_t expansion_ports[16+16];
145
146   /* index of the currently active card (-1 if none) */
147   int active_card;
148
149   /* index of the currently active card, overridden by the mapper */
150   int active_card_tmp;
151
152   /* Mapper override. */
153   int mapper_override;
154
155   // ila: inta status register (not actually used on ti-99/4(a), but nevertheless
156   // present)
157   int ila;
158
159   // ilb: intb status register (completely pointless on ti-99/4(a), as neither
160   // INTB nor SENILB are connected; OTOH, INTB can trigger interrupts on a Geneve,
161   // and snug sgcpu 99/4p can sense ILB)
162   int ilb;
163
164   /* only used by the snug sgcpu 99/4p */
165   int senila, senilb;
166
167   /* hack to simulate TMS9900 byte write */
168   int tmp_buffer;
169
170   /* inta/intb handlers */
171   void (*inta_callback)(running_machine *machine, int state);
172   void (*intb_callback)(running_machine *machine, int state);
173
174   address_space *space;
175
176} ti99_peb_state;
177
178INLINE ti99_peb_state *get_safe_token(running_device *device)
179{
180   assert(device != NULL);
181   assert(downcast<legacy_device_base *>(device)->token() != NULL);
182   return (ti99_peb_state *)downcast<legacy_device_base *>(device)->token();
183}
184
185INLINE const ti99_peb_config *get_config(running_device *device)
186{
187   assert(device != NULL);
188   assert(device->type() == PBOX);
189   return (const ti99_peb_config *) downcast<const legacy_device_config_base &>(device->baseconfig()).inline_config();
190}
191
192/*
193    Sets the handlers for one expansion port (normal 8-bit card)
194
195    cru_base: CRU base address (any of 0x1000, 0x1100, 0x1200, ..., 0x1F00)
196        (snug sgcpu 99/4p accepts 0x0400, ..., 0x1F00, ti-99/8 accepts 0x1000,
197        ..., 0x2F00)
198    handler: handler structure for the given card
199*/
200void ti99_peb_set_card_handlers(running_device *box, int cru_base, const ti99_peb_card_handlers_t *handler)
201{
202   int port;
203   ti99_peb_state *peb = get_safe_token(box);
204
205   if (cru_base & 0xff)
206      return;
207
208   if (peb->has_16bit_peb)
209   {
210      port = (cru_base - 0x0400) >> 8;
211
212      if ((port>=0) && (port<28))
213      {
214         peb->ti99_4p_expansion_ports[port].cru_read = handler->cru_read;
215         peb->ti99_4p_expansion_ports[port].cru_write = handler->cru_write;
216         peb->ti99_4p_expansion_ports[port].width = width_8bit;
217         peb->ti99_4p_expansion_ports[port].w.width_8bit.mem_read = handler->mem_read;
218         peb->ti99_4p_expansion_ports[port].w.width_8bit.mem_write = handler->mem_write;
219      }
220   }
221   else
222   {
223      port = (cru_base - 0x1000) >> 8;
224
225      if ((port>=0) && (port</*16*/32))
226      {
227         peb->expansion_ports[port] = *handler;
228      }
229   }
230}
231
232/*
233    Sets the handlers for one expansion port (special 16-bit card for snug
234    sgcpu 99/4p)
235
236    cru_base: CRU base address (any of 0x1000, 0x1100, 0x1200, ..., 0x1F00)
237        (snug sgcpu 99/4p accepts 0x0400, ..., 0x1F00, ti-99/8 accepts 0x1000,
238        ..., 0x2F00)
239    handler: handler structure for the given card
240*/
241void ti99_peb_set_16bit_card_handlers(running_device *box, int cru_base, const ti99_peb_16bit_card_handlers_t *handler)
242{
243   int port;
244   ti99_peb_state *peb = get_safe_token(box);
245
246   if (cru_base & 0xff)
247      return;
248
249   if (peb->has_16bit_peb)
250   {
251      port = (cru_base - 0x0400) >> 8;
252
253      if ((port>=0) && (port<28))
254      {
255         peb->ti99_4p_expansion_ports[port].cru_read = handler->cru_read;
256         peb->ti99_4p_expansion_ports[port].cru_write = handler->cru_write;
257         peb->ti99_4p_expansion_ports[port].width = width_16bit;
258         peb->ti99_4p_expansion_ports[port].w.width_16bit.mem_read = handler->mem_read;
259         peb->ti99_4p_expansion_ports[port].w.width_16bit.mem_write = handler->mem_write;
260      }
261   }
262}
263
264/*
265    Update ila status register and assert or clear INTA interrupt line
266    accordingly.
267
268    bit: bit number ([0,7] for original INTA register, [8,15] are extra
269        "virtual" bits for devices that assert the INTA line without setting a
270        bit of the ILA register)
271    state: 1 to assert bit, 0 to clear
272*/
273void ti99_peb_set_ila_bit(running_device *box, int bit, int state)
274{
275   ti99_peb_state *peb = get_safe_token(box);
276   if (state)
277   {
278      peb->ila |= 1 << bit;
279      if (peb->inta_callback)
280         (*peb->inta_callback)(box->machine, 1);
281   }
282   else
283   {
284      peb->ila &= ~(1 << bit);
285      if ((!peb->ila) && peb->inta_callback)
286         (*peb->inta_callback)(box->machine, 0);
287   }
288}
289
290/*
291    Update ilb status register and assert or clear INTB interrupt line
292    accordingly.
293
294    bit: bit number ([0,7] for original INTAB register, [8,15] are extra
295        "virtual" bits for devices that assert the INTB line without setting a
296        bit of the ILB register)
297    state: 1 to assert bit, 0 to clear
298*/
299void ti99_peb_set_ilb_bit(running_device *box, int bit, int state)
300{
301   ti99_peb_state *peb = get_safe_token(box);
302
303   if (state)
304   {
305      peb->ilb |= 1 << bit;
306      if (peb->intb_callback)
307         (*peb->intb_callback)(box->machine, 1);
308   }
309   else
310   {
311      peb->ilb &= ~(1 << bit);
312      if ((!peb->ilb) && peb->intb_callback)
313         (*peb->intb_callback)(box->machine, 0);
314   }
315}
316
317
318/*
319    Read CRU in range >1000->1ffe (>800->fff) (ti-99/4(a))
320*/
321READ8_DEVICE_HANDLER( ti99_4x_peb_cru_r )
322{
323   int port;
324   cru_read_handler handler;
325   int reply;
326   ti99_peb_state *peb = get_safe_token(device);
327
328   port = (offset & 0x00f0) >> 4;
329   handler = peb->expansion_ports[port].cru_read;
330
331   reply = (handler) ? (*handler)(device->machine, offset & 0xf) : 0;
332
333   return reply;
334}
335
336/*
337    Write CRU in range >1000->1ffe (>800->fff) (ti-99/4(a))
338*/
339WRITE8_DEVICE_HANDLER( ti99_4x_peb_cru_w )
340{
341   int port;
342   cru_write_handler handler;
343   ti99_peb_state *peb = get_safe_token(device);
344
345   port = (offset & 0x0780) >> 7;
346   handler = peb->expansion_ports[port].cru_write;
347
348   if (handler)
349      (*handler)(device->machine, offset & 0x7f, data);
350
351   /* expansion card enable? */
352   if ((offset & 0x7f) == 0)
353   {
354      if (data & 1)
355      {
356         /* enable */
357         peb->active_card = port;
358      }
359      else
360      {
361         if (port == peb->active_card)   /* geez... who cares? */
362         {
363            peb->active_card = -1;         /* no port selected */
364         }
365      }
366   }
367}
368
369/*
370    Read mem in range >4000->5ffe (ti-99/4(a))
371*/
372READ16_DEVICE_HANDLER( ti99_4x_peb_r )
373{
374   int reply = 0;
375   read8_space_func handler;
376   ti99_peb_state *peb = get_safe_token(device);
377
378   cpu_adjust_icount(device->machine->firstcpu,-4);
379
380   if (peb->active_card != -1)
381   {
382      handler = peb->expansion_ports[peb->active_card].mem_read;
383      if (handler)
384      {
385         reply = (*handler)(peb->space, (offset << 1) + 1);
386         reply |= ((unsigned) (*handler)(peb->space, offset << 1)) << 8;
387      }
388   }
389//  printf("[%04x:%04x] = %04x\n", (active_card<<8)+0x1000, (offset<<1)+0x4000, reply);
390
391   return peb->tmp_buffer = reply;
392}
393
394/*
395    Write mem in range >4000->5ffe (ti-99/4(a))
396*/
397WRITE16_DEVICE_HANDLER( ti99_4x_peb_w )
398{
399   write8_space_func handler;
400   ti99_peb_state *peb = get_safe_token(device);
401
402   cpu_adjust_icount(device->machine->firstcpu,-4);
403
404   /* simulate byte write */
405   data = (peb->tmp_buffer & ~mem_mask) | (data & mem_mask);
406
407   if (peb->active_card != -1)
408   {
409      handler = peb->expansion_ports[peb->active_card].mem_write;
410      if (handler)
411      {
412         (*handler)(peb->space, (offset << 1) + 1, data & 0xff);
413         (*handler)(peb->space, offset << 1, (data >> 8) & 0xff);
414      }
415   }
416}
417
418
419/*
420    Read CRU in range >1000->1ffe (>800->fff) (Geneve)
421*/
422READ8_DEVICE_HANDLER( geneve_peb_cru_r )
423{
424   int port;
425   cru_read_handler handler;
426   int reply;
427   ti99_peb_state *peb = get_safe_token(device);
428
429   port = (offset & 0x00f0) >> 4;
430   handler = peb->expansion_ports[port].cru_read;
431
432   reply = (handler) ? (*handler)(device->machine, offset & 0xf) : 0;
433
434   return reply;
435}
436
437/*
438    Write CRU in range >1000->1ffe (>800->fff) (Geneve)
439*/
440WRITE8_DEVICE_HANDLER( geneve_peb_cru_w )
441{
442   int port;
443   cru_write_handler handler;
444   ti99_peb_state *peb = get_safe_token(device);
445
446   port = (offset & 0x0780) >> 7;
447   handler = peb->expansion_ports[port].cru_write;
448
449   if (handler)
450      (*handler)(device->machine, offset & 0x7f, data);
451
452   /* expansion card enable? */
453   if ((offset & 0x7f) == 0)
454   {
455      if (data & 1)
456      {
457         /* enable */
458         peb->active_card = port;
459      }
460      else
461      {
462         if (port == peb->active_card)   /* geez... who cares? */
463         {
464            peb->active_card = -1;         /* no port selected */
465         }
466      }
467   }
468}
469
470/*
471    Read mem in range >4000->5fff (Geneve)
472*/
473READ8_DEVICE_HANDLER( geneve_peb_r )
474{
475   int reply = 0;
476   read8_space_func handler;
477   ti99_peb_state *peb = get_safe_token(device);
478
479   cpu_adjust_icount(device->machine->firstcpu,-8);
480
481   if (peb->active_card != -1)
482   {
483      handler = peb->expansion_ports[peb->active_card].mem_read;
484      if (handler)
485         reply = (*handler)(peb->space, offset);
486   }
487
488   return reply;
489}
490
491/*
492    Write mem in range >4000->5fff (Geneve)
493*/
494WRITE8_DEVICE_HANDLER( geneve_peb_w )
495{
496   write8_space_func handler;
497   ti99_peb_state *peb = get_safe_token(device);
498
499   cpu_adjust_icount(device->machine->firstcpu,-8);
500
501   if (peb->active_card != -1)
502   {
503      handler = peb->expansion_ports[peb->active_card].mem_write;
504      if (handler)
505         (*handler)(peb->space, offset, data);
506   }
507}
508
509/*
510    Read CRU in range >1000->2ffe (>0800->17ff) (ti-99/8)
511*/
512READ8_DEVICE_HANDLER( ti99_8_peb_cru_r )
513{
514   int port;
515   cru_read_handler handler;
516   int reply;
517   ti99_peb_state *peb = get_safe_token(device);
518
519   port = (offset & 0x01f0) >> 4;
520   handler = peb->expansion_ports[port].cru_read;
521
522   reply = (handler) ? (*handler)(device->machine, offset & 0xf) : 0;
523
524   return reply;
525}
526
527/*
528    Write CRU in range >1000->2ffe (>0800->17ff) (ti-99/8)
529*/
530WRITE8_DEVICE_HANDLER( ti99_8_peb_cru_w )
531{
532   int port;
533   cru_write_handler handler;
534   ti99_peb_state *peb = get_safe_token(device);
535
536   port = (offset & 0x0f80) >> 7;
537   handler = peb->expansion_ports[port].cru_write;
538
539   if (handler)
540      (*handler)(device->machine, offset & 0x7f, data);
541
542   /* expansion card enable? */
543   if ((offset & 0x7f) == 0)
544   {
545      if (data & 1)
546      {
547         /* enable */
548         peb->active_card = port;
549      }
550      else
551      {
552         if (port == peb->active_card)   /* geez... who cares? */
553         {
554            peb->active_card = -1;         /* no port selected */
555         }
556      }
557   }
558}
559
560/*
561    Read mem in range >4000->5fff (ti-99/8)
562*/
563READ8_DEVICE_HANDLER( ti99_8_peb_r )
564{
565   int reply = 0;
566   read8_space_func handler;
567   ti99_peb_state *peb = get_safe_token(device);
568
569   cpu_adjust_icount(device->machine->firstcpu,-4);
570
571   if (peb->active_card != -1)
572   {
573      handler = peb->expansion_ports[peb->active_card].mem_read;
574      if (handler)
575         reply = (*handler)(peb->space, offset);
576   }
577
578   return reply;
579}
580
581/*
582    Write mem in range >4000->5fff (ti-99/8)
583*/
584WRITE8_DEVICE_HANDLER( ti99_8_peb_w )
585{
586   write8_space_func handler;
587   ti99_peb_state *peb = get_safe_token(device);
588
589   cpu_adjust_icount(device->machine->firstcpu,-4);
590
591   if (peb->active_card != -1)
592   {
593      handler = peb->expansion_ports[peb->active_card].mem_write;
594      if (handler)
595         (*handler)(peb->space, offset, data);
596   }
597}
598
599/*
600    Read CRU in range >0400->1ffe (>200->fff) (snug sgcpu 99/4p)
601*/
602READ8_DEVICE_HANDLER( ti99_4p_peb_cru_r )
603{
604   int port;
605   cru_read_handler handler;
606   int reply;
607   ti99_peb_state *peb = get_safe_token(device);
608
609   port = offset >> 4;
610   handler = peb->ti99_4p_expansion_ports[port].cru_read;
611
612   reply = (handler) ? (*handler)(device->machine, offset & 0xf) : 0;
613
614   return reply;
615}
616
617/*
618    Write CRU in range >0400->1ffe (>200->fff) (snug sgcpu 99/4p)
619*/
620WRITE8_DEVICE_HANDLER( ti99_4p_peb_cru_w )
621{
622   int port;
623   cru_write_handler handler;
624   ti99_peb_state *peb = get_safe_token(device);
625
626   int cru_address = (offset + 0x200)<<1;
627
628   port = offset >> 7;
629   handler = peb->ti99_4p_expansion_ports[port].cru_write;
630
631   if (handler)
632      (*handler)(device->machine, offset & 0x7f, data);
633
634   /* expansion card enable? */
635   if ((cru_address & 0xfe) == 0)
636   {
637      if (data & 1)
638      {
639         /* enable */
640         if (cru_address == 0x1e00)
641         {
642            // The internal mapper has precedence over the external bus.
643            // It may be turned on although there is another device currently turned on
644            peb->active_card_tmp = peb->active_card;
645            peb->mapper_override = TRUE;
646         }
647         peb->active_card = port;
648      }
649      else
650      {
651         if ((cru_address == 0x1e00) && peb->mapper_override)
652         {
653            peb->active_card = peb->active_card_tmp;
654            peb->mapper_override = FALSE;
655         }
656         else
657         {
658            if (port == peb->active_card)   /* geez... who cares? */
659            {
660               peb->active_card = -1;         /* no port selected */
661            }
662         }
663      }
664   }
665}
666
667/*
668    Read mem in range >4000->5ffe (snug sgcpu 99/4p)
669*/
670READ16_DEVICE_HANDLER( ti99_4p_peb_r )
671{
672   int reply = 0;
673   read8_space_func handler;
674   read16_space_func handler16;
675   ti99_peb_state *peb = get_safe_token(device);
676
677   if (peb->active_card == -1)
678      cpu_adjust_icount(device->machine->firstcpu,-4);   /* ??? */
679   else
680   {
681      if (peb->ti99_4p_expansion_ports[peb->active_card].width == width_8bit)
682      {
683         cpu_adjust_icount(device->machine->firstcpu,-4);
684
685         handler = peb->ti99_4p_expansion_ports[peb->active_card].w.width_8bit.mem_read;
686         if (handler)
687         {
688            reply = (*handler)(peb->space, (offset << 1) + 1);
689            reply |= ((unsigned) (*handler)(peb->space, offset << 1)) << 8;
690         }
691      }
692      else
693      {
694         cpu_adjust_icount(device->machine->firstcpu,-1);   /* ??? */
695
696         handler16 = peb->ti99_4p_expansion_ports[peb->active_card].w.width_16bit.mem_read;
697         if (handler16)
698            reply = (*handler16)(peb->space, offset, /*mem_mask*/0xffff);
699      }
700   }
701
702   if (peb->senila || peb->senilb)
703   {
704      if ((peb->active_card != -1) || (peb->senila && peb->senilb))
705         /* ah, the smell of burnt silicon... */
706         logerror("<Scrrrrr>: your computer has just burnt (maybe).\n");
707
708      if (peb->senila)
709         reply = (peb->ila & 0xff) | (peb->ila << 8);
710      else if (peb->senilb)
711         reply = (peb->ilb & 0xff) | (peb->ilb << 8);
712   }
713
714//  printf("[%04x:%04x] = %04x\n", (active_card<<8)+0x400, (offset<<1)+0x4000, reply);
715   return peb->tmp_buffer = reply;
716}
717
718/*
719    Write mem in range >4000->5ffe (snug sgcpu 99/4p)
720*/
721WRITE16_DEVICE_HANDLER( ti99_4p_peb_w )
722{
723   write8_space_func handler;
724   write16_space_func handler16;
725   ti99_peb_state *peb = get_safe_token(device);
726
727   if (peb->active_card == -1)
728      cpu_adjust_icount(device->machine->firstcpu,-4);   /* ??? */
729   else
730   {
731      /* simulate byte write */
732      data = (peb->tmp_buffer & ~mem_mask) | (data & mem_mask);
733
734      if (peb->ti99_4p_expansion_ports[peb->active_card].width == width_8bit)
735      {
736         cpu_adjust_icount(device->machine->firstcpu,-4);
737
738         handler = peb->ti99_4p_expansion_ports[peb->active_card].w.width_8bit.mem_write;
739         if (handler)
740         {
741            (*handler)(peb->space, (offset << 1) + 1, data & 0xff);
742            (*handler)(peb->space, offset << 1, (data >> 8) & 0xff);
743         }
744      }
745      else
746      {
747         cpu_adjust_icount(device->machine->firstcpu,-1);   /* ??? */
748
749         handler16 = peb->ti99_4p_expansion_ports[peb->active_card].w.width_16bit.mem_write;
750         if (handler16)
751            (*handler16)(peb->space, offset, data, /*mem_mask*/0xffff);
752      }
753   }
754}
755
756/*
757    Set the state of the SENILA line (snug sgcpu 99/4p)
758*/
759void ti99_4p_peb_set_senila(running_device *box, int state)
760{
761   ti99_peb_state *peb = get_safe_token(box);
762   peb->senila = (state != 0);
763}
764
765/*
766    Set the state of the SENILB line (snug sgcpu 99/4p)
767*/
768void ti99_4p_peb_set_senilb(running_device *box, int state)
769{
770   ti99_peb_state *peb = get_safe_token(box);
771   peb->senilb = (state != 0);
772}
773
774
775/***************************************************************************
776    DEVICE FUNCTIONS
777***************************************************************************/
778
779static DEVICE_START( ti99_peb )
780{
781}
782
783static DEVICE_STOP( ti99_peb )
784{
785}
786
787static DEVICE_RESET( ti99_peb )
788{
789   ti99_peb_state *peb = get_safe_token(device);
790
791   peb->has_16bit_peb = get_config(device)->mode16;
792   peb->inta_callback = get_config(device)->inta_callback;
793   peb->intb_callback = get_config(device)->intb_callback;
794
795   peb->active_card = -1;
796   peb->active_card_tmp = -1;
797
798   peb->mapper_override = FALSE; // for ti99_4p
799
800   peb->ila = 0;
801   peb->ilb = 0;
802
803   peb->space = cputag_get_address_space(device->machine, "maincpu", ADDRESS_SPACE_PROGRAM);
804
805   // Remove all card handlers; must be reinstalled
806   memset(peb->expansion_ports, 0, sizeof(peb->expansion_ports));
807   memset(peb->ti99_4p_expansion_ports, 0, sizeof(peb->ti99_4p_expansion_ports));
808}
809
810static const char DEVTEMPLATE_SOURCE[] = __FILE__;
811
812#define DEVTEMPLATE_ID(p,s)             p##ti99_peb##s
813#define DEVTEMPLATE_FEATURES            DT_HAS_START | DT_HAS_STOP | DT_HAS_RESET | DT_HAS_INLINE_CONFIG
814#define DEVTEMPLATE_NAME                "TI99 Peripheral Expansion System"
815#define DEVTEMPLATE_FAMILY              "External devices"
816#include "devtempl.h"
817
818DEFINE_LEGACY_DEVICE( PBOX, ti99_peb );
src/mess/devices/ti99_peb.h
r9500r9501
1/*
2    header file for machine/99_peb.c
3*/
4
5/*
6    mode16: TRUE if we are using the snug sgcpu 99/4p 16-bit extensions
7    inta_callback: callback called when the state of INTA changes (may be NULL)
8    intb_callback: callback called when the state of INTB changes (may be NULL)
9*/
10typedef struct _ti99_peb_config ti99_peb_config;
11struct _ti99_peb_config
12{
13   int      mode16;
14   void   (*inta_callback)(running_machine *machine, int state);
15   void   (*intb_callback)(running_machine *machine, int state);
16
17};
18
19/*
20    prototype for CRU handlers in expansion system
21*/
22typedef int (*cru_read_handler)(running_machine *machine, int offset);
23typedef void (*cru_write_handler)(running_machine *machine, int offset, int data);
24
25/*
26    Descriptor for TI peripheral expansion cards (8-bit bus)
27*/
28typedef struct ti99_peb_card_handlers_t
29{
30   cru_read_handler cru_read;      /* card CRU read handler */
31   cru_write_handler cru_write;   /* card CRU handler */
32
33   read8_space_func mem_read;      /* card mem read handler (8 bits) */
34   write8_space_func mem_write;   /* card mem write handler (8 bits) */
35} ti99_peb_card_handlers_t;
36
37/*
38    Descriptor for 16-bit peripheral expansion cards designed for the snug
39    sgcpu 99/4p system.  (These cards were not designed by TI, TI always
40    regarded the ti-99 as an 8-bit system.)
41*/
42typedef struct ti99_peb_16bit_card_handlers_t
43{
44   cru_read_handler cru_read;      /* card CRU read handler */
45   cru_write_handler cru_write;   /* card CRU handler */
46
47   read16_space_func mem_read;      /* card mem read handler (16 bits) */
48   write16_space_func mem_write;      /* card mem write handler (16 bits) */
49} ti99_peb_16bit_card_handlers_t;
50
51/* masks for ila and ilb */
52enum
53{
54   /* bits from actual ILA register */
55   inta_rs232_1_bit = 7-0,
56   inta_rs232_2_bit = 7-1,
57   inta_rs232_3_bit = 7-4,
58   inta_rs232_4_bit = 7-5,
59
60   /* extra "virtual" bits for devices that assert the INTA line without
61    setting a bit of the ILA register */
62   inta_ide_bit     = 8,
63   inta_ide_clk_bit = 9,
64
65   /* bits from actual ILB register */
66   intb_fdc_bit     = 7-0,
67   intb_ieee488_bit = 7-1
68};
69
70void ti99_peb_set_card_handlers(running_device *box, int cru_base, const ti99_peb_card_handlers_t *handler);
71void ti99_peb_set_16bit_card_handlers(running_device *box, int cru_base, const ti99_peb_16bit_card_handlers_t *handler);
72void ti99_peb_set_ila_bit(running_device *box, int bit, int state);
73void ti99_peb_set_ilb_bit(running_device *box, int bit, int state);
74
75READ8_DEVICE_HANDLER( ti99_4x_peb_cru_r );
76WRITE8_DEVICE_HANDLER( ti99_4x_peb_cru_w );
77READ16_DEVICE_HANDLER( ti99_4x_peb_r );
78WRITE16_DEVICE_HANDLER( ti99_4x_peb_w );
79
80READ8_DEVICE_HANDLER( geneve_peb_cru_r );
81WRITE8_DEVICE_HANDLER( geneve_peb_cru_w );
82READ8_DEVICE_HANDLER( geneve_peb_r );
83WRITE8_DEVICE_HANDLER( geneve_peb_w );
84
85READ8_DEVICE_HANDLER( ti99_8_peb_cru_r );
86WRITE8_DEVICE_HANDLER( ti99_8_peb_cru_w );
87READ8_DEVICE_HANDLER( ti99_8_peb_r );
88WRITE8_DEVICE_HANDLER( ti99_8_peb_w );
89
90READ8_DEVICE_HANDLER( ti99_4p_peb_cru_r );
91WRITE8_DEVICE_HANDLER( ti99_4p_peb_cru_w );
92READ16_DEVICE_HANDLER( ti99_4p_peb_r );
93WRITE16_DEVICE_HANDLER( ti99_4p_peb_w );
94
95void ti99_4p_peb_set_senila(running_device *box, int state);
96void ti99_4p_peb_set_senilb(running_device *box, int state);
97
98/* device interface */
99DECLARE_LEGACY_DEVICE( PBOX, ti99_peb );
100
101#define MDRV_PBOX_ADD(_tag, _mode16, _inta, _intb)         \
102   MDRV_DEVICE_ADD(_tag, PBOX, 0)                     \
103   MDRV_DEVICE_CONFIG_DATA32(ti99_peb_config, mode16, _mode16)   \
104   MDRV_DEVICE_CONFIG_DATAPTR(ti99_peb_config, inta_callback, _inta)   \
105   MDRV_DEVICE_CONFIG_DATAPTR(ti99_peb_config, intb_callback, _intb)
106
107
src/mess/machine/99_dsk.c
r9500r9501
1/*
2    TI-99/4 and /4a disk controller emulation.
3
4    Known disk controllers:
5    * TI original SD disk controller.  First sold as a side port module
6      (PHP1800), later as a card to be inserted in the PE-box (PHP1240).
7      Uses a WD1771 FDC, and supports a format of 40 tracks of 9 sectors.
8    * TI DD disk controller prototype.  Uses some NEC FDC and supports 16
9      sectors per track.  (Not emulated)
10    * CorComp FDC.  Specs unknown, but it supports DD.  (Not emulated)
11    * SNUG BwG.  A nice DD disk controller.  Supports 18 sectors per track.
12    * Myarc HFDC.  Extremely elaborate, supports DD (and even HD, provided that
13      a) the data separator is a 9216B and not a 9216, and b) that the OS
14      overrides the hfdc DSR, whose HD support is buggy) and MFM harddisks.
15
16    An alternative was installing the hexbus controller (which was just a
17    prototype, and is not emulated) and connecting a hexbus floppy disk
18    controller.  The integrated hexbus port was the only supported way to
19    attach a floppy drive to a TI-99/2 or a TI-99/5.  The integrated hexbus
20    port was the recommended way to attach a floppy drive to the TI-99/8,
21    but I think this computer supported the TI-99/4(a) disk controllers, too.
22
23    Raphael Nabet, 1999-2004.
24
25    CHANGES
26
27    * Removed format definition and put it in separate file (ti99_dsk)
28      Michael Zapf, Feb 2010
29*/
30
31#include "emu.h"
32#include "wd17xx.h"
33#include "smc92x4.h"
34#include "ti99_4x.h"  /* required for memory region offsets */
35#include "devices/ti99_peb.h"
36#include "99_dsk.h"
37#include "mm58274c.h"
38#include "devices/flopdrv.h"
39#include "devices/harddriv.h"
40#include "devices/ti99_hd.h"
41#include "harddisk.h"
42#include "formats/ti99_dsk.h"
43
44#define MAX_FLOPPIES 4
45
46/* defines for DRQ_IRQ_status */
47enum
48{
49   fdc_IRQ = 1,
50   fdc_DRQ = 2
51};
52
53/* current state of the DRQ and IRQ lines */
54static int DRQ_IRQ_status;
55
56/* when TRUE the CPU is halted while DRQ/IRQ are true */
57static int DSKhold;
58/* disk selection bits */
59static int DSEL;
60/* currently selected disk unit */
61static int DSKnum;
62/* current side */
63static int DSKside;
64/* 1 if motor is on */
65static int DVENA;
66/* on rising edge, sets DVENA for 4.23 seconds on rising edge */
67static int motor_on;
68/* count 4.23s from rising edge of motor_on */
69static emu_timer *motor_on_timer;
70
71static running_device *expansion_box;
72
73/*
74    Resets the drive geometry. This is required because the heuristic of
75    the default implementation sets the drive geometry to the geometry
76    of the medium.
77*/
78static void set_geometry(running_device *drive, floppy_type_t type)
79{
80   if (drive!=NULL)
81      floppy_drive_set_geometry(drive, type);
82   else
83      logerror("Drive not found\n");
84}
85
86static void set_all_geometries(running_machine *machine, floppy_type_t type)
87{
88   set_geometry(machine->device(FLOPPY_0), type);
89   set_geometry(machine->device(FLOPPY_1), type);
90   set_geometry(machine->device(FLOPPY_2), type);
91   set_geometry(machine->device(FLOPPY_3), type);
92}
93
94/*
95    call this when the state of DSKhold or DRQ/IRQ or DVENA change
96
97    Emulation is faulty because the CPU is actually stopped in the midst of
98    instruction, at the end of the memory access
99*/
100static void fdc_handle_hold(running_machine *machine)
101{
102   if (DSKhold && (!DRQ_IRQ_status) && DVENA)
103      cputag_set_input_line(machine, "maincpu", INPUT_LINE_HALT, ASSERT_LINE);
104   else
105      cputag_set_input_line(machine, "maincpu", INPUT_LINE_HALT, CLEAR_LINE);
106}
107
108/*
109    callback called at the end of DVENA pulse
110*/
111static TIMER_CALLBACK(motor_on_timer_callback)
112{
113   DVENA = 0;
114   fdc_handle_hold(machine);
115}
116
117/*
118    callback called whenever DRQ/IRQ state change
119*/
120static WRITE_LINE_DEVICE_HANDLER( ti99_fdc_intrq_w )
121{
122   if (state)
123   {
124      DRQ_IRQ_status |= fdc_IRQ;
125      ti99_peb_set_ilb_bit(expansion_box, intb_fdc_bit, 1);
126   }
127   else
128   {
129      DRQ_IRQ_status &= ~fdc_IRQ;
130      ti99_peb_set_ilb_bit(expansion_box, intb_fdc_bit, 0);
131   }
132
133   fdc_handle_hold(device->machine);
134}
135
136static WRITE_LINE_DEVICE_HANDLER( ti99_fdc_drq_w )
137{
138   if (state)
139      DRQ_IRQ_status |= fdc_DRQ;
140   else
141      DRQ_IRQ_status &= ~fdc_DRQ;
142
143   fdc_handle_hold(device->machine);
144}
145
146const wd17xx_interface ti99_wd17xx_interface =
147{
148   DEVCB_NULL,
149   DEVCB_LINE(ti99_fdc_intrq_w),
150   DEVCB_LINE(ti99_fdc_drq_w),
151   {FLOPPY_0, FLOPPY_1, FLOPPY_2, FLOPPY_3}
152};
153
154/*
155    Initializes all available controllers. This routine is only used in the
156    init state of the emulator. During the normal operation, only the
157    reset routines are used.
158*/
159// TODO: Check that:    floppy_mon_w(w->drive, CLEAR_LINE);
160
161void ti99_floppy_controllers_init_all(running_machine *machine)
162{
163   motor_on_timer = timer_alloc(machine, motor_on_timer_callback, NULL);
164   expansion_box = machine->device("per_exp_box");
165}
166
167/*===========================================================================*/
168/*
169    TI99/4(a) Floppy disk controller card emulation
170*/
171
172/* prototypes */
173static TIMER_CALLBACK(motor_on_timer_callback);
174static int fdc_cru_r(running_machine *machine, int offset);
175static void fdc_cru_w(running_machine *machine, int offset, int data);
176static READ8_HANDLER(fdc_mem_r);
177static WRITE8_HANDLER(fdc_mem_w);
178
179/* pointer to the fdc ROM data */
180static UINT8 *ti99_disk_DSR;
181
182static const ti99_peb_card_handlers_t fdc_handlers =
183{
184   fdc_cru_r,
185   fdc_cru_w,
186   fdc_mem_r,
187   fdc_mem_w
188};
189
190/*
191    Reset fdc card, set up handlers
192*/
193void ti99_fdc_reset(running_machine *machine)
194{
195   running_device *fdc = machine->device("wd179x");
196   ti99_disk_DSR = memory_region(machine, region_dsr) + offset_fdc_dsr;
197   DSEL = 0;
198   DSKnum = -1;
199   DSKside = 0;
200
201   DVENA = 0;
202   motor_on = 0;
203
204   ti99_set_80_track_drives(FALSE);
205
206   floppy_type_t flop = FLOPPY_STANDARD_5_25_DSDD_40;
207   set_all_geometries(machine, flop);
208
209   ti99_peb_set_card_handlers(expansion_box, 0x1100, &fdc_handlers);
210   if (fdc) {
211      wd17xx_reset(fdc);      /* resets the fdc */
212      wd17xx_dden_w(fdc, ASSERT_LINE);
213   }
214}
215
216/*
217    Read disk CRU interface
218
219    bit 0: HLD pin
220    bit 1-3: drive n active
221    bit 4: 0: motor strobe on
222    bit 5: always 0
223    bit 6: always 1
224    bit 7: selected side
225*/
226static int fdc_cru_r(running_machine *machine, int offset)
227{
228   int reply;
229
230   switch (offset)
231   {
232   case 0:
233      reply = 0x40;
234      if (DSKside)
235         reply |= 0x80;
236      if (DVENA)
237         reply |= (DSEL << 1);
238      if (! DVENA)
239         reply |= 0x10;
240      break;
241
242   default:
243      reply = 0;
244      break;
245   }
246
247   return reply;
248}
249
250/*
251    Write disk CRU interface
252*/
253static void fdc_cru_w(running_machine *machine, int offset, int data)
254{
255   running_device *fdc = machine->device("wd179x");
256
257   switch (offset)
258   {
259   case 0:
260      /* WRITE to DISK DSR ROM bit (bit 0) */
261      /* handled in xxx_peb_cru_w() */
262      break;
263
264   case 1:
265      /* Strobe motor (motor is on for 4.23 sec) */
266      if (data && !motor_on)
267      {   /* on rising edge, set DVENA for 4.23s */
268         DVENA = 1;
269         fdc_handle_hold(machine);
270         timer_adjust_oneshot(motor_on_timer, ATTOTIME_IN_MSEC(4230), 0);
271      }
272      motor_on = data;
273      break;
274
275   case 2:
276      /* Set disk ready/hold (bit 2)
277            0: ignore IRQ and DRQ
278            1: TMS9900 is stopped until IRQ or DRQ are set (OR the motor stops rotating - rotates
279              for 4.23s after write to revelant CRU bit, this is not emulated and could cause
280              the TI99 to lock...) */
281      DSKhold = data;
282      fdc_handle_hold(machine);
283      break;
284
285   case 3:
286      /* Load disk heads (HLT pin) (bit 3) */
287      /* ... */
288      break;
289
290   case 4:
291   case 5:
292   case 6:
293      /* Select drive X (bits 4-6) */
294      {
295         int drive = offset-4;               /* drive # (0-2) */
296
297         if (data)
298         {
299            DSEL |= 1 << drive;
300
301            if (drive != DSKnum)         /* turn on drive... already on ? */
302            {
303               DSKnum = drive;
304
305               wd17xx_set_drive(fdc,DSKnum);
306               /*wd17xx_set_side(DSKside);*/
307            }
308         }
309         else
310         {
311            DSEL &= ~ (1 << drive);
312
313            if (drive == DSKnum)         /* geez... who cares? */
314            {
315               DSKnum = -1;            /* no drive selected */
316            }
317         }
318      }
319      break;
320
321   case 7:
322      /* Select side of disk (bit 7) */
323      DSKside = data;
324      wd17xx_set_side(fdc,DSKside);
325      break;
326   }
327}
328
329
330/*
331    read a byte in disk DSR space
332*/
333static  READ8_HANDLER(fdc_mem_r)
334{
335   running_device *fdc = space->machine->device("wd179x");
336
337   /* only use the even addresses from 1ff0 to 1ff6.
338       Note that data is inverted. */
339   if (offset >= 0x1ff0 && (offset & 0x09)==0)
340      return wd17xx_r(fdc, (offset >> 1)&0x03) ^ 0xff;
341   else
342      return ti99_disk_DSR[offset];
343}
344
345/*
346    write a byte in disk DSR space
347*/
348static WRITE8_HANDLER(fdc_mem_w)
349{
350   running_device *fdc = space->machine->device("wd179x");
351
352   /* only use the even addresses from 1ff8 to 1ffe.
353       Note that data is inverted. */
354   if (offset >= 0x1ff0 && (offset & 0x09)==0x08)
355      wd17xx_w(fdc, (offset >> 1)&0x03, data ^ 0xff);
356}
357
358
359#if HAS_99CCFDC
360/*===========================================================================*/
361/*
362    Alternate fdc: CorcComp FDC
363
364    Advantages:
365    * this card supports Double Density.
366    * this card support an additional floppy drive, for a total of 4 floppies.
367
368    References:
369    * ???
370*/
371
372/* prototypes */
373static int ccfdc_cru_r(running_machine *machine, int offset);
374static void ccfdc_cru_w(running_machine *machine, int offset, int data);
375static READ8_HANDLER(ccfdc_mem_r);
376static WRITE8_HANDLER(ccfdc_mem_w);
377
378static const ti99_peb_card_handlers_t ccfdc_handlers =
379{
380   ccfdc_cru_r,
381   ccfdc_cru_w,
382   ccfdc_mem_r,
383   ccfdc_mem_w
384};
385
386#if HAS_99CCFDC
387void ti99_ccfdc_reset(running_machine *machine)
388{
389   running_device *fdc = machine->device("wd179x");
390
391   ti99_disk_DSR = memory_region(machine, region_dsr) + offset_ccfdc_dsr;
392   DSEL = 0;
393   DSKnum = -1;
394   DSKside = 0;
395
396   DVENA = 0;
397   motor_on = 0;
398
399   ti99_set_80_track_drives(FALSE);
400
401   floppy_type_t flop = FLOPPY_STANDARD_5_25_DSDD_40;
402   set_all_geometries(machine, flop);
403
404   ti99_peb_set_card_handlers(expansion_box, 0x1100, &ccfdc_handlers);
405
406   wd17xx_reset(fdc);      /* initialize the floppy disk controller */
407   wd17xx_dden(fdc, CLEAR_LINE);
408}
409#endif
410
411
412/*
413    Read disk CRU interface
414
415    bit 0: drive 4 active (not emulated)
416    bit 1-3: drive n active
417    bit 4-7: dip switches 1-4
418*/
419static int ccfdc_cru_r(int offset)
420{
421   int reply;
422
423   switch (offset)
424   {
425   case 0:
426      /* CRU bits: beware, logic levels of DIP-switches are inverted  */
427      reply = 0x50;
428      if (DVENA)
429         reply |= ((DSEL << 1) | (DSEL >> 3)) & 0x0f;
430      break;
431
432   default:
433      reply = 0;
434      break;
435   }
436
437   return reply;
438}
439
440
441/*
442    Write disk CRU interface
443*/
444static void ccfdc_cru_w(running_machine *machine, int offset, int data)
445{
446   running_device *fdc = machine->device("wd179x");
447
448   switch (offset)
449   {
450   case 0:
451      /* WRITE to DISK DSR ROM bit (bit 0) */
452      /* handled in xxx_peb_cru_w() */
453      break;
454
455   case 1:
456      /* Strobe motor (motor is on for 4.23 sec) */
457      if (data && !motor_on)
458      {   /* on rising edge, set DVENA for 4.23s */
459         DVENA = 1;
460         fdc_handle_hold(machine);
461         timer_adjust_oneshot(motor_on_timer, ATTOTIME_IN_MSEC(4230), 0);
462      }
463      motor_on = data;
464      break;
465
466   case 2:
467      /* Set disk ready/hold (bit 2)
468            0: ignore IRQ and DRQ
469            1: TMS9900 is stopped until IRQ or DRQ are set (OR the motor stops rotating - rotates
470              for 4.23s after write to revelant CRU bit, this is not emulated and could cause
471              the TI99 to lock...) */
472      DSKhold = data;
473      fdc_handle_hold(machine);
474      break;
475
476   case 4:
477   case 5:
478   case 6:
479   case 8:
480      /* Select drive 0-2 (DSK1-DSK3) (bits 4-6) */
481      /* Select drive 3 (DSK4) (bit 8) */
482      {
483         int drive = (offset == 8) ? 3 : (offset-4);      /* drive # (0-3) */
484
485         if (data)
486         {
487            DSEL |= 1 << drive;
488
489            if (drive != DSKnum)         /* turn on drive... already on ? */
490            {
491               DSKnum = drive;
492
493               wd17xx_set_drive(fdc,DSKnum);
494               /*wd17xx_set_side(fdc,DSKside);*/
495            }
496         }
497         else
498         {
499            DSEL &= ~ (1 << drive);
500
501            if (drive == DSKnum)         /* geez... who cares? */
502            {
503               DSKnum = -1;            /* no drive selected */
504            }
505         }
506      }
507      break;
508
509   case 7:
510      /* Select side of disk (bit 7) */
511      DSKside = data;
512      wd17xx_set_side(fdc,DSKside);
513      break;
514
515   case 10:
516      /* double density enable (active low) */
517      wd17xx_dden(fdc, data ? ASSERT_LINE : CLEAR_LINE);
518      break;
519
520   case 11:
521      /* EPROM A13 */
522      break;
523
524   case 13:
525      /* RAM A10 */
526      break;
527
528   case 14:
529      /* override FDC with RTC (active high) */
530      break;
531
532   case 15:
533      /* EPROM A14 */
534      break;
535
536   case 3:
537   case 9:
538   case 12:
539      /* Unused (bit 3, 9 & 12) */
540      break;
541   }
542}
543
544
545/*
546    read a byte in disk DSR space
547*/
548static READ8_HANDLER(ccfdc_mem_r)
549{
550   int reply = 0;
551
552   reply = ti99_disk_DSR[offset];
553
554   return reply;
555}
556
557/*
558    write a byte in disk DSR space
559*/
560static WRITE8_HANDLER(ccfdc_mem_w)
561{
562}
563#endif
564
565
566/*===========================================================================*/
567/*
568    Alternate fdc: BwG card from SNUG
569
570    Advantages:
571    * this card supports Double Density.
572    * as this card includes its own RAM, it does not need to allocate a portion
573      of VDP RAM to store I/O buffers.
574    * this card includes a MM58274C RTC.
575    * this card support an additional floppy drive, for a total of 4 floppies.
576
577    Reference:
578    * BwG Disketten-Controller: Beschreibung der DSR
579        <http://home.t-online.de/home/harald.glaab/snug/bwg.pdf>
580*/
581
582/* prototypes */
583static int bwg_cru_r(running_machine *machine, int offset);
584static void bwg_cru_w(running_machine *machine, int offset, int data);
585static READ8_HANDLER(bwg_mem_r);
586static WRITE8_HANDLER(bwg_mem_w);
587
588static const ti99_peb_card_handlers_t bwg_handlers =
589{
590   bwg_cru_r,
591   bwg_cru_w,
592   bwg_mem_r,
593   bwg_mem_w
594};
595
596static int bwg_rtc_enable;
597static int bwg_ram_offset;
598static int bwg_rom_offset;
599static UINT8 *bwg_ram;
600
601
602/*
603    Reset fdc card, set up handlers
604*/
605void ti99_bwg_reset(running_machine *machine)
606{
607   running_device *fdc = machine->device("wd179x");
608
609   ti99_disk_DSR = memory_region(machine, region_dsr) + offset_bwg_dsr;
610        bwg_ram = memory_region(machine, region_dsr) + offset_bwg_ram;
611   bwg_ram_offset = 0;
612   bwg_rom_offset = 0;
613   bwg_rtc_enable = 0;
614
615   DSEL = 0;
616   DSKnum = -1;
617   DSKside = 0;
618
619   DVENA = 0;
620   motor_on = 0;
621
622   ti99_set_80_track_drives(FALSE);
623
624   floppy_type_t flop = FLOPPY_STANDARD_5_25_DSDD_40;
625   set_all_geometries(machine, flop);
626
627   ti99_peb_set_card_handlers(expansion_box, 0x1100, & bwg_handlers);
628
629   wd17xx_reset(fdc);      /* initialize the floppy disk controller */
630   wd17xx_dden_w(fdc, CLEAR_LINE);
631}
632
633/*
634    Read disk CRU interface
635
636    bit 0: drive 4 active (not emulated)
637    bit 1-3: drive n active
638    bit 4-7: dip switches 1-4
639*/
640static int bwg_cru_r(running_machine *machine, int offset)
641{
642   int reply;
643
644   switch (offset)
645   {
646   case 0:
647      /* CRU bits: beware, logic levels of DIP-switches are inverted  */
648      reply = 0x50;
649      if (DVENA)
650         reply |= ((DSEL << 1) | (DSEL >> 3)) & 0x0f;
651      break;
652
653   default:
654      reply = 0;
655      break;
656   }
657
658   return reply;
659}
660
661
662/*
663    Write disk CRU interface
664*/
665static void bwg_cru_w(running_machine *machine, int offset, int data)
666{
667   running_device *fdc = machine->device("wd179x");
668
669   switch (offset)
670   {
671   case 0:
672      /* WRITE to DISK DSR ROM bit (bit 0) */
673      /* handled in xxx_peb_cru_w() */
674      break;
675
676   case 1:
677      /* Strobe motor (motor is on for 4.23 sec) */
678      if (data && !motor_on)
679      {   /* on rising edge, set DVENA for 4.23s */
680         DVENA = 1;
681         fdc_handle_hold(machine);
682         timer_adjust_oneshot(motor_on_timer, ATTOTIME_IN_MSEC(4230), 0);
683      }
684      motor_on = data;
685      break;
686
687   case 2:
688      /* Set disk ready/hold (bit 2)
689            0: ignore IRQ and DRQ
690            1: TMS9900 is stopped until IRQ or DRQ are set (OR the motor stops rotating - rotates
691              for 4.23s after write to revelant CRU bit, this is not emulated and could cause
692              the TI99 to lock...) */
693      DSKhold = data;
694      fdc_handle_hold(machine);
695      break;
696
697   case 4:
698   case 5:
699   case 6:
700   case 8:
701      /* Select drive 0-2 (DSK1-DSK3) (bits 4-6) */
702      /* Select drive 3 (DSK4) (bit 8) */
703      {
704         int drive = (offset == 8) ? 3 : (offset-4);      /* drive # (0-3) */
705
706         if (data)
707         {
708            DSEL |= 1 << drive;
709
710            if (drive != DSKnum)         /* turn on drive... already on ? */
711            {
712               DSKnum = drive;
713
714               wd17xx_set_drive(fdc,DSKnum);
715               /*wd17xx_set_side(fdc,DSKside);*/
716            }
717         }
718         else
719         {
720            DSEL &= ~ (1 << drive);
721
722            if (drive == DSKnum)         /* geez... who cares? */
723            {
724               DSKnum = -1;            /* no drive selected */
725            }
726         }
727      }
728      break;
729
730   case 7:
731      /* Select side of disk (bit 7) */
732      DSKside = data;
733      wd17xx_set_side(fdc,DSKside);
734      break;
735
736   case 10:
737      /* double density enable (active low) */
738      wd17xx_dden_w(fdc, data ? ASSERT_LINE : CLEAR_LINE);
739      break;
740
741   case 11:
742      /* EPROM A13 */
743      if (data)
744         bwg_rom_offset |= 0x2000;
745      else
746         bwg_rom_offset &= ~0x2000;
747      break;
748
749   case 13:
750      /* RAM A10 */
751      if (data)
752         bwg_ram_offset = 0x0400;
753      else
754         bwg_ram_offset = 0x0000;
755      break;
756
757   case 14:
758      /* override FDC with RTC (active high) */
759      bwg_rtc_enable = data;
760      break;
761
762   case 15:
763      /* EPROM A14 */
764      if (data)
765         bwg_rom_offset |= 0x4000;
766      else
767         bwg_rom_offset &= ~0x4000;
768      break;
769
770   case 3:
771   case 9:
772   case 12:
773      /* Unused (bit 3, 9 & 12) */
774      break;
775   }
776}
777
778
779/*
780    read a byte in disk DSR space
781*/
782static  READ8_HANDLER(bwg_mem_r)
783{
784   running_device *fdc = space->machine->device("wd179x");
785
786   int reply = 0;
787
788   if (offset < 0x1c00)
789      reply = ti99_disk_DSR[bwg_rom_offset+offset];
790   else if (offset < 0x1fe0)
791      reply = bwg_ram[bwg_ram_offset+(offset-0x1c00)];
792   else if (bwg_rtc_enable)
793   {
794      if (! (offset & 1))
795         reply = mm58274c_r(space->machine->device("mm58274c_floppy"), (offset - 0x1FE0) >> 1);
796   }
797   else
798   {
799      if (offset < 0x1ff0)
800         reply = bwg_ram[bwg_ram_offset+(offset-0x1c00)];
801      else
802         switch (offset)
803         {
804         case 0x1FF0:               /* Status register */
805            reply = wd17xx_status_r(fdc, offset);
806            break;
807         case 0x1FF2:               /* Track register */
808            reply = wd17xx_track_r(fdc, offset);
809            break;
810         case 0x1FF4:               /* Sector register */
811            reply = wd17xx_sector_r(fdc, offset);
812            break;
813         case 0x1FF6:               /* Data register */
814            reply = wd17xx_data_r(fdc, offset);
815            break;
816         default:
817            reply = 0;
818            break;
819         }
820   }
821   return reply;
822}
823
824/*
825    write a byte in disk DSR space
826*/
827static WRITE8_HANDLER(bwg_mem_w)
828{
829   running_device *fdc = space->machine->device("wd179x");
830
831   if (offset < 0x1c00)
832      ;
833   else if (offset < 0x1fe0)
834      bwg_ram[bwg_ram_offset+(offset-0x1c00)] = data;
835   else if (bwg_rtc_enable)
836   {
837      if (! (offset & 1))
838         mm58274c_w(space->machine->device("mm58274c_floppy"), (offset - 0x1FE0) >> 1, data);
839   }
840   else
841   {
842      if (offset < 0x1ff0)
843      {
844         bwg_ram[bwg_ram_offset+(offset-0x1c00)] = data;
845      }
846      else
847      {
848         switch (offset)
849         {
850         case 0x1FF8:               /* Command register */
851            wd17xx_command_w(fdc, offset, data);
852            break;
853         case 0x1FFA:               /* Track register */
854            wd17xx_track_w(fdc, offset, data);
855            break;
856         case 0x1FFC:               /* Sector register */
857            wd17xx_sector_w(fdc, offset, data);
858            break;
859         case 0x1FFE:               /* Data register */
860            wd17xx_data_w(fdc, offset, data);
861            break;
862         }
863      }
864   }
865}
866
867
868/*===========================================================================*/
869/*
870    Alternate fdc: HFDC card built by Myarc
871
872    Advantages: same as BwG, plus:
873    * high density support (only on upgraded cards, I think)
874    * hard disk support (only prehistoric mfm hard disks are supported, though)
875    * DMA support (I think the DMA controller can only access the on-board RAM)
876
877    This card includes a MM58274C RTC and a 9234 HFDC with its various support
878    chips.
879
880    Reference:
881    * hfdc manual
882        <ftp://ftp.whtech.com//datasheets & manuals/Hardware manuals/hfdc manual.max>
883
884    For smc92x4 (HFDC-internal DSR)
885    FM:  gap0=3, gap1=26, gap2=11, gap3=27, gap4=42, sync=6, count=9, size=2, fm=16, gap_byte=ff
886    MFM: gap0=2, gap1=30, gap2=22, gap3=20, gap4=42, sync=12, count=18, size=2, fm=0, gap_byte=4e
887*/
888
889/* prototypes */
890static int hfdc_cru_r(running_machine *machine, int offset);
891static void hfdc_cru_w(running_machine *machine, int offset, int data);
892static  READ8_HANDLER(hfdc_mem_r);
893static WRITE8_HANDLER(hfdc_mem_w);
894
895static const ti99_peb_card_handlers_t hfdc_handlers =
896{
897   hfdc_cru_r,
898   hfdc_cru_w,
899   hfdc_mem_r,
900   hfdc_mem_w
901};
902
903#define HFDC_MAX_FLOPPY 4
904#define HFDC_MAX_HARD 4
905
906static int hfdc_rtc_enable;
907static int hfdc_ram_offset[3];
908static int hfdc_rom_offset;
909static int cru_sel;
910static UINT8 *hfdc_ram;
911
912static int hfdc_irq_state;
913static int hfdc_dip_state;
914
915static running_device *floppy_unit[4];
916static running_device *harddisk_unit[4];
917
918static UINT8 output1_latch;
919static UINT8 output2_latch;
920
921static int dma_address;
922
923static int line_to_index(UINT8 line, int max)
924{
925   int index = 0;
926   while (index < max)
927   {
928      if ((line & 0x01)!=0)
929         break;
930      else
931      {
932         line = line >> 1;
933         index++;
934      }
935   }
936   if (index==max) return -1;
937   return index;
938}
939
940/*
941    Select the HFDC hard disk unit
942    This function implements the selection logic on the PCB (outside the
943    controller chip)
944    The HDC9234 allows up to four drives to be selected by the select lines.
945    This is not enough for controlling four floppy drives and three hard
946    drives, so the user programmable outputs are used to select the floppy
947    drives. This selection happens completely outside of the controller,
948    so we must implement it here.
949*/
950
951static running_device *hfdc_current_harddisk(void)
952{
953   int disk_unit = -1;
954   disk_unit = line_to_index((output1_latch>>4)&0x0f, HFDC_MAX_HARD);
955
956   /* The HFDC does not use disk_unit=0. The first HD has index 1. */
957/*  if (disk_unit>=0) printf("Select hard disk %d\n", disk_unit);
958    else printf("No hard disk selected\n");
959*/
960   return harddisk_unit[disk_unit];
961}
962
963/*
964    Select the HFDC floppy disk unit
965    This function implements the selection logic on the PCB (outside the
966    controller chip)
967*/
968
969static running_device *hfdc_current_floppy(void)
970{
971   int disk_unit = -1;
972   disk_unit = line_to_index(output1_latch & 0x0f, HFDC_MAX_FLOPPY);
973
974   if (disk_unit<0)
975   {
976   //  printf("No unit selected\n");
977      return NULL;
978   }
979
980   // printf("Select floppy disk %d (output1=%02x)\n", index, output1_latch);
981   return floppy_unit[disk_unit];
982}
983
984/*
985    Called whenever the state of the sms9234 interrupt pin changes.
986*/
987static WRITE_LINE_DEVICE_HANDLER( ti99_hfdc_intrq_w )
988{
989   hfdc_irq_state = state;
990
991   /* Set INTA */
992   if (state)
993   {
994      ti99_peb_set_ila_bit(expansion_box, intb_fdc_bit, 1);
995   }
996   else
997   {
998      ti99_peb_set_ila_bit(expansion_box, intb_fdc_bit, 0);
999   }
1000
1001   /* TODO: Check */
1002   fdc_handle_hold(device->machine);
1003}
1004
1005/*
1006    Called whenever the state of the sms9234 DMA in progress changes.
1007*/
1008static WRITE_LINE_DEVICE_HANDLER( ti99_hfdc_dip_w )
1009{
1010   hfdc_dip_state = state;
1011}
1012
1013static WRITE8_DEVICE_HANDLER( ti99_hfdc_auxbus_out )
1014{
1015   switch (offset)
1016   {
1017   case INPUT_STATUS:
1018      logerror("99_dsk: Invalid operation: S0=S1=0, but tried to write (expected: read drive status)\n");
1019      return;
1020   case OUTPUT_DMA_ADDR:
1021      /* Value is dma address byte. Shift previous contents to the left. */
1022      dma_address = ((dma_address << 8) + (data&0xff))&0xffffff;
1023      break;
1024   case OUTPUT_OUTPUT1:
1025      /* value is output1 */
1026      output1_latch = data;
1027      break;
1028   case OUTPUT_OUTPUT2:
1029      /* value is output2 */
1030      output2_latch = data;
1031      break;
1032   }
1033}
1034
1035static READ_LINE_DEVICE_HANDLER( ti99_hfdc_auxbus_in )
1036{
1037   running_device *drive;
1038   UINT8 reply = 0;
1039
1040   if (output1_latch==0)
1041   {
1042      // printf("Neither floppy nor hard disk selected.\n");
1043      return 0; /* is that the correct default value? */
1044   }
1045
1046   /* If a floppy is selected, we have one line set among the four programmable outputs. */
1047   if ((output1_latch & 0x0f)!=0)
1048   {
1049      drive = hfdc_current_floppy();
1050
1051      /* Get floppy status. */
1052      if (floppy_drive_get_flag_state(drive, FLOPPY_DRIVE_INDEX) == FLOPPY_DRIVE_INDEX)
1053         reply |= DS_INDEX;
1054      if (floppy_tk00_r(drive) == CLEAR_LINE)
1055         reply |= DS_TRK00;
1056      if (floppy_wpt_r(drive) == CLEAR_LINE)
1057         reply |= DS_WRPROT;
1058
1059      /* if (image_exists(disk_img)) */
1060
1061      reply |= DS_READY;  /* Floppies don't have a READY line; line is pulled up */
1062      reply |= DS_SKCOM;  /* Same here. */
1063   }
1064   else /* one of the first four lines must be selected */
1065   {
1066      UINT8 state;
1067      drive = hfdc_current_harddisk();
1068      state = ti99_mfm_harddisk_status(drive);
1069      if (state & MFMHD_TRACK00)
1070         reply |= DS_TRK00;
1071      if (state & MFMHD_SEEKCOMP)
1072         reply |= DS_SKCOM;
1073      if (state & MFMHD_WRFAULT)
1074         reply |= DS_WRFAULT;
1075      if (state & MFMHD_INDEX)
1076         reply |= DS_INDEX;
1077      if (state & MFMHD_READY)
1078         reply |= DS_READY;
1079   }
1080   return reply;
1081}
1082
1083/*
1084    Read a byte from buffer in DMA mode
1085*/
1086static UINT8 hfdc_dma_read_callback(void)
1087{
1088   UINT8 value = hfdc_ram[dma_address & 0x7fff];
1089   dma_address++;
1090   return value;
1091}
1092
1093/*
1094    Write a byte to buffer in DMA mode
1095*/
1096static void hfdc_dma_write_callback(UINT8 data)
1097{
1098   hfdc_ram[dma_address & 0x7fff] = data;
1099   dma_address++;
1100}
1101
1102/*
1103    Preliminary MFM harddisk interface.
1104*/
1105static void hfdc_harddisk_get_next_id(int head, chrn_id_hd *id)
1106{
1107   running_device *harddisk = hfdc_current_harddisk();
1108   ti99_mfm_harddisk_get_next_id(harddisk, head, id);
1109}
1110
1111static void hfdc_harddisk_seek(int direction)
1112{
1113   running_device *harddisk = hfdc_current_harddisk();
1114   ti99_mfm_harddisk_seek(harddisk, direction);
1115}
1116
1117static void hfdc_harddisk_read_sector(int cylinder, int head, int sector, UINT8 **buf, int *sector_length)
1118{
1119   running_device *harddisk = hfdc_current_harddisk();
1120   if (harddisk != NULL)
1121      ti99_mfm_harddisk_read_sector(harddisk, cylinder, head, sector, buf, sector_length);
1122}
1123
1124static void hfdc_harddisk_write_sector(int cylinder, int head, int sector, UINT8 *buf, int sector_length)
1125{
1126   running_device *harddisk = hfdc_current_harddisk();
1127   if (harddisk != NULL)
1128      ti99_mfm_harddisk_write_sector(harddisk, cylinder, head, sector, buf, sector_length);
1129}
1130
1131static void hfdc_harddisk_read_track(int head, UINT8 **buffer, int *data_count)
1132{
1133   running_device *harddisk = hfdc_current_harddisk();
1134   if (harddisk != NULL)
1135      ti99_mfm_harddisk_read_track(harddisk, head, buffer, data_count);
1136}
1137
1138static void hfdc_harddisk_write_track(int head, UINT8 *buffer, int data_count)
1139{
1140   running_device *harddisk = hfdc_current_harddisk();
1141   if (harddisk != NULL)
1142      ti99_mfm_harddisk_write_track(harddisk, head, buffer, data_count);
1143}
1144
1145/*
1146    Reset fdc card, set up handlers
1147*/
1148void ti99_hfdc_reset(running_machine *machine)
1149{
1150   running_device *device = machine->device("smc92x4");
1151   const char *flopname[] = {FLOPPY_0, FLOPPY_1, FLOPPY_2, FLOPPY_3};
1152   const char *hardname[] = {MFMHD_0, MFMHD_1, MFMHD_2};
1153
1154   int i;
1155
1156   ti99_disk_DSR = memory_region(machine, region_dsr) + offset_hfdc_dsr;
1157   hfdc_ram = memory_region(machine, region_dsr) + offset_hfdc_ram;
1158   hfdc_ram_offset[0] = hfdc_ram_offset[1] = hfdc_ram_offset[2] = 0;
1159   hfdc_rom_offset = 0;
1160   hfdc_rtc_enable = 0;
1161
1162   DSEL = 0;
1163   DSKnum = -1;
1164   DSKside = 0;
1165
1166   DVENA = 0;
1167   motor_on = 0;
1168
1169   ti99_peb_set_card_handlers(expansion_box, 0x1100, & hfdc_handlers);
1170
1171   if ((input_port_read(machine, "DISKCTRL") & DISK_HFDC)
1172      && (input_port_read(machine, "HFDCDIP")&0x55))
1173      ti99_set_80_track_drives(TRUE);
1174   else
1175      ti99_set_80_track_drives(FALSE);
1176
1177   smc92x4_set_timing(device, input_port_read(machine, "DRVSPD"));
1178
1179   floppy_type_t flop = FLOPPY_STANDARD_5_25_DSHD;
1180   set_all_geometries(machine, flop);
1181
1182   /* Connect floppy drives to controller. Note that *this* is the
1183       controller, not the controller chip. The pcb contains a select
1184       logic.
1185       TODO: Turn this implementation into a device so that this is
1186       correctly modelled.
1187    */
1188   for (i = 0; i < 4; i++)
1189   {
1190      if (device->owner() != NULL)
1191      {
1192         floppy_unit[i] = device->owner()->subdevice(flopname[i]);
1193         if (floppy_unit[i]==NULL)
1194         {
1195            floppy_unit[i] = device->machine->device(flopname[i]);
1196         }
1197      }
1198      else
1199      {
1200         floppy_unit[i] = device->machine->device(flopname[i]);
1201      }
1202
1203      if (floppy_unit[i]!=NULL)
1204      {
1205         floppy_drive_set_controller(floppy_unit[i], device);
1206//          floppy_drive_set_index_pulse_callback(floppy_unit[i], smc92x4_index_pulse_callback);
1207         floppy_drive_set_rpm(floppy_unit[i], 300.);
1208      }
1209      else
1210      {
1211         logerror("99_dsk: Image %s is null\n", flopname[i]);
1212      }
1213   }
1214
1215   /* In the HFDC ROM, WDSx selects drive x; drive 0 is not used */
1216   for (i = 1; i < 4; i++)
1217   {
1218      harddisk_unit[i] = device->machine->device(hardname[i-1]);
1219   }
1220   harddisk_unit[0] = NULL;
1221
1222   if (device) {
1223      smc92x4_reset(device);
1224   }
1225}
1226
1227const smc92x4_interface ti99_smc92x4_interface =
1228{
1229   FALSE,      /* do not use the full track layout */
1230   DEVCB_LINE(ti99_hfdc_intrq_w),
1231   DEVCB_LINE(ti99_hfdc_dip_w),
1232   DEVCB_HANDLER(ti99_hfdc_auxbus_out),
1233   DEVCB_LINE(ti99_hfdc_auxbus_in),
1234
1235   hfdc_current_floppy,
1236   hfdc_dma_read_callback,
1237   hfdc_dma_write_callback,
1238
1239   /* Preliminary MFM harddisk interface. */
1240   hfdc_harddisk_get_next_id,
1241   hfdc_harddisk_seek,
1242   hfdc_harddisk_read_sector,
1243   hfdc_harddisk_write_sector,
1244   hfdc_harddisk_read_track,
1245   hfdc_harddisk_write_track
1246};
1247
1248int mycheck = 0;
1249
1250/*
1251    Read disk CRU interface
1252    HFDC manual p. 44
1253
1254    CRU Select=0
1255    CRU rel. address    Definition
1256    00          Disk controller interrupt
1257    02          Motor status
1258    04          DMA in progress
1259
1260    Note that the cru line settings on the board do not match the
1261    description. 02 and 04 switch positions. Similarly, the dip switches
1262    for the drive configurations are not correctly enumerated in the manual.
1263
1264    CRU Select=1
1265    CRU rel. address    Definition
1266    00          Switch 4 status \_ drive 2 config
1267    02          Switch 3 status /
1268    04          Switch 2 status \_ drive 1 config
1269    06          Switch 1 status /
1270    08          Switch 8 status \_ drive 4 config
1271    0A          Switch 7 status /
1272    0C          Switch 6 status \_ drive 3 config
1273    0E          Switch 5 status /
1274
1275    config: 00 = 9/16/18 sectors, 40 tracks, 16 msec
1276        10 = 9/16/18 sectors, 40 tracks, 8 msec
1277        01 = 9/16/18 sectors, 80 tracks, 2 msec
1278        11 = 36 sectors, 80 tracks, 2 msec
1279*/
1280static int hfdc_cru_r(running_machine *machine, int offset)
1281{
1282   int reply;
1283   if (offset==0)  /* CRU bits 0-7 */
1284   {
1285      /* CRU bits */
1286      if (cru_sel)
1287      {
1288         /* DIP switches.  Logic levels are inverted (on->0, off->1).  CRU
1289            bit order is the reverse of DIP-switch order, too (dip 1 -> bit 7,
1290            dip 8 -> bit 0).
1291
1292            MZ: 00 should not be used since there is a bug in the
1293            DSR of the HFDC which causes problems with SD disks
1294            (controller tries DD and then fails to fall back to SD) */
1295
1296         reply = ~(input_port_read(machine, "HFDCDIP"));
1297//          printf("hfdc cru read 7-0 = %02x\n", reply);
1298      }
1299      else
1300      {
1301         reply = 0;
1302/*          if (hfdc_irq_state)
1303                reply |= 1;
1304            if (motor_on)
1305                reply |= 2;
1306            if (hfdc_dma_in_progress)
1307                reply |= 4;*/
1308
1309         if (hfdc_irq_state)
1310            reply |= 0x01;
1311         if (hfdc_dip_state)
1312            reply |= 0x02;
1313         if (motor_on)
1314            reply |= 0x04;
1315//          printf("hfdc cru read 7-0 = %02x\n", reply);
1316
1317      }
1318   }
1319   else /* CRU bits 8+ */
1320      reply = 0;
1321//  printf("hfdc cru read %d = %d\n", offset, reply);
1322
1323   return reply;
1324}
1325
1326
1327/*
1328    Write disk CRU interface
1329    HFDC manual p. 43
1330
1331    CRU rel. address    Definition              Active
1332    00          Device Service Routine Select       HIGH
1333    02          Reset to controller chip        LOW
1334    04          Floppy Motor on / CD0           HIGH
1335    06          ROM page select 0 / CD1
1336    08          ROM page select 1 / CRU input select
1337    12/4/6/8/A      RAM page select at 0x5400
1338    1C/E/0/2/4      RAM page select at 0x5800
1339    26/8/A/C/E      RAM page select at 0x5C00
1340
1341    CD0 and CD1 are Clock Divider selections for the Floppy Data Separator (FDC9216)
1342*/
1343static void hfdc_cru_w(running_machine *machine, int offset, int data)
1344{
1345   switch (offset)
1346   {
1347   case 0:
1348      /* WRITE to DISK DSR ROM bit (bit 0) */
1349      /* handled in xxx_peb_cru_w() */
1350      break;
1351
1352   case 1:
1353      /* reset fdc (active low) */
1354      if (!data)
1355      {
1356         running_device *device = machine->device("smc92x4");
1357         smc92x4_reset(device);
1358      }
1359      break;
1360
1361   case 2:
1362      /* Strobe motor and Clock Divider Bit 0 (CD0) */
1363      if (data && !motor_on)
1364      {
1365         DVENA = 1;
1366         fdc_handle_hold(machine);
1367         timer_adjust_oneshot(motor_on_timer, ATTOTIME_IN_MSEC(4230), 0);
1368      }
1369      motor_on = data;
1370      //printf("99dsk set motor on / clock divider 0 to %d\n", data);
1371      break;
1372
1373   case 3:
1374      /* rom page select 0 and Clock Divider Bit 1 (CD1) */
1375      if (data)
1376         hfdc_rom_offset |= 0x2000;
1377      else
1378         hfdc_rom_offset &= ~0x2000;
1379      //printf("99dsk set rom page 0 / clock divider 1 to %d\n", data);
1380      break;
1381
1382   case 4:
1383      /* rom page select 1 + cru sel */
1384      if (data)
1385         hfdc_rom_offset |= 0x1000;
1386      else
1387         hfdc_rom_offset &= ~0x1000;
1388      cru_sel = data;
1389      break;
1390
1391   case 9:
1392   case 10:
1393   case 11:
1394   case 12:
1395   case 13:
1396   case 14:
1397   case 15:
1398   case 16:
1399   case 17:
1400   case 18:
1401   case 19:
1402   case 20:
1403   case 21:
1404   case 22:
1405   case 23:
1406      /* ram page select */
1407      if (data)
1408         hfdc_ram_offset[(offset-9)/5] |= 0x400 << ((offset-9)%5);
1409      else
1410         hfdc_ram_offset[(offset-9)/5] &= ~(0x400 << ((offset-9)%5));
1411      break;
1412   }
1413//  printf("hfdc cru write bit %d = %d\n", offset, data);
1414}
1415
1416
1417/*
1418    read a byte in disk DSR space
1419    HFDC manual, p. 44
1420    Memory map as seen by the 99/4A PEB
1421
1422    0x4000 - 0x4fbf one of four possible ROM pages
1423    0x4fc0 - 0x4fcf tape select
1424    0x4fd0 - 0x4fdf disk controller select
1425    0x4fe0 - 0x4fff time chip select
1426
1427    0x5000 - 0x53ff static RAM page 0x10
1428    0x5400 - 0x57ff static RAM page any of 32 pages
1429    0x5800 - 0x5bff static RAM page any of 32 pages
1430    0x5c00 - 0x5fff static RAM page any of 32 pages
1431*/
1432static  READ8_HANDLER(hfdc_mem_r)
1433{
1434   running_device *device = space->machine->device("smc92x4");
1435
1436   if (offset >= 0x0000 && offset <= 0x0fbf)
1437   {
1438      /* dsr ROM */
1439      return ti99_disk_DSR[hfdc_rom_offset+offset];
1440   }
1441
1442   if (offset >= 0xfc0 && offset <= 0x0fcf)
1443   {
1444      /* tape controller */
1445      logerror("99_dsk: Tape support not available (access to offset %04x)\n", offset);
1446      return 0;
1447   }
1448
1449   if (offset >= 0xfd0 && offset <= 0x0fdf)
1450        {
1451                /* Disk controller. Note that the odd addresses are ignored and
1452                   the addresses used for the write ports are also masked away
1453                   since the write operations in the ti99 system are always
1454                   accompanied by read operations before.
1455                */
1456                if ((offset & 3) == 0x00)
1457                {
1458                  return smc92x4_r(device, (offset>>2)&1);
1459                }
1460                else return 0;
1461        }
1462   if (offset >= 0x0fe0 && offset <= 0x0fff)
1463   {
1464      /* Real-time clock. Again, ignore odd addresses. */
1465      if ((offset & 1) == 0)
1466      {
1467         running_device *clock = space->machine->device("mm58274c_floppy");
1468         return mm58274c_r(clock, (offset - 0x0fe0) >> 1);
1469      }
1470      else return 0;
1471   }
1472
1473   if (offset >= 0x1000 && offset <= 0x13ff)
1474   {
1475      /* ram page >08 (hfdc manual says >10) */
1476      return hfdc_ram[0x2000+(offset-0x1000)];
1477   }
1478
1479   /* The remaining space is ram with mapper:
1480       1400, 1800, 1c00 are the three banks; get the pointer
1481       plus the offset within the bank
1482    */
1483   return hfdc_ram[hfdc_ram_offset[(offset-0x1400) >> 10] + (offset & 0x3ff)];
1484}
1485
1486/*
1487    write a byte in disk DSR space
1488*/
1489static WRITE8_HANDLER(hfdc_mem_w)
1490{
1491   running_device *diskcnt = space->machine->device("smc92x4");
1492
1493   if (offset >= 0x0000 && offset <= 0x0fbf)
1494   {
1495      /* dsr ROM */
1496      logerror("99_dsk: Writing to HFDC ROM ignored (access to offset %04x)\n", offset);
1497      return;
1498   }
1499
1500   if (offset >= 0xfc0 && offset <= 0x0fcf)
1501   {
1502      /* tape controller */
1503      logerror("99_dsk: Tape support not available (access to offset %04x)\n", offset);
1504      return;
1505   }
1506
1507   if (offset >= 0xfd0 && offset <= 0x0fdf)
1508        {
1509                /* Disk controller. Note that the odd addresses are ignored. */
1510                if ((offset & 3) == 0x02)   /* 0x0fd2 and 0x0fd6 */
1511                {
1512                  smc92x4_w(diskcnt, (offset>>2)&1, data);
1513                }
1514                return;
1515        }
1516
1517   if (offset >= 0x0fe0 && offset <= 0x0fff)
1518   {
1519      /* Real-time clock. Again, ignore odd addresses. */
1520      if ((offset & 1) == 0)
1521      {
1522         running_device *clock = space->machine->device("mm58274c_floppy");
1523         mm58274c_w(clock, (offset - 0x0fe0) >> 1, data);
1524      }
1525      return;
1526   }
1527
1528   if (offset >= 0x1000 && offset <= 0x13ff)
1529   {
1530      /* ram page >08 (hfdc manual says >10) */
1531      hfdc_ram[0x2000+(offset-0x1000)] = data;
1532      return;
1533   }
1534
1535   /* The remaining space is ram with mapper:
1536       1400, 1800, 1c00 are the three banks; get the pointer
1537       plus the offset within the bank
1538    */
1539//  if ((offset&0x0f)==0) printf("\n");
1540//  printf("%02x ", data);
1541
1542   hfdc_ram[hfdc_ram_offset[(offset-0x1400) >> 10] + (offset & 0x3ff)] = data;
1543}
src/mess/machine/99_dsk.h
r9500r9501
1#ifndef TI99_DSK_H_
2#define TI99_DSK_H_
3
4#include "wd17xx.h"
5#include "smc92x4.h"
6#include "formats/flopimg.h"
7
8/* Note: this currently mirrors the flag in ti99_4x.h */
9#define HAS_99CCFDC 0
10
11void ti99_floppy_controllers_init_all(running_machine *machine);
12void ti99_fdc_reset(running_machine *machine);
13#if HAS_99CCFDC
14void ti99_ccfdc_reset(running_machine *machine);
15#endif
16void ti99_bwg_reset(running_machine *machine);
17void ti99_hfdc_reset(running_machine *machine);
18
19int ti99_image_in_80_track_drive(void);
20
21extern const wd17xx_interface ti99_wd17xx_interface;
22extern const smc92x4_interface ti99_smc92x4_interface;
23
24#endif /* TI99_DSK_H_ */
src/mess/machine/99_usbsm.c
r9500r9501
1/*
2    Thierry Nouspikel's USB-SmartMedia card emulation
3
4    This card features three USB ports (two host and one device) and a
5    SmartMedia interface.  The original prototype was designed by Thierry
6    Nouspikel, and its description was published in 2003; a small series of
7    approximately 100 printed-circuit boards was ordered shortly afterwards
8    by various TI users.
9
10    The specs have been published in <http://www.nouspikel.com/ti99/usb.html>.
11
12    The USB interface uses a Philips ISP1161A USB controller that supports
13    USB 2.0 full-speed (12 Mbit/s) and low-speed (1.5 Mbit/s) I/O (high speed
14    (480 Mbits/sec) is not supported, but it is hardly a problem since TI99 is
15    too slow to take advantage from high speed).  The SmartMedia interface uses
16    a few TTL buffers.  The card also includes an 8MByte StrataFlash FEEPROM
17    and 1MByte of SRAM for DSR use.
18
19    TODO:
20    * Test SmartMedia support
21    * Implement USB controller and assorted USB devices
22    * Save DSR FEEPROM to disk
23
24    Raphael Nabet, 2004.
25*/
26
27#include "emu.h"
28#include "ti99_4x.h"
29#include "devices/ti99_peb.h"
30#include "99_usbsm.h"
31#include "strata.h"
32#include "smartmed.h"
33
34
35/* prototypes */
36static int usbsm_cru_r(running_machine *machine, int offset);
37static void usbsm_cru_w(running_machine *machine, int offset, int data);
38static  READ8_HANDLER(usbsm_mem_r);
39static WRITE8_HANDLER(usbsm_mem_w);
40static UINT16 usbsm_mem_16_r(address_space* space,offs_t offset);
41static void usbsm_mem_16_w(address_space* space,offs_t offset, UINT16 data);
42
43/* pointer to the SRAM area */
44static UINT16 *ti99_usbsm_RAM;
45static int feeprom_page;
46static int sram_page;
47
48static running_device *expansion_box;
49
50static const ti99_peb_card_handlers_t usbsm_handlers =
51{
52   usbsm_cru_r,
53   usbsm_cru_w,
54   usbsm_mem_r,
55   usbsm_mem_w
56};
57
58static UINT8 cru_register;
59enum
60{
61   cru_reg_io_regs_enable = 0x02,
62   cru_reg_int_enable = 0x04,
63   cru_reg_sm_enable = 0x08,
64   cru_reg_feeprom_write_enable = 0x10
65};
66static int input_latch, output_latch;
67
68/* The card has a 8-bit->16-bit demultiplexer that can be set-up to assume
69either that the LSByte of a word is accessed first or that the MSByte of a word
70is accessed first.  The former is true with ti-99/4(a), the latter with the
71tms9995 CPU used by Geneve and ti-99/8. */
72static int tms9995_mode;
73
74/*
75    Initilaizes USB-SmartMedia card, set up handlers
76*/
77void ti99_usbsm_init(running_machine *machine)
78{
79   ti99_usbsm_RAM = auto_alloc_array(machine, UINT16, 0x100000/2);
80   strataflash_init(machine, 0);
81}
82
83/*
84    Reset USB-SmartMedia card, set up handlers
85*/
86int ti99_usbsm_reset(running_machine *machine, int in_tms9995_mode)
87{
88   expansion_box = machine->device("per_exp_box");
89   ti99_peb_set_card_handlers(expansion_box, 0x1600, & usbsm_handlers);
90
91   feeprom_page = 0;
92   sram_page = 0;
93   cru_register = 0;
94
95   tms9995_mode = in_tms9995_mode;
96
97   return 0;
98}
99
100/*
101    Read USB-SmartMedia CRU interface
102*/
103static int usbsm_cru_r(running_machine *machine, int offset)
104{
105   int reply = 0;
106   running_device *smartmedia =machine->device("smartmedia");
107   offset &= 3;
108
109   switch (offset)
110   {
111   case 0:
112      /*
113            bit
114            0   >1x00   0: USB Host controller requests interrupt.
115            1   >1x02   0: USB Device controller requests interrupt.
116            2   >1x04   1: USB Host controller suspended.
117            3   >1x06   1: USB Device controller suspended.
118            4   >1x08   0: Strata FEEPROM is busy.
119                        1: Strata FEEPROM is ready.
120            5   >1x0A   0: SmartMedia card is busy.
121                        1: SmartMedia card absent or ready.
122            6   >1x0C   0: No SmartMedia card present.
123                        1: A card is in the connector.
124            7   >1x0E   0: SmartMedia card is protected.
125                        1: Card absent or not protected.
126         */
127      reply = 0x33;
128      if (! smartmedia_present(smartmedia))
129         reply |= 0xc0;
130      else if (! smartmedia_protected(smartmedia))
131         reply |= 0x80;
132      break;
133   }
134
135   return reply;
136}
137
138/*
139    Write USB-SmartMedia CRU interface
140*/
141static void usbsm_cru_w(running_machine *machine, int offset, int data)
142{
143   offset &= 31;
144
145
146   switch (offset)
147   {
148   case 0:         /* turn card on: handled by core */
149      break;
150
151   case 1:         /* enable I/O registers */
152   case 2:         /* enable interrupts */
153   case 3:         /* enable SmartMedia card */
154   case 4:         /* enable FEEPROM writes (and disable reads) */
155      if (data)
156         cru_register |= 1 << offset;
157      else
158         cru_register &= ~ (1 << offset);
159      break;
160   case 5:         /* FEEPROM page */
161   case 6:
162   case 7:
163   case 8:
164   case 9:
165   case 10:
166   case 11:
167   case 12:
168   case 13:
169   case 14:
170   case 15:
171      if (data)
172         feeprom_page |= 1 << (offset-5);
173      else
174         feeprom_page &= ~ (1 << (offset-5));
175      break;
176
177   case 16:      /* SRAM page */
178   case 17:
179   case 18:
180   case 19:
181   case 20:
182   case 21:
183   case 22:
184   case 23:
185      if (data)
186         sram_page |= 1 << (offset-16);
187      else
188         sram_page &= ~ (1 << (offset-16));
189      break;
190   }
191}
192
193/*
194    read a byte in USB-SmartMedia DSR space
195*/
196static READ8_HANDLER(usbsm_mem_r)
197{
198   if (tms9995_mode ? (!(offset & 1)) : (offset & 1))
199   {   /* first read triggers 16-bit read cycle */
200      input_latch = usbsm_mem_16_r(space,offset >> 1);
201   }
202
203   /* return latched input */
204   return (offset & 1) ? input_latch : (input_latch >> 8);
205}
206
207/*
208    write a byte in USB-SmartMedia DSR space
209*/
210static WRITE8_HANDLER(usbsm_mem_w)
211{
212   /* latch write */
213   if (offset & 1)
214      output_latch = (output_latch & 0xff00) | data;
215   else
216      output_latch = (output_latch & 0x00ff) | (data << 8);
217
218   if (tms9995_mode ? (offset & 1) : (!(offset & 1)))
219   {   /* second write triggers 16-bit write cycle */
220      usbsm_mem_16_w(space,offset >> 1, output_latch);
221   }
222}
223
224/*
225    demultiplexed read in USB-SmartMedia DSR space
226*/
227static UINT16 usbsm_mem_16_r(address_space* space,offs_t offset)
228{
229   UINT16 reply = 0;
230   running_device *smartmedia =space->machine->device("smartmedia");
231   if (offset < 0x800)
232   {   /* 0x4000-0x4fff range */
233      if ((cru_register & cru_reg_io_regs_enable) && (offset >= 0x7f8))
234      {   /* SmartMedia interface */
235         if (offset == 0)
236            reply = smartmedia_data_r(smartmedia) << 8;
237      }
238      else
239      {   /* FEEPROM */
240         if (! (cru_register & cru_reg_feeprom_write_enable))
241            reply = strataflash_16_r(0, offset);
242      }
243   }
244   else
245   {   /* 0x5000-0x5fff range */
246      if ((cru_register & cru_reg_io_regs_enable) && (offset >= 0xff8))
247      {   /* USB controller */
248      }
249      else
250      {   /* SRAM */
251         reply = ti99_usbsm_RAM[sram_page*0x800+(offset-0x800)];
252      }
253   }
254
255   return reply;
256}
257
258/*
259    demultiplexed write in USB-SmartMedia DSR space
260*/
261static void usbsm_mem_16_w(address_space* space,offs_t offset, UINT16 data)
262{
263   running_device *smartmedia =space->machine->device("smartmedia");
264   if (offset < 0x800)
265   {   /* 0x4000-0x4fff range */
266      if ((cru_register & cru_reg_io_regs_enable) && (offset >= 0x7f8))
267      {   /* SmartMedia interface */
268         switch (offset & 3)
269         {
270         case 0:
271            smartmedia_data_w(smartmedia, data >> 8);
272            break;
273         case 1:
274            smartmedia_address_w(smartmedia, data >> 8);
275            break;
276         case 2:
277            smartmedia_command_w(smartmedia, data >> 8);
278            break;
279         case 3:
280            /* bogus, don't use(?) */
281            break;
282         }
283      }
284      else
285      {   /* FEEPROM */
286         if (cru_register & cru_reg_feeprom_write_enable)
287            strataflash_16_w(0, offset, data);
288      }
289   }
290   else
291   {   /* 0x5000-0x5fff range */
292      if ((cru_register & cru_reg_io_regs_enable) && (offset >= 0xff8))
293      {   /* USB controller */
294      }
295      else
296      {   /* SRAM */
297         ti99_usbsm_RAM[sram_page*0x800+(offset-0x800)] = data;
298      }
299   }
300}
src/mess/machine/99_usbsm.h
r9500r9501
1#if 0
2DEVICE_START( ti99_sm );
3DEVICE_IMAGE_LOAD( ti99_sm );
4DEVICE_IMAGE_UNLOAD( ti99_sm );
5#endif
6
7void ti99_usbsm_init(running_machine *machine);
8int ti99_usbsm_reset(running_machine *machine, int in_tms9995_mode);
src/mess/machine/99_peb.c
r9500r9501
1/************************************************************************
2
3    Obsoleted by devices/ti99_peb.c
4
5************************************************************************/
6
7/*
8    Peripheral expansion bus support.
9
10    The ti-99/4, ti-99/4a, ti computer 99/8, myarc geneve, and snug sgcpu
11    99/4p systems all feature a bus connector that enables the connection of
12    extension cards.  (Although the hexbus is the preferred bus to add
13    additional peripherals to a ti-99/8, ti-99/8 is believed to be compatible
14    with the older PEB system.)  In the case of the TI consoles, this bus
15    connector is located on the right side of the console.
16
17    While a few extension cards connect to the side bus connector of the
18    ti-99/4(a) console directly, most extension cards were designed to be
19    inserted in a PEB instead.  The PEB (Peripheral Expansion Box) is a big box
20    with an alimentation, a few bus drivers, and several card slots, that
21    connects to the ti-99/4(a) side port.  The reason for using a PEB is that
22    daisy-chaining many modules caused the system to be unreliable due to the
23    noise produced by the successive contacts.  (As a matter of fact, TI
24    initially released most of its extension cards as side bus units, but when
25    the design proved to be unreliable, the PEB was introduced.  The TI speech
26    synthesizer was the only TI extension that remained on the side bus after
27    the introduction of the PEB, probably because TI wanted the speech
28    synthesizer to be a cheap extension, and the PEB was not cheap.)
29
30    The third-party myarc geneve and snug sgcpu computers are actually cards
31    to be inserted into a PEB: they have a PC keyboard connector, and replace
32    the original ti-99 console completely.
33
34    Each expansion card is assigned to one of 16 CRU address ranges.
35    I appended the names of known TI peripherals that use each port (I appended
36    '???' when I don't know what the peripheral is :-) ).
37    * 0x1000-0x10FE "For test equipment use on production line"
38    * 0x1100-0x11FE disk controller
39    * 0x1200-0x12FE modem???
40    * 0x1300-0x13FE RS232 1&2, PIO 1
41    * 0x1400-0x14FE unassigned
42    * 0x1500-0x15FE RS232 3&4, PIO 2
43    * 0x1600-0x16FE unassigned
44    * 0x1700-0x17FE hex-bus (prototypes)
45    * 0x1800-0x18FE thermal printer (early peripheral)
46    * 0x1900-0x19FE EPROM programmer??? (Mezzanine board in July 1981's TI99/7
47        prototype)
48    * 0x1A00-0x1AFE unassigned
49    * 0x1B00-0x1BFE TI GPL debugger card
50    * 0x1C00-0x1CFE Video Controller Card (Possibly the weirdest device.  This
51        card is connected to the video output of the computer, to a VCR, and a
52        video monitor.  It can control the VCR, connect the display to either
53        VCR output or computer video output, and it can read or save binary
54        data to video tape.  I think it can act as a genlock interface (i.e.
55        TMS9918 transparent background shows the video signal), too, but I am
56        not sure about this.)
57    * 0x1D00-0x1DFE IEEE 488 Controller Card ('intelligent' parallel bus,
58        schematics on ftp.whtech.com)
59    * 0x1E00-0x1EFE unassigned
60    * 0x1F00-0x1FFE P-code card (part of a complete development system)
61
62    The ti-99/8 implements 16 extra ports:
63    * 0x2000-0x26ff and 0x2800-0x2fff: reserved for future expansion?
64    * 0x2700-0x27ff: internal DSR
65
66    The snug sgcpu 99/4p implements 12 extra ports:
67    * 0x0400-0x0eff: free
68    * 0x0f00-0x0fff: internal DSR
69
70    Known mappings for 3rd party cards:
71    * Horizon RAMdisk: any ports from 0 to 7 (port 0 is most common).
72    * Myarc 128k/512k (RAM and DSR ROM): port 0 (0x1000-0x11FE)
73    * Corcomp 512k (RAM and DSR ROM): port unknown
74    * Super AMS 128k/512k: port 14 (0x1E00-0x1EFE)
75    * Foundation 128k/512k: port 14 (0x1E00-0x1EFE)
76    * Gram Karte: any port (0-15)
77    * EVPC (video card): 0x1400-0x14FE
78    * HSGPL (GROM replacement): 0x1B00-0x1BFE
79
80    Of course, these devices additionally need some support routines, and
81    possibly memory-mapped I/O registers.  To do so, memory range 0x4000-5FFF
82    is shared by all cards.  The system enables each card as needed by writing
83    a 1 to the first CRU bit: when this happens the card can safely enable its
84    ROM, RAM, memory-mapped registers, etc.  Provided the ROM uses the proper
85    ROM header, the system will recognize and call peripheral I/O functions,
86    interrupt service routines, and startup routines.  (All these routines are
87    generally called DSR = Device Service Routine.)
88
89    Also, the cards can trigger level-1 ("INTA") interrupts.  A LOAD interrupt
90    is present on the side port of the ti-99/4(a), too, but it was never used
91    by TI, AFAIK.  Also, an interrupt line called "INTB" is found on several
92    cards built by TI, but it is not connected: I am quite unsure whether it
93    was intended to be connected to the LOAD line, to the INT2 line of TMS9985,
94    or it was only to be used with the ti-99/4(a) development system running on
95    a TI990/10.  This is not the only unused feature: cards built by TI support
96    sensing of an interrupt status register and 19-bit addressing, even though
97    ti-99/4(A) does not take advantage of these features.  TI documentation
98    tells that some of these features are "defined by the Personal Computer PCC
99    at Texas Instrument", which is not very explicit (What on earth does "PCC"
100    stand for?).  Maybe it refers to the ti-99/4(a) development system running
101    on a TI990/10, or to the ti-99/7 and ti-99/8 prototypes.
102
103    Note that I use 8-bit RAM handlers.  Obviously, using 16-bit handlers would
104    be equivalent and faster on a ti-99/4(a), but we need to interface the
105    extension cards not only to the ti-99/4(a), but to the geneve and ti-99/8
106    emulators as well.
107*/
108
109#include "emu.h"
110#include "99_peb.h"
111
112/* TRUE if we are using the snug sgcpu 99/4p 16-bit extensions */
113static int has_16bit_peb;
114
115/* handlers for each of 16 slots + 16 extra slots for ti-99/8 */
116static ti99_peb_card_handlers_t expansion_ports[16+16];
117
118enum width_t {
119   width_8bit = 0,
120   width_16bit
121};
122/* expansion card structure for the snug sgcpu 99/4p system, which supports
123dynamical 16-bit accesses (TI did not design this!) */
124typedef struct ti99_4p_peb_card_handlers_t
125{
126   cru_read_handler cru_read;      /* card CRU read handler */
127   cru_write_handler cru_write;   /* card CRU handler */
128
129   width_t width;
130   union
131   {
132      struct
133      {
134         read8_space_func mem_read;      /* card mem read handler (8 bits) */
135         write8_space_func mem_write;   /* card mem write handler (8 bits) */
136      } width_8bit;
137      struct
138      {
139         read16_space_func mem_read;   /* card mem read handler (16 bits) */
140         write16_space_func mem_write;   /* card mem write handler (16 bits) */
141      } width_16bit;
142   } w;
143} ti99_4p_peb_card_handlers_t;
144
145/* handlers for each of 28 slots */
146static ti99_4p_peb_card_handlers_t ti99_4p_expansion_ports[28];
147
148/* index of the currently active card (-1 if none) */
149static int active_card;
150
151/* index of the currently active card, overridden by the mapper */
152static int active_card_tmp;
153
154/* Mapper override. */
155static int mapper_override;
156
157/* ila: inta status register (not actually used on ti-99/4(a), but nevertheless
158present) */
159static int ila;
160/* ilb: intb status register (completely pointless on ti-99/4(a), as neither
161INTB nor SENILB are connected; OTOH, INTB can trigger interrupts on a Geneve,
162and snug sgcpu 99/4p can sense ILB) */
163static int ilb;
164
165/* only used by the snug sgcpu 99/4p */
166static int senila, senilb;
167
168/* hack to simulate TMS9900 byte write */
169static int tmp_buffer;
170
171/* inta/intb handlers */
172static void (*inta_callback)(running_machine *machine, int state);
173static void (*intb_callback)(running_machine *machine, int state);
174
175
176/*
177    Initializes the expansion card handlers
178
179*/
180void ti99_peb_init()
181{
182   memset(expansion_ports, 0, sizeof(expansion_ports));
183   memset(ti99_4p_expansion_ports, 0, sizeof(ti99_4p_expansion_ports));
184}
185
186
187/*
188    Resets the expansion card handlers
189
190    in_has_16bit_peb: TRUE if we are using the snug sgcpu 99/4p 16-bit
191        extensions
192    in_inta_callback: callback called when the state of INTA changes (may be
193        NULL)
194    in_intb_callback: callback called when the state of INTB changes (may be
195        NULL)
196*/
197void ti99_peb_reset(int in_has_16bit_peb, void (*in_inta_callback)(running_machine *machine, int state), void (*in_intb_callback)(running_machine *machine, int state))
198{
199   has_16bit_peb = in_has_16bit_peb;
200   inta_callback = in_inta_callback;
201   intb_callback = in_intb_callback;
202
203   active_card = -1;
204   active_card_tmp = -1;
205
206   mapper_override = FALSE; // for ti99_4p
207
208   ila = 0;
209   ilb = 0;
210}
211
212/*
213    Sets the handlers for one expansion port (normal 8-bit card)
214
215    cru_base: CRU base address (any of 0x1000, 0x1100, 0x1200, ..., 0x1F00)
216        (snug sgcpu 99/4p accepts 0x0400, ..., 0x1F00, ti-99/8 accepts 0x1000,
217        ..., 0x2F00)
218    handler: handler structure for the given card
219*/
220void ti99_peb_set_card_handlers(int cru_base, const ti99_peb_card_handlers_t *handler)
221{
222   int port;
223
224   if (cru_base & 0xff)
225      return;
226
227   if (has_16bit_peb)
228   {
229      port = (cru_base - 0x0400) >> 8;
230
231      if ((port>=0) && (port<28))
232      {
233         ti99_4p_expansion_ports[port].cru_read = handler->cru_read;
234         ti99_4p_expansion_ports[port].cru_write = handler->cru_write;
235         ti99_4p_expansion_ports[port].width = width_8bit;
236         ti99_4p_expansion_ports[port].w.width_8bit.mem_read = handler->mem_read;
237         ti99_4p_expansion_ports[port].w.width_8bit.mem_write = handler->mem_write;
238      }
239   }
240   else
241   {
242      port = (cru_base - 0x1000) >> 8;
243
244      if ((port>=0) && (port</*16*/32))
245      {
246         expansion_ports[port] = *handler;
247      }
248   }
249}
250
251/*
252    Sets the handlers for one expansion port (special 16-bit card for snug
253    sgcpu 99/4p)
254
255    cru_base: CRU base address (any of 0x1000, 0x1100, 0x1200, ..., 0x1F00)
256        (snug sgcpu 99/4p accepts 0x0400, ..., 0x1F00, ti-99/8 accepts 0x1000,
257        ..., 0x2F00)
258    handler: handler structure for the given card
259*/
260void ti99_peb_set_16bit_card_handlers(int cru_base, const ti99_peb_16bit_card_handlers_t *handler)
261{
262   int port;
263
264   if (cru_base & 0xff)
265      return;
266
267   if (has_16bit_peb)
268   {
269      port = (cru_base - 0x0400) >> 8;
270
271      if ((port>=0) && (port<28))
272      {
273         ti99_4p_expansion_ports[port].cru_read = handler->cru_read;
274         ti99_4p_expansion_ports[port].cru_write = handler->cru_write;
275         ti99_4p_expansion_ports[port].width = width_16bit;
276         ti99_4p_expansion_ports[port].w.width_16bit.mem_read = handler->mem_read;
277         ti99_4p_expansion_ports[port].w.width_16bit.mem_write = handler->mem_write;
278      }
279   }
280}
281
282/*
283    Update ila status register and assert or clear INTA interrupt line
284    accordingly.
285
286    bit: bit number ([0,7] for original INTA register, [8,15] are extra
287        "virtual" bits for devices that assert the INTA line without setting a
288        bit of the ILA register)
289    state: 1 to assert bit, 0 to clear
290*/
291void ti99_peb_set_ila_bit(running_machine *machine, int bit, int state)
292{
293   if (state)
294   {
295      ila |= 1 << bit;
296      if (inta_callback)
297         (*inta_callback)(machine, 1);
298   }
299   else
300   {
301      ila &= ~(1 << bit);
302      if ((! ila) && inta_callback)
303         (*inta_callback)(machine, 0);
304   }
305}
306
307/*
308    Update ilb status register and assert or clear INTB interrupt line
309    accordingly.
310
311    bit: bit number ([0,7] for original INTAB register, [8,15] are extra
312        "virtual" bits for devices that assert the INTB line without setting a
313        bit of the ILB register)
314    state: 1 to assert bit, 0 to clear
315*/
316void ti99_peb_set_ilb_bit(running_machine *machine, int bit, int state)
317{
318   if (state)
319   {
320      ilb |= 1 << bit;
321      if (intb_callback)
322         (*intb_callback)(machine, 1);
323   }
324   else
325   {
326      ilb &= ~(1 << bit);
327      if ((! ilb) && intb_callback)
328         (*intb_callback)(machine, 0);
329   }
330}
331
332
333/*
334    Read CRU in range >1000->1ffe (>800->fff) (ti-99/4(a))
335*/
336READ8_HANDLER ( ti99_4x_peb_cru_r )
337{
338   int port;
339   cru_read_handler handler;
340   int reply;
341
342   port = (offset & 0x00f0) >> 4;
343   handler = expansion_ports[port].cru_read;
344
345   reply = (handler) ? (*handler)(space->machine, offset & 0xf) : 0;
346
347   return reply;
348}
349
350/*
351    Write CRU in range >1000->1ffe (>800->fff) (ti-99/4(a))
352*/
353WRITE8_HANDLER ( ti99_4x_peb_cru_w )
354{
355   int port;
356   cru_write_handler handler;
357
358   port = (offset & 0x0780) >> 7;
359   handler = expansion_ports[port].cru_write;
360
361   if (handler)
362      (*handler)(space->machine, offset & 0x7f, data);
363
364   /* expansion card enable? */
365   if ((offset & 0x7f) == 0)
366   {
367      if (data & 1)
368      {
369         /* enable */
370         active_card = port;
371      }
372      else
373      {
374         if (port == active_card)   /* geez... who cares? */
375         {
376            active_card = -1;         /* no port selected */
377         }
378      }
379   }
380}
381
382/*
383    Read mem in range >4000->5ffe (ti-99/4(a))
384*/
385READ16_HANDLER ( ti99_4x_peb_r )
386{
387   int reply = 0;
388   read8_space_func handler;
389
390   cpu_adjust_icount(space->machine->firstcpu,-4);
391
392   if (active_card != -1)
393   {
394      handler = expansion_ports[active_card].mem_read;
395      if (handler)
396      {
397         reply = (*handler)(space, (offset << 1) + 1);
398         reply |= ((unsigned) (*handler)(space, offset << 1)) << 8;
399      }
400   }
401//  printf("[%04x:%04x] = %04x\n", (active_card<<8)+0x1000, (offset<<1)+0x4000, reply);
402
403   return tmp_buffer = reply;
404}
405
406/*
407    Write mem in range >4000->5ffe (ti-99/4(a))
408*/
409WRITE16_HANDLER ( ti99_4x_peb_w )
410{
411   write8_space_func handler;
412
413   cpu_adjust_icount(space->machine->firstcpu,-4);
414
415   /* simulate byte write */
416   data = (tmp_buffer & ~mem_mask) | (data & mem_mask);
417
418   if (active_card != -1)
419   {
420      handler = expansion_ports[active_card].mem_write;
421      if (handler)
422      {
423         (*handler)(space, (offset << 1) + 1, data & 0xff);
424         (*handler)(space, offset << 1, (data >> 8) & 0xff);
425      }
426   }
427}
428
429
430/*
431    Read CRU in range >1000->1ffe (>800->fff) (Geneve)
432*/
433 READ8_HANDLER ( geneve_peb_cru_r )
434{
435   int port;
436   cru_read_handler handler;
437   int reply;
438
439   port = (offset & 0x00f0) >> 4;
440   handler = expansion_ports[port].cru_read;
441
442   reply = (handler) ? (*handler)(space->machine, offset & 0xf) : 0;
443
444   return reply;
445}
446
447/*
448    Write CRU in range >1000->1ffe (>800->fff) (Geneve)
449*/
450WRITE8_HANDLER ( geneve_peb_cru_w )
451{
452   int port;
453   cru_write_handler handler;
454
455   port = (offset & 0x0780) >> 7;
456   handler = expansion_ports[port].cru_write;
457
458   if (handler)
459      (*handler)(space->machine, offset & 0x7f, data);
460
461   /* expansion card enable? */
462   if ((offset & 0x7f) == 0)
463   {
464      if (data & 1)
465      {
466         /* enable */
467         active_card = port;
468      }
469      else
470      {
471         if (port == active_card)   /* geez... who cares? */
472         {
473            active_card = -1;         /* no port selected */
474         }
475      }
476   }
477}
478
479/*
480    Read mem in range >4000->5fff (Geneve)
481*/
482 READ8_HANDLER ( geneve_peb_r )
483{
484   int reply = 0;
485   read8_space_func handler;
486
487   cpu_adjust_icount(space->machine->firstcpu,-8);
488
489   if (active_card != -1)
490   {
491      handler = expansion_ports[active_card].mem_read;
492      if (handler)
493         reply = (*handler)(space, offset);
494   }
495
496   return reply;
497}
498
499/*
500    Write mem in range >4000->5fff (Geneve)
501*/
502WRITE8_HANDLER ( geneve_peb_w )
503{
504   write8_space_func handler;
505
506   cpu_adjust_icount(space->machine->firstcpu,-8);
507
508   if (active_card != -1)
509   {
510      handler = expansion_ports[active_card].mem_write;
511      if (handler)
512         (*handler)(space, offset, data);
513   }
514}
515
516/*
517    Read CRU in range >1000->2ffe (>0800->17ff) (ti-99/8)
518*/
519 READ8_HANDLER ( ti99_8_peb_cru_r )
520{
521   int port;
522   cru_read_handler handler;
523   int reply;
524
525   port = (offset & 0x01f0) >> 4;
526   handler = expansion_ports[port].cru_read;
527
528   reply = (handler) ? (*handler)(space->machine, offset & 0xf) : 0;
529
530   return reply;
531}
532
533/*
534    Write CRU in range >1000->2ffe (>0800->17ff) (ti-99/8)
535*/
536WRITE8_HANDLER ( ti99_8_peb_cru_w )
537{
538   int port;
539   cru_write_handler handler;
540
541   port = (offset & 0x0f80) >> 7;
542   handler = expansion_ports[port].cru_write;
543
544   if (handler)
545      (*handler)(space->machine, offset & 0x7f, data);
546
547   /* expansion card enable? */
548   if ((offset & 0x7f) == 0)
549   {
550      if (data & 1)
551      {
552         /* enable */
553         active_card = port;
554      }
555      else
556      {
557         if (port == active_card)   /* geez... who cares? */
558         {
559            active_card = -1;         /* no port selected */
560         }
561      }
562   }
563}
564
565/*
566    Read mem in range >4000->5fff (ti-99/8)
567*/
568 READ8_HANDLER ( ti99_8_peb_r )
569{
570   int reply = 0;
571   read8_space_func handler;
572
573   cpu_adjust_icount(space->machine->firstcpu,-4);
574
575   if (active_card != -1)
576   {
577      handler = expansion_ports[active_card].mem_read;
578      if (handler)
579         reply = (*handler)(space, offset);
580   }
581
582   return reply;
583}
584
585/*
586    Write mem in range >4000->5fff (ti-99/8)
587*/
588WRITE8_HANDLER ( ti99_8_peb_w )
589{
590   write8_space_func handler;
591
592   cpu_adjust_icount(space->machine->firstcpu,-4);
593
594   if (active_card != -1)
595   {
596      handler = expansion_ports[active_card].mem_write;
597      if (handler)
598         (*handler)(space, offset, data);
599   }
600}
601
602/*
603    Read CRU in range >0400->1ffe (>200->fff) (snug sgcpu 99/4p)
604*/
605READ8_HANDLER( ti99_4p_peb_cru_r )
606{
607   int port;
608   cru_read_handler handler;
609   int reply;
610
611   port = offset >> 4;
612   handler = ti99_4p_expansion_ports[port].cru_read;
613
614   reply = (handler) ? (*handler)(space->machine, offset & 0xf) : 0;
615
616   return reply;
617}
618
619/*
620    Write CRU in range >0400->1ffe (>200->fff) (snug sgcpu 99/4p)
621*/
622WRITE8_HANDLER( ti99_4p_peb_cru_w )
623{
624   int port;
625   cru_write_handler handler;
626
627   int cru_address = (offset + 0x200)<<1;
628
629   port = offset >> 7;
630   handler = ti99_4p_expansion_ports[port].cru_write;
631
632   if (handler)
633      (*handler)(space->machine, offset & 0x7f, data);
634
635   /* expansion card enable? */
636   if ((cru_address & 0xfe) == 0)
637   {
638      if (data & 1)
639      {
640         /* enable */
641         if (cru_address == 0x1e00)
642         {
643            // The internal mapper has precedence over the external bus.
644            // It may be turned on although there is another device currently turned on
645            active_card_tmp = active_card;
646            mapper_override = TRUE;
647         }
648         active_card = port;
649      }
650      else
651      {
652         if ((cru_address == 0x1e00) && mapper_override)
653         {
654            active_card = active_card_tmp;
655            mapper_override = FALSE;
656         }
657         else
658         {
659            if (port == active_card)   /* geez... who cares? */
660            {
661               active_card = -1;         /* no port selected */
662            }
663         }
664      }
665   }
666}
667
668/*
669    Read mem in range >4000->5ffe (snug sgcpu 99/4p)
670*/
671READ16_HANDLER ( ti99_4p_peb_r )
672{
673   int reply = 0;
674   read8_space_func handler;
675   read16_space_func handler16;
676
677
678   if (active_card == -1)
679      cpu_adjust_icount(space->machine->firstcpu,-4);   /* ??? */
680   else
681   {
682
683      if (ti99_4p_expansion_ports[active_card].width == width_8bit)
684      {
685         cpu_adjust_icount(space->machine->firstcpu,-4);
686
687         handler = ti99_4p_expansion_ports[active_card].w.width_8bit.mem_read;
688         if (handler)
689         {
690            reply = (*handler)(space, (offset << 1) + 1);
691            reply |= ((unsigned) (*handler)(space, offset << 1)) << 8;
692         }
693      }
694      else
695      {
696         cpu_adjust_icount(space->machine->firstcpu,-1);   /* ??? */
697
698         handler16 = ti99_4p_expansion_ports[active_card].w.width_16bit.mem_read;
699         if (handler16)
700            reply = (*handler16)(space, offset, /*mem_mask*/0xffff);
701      }
702   }
703
704   if (senila || senilb)
705   {
706      if ((active_card != -1) || (senila && senilb))
707         /* ah, the smell of burnt silicon... */
708         logerror("<Scrrrrr>: your computer has just burnt (maybe).\n");
709
710      if (senila)
711         reply = (ila & 0xff) | (ila << 8);
712      else if (senilb)
713         reply = (ilb & 0xff) | (ilb << 8);
714   }
715
716//  printf("[%04x:%04x] = %04x\n", (active_card<<8)+0x400, (offset<<1)+0x4000, reply);
717   return tmp_buffer = reply;
718}
719
720/*
721    Write mem in range >4000->5ffe (snug sgcpu 99/4p)
722*/
723WRITE16_HANDLER ( ti99_4p_peb_w )
724{
725   write8_space_func handler;
726   write16_space_func handler16;
727
728   if (active_card == -1)
729      cpu_adjust_icount(space->machine->firstcpu,-4);   /* ??? */
730   else
731   {
732      /* simulate byte write */
733      data = (tmp_buffer & ~mem_mask) | (data & mem_mask);
734
735      if (ti99_4p_expansion_ports[active_card].width == width_8bit)
736      {
737         cpu_adjust_icount(space->machine->firstcpu,-4);
738
739         handler = ti99_4p_expansion_ports[active_card].w.width_8bit.mem_write;
740         if (handler)
741         {
742            (*handler)(space, (offset << 1) + 1, data & 0xff);
743            (*handler)(space, offset << 1, (data >> 8) & 0xff);
744         }
745      }
746      else
747      {
748         cpu_adjust_icount(space->machine->firstcpu,-1);   /* ??? */
749
750         handler16 = ti99_4p_expansion_ports[active_card].w.width_16bit.mem_write;
751         if (handler16)
752            (*handler16)(space, offset, data, /*mem_mask*/0xffff);
753      }
754   }
755}
756
757/*
758    Set the state of the SENILA line (snug sgcpu 99/4p)
759*/
760void ti99_4p_peb_set_senila(int state)
761{
762   senila = (state != 0);
763}
764
765/*
766    Set the state of the SENILB line (snug sgcpu 99/4p)
767*/
768void ti99_4p_peb_set_senilb(int state)
769{
770   senilb = (state != 0);
771}
src/mess/machine/99_peb.h
r9500r9501
1/************************************************************************
2
3    Obsoleted by devices/ti99_peb.h
4
5************************************************************************/
6
7/*
8    header file for machine/99_peb.c
9*/
10
11/*
12    prototype for CRU handlers in expansion system
13*/
14typedef int (*cru_read_handler)(running_machine *machine, int offset);
15typedef void (*cru_write_handler)(running_machine *machine, int offset, int data);
16
17/*
18    Descriptor for TI peripheral expansion cards (8-bit bus)
19*/
20typedef struct ti99_peb_card_handlers_t
21{
22   cru_read_handler cru_read;      /* card CRU read handler */
23   cru_write_handler cru_write;   /* card CRU handler */
24
25   read8_space_func mem_read;      /* card mem read handler (8 bits) */
26   write8_space_func mem_write;   /* card mem write handler (8 bits) */
27} ti99_peb_card_handlers_t;
28
29/*
30    Descriptor for 16-bit peripheral expansion cards designed for the snug
31    sgcpu 99/4p system.  (These cards were not designed by TI, TI always
32    regarded the ti-99 as an 8-bit system.)
33*/
34typedef struct ti99_peb_16bit_card_handlers_t
35{
36   cru_read_handler cru_read;      /* card CRU read handler */
37   cru_write_handler cru_write;   /* card CRU handler */
38
39   read16_space_func mem_read;      /* card mem read handler (16 bits) */
40   write16_space_func mem_write;      /* card mem write handler (16 bits) */
41} ti99_peb_16bit_card_handlers_t;
42
43/* masks for ila and ilb */
44enum
45{
46   /* bits from actual ILA register */
47   inta_rs232_1_bit = 7-0,
48   inta_rs232_2_bit = 7-1,
49   inta_rs232_3_bit = 7-4,
50   inta_rs232_4_bit = 7-5,
51
52   /* extra "virtual" bits for devices that assert the INTA line without
53    setting a bit of the ILA register */
54   inta_ide_bit     = 8,
55   inta_ide_clk_bit = 9,
56
57   /* bits from actual ILB register */
58   intb_fdc_bit     = 7-0,
59   intb_ieee488_bit = 7-1
60};
61
62void ti99_peb_init(void);
63void ti99_peb_reset(int in_has_16bit_peb, void (*in_inta_callback)(running_machine *machine, int state), void (*in_intb_callback)(running_machine *machine, int state));
64
65void ti99_peb_set_card_handlers(int cru_base, const ti99_peb_card_handlers_t *handler);
66void ti99_peb_set_16bit_card_handlers(int cru_base, const ti99_peb_16bit_card_handlers_t *handler);
67void ti99_peb_set_ila_bit(running_machine *machine, int bit, int state);
68void ti99_peb_set_ilb_bit(running_machine *machine, int bit, int state);
69
70 READ8_HANDLER ( ti99_4x_peb_cru_r );
71WRITE8_HANDLER ( ti99_4x_peb_cru_w );
72READ16_HANDLER ( ti99_4x_peb_r );
73WRITE16_HANDLER ( ti99_4x_peb_w );
74
75 READ8_HANDLER ( geneve_peb_cru_r );
76WRITE8_HANDLER ( geneve_peb_cru_w );
77 READ8_HANDLER ( geneve_peb_r );
78WRITE8_HANDLER ( geneve_peb_w );
79
80 READ8_HANDLER ( ti99_8_peb_cru_r );
81WRITE8_HANDLER ( ti99_8_peb_cru_w );
82 READ8_HANDLER ( ti99_8_peb_r );
83WRITE8_HANDLER ( ti99_8_peb_w );
84
85 READ8_HANDLER ( ti99_4p_peb_cru_r );
86WRITE8_HANDLER ( ti99_4p_peb_cru_w );
87READ16_HANDLER ( ti99_4p_peb_r );
88WRITE16_HANDLER ( ti99_4p_peb_w );
89
90void ti99_4p_peb_set_senila(int state);
91void ti99_4p_peb_set_senilb(int state);
src/mess/machine/994x_ser.c
r9500r9501
1/*
2    TI99/4(a) RS232 card emulation
3
4    This card features two RS232C ports (which share one single connector) and
5    one centronics-like fully bi-directional parallel port.  Each TI99 system
6    can accomodate two such RS232 cards (provided a resistor is moved in one of
7    the cards to change its CRU base address from >1300 to >1500), for a total
8    of four RS232 ports and two parallel ports.
9
10    The card is fairly simple: two 9902 chips handle one serial port each, two
11    unidirectional TTL buffers handle the PIO data bus, there is extra TTL for
12    address decoding and CRU interface, and a DSR ROM.
13
14    References:
15    <http://www.nouspikel.com/ti99/rs232c.htm>: great description of the
16        hardware and software aspects.
17    <ftp://ftp.whtech.com//datasheets/TMS9902A.max>: tms9902a datasheet
18    <ftp://ftp.whtech.com//datasheets/Hardware manuals/ti rs232 card schematic.max>
19
20    Raphael Nabet, 2003.
21*/
22
23#include "emu.h"
24#include "ti99_4x.h"
25#include "devices/ti99_peb.h"
26#include "tms9902.h"
27#include "994x_ser.h"
28
29#include "machine/tms9902.h"
30
31/* prototypes */
32static int rs232_cru_r(running_machine *machine, int offset);
33static void rs232_cru_w(running_machine *machine, int offset, int data);
34static READ8_HANDLER(rs232_mem_r);
35static WRITE8_HANDLER(rs232_mem_w);
36
37/* pointer to the rs232 ROM data */
38static UINT8 *rs232_DSR;
39
40typedef struct _pio_t pio_t;
41struct _pio_t
42{
43   int pio_direction;   // a.k.a. PIOOC pio in output mode if 0
44   int pio_handshakeout;
45   int pio_handshakein;
46   int pio_spareout;
47   int pio_sparein;
48   int flag0;   // spare
49   int cts1;   // a.k.a. flag1
50   int cts2;   // a.k.a. flag2
51   int led;      // a.k.a. flag3
52   int pio_out_buffer;
53   int pio_in_buffer;
54   int pio_readable;
55   int pio_writable;
56   int pio_write;     // 1 if image is to be written to
57};
58
59typedef struct _card_t card_t;
60struct _card_t
61{
62   int i;
63};
64
65INLINE pio_t *get_safe_token_pio(running_device *device)
66{
67   assert(device != NULL);
68   assert(device->type() == TI99_4_PIO);
69
70   return (pio_t *)downcast<legacy_device_base *>(device)->token();
71}
72
73static const ti99_peb_card_handlers_t rs232_handlers =
74{
75   rs232_cru_r,
76   rs232_cru_w,
77   rs232_mem_r,
78   rs232_mem_w
79};
80
81/*
82    Initialize pio unit and open image
83*/
84static DEVICE_IMAGE_LOAD( ti99_4_pio )
85{
86   pio_t *pio = get_safe_token_pio(image);
87   /* tell whether the image is writable */
88   pio->pio_readable = ! image.has_been_created();
89   /* tell whether the image is writable */
90   pio->pio_writable = image.is_writable();
91
92   if (pio->pio_write && pio->pio_writable)
93      pio->pio_handshakein = 0;   /* receiver ready */
94   else
95      pio->pio_handshakein = 1;
96
97   return IMAGE_INIT_PASS;
98}
99
100/*
101    close a pio image
102*/
103static DEVICE_IMAGE_UNLOAD( ti99_4_pio )
104{
105   pio_t *pio = get_safe_token_pio(image);
106   pio->pio_writable = 0;
107   pio->pio_handshakein = 1;   /* receiver not ready */
108   pio->pio_sparein = 0;
109}
110
111static DEVICE_START( ti99_4_pio )
112{
113}
114
115static DEVICE_RESET( ti99_4_pio )
116{
117   pio_t *pio = get_safe_token_pio(device);
118   pio->pio_direction = 0;
119   pio->pio_handshakeout = 0;
120   pio->pio_spareout = 0;
121   pio->flag0 = 0;
122   pio->cts1 = 0;
123   pio->cts2 = 0;
124   pio->led = 0;
125   pio->pio_write = 1;
126}
127/*
128    Initialize rs232 unit and open image
129*/
130static DEVICE_IMAGE_LOAD( ti99_4_rs232 )
131{
132   running_device *tms9902 = NULL;
133
134   if (strcmp(image.device().tag(), "rs232:port0")) {
135      tms9902 = image.device().machine->device("rs232:tms9902_0");
136   }
137   if (strcmp(image.device().tag(), "rs232:port1")) {
138      tms9902 = image.device().machine->device("rs232:tms9902_1");
139   }
140
141   if (image)
142   {
143      tms9902_set_cts(tms9902, 1);
144      tms9902_set_dsr(tms9902, 1);
145   }
146   else
147   {
148      tms9902_set_cts(tms9902, 0);
149      tms9902_set_dsr(tms9902, 0);
150   }
151
152   return IMAGE_INIT_PASS;
153}
154
155/*
156    close a rs232 image
157*/
158static DEVICE_IMAGE_UNLOAD( ti99_4_rs232 )
159{
160}
161
162/*
163    Initializes rs232 card, set up handlers
164*/
165static DEVICE_START( ti99_4_rs232 )
166{
167   rs232_DSR = memory_region(device->machine, region_dsr) + offset_rs232_dsr;
168}
169
170/*
171    Reset rs232 card, set up handlers
172*/
173static DEVICE_RESET( ti99_4_rs232 )
174{
175   rs232_DSR = memory_region(device->machine, region_dsr) + offset_rs232_dsr;
176   running_device *box = device->machine->device("per_exp_box");
177   ti99_peb_set_card_handlers(box, 0x1300, & rs232_handlers);
178}
179
180static READ8_DEVICE_HANDLER(ti99_4_pio_r)
181{
182   pio_t *pio = get_safe_token_pio(device);
183   UINT8 reply = 0x00;
184   if (pio->pio_direction)
185      reply |= 0x02;
186   if (pio->pio_handshakein)
187      reply |= 0x04;
188   if (pio->pio_sparein)
189      reply |= 0x08;
190   if (pio->flag0)
191      reply |= 0x10;
192   if (pio->cts1)
193      reply |= 0x20;
194   if (pio->cts2)
195      reply |= 0x40;
196   if (pio->led)
197      reply |= 0x80;
198   return reply;
199}
200
201static READ8_DEVICE_HANDLER(ti99_4_pio_buf_r)
202{
203   pio_t *pio = get_safe_token_pio(device);
204   return pio->pio_direction ? pio->pio_in_buffer : pio->pio_out_buffer;
205}
206
207static WRITE8_DEVICE_HANDLER(ti99_4_pio_buf_w)
208{
209   pio_t *pio = get_safe_token_pio(device);
210   pio->pio_out_buffer = data;
211}
212
213static WRITE8_DEVICE_HANDLER(ti99_4_pio_w)
214{
215   pio_t *pio = get_safe_token_pio(device);
216   device_image_interface *image = dynamic_cast<device_image_interface *>(device);
217   switch (offset & 7)
218   {
219      case 0:
220         /* WRITE to rs232 card enable bit (bit 0) */
221         /* handled in xxx_peb_cru_w() */
222         break;
223
224      case 1:
225         pio->pio_direction = data;
226         break;
227
228      case 2:
229         if (data != pio->pio_handshakeout)
230         {
231            pio->pio_handshakeout = data;
232            if (pio->pio_write && pio->pio_writable && (! pio->pio_direction))
233            {   /* PIO in output mode */
234               if (!pio->pio_handshakeout)
235               {   /* write data strobe */
236                  /* write data and acknowledge */
237                  UINT8 buf = pio->pio_out_buffer;
238                  if (image->fwrite(&buf, 1))
239                     pio->pio_handshakein = 1;
240               }
241               else
242               {
243                  /* end strobe */
244                  /* we can write some data: set receiver ready */
245                  pio->pio_handshakein = 0;
246               }
247            }
248            if ((!pio->pio_write) && pio->pio_readable /*&& pio_direction*/)
249            {   /* PIO in input mode */
250               if (!pio->pio_handshakeout)
251               {   /* receiver ready */
252                  /* send data and strobe */
253                  UINT8 buf;
254                  if (image->fread(&buf, 1))
255                     pio->pio_in_buffer = buf;
256                  pio->pio_handshakein = 0;
257               }
258               else
259               {
260                  /* data acknowledge */
261                  /* we can send some data: set transmitter ready */
262                  pio->pio_handshakein = 1;
263               }
264            }
265         }
266         break;
267
268      case 3:
269         pio->pio_spareout = data;
270         break;
271
272      case 4:
273         pio->flag0 = data;
274         break;
275
276      case 5:
277         pio->cts1 = data;
278         break;
279
280      case 6:
281         pio->cts2 = data;
282         break;
283
284      case 7:
285         pio->led = data;
286         break;
287   }
288}
289/*
290    Read rs232 card CRU interface
291
292    bit 0: always 0
293    ...
294*/
295static int rs232_cru_r(running_machine *machine, int offset)
296{
297   int reply;
298
299   switch (offset >> 2)
300   {
301   case 0:
302      /* custom buffer */
303      switch (offset)
304      {
305      case 0:
306         reply = ti99_4_pio_r(machine->device("rs232:pio"), offset);
307         break;
308
309      default:
310         reply = 0;
311         break;
312      }
313      break;
314
315   case 1:
316      /* first 9902 */
317      reply = tms9902_cru_r(machine->device("rs232:tms9902_0"), offset);
318      break;
319
320   case 2:
321      /* second 9902 */
322      reply = tms9902_cru_r(machine->device("rs232:tms9902_1"), offset);
323      break;
324
325   default:
326      /* NOP */
327      reply = 0;   /* ??? */
328      break;
329   }
330
331   return reply;
332}
333
334/*
335    Write rs232 card CRU interface
336*/
337static void rs232_cru_w(running_machine *machine, int offset, int data)
338{
339   switch (offset >> 5)
340   {
341   case 0:
342      /* custom buffer */
343      ti99_4_pio_w(machine->device("rs232:pio"), offset, data);
344      break;
345
346   case 1:
347      /* first 9902 */
348      tms9902_cru_w(machine->device("rs232:tms9902_0"), offset, data);
349      break;
350
351   case 2:
352      /* second 9902 */
353      tms9902_cru_w(machine->device("rs232:tms9902_1"), offset, data);
354      break;
355
356   default:
357      /* NOP */
358      break;
359   }
360}
361
362
363/*
364    read a byte in rs232 DSR space
365*/
366static  READ8_HANDLER(rs232_mem_r)
367{
368   int reply;
369
370   if (offset < 0x1000)
371   {
372      /* DSR ROM */
373      reply = rs232_DSR[offset];
374   }
375   else
376   {
377      /* PIO */
378      reply = ti99_4_pio_buf_r(space->machine->device("rs232:pio"), offset);
379   }
380
381   return reply;
382}
383
384/*
385    write a byte in rs232 DSR space
386*/
387static WRITE8_HANDLER(rs232_mem_w)
388{
389   if (offset >= 0x1000)
390   {
391      /* PIO */
392      ti99_4_pio_buf_w(space->machine->device("rs232:pio"), offset, data);
393   }
394   else
395   {
396      /* DSR ROM: do nothing */
397   }
398}
399
400/*
401    rs232 interrupt handler
402*/
403static TMS9902_INT_CALLBACK( int_callback_0 )
404{
405   running_device *box = device->machine->device("per_exp_box");
406   ti99_peb_set_ila_bit(box, inta_rs232_1_bit, INT);
407}
408static TMS9902_INT_CALLBACK( int_callback_1 )
409{
410   running_device *box = device->machine->device("per_exp_box");
411   ti99_peb_set_ila_bit(box, inta_rs232_2_bit, INT);
412}
413
414static TMS9902_XMIT_CALLBACK( xmit_callback_0 )
415{
416   UINT8 buf = data;
417   device_image_interface *rs232_fp = dynamic_cast<device_image_interface *>(device->machine->device("rs232:port0"));
418
419   if (rs232_fp)
420      rs232_fp->fwrite(&buf, 1);
421}
422
423static TMS9902_XMIT_CALLBACK( xmit_callback_1 )
424{
425   UINT8 buf = data;
426   device_image_interface *rs232_fp = dynamic_cast<device_image_interface *>(device->machine->device("rs232:port1"));
427
428   if (rs232_fp)
429      rs232_fp->fwrite(&buf, 1);
430}
431static const tms9902_interface tms9902_params_0 =
432{
433   3000000.,            /* clock rate (3MHz) */
434   int_callback_0,         /* called when interrupt pin state changes */
435   NULL,//rts_callback,            /* called when Request To Send pin state changes */
436   NULL,//brk_callback,            /* called when BReaK state changes */
437   xmit_callback_0         /* called when a character is transmitted */
438};
439
440static const tms9902_interface tms9902_params_1 =
441{
442   3000000.,            /* clock rate (3MHz) */
443   int_callback_1,         /* called when interrupt pin state changes */
444   NULL,//rts_callback,            /* called when Request To Send pin state changes */
445   NULL,//brk_callback,            /* called when BReaK state changes */
446   xmit_callback_1         /* called when a character is transmitted */
447};
448
449DEVICE_GET_INFO( ti99_4_rs232 )
450{
451   switch ( state )
452   {
453      case DEVINFO_INT_TOKEN_BYTES:            info->i = sizeof(card_t);                     break;
454      case DEVINFO_INT_INLINE_CONFIG_BYTES:      info->i = 0;                        break;
455      case DEVINFO_INT_IMAGE_TYPE:               info->i = IO_SERIAL;                                      break;
456      case DEVINFO_INT_IMAGE_READABLE:            info->i = 1;                                               break;
457      case DEVINFO_INT_IMAGE_WRITEABLE:         info->i = 1;                                               break;
458      case DEVINFO_INT_IMAGE_CREATABLE:          info->i = 1;                                               break;
459
460      case DEVINFO_FCT_START:                      info->start = DEVICE_START_NAME( ti99_4_rs232 );              break;
461      case DEVINFO_FCT_RESET:                  info->reset = DEVICE_RESET_NAME( ti99_4_rs232 );         break;
462      case DEVINFO_FCT_IMAGE_LOAD:              info->f = (genf *) DEVICE_IMAGE_LOAD_NAME( ti99_4_rs232 );    break;
463      case DEVINFO_FCT_IMAGE_UNLOAD:              info->f = (genf *) DEVICE_IMAGE_UNLOAD_NAME(ti99_4_rs232 );  break;
464      case DEVINFO_STR_NAME:                      strcpy( info->s, "TI99 RS232 port");                            break;
465      case DEVINFO_STR_FAMILY:                    strcpy(info->s, "TI99 RS232 port");                            break;
466      case DEVINFO_STR_IMAGE_FILE_EXTENSIONS:       strcpy(info->s, "");                                           break;
467      case DEVINFO_STR_VERSION:                  strcpy(info->s, "1.0");                              break;
468      case DEVINFO_STR_SOURCE_FILE:               strcpy(info->s, __FILE__);                           break;
469      case DEVINFO_STR_CREDITS:                  strcpy(info->s, "Copyright the MESS Team");       break;
470   }
471}
472
473DECLARE_LEGACY_IMAGE_DEVICE(TI99_4_RS232, ti99_4_rs232);
474DEFINE_LEGACY_IMAGE_DEVICE(TI99_4_RS232, ti99_4_rs232);
475
476#define MDRV_TI99_4_RS232_ADD(_tag) \
477   MDRV_DEVICE_ADD(_tag, TI99_4_RS232, 0)
478
479
480DEVICE_GET_INFO( ti99_4_pio )
481{
482   switch ( state )
483   {
484      case DEVINFO_INT_TOKEN_BYTES:            info->i = sizeof(pio_t);                     break;
485      case DEVINFO_INT_INLINE_CONFIG_BYTES:      info->i = 0;                        break;
486      case DEVINFO_INT_IMAGE_TYPE:               info->i = IO_PARALLEL;                                      break;
487      case DEVINFO_INT_IMAGE_READABLE:            info->i = 1;                                               break;
488      case DEVINFO_INT_IMAGE_WRITEABLE:         info->i = 1;                                               break;
489      case DEVINFO_INT_IMAGE_CREATABLE:          info->i = 1;                                               break;
490
491      case DEVINFO_FCT_START:                      info->start = DEVICE_START_NAME( ti99_4_pio );              break;
492      case DEVINFO_FCT_RESET:                  info->reset = DEVICE_RESET_NAME( ti99_4_pio );         break;
493      case DEVINFO_FCT_IMAGE_LOAD:              info->f = (genf *) DEVICE_IMAGE_LOAD_NAME( ti99_4_pio );    break;
494      case DEVINFO_FCT_IMAGE_UNLOAD:              info->f = (genf *) DEVICE_IMAGE_UNLOAD_NAME(ti99_4_pio );  break;
495      case DEVINFO_STR_NAME:                      strcpy( info->s, "TI99 PIO port");                            break;
496      case DEVINFO_STR_FAMILY:                    strcpy(info->s, "TI99 PIO port");                            break;
497      case DEVINFO_STR_IMAGE_FILE_EXTENSIONS:       strcpy(info->s, "");                                           break;
498      case DEVINFO_STR_VERSION:                  strcpy(info->s, "1.0");                              break;
499      case DEVINFO_STR_SOURCE_FILE:               strcpy(info->s, __FILE__);                           break;
500      case DEVINFO_STR_CREDITS:                  strcpy(info->s, "Copyright the MESS Team");       break;
501   }
502}
503
504
505DEFINE_LEGACY_IMAGE_DEVICE(TI99_4_PIO, ti99_4_pio);
506
507static MACHINE_CONFIG_FRAGMENT( ti99_4_rs232 )
508   MDRV_TMS9902_ADD("tms9902_0", tms9902_params_0)
509   MDRV_TMS9902_ADD("tms9902_1", tms9902_params_1)
510   MDRV_TI99_4_RS232_ADD("port0")
511   MDRV_TI99_4_RS232_ADD("port1")
512   MDRV_TI99_4_PIO_ADD("pio")
513MACHINE_CONFIG_END
514
515static DEVICE_START( ti99_4_rs232_card )
516{
517}
518
519static DEVICE_RESET( ti99_4_rs232_card )
520{
521}
522
523DEVICE_GET_INFO( ti99_4_rs232_card )
524{
525   switch ( state )
526   {
527      case DEVINFO_INT_TOKEN_BYTES:            info->i = sizeof(card_t);                     break;
528      case DEVINFO_INT_INLINE_CONFIG_BYTES:      info->i = 0;                        break;
529      case DEVINFO_FCT_START:                      info->start = DEVICE_START_NAME( ti99_4_rs232_card );              break;
530      case DEVINFO_FCT_RESET:                  info->reset = DEVICE_RESET_NAME( ti99_4_rs232_card );         break;
531
532      case DEVINFO_PTR_MACHINE_CONFIG:         info->machine_config = MACHINE_CONFIG_NAME(ti99_4_rs232);      break;
533      case DEVINFO_STR_NAME:                      strcpy( info->s, "TI99 RS232 card");                            break;
534      case DEVINFO_STR_FAMILY:                    strcpy(info->s, "TI99 RS232 card");                            break;
535      case DEVINFO_STR_VERSION:                  strcpy(info->s, "1.0");                              break;
536      case DEVINFO_STR_SOURCE_FILE:               strcpy(info->s, __FILE__);                           break;
537      case DEVINFO_STR_CREDITS:                  strcpy(info->s, "Copyright the MESS Team");       break;
538   }
539}
540
541DEFINE_LEGACY_DEVICE(TI99_4_RS232_CARD, ti99_4_rs232_card);
src/mess/machine/994x_ser.h
r9500r9501
1#ifndef __994X_SER_H__
2#define __994X_SER_H__
3
4DECLARE_LEGACY_IMAGE_DEVICE(TI99_4_PIO, ti99_4_pio);
5
6#define MDRV_TI99_4_PIO_ADD(_tag) \
7   MDRV_DEVICE_ADD(_tag, TI99_4_PIO, 0)
8
9/***************************************************************************
10    DEVICE CONFIGURATION MACROS
11***************************************************************************/
12
13DECLARE_LEGACY_DEVICE(TI99_4_RS232_CARD, ti99_4_rs232_card);
14
15#define MDRV_TI99_4_RS232_CARD_ADD(_tag) \
16   MDRV_DEVICE_ADD(_tag, TI99_4_RS232_CARD, 0)
17
18#endif /* __994X_SER_H__ */
19
src/mess/machine/geneve.c
r9500r9501
1/*
2    Machine code for Myarc Geneve.
3    Raphael Nabet, 2003.
4*/
5
6#include <math.h>
7#include "emu.h"
8#include "tms9901.h"
9#include "mm58274c.h"
10#include "video/v9938.h"
11#include "audio/spchroms.h"
12#include "ti99_4x.h"
13#include "includes/geneve.h"
14#include "devices/ti99_peb.h"
15#include "994x_ser.h"
16#include "99_dsk.h"
17#include "99_ide.h"
18#include "99_usbsm.h"
19
20#include "sound/tms5220.h"   /* for tms5220_set_variant() */
21#include "sound/sn76496.h"
22
23static void read_key_if_possible(running_machine *machine);
24static void poll_keyboard(running_machine *machine);
25static void poll_mouse(running_machine *machine);
26
27/*
28    pointers to memory areas
29*/
30/* pointer to boot ROM */
31static UINT8 *ROM_ptr;
32/* pointer to alternative boot ROM */
33static UINT8 *AROM_ptr;
34/* pointer to static RAM */
35static UINT8 *SRAM_ptr;
36/* pointer to dynamic RAM */
37static UINT8 *DRAM_ptr;
38
39/*
40    Configuration
41*/
42/* TRUE if speech synthesizer present */
43static char has_speech;
44
45/* TRUE if ide card present */
46static char has_ide;
47/* TRUE if rs232 card present */
48static char has_rs232;
49/* TRUE if genmod extension present */
50/*static char has_genmod;*/
51/* TRUE if usb-sm card present */
52static char has_usb_sm;
53
54/* keyboard interface */
55static int JoySel;
56enum
57{
58   KeyQueueSize = 256,
59   MaxKeyMessageLen = 10,
60   KeyAutoRepeatDelay = 30,
61   KeyAutoRepeatRate = 6
62};
63static UINT8 KeyQueue[KeyQueueSize];
64static int KeyQueueHead;
65static int KeyQueueLen;
66static int KeyInBuf;
67static int KeyReset;
68static UINT32 KeyStateSave[4];
69static int KeyNumLockState;
70static int KeyCtrlState;
71static int KeyAltState;
72static int KeyRealShiftState;
73static int KeyFakeShiftState;
74static int KeyFakeUnshiftState;
75static int KeyAutoRepeatKey;
76static int KeyAutoRepeatTimer;
77
78static running_device *expansion_box;
79
80/*
81    GROM support.
82
83    The Geneve does not include any GROM, but it features a simple GROM emulator.
84
85    One oddity is that, since the Geneve does not use a look-ahead buffer, GPL
86    data is always off one byte, i.e. GPL bytes 0, 1, 2... are stored in bytes
87    1, 2, 3... of pages >38->3f (byte 0 of page >38 is has GPL address >ffff).
88
89    I think that I have once read that the geneve GROM emulator does not
90    emulate wrap-around within a GROM, i.e. address >1fff is followed by >2000
91    (instead of >0000 with a real GROM).
92*/
93static struct
94{
95   unsigned int addr;
96   char raddr_LSB, waddr_LSB;
97} GPL_port;
98
99/*
100    Cartridge support
101
102    The Geneve does not have a cartridge port, but it has cartridge emulation.
103*/
104static int cartridge_page;
105
106
107static int mode_flags;
108
109static UINT8 page_lookup[8];
110
111enum
112{
113   mf_PAL         = 0x001,   /* bit 5 */
114   mf_keycaps      = 0x004,   /* bit 7 - exact meaning unknown */
115   mf_keyclock      = 0x008,   /* bit 8 */
116   mf_keyclear      = 0x010,   /* bit 9 */
117   mf_genevemode   = 0x020,   /* bit 10 */
118   mf_mapmode      = 0x040,   /* bit 11 */
119   mf_cartpaging   = 0x080,   /* bit 12 */
120   mf_cart6protect   = 0x100,   /* bit 13 */
121   mf_cart7protect   = 0x200,   /* bit 14 */
122   mf_waitstate   = 0x400      /* bit 15 - exact meaning unknown */
123};
124
125/* tms9995_ICount: used to implement memory waitstates (hack) */
126/* NPW 23-Feb-2004 - externs no longer needed because we now use cpu_adjust_icount(space->machine->device("maincpu"),) */
127
128enum
129{
130   BOOT_V09 = 0,
131   BOOT_V10 = 1
132};
133
134/*===========================================================================*/
135/*
136    General purpose code:
137    initialization, cart loading, etc.
138*/
139
140DRIVER_INIT( geneve )
141{
142   /*has_genmod = FALSE;*/
143}
144
145DRIVER_INIT( genmod )
146{
147   /*has_genmod = TRUE;*/
148}
149
150MACHINE_START( geneve )
151{
152   /* Initialize all. Actually, at this point, we don't know
153       how the switches are set. Later we use the configuration switches to
154       determine which one to use. */
155   ti99_floppy_controllers_init_all(machine);
156   ti99_ide_init(machine);
157   ti99_usbsm_init(machine);
158
159   /* set up RAM pointers */
160   ROM_ptr = memory_region(machine, "maincpu") + offset_rom_geneve;
161   AROM_ptr = memory_region(machine, "maincpu") + offset_altrom_geneve;
162   SRAM_ptr = memory_region(machine, "maincpu") + offset_sram_geneve;
163   DRAM_ptr = memory_region(machine, "maincpu") + offset_dram_geneve;
164}
165
166MACHINE_RESET( geneve )
167{
168   mode_flags = /*0*/mf_mapmode;
169   /* initialize page lookup */
170   memset(page_lookup, 0, sizeof(page_lookup));
171
172   /* Initialize GROMs */
173   memset(& GPL_port, 0, sizeof(GPL_port));
174
175   /* reset cartridge mapper */
176   cartridge_page = 0;
177
178   expansion_box = machine->device("per_exp_box");
179
180   v9938_reset(0);
181
182   /* clear keyboard interface state (probably overkill, but can't harm) */
183   JoySel = 0;
184   KeyQueueHead = KeyQueueLen = 0;
185   memset(KeyStateSave, 0, sizeof(KeyStateSave));
186   KeyNumLockState = 0;
187   KeyCtrlState = 0;
188   KeyAltState = 0;
189   KeyRealShiftState = 0;
190   KeyFakeShiftState = 0;
191   KeyFakeUnshiftState = 0;
192   KeyAutoRepeatKey = 0;
193   KeyInBuf = 0;
194   KeyReset = 1;
195
196   /* read config */
197   has_speech = input_port_read(machine, "SPEECH");
198   has_ide =  input_port_read(machine, "HDCTRL") & HD_IDE;
199   has_rs232 = input_port_read(machine, "SERIAL") & SERIAL_TI;
200   has_usb_sm = input_port_read(machine, "HDCTRL") & HD_USB;
201
202   /* set up optional expansion hardware */
203
204   if (has_speech)
205   {
206      static const spchroms_interface speech_intf = { region_speech_rom };
207      spchroms_config(machine, &speech_intf);
208   }
209
210   switch (input_port_read(machine, "DISKCTRL"))
211   {
212   case DISK_TIFDC:
213      ti99_fdc_reset(machine);
214      break;
215#if HAS_99CCFDC
216   case DISK_CC:
217      ti99_ccfdc_reset(machine);
218      break;
219#endif
220   case DISK_BWG:
221      ti99_bwg_reset(machine);
222      break;
223   case DISK_HFDC:
224      ti99_hfdc_reset(machine);
225      break;
226   case DISK_NONE:
227      break;
228   }
229
230   if (has_ide)
231   {
232      ti99_ide_reset(machine, TRUE);
233   }
234
235   if (has_usb_sm)
236      ti99_usbsm_reset(machine, TRUE);
237
238   /* reset CPU */
239   machine->device("maincpu")->reset();
240}
241
242/*
243    video initialization.
244*/
245VIDEO_START(geneve)
246{
247   VIDEO_START_CALL(generic_bitmapped);
248   v9938_init(machine, 0, *machine->primary_screen, machine->generic.tmpbitmap, MODEL_V9938, /*0x20000*/0x30000, tms9901_set_int2);   /* v38 with 128 kb of video RAM */
249}
250
251/*
252    scanline interrupt
253*/
254INTERRUPT_GEN( geneve_hblank_interrupt )
255{
256   static int line_count;
257   v9938_interrupt(device->machine, 0);
258   if (++line_count == 262)
259   {
260      line_count = 0;
261      poll_keyboard(device->machine);
262      poll_mouse(device->machine);
263   }
264}
265
266/*
267    inta is connected to both tms9901 IRQ1 line and to tms9995 INT4/EC line.
268*/
269void inta_callback(running_machine *machine, int state)
270{
271   tms9901_set_single_int(machine->device("tms9901"), 1, state);
272   cputag_set_input_line(machine, "maincpu", 1, state ? ASSERT_LINE : CLEAR_LINE);
273}
274
275/*
276    intb is connected to tms9901 IRQ12 line.
277*/
278void intb_callback(running_machine *machine, int state)
279{
280   tms9901_set_single_int(machine->device("tms9901"), 12, state);
281}
282
283
284/*===========================================================================*/
285#if 0
286#pragma mark -
287#pragma mark MEMORY HANDLERS
288#endif
289/*
290    Memory handlers.
291*/
292
293/*
294    TMS5200 speech chip read
295*/
296static  READ8_HANDLER ( geneve_speech_r )
297{
298   cpu_adjust_icount(space->machine->device("maincpu"),-8);      /* this is just a minimum, it can be more */
299
300   return tms5220_status_r(space->machine->device("tmc0285"), offset);
301}
302
303#if 0
304
305static void speech_kludge_callback(int dummy)
306{
307   if (! tms5220_readyq_r(space->machine->device("tmc0285")))
308   {
309      /* Weirdly enough, we are always seeing some problems even though
310        everything is working fine. */
311#if 0
312      attotime time_to_ready = double_to_attotime(tms5220_time_to_ready());
313      logerror("ti99/4a speech says aaargh!\n");
314      logerror("(time to ready: %f -> %d)\n", time_to_ready, (int) ceil(3000000*time_to_ready));
315#endif
316   }
317}
318
319#endif
320
321/*
322    TMS5200 speech chip write
323*/
324static WRITE8_HANDLER ( geneve_speech_w )
325{
326   cpu_adjust_icount(space->machine->device("maincpu"),-32*4);      /* this is just an approx. minimum, it can be much more */
327
328#if 1
329   /* the stupid design of the tms5220 core means that ready is cleared when
330    there are 15 bytes in FIFO.  It should be 16.  Of course, if it were the
331    case, we would need to store the value on the bus, which would be more
332    complex. */
333   if (! tms5220_readyq_r(space->machine->device("tmc0285")))
334   {
335      attotime time_to_ready = double_to_attotime(tms5220_time_to_ready(space->machine->device("tmc0285")));
336      int cycles_to_ready = space->machine->device<cpu_device>("maincpu")->attotime_to_cycles(time_to_ready);
337
338      logerror("time to ready: %f -> %d\n", attotime_to_double(time_to_ready), (int) cycles_to_ready);
339
340      cpu_adjust_icount(space->machine->device("maincpu"),-cycles_to_ready);
341      timer_set(space->machine, attotime_zero, NULL, 0, /*speech_kludge_callback*/NULL);
342   }
343#endif
344
345   tms5220_data_w(space->machine->device("tmc0285"), offset, data);
346}
347
348READ8_HANDLER ( geneve_r )
349{
350   int page;
351
352   /* 03-Apr-2007 - hack because this seems to be called on startup */
353   if (!DRAM_ptr)
354      return 0;
355
356   if (mode_flags & mf_genevemode)
357   {
358      /* geneve mode */
359      if ((offset >= 0xf100) && (offset < 0xf140))
360      {
361         /* memory-mapped registers */
362         /* VDP ports 2 & 3 and sound port are write-only */
363         switch (offset)
364         {
365         case 0xf100:
366         case 0xf108:      /* mirror? */
367            return v9938_0_vram_r(space, 0);
368
369         case 0xf102:
370         case 0xf10a:      /* mirror? */
371            return v9938_0_status_r(space, 0);
372
373         case 0xf110:
374         case 0xf111:
375         case 0xf112:
376         case 0xf113:
377         case 0xf114:
378         case 0xf115:
379         case 0xf116:
380         case 0xf117:
381            return page_lookup[offset-0xf110];
382
383         case 0xf118:
384            return KeyInBuf ? KeyQueue[KeyQueueHead] : 0;
385
386         case 0xf130:
387         case 0xf131:
388         case 0xf132:
389         case 0xf133:
390         case 0xf134:
391         case 0xf135:
392         case 0xf136:
393         case 0xf137:
394         case 0xf138:
395         case 0xf139:
396         case 0xf13a:
397         case 0xf13b:
398         case 0xf13c:
399         case 0xf13d:
400         case 0xf13e:
401         case 0xf13f:
402            return mm58274c_r(space->machine->device("mm58274c"), offset-0xf130);
403
404         default:
405            logerror("unmapped read offs=%d\n", (int) offset);
406            return 0;
407         }
408      }
409   }
410   else
411   {
412      /* ti99 mode */
413      if ((offset >= 0x8000) && (offset < 0x8020))
414      {
415         /* 0x8000-0x801f */
416         /* geneve memory-mapped registers */
417         switch (offset)
418         {
419         case 0x8000:
420         case 0x8001:
421         case 0x8002:
422         case 0x8003:
423         case 0x8004:
424         case 0x8005:
425         case 0x8006:
426         case 0x8007:
427            return page_lookup[offset-0x8000];
428
429         case 0x8008:
430            return KeyInBuf ? KeyQueue[KeyQueueHead] : 0;
431
432         case 0x8010:
433         case 0x8011:
434         case 0x8012:
435         case 0x8013:
436         case 0x8014:
437         case 0x8015:
438         case 0x8016:
439         case 0x8017:
440         case 0x8018:
441         case 0x8019:
442         case 0x801a:
443         case 0x801b:
444         case 0x801c:
445         case 0x801d:
446         case 0x801e:
447         case 0x801f:
448            return mm58274c_r(space->machine->device("mm58274c"), offset-0xf130);
449
450         default:
451            logerror("unmapped read offs=%d\n", (int) offset);
452            return 0;
453         }
454      }
455      else if ((offset >= 0x8400) && (offset < 0xa000))
456      {
457         /* 0x8400-0x9fff */
458         /* ti99 memory-mapped registers */
459         switch ((offset - 0x8000) >> 10)
460         {
461         case 2:
462            /* VDP read */
463            if (! (offset & 1))
464            {
465               if (offset & 2)
466               {   /* read VDP status */
467                  return v9938_0_status_r(space, 0);
468               }
469               else
470               {   /* read VDP RAM */
471                  return v9938_0_vram_r(space, 0);
472               }
473            }
474            return 0;
475
476         case 4:
477            /* speech read */
478            if ((! (offset & 1)) && has_speech)
479            {
480               return geneve_speech_r(space, 0);
481            }
482            return 0;
483
484         case 6:
485            /* GPL read */
486            if (! (offset & 1))
487            {
488               if (offset & 2)
489               {   /* read GPL address */
490                  int reply;
491
492                  GPL_port.waddr_LSB = FALSE;   /* right??? */
493
494                  if (GPL_port.raddr_LSB)
495                  {
496                     reply = GPL_port.addr & 0xff;
497                     GPL_port.raddr_LSB = FALSE;
498                  }
499                  else
500                  {
501                     reply = GPL_port.addr >> 8;
502                     GPL_port.raddr_LSB = TRUE;
503                  }
504                  return reply;
505               }
506               else
507               {   /* read GPL data */
508                  int reply;
509
510                  reply = DRAM_ptr[0x38*0x2000 + GPL_port.addr];
511                  GPL_port.addr = (GPL_port.addr + 1) & 0xffff;
512                  GPL_port.raddr_LSB = GPL_port.waddr_LSB = FALSE;
513
514                  return reply;
515               }
516            }
517            return 0;
518
519         default:
520            logerror("unmapped read offs=%d\n", (int) offset);
521            return 0;
522         }
523      }
524   }
525
526   page = offset >> 13;
527
528   if (! (mode_flags & mf_mapmode))
529   {
530      if ((mode_flags & mf_genevemode) || (page != 3))
531         page = page_lookup[page];
532      else
533         /* Cartridge page under ti99 emulation */
534         page = ((mode_flags & mf_cartpaging) || ! cartridge_page) ? 0x36 : 0x37;
535   }
536   else
537      page = page + 0xf0;
538
539   offset &= 0x1fff;
540
541   /* Although we could have 128K boot ROM (page f0...ff), the stock
542    Geneve only has 16K. The address is incompletely decoded, so page
543    f0 is mirrored on all even pages up to fe, and f1 is mirrored on
544    f3, f5, ... ff.
545    Currently, MESS is delivered with the 16K ROM only. So for the time
546    being, we won't lose much if we mask the page bits.
547    Michael Zapf, 2008-01-23
548    */
549   if (page > 0xf1) page &= 0xf1;
550
551   switch (page)
552   {
553   case 0xf0:
554   case 0xf1:
555      /* Boot ROM */
556      if (input_port_read(space->machine, "BOOTROM")==BOOT_V09)
557         return AROM_ptr[(page-0xf0)*0x2000 + offset];
558      else
559         return ROM_ptr[(page-0xf0)*0x2000 + offset];
560
561   case 0xe8:
562   case 0xe9:
563   case 0xea:
564   case 0xeb:
565   case 0xec:
566   case 0xed:
567   case 0xee:
568   case 0xef:
569      /* SRAM */
570      return SRAM_ptr[(page-0xe8)*0x2000 + offset];
571
572#if 0
573   case 0x7a:   /* mirror of 0xba??? */
574      return 0;
575#endif
576   case 0xba:
577      /* DSR space */
578      return geneve_peb_r(expansion_box, offset);
579
580   case 0xbc:
581      /* speech space */
582      if (has_speech)
583      {
584         if ((offset >= 0x1000) && (offset < 0x1400) && (! (offset & 1)))
585            return geneve_speech_r(space, 0);
586         else
587            return 0;
588      }
589
590   default:
591      /* DRAM */
592      return DRAM_ptr[page*0x2000 + offset];
593   }
594
595   logerror("unmapped read page=%d offs=%d\n", (int) page, (int) offset);
596   return 0;
597}
598
599WRITE8_HANDLER ( geneve_w )
600{
601   int page;
602
603   if (mode_flags & mf_genevemode)
604   {
605      /* geneve mode */
606      if ((offset >= 0xf100) && (offset < 0xf140))
607      {
608         /* memory-mapped registers */
609         /* VDP ports 2 & 3 and sound port are write-only */
610         switch (offset)
611         {
612         case 0xf100:
613         case 0xf108:      /* mirror? */
614            v9938_0_vram_w(space, 0, data);
615            return;
616
617         case 0xf102:
618         case 0xf10a:      /* mirror? */
619            v9938_0_command_w(space, 0, data);
620            return;
621
622         case 0xf104:
623         case 0xf10c:      /* mirror? */
624            v9938_0_palette_w(space, 0, data);
625            return;
626
627         case 0xf106:
628         case 0xf10e:      /* mirror? */
629            v9938_0_register_w(space, 0, data);
630            return;
631
632         case 0xf110:
633         case 0xf111:
634         case 0xf112:
635         case 0xf113:
636         case 0xf114:
637         case 0xf115:
638         case 0xf116:
639         case 0xf117:
640            page_lookup[offset-0xf110] = data;
641            return;
642
643#if 0
644         case 0xf118:  // read-only register???
645            key_buf = data;
646            return;
647#endif
648
649         case 0xf120:
650            sn76496_w(space->machine->device("sn76496"), 0, data);
651            break;
652
653         case 0xf130:
654         case 0xf131:
655         case 0xf132:
656         case 0xf133:
657         case 0xf134:
658         case 0xf135:
659         case 0xf136:
660         case 0xf137:
661         case 0xf138:
662         case 0xf139:
663         case 0xf13a:
664         case 0xf13b:
665         case 0xf13c:
666         case 0xf13d:
667         case 0xf13e:
668         case 0xf13f:
669            mm58274c_w(space->machine->device("mm58274c"), offset-0xf130, data);
670            return;
671
672         default:
673            logerror("unmapped write offs=%d data=%d\n", (int) offset, (int) data);
674            return;
675         }
676      }
677   }
678   else
679   {
680      /* ti99 mode */
681      if ((offset >= 0x8000) && (offset < 0x8020))
682      {
683         /* 0x8000-0x801f */
684         /* geneve memory-mapped registers */
685         switch (offset)
686         {
687         case 0x8000:
688         case 0x8001:
689         case 0x8002:
690         case 0x8003:
691         case 0x8004:
692         case 0x8005:
693         case 0x8006:
694         case 0x8007:
695            page_lookup[offset-0x8000] = data;
696            return;
697
698#if 0
699         case 0x8008:  // read-only register???
700            key_buf = data;
701            return
702#endif
703
704         case 0x8010:
705         case 0x8011:
706         case 0x8012:
707         case 0x8013:
708         case 0x8014:
709         case 0x8015:
710         case 0x8016:
711         case 0x8017:
712         case 0x8018:
713         case 0x8019:
714         case 0x801a:
715         case 0x801b:
716         case 0x801c:
717         case 0x801d:
718         case 0x801e:
719         case 0x801f:
720            mm58274c_w(space->machine->device("mm58274c"), offset-0xf130, data);
721            return;
722
723         default:
724            logerror("unmapped write offs=%d data=%d\n", (int) offset, (int) data);
725            return;
726         }
727      }
728      else if ((offset >= 0x8400) && (offset < 0xa000))
729      {
730         /* 0x8400-0x9fff */
731         /* ti99 memory-mapped registers */
732         switch ((offset - 0x8000) >> 10)
733         {
734         case 1:
735            /* sound write */
736            sn76496_w(space->machine->device("sn76496"), 0, data);
737            return;
738
739         case 3:
740            /* VDP write */
741            if (! (offset & 1))
742            {
743
744               switch ((offset >> 1) & 3)
745               {
746               case 0:
747                  /* write VDP RAM */
748                  v9938_0_vram_w(space, 0, data);
749                  break;
750               case 1:
751                  /* write VDP address */
752                  v9938_0_command_w(space, 0, data);
753                  break;
754               case 2:
755                  /* write palette */
756                  v9938_0_palette_w(space, 0, data);
757                  break;
758               case 3:
759                  /* write register */
760                  v9938_0_register_w(space, 0, data);
761                  break;
762               }
763            }
764            return;
765
766         case 5:
767            /* speech write */
768            if ((! (offset & 1)) && has_speech)
769            {
770               geneve_speech_w(space, 0, data);
771            }
772            return;
773
774         case 7:
775            /* GPL write */
776            if (! (offset & 1))
777            {
778               if (offset & 2)
779               {   /* write GPL address */
780                  GPL_port.raddr_LSB = FALSE;
781
782                  if (GPL_port.waddr_LSB)
783                  {
784                     GPL_port.addr = (GPL_port.addr & 0xFF00) | data;
785
786                     /* increment */
787                     GPL_port.addr = (GPL_port.addr + 1) & 0xffff;
788
789                     GPL_port.waddr_LSB = FALSE;
790                  }
791                  else
792                  {
793                     GPL_port.addr = ((int) data << 8) | (GPL_port.addr & 0xFF);
794
795                     GPL_port.waddr_LSB = TRUE;
796                  }
797               }
798               else
799               {   /* write GPL data: probably not implemented */
800                  GPL_port.addr = (GPL_port.addr + 1) & 0xffff;
801                  GPL_port.raddr_LSB = GPL_port.waddr_LSB = FALSE;
802               }
803            }
804            return;
805
806         default:
807            logerror("unmapped write offs=%d data=%d\n", (int) offset, (int) data);
808            return;
809         }
810      }
811   }
812
813   page = offset >> 13;
814
815   if (! (mode_flags & mf_mapmode))
816   {
817      if ((mode_flags & mf_genevemode) || (page != 3))
818         page = page_lookup[page];
819      else
820      {
821         /* Cartridge page under ti99 emulation */
822         if (! (mode_flags & mf_cartpaging))
823         {   /* bankswitching */
824            cartridge_page = (offset & 2) != 0;
825            return;
826         }
827         else
828         {
829            /* writing to (non-bankswitched) cart -> page 0x36 */
830            page = 0x36;
831            if ((offset < 0x7000) ? (! (mode_flags & mf_cart6protect)) : (! (mode_flags & mf_cart7protect)))
832            {
833               /* Trying to write a write-protected cartridge */
834               logerror("Ignoring write to a write-protected cartridge\n");
835               return;
836            }
837         }
838      }
839   }
840   else
841      page = page + 0xf0;
842
843   offset &= 0x1fff;
844
845   /* ROM is incompletely decoded. Pages f0, f2, f4 ... fe all map to the
846       first 8K Boot ROM; f1, ..., ff to the second 8K. See above. */
847   if (page > 0xf1) page &= 0xf1;
848
849   switch (page)
850   {
851   case 0xf0:
852   case 0xf1:
853      /* Boot ROM */
854      return;
855
856   case 0xe8:
857   case 0xe9:
858   case 0xea:
859   case 0xeb:
860   case 0xec:
861   case 0xed:
862   case 0xee:
863   case 0xef:
864      /* SRAM */
865      SRAM_ptr[(page-0xe8)*0x2000 + offset] = data;
866      return;
867
868#if 0
869   case 0x7a:   /* mirror of 0xba??? */
870      return;
871#endif
872   case 0xba:
873      /* DSR space */
874      geneve_peb_w(expansion_box, offset, data);
875      return;
876
877   case 0xbc:
878      /* speech space */
879      if (has_speech)
880      {
881         if ((offset >= 0x1400) && (offset < 0x1800) && (! (offset & 1)))
882            geneve_speech_w(space, 0, data);
883         return;
884      }
885
886   default:
887      /* DRAM */
888      DRAM_ptr[page*0x2000 + offset] = data;
889      return;
890   }
891
892   logerror("unmapped write page=%d offs=%d data=%d\n", (int) page, (int) offset, (int) data);
893   return;
894}
895
896
897/*===========================================================================*/
898#if 0
899#pragma mark -
900#pragma mark CRU HANDLERS
901#endif
902
903WRITE8_HANDLER ( geneve_peb_mode_cru_w )
904{
905   if ((offset >= /*0x770*/0x775) && (offset < 0x780))
906   {
907      int old_flags = mode_flags;
908
909      /* tms9995 user flags */
910      if (data)
911         mode_flags |= 1 << (offset - 0x775);
912      else
913         mode_flags &= ~(1 << (offset - 0x775));
914
915      if ((offset == 0x778) && data && (! (old_flags & mf_keyclock)))
916      {
917         /* set mf_keyclock */
918         read_key_if_possible(space->machine);
919      }
920      if (offset == 0x779)
921      {
922         if (data && (! (old_flags & mf_keyclear)))
923         {
924            /* set mf_keyclear: enable key input */
925            /* shift in new key immediately if possible */
926            read_key_if_possible(space->machine);
927         }
928         else if ((! data) && (old_flags & mf_keyclear))
929         {
930            /* clear mf_keyclear: clear key input */
931            if (KeyQueueLen)
932            {
933               KeyQueueHead = (KeyQueueHead + 1) % KeyQueueSize;
934               KeyQueueLen--;
935            }
936            /* clear keyboard interrupt */
937            tms9901_set_single_int(space->machine->device("tms9901"), 8, 0);
938            KeyInBuf = 0;
939         }
940      }
941   }
942
943   geneve_peb_cru_w(expansion_box, offset, data);
944}
945
946/*===========================================================================*/
947#if 0
948#pragma mark -
949#pragma mark KEYBOARD INTERFACE
950#endif
951
952static void read_key_if_possible(running_machine *machine)
953{
954   /* if keyboard reset is not asserted, and key clock is enabled, and key
955    buffer clear is disabled, and key queue is not empty. */
956   if ((! KeyReset) && (mode_flags & mf_keyclock) && (mode_flags & mf_keyclear) && KeyQueueLen)
957   {
958      tms9901_set_single_int(machine->device("tms9901"), 8, 1);
959      KeyInBuf = 1;
960   }
961}
962
963INLINE void post_in_KeyQueue(int keycode)
964{
965   KeyQueue[(KeyQueueHead+KeyQueueLen) % KeyQueueSize] = keycode;
966   KeyQueueLen++;
967}
968
969static void poll_keyboard(running_machine *machine)
970{
971   UINT32 keystate;
972   UINT32 key_transitions;
973   int i, j;
974   int keycode;
975   int pressed;
976   static const char *const keynames[] = { "KEY0", "KEY1", "KEY2", "KEY3", "KEY4", "KEY5", "KEY6", "KEY7" };
977
978   static const UINT8 keyboard_mf1_code[0xe] =
979   {
980      /* extended keys that are equivalent to non-extended keys */
981      0x1c,   /* keypad enter */
982      0x1d,   /* right control */
983      0x38,   /* alt gr */
984      /* extra codes are 0x5b for Left Windows, 0x5c for Right Windows, 0x5d
985        for Menu, 0x5e for power, 0x5f for sleep, 0x63 for wake, but I doubt
986        any Geneve program would take advantage of these. */
987
988      /* extended key that is equivalent to a non-extended key
989        with shift off */
990      0x35,   /* pad slash */
991
992      /* extended keys that are equivalent to non-extended keys
993        with numlock off */
994      0x47,   /* home */
995      0x48,   /* up */
996      0x49,   /* page up */
997      0x4b,   /* left */
998      0x4d,   /* right */
999      0x4f,   /* end */
1000      0x50,   /* down */
1001      0x51,   /* page down */
1002      0x52,   /* insert */
1003      0x53   /* delete */
1004   };
1005
1006
1007   if (KeyReset)
1008      return;
1009
1010   /* Poll keyboard */
1011   for (i = 0; (i < 4) && (KeyQueueLen <= (KeyQueueSize-MaxKeyMessageLen)); i++)
1012   {
1013      keystate = input_port_read(machine, keynames[2*i]) | (input_port_read(machine, keynames[2*i + 1]) << 16);
1014      key_transitions = keystate ^ KeyStateSave[i];
1015      if (key_transitions)
1016      {
1017         for (j = 0; (j < 32) && (KeyQueueLen <= (KeyQueueSize-MaxKeyMessageLen)); j++)
1018         {
1019            if ((key_transitions >> j) & 1)
1020            {
1021               keycode = (i << 5) | j;
1022               pressed = ((keystate >> j) & 1);
1023               if (pressed)
1024                  KeyStateSave[i] |= (1 << j);
1025               else
1026                  KeyStateSave[i] &= ~ (1 << j);
1027
1028               /* Update auto-repeat */
1029               if (pressed)
1030               {
1031                  KeyAutoRepeatKey = keycode;
1032                  KeyAutoRepeatTimer = KeyAutoRepeatDelay+1;
1033               }
1034               else /*if (keycode == KeyAutoRepeatKey)*/
1035                  KeyAutoRepeatKey = 0;
1036
1037               /* Release Fake Shift/Unshift if another key is pressed */
1038               /* We do so if a key is released, though it is actually
1039                    required only if it is a modifier key */
1040               /*if (pressed)*/
1041               {
1042                  if (KeyFakeShiftState)
1043                  {
1044                     /* Fake shift release */
1045                     post_in_KeyQueue(0xe0);
1046                     post_in_KeyQueue(0xaa);
1047                     KeyFakeShiftState = 0;
1048                  }
1049                  if (KeyFakeUnshiftState)
1050                  {
1051                     /* Fake shift press */
1052                     post_in_KeyQueue(0xe0);
1053                     post_in_KeyQueue(0x2a);
1054                     KeyFakeUnshiftState = 0;
1055                  }
1056               }
1057
1058               /* update shift and numlock state */
1059               if ((keycode == 0x2a) || (keycode == 0x36))
1060                  KeyRealShiftState = KeyRealShiftState + (pressed ? +1 : -1);
1061               if ((keycode == 0x1d) || (keycode == 0x61))
1062                  KeyCtrlState = KeyCtrlState + (pressed ? +1 : -1);
1063               if ((keycode == 0x38) || (keycode == 0x62))
1064                  KeyAltState = KeyAltState + (pressed ? +1 : -1);
1065               if ((keycode == 0x45) && pressed)
1066                  KeyNumLockState = ! KeyNumLockState;
1067
1068               if ((keycode >= 0x60) && (keycode < 0x6e))
1069               {   /* simpler extended keys */
1070                  /* these keys are emulated */
1071
1072                  if ((keycode >= 0x63) && pressed)
1073                  {
1074                     /* Handle shift state */
1075                     if (keycode == 0x63)
1076                     {   /* non-shifted key */
1077                        if (KeyRealShiftState)
1078                           /* Fake shift unpress */
1079                           KeyFakeUnshiftState = 1;
1080                     }
1081                     else /*if (keycode >= 0x64)*/
1082                     {   /* non-numlock mode key */
1083                        if (KeyNumLockState & ! KeyRealShiftState)
1084                           /* Fake shift press if numlock is active */
1085                           KeyFakeShiftState = 1;
1086                        else if ((! KeyNumLockState) & KeyRealShiftState)
1087                           /* Fake shift unpress if shift is down */
1088                           KeyFakeUnshiftState = 1;
1089                     }
1090
1091                     if (KeyFakeShiftState)
1092                     {
1093                        post_in_KeyQueue(0xe0);
1094                        post_in_KeyQueue(0x2a);
1095                     }
1096
1097                     if (KeyFakeUnshiftState)
1098                     {
1099                        post_in_KeyQueue(0xe0);
1100                        post_in_KeyQueue(0xaa);
1101                     }
1102                  }
1103
1104                  keycode = keyboard_mf1_code[keycode-0x60];
1105                  if (! pressed)
1106                     keycode |= 0x80;
1107                  post_in_KeyQueue(0xe0);
1108                  post_in_KeyQueue(keycode);
1109               }
1110               else if (keycode == 0x6e)
1111               {   /* emulate Print Screen / System Request (F13) key */
1112                  /* this is a bit complex, as Alt+PrtScr -> SysRq */
1113                  /* Additionally, Ctrl+PrtScr involves no fake shift press */
1114                  if (KeyAltState)
1115                  {
1116                     /* SysRq */
1117                     keycode = 0x54;
1118                     if (! pressed)
1119                        keycode |= 0x80;
1120                     post_in_KeyQueue(keycode);
1121                  }
1122                  else
1123                  {
1124                     /* Handle shift state */
1125                     if (pressed && (! KeyRealShiftState) && (! KeyCtrlState))
1126                     {   /* Fake shift press */
1127                        post_in_KeyQueue(0xe0);
1128                        post_in_KeyQueue(0x2a);
1129                        KeyFakeShiftState = 1;
1130                     }
1131
1132                     keycode = 0x37;
1133                     if (! pressed)
1134                        keycode |= 0x80;
1135                     post_in_KeyQueue(0xe0);
1136                     post_in_KeyQueue(keycode);
1137                  }
1138               }
1139               else if (keycode == 0x6f)
1140               {   /* emulate pause (F15) key */
1141                  /* this is a bit complex, as Pause -> Ctrl+NumLock and
1142                        Ctrl+Pause -> Ctrl+ScrLock.  Furthermore, there is no
1143                        repeat or release. */
1144                  if (pressed)
1145                  {
1146                     if (KeyCtrlState)
1147                     {
1148                        post_in_KeyQueue(0xe0);
1149                        post_in_KeyQueue(0x46);
1150                        post_in_KeyQueue(0xe0);
1151                        post_in_KeyQueue(0xc6);
1152                     }
1153                     else
1154                     {
1155                        post_in_KeyQueue(0xe1);
1156                        post_in_KeyQueue(0x1d);
1157                        post_in_KeyQueue(0x45);
1158                        post_in_KeyQueue(0xe1);
1159                        post_in_KeyQueue(0x9d);
1160                        post_in_KeyQueue(0xc5);
1161                     }
1162                  }
1163               }
1164               else
1165               {
1166                  if (! pressed)
1167                     keycode |= 0x80;
1168                  post_in_KeyQueue(keycode);
1169               }
1170               read_key_if_possible(machine);
1171            }
1172         }
1173      }
1174   }
1175
1176   /* Handle auto-repeat */
1177   if ((KeyQueueLen <= (KeyQueueSize-MaxKeyMessageLen)) && KeyAutoRepeatKey && (--KeyAutoRepeatTimer == 0))
1178   {
1179      if ((KeyAutoRepeatKey >= 0x60) && (KeyAutoRepeatKey < 0x6e))
1180      {
1181         post_in_KeyQueue(0xe0);
1182         post_in_KeyQueue(keyboard_mf1_code[KeyAutoRepeatKey-0x60]);
1183      }
1184      else if (KeyAutoRepeatKey == 0x6e)
1185      {
1186         if (KeyAltState)
1187            post_in_KeyQueue(0x54);
1188         else
1189         {
1190            post_in_KeyQueue(0xe0);
1191            post_in_KeyQueue(0x37);
1192         }
1193      }
1194      else if (KeyAutoRepeatKey == 0x6f)
1195         ;
1196      else
1197      {
1198         post_in_KeyQueue(KeyAutoRepeatKey);
1199      }
1200      read_key_if_possible(machine);
1201      KeyAutoRepeatTimer = KeyAutoRepeatRate;
1202   }
1203}
1204
1205static void poll_mouse(running_machine *machine)
1206{
1207   static int last_mx = 0, last_my = 0;
1208   int new_mx, new_my;
1209   int delta_x, delta_y, buttons;
1210
1211   buttons = input_port_read(machine, "MOUSE0");
1212   new_mx = input_port_read(machine, "MOUSEX");
1213   new_my = input_port_read(machine, "MOUSEY");
1214
1215   /* compute x delta */
1216   delta_x = new_mx - last_mx;
1217
1218   /* check for wrap */
1219   if (delta_x > 0x80)
1220      delta_x = 0x100-delta_x;
1221   if  (delta_x < -0x80)
1222      delta_x = -0x100-delta_x;
1223
1224   last_mx = new_mx;
1225
1226   /* compute y delta */
1227   delta_y = new_my - last_my;
1228
1229   /* check for wrap */
1230   if (delta_y > 0x80)
1231      delta_y = 0x100-delta_y;
1232   if  (delta_y < -0x80)
1233      delta_y = -0x100-delta_y;
1234
1235   last_my = new_my;
1236
1237   v9938_update_mouse_state(0, delta_x, delta_y, buttons & 3);
1238}
1239
1240
1241/*===========================================================================*/
1242#if 0
1243#pragma mark -
1244#pragma mark TMS9901 INTERFACE
1245#endif
1246/*
1247    Geneve-specific tms9901 I/O handlers
1248
1249    See mess/machine/tms9901.c for generic tms9901 CRU handlers.
1250*/
1251/*
1252    TMS9901 interrupt handling on a Geneve.
1253
1254    Geneve uses the following interrupts:
1255    INT1: external interrupt (used by RS232 controller, for instance) -
1256      connected to tms9995 int4, too.
1257    INT2: VDP interrupt
1258    TMS9901 timer interrupt? (overrides INT3)
1259    INT8: keyboard interrupt???
1260    INT10: mouse interrupt???
1261    INT11: clock interrupt???
1262    INT12: INTB interrupt from PE-bus
1263*/
1264
1265/*
1266    set the state of int2 (called by tms9928 core)
1267*/
1268#ifdef UNUSED_FUNCTION
1269void tms9901_set_int2(int state)
1270{
1271   tms9901_set_single_int(machine->device("tms9901"), 2, state);
1272}
1273#endif
1274
1275/*
1276    Called by the 9901 core whenever the state of INTREQ and IC0-3 changes
1277*/
1278static TMS9901_INT_CALLBACK( tms9901_interrupt_callback )
1279{
1280   /* INTREQ is connected to INT1 (IC0-3 are not connected) */
1281   cputag_set_input_line(device->machine, "maincpu", 0, intreq ? ASSERT_LINE : CLEAR_LINE);
1282}
1283
1284/*
1285    Read pins INT3*-INT7* of Geneve 9901.
1286
1287    signification:
1288     (bit 1: INT1 status)
1289     (bit 2: INT2 status)
1290     bit 3-7: joystick status
1291*/
1292static READ8_DEVICE_HANDLER( R9901_0 )
1293{
1294   int answer;
1295
1296   answer = input_port_read(device->machine, "JOY") >> (JoySel * 8);
1297
1298   return (answer);
1299}
1300
1301/*
1302    Read pins INT8*-INT15* of Geneve 9901.
1303
1304    signification:
1305     (bit 0: keyboard interrupt)
1306     bit 1: unused
1307     bit 2: mouse right button
1308     (bit 3: clock interrupt)
1309     (bit 4: INTB from PE-bus)
1310     bit 5 & 7: used as output
1311     bit 6: unused
1312*/
1313static READ8_DEVICE_HANDLER( R9901_1 )
1314{
1315   int answer;
1316
1317   answer = (input_port_read(device->machine, "MOUSE0") & 4) ^ 4;
1318
1319   return answer;
1320}
1321
1322/*
1323    Read pins P0-P7 of Geneve 9901.
1324*/
1325static READ8_DEVICE_HANDLER( R9901_2 )
1326{
1327   return 0;
1328}
1329
1330/*
1331    Read pins P8-P15 of Geneve 9901.
1332    bit 4: mouse right button
1333*/
1334static READ8_DEVICE_HANDLER( R9901_3 )
1335{
1336   int answer = 0;
1337
1338   if (! (input_port_read(device->machine, "MOUSE0") & 4))
1339      answer |= 0x10;
1340
1341   return answer;
1342}
1343
1344
1345/*
1346    Write PE bus reset line
1347*/
1348static WRITE8_DEVICE_HANDLER( W9901_PE_bus_reset )
1349{
1350}
1351
1352/*
1353    Write VDP reset line
1354*/
1355static WRITE8_DEVICE_HANDLER( W9901_VDP_reset )
1356{
1357}
1358
1359/*
1360    Write joystick select line
1361*/
1362static WRITE8_DEVICE_HANDLER( W9901_JoySel )
1363{
1364   JoySel = data;
1365}
1366
1367static WRITE8_DEVICE_HANDLER( W9901_KeyboardReset )
1368{
1369   KeyReset = ! data;
1370   if (KeyReset)
1371   {
1372      /* reset -> clear keyboard key queue, but not geneve key buffer */
1373      KeyQueueLen = KeyInBuf ? 1 : 0;
1374      memset(KeyStateSave, 0, sizeof(KeyStateSave));
1375      KeyNumLockState = 0;
1376      KeyCtrlState = 0;
1377      KeyAltState = 0;
1378      KeyRealShiftState = 0;
1379      KeyFakeShiftState = 0;
1380      KeyFakeUnshiftState = 0;
1381      KeyAutoRepeatKey = 0;
1382   }
1383   /*else
1384        poll_keyboard(space->machine);*/
1385}
1386
1387/*
1388    Write external mem cycles (0=long, 1=short)
1389*/
1390static WRITE8_DEVICE_HANDLER( W9901_ext_mem_wait_states )
1391{
1392}
1393
1394/*
1395    Write vdp wait cycles (1=add 15 cycles, 0=add none)
1396*/
1397static WRITE8_DEVICE_HANDLER( W9901_VDP_wait_states )
1398{
1399}
1400
1401/* tms9901 setup */
1402const tms9901_interface tms9901reset_param_ti99 =
1403{
1404   TMS9901_INT1 | TMS9901_INT2 | TMS9901_INT8 | TMS9901_INTB | TMS9901_INTC,   /* only input pins whose state is always known */
1405
1406   {   /* read handlers */
1407      R9901_0,
1408      R9901_1,
1409      R9901_2,
1410      R9901_3
1411   },
1412
1413   {   /* write handlers */
1414      W9901_PE_bus_reset,
1415      W9901_VDP_reset,
1416      W9901_JoySel,
1417      NULL,
1418      NULL,
1419      NULL,
1420      W9901_KeyboardReset,
1421      W9901_ext_mem_wait_states,
1422      NULL,
1423      W9901_VDP_wait_states,
1424      NULL,
1425      NULL,
1426      NULL,
1427      NULL,
1428      NULL,
1429      NULL
1430   },
1431
1432   /* interrupt handler */
1433   tms9901_interrupt_callback,
1434
1435   /* clock rate = 3MHz */
1436   3000000.
1437};
1438
1439
src/mess/machine/ti99pcod.c
r9500r9501
1/*
2    TI-99 P-Code Card emulation.
3    Michael Zapf, July 2009
4
5    The P-Code card is part of the UCSD p-System support for the TI-99
6    computer family. This system is a comprehensive development system for
7    creating, running, and debugging programs written in UCSD Pascal.
8
9    The complete system consists of
10    - P-Code card, plugged into the Peripheral Expansion Box (PEB)
11    - Software on disk:
12      + PHD5063: UCSD p-System Compiler
13      + PHD5064: UCSD p-System Assembler/Linker
14      + PHD5065: UCSD p-System Editor/Filer (2 disks)
15
16    The card has a switch on the circuit board extending outside the PEB
17    which allows to turn off the card without removing it. Unlike other
18    expansion cards for the TI system, the P-Code card immediately takes
19    over control after the system is turned on.
20
21    When the p-System is booted, the screen turns cyan and remains empty.
22    There are two beeps, a pause for about 15 seconds, another three beeps,
23    and then a welcome text is displayed with a one-line menu at the screen
24    top. (Delay times seem unrealistically short; the manual says
25    30-60 seconds. To be checked.)
26    Many of the functions require one of the disks be inserted in one
27    of the disk drives. You can leave the p-System by waiting for the menu
28    to appear, and typing H (halt). This returns you to the Master Title
29    Screen, and the card is inactive until the system is reset.
30
31    The P-Code card contains the P-Code interpreter which is somewhat
32    comparable to today's Java virtual machine. Programs written for the
33    p-System are interchangeable between different platforms.
34
35    On the P-Code card we find 12 KiB of ROM, visible in the DSR memory area
36    (>4000 to >5FFF). The first 4 KiB (>4000->4FFF) are from the 4732 ROM,
37    the second and third 4 KiB (>5000->5FFF) are from a 4764 ROM, switched
38    by setting the CRU bit 4 to 1 on the CRU base >1F00.
39
40    CRU base >1F00
41        Bit 0: Activate card
42        Bit 4: Select bank 2 of the 4764 ROM (0 = bank 1)
43        Bit 7: May be connected to an indicator LED which is by default
44               wired to bit 0 (on the PCB)
45
46    The lines are used in a slightly uncommon way: the three bits of the
47    CRU bit address are A8, A13, and A14 (A15=LSB). Hence, bit 4 is at
48    address >1F80, and bit 7 is at address >1F86. These bits are purely
49    write-only.
50
51    Moreover, the card contains 48 KiB of GROM memory, occupying the address
52    space from G>0000 to G>FFFF in portions of 6KiB at every 8KiB boundary.
53
54    Another specialty of the card is that the GROM contents are accessed via
55    another GROM base address than what is used in the console:
56    - >5BFC = read GROM data
57    - >5BFE = read GROM address
58    - >5FFC = write GROM data
59    - >5FFE = write GROM address
60
61    This makes the GROM memory "private" to the card; together with the
62    rest of the ROM space the ports become invisible when the card is
63    deactivated.
64
65    Emulation information:
66
67    The P-Code card switch is mapped to a DIP switch in the configuration
68    menu. If the switch is turned on, the system assumes that ROM dumps are
69    present called "pcode_r0.bin" (4 KiB), "pcode_r1.bin" (8KiB),
70    "pcode_g0.bin" (64 KiB). The switch is turned off by default. Check the
71    switch position if the Master Title Screen does not appear as expected.
72*/
73#include "emu.h"
74#include "devices/ti99_peb.h"
75#include "ti99_4x.h"
76#include "ti99pcod.h"
77
78static const int GROM_base = 0x1bfc;
79static int bank_select; // 0 or 1
80/*
81    Pointer to the pcode ROM data. We have three sections of the ROM
82    code: 4K from one chip, 2 banks with 4K each from the second chip.
83*/
84static UINT8 *ti99_pcode_rom0;
85static UINT8 *ti99_pcode_rom1;
86static UINT8 *ti99_pcode_rom2;
87static UINT8 *ti99_pcode_grom;
88
89static READ8_HANDLER(pcode_mem_r);
90static WRITE8_HANDLER(pcode_mem_w);
91static int pcode_cru_r(running_machine *machine, int offset);
92static void pcode_cru_w(running_machine *machine, int offset, int data);
93
94static running_device *expansion_box;
95
96static const ti99_peb_card_handlers_t pcode_handlers =
97{
98   pcode_cru_r,
99   pcode_cru_w,
100   pcode_mem_r,
101   pcode_mem_w
102};
103
104/*************************************************************************
105   Private GROM support
106   The P-Code card contains 8 GROMs, spanning the whole GROM address
107   space. But since the card uses an own GROM base address, the console
108   GROMs are not affected. The GROMs on the P-Code card can only be
109   accessed when the card is selected.
110   We take the routines from ti99_4x, slightly changing them. (At some later
111   time we should possibly model the GROMs as own devices.)
112**************************************************************************/
113
114/* descriptor for pcode GROMs */
115static GROM_port_t pcode_GROMs;
116
117static UINT8 GROM_dataread(void)
118{
119   UINT8 reply;
120   /* GROMs are buffered. Data is retrieved from a buffer,
121    while the buffer is replaced with the next cell
122    content. */
123   reply = pcode_GROMs.buf;
124
125   /* Get next value, put it in buffer. Note that the
126    GROM wraps at 8K boundaries. */
127   pcode_GROMs.buf = pcode_GROMs.data_ptr[pcode_GROMs.addr];
128
129   /* The program counter wraps at each GROM chip size (8K),
130    so 0x5fff + 1 = 0x4000. */
131   pcode_GROMs.addr = ((pcode_GROMs.addr + 1) & 0x1FFF) | (pcode_GROMs.addr & 0xE000);
132
133   /* Reset the read and write address flipflops. */
134   pcode_GROMs.raddr_LSB = pcode_GROMs.waddr_LSB = FALSE;
135
136   return reply;
137}
138
139/*
140    GROM read for P-Code card
141    For comments, see the handler for TI-99/4A
142*/
143static READ8_HANDLER ( ti99_pcode_grom_r )
144{
145   UINT8 reply;
146
147   cpu_adjust_icount(space->machine->firstcpu,-4);
148
149   if (offset & 2)
150   {
151      pcode_GROMs.waddr_LSB = FALSE;
152
153      if (pcode_GROMs.raddr_LSB)
154      {
155         reply = pcode_GROMs.addr & 0x00ff;
156         pcode_GROMs.raddr_LSB = FALSE;
157      }
158      else
159      {
160         reply = (pcode_GROMs.addr>>8) & 0x00ff;
161         pcode_GROMs.raddr_LSB = TRUE;
162      }
163   }
164   else
165      reply = GROM_dataread();
166
167   return reply;
168}
169
170/*
171    GROM write for P-Code card.
172    For comments, see the handler for TI-99/4A
173*/
174static WRITE8_HANDLER ( ti99_pcode_grom_w )
175{
176   cpu_adjust_icount(space->machine->firstcpu,-4);
177
178   if (offset & 2)
179   {
180      pcode_GROMs.raddr_LSB = FALSE;
181      if (pcode_GROMs.waddr_LSB)
182      {
183         pcode_GROMs.addr = (pcode_GROMs.addr & 0xFF00) | (data & 0xFF);
184
185         GROM_dataread();
186         pcode_GROMs.waddr_LSB = FALSE;
187      }
188      else
189      {
190         pcode_GROMs.addr = ((data<<8) & 0xFF00) | (pcode_GROMs.addr & 0xFF);
191         pcode_GROMs.waddr_LSB = TRUE;
192      }
193
194   }
195   else
196   {
197      GROM_dataread();
198      pcode_GROMs.raddr_LSB = pcode_GROMs.waddr_LSB = FALSE;
199   }
200}
201
202/**************************************************************************/
203
204void ti99_pcode_reset(running_machine *machine)
205{
206   ti99_pcode_rom0 = memory_region(machine, region_dsr) + offset_pcode_rom;
207   ti99_pcode_rom1 = ti99_pcode_rom0 + 0x1000;
208   ti99_pcode_rom2 = ti99_pcode_rom1 + 0x1000;
209   ti99_pcode_grom = memory_region(machine, region_dsr) + offset_pcode_grom;
210   bank_select = 0;
211   pcode_GROMs.addr = 0;
212   pcode_GROMs.data_ptr = ti99_pcode_grom;
213
214   expansion_box = machine->device("per_exp_box");
215
216   ti99_peb_set_card_handlers(expansion_box, 0x1f00, &pcode_handlers);
217}
218
219/*
220    The CRU write handler. The CRU is a serial interface in the console.
221    Using the CRU we can switch the banks in the p-code card
222    Bit 0 = activate card
223    Bit 4 = select second bank of high ROM.
224    Note that the CRU address is created from address lines A8, A13, and A14
225    so bit 0 is at 0x1f00, but bit 4 is at 0x1f80 (bit 7 would be 0x1f86
226    but it is not used)
227*/
228static void pcode_cru_w(running_machine *machine, int offset, int data)
229{
230   /* offset is the bit number. The CRU base address is already divided
231           by 2. */
232   if (offset == 0)
233   {
234//      printf("pcode card state = %d\n", data);
235   }
236   if (offset == 0x40)  // Bit 4 is on A8
237   {
238      if (data==0)
239         bank_select = 0;
240      else
241         bank_select = 1;
242//      printf("pcode bank select = %d\n", data);
243   }
244}
245
246/*
247    The CRU read handler. The p-code card does not provide a CRU read
248    functionality, so we assume that it only returns 0.
249*/
250static int pcode_cru_r(running_machine *machine, int offset)
251{
252   return 0;
253}
254
255/*
256    Read a byte in pcode DSR space
257*/
258static  READ8_HANDLER( pcode_mem_r )
259{
260   UINT8 reply;
261   if (offset < 0x1000)
262   {
263      /* Accesses ROM 4732 (4K) */
264      reply = ti99_pcode_rom0[offset];
265   }
266   else
267   {
268      /* Check if we access the GROM port */
269      switch (offset)
270      {
271         /* GROMs only answer at even addresses. The odd addresses are
272            undefined, so we can as well just ignore these cases. */
273      case 0x1bfc:
274      case 0x1bfe:
275         reply = ti99_pcode_grom_r(space, offset);
276         break;
277      case 0x1ffc:
278      case 0x1ffe:
279         // Cannot read from this port
280         reply = 0;
281         break;
282      default:
283         /* Accesses ROM 4764 (2*4K)
284            We have two banks here which are activated according
285            to the setting of CRU bit 4
286            */
287         reply = (bank_select==0)? ti99_pcode_rom1[offset-0x1000] : ti99_pcode_rom2[offset-0x1000];
288      }
289   }
290   return reply;
291}
292
293/*
294    Write a byte in P-Code ROM space. This is only useful for setting the
295    GROM address.
296*/
297static WRITE8_HANDLER( pcode_mem_w )
298{
299   /* Check if we access the GROM "set address" port */
300   if (offset == 0x1ffe)
301   {
302      ti99_pcode_grom_w(space, offset, data);
303   }
304}
305
src/mess/machine/ti99pcod.h
r9500r9501
1/*
2    TI-99 P-Code Card emulation.
3    Michael Zapf, July 2009
4*/
5
6void ti99_pcode_reset(running_machine *machine);
7
src/mess/machine/99_ide.c
r9500r9501
1/*
2    Thierry Nouspikel's IDE card emulation
3
4    This card is just a prototype.  It has been designed by Thierry Nouspikel,
5    and its description was published in 2001.  The card have been revised in
6    2004.
7
8    The specs have been published in <http://www.nouspikel.com/ti99/ide.html>.
9
10    The IDE interface is quite simple, since it only implements PIO transfer.
11    The card includes a clock chip to timestamp files, and an SRAM for the DSR.
12    It should be possible to use a battery backed DSR SRAM, but since the clock
13    chip includes 4kb of battery-backed RAM, a bootstrap loader can be saved in
14    the clock SRAM in order to load the DSR from the HD when the computer
15    starts.
16
17    Raphael Nabet, 2002-2004.
18*/
19
20#include "emu.h"
21#include "machine/idectrl.h"
22#include "machine/rtc65271.h"
23#include "ti99_4x.h"
24#include "devices/ti99_peb.h"
25#include "99_ide.h"
26
27
28/* prototypes */
29static int ide_cru_r(running_machine *machine, int offset);
30static void ide_cru_w(running_machine *machine, int offset, int data);
31static READ8_HANDLER(ide_mem_r);
32static WRITE8_HANDLER(ide_mem_w);
33
34/* pointer to the IDE RAM area */
35static UINT8 *ti99_ide_RAM;
36static int cur_page;
37enum
38{   /* 0xff for 2 mbytes, 0x3f for 512kbytes, 0x03 for 32 kbytes */
39   page_mask = /*0xff*/0x3f
40};
41
42static const ti99_peb_card_handlers_t ide_handlers =
43{
44   ide_cru_r,
45   ide_cru_w,
46   ide_mem_r,
47   ide_mem_w
48};
49
50static int sram_enable;
51static int sram_enable_dip = 0;
52static int cru_register;
53enum
54{
55   cru_reg_page_switching = 0x04,
56   cru_reg_page_0 = 0x08,
57   /*cru_reg_rambo = 0x10,*/   /* not emulated */
58   cru_reg_wp = 0x20,
59   cru_reg_int_en = 0x40,
60   cru_reg_reset = 0x80
61};
62static int input_latch, output_latch;
63
64static int ide_irq, clk_irq;
65
66/* The card has a 8-bit->16-bit demultiplexer that can be set-up to assume
67either that the LSByte of a word is accessed first or that the MSByte of a word
68is accessed first.  The former is true with ti-99/4(a), the latter with the
69tms9995 CPU used by Geneve and ti-99/8.  Note that the first revision of IDE
70only supported ti-99/4(a) (LSByte first) mode. */
71static int tms9995_mode;
72
73static running_device *expansion_box;
74
75/*
76    ti99_ide_interrupt()
77
78    IDE interrupt callback
79*/
80void ti99_ide_interrupt(running_device *device, int state)
81{
82   ide_irq = state;
83   if (cru_register & cru_reg_int_en)
84      ti99_peb_set_ila_bit(expansion_box, inta_ide_bit, state);
85}
86
87/*
88    clk_interrupt_callback()
89
90    clock interrupt callback
91*/
92void ti99_clk_interrupt_callback(running_device *device, int state)
93{
94   clk_irq = state;
95   ti99_peb_set_ila_bit(expansion_box, inta_ide_clk_bit, state);
96}
97
98/*
99    Initializes the ide card, set up handlers
100*/
101void ti99_ide_init(running_machine *machine)
102{
103//  rtc65271_init(machine, memory_region(machine, region_dsr) + offset_ide_ram2, clk_interrupt_callback);
104   ti99_ide_RAM = memory_region(machine, region_dsr) + offset_ide_ram;
105}
106
107/*
108    Reset ide card, set up handlers
109*/
110void ti99_ide_reset(running_machine *machine, int in_tms9995_mode)
111{
112   expansion_box = machine->device("per_exp_box");
113   ti99_peb_set_card_handlers(expansion_box, 0x1000, & ide_handlers);
114
115   cur_page = 0;
116   sram_enable = 0;
117   cru_register = 0;
118
119   tms9995_mode = in_tms9995_mode;
120}
121
122/*
123    Read ide CRU interface
124*/
125static int ide_cru_r(running_machine *machine, int offset)
126{
127   int reply;
128
129   switch (offset)
130   {
131   default:
132      reply = cru_register & 0x30;
133      reply |= 8;   /* IDE bus IORDY always set */
134      if (! clk_irq)
135         reply |= 4;
136      if (sram_enable_dip)
137         reply |= 2;
138      if (! ide_irq)
139         reply |= 1;
140      break;
141   }
142
143   return reply;
144}
145
146/*
147    Write ide CRU interface
148*/
149static void ide_cru_w(running_machine *machine, int offset, int data)
150{
151   offset &= 7;
152
153
154   switch (offset)
155   {
156   case 0:         /* turn card on: handled by core */
157      break;
158
159   case 1:         /* enable SRAM or registers in 0x4000-0x40ff */
160      sram_enable = data;
161      break;
162
163   case 2:         /* enable SRAM page switching */
164   case 3:         /* force SRAM page 0 */
165   case 4:         /* enable SRAM in 0x6000-0x7000 ("RAMBO" mode) */
166   case 5:         /* write-protect RAM */
167   case 6:         /* irq and reset enable */
168   case 7:         /* reset drive */
169      if (data)
170         cru_register |= 1 << offset;
171      else
172         cru_register &= ~ (1 << offset);
173
174      if (offset == 6)
175         ti99_peb_set_ila_bit(expansion_box, inta_ide_bit, (cru_register & cru_reg_int_en) && ide_irq);
176
177      if ((offset == 6) || (offset == 7))
178         if ((cru_register & cru_reg_int_en) && !(cru_register & cru_reg_reset))
179            devtag_reset(machine, "ide");
180      break;
181   }
182}
183
184/*
185    read a byte in ide DSR space
186*/
187static READ8_HANDLER(ide_mem_r)
188{
189   int reply = 0;
190   running_device *ide_rtc = space->machine->device("ide_rtc");
191
192   if ((offset <= 0xff) && (sram_enable == sram_enable_dip))
193   {   /* registers */
194      switch ((offset >> 5) & 0x3)
195      {
196      case 0:      /* RTC RAM */
197         if (offset & 0x80)
198            /* RTC RAM page register */
199            reply = rtc65271_xram_r(ide_rtc, (offset & 0x1f) | 0x20);
200         else
201            /* RTC RAM read */
202            reply = rtc65271_xram_r(ide_rtc, offset);
203         break;
204      case 1:      /* RTC registers */
205         if (offset & 0x10)
206            /* register data */
207            reply = rtc65271_rtc_r(ide_rtc, 1);
208         else
209            /* register select */
210            reply = rtc65271_rtc_r(ide_rtc, 0);
211         break;
212      case 2:      /* IDE registers set 1 (CS1Fx) */
213         if (tms9995_mode ? (!(offset & 1)) : (offset & 1))
214         {   /* first read triggers 16-bit read cycle */
215            running_device *ide_device = space->machine->device("ide");
216            input_latch = (! (offset & 0x10)) ? ide_bus_r(ide_device, 0, (offset >> 1) & 0x7) : 0;
217         }
218
219         /* return latched input */
220         /*reply = (offset & 1) ? input_latch : (input_latch >> 8);*/
221         /* return latched input - bytes are swapped in 2004 IDE card */
222         reply = (offset & 1) ? (input_latch >> 8) : input_latch;
223         break;
224      case 3:      /* IDE registers set 2 (CS3Fx) */
225         if (tms9995_mode ? (!(offset & 1)) : (offset & 1))
226         {   /* first read triggers 16-bit read cycle */
227            running_device *ide_device = space->machine->device("ide");
228            input_latch = (! (offset & 0x10)) ? ide_bus_r(ide_device, 1, (offset >> 1) & 0x7) : 0;
229         }
230
231         /* return latched input */
232         /*reply = (offset & 1) ? input_latch : (input_latch >> 8);*/
233         /* return latched input - bytes are swapped in 2004 IDE card */
234         reply = (offset & 1) ? (input_latch >> 8) : input_latch;
235         break;
236      }
237   }
238   else
239   {   /* sram */
240      if ((cru_register & cru_reg_page_0) || (offset >= 0x1000))
241         reply = ti99_ide_RAM[offset+0x2000*cur_page];
242      else
243         reply = ti99_ide_RAM[offset];
244   }
245
246   return reply;
247}
248
249/*
250    write a byte in ide DSR space
251*/
252static WRITE8_HANDLER(ide_mem_w)
253{
254   running_device *ide_rtc = space->machine->device("ide_rtc");
255
256   if (cru_register & cru_reg_page_switching)
257   {
258      cur_page = (offset >> 1) & page_mask;
259   }
260
261   if ((offset <= 0xff) && (sram_enable == sram_enable_dip))
262   {   /* registers */
263      switch ((offset >> 5) & 0x3)
264      {
265      case 0:      /* RTC RAM */
266         if (offset & 0x80)
267            /* RTC RAM page register */
268            rtc65271_xram_w(ide_rtc,(offset & 0x1f) | 0x20, data);
269         else
270            /* RTC RAM write */
271            rtc65271_xram_w(ide_rtc,offset, data);
272         break;
273      case 1:      /* RTC registers */
274         if (offset & 0x10)
275            /* register data */
276            rtc65271_rtc_w(ide_rtc, 1, data);
277         else
278            /* register select */
279            rtc65271_rtc_w(ide_rtc, 0, data);
280         break;
281      case 2:      /* IDE registers set 1 (CS1Fx) */
282#if 0
283         /* latch write */
284         if (offset & 1)
285            output_latch = (output_latch & 0xff00) | data;
286         else
287            output_latch = (output_latch & 0x00ff) | (data << 8);
288#endif
289         /* latch write - bytes are swapped in 2004 IDE card */
290         if (offset & 1)
291            output_latch = (output_latch & 0x00ff) | (data << 8);
292         else
293            output_latch = (output_latch & 0xff00) | data;
294
295         if (tms9995_mode ? (offset & 1) : (!(offset & 1)))
296         {   /* second write triggers 16-bit write cycle */
297            running_device *ide_device = space->machine->device("ide");
298            ide_bus_w(ide_device, 0, (offset >> 1) & 0x7, output_latch);
299         }
300         break;
301      case 3:      /* IDE registers set 2 (CS3Fx) */
302#if 0
303         /* latch write */
304         if (offset & 1)
305            output_latch = (output_latch & 0xff00) | data;
306         else
307            output_latch = (output_latch & 0x00ff) | (data << 8);
308#endif
309         /* latch write - bytes are swapped in 2004 IDE card */
310         if (offset & 1)
311            output_latch = (output_latch & 0x00ff) | (data << 8);
312         else
313            output_latch = (output_latch & 0xff00) | data;
314
315         if (tms9995_mode ? (offset & 1) : (!(offset & 1)))
316         {   /* second write triggers 16-bit write cycle */
317            running_device *ide_device = space->machine->device("ide");
318            ide_bus_w(ide_device, 1, (offset >> 1) & 0x7, output_latch);
319         }
320         break;
321      }
322   }
323   else
324   {   /* sram */
325      if (! (cru_register & cru_reg_wp))
326      {
327         if ((cru_register & cru_reg_page_0) || (offset >= 0x1000))
328            ti99_ide_RAM[offset+0x2000*cur_page] = data;
329         else
330            ti99_ide_RAM[offset] = data;
331      }
332   }
333}
334
src/mess/machine/99_ide.h
r9500r9501
1int ti99_ide_load_memcard(running_machine *machine);
2int ti99_ide_save_memcard(void);
3
4void ti99_ide_init(running_machine *machine);
5void ti99_ide_reset(running_machine *machine, int in_tms9995_mode);
6
7void ti99_ide_interrupt(running_device *device, int state);
src/mess/machine/99_hsgpl.c
r9500r9501
1/*
2    SNUG HSGPL card emulation.
3    Raphael Nabet, 2003.
4*/
5
6#include "emu.h"
7#include "emuopts.h"
8#include "ti99_4x.h"
9#include "devices/ti99_peb.h"
10#include "99_hsgpl.h"
11#include "at29040.h"
12
13/*
14    Supports 16 banks of 8 GROMs (8kbytes each) with 16 associated banks of
15    32kbytes (8kbytes*4) of module ROM, 2 banks of 8 GRAMs with 2 associated
16    banks of 32 kbytes of RAM, and 512kbytes of DSR.  Roms are implemented with
17    512kbyte EEPROMs (1 for DSR, 2 for GROMs, 1 for cartridge ROM).  RAM is
18    implemented with 128kbyte SRAMs (1 for GRAM, 1 for cartridge RAM - only the
19    first 64kbytes of the cartridge RAM chip is used).
20
21    CRU bits:
22       Name    Equates Meaning
23    >0 DEN     DSRENA  DSR Enable
24    >1 GRMENA  GRMENA  Enable GRAM instead of GROM in banks 0 and 1
25    >2 BNKINH* BNKENA  Disable banking
26    >3 PG0     PG0
27    >4 PG1     PG1
28    >5 PG2     PG2     Paging-Bits for DSR-area
29    >6 PG3     PG3
30    >7 PG4     PG4
31    >8 PG5     PG5
32    >9 CRDENA  CRDENA  Activate memory areas of HSGPL (i.e. enable HSGPL GROM and ROM6 ports)
33    >A WRIENA  WRIENA  write enable for RAM and GRAM (and flash GROM!)
34    >B SCENA   SCARTE  Activate SuperCart-banking
35    >C LEDENA  LEDENA  light LED on
36    >D -       -       free
37    >E MBXENA  MBXENA  Activate MBX-Banking
38    >F RAMENA  RAMENA  Enable RAM6000 instead of ROM6000 in banks 0 and 1
39
40
41    Direct access ports for all memory areas (the original manual gives
42    >9880->989C and >9C80->9C9C for ROM6000, but this is incorrect):
43
44    Module bank Read    Write   Read ROM6000        Write ROM6000
45                GROM    GROM
46    0           >9800   >9C00   >9860 Offset >0000  >9C60 Offset >0000
47    1           >9804   >9C04   >9860 Offset >8000  >9C60 Offset >8000
48    2           >9808   >9C08   >9864 Offset >0000  >9C64 Offset >0000
49    3           >980C   >9C0C   >9864 Offset >8000  >9C64 Offset >8000
50    4           >9810   >9C10   >9868 Offset >0000  >9C68 Offset >0000
51    5           >9814   >9C14   >9868 Offset >8000  >9C68 Offset >8000
52    6           >9818   >9C18   >986C Offset >0000  >9C6C Offset >0000
53    7           >981C   >9C1C   >986C Offset >8000  >9C6C Offset >8000
54    8           >9820   >9C20   >9870 Offset >0000  >9C70 Offset >0000
55    9           >9824   >9C24   >9870 Offset >8000  >9C70 Offset >8000
56    10          >9828   >9C28   >9874 Offset >0000  >9C74 Offset >0000
57    11          >982C   >9C2C   >9874 Offset >8000  >9C74 Offset >8000
58    12          >9830   >9C30   >9878 Offset >0000  >9C78 Offset >0000
59    13          >9834   >9C34   >9878 Offset >8000  >9C78 Offset >8000
60    14          >9838   >9C38   >987C Offset >0000  >9C7C Offset >0000
61    15          >983C   >9C3C   >987C Offset >8000  >9C7C Offset >8000
62
63    Module bank Read    Write   Read RAM6000        Write RAM6000
64                GRAM    GRAM
65    16 (Ram)    >9880   >9C80   >98C0 Offset >0000  >9CC0 Offset >0000
66    17 (Ram)    >9884   >9C84   >98C0 Offset >8000  >9CC0 Offset >8000
67
68    DSR bank    Read    Write
69    0 - 7       >9840   >9C40
70    8 - 15      >9844   >9C44
71    16 - 23     >9848   >9C48
72    24 - 31     >984C   >9C4C
73    32 - 39     >9850   >9C50
74    40 - 47     >9854   >9C54
75    48 - 55     >9858   >9C58
76    56 - 63     >985C   >9C5C
77
78    Note: Writing only works for areas set up as RAM.  To write to the
79        FEEPROMs, you must used the algorithm specified by their respective
80        manufacturer.
81*/
82
83static struct
84{
85   UINT8 *GRAM_ptr;
86   UINT8 *RAM6_ptr;
87
88   UINT16 addr;
89   char raddr_LSB, waddr_LSB;
90
91   /* Holds the current GROM base */
92   int cur_port;
93
94   /* Holds the current ROM6 bank */
95   int cur_bank;
96
97   /* Latches the setting of the 16 CRU bits. Also contains the */
98   /* current DSR bank (PG0...) */
99   int cru_reg;
100} hsgpl;
101
102enum
103{
104   cr_grmena  = 0x0002,
105   cr_bnkinh  = 0x0004,
106   cr_pg      = 0x01f8,
107   cr_pg_mask = 0x3f,
108   cr_pg_shift= 3,
109   cr_crdena  = 0x0200,
110   cr_crdena_bit = 9,
111   cr_wriena  = 0x0400,
112   cr_scena   = 0x0800,
113   cr_ledena  = 0x1000,
114   cr_free    = 0x2000,
115   cr_mbxena  = 0x4000,
116   cr_ramena  = 0x8000
117};
118
119static void hsgpl_cru_w(running_machine *machine, int offset, int data);
120static READ8_HANDLER(hsgpl_dsr_r);
121
122static running_device *expansion_box;
123
124static const ti99_peb_card_handlers_t hsgpl_handlers =
125{
126   NULL,
127   hsgpl_cru_w,
128   hsgpl_dsr_r,
129   NULL
130};
131
132enum
133{
134   feeprom_grom0 = 0,
135   feeprom_grom1 = 1,
136   feeprom_rom6  = 2,
137   feeprom_dsr   = 3
138};
139
140
141static int ti99_hsgpl_file_load(running_machine *machine, mame_file *file)
142{
143   UINT8 version;
144   UINT8 *rgn;
145
146   /* version flag */
147   if (mame_fread(file, & version, 1) != 1)
148      return 1;
149   if (version != 0)
150      return 1;
151
152   rgn = memory_region(machine, region_hsgpl);
153
154   /* read DSR */
155   at29c040a_init_data_ptr(feeprom_dsr, rgn + offset_hsgpl_dsr);
156   if (at29c040a_file_load(feeprom_dsr, file))
157      return 1;
158
159   /* read GROM 0 */
160   at29c040a_init_data_ptr(feeprom_grom0, rgn + offset_hsgpl_grom);
161   if (at29c040a_file_load(feeprom_grom0, file))
162      return 1;
163
164   /* read GROM 1 */
165   at29c040a_init_data_ptr(feeprom_grom1, rgn + offset_hsgpl_grom + 0x80000);
166   if (at29c040a_file_load(feeprom_grom1, file))
167      return 1;
168
169   /* read ROM6 */
170   at29c040a_init_data_ptr(feeprom_rom6, rgn + offset_hsgpl_rom6);
171   if (at29c040a_file_load(feeprom_rom6, file))
172      return 1;
173
174   return 0;
175}
176
177static int ti99_hsgpl_file_save(mame_file *file)
178{
179   UINT8 version;
180
181   /* version flag */
182   version = 0;
183   if (mame_fwrite(file, & version, 1) != 1)
184      return 1;
185
186   /* save DSR */
187   if (at29c040a_file_save(feeprom_dsr, file))
188      return 1;
189
190   /* save GROM 0 */
191   if (at29c040a_file_save(feeprom_grom0, file))
192      return 1;
193
194   /* save GROM 1 */
195   if (at29c040a_file_save(feeprom_grom1, file))
196      return 1;
197
198   /* save ROM6 */
199   if (at29c040a_file_save(feeprom_rom6, file))
200      return 1;
201
202   return 0;
203}
204
205static int ti99_hsgpl_get_dirty_flag(void)
206{
207   return at29c040a_get_dirty_flag(feeprom_dsr)
208         || at29c040a_get_dirty_flag(feeprom_grom0)
209         || at29c040a_get_dirty_flag(feeprom_grom1)
210         || at29c040a_get_dirty_flag(feeprom_rom6);
211}
212
213
214
215int ti99_hsgpl_load_flashroms(running_machine *machine, const char *name)
216{
217   file_error filerr;
218   mame_file *file;
219
220   filerr = mame_fopen(SEARCHPATH_NVRAM, name, OPEN_FLAG_READ, &file);
221   if (filerr != FILERR_NONE)
222      return 0;
223   if (ti99_hsgpl_file_load(machine, file))
224   {
225      mame_fclose(file);
226      return 1;
227   }
228
229   mame_fclose(file);
230   return 0;
231}
232
233int ti99_hsgpl_save_flashroms(running_machine *machine, const char *name)
234{
235   file_error filerr;
236   mame_file *file;
237
238   if (ti99_hsgpl_get_dirty_flag())
239   {
240      filerr = mame_fopen(SEARCHPATH_NVRAM, name,
241         OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS, &file);
242
243      if (filerr != FILERR_NONE)
244         return 1;
245      if (ti99_hsgpl_file_save(file))
246      {
247         mame_fclose(file);
248         return 1;
249      }
250
251      mame_fclose(file);
252   }
253
254   return 0;
255}
256
257/*
258    Initialize hsgpl card, set up handlers
259*/
260void ti99_hsgpl_init(running_machine *machine)
261{
262   UINT8 *rgn = memory_region(machine, region_hsgpl);
263   hsgpl.GRAM_ptr = rgn + offset_hsgpl_gram;
264   hsgpl.RAM6_ptr = rgn + offset_hsgpl_ram6;
265
266   at29c040a_init_data_ptr(feeprom_grom0, rgn + offset_hsgpl_grom);
267   at29c040a_init(machine,feeprom_grom0);
268   at29c040a_init_data_ptr(feeprom_grom1, rgn + offset_hsgpl_grom + 0x80000);
269   at29c040a_init(machine,feeprom_grom1);
270   at29c040a_init_data_ptr(feeprom_rom6, rgn + offset_hsgpl_rom6);
271   at29c040a_init(machine,feeprom_rom6);
272   at29c040a_init_data_ptr(feeprom_dsr, rgn + offset_hsgpl_dsr);
273   at29c040a_init(machine,feeprom_dsr);
274}
275
276/*
277    Reset hsgpl card
278*/
279void ti99_hsgpl_reset(running_machine *machine)
280{
281   hsgpl.addr = 0;
282   hsgpl.raddr_LSB = 0;
283   hsgpl.waddr_LSB = 0;
284   hsgpl.cur_port = 0;
285   hsgpl.cur_bank = 0;
286   hsgpl.cru_reg = 0;
287
288   expansion_box = machine->device("per_exp_box");
289
290   /* Card is enabled on startup. */
291   ti99_set_hsgpl_crdena(1);
292
293   ti99_peb_set_card_handlers(expansion_box, 0x1b00, &hsgpl_handlers);
294}
295
296
297/*
298    Write hsgpl CRU interface
299*/
300static void hsgpl_cru_w(running_machine *machine, int offset, int data)
301{
302   offset &= 0xf;
303
304   if (data)
305      hsgpl.cru_reg |= 1 << offset;
306   else
307      hsgpl.cru_reg &= ~ (1 << offset);
308
309   if (offset == cr_crdena_bit)
310      ti99_set_hsgpl_crdena(data);
311}
312
313/*
314    read a byte in hsgpl DSR space (4000-5fff)
315*/
316static  READ8_HANDLER(hsgpl_dsr_r)
317{
318   int dsr_page = (hsgpl.cru_reg >> cr_pg_shift) & cr_pg_mask;
319
320   return at29c040a_r(feeprom_dsr, offset + 0x2000 * dsr_page);
321}
322
323/*
324    GPL read
325*/
326READ16_HANDLER ( ti99_hsgpl_gpl_r )
327{
328   int port;
329   int reply;
330
331   //activecpu_adjust_icount(-4);
332
333   port = hsgpl.cur_port = (offset & 0x1FE) >> 1;
334
335   if (offset & 1)
336   {   /* read GPL address */
337      hsgpl.waddr_LSB = FALSE;   /* right??? */
338
339      if (hsgpl.raddr_LSB)
340      {
341         reply = ((hsgpl.addr + 1) << 8) & 0xff00;
342         hsgpl.raddr_LSB = FALSE;
343      }
344      else
345      {
346         reply = (hsgpl.addr + 1) & 0xff00;
347         hsgpl.raddr_LSB = TRUE;
348      }
349//      printf("hsgpl grmra: [%04x] = %02x\n", (offset<<1)+0x9800, reply>>8);
350   }
351   else
352   {   /* read GPL data */
353      //reply = (data_ptr ? ((int) data_ptr[hsgpl.addr]) : 0) << 8;   /* read data */
354
355      switch (port)
356      {
357      case 0:
358      case 1:
359         if (hsgpl.cru_reg & cr_grmena)
360         {
361            reply = hsgpl.GRAM_ptr[hsgpl.addr + 0x10000*port];
362            break;
363         }
364      case 2:
365      case 3:
366      case 4:
367      case 5:
368      case 6:
369      case 7:
370         reply = at29c040a_r(feeprom_grom0, hsgpl.addr + 0x10000*port);
371         break;
372
373      case 8:
374      case 9:
375      case 10:
376      case 11:
377      case 12:
378      case 13:
379      case 14:
380      case 15:
381         reply = at29c040a_r(feeprom_grom1, hsgpl.addr + 0x10000*(port-8));
382         break;
383
384      case 16:
385      case 17:
386      case 18:
387      case 19:
388      case 20:
389      case 21:
390      case 22:
391      case 23:
392         reply = at29c040a_r(feeprom_dsr, hsgpl.addr + 0x10000*(port-16));
393         break;
394
395      case 24:
396      case 25:
397      case 26:
398      case 27:
399      case 28:
400      case 29:
401      case 30:
402      case 31:
403         /* The HSGPL software manual says 32-47, but this is incorrect */
404         reply = at29c040a_r(feeprom_rom6, hsgpl.addr + 0x10000*(port-24));
405         break;
406
407      case 32:
408      case 33:
409         /* GRAM access */
410         reply = hsgpl.GRAM_ptr[hsgpl.addr + 0x10000*(port-32)];
411         break;
412
413      case 48:
414      case 49:
415         /* RAM6 access */
416         reply = hsgpl.RAM6_ptr[hsgpl.addr];
417         break;
418
419      default:
420         logerror("unknown GPL port\n");
421         reply = 0;
422         break;
423      }
424
425//      printf("hsgpl grmrd: [%04x:%04x] = %02x\n", (offset<<1)+0x9800, hsgpl.addr, reply);
426
427      reply <<= 8;
428
429      /* increment address */
430      hsgpl.addr++;
431      hsgpl.raddr_LSB = hsgpl.waddr_LSB = FALSE;
432   }
433   return reply;
434}
435
436/*
437    GPL write
438*/
439WRITE16_HANDLER ( ti99_hsgpl_gpl_w )
440{
441   int port;
442
443   //activecpu_adjust_icount(-4);
444
445   port = hsgpl.cur_port = (offset & 0x1FE) >> 1;
446
447   if (offset & 1)
448   {   /* write GPL address */
449      hsgpl.raddr_LSB = FALSE;
450
451      if (hsgpl.waddr_LSB)
452      {
453         hsgpl.addr = (hsgpl.addr & 0xFF00) | ((data >> 8) & 0xFF);
454         hsgpl.waddr_LSB = FALSE;
455//          printf("hsgpl grmsa: [%04x:%04x]\n", (offset<<1)+0x9c00, hsgpl.addr);
456      }
457      else
458      {
459         hsgpl.addr = (data & 0xFF00) | (hsgpl.addr & 0xFF);
460
461         hsgpl.waddr_LSB = TRUE;
462      }
463   }
464   else
465   {   /* write GPL data */
466      data = (data >> 8) & 0xFF;
467
468      if (hsgpl.cru_reg & cr_wriena)
469      {
470         switch (port)
471         {
472         case 0:
473         case 1:
474            if (hsgpl.cru_reg & cr_grmena)
475            {
476               hsgpl.GRAM_ptr[hsgpl.addr + 0x10000*port] = data;
477               break;
478            }
479         case 2:
480         case 3:
481         case 4:
482         case 5:
483         case 6:
484         case 7:
485            at29c040a_w(feeprom_grom0, hsgpl.addr + 0x10000*port, data);
486            break;
487
488         case 8:
489         case 9:
490         case 10:
491         case 11:
492         case 12:
493         case 13:
494         case 14:
495         case 15:
496            at29c040a_w(feeprom_grom1, hsgpl.addr + 0x10000*(port-8), data);
497            break;
498
499         case 16:
500         case 17:
501         case 18:
502         case 19:
503         case 20:
504         case 21:
505         case 22:
506         case 23:
507            at29c040a_w(feeprom_dsr, hsgpl.addr + 0x10000*(port-16), data);
508            break;
509
510         case 24:
511         case 25:
512         case 26:
513         case 27:
514         case 28:
515         case 29:
516         case 30:
517         case 31:
518            /* The HSGPL manual says 32-47, but this is incorrect */
519            at29c040a_w(feeprom_rom6, hsgpl.addr + 0x10000*(port-24), data);
520            break;
521
522         case 32:
523         case 33:
524            /* GRAM access */
525            hsgpl.GRAM_ptr[hsgpl.addr + 0x10000*(port-32)] = data;
526            break;
527
528         case 48:
529         case 49:
530            /* RAM6 access */
531            hsgpl.RAM6_ptr[hsgpl.addr] = data;
532            break;
533
534         default:
535            logerror("unknown GPL port\n");
536            break;
537         }
538      }
539
540      hsgpl.addr++;
541      hsgpl.raddr_LSB = hsgpl.waddr_LSB = FALSE;
542   }
543}
544
545/*
546    Cartridge space read
547*/
548READ16_HANDLER ( ti99_hsgpl_rom6_r )
549{
550   int port = hsgpl.cur_port;
551   int reply;
552
553   switch (port)
554   {
555   case 0:
556   case 1:
557      if (hsgpl.cru_reg & cr_ramena)
558      {
559         reply = hsgpl.RAM6_ptr[1 + 2*offset + 0x2000*hsgpl.cur_bank + 0x8000*port];
560         reply |= hsgpl.RAM6_ptr[2*offset + 0x2000*hsgpl.cur_bank + 0x8000*port] << 8;
561         break;
562      }
563   case 2:
564   case 3:
565   case 4:
566   case 5:
567   case 6:
568   case 7:
569   case 8:
570   case 9:
571   case 10:
572   case 11:
573   case 12:
574   case 13:
575   case 14:
576   case 15:
577      reply = at29c040a_r(feeprom_rom6, 1 + 2*offset + 0x2000*hsgpl.cur_bank + 0x8000*port);
578      reply |= at29c040a_r(feeprom_rom6, 2*offset + 0x2000*hsgpl.cur_bank + 0x8000*port) << 8;
579      break;
580
581   case 32:
582   case 33:
583      reply = hsgpl.RAM6_ptr[1 + 2*offset + 0x2000*hsgpl.cur_bank + 0x8000*(port-32)];
584      reply |= hsgpl.RAM6_ptr[2*offset + 0x2000*hsgpl.cur_bank + 0x8000*(port-32)] << 8;
585      break;
586
587   default:
588      logerror("unknown >6000 port\n");
589      reply = 0;
590      break;
591   }
592//  printf("[%02x:%04x] = %04x\n", hsgpl.cur_bank, 0x6000 + 2*offset, reply);
593   return reply;
594}
595
596/*
597    Cartridge space write
598*/
599WRITE16_HANDLER ( ti99_hsgpl_rom6_w )
600{
601   int port = hsgpl.cur_port;
602
603   if (! (hsgpl.cru_reg & cr_bnkinh))
604   {
605      hsgpl.cur_bank = offset & 3;
606      return;      /* right??? */
607   }
608
609   if ((hsgpl.cru_reg & cr_mbxena) && (offset == 0x07ff) && ACCESSING_BITS_8_15)
610   {   /* MBX: mapper at 0x6ffe */
611      hsgpl.cur_bank = (data >> 8) & 0x3;
612      return;
613   }
614
615   // MBX: RAM in 0x6c00-0x6ffd (it is unclear whether the MBX RAM area is
616   // enabled/disabled by the wriena bit).  I guess RAM is unpaged, but it is
617   // not implemented
618   if ((hsgpl.cru_reg & cr_wriena) || ((hsgpl.cru_reg & cr_mbxena) && (offset >= 0x0600) && (offset <= 0x07fe)))
619   {
620      switch (port)
621      {
622      case 0:
623      case 1:
624         if (hsgpl.cru_reg & cr_ramena)
625         {
626            if (ACCESSING_BITS_0_7)
627               hsgpl.RAM6_ptr[1 + 2*offset + 0x2000*hsgpl.cur_bank + 0x8000*port] = data;
628            if (ACCESSING_BITS_8_15)
629               hsgpl.RAM6_ptr[2*offset + 0x2000*hsgpl.cur_bank + 0x8000*port] = data >> 8;
630            break;
631         }
632      case 2:
633      case 3:
634      case 4:
635      case 5:
636      case 6:
637      case 7:
638      case 8:
639      case 9:
640      case 10:
641      case 11:
642      case 12:
643      case 13:
644      case 14:
645      case 15:
646         // feeprom is normally written to using GPL ports, and I don't know
647         // writing through >6000 page is enabled
648#if 0
649         at29c040a_w(feeprom_rom6, 1 + 2*offset + 0x2000*hsgpl.cur_bank + 0x8000*port, data);
650         at29c040a_w(feeprom_rom6, 2*offset + 0x2000*hsgpl.cur_bank + 0x8000*port, data >> 8);
651#endif
652         break;
653
654      case 32:
655      case 33:
656         if (ACCESSING_BITS_0_7)
657            hsgpl.RAM6_ptr[1 + 2*offset + 0x2000*hsgpl.cur_bank + 0x8000*(port-32)] = data;
658         if (ACCESSING_BITS_8_15)
659            hsgpl.RAM6_ptr[2*offset + 0x2000*hsgpl.cur_bank + 0x8000*(port-32)] = data >> 8;
660         break;
661
662      default:
663         logerror("unknown >6000 port\n");
664         break;
665      }
666   }
667}
src/mess/machine/99_hsgpl.h
r9500r9501
1/*
2    SNUG HSGPL card emulation.
3    Raphael Nabet, 2003.
4*/
5
6int ti99_hsgpl_load_flashroms(running_machine *machine, const char *filename);
7int ti99_hsgpl_save_flashroms(running_machine *machine, const char *filename);
8
9void ti99_hsgpl_init(running_machine *machine);
10void ti99_hsgpl_reset(running_machine *machine);
11
12READ16_HANDLER ( ti99_hsgpl_gpl_r );
13WRITE16_HANDLER ( ti99_hsgpl_gpl_w );
14
15READ16_HANDLER ( ti99_hsgpl_rom6_r );
16WRITE16_HANDLER ( ti99_hsgpl_rom6_w );
src/mess/machine/ti99_4x.c
r9500r9501
1/*
2    Machine code for TI99/4, TI-99/4A, TI-99/8, and SNUG SGCPU (a.k.a. 99/4P).
3    Raphael Nabet, 1999-2003.
4    Some code was originally derived from Ed Swartz's V9T9.
5
6    References:
7    * The TI-99/4A Tech Pages.  Great site with complete technical description
8      of the TI99/4a.
9        <http://www.nouspikel.com/ti99/titech.htm>
10    * ftp.whtech.com has schematics and hardware documentations.  The documents
11      of most general interest are:
12        <ftp://ftp.whtech.com//datasheets/Hardware manuals/99-4  console specification and schematic.pdf>
13        <ftp://ftp.whtech.com//datasheets/Hardware manuals/99-4A Console and peripheral Expansion System Technical Data.pdf>
14      Schematics for various extension cards are available in the same directory.
15    * V9T9 source code.  This older emulator was often fairly accurate.
16    * Harald Glaab's site has software and documentation for the various SNUG
17      cards: 99/4P (nicknamed "SGCPU"), EVPC, BwG.
18        <http://home.t-online.de/home/harald.glaab/snug/>
19    * The TI-99/4 CPU ROM is the only source of information for the IR remote
20      handset controller protocol.  I have written a document that explains
21      this protocol.
22    * TI-99/8 ROM source code (6 PC99 disk images):
23        <ftp://ftp.whtech.com//source/998Source Disk1.DSK>
24        ...
25        <ftp://ftp.whtech.com//source/998Source Disk6.DSK>
26    * TI-99/8 schematics.  This is a valuable source of information, BUT the
27      schematics describe an early prototype (no Extended Basic, etc.).
28        <ftp://ftp.whtech.com//datasheets & manuals/99-8 Computer/99-8 schematic.max>
29      I have written an index for the signals on these schematics.
30
31Emulated:
32    * All TI99 basic console hardware, except a few tricks in TMS9901 emulation.
33    * Cartridges with ROM (either non-paged or paged), RAM (minimemory) and
34      GROM.  Supercart and MBX support are not finished.
35    * Speech Synthesizer, with standard speech ROM (no speech ROM expansion).
36    * Disk emulation (SSSD disk images with TI fdc, both SSSD and DSDD with
37      SNUG's BwG and HFDC fdcs).
38    * Hard disk (HFDC and IDE).
39    * Mechatronics mouse.
40    * save minimemory contents
41
42    Compatibility looks quite good.
43
44Issues:
45    * floppy disk timings are not emulated (general issue)
46
47TODO:
48    * support for other peripherals and DSRs as documentation permits
49    * implement the EVPC palette chip
50    * finish 99/4p support: ROM6, HSGPL (implemented, but not fully debugged)
51*/
52
53#include <math.h>
54#include "emu.h"
55#include "tms9901.h"
56#include "video/v9938.h"
57#include "audio/spchroms.h"
58#include "devices/cassette.h"
59#include "ti99_4x.h"
60#include "devices/ti99_peb.h"
61#include "994x_ser.h"
62#include "99_dsk.h"
63#include "99_ide.h"
64#include "99_hsgpl.h"
65#include "99_usbsm.h"
66#include "ti99pcod.h"
67
68#include "sound/tms5220.h"   /* for tms5220_set_variant() */
69#include "sound/sn76496.h"
70
71#include "devices/harddriv.h"   /* for device_init_mess_hd() */
72#include "smc92x4.h"   /* for smc92x4_hd_load()/smc92x4_hd_unload() */
73
74/* prototypes */
75static READ16_HANDLER ( ti99_rspeech_r );
76static WRITE16_HANDLER ( ti99_wspeech_w );
77
78static void ti99_handset_task(running_machine *machine);
79static void mecmouse_poll(running_machine *machine);
80
81static void ti99_8_internal_dsr_reset(running_machine *machine);
82
83static void ti99_4p_internal_dsr_reset(running_machine *machine);
84static void ti99_TIxram_init(running_machine *machine);
85static void ti99_sAMSxram_init(running_machine *machine);
86static void ti99_4p_mapper_init(running_machine *machine);
87static void ti99_myarcxram_init(running_machine *machine);
88static void ti99_evpc_reset(running_machine *machine);
89static void ti99_evpc_load_novram(running_machine *machine, const char *filename);
90static void ti99_evpc_save_novram(running_machine *machine, const char *filename);
91
92/*
93    pointer to extended RAM area
94*/
95static UINT16 *xRAM_ptr;
96
97/*
98    Configuration
99*/
100/* model of ti99 in emulation */
101static enum
102{
103   model_99_4,
104   model_99_4a,
105   model_99_8,
106   model_99_4p
107} ti99_model;
108
109/* TRUE if speech synthesizer present */
110static char has_speech;
111
112/* TRUE if ide card present */
113static char has_ide;
114/* TRUE if evpc card present */
115static char has_evpc;
116/* TRUE if rs232 card present */
117static char has_rs232;
118/* TRUE if ti99/4 IR remote handset present */
119static char has_handset;
120/* TRUE if hsgpl card present */
121static char has_hsgpl;
122static char hsgpl_flash_mode;
123
124/* TRUE if mechatronics mouse present */
125static char has_mecmouse;
126/* TRUE if usb-sm card present */
127static char has_usb_sm;
128
129/* TRUE if p-code card present */
130static char has_pcode;
131
132/* handset interface */
133static int handset_buf;
134static int handset_buflen;
135static int handset_clock;
136static int handset_ack;
137
138/* Expansion RAM type */
139static int xRAM_kind;
140
141enum
142{
143   max_handsets = 4
144};
145
146/* mechatronics  */
147static int mecmouse_sel;
148static int mecmouse_read_y;
149static int mecmouse_x, mecmouse_y;
150static int mecmouse_x_buf, mecmouse_y_buf;
151
152/* keyboard interface */
153static int KeyCol;
154static int AlphaLockLine;
155
156/*
157    GROM support.
158
159In short:
160
161    TI99/4x hardware supports GROMs.  GROMs are slow ROM devices, which are
162    interfaced via a 8-bit data bus, and include an internal address pointer
163    which is incremented after each read.  This implies that accesses are
164    faster when reading consecutive bytes, although the address pointer can be
165    read and written at any time.
166
167    They are generally used to store programs in GPL (Graphic Programming
168    Language: a proprietary, interpreted language - the interpreter takes most
169    of a TI99/4(a) CPU ROMs).  They can used to store large pieces of data,
170    too.
171
172    Both TI-99/4 and TI-99/4a include three GROMs, with some start-up code,
173    system routines and TI-Basic.  TI99/4 includes an additional Equation
174    Editor.  According to the preliminary schematics found on ftp.whtech.com,
175    TI-99/8 includes the three standard GROMs and 16 GROMs for the UCSD
176    p-system.  TI99/2 does not include GROMs at all, and was not designed to
177    support any, although it should be relatively easy to create an expansion
178    card with the GPL interpreter and a /4a cartridge port.
179
180The simple way:
181
182    Each GROM is logically 8kb long.
183
184    Communication with GROM is done with 4 memory-mapped locations.  You can read or write
185    a 16-bit address pointer, and read data from GROMs.  One register allows to write data, too,
186    which would support some GRAMs, but AFAIK TI never built such GRAMs (although docs from TI
187    do refer to this possibility).
188
189    Since address are 16-bit long, you can have up to 8 GROMs.  So, a cartridge may
190    include up to 5 GROMs.  (Actually, there is a way more GROMs can be used - see below...)
191
192    The address pointer is incremented after each GROM operation, but it will always remain
193    within the bounds of the currently selected GROM (e.g. after 0x3fff comes 0x2000).
194
195Some details:
196
197    Original TI-built GROM are 6kb long, but take 8kb in address space.  The extra 2kb can be
198    read, and follow the following formula:
199        GROM[0x1800+offset] = GROM[0x0800+offset] | GROM[0x1000+offset];
200    (sounds like address decoding is incomplete - we are lucky we don't burn any silicon when
201    doing so...)
202
203    Needless to say, some hackers simulated 8kb GRAMs and GROMs with normal RAM/PROM chips and
204    glue logic.
205
206GPL ports:
207
208    When accessing the GROMs registers, 8 address bits (cpu_addr & 0x03FC) may
209    be used as a port number, which permits the use of up to 256 independant
210    GROM ports, with 64kb of address space in each.  TI99/4(a) ROMs can take
211    advantage of the first 16 ports: it will look for GPL programs in every
212    GROM of the 16 first ports.  Additionally, while the other 240 ports cannot
213    contain standard GROMs with GPL code, they may still contain custom GROMs
214    with data.
215
216    Note, however, that the TI99/4(a) console does not decode the page number, so console GROMs
217    occupy the first 24kb of EVERY port, and cartridge GROMs occupy the next 40kb of EVERY port
218    (with the exception of one demonstration from TI that implements several distinct ports).
219    (Note that the TI99/8 console does have the required decoder.)  Fortunately, GROM drivers
220    have a relatively high impedance, and therefore extension cards can use TTL drivers to impose
221    another value on the data bus with no risk of burning the console GROMs.  This hack permits
222    the addition of additionnal GROMs in other ports, with the only side effect that whenever
223    the address pointer in port N is altered, the address pointer of console GROMs in port 0
224    is altered, too.  Overriding the system GROMs with custom code is possible, too (some hackers
225    have done so), but I would not recommended it, as connecting such a device to a TI99/8 might
226    burn some drivers.
227
228    The p-code card (-> UCSD Pascal system) contains 8 GROMs, all in port 16.  This port is not
229    in the range recognized by the TI ROMs (0-15), and therefore it is used by the p-code DSR ROMs
230    as custom data.  Additionally, some hackers used the extra ports to implement "GRAM" devices.
231
232    The handling of cartridge GROMs has moved to ti99cart.c.
233*/
234
235/* descriptor for console GROMs */
236static GROM_port_t console_GROMs;
237
238/* true if hsgpl is enabled (i.e. has_hsgpl is true and hsgpl cru bit crdena is
239set) */
240static char hsgpl_crdena;
241
242/* Used to cache the switch settings. */
243static UINT8 gk_switch[8];
244
245/* DIP switches of EVPC */
246static UINT8 evpc_switch[4];
247
248/* Pointer to the cartridge system for the 99/8 */
249static running_device *multicart8;
250
251/* ti99/8 hardware */
252static UINT8 ti99_8_enable_rom_and_ports;
253
254static UINT32 ti99_8_mapper_regs[16];
255static UINT8 ti99_8_mapper_status;
256
257static UINT8 *xRAM_ptr_8;
258static UINT8 *ROM0_ptr_8;
259static UINT8 *ROM1_ptr_8;
260static UINT8 *ROM2_ptr_8;
261static UINT8 *ROM3_ptr_8;
262static UINT8 *sRAM_ptr_8;
263
264/* tms9900_ICount: used to implement memory waitstates (hack) */
265/* tms9995_ICount: used to implement memory waitstates (hack) */
266/* NPW 23-Feb-2004 - externs no longer needed because we now use cpu_adjust_icount(space->machine->device("maincpu"),) */
267
268/* Link to the cartridge system. */
269static running_device *cartslots;
270
271/* Link to the Peripheral Expansion Box */
272static running_device *expansion_box;
273
274/*===========================================================================*/
275/*
276    General purpose code:
277    initialization, cart loading, etc.
278*/
279
280static void create_grom_high2k(int first, int last)
281{
282   /* Generate missing chunk of each console GROMs. Although a GROM */
283   /* occupies 8 KiB of address space, it only has 6 KiB capacity, and */
284   /* the last 2 KiB mirror previous content as shown above. */
285   int base;
286   for (base=(first&0xe000); base<((last+1)&0xe000); base+=0x2000)
287   {
288      int j;
289      for (j=0; j<0x800; j++)
290      {
291         console_GROMs.data_ptr[base+0x1800+j] =
292              console_GROMs.data_ptr[base+0x0800+j]
293            | console_GROMs.data_ptr[base+0x1000+j];
294      }
295   }
296}
297
298int ti99_is_99_8()
299{
300   return ti99_model == model_99_8;
301}
302
303DRIVER_INIT( ti99_4 )
304{
305   ti99_model = model_99_4;
306   has_evpc = FALSE;
307
308   /* set up memory pointers */
309   xRAM_ptr = (UINT16 *) (memory_region(machine, "maincpu") + offset_xram);
310   console_GROMs.data_ptr = memory_region(machine, region_grom);
311   create_grom_high2k(0x0000, 0x5fff);
312}
313
314DRIVER_INIT( ti99_4a )
315{
316   ti99_model = model_99_4a;
317   has_evpc = FALSE;
318
319   /* set up memory pointers */
320   xRAM_ptr = (UINT16 *) (memory_region(machine, "maincpu") + offset_xram);
321   console_GROMs.data_ptr = memory_region(machine, region_grom);
322   create_grom_high2k(0x0000, 0x5fff);
323}
324
325DRIVER_INIT( ti99_4ev )
326{
327   UINT8 *mem = memory_region(machine, "maincpu");
328   ti99_model = model_99_4a;
329   has_evpc = TRUE;
330
331   /* set up memory pointers */
332   xRAM_ptr = (UINT16 *) (mem + offset_xram);
333   console_GROMs.data_ptr = memory_region(machine, region_grom);
334   create_grom_high2k(0x0000, 0x5fff);
335}
336
337static const TMS9928a_interface tms9918_interface =
338{
339   TMS99x8,
340   0x4000,
341   15, 15,
342   tms9901_set_int2
343};
344
345MACHINE_START( ti99_4_60hz )
346{
347   ti99_common_init(machine, &tms9918_interface);
348}
349
350static const TMS9928a_interface tms9929_interface =
351{
352   TMS9929,
353   0x4000,
354   13, 13,
355   tms9901_set_int2
356};
357
358MACHINE_START( ti99_4_50hz )
359{
360   ti99_common_init(machine, &tms9929_interface);
361}
362
363static const TMS9928a_interface tms9918a_interface =
364{
365   TMS99x8A,
366   0x4000,
367   15, 15,
368   tms9901_set_int2
369};
370
371MACHINE_START( ti99_4a_60hz )
372{
373   ti99_common_init(machine, &tms9918a_interface);
374}
375
376static const TMS9928a_interface tms9929a_interface =
377{
378   TMS9929A,
379   0x4000,
380   13, 13,
381   tms9901_set_int2
382};
383
384MACHINE_START( ti99_4a_50hz )
385{
386   ti99_common_init(machine, &tms9929a_interface);
387}
388
389MACHINE_START( ti99_4ev_60hz)
390{
391   /* has an own VDP, so skip initing the VDP */
392   ti99_common_init(machine, 0);
393}
394
395void ti99_common_init(running_machine *machine, const TMS9928a_interface *gfxparm)
396{
397   if (gfxparm != 0)
398      TMS9928A_configure(gfxparm);
399
400   /* Initialize all. Actually, at this point, we don't know */
401   /* how the switches are set. Later we use the configuration switches */
402   /* to determine which one to use. */
403   ti99_floppy_controllers_init_all(machine);
404   ti99_ide_init(machine);
405   ti99_hsgpl_init(machine);
406   ti99_usbsm_init(machine);
407
408   /* Find the cartslot device and cache it. This is a string search, */
409   /* and we don't want to repeat it on each memory access. */
410   cartslots = machine->device("ti99_multicart");
411   assert(cartslots != NULL);
412}
413
414
415/*
416    ti99_init_machine(); called before ti99_load_rom...
417*/
418MACHINE_RESET( ti99 )
419{
420   address_space *space = cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM);
421   /*console_GROMs.data_ptr = memory_region(machine, region_grom);*/
422   console_GROMs.addr = 0;
423   console_GROMs.buf = 0;
424   console_GROMs.raddr_LSB = FALSE;
425   console_GROMs.waddr_LSB = FALSE;
426
427   expansion_box = machine->device("per_exp_box");
428
429   /* set up scratch pad pointer */
430   memory_set_bankptr(machine, "bank1", memory_region(machine, "maincpu") + offset_sram);
431
432   if (!has_evpc) TMS9928A_reset();
433   else v9938_reset(0);
434
435   /* clear keyboard interface state (probably overkill, but can't harm) */
436   KeyCol = 0;
437   AlphaLockLine = 0;
438
439   /* reset handset */
440   handset_buf = 0;
441   handset_buflen = 0;
442   handset_clock = 0;
443   handset_ack = 0;
444   tms9901_set_single_int(machine->device("tms9901"), 12, 0);
445
446   /* read config */
447   xRAM_kind = input_port_read(machine, "RAM");
448
449   has_speech = input_port_read(machine, "SPEECH");
450   has_ide = input_port_read(machine, "HDCTRL") & HD_IDE;
451   has_rs232 = input_port_read(machine, "SERIAL") & SERIAL_TI;
452   has_handset = (ti99_model == model_99_4)? (input_port_read(machine, "HCI") & HCI_IR) : FALSE;
453   has_mecmouse = input_port_read(machine, "HCI") & HCI_MECMOUSE;
454   has_hsgpl = input_port_read(machine, "EXTCARD") & (EXT_HSGPL_ON | EXT_HSGPL_FLASH);
455   has_usb_sm = input_port_read(machine, "HDCTRL") & HD_USB;
456   has_pcode = input_port_read(machine, "EXTCARD") & EXT_PCODE;
457
458   hsgpl_flash_mode = input_port_read(machine, "EXTCARD") & EXT_HSGPL_FLASH;
459
460   /* Get the GK settings once */
461   gk_switch[1] = input_port_read(machine, "GKSWITCH1");
462   gk_switch[2] = input_port_read(machine, "GKSWITCH2");
463   gk_switch[3] = input_port_read(machine, "GKSWITCH3");
464   gk_switch[4] = input_port_read(machine, "GKSWITCH4");
465   gk_switch[5] = input_port_read(machine, "GKSWITCH5");
466
467   // set up optional expansion hardware
468   if (has_speech)
469   {
470      static const spchroms_interface speech_intf = { region_speech_rom };
471
472      spchroms_config(machine, &speech_intf);
473
474      memory_install_read16_handler(space, 0x9000, 0x93ff, 0, 0, ti99_rspeech_r);
475      memory_install_write16_handler(space, 0x9400, 0x97ff, 0, 0, ti99_wspeech_w);
476   }
477   else
478   {
479      memory_install_read16_handler(space, 0x9000, 0x93ff, 0, 0, ti99_nop_8_r);
480      memory_install_write16_handler(space, 0x9400, 0x97ff, 0, 0, ti99_nop_8_w);
481   }
482
483   switch (xRAM_kind)
484   {
485   case RAM_TI32:
486      ti99_TIxram_init(machine);
487      break;
488   case RAM_SUPERAMS1024:
489      ti99_sAMSxram_init(machine);
490      break;
491   case RAM_FOUNDATION128:
492   case RAM_FOUNDATION512:
493   case RAM_MYARC128:
494   case RAM_MYARC512:
495      ti99_myarcxram_init(machine);
496      break;
497   case RAM_NONE:
498   default:
499      memory_install_read16_handler(space, 0x2000, 0x3fff, 0, 0, ti99_nop_8_r);
500      memory_install_write16_handler(space, 0x2000, 0x3fff, 0, 0, ti99_nop_8_w);
501      memory_install_read16_handler(space, 0xa000, 0xffff, 0, 0, ti99_nop_8_r);
502      memory_install_write16_handler(space, 0xa000, 0xffff, 0, 0, ti99_nop_8_w);
503      break;
504   }
505
506   switch (input_port_read(machine, "DISKCTRL"))
507   {
508   case DISK_TIFDC:
509      ti99_fdc_reset(machine);
510      break;
511#if HAS_99CCFDC
512   case DISK_CC:
513      ti99_ccfdc_reset(machine);
514      break;
515#endif
516   case DISK_BWG:
517      ti99_bwg_reset(machine);
518      break;
519   case DISK_HFDC:
520      ti99_hfdc_reset(machine);
521      break;
522   case DISK_NONE:
523      break;
524   }
525
526   if (has_ide)
527      ti99_ide_reset(machine, FALSE);
528
529   if (has_hsgpl)
530      ti99_hsgpl_reset(machine);
531   else
532      hsgpl_crdena = 0;
533
534   if (has_usb_sm)
535      ti99_usbsm_reset(machine, FALSE);
536
537   if (has_evpc)
538   {
539      /* Get the EVPC settings once */
540      evpc_switch[0] = input_port_read(machine, "EVPC-SW1");
541      evpc_switch[1] = input_port_read(machine, "EVPC-SW3");
542      evpc_switch[2] = input_port_read(machine, "EVPC-SW4");
543      evpc_switch[3] = input_port_read(machine, "EVPC-SW8");
544      ti99_evpc_reset(machine);
545   }
546
547   if (has_pcode)
548      ti99_pcode_reset(machine);
549
550   /* initialize mechatronics mouse */
551   mecmouse_sel = 0;
552   mecmouse_read_y = 0;
553   mecmouse_x = 0;
554   mecmouse_y = 0;
555}
556
557#ifdef UNUSED_FUNCTION
558void machine_stop_ti99(void)
559{
560   if (has_hsgpl)
561      ti99_hsgpl_save_memcard();
562
563   if (has_rs232)
564      ti99_rs232_cleanup();
565
566   tms9901_cleanup(0);
567}
568#endif
569
570NVRAM_HANDLER( ti99 )
571{
572   // called from generic.c
573   // (running_machine *machine, mame_file *file, int read_or_write)
574
575   astring *hsname = astring_assemble_3(astring_alloc(), machine->gamedrv->name, PATH_SEPARATOR, "hsgpl.nv");
576   astring *evname = astring_assemble_3(astring_alloc(), machine->gamedrv->name, PATH_SEPARATOR, "evpc.nv");
577
578   // We always try to read the HSGPL, even when the config switch is
579   // set to off. Otherwise, when the system is started without HSGPL
580   // and we later switch on the card and do a reset, the console locks
581   // up as it does not find any content. Likewise, we save the contents
582   // even when the card has been turned off during runtime.
583   if (read_or_write==0)
584   {
585      ti99_hsgpl_load_flashroms(machine, astring_c(hsname));
586      if (has_evpc) ti99_evpc_load_novram(machine, astring_c(evname));
587   }
588   else
589   {
590      ti99_hsgpl_save_flashroms(machine, astring_c(hsname));
591      if (has_evpc) ti99_evpc_save_novram(machine, astring_c(evname));
592   }
593
594   astring_free(hsname);
595   astring_free(evname);
596}
597
598INPUT_CHANGED( hsgpl_changed )
599{
600   hsgpl_flash_mode = newval & EXT_HSGPL_FLASH;
601}
602
603INPUT_CHANGED( gk_changed )
604{
605   gk_switch[(UINT64)param&0x07] = newval;
606}
607
608UINT8 get_gk_switch(int index)
609{
610   return gk_switch[index];
611}
612
613/*
614    VBL interrupt  (mmm...  actually, it happens when the beam enters the lower
615    border, so it is not a genuine VBI, but who cares ?)
616*/
617INTERRUPT_GEN( ti99_vblank_interrupt )
618{
619   TMS9928A_interrupt(device->machine);
620   if (has_handset)
621      ti99_handset_task(device->machine);
622   if (has_mecmouse)
623      mecmouse_poll(device->machine);
624}
625
626/*
627    Backdoor function that is called by hsgpl, so that the machine code knows
628    whether hsgpl or console GROMs are active
629    Called from 99_hsgpl.c
630*/
631void ti99_set_hsgpl_crdena(int data)
632{
633   hsgpl_crdena = (data != 0);
634}
635
636/*===========================================================================*/
637#if 0
638#pragma mark -
639#pragma mark MEMORY HANDLERS
640#endif
641/*
642    Memory handlers.
643
644    TODO:
645    * actually implement GRAM support and GPL port support
646*/
647
648/*
649    Same as MRA16_NOP, but with an additionnal delay caused by the 16->8 bit
650    bus multiplexer.
651*/
652READ16_HANDLER ( ti99_nop_8_r )
653{
654   cpu_adjust_icount(space->machine->device("maincpu"),-4);
655//  cpu_spinuntil_time(space->machine->firstcpu, ATTOTIME_IN_USEC(6));
656
657   return (0);
658}
659
660WRITE16_HANDLER ( ti99_nop_8_w )
661{
662   cpu_adjust_icount(space->machine->device("maincpu"),-4);
663//  cpu_spinuntil_time(space->machine->firstcpu, ATTOTIME_IN_USEC(6));
664}
665
666/*
667    Cartridge space (>6000->7FFF). This is usually connected to the cartridge
668    port, but is also used by the HSGPL. So we need to check this here and then
669    delegate to the respective component.
670*/
671READ16_HANDLER ( ti99_cart_r )
672{
673   if (hsgpl_crdena && !hsgpl_flash_mode)
674      /* hsgpl is enabled */
675      return ti99_hsgpl_rom6_r(space, offset, mem_mask);
676   return ti99_multicart_r(cartslots, offset, mem_mask);
677}
678
679/*
680    Cartridge space (>6000->7FFF). This is usually connected to the cartridge
681    port, but is also used by the HSGPL. So we need to check this here and then
682    delegate to the respective component.
683*/
684WRITE16_HANDLER ( ti99_cart_w )
685{
686   // Writing always means that we access the cartridges (and possibly the HGSPL)
687   // Except when we use the SGCPU.
688   if (ti99_model != model_99_4p)
689      ti99_multicart_w(cartslots, offset, data, mem_mask);
690
691   if (hsgpl_crdena && !hsgpl_flash_mode)
692      /* hsgpl is enabled */
693      ti99_hsgpl_rom6_w(space, offset, data, mem_mask);
694}
695
696/*---------------------------------------------------------------------------*/
697/*
698    memory-mapped register handlers.
699
700Theory:
701
702    These are registers to communicate with several peripherals.
703    These registers are all 8-bit-wide, and are located at even adresses between
704    0x8400 and 0x9FFE.
705    The registers are identified by (addr & 1C00), and, for VDP and GPL access,
706    by (addr & 2).  These registers are either read-only or write-only.  (Or,
707    more accurately, (addr & 4000) disables register read, whereas
708    !(addr & 4000) disables register write.)
709
710    Memory mapped registers list:
711    - write sound chip. (8400-87FE)
712    - read VDP memory. (8800-8BFC), (addr&2) == 0
713    - read VDP status. (8802-8BFE), (addr&2) == 2
714    - write VDP memory. (8C00-8FFC), (addr&2) == 0
715    - write VDP address and VDP register. (8C02-8FFE), (addr&2) == 2
716    - read speech synthesis chip. (9000-93FE)
717    - write speech synthesis chip. (9400-97FE)
718    - read GPL memory. (9800-9BFC), (addr&2) == 0 (1)
719    - read GPL adress. (9802-9BFE), (addr&2) == 2 (1)
720    - write GPL memory. (9C00-9FFC), (addr&2) == 0 (1)
721    - write GPL adress. (9C02-9FFE), (addr&2) == 2 (1)
722
723(1) on some hardware, (addr & 0x3FC) provides a GPL page number.
724*/
725
726/*
727    TMS9919 sound chip write
728*/
729WRITE16_HANDLER ( ti99_wsnd_w )
730{
731   cpu_adjust_icount(space->machine->device("maincpu"),-4);
732//  cpu_spinuntil_time(space->machine->firstcpu, ATTOTIME_IN_USEC(6));
733
734   sn76496_w(space->machine->device("sn76496"), offset, (data >> 8) & 0xff);
735}
736
737/*
738    TMS9918(A)/9928(A)/9929(A) VDP read
739*/
740READ16_HANDLER ( ti99_rvdp_r )
741{
742   cpu_adjust_icount(space->machine->device("maincpu"),-4);
743//  cpu_spinuntil_time(space->machine->firstcpu, ATTOTIME_IN_USEC(6));
744
745   if (offset & 1)
746   {   /* read VDP status */
747      return ((int) TMS9928A_register_r(space, 0)) << 8;
748   }
749   else
750   {   /* read VDP RAM */
751      return ((int) TMS9928A_vram_r(space, 0)) << 8;
752   }
753}
754
755/*
756    TMS9918(A)/9928(A)/9929(A) vdp write
757*/
758WRITE16_HANDLER ( ti99_wvdp_w )
759{
760   cpu_adjust_icount(space->machine->device("maincpu"),-4);
761//  cpu_spinuntil_time(space->machine->firstcpu, ATTOTIME_IN_USEC(6));
762
763   if (offset & 1)
764   {   /* write VDP address */
765      TMS9928A_register_w(space, 0, (data >> 8) & 0xff);
766   }
767   else
768   {   /* write VDP data */
769      TMS9928A_vram_w(space, 0, (data >> 8) & 0xff);
770   }
771}
772
773/*
774    TMS0285 speech chip read
775*/
776static READ16_HANDLER ( ti99_rspeech_r )
777{
778   cpu_adjust_icount(space->machine->device("maincpu"),-(18+3));      /* this is just a minimum, it can be more */
779
780   return ((int) tms5220_status_r(space->machine->device("tmc0285"), offset)) << 8;
781}
782
783#if 0
784
785static void speech_kludge_callback(int dummy)
786{
787   if (! tms5220_readyq_r())
788   {
789      /* Weirdly enough, we are always seeing some problems even */
790      /* though everything is working fine. */
791      attotime time_to_ready = double_to_attotime(tms5220_time_to_ready());
792      logerror("ti99/4a speech says aaargh!\n");
793      logerror("(time to ready: %f -> %d)\n", time_to_ready, (int) ceil(3000000*time_to_ready));
794   }
795}
796
797#endif
798
799/*
800    TMS0285 speech chip write
801*/
802static WRITE16_HANDLER ( ti99_wspeech_w )
803{
804   cpu_adjust_icount(space->machine->device("maincpu"),-(54+3));      /* this is just an approx. minimum, it can be much more */
805
806   #if 1
807   /* the stupid design of the tms5220 core means that ready is cleared */
808   /* when there are 15 bytes in FIFO.  It should be 16.  Of course, if */
809   /* it were the case, we would need to store the value on the bus, */
810   /* which would be more complex. */
811   if (! tms5220_readyq_r(space->machine->device("tmc0285")))
812   {
813      attotime time_to_ready = double_to_attotime(tms5220_time_to_ready(space->machine->device("tmc0285")));
814      int cycles_to_ready = space->machine->device<cpu_device>("maincpu")->attotime_to_cycles(time_to_ready);
815
816      logerror("time to ready: %f -> %d\n", attotime_to_double(time_to_ready), (int) cycles_to_ready);
817
818      cpu_adjust_icount(space->machine->device("maincpu"),-cycles_to_ready);
819      timer_set(space->machine, attotime_zero, NULL, 0, /*speech_kludge_callback*/NULL);
820   }
821   #endif
822
823   tms5220_data_w(space->machine->device("tmc0285"), offset, (data >> 8) & 0xff);
824}
825
826static UINT8 GROM_dataread(running_machine *machine, offs_t offset)
827{
828   UINT8 reply = 0, replycart;
829   int override_console = FALSE;
830
831   // Operation of GRAMKracker
832   if (input_port_read(machine, "CARTSLOT")==CART_GK)
833   {
834      if (((console_GROMs.addr < 0x2000) && (gk_switch[2]==GK_GRAM0))
835         || ((console_GROMs.addr >= 0x2000) && (console_GROMs.addr < 0x4000) &&
836            ((gk_switch[3]==GK_GRAM12) || (gk_switch[5]==GK_LDON)))
837         || ((console_GROMs.addr >= 0x4000) && (console_GROMs.addr < 0x6000) &&
838            (gk_switch[3]==GK_GRAM12)))
839      {
840         override_console = TRUE;
841      }
842   }
843
844   if (console_GROMs.addr < 0x6000)
845   {
846      /* GROMs are buffered. Data is retrieved from a buffer, */
847      /* while the buffer is replaced with the next cell content. */
848      reply = console_GROMs.buf;
849
850      /* Get next value, put it in buffer. Note that the GROM */
851      /* wraps at 8K boundaries. */
852      console_GROMs.buf = console_GROMs.data_ptr[console_GROMs.addr];
853   }
854
855   // The address pointer in the cartridge system is updated by this call
856   replycart = ti99_cartridge_grom_r(cartslots, offset);
857
858   if (console_GROMs.addr >= 0x6000 || override_console)
859   {
860      reply = replycart;
861   }
862
863   /* Each GROM chip has its own counter, so we update all of them even */
864   /* when we do not access them. */
865   /* The program counter wraps at each GROM chip size (8K), */
866   /* so 0x5fff + 1 = 0x4000. */
867   console_GROMs.addr = ((console_GROMs.addr + 1) & 0x1FFF) | (console_GROMs.addr & 0xE000);
868
869   /* Reset the read and write address flipflops. */
870   console_GROMs.raddr_LSB = console_GROMs.waddr_LSB = FALSE;
871
872   return reply;
873}
874
875static void GRAM_datawrite(offs_t offset, UINT8 data)
876{
877   // The console does not contain RAM at these locations.
878   // Writing has only effect when there is a GRAM Kracker
879   ti99_cartridge_grom_w(cartslots, offset, data);
880
881   /* Each GROM chip has its own counter, so we update all of them even */
882   /* when we do not access them. */
883   /* The program counter wraps at each GROM chip size (8K), */
884   /* so 0x5fff + 1 = 0x4000. */
885   console_GROMs.addr = ((console_GROMs.addr + 1) & 0x1FFF) | (console_GROMs.addr & 0xE000);
886
887   /* Reset the read and write address flipflops. */
888   console_GROMs.raddr_LSB = console_GROMs.waddr_LSB = FALSE;
889}
890
891
892/*
893    GPL read
894*/
895READ16_HANDLER ( ti99_grom_r )
896{
897   UINT16 reply, replycart;
898
899   cpu_adjust_icount(space->machine->device("maincpu"),-4 /*20+3*/);      /* from 4 to 23? */
900   //  cpu_spinuntil_time(space->machine->firstcpu, ATTOTIME_IN_USEC(6));
901
902   /* This implementation features a multislot cartridge system which    */
903   /* is based on multiple GROM base addresses. The standard base        */
904   /* is >9800 (slot 0). When we access the port >9804, we switch to     */
905   /* slot 1, >9808 is slot 2, ... >983C is slot 15. Although            */
906   /* theoretically we could address up to 256 banks, the TI operating   */
907   /* system does not check more than 16 banks.                          */
908   /* Cartridges may also contain ROMs which need to be banked           */
909   /* simultaneously. We use the cartridge slot number to swap the ROM   */
910   /* at >6000, or RAM if available. I don't know whether this is the    */
911   /* way Texas Instruments envisaged it in the OS, but it is the only   */
912   /* plausible way to allow for GROM+ROM cartridges.                    */
913   /* Note that some cartridges may have programming flaws which only    */
914   /* appear when the cartridge is used in a higher-numbered slot.       */
915   /* Parsec is one example which only runs in slot 0 as the             */
916   /* programmers hard-coded an access to GROM port 0. Note: This *may*  */
917   /* be worked around if we make sure that switching only occurs        */
918   /* when the address is set, not when data is read or written. But     */
919   /* it's not clear whether this has unwanted side effects.             */
920
921   if (offset & 1)
922   {   /* Read GROM address */
923      /* We only have one GROM program counter for the console */
924      /* GROMs and all cartridge GROMs in all banks(!). Hardware */
925      /* implementations must take this into account as well. Thus, */
926      /* we use a structure here in the console, rather than */
927      /* separate counters in each GROM chip. */
928
929      /* We call the cartridge system here, but we ignore the */
930      /* value. This is done to sync the flags. */
931      replycart = ti99_cartridge_grom_r(cartslots, (offset<<1))<<8;
932
933      /* When reading, reset the hi/lo flag byte for writing. */
934      /* TODO: Verify this with a real machine. */
935      console_GROMs.waddr_LSB = FALSE;
936
937      /* Address reading is done in two steps; first, the high byte */
938      /* is transferred, then the low byte. */
939      if (console_GROMs.raddr_LSB)
940      {
941         /* second pass */
942         reply = (console_GROMs.addr << 8) & 0xff00;
943         console_GROMs.raddr_LSB = FALSE;
944      }
945      else
946      {
947         /* first pass */
948         reply = console_GROMs.addr & 0xff00;
949         console_GROMs.raddr_LSB = TRUE;
950      }
951      /* GROM address values must be globally unique. */
952      assert (replycart == reply);
953   }
954   else
955   {
956      /* Read GROM data */
957      /* Note that we shift the GROM port address to accomodate for */
958      /* 8-bit and 16-bit systems. */
959      reply = ((UINT16)GROM_dataread(space->machine, offset<<1)) << 8;
960   }
961
962   if (hsgpl_crdena)
963   {
964      /* We must prevent the HSGPL to override the console GROMs */
965      /* when it is not yet set up - or the console will get stuck */
966      /* in a black screen. The "flash mode" allows to read GROMs */
967      /* only in higher banks; writing is enabled for all banks. */
968      int bank = (offset>>1)&0xff;
969      if (!hsgpl_flash_mode || (bank>=16))
970      {
971         /* hsgpl buffers always override console GROM buffers */
972         reply = ti99_hsgpl_gpl_r(space, offset, mem_mask);
973      }
974   }
975
976   return reply;
977}
978
979/*
980    GPL write
981*/
982WRITE16_HANDLER ( ti99_grom_w )
983{
984   cpu_adjust_icount(space->machine->device("maincpu"),-4/*20+3*/);      /* from 4 to 23? */
985   //  cpu_spinuntil_time(space->machine->firstcpu, ATTOTIME_IN_USEC(6));
986
987   if (offset & 1)
988   {
989      ti99_cartridge_grom_w(cartslots, (offset<<1), (data>>8)&0xff);
990
991      /* write GROM address */
992      /* see comments above */
993      console_GROMs.raddr_LSB = FALSE;
994
995      /* Implements the internal flipflop. */
996      /* The Editor/Assembler manuals says that the current address */
997      /* plus one is returned. This effect is properly emulated */
998      /* by using a read-ahead buffer. */
999      if (console_GROMs.waddr_LSB)
1000      {
1001         /* Accept low byte (2nd write) */
1002         console_GROMs.addr = (console_GROMs.addr & 0xFF00) | ((data >> 8) & 0xFF);
1003         /* Setting the address causes a new read, putting the */
1004         /* value into the buffer. We don't need the value here. */
1005         GROM_dataread(space->machine, (offset<<1)&0xfffc);
1006         console_GROMs.waddr_LSB = FALSE;
1007      }
1008      else
1009      {
1010         /* Accept high byte (1st write) */
1011         console_GROMs.addr = (data & 0xFF00) | (console_GROMs.addr & 0xFF);
1012         console_GROMs.waddr_LSB = TRUE;
1013      }
1014   }
1015   else
1016   {
1017      /* write GRAM data */
1018      GRAM_datawrite(offset<<1, (data>>8)&0xff);
1019      console_GROMs.raddr_LSB = console_GROMs.waddr_LSB = FALSE;
1020   }
1021
1022   if (hsgpl_crdena)
1023   {
1024      /* If the HSGPL card is used, we always attempt to write to */
1025      /* its memory, even in flash mode. Writing does no harm to */
1026      /* the internal GROMs. */
1027      ti99_hsgpl_gpl_w(space, offset, data, mem_mask);
1028   }
1029}
1030
1031/*===========================================================================*/
1032#if 0
1033#pragma mark -
1034#pragma mark TI-99/4 HANDSETS
1035#endif
1036/*
1037    Handset support (TI99/4 only)
1038
1039    The ti99/4 was intended to support some so-called "IR remote handsets".
1040    This feature was canceled at the last minute (reportedly ten minutes before
1041    the introductory press conference in June 1979), but the first thousands of
1042    99/4 units had the required port, and the support code was seemingly not
1043    deleted from ROMs until the introduction of the ti99/4a in 1981.  You could
1044    connect up to 4 20-key keypads, and up to 4 joysticks with a maximum
1045    resolution of 15 levels on each axis.
1046
1047    The keyboard DSR was able to couple two 20-key keypads together to emulate
1048    a full 40-key keyboard.  Keyboard modes 0, 1 and 2 would select either the
1049    console keyboard with its two wired remote controllers (i.e. joysticks), or
1050    remote handsets 1 and 2 with their associated IR remote controllers (i.e.
1051    joysticks), according to which was currently active.
1052*/
1053
1054/*
1055    ti99_handset_poll_bus()
1056
1057    Poll the current state of the 4-bit data bus that goes from the I/R
1058    receiver to the tms9901.
1059*/
1060static int ti99_handset_poll_bus(void)
1061{
1062   return (has_handset) ? (handset_buf & 0xf) : 0;
1063}
1064
1065/*
1066    ti99_handset_ack_callback()
1067
1068    Handle data acknowledge sent by the ti-99/4 handset ISR (through tms9901
1069    line P0).  This function is called by a delayed timer 30us after the state
1070    of P0 is changed, because, in one occasion, the ISR asserts the line before
1071    it reads the data, so we need to delay the acknowledge process.
1072*/
1073static TIMER_CALLBACK(ti99_handset_ack_callback)
1074{
1075   handset_clock = ! handset_clock;
1076   handset_buf >>= 4;
1077   handset_buflen--;
1078   tms9901_set_single_int(machine->device("tms9901"), 12, 0);
1079
1080   if (handset_buflen == 1)
1081   {
1082      // Unless I am missing something, the third and last nybble of the
1083      // message is not acknowledged by the DSR in any way, and the first nybble
1084      // of next message is not requested for either, so we need to decide on
1085      // our own when we can post a new event.  Currently, we wait for 1000us
1086      // after the DSR acknowledges the second nybble.
1087      timer_set(machine, ATTOTIME_IN_USEC(1000), NULL, 0, ti99_handset_ack_callback);
1088   }
1089
1090   if (handset_buflen == 0)
1091      /* See if we need to post a new event */
1092      ti99_handset_task(machine);
1093}
1094
1095/*
1096    ti99_handset_set_ack()
1097    Handler for tms9901 P0 pin (handset data acknowledge)
1098*/
1099static WRITE8_DEVICE_HANDLER( ti99_handset_set_ack )
1100{
1101   if (has_handset && handset_buflen && (data != handset_ack))
1102   {
1103      handset_ack = data;
1104      if (data == handset_clock)
1105         /* I don't know what the real delay is, but 30us apears to be enough */
1106         timer_set(device->machine, ATTOTIME_IN_USEC(30), NULL, 0, ti99_handset_ack_callback);
1107   }
1108}
1109
1110/*
1111    ti99_handset_post_message()
1112
1113    Post a 12-bit message: trigger an interrupt on the tms9901, and store the
1114    message in the I/R receiver buffer so that the handset ISR will read this
1115    message.
1116
1117    message: 12-bit message to post (only the 12 LSBits are meaningful)
1118*/
1119static void ti99_handset_post_message(running_machine *machine, int message)
1120{
1121   /* post message and assert interrupt */
1122   handset_clock = 1;
1123   handset_buf = ~ message;
1124   handset_buflen = 3;
1125   tms9901_set_single_int(machine->device("tms9901"), 12, 1);
1126}
1127
1128/*
1129    ti99_handset_poll_keyboard()
1130    Poll the current state of one given handset keypad.
1131    num: number of the keypad to poll (0-3)
1132    Returns TRUE if the handset state has changed and a message was posted.
1133*/
1134static int ti99_handset_poll_keyboard(running_machine *machine, int num)
1135{
1136   static UINT8 previous_key[max_handsets];
1137
1138   UINT32 key_buf;
1139   UINT8 current_key;
1140   int i;
1141   static const char *const keynames[] = { "KP0", "KP1", "KP2", "KP3", "KP4" };
1142
1143   /* read current key state */
1144   key_buf = ( input_port_read(machine, keynames[num]) | (input_port_read(machine, keynames[num + 1]) << 16) ) >> (4*num);
1145
1146   // If a key was previously pressed, this key was not shift, and this key is
1147   // still down, then don't change the current key press.
1148   if (previous_key[num] && (previous_key[num] != 0x24)
1149      && (key_buf & (1 << (previous_key[num] & 0x1f))))
1150   {
1151      /* check the shift modifier state */
1152      if (((previous_key[num] & 0x20) != 0) == ((key_buf & 0x0008) != 0))
1153         /* the shift modifier state has not changed */
1154      return FALSE;
1155      else
1156      {
1157         // The shift modifier state has changed: we need to update the
1158         // keyboard state
1159         if (key_buf & 0x0008)
1160         {   /* shift has been pressed down */
1161            previous_key[num] = current_key = previous_key[num] | 0x20;
1162         }
1163         else
1164         {   /* shift has been pressed down */
1165            previous_key[num] = current_key = previous_key[num] & ~0x20;
1166         }
1167         /* post message */
1168         ti99_handset_post_message(machine, (((unsigned) current_key) << 4) | (num << 1));
1169
1170         return TRUE;
1171      }
1172
1173   }
1174
1175   current_key = 0;   /* default value if no key is down */
1176   for (i=0; i<20; i++)
1177   {
1178      if (key_buf & (1 << i))
1179      {
1180         current_key = i + 1;
1181         if (key_buf & 0x0008)
1182            current_key |= 0x20;   /* set shift flag */
1183
1184         if (current_key != 0x24)
1185            // If this is the shift key, any other key we may find will
1186            // have higher priority; otherwise, we may exit the loop and keep
1187            // the key we have just found.
1188            break;
1189      }
1190   }
1191
1192   if (current_key != previous_key[num])
1193   {
1194      previous_key[num] = current_key;
1195
1196      /* post message */
1197      ti99_handset_post_message(machine, (((unsigned) current_key) << 4) | (num << 1));
1198
1199      return TRUE;
1200   }
1201
1202   return FALSE;
1203}
1204
1205/*
1206    ti99_handset_poll_joystick()
1207
1208    Poll the current state of one given handset joystick.
1209    num: number of the joystick to poll (0-3)
1210    Returns TRUE if the handset state has changed and a message was posted.
1211*/
1212static int ti99_handset_poll_joystick(running_machine *machine, int num)
1213{
1214   static UINT8 previous_joy[max_handsets];
1215   UINT8 current_joy;
1216   int current_joy_x, current_joy_y;
1217   int message;
1218   static const char *const joynames[2][4] =
1219         {
1220            { "JOY0", "JOY2", "JOY4", "JOY6" },      // X axis
1221            { "JOY1", "JOY3", "JOY5", "JOY7" }      // Y axis
1222         };
1223
1224   /* read joystick position */
1225   current_joy_x = input_port_read(machine, joynames[0][num]);
1226   current_joy_y = input_port_read(machine, joynames[1][num]);
1227   /* compare with last saved position */
1228   current_joy = current_joy_x | (current_joy_y << 4);
1229   if (current_joy != previous_joy[num])
1230   {
1231      /* save position */
1232      previous_joy[num] = current_joy;
1233
1234      /* transform position to signed quantity */
1235      current_joy_x -= 7;
1236      current_joy_y -= 7;
1237
1238      message = 0;
1239
1240      /* set sign */
1241      // note that we set the sign if the joystick position is 0 to work
1242      // around a bug in the ti99/4 ROMs
1243      if (current_joy_x <= 0)
1244      {
1245         message |= 0x040;
1246         current_joy_x = - current_joy_x;
1247      }
1248
1249      if (current_joy_y <= 0)
1250      {
1251         message |= 0x400;
1252         current_joy_y = - current_joy_y;
1253      }
1254
1255      /* convert absolute values to Gray code and insert in message */
1256      if (current_joy_x & 4)
1257         current_joy_x ^= 3;
1258      if (current_joy_x & 2)
1259         current_joy_x ^= 1;
1260      message |= current_joy_x << 3;
1261
1262      if (current_joy_y & 4)
1263         current_joy_y ^= 3;
1264      if (current_joy_y & 2)
1265         current_joy_y ^= 1;
1266      message |= current_joy_y << 7;
1267
1268      /* set joystick address */
1269      message |= (num << 1) | 0x1;
1270
1271      /* post message */
1272      ti99_handset_post_message(machine, message);
1273
1274      return TRUE;
1275   }
1276
1277   return FALSE;
1278}
1279
1280/*
1281    ti99_handset_task()
1282    Manage handsets, posting an event if the state of any handset has changed.
1283*/
1284static void ti99_handset_task(running_machine *machine)
1285{
1286   int i;
1287
1288   if (handset_buflen == 0)
1289   {   /* poll every handset */
1290      for (i=0; i<max_handsets; i++)
1291         if (ti99_handset_poll_joystick(machine, i))
1292            return;
1293      for (i=0; i<max_handsets; i++)
1294         if (ti99_handset_poll_keyboard(machine, i))
1295            return;
1296   }
1297   else if (handset_buflen == 3)
1298   {   /* update messages after they have been posted */
1299      if (handset_buf & 1)
1300      {   /* keyboard */
1301         ti99_handset_poll_keyboard(machine, (~ (handset_buf >> 1)) & 0x3);
1302      }
1303      else
1304      {   /* joystick */
1305         ti99_handset_poll_joystick(machine, (~ (handset_buf >> 1)) & 0x3);
1306      }
1307   }
1308}
1309
1310
1311/*===========================================================================*/
1312#if 0
1313#pragma mark -
1314#pragma mark MECHATRONICS MOUSE
1315#endif
1316
1317static void mecmouse_select(int selnow, int stick1, int stick2)
1318{
1319   /* The Mechatronic mouse is connected to the joystick port and occupies
1320    both joystick select lines and the switch lines. From these five
1321    lines, left/right/down are used for the motion (i.e. 3 motion steps
1322    for positive and four for negative motion and one for rest),
1323    the fire line is used for the secondary mouse button, and the up
1324    line is used for the primary button.
1325    The mouse motion is delivered by the same lines for both directions;
1326    this requires swapping the axes. According to the source code of
1327    the accompanying mouse driver, the readout of the current axis is
1328    done by selecting joystick 1, then joystick 2. The axis swapping is
1329    achieved by selecting stick 1 again. When selecting stick 2, the
1330    second axis is seen on the input lines.
1331    Interrupting this sequence will lead to swapped axes. This is
1332    prevented by resetting the toggle when the mouse is deselected
1333    (neither 1 nor 2 are selected).
1334
1335    The joystick lines are selected as follows:
1336    TI-99/4:  Stick 1: P4=1, P3=0, P2=1 (5)
1337    Stick 2: P4=1, P3=1, P2=0 (6)
1338
1339    TI-99/4A: Stick 1: P4=1, P3=1, P2=0 (6)
1340    Stick 2: P4=1, P3=1, P2=1 (7)
1341
1342    TI-99/8:  Stick 1: P3=1, P2=1, P1=1, P0=0 (14)
1343    Stick 2: P3=1, P2=1, P1=1, P0=1 (15)
1344
1345    Geneve: n/a, has own mouse handling via v9938
1346
1347    As we can only deliver at max 3 steps positive and 4 steps negative,
1348    we split the delta so that subsequent queries add up to the actual
1349    delta. That is, one delta of +10 yields a 3+3+3+1.
1350
1351    mecmouse_x holds the current delta to be counted down for x
1352    (y accordingly)
1353
1354    mecmouse_x_buf is the current step count reported to CRU
1355
1356    Michael Zapf, 2008-01-22
1357    */
1358
1359   if (selnow==stick2) {
1360      if (mecmouse_sel==stick1) {
1361         if (! mecmouse_read_y)
1362         {
1363            /* Sample x motion. */
1364            if (mecmouse_x < -4)
1365               mecmouse_x_buf = -4;
1366            else if (mecmouse_x > 3)
1367               mecmouse_x_buf = 3;
1368            else
1369               mecmouse_x_buf = mecmouse_x;
1370            mecmouse_x -= mecmouse_x_buf;
1371            mecmouse_x_buf = (mecmouse_x_buf-1) & 7;
1372         }
1373         else
1374         {
1375            /* Sample y motion. */
1376            if (mecmouse_y < -4)
1377               mecmouse_y_buf = -4;
1378            else if (mecmouse_y > 3)
1379               mecmouse_y_buf = 3;
1380            else
1381               mecmouse_y_buf = mecmouse_y;
1382            mecmouse_y -= mecmouse_y_buf;
1383            mecmouse_y_buf = (mecmouse_y_buf-1) & 7;
1384         }
1385      }
1386      mecmouse_sel = selnow;
1387   }
1388   else if (selnow==stick1)
1389   {
1390      if (mecmouse_sel==stick2)
1391      {
1392         /* Swap the axes. */
1393         mecmouse_read_y = ! mecmouse_read_y;
1394      }
1395      mecmouse_sel = selnow;
1396   }
1397   else
1398   {
1399      /* Reset the axis toggle when the mouse is deselected */
1400      mecmouse_read_y = 0;
1401   }
1402}
1403
1404static void mecmouse_poll(running_machine *machine)
1405{
1406   static int last_mx = 0, last_my = 0;
1407   int new_mx, new_my;
1408   int delta_x, delta_y;
1409
1410   new_mx = input_port_read(machine, "MOUSEX");
1411   new_my = input_port_read(machine, "MOUSEY");
1412
1413   /* compute x delta */
1414   delta_x = new_mx - last_mx;
1415
1416   /* check for wrap */
1417   if (delta_x > 0x80)
1418      delta_x = -0x100+delta_x;
1419   if  (delta_x < -0x80)
1420      delta_x = 0x100+delta_x;
1421
1422   /* Prevent unplausible values at startup. */
1423   if (delta_x > 100 || delta_x<-100) delta_x = 0;
1424
1425   last_mx = new_mx;
1426
1427   /* compute y delta */
1428   delta_y = new_my - last_my;
1429
1430   /* check for wrap */
1431   if (delta_y > 0x80)
1432      delta_y = -0x100+delta_y;
1433   if  (delta_y < -0x80)
1434      delta_y = 0x100+delta_y;
1435
1436   if (delta_y > 100 || delta_y<-100) delta_y = 0;
1437
1438   last_my = new_my;
1439
1440   /* update state */
1441   mecmouse_x += delta_x;
1442   mecmouse_y += delta_y;
1443}
1444
1445/*===========================================================================*/
1446#if 0
1447#pragma mark -
1448#pragma mark TMS9901 INTERFACE
1449#endif
1450/*
1451    TI99/4x-specific tms9901 I/O handlers
1452
1453    See mess/machine/tms9901.c for generic tms9901 CRU handlers.
1454
1455    BTW, although TMS9900 is generally big-endian, it is little endian as far as CRU is
1456    concerned. (i.e. bit 0 is the least significant)
1457
1458KNOWN PROBLEMS:
1459    * a read or write to bits 16-31 causes TMS9901 to quit timer mode.  The problem is:
1460      on a TI99/4A, any memory access causes a dummy CRU read.  Therefore, TMS9901 can quit
1461      timer mode even though the program did not explicitely ask... and THIS is impossible
1462      to emulate efficiently (we would have to check every memory operation).
1463*/
1464/*
1465    TMS9901 interrupt handling on a TI99/4(a).
1466
1467    TI99/4(a) uses the following interrupts:
1468    INT1: external interrupt (used by RS232 controller, for instance)
1469    INT2: VDP interrupt
1470    TMS9901 timer interrupt (overrides INT3)
1471    INT12: handset interrupt (only on a TI-99/4 with the handset prototypes)
1472
1473    Three (occasionally four) interrupts are used by the system (INT1, INT2,
1474    timer, and INT12 on a TI-99/4 with remote handset prototypes), out of 15/16
1475    possible interrupts.  Keyboard pins can be used as interrupt pins, too, but
1476    this is not emulated (it's a trick, anyway, and I don't know any program
1477    which uses it).
1478
1479    When an interrupt line is set (and the corresponding bit in the interrupt mask is set),
1480    a level 1 interrupt is requested from the TMS9900.  This interrupt request lasts as long as
1481    the interrupt pin and the revelant bit in the interrupt mask are set.
1482
1483    TIMER interrupts are kind of an exception, since they are not associated with an external
1484    interrupt pin, and I guess it takes a write to the 9901 CRU bit 3 ("SBO 3") to clear
1485    the pending interrupt (or am I wrong once again ?).
1486
1487nota:
1488    All interrupt routines notify (by software) the TMS9901 of interrupt
1489    recognition (with a "SBO n").  However, unless I am missing something, this
1490    has absolutely no consequence on the TMS9901 (except for the TIMER
1491    interrupt routine), and interrupt routines would work fine without this
1492    SBO instruction.  This is quite weird.  Maybe the interrupt recognition
1493    notification is needed on TMS9985, or any other weird variant of TMS9900
1494    (how about the TI-99 development system connected to a TI990/10?).
1495*/
1496
1497/*
1498    set the state of int1 (called by the peb core)
1499*/
1500void tms9901_set_int1(running_machine *machine, int state)
1501{
1502   tms9901_set_single_int(machine->device("tms9901"), 1, state);
1503}
1504
1505/*
1506    set the state of int2 (called by the tms9928 core)
1507*/
1508void tms9901_set_int2(running_machine *machine, int state)
1509{
1510   tms9901_set_single_int(machine->device("tms9901"), 2, state);
1511}
1512
1513/*
1514    Called by the 9901 core whenever the state of INTREQ and IC0-3 changes
1515*/
1516static TMS9901_INT_CALLBACK( tms9901_interrupt_callback )
1517{
1518   if (intreq)
1519   {
1520      // On TI99, TMS9900 IC0-3 lines are not connected to TMS9901,
1521      // but hard-wired to force level 1 interrupts
1522      cputag_set_input_line_and_vector(device->machine, "maincpu", 0, ASSERT_LINE, 1);   /* interrupt it, baby */
1523   }
1524   else
1525   {
1526      cputag_set_input_line(device->machine, "maincpu", 0, CLEAR_LINE);
1527   }
1528}
1529
1530/*
1531    Read pins INT3*-INT7* of TI99's 9901.
1532
1533    signification:
1534     (bit 1: INT1 status)
1535     (bit 2: INT2 status)
1536     bit 3-7: keyboard status bits 0 to 4
1537*/
1538static READ8_DEVICE_HANDLER( ti99_R9901_0 )
1539{
1540   int answer;
1541   static const char *const keynames[] = { "KEY0", "KEY1", "KEY2", "KEY3" };
1542
1543   if ((ti99_model == model_99_4) && (KeyCol == 7))
1544      answer = (ti99_handset_poll_bus() << 3) | 0x80;
1545   else if (has_mecmouse && (KeyCol == ((ti99_model == model_99_4) ? 6 : 7)))
1546   {
1547      int buttons = input_port_read(device->machine, "MOUSE0") & 3;
1548
1549      answer = (mecmouse_read_y ? mecmouse_y_buf : mecmouse_x_buf) << 4;
1550
1551      if (! (buttons & 1))
1552         /* action button */
1553         answer |= 0x08;
1554      if (! (buttons & 2))
1555         /* home button */
1556         answer |= 0x80;
1557   }
1558   else
1559   {
1560      answer = ((input_port_read(device->machine, keynames[KeyCol >> 1]) >> ((KeyCol & 1) * 8)) << 3) & 0xF8;
1561   }
1562
1563   if ((ti99_model == model_99_4a) || (ti99_model == model_99_4p))
1564   {
1565      if (! AlphaLockLine)
1566         answer &= ~ (input_port_read(device->machine, "ALPHA") << 3);
1567   }
1568
1569   return answer;
1570}
1571
1572/*
1573    Read pins INT8*-INT15* of TI99's 9901.
1574
1575    signification:
1576     bit 0-2: keyboard status bits 5 to 7
1577     bit 3: tape input mirror
1578     (bit 4: IR remote handset interrupt)
1579     bit 5-7: weird, not emulated
1580*/
1581static READ8_DEVICE_HANDLER( ti99_R9901_1 )
1582{
1583   int answer;
1584   static const char *const keynames[] = { "KEY0", "KEY1", "KEY2", "KEY3" };
1585
1586   if (/*(ti99_model == model_99_4) &&*/ (KeyCol == 7))
1587      answer = 0x07;
1588   else
1589   {
1590      answer = ((input_port_read(device->machine, keynames[KeyCol >> 1]) >> ((KeyCol & 1) * 8)) >> 5) & 0x07;
1591   }
1592
1593   /* we don't take CS2 into account, as CS2 is a write-only unit */
1594#if 0
1595   if (cassette_input(device->machine->device("cassette1")) > 0)
1596      answer |= 8;
1597#endif
1598
1599   return answer;
1600}
1601
1602/*
1603    Read pins P0-P7 of TI99's 9901.
1604
1605     bit 1: handset data clock pin
1606*/
1607static READ8_DEVICE_HANDLER( ti99_R9901_2 )
1608{
1609   return (has_handset && handset_clock) ? 2 : 0;
1610}
1611
1612/*
1613    Read pins P8-P15 of TI99's 9901.
1614
1615     bit 26: IR handset interrupt
1616     bit 27: tape input
1617*/
1618static READ8_DEVICE_HANDLER( ti99_R9901_3 )
1619{
1620   int answer;
1621
1622   if (has_handset && (handset_buflen == 3))
1623      answer = 0;
1624   else
1625      answer = 4;   /* on systems without handset, the pin is pulled up to avoid spurious interrupts */
1626
1627   /* we don't take CS2 into account, as CS2 is a write-only unit */
1628   if ( (ti99_model != model_99_8) && (ti99_model != model_99_4p))
1629   {
1630      if (cassette_input(device->machine->device("cassette1")) > 0)
1631         answer |= 8;
1632   }
1633   else
1634   {
1635      if (cassette_input(device->machine->device("cassette")) > 0)
1636         answer |= 8;
1637   }
1638
1639   return answer;
1640}
1641
1642
1643/*
1644    WRITE key column select (P2-P4)
1645*/
1646static WRITE8_DEVICE_HANDLER( ti99_KeyC )
1647{
1648   if (data)
1649      KeyCol |= 1 << (offset-2);
1650   else
1651      KeyCol &= ~ (1 << (offset-2));
1652
1653   if (has_mecmouse)
1654      mecmouse_select(KeyCol, (ti99_model == model_99_4) ? 5 : 6, (ti99_model == model_99_4) ? 6 : 7);
1655}
1656
1657/*
1658    WRITE alpha lock line - TI99/4a only (P5)
1659*/
1660static WRITE8_DEVICE_HANDLER( ti99_AlphaW )
1661{
1662   if ((ti99_model == model_99_4a) || (ti99_model == model_99_4p))
1663      AlphaLockLine = data;
1664}
1665
1666/*
1667    Read pins INT8*-INT15* of TI99's 9901.
1668
1669    signification:
1670     bit 0-2: keyboard status bits 2 to 4
1671     bit 3: tape input mirror
1672     (bit 4: IR remote handset interrupt)
1673     bit 5-7: weird, not emulated
1674*/
1675static READ8_DEVICE_HANDLER( ti99_8_R9901_1 )
1676{
1677   int answer;
1678   static const char *const keynames[] = {
1679      "KEY0", "KEY1", "KEY2", "KEY3", "KEY4", "KEY5", "KEY6", "KEY7",
1680      "KEY8", "KEY9", "KEY10", "KEY11", "KEY12", "KEY13", "KEY14", "KEY15"
1681   };
1682
1683   if (has_mecmouse && (KeyCol == 15))
1684   {
1685      int buttons = input_port_read(device->machine, "MOUSE0") & 3;
1686
1687      answer = ((mecmouse_read_y ? mecmouse_y_buf : mecmouse_x_buf) << 1) & 0x03;
1688
1689      if (! (buttons & 2))
1690         /* home button */
1691         answer |= 0x04;
1692   }
1693   else
1694   {
1695      answer = (input_port_read(device->machine, keynames[KeyCol]) >> 2) & 0x07;
1696   }
1697
1698   /* we don't take CS2 into account, as CS2 is a write-only unit */
1699#if 0
1700   if (cassette_input(machine->device("cassette")) > 0)
1701      answer |= 8;
1702#endif
1703
1704   return answer;
1705}
1706
1707/*
1708    command CS1/CS2 tape unit motor (P6-P7)
1709*/
1710static WRITE8_DEVICE_HANDLER( ti99_CS_motor )
1711{
1712   running_device *img;
1713
1714   if ( (ti99_model != model_99_8) && (ti99_model != model_99_4p))
1715   {
1716      img = device->machine->device((offset-6 ) ? "cassette2" :  "cassette1" );
1717   }
1718   else
1719   {
1720      img = device->machine->device("cassette");
1721   }
1722   cassette_change_state(img, data ? CASSETTE_MOTOR_ENABLED : CASSETTE_MOTOR_DISABLED, CASSETTE_MASK_MOTOR);
1723}
1724
1725/*
1726    audio gate (P8)
1727
1728    Set to 1 before using tape: this enables the mixing of tape input sound
1729    with computer sound.
1730
1731    We do not really need to emulate this as the tape recorder generates sound
1732    on its own.
1733*/
1734static WRITE8_DEVICE_HANDLER( ti99_audio_gate )
1735{
1736}
1737
1738/*
1739    tape output (P9)
1740    I think polarity is correct, but don't take my word for it.
1741*/
1742static WRITE8_DEVICE_HANDLER( ti99_CS_output )
1743{
1744   if ((ti99_model != model_99_8) && (ti99_model != model_99_4p))   /* 99/8 only has one tape port!!! */
1745   {
1746      cassette_output(device->machine->device("cassette1"), data ? +1 : -1);
1747      cassette_output(device->machine->device("cassette2"), data ? +1 : -1);
1748   }
1749   else
1750   {
1751      cassette_output(device->machine->device("cassette"), data ? +1 : -1);
1752   }
1753}
1754
1755/* tms9901 setup */
1756const tms9901_interface tms9901reset_param_ti99_4x =
1757{
1758   TMS9901_INT1 | TMS9901_INT2 | TMS9901_INTC,   /* only input pins whose state is always known */
1759
1760   {   /* read handlers */
1761      ti99_R9901_0,
1762      ti99_R9901_1,
1763      ti99_R9901_2,
1764      ti99_R9901_3
1765   },
1766
1767   {   /* write handlers */
1768      ti99_handset_set_ack,
1769      NULL,
1770      ti99_KeyC,
1771      ti99_KeyC,
1772      ti99_KeyC,
1773      ti99_AlphaW,
1774      ti99_CS_motor,
1775      ti99_CS_motor,
1776      ti99_audio_gate,
1777      ti99_CS_output,
1778      NULL,
1779      NULL,
1780      NULL,
1781      NULL,
1782      NULL,
1783      NULL
1784   },
1785
1786   /* interrupt handler */
1787   tms9901_interrupt_callback,
1788
1789   /* clock rate = 3MHz */
1790   3000000.
1791};
1792
1793/*===========================================================================*/
1794/*
1795    TI memory extension support.
1796
1797    Simple 8-bit DRAM: 32kb in two chunks of 8kb and 24kb repectively.
1798    Since the RAM is on the 8-bit bus, there is an additionnal delay.
1799*/
1800
1801static READ16_HANDLER ( ti99_TIxramlow_r );
1802static WRITE16_HANDLER ( ti99_TIxramlow_w );
1803static READ16_HANDLER ( ti99_TIxramhigh_r );
1804static WRITE16_HANDLER ( ti99_TIxramhigh_w );
1805
1806static void ti99_TIxram_init(running_machine *machine)
1807{
1808   address_space *space = cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM);
1809
1810   memory_install_read16_handler(space, 0x2000, 0x3fff, 0, 0, ti99_TIxramlow_r);
1811   memory_install_write16_handler(space, 0x2000, 0x3fff, 0, 0, ti99_TIxramlow_w);
1812   memory_install_read16_handler(space, 0xa000, 0xffff, 0, 0, ti99_TIxramhigh_r);
1813   memory_install_write16_handler(space, 0xa000, 0xffff, 0, 0, ti99_TIxramhigh_w);
1814}
1815
1816/* low 8 kb: 0x2000-0x3fff */
1817static READ16_HANDLER ( ti99_TIxramlow_r )
1818{
1819   cpu_adjust_icount(space->machine->device("maincpu"),-4);
1820//  cpu_spinuntil_time(space->machine->firstcpu, ATTOTIME_IN_USEC(6));
1821
1822   return xRAM_ptr[offset];
1823}
1824
1825static WRITE16_HANDLER ( ti99_TIxramlow_w )
1826{
1827   cpu_adjust_icount(space->machine->device("maincpu"),-4);
1828//  cpu_spinuntil_time(space->machine->firstcpu, ATTOTIME_IN_USEC(6));
1829   COMBINE_DATA(xRAM_ptr + offset);
1830}
1831
1832/* high 24 kb: 0xa000-0xffff */
1833static READ16_HANDLER ( ti99_TIxramhigh_r )
1834{
1835   cpu_adjust_icount(space->machine->device("maincpu"),-4);
1836//  cpu_spinuntil_time(space->machine->firstcpu, ATTOTIME_IN_USEC(6));
1837   return xRAM_ptr[offset+0x1000];
1838}
1839
1840static WRITE16_HANDLER ( ti99_TIxramhigh_w )
1841{
1842   cpu_adjust_icount(space->machine->device("maincpu"),-4);
1843//  cpu_spinuntil_time(space->machine->firstcpu, ATTOTIME_IN_USEC(6));
1844
1845   COMBINE_DATA(xRAM_ptr + offset+0x1000);
1846}
1847
1848
1849/*===========================================================================*/
1850/*
1851    Super AMS memory extension support.
1852
1853    Up to 1Mb of SRAM.  Straightforward mapper, works with 4kb chunks.  The mapper was designed
1854    to be extendable with other RAM areas.
1855*/
1856
1857/* prototypes */
1858static void sAMS_cru_w(running_machine *machine, int offset, int data);
1859static  READ8_HANDLER(sAMS_mapper_r);
1860static WRITE8_HANDLER(sAMS_mapper_w);
1861
1862static READ16_HANDLER ( ti99_sAMSxramlow_r );
1863static WRITE16_HANDLER ( ti99_sAMSxramlow_w );
1864static READ16_HANDLER ( ti99_sAMSxramhigh_r );
1865static WRITE16_HANDLER ( ti99_sAMSxramhigh_w );
1866
1867
1868static const ti99_peb_card_handlers_t sAMS_expansion_handlers =
1869{
1870   NULL,
1871   sAMS_cru_w,
1872   sAMS_mapper_r,
1873   sAMS_mapper_w
1874};
1875
1876
1877static int sAMS_mapper_on;
1878static int sAMSlookup[16];
1879
1880/* set up super AMS handlers, and set initial state */
1881static void ti99_sAMSxram_init(running_machine *machine)
1882{
1883   int i;
1884
1885   address_space *space = cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM);
1886
1887   memory_install_read16_handler(space, 0x2000, 0x3fff, 0, 0, ti99_sAMSxramlow_r);
1888   memory_install_write16_handler(space, 0x2000, 0x3fff, 0, 0, ti99_sAMSxramlow_w);
1889   memory_install_read16_handler(space, 0xa000, 0xffff, 0, 0, ti99_sAMSxramhigh_r);
1890   memory_install_write16_handler(space, 0xa000, 0xffff, 0, 0, ti99_sAMSxramhigh_w);
1891
1892   ti99_peb_set_card_handlers(expansion_box, 0x1e00, & sAMS_expansion_handlers);
1893
1894   sAMS_mapper_on = 0;
1895
1896   for (i=0; i<16; i++)
1897      sAMSlookup[i] = i << 11;
1898}
1899
1900/* write CRU bit:
1901    bit0: enable/disable mapper registers in DSR space,
1902    bit1: enable/disable address mapping */
1903static void sAMS_cru_w(running_machine *machine, int offset, int data)
1904{
1905   if (offset == 1)
1906      sAMS_mapper_on = data;
1907}
1908
1909/* read a mapper register */
1910static  READ8_HANDLER(sAMS_mapper_r)
1911{
1912   return (sAMSlookup[(offset >> 1) & 0xf] >> 11);
1913}
1914
1915/* write a mapper register */
1916static WRITE8_HANDLER(sAMS_mapper_w)
1917{
1918   sAMSlookup[(offset >> 1) & 0xf] = ((int) data) << 11;
1919}
1920
1921/* low 8 kb: 0x2000-0x3fff */
1922static READ16_HANDLER ( ti99_sAMSxramlow_r )
1923{
1924   cpu_adjust_icount(space->machine->device("maincpu"),-4);
1925   //  cpu_spinuntil_time(space->machine->firstcpu, ATTOTIME_IN_USEC(6));
1926
1927   if (sAMS_mapper_on)
1928      return xRAM_ptr[(offset&0x7ff)+sAMSlookup[(0x1000+offset)>>11]];
1929   else
1930      return xRAM_ptr[offset+0x1000];
1931}
1932
1933static WRITE16_HANDLER ( ti99_sAMSxramlow_w )
1934{
1935   cpu_adjust_icount(space->machine->device("maincpu"),-4);
1936//  cpu_spinuntil_time(space->machine->firstcpu, ATTOTIME_IN_USEC(6));
1937
1938   if (sAMS_mapper_on)
1939      COMBINE_DATA(xRAM_ptr + (offset&0x7ff)+sAMSlookup[(0x1000+offset)>>11]);
1940   else
1941      COMBINE_DATA(xRAM_ptr + offset+0x1000);
1942}
1943
1944/* high 24 kb: 0xa000-0xffff */
1945static READ16_HANDLER ( ti99_sAMSxramhigh_r )
1946{
1947   cpu_adjust_icount(space->machine->device("maincpu"),-4);
1948//  cpu_spinuntil_time(space->machine->firstcpu, ATTOTIME_IN_USEC(6));
1949
1950   if (sAMS_mapper_on)
1951      return xRAM_ptr[(offset&0x7ff)+sAMSlookup[(0x5000+offset)>>11]];
1952   else
1953      return xRAM_ptr[offset+0x5000];
1954}
1955
1956static WRITE16_HANDLER ( ti99_sAMSxramhigh_w )
1957{
1958   cpu_adjust_icount(space->machine->device("maincpu"),-4);
1959//  cpu_spinuntil_time(space->machine->firstcpu, ATTOTIME_IN_USEC(6));
1960
1961   if (sAMS_mapper_on)
1962      COMBINE_DATA(xRAM_ptr + (offset&0x7ff)+sAMSlookup[(0x5000+offset)>>11]);
1963   else
1964      COMBINE_DATA(xRAM_ptr + offset+0x5000);
1965}
1966
1967/*===========================================================================*/
1968/*
1969    myarc-ish memory extension support (foundation, and myarc clones).
1970
1971    Up to 512kb of RAM.  Straightforward mapper, works with 32kb chunks.
1972*/
1973
1974static int myarc_cru_r(running_machine *machine, int offset);
1975static void myarc_cru_w(running_machine *machine, int offset, int data);
1976
1977static READ16_HANDLER ( ti99_myarcxramlow_r );
1978static WRITE16_HANDLER ( ti99_myarcxramlow_w );
1979static READ16_HANDLER ( ti99_myarcxramhigh_r );
1980static WRITE16_HANDLER ( ti99_myarcxramhigh_w );
1981
1982
1983static const ti99_peb_card_handlers_t myarc_expansion_handlers =
1984{
1985   myarc_cru_r,
1986   myarc_cru_w,
1987   NULL,
1988   NULL
1989};
1990
1991static int myarc_cur_page_offset;
1992static int myarc_page_offset_mask;
1993
1994/* set up myarc handlers, and set initial state */
1995static void ti99_myarcxram_init(running_machine *machine)
1996{
1997   address_space *space = cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM);
1998
1999   memory_install_read16_handler(space, 0x2000, 0x3fff, 0, 0, ti99_myarcxramlow_r);
2000   memory_install_write16_handler(space, 0x2000, 0x3fff, 0, 0, ti99_myarcxramlow_w);
2001   memory_install_read16_handler(space, 0xa000, 0xffff, 0, 0, ti99_myarcxramhigh_r);
2002   memory_install_write16_handler(space, 0xa000, 0xffff, 0, 0, ti99_myarcxramhigh_w);
2003
2004   switch (xRAM_kind)
2005   {
2006   case RAM_FOUNDATION128:   /* 128kb foundation */
2007   case RAM_MYARC128:      /* 128kb myarc clone */
2008      myarc_page_offset_mask = 0x0c000;
2009      break;
2010   case RAM_FOUNDATION512:   /* 512kb foundation */
2011   case RAM_MYARC512:      /* 512kb myarc clone */
2012      myarc_page_offset_mask = 0x3c000;
2013      break;
2014   default:
2015      break;   /* let's just keep GCC's big mouth shut */
2016   }
2017
2018   switch (xRAM_kind)
2019   {
2020   case RAM_FOUNDATION128:   /* 128kb foundation */
2021   case RAM_FOUNDATION512:   /* 512kb foundation */
2022      ti99_peb_set_card_handlers(expansion_box, 0x1e00, & myarc_expansion_handlers);
2023      break;
2024   case RAM_MYARC128:      /* 128kb myarc clone */
2025   case RAM_MYARC512:      /* 512kb myarc clone */
2026      ti99_peb_set_card_handlers(expansion_box, 0x1000, & myarc_expansion_handlers);
2027      ti99_peb_set_card_handlers(expansion_box, 0x1900, & myarc_expansion_handlers);
2028      break;
2029   default:
2030      break;   /* let's just keep GCC's big mouth shut */
2031   }
2032
2033   myarc_cur_page_offset = 0;
2034}
2035
2036/* read CRU bit:
2037    bit 1-2 (128kb) or 1-4 (512kb): read current map offset */
2038static int myarc_cru_r(running_machine *machine, int offset)
2039{
2040   /*if (offset == 0)*/   /* right??? */
2041   {
2042      return (myarc_cur_page_offset >> 14);
2043   }
2044}
2045
2046/* write CRU bit:
2047    bit 1-2 (128kb) or 1-4 (512kb): write map offset */
2048static void myarc_cru_w(running_machine *machine, int offset, int data)
2049{
2050   offset &= 0x7;   /* right??? */
2051   if (offset >= 1)
2052   {
2053      int mask = 1 << (offset-1+14);
2054
2055      if (data)
2056         myarc_cur_page_offset |= mask;
2057      else
2058         myarc_cur_page_offset &= ~mask;
2059
2060      myarc_cur_page_offset &= myarc_page_offset_mask;
2061   }
2062}
2063
2064/* low 8 kb: 0x2000-0x3fff */
2065static READ16_HANDLER ( ti99_myarcxramlow_r )
2066{
2067   cpu_adjust_icount(space->machine->device("maincpu"),-4);
2068   return xRAM_ptr[myarc_cur_page_offset + offset];
2069}
2070
2071static WRITE16_HANDLER ( ti99_myarcxramlow_w )
2072{
2073   cpu_adjust_icount(space->machine->device("maincpu"),-4);
2074   COMBINE_DATA(xRAM_ptr + myarc_cur_page_offset + offset);
2075}
2076
2077/* high 24 kb: 0xa000-0xffff */
2078static READ16_HANDLER ( ti99_myarcxramhigh_r )
2079{
2080   cpu_adjust_icount(space->machine->device("maincpu"),-4);
2081   return xRAM_ptr[myarc_cur_page_offset + offset+0x1000];
2082}
2083
2084static WRITE16_HANDLER ( ti99_myarcxramhigh_w )
2085{
2086   cpu_adjust_icount(space->machine->device("maincpu"),-4);
2087   COMBINE_DATA(xRAM_ptr + myarc_cur_page_offset + offset+0x1000);
2088}
2089
2090
2091/**************************************************************************
2092    EVPC (Enhanced Video Processor Card) from SNUG
2093    based on v9938 (may also be equipped with v9958)
2094    Can be used with TI-99/4A as an add-on card; internal VDP must be removed
2095
2096    The SGCPU ("TI-99/4P") only runs with EVPC.
2097***************************************************************************/
2098
2099#include "emuopts.h"
2100
2101/* prototypes */
2102static int evpc_cru_r(running_machine *machine, int offset);
2103static void evpc_cru_w(running_machine *machine, int offset, int data);
2104static  READ8_HANDLER(evpc_mem_r);
2105static WRITE8_HANDLER(evpc_mem_w);
2106
2107/* pointer to the evpc DSR area */
2108static UINT8 *ti99_evpc_DSR;
2109
2110static int RAMEN;
2111static int evpc_dsr_page;
2112
2113/*
2114    NOVRAM area
2115*/
2116static UINT8 ti99_evpc_novram[256];
2117
2118static const ti99_peb_card_handlers_t evpc_handlers =
2119{
2120   evpc_cru_r,
2121   evpc_cru_w,
2122   evpc_mem_r,
2123   evpc_mem_w
2124};
2125
2126static struct
2127{
2128   UINT8 read_index, write_index, mask;
2129   int read;
2130   int state;
2131   struct { UINT8 red, green, blue; } color[0x100];
2132   //int dirty;
2133} evpc_palette;
2134
2135/*
2136    NOVRAM handling
2137*/
2138static void ti99_evpc_load_novram(running_machine *machine, const char *filename)
2139{
2140   file_error filerr;
2141   mame_file *file;
2142
2143   filerr = mame_fopen(SEARCHPATH_NVRAM, filename, OPEN_FLAG_READ, &file);
2144   if (filerr == FILERR_NONE)
2145   {
2146      if (mame_fread(file, ti99_evpc_novram, 256) != 256)
2147         logerror("ti99_4ev: NOVRAM load error\n");
2148      mame_fclose(file);
2149   }
2150}
2151
2152static void ti99_evpc_save_novram(running_machine *machine, const char *filename)
2153{
2154   file_error filerr;
2155   mame_file *file;
2156
2157   filerr = mame_fopen(SEARCHPATH_NVRAM, filename,
2158         OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS, &file);
2159
2160   if (filerr == FILERR_NONE)
2161   {
2162      if (mame_fwrite(file, ti99_evpc_novram, 256) != 256)
2163         logerror("ti99_4ev: NOVRAM save error\n");
2164      mame_fclose(file);
2165   }
2166}
2167
2168INPUT_CHANGED( evpc_changed )
2169{
2170   evpc_switch[(UINT64)param&0x03] = newval;
2171}
2172
2173INTERRUPT_GEN( ti99_4ev_hblank_interrupt )
2174{
2175//  static int line_count;
2176   v9938_interrupt(device->machine, 0);
2177
2178   // No Mechatronic Mouse with v9938 (has own mouse)
2179/*  if (++line_count == 262)
2180    {
2181        line_count = 0;
2182        if (has_mecmouse)
2183            mecmouse_poll(device->machine);
2184    } */
2185}
2186
2187// still unused
2188TIMER_DEVICE_CALLBACK( ti99_4ev_scanline_interrupt )
2189{
2190   v9938_interrupt(timer.machine, 0);
2191}
2192
2193/*
2194    Video initialization. (also used by SGCPU)
2195*/
2196VIDEO_START( ti99_4ev )
2197{
2198   VIDEO_START_CALL(generic_bitmapped);
2199   v9938_init(machine, 0, *machine->primary_screen, machine->generic.tmpbitmap,
2200      MODEL_V9938, 0x20000, tms9901_set_int2);   /* v38 with 128 kb of video RAM */
2201}
2202
2203/*
2204    V38 VDP read
2205*/
2206READ16_HANDLER ( ti99_rv38_r )
2207{
2208   cpu_adjust_icount(space->machine->device("maincpu"),-4);
2209//  cpu_spinuntil_time(space->machine->firstcpu, ATTOTIME_IN_USEC(6));
2210
2211   if (offset & 1)
2212   {   /* read VDP status */
2213      return ((int) v9938_0_status_r(space, 0)) << 8;
2214   }
2215   else
2216   {   /* read VDP RAM */
2217      return ((int) v9938_0_vram_r(space, 0)) << 8;
2218   }
2219}
2220
2221/*
2222    V38 vdp write
2223*/
2224WRITE16_HANDLER ( ti99_wv38_w )
2225{
2226   cpu_adjust_icount(space->machine->device("maincpu"),-4);
2227//  cpu_spinuntil_time(space->machine->firstcpu, ATTOTIME_IN_USEC(6));
2228
2229   switch (offset & 3)
2230   {
2231   case 0:
2232      /* write VDP data */
2233      v9938_0_vram_w(space, 0, (data >> 8) & 0xff);
2234      break;
2235   case 1:
2236      /* write VDP address */
2237      v9938_0_command_w(space, 0, (data >> 8) & 0xff);
2238      break;
2239   case 2:
2240      /* write VDP palette */
2241      v9938_0_palette_w(space, 0, (data >> 8) & 0xff);
2242      break;
2243   case 3:
2244      /* write VDP register pointer (indirect access) */
2245      v9938_0_register_w(space, 0, (data >> 8) & 0xff);
2246      break;
2247   }
2248}
2249
2250/*
2251    Reset evpc card, set up handlers
2252*/
2253static void ti99_evpc_reset(running_machine *machine)
2254{
2255   ti99_evpc_DSR = memory_region(machine, region_dsr) + offset_evpc_dsr;
2256   running_device *box = machine->device("per_exp_box");
2257
2258   RAMEN = 0;
2259   evpc_dsr_page = 0;
2260
2261   ti99_peb_set_card_handlers(box, 0x1400, & evpc_handlers);
2262}
2263
2264/*
2265    Read EVPC CRU interface (dip switches)
2266    0: Video timing (PAL/NTSC)
2267    1: -
2268    2: charset
2269    3: RAM shift
2270    4: -
2271    5: -
2272    6: -
2273    7: DIP or NOVRAM
2274    Logic is inverted
2275*/
2276static int evpc_cru_r(running_machine *machine, int offset)
2277{
2278   UINT8 value = 0;
2279
2280   if (offset == 0)
2281      value = ~(evpc_switch[0] | (evpc_switch[1]<<2) | (evpc_switch[2]<<3) | (evpc_switch[3]<<7));
2282
2283   return value;
2284}
2285
2286/*
2287    Write evpc CRU interface
2288*/
2289static void evpc_cru_w(running_machine *machine, int offset, int data)
2290{
2291   switch (offset)
2292   {
2293   case 0:
2294      break;
2295
2296   case 1:
2297      if (data)
2298         evpc_dsr_page |= 1;
2299      else
2300         evpc_dsr_page &= ~1;
2301      break;
2302
2303   case 2:
2304      break;
2305
2306   case 3:
2307      RAMEN = data;
2308      break;
2309
2310   case 4:
2311      if (data)
2312         evpc_dsr_page |= 4;
2313      else
2314         evpc_dsr_page &= ~4;
2315      break;
2316
2317   case 5:
2318      if (data)
2319         evpc_dsr_page |= 2;
2320      else
2321         evpc_dsr_page &= ~2;
2322      break;
2323
2324   case 6:
2325      break;
2326
2327   case 7:
2328      break;
2329   }
2330}
2331
2332/*
2333    read a byte in evpc DSR space
2334*/
2335static  READ8_HANDLER(evpc_mem_r)
2336{
2337   UINT8 reply = 0;
2338
2339   if (offset < 0x1f00)
2340   {
2341      reply = ti99_evpc_DSR[offset+evpc_dsr_page*0x2000];
2342   }
2343   else if (offset < 0x1ff0)
2344   {
2345      if (RAMEN)
2346      {
2347         reply = ti99_evpc_novram[offset-0x1f00];
2348      }
2349      else
2350      {
2351         reply = ti99_evpc_DSR[offset+evpc_dsr_page*0x2000];
2352      }
2353   }
2354   else
2355   {   /* PALETTE */
2356      switch (offset - 0x1ff0)
2357      {
2358      case 0:
2359         /* Palette Read Address Register */
2360         reply = evpc_palette.write_index;
2361         break;
2362
2363      case 2:
2364         /* Palette Read Color Value */
2365         if (evpc_palette.read)
2366         {
2367            switch (evpc_palette.state)
2368            {
2369            case 0:
2370               reply = evpc_palette.color[evpc_palette.read_index].red;
2371               break;
2372            case 1:
2373               reply = evpc_palette.color[evpc_palette.read_index].green;
2374               break;
2375            case 2:
2376               reply = evpc_palette.color[evpc_palette.read_index].blue;
2377               break;
2378            }
2379            evpc_palette.state++;
2380            if (evpc_palette.state == 3)
2381            {
2382               evpc_palette.state = 0;
2383               evpc_palette.read_index++;
2384            }
2385         }
2386         break;
2387
2388      case 4:
2389         /* Palette Read Pixel Mask */
2390         reply = evpc_palette.mask;
2391         break;
2392      case 6:
2393         /* Palette Read Address Register for Color Value */
2394         if (evpc_palette.read)
2395            reply = 0;
2396         else
2397            reply = 3;
2398         break;
2399      }
2400   }
2401
2402   return reply;
2403}
2404
2405/*
2406    write a byte in evpc DSR space
2407*/
2408static WRITE8_HANDLER(evpc_mem_w)
2409{
2410   if ((offset >= 0x1f00) && (offset < 0x1ff0) && RAMEN)
2411   {
2412      // NOVRAM
2413      ti99_evpc_novram[offset-0x1f00] = data;
2414   }
2415   else if (offset >= 0x1ff0)
2416   {   /* PALETTE */
2417      logerror("palette write, offset=%d\n, data=%d", offset-0x1ff0, data);
2418      switch (offset - 0x1ff0)
2419      {
2420      case 8:
2421         /* Palette Write Address Register */
2422         logerror("EVPC palette address write (for write access)\n");
2423         evpc_palette.write_index = data;
2424         evpc_palette.state = 0;
2425         evpc_palette.read = 0;
2426         break;
2427
2428      case 10:
2429         /* Palette Write Color Value */
2430         logerror("EVPC palette color write\n");
2431         if (! evpc_palette.read)
2432         {
2433            switch (evpc_palette.state)
2434            {
2435            case 0:
2436               evpc_palette.color[evpc_palette.write_index].red = data;
2437               break;
2438            case 1:
2439               evpc_palette.color[evpc_palette.write_index].green = data;
2440               break;
2441            case 2:
2442               evpc_palette.color[evpc_palette.write_index].blue = data;
2443               break;
2444            }
2445            evpc_palette.state++;
2446            if (evpc_palette.state == 3)
2447            {
2448               evpc_palette.state = 0;
2449               evpc_palette.write_index++;
2450            }
2451            //evpc_palette.dirty = 1;
2452         }
2453         break;
2454
2455      case 12:
2456         /* Palette Write Pixel Mask */
2457         logerror("EVPC palette mask write\n");
2458         evpc_palette.mask = data;
2459         break;
2460
2461      case 14:
2462         /* Palette Write Address Register for Color Value */
2463         logerror("EVPC palette address write (for read access)\n");
2464         evpc_palette.read_index=data;
2465         evpc_palette.state=0;
2466         evpc_palette.read=1;
2467         break;
2468      }
2469   }
2470}
2471
2472/**************************************************************************
2473    TI-99/8
2474***************************************************************************/
2475
2476DRIVER_INIT( ti99_8 )
2477{
2478   UINT8 *mem = memory_region(machine, "maincpu");
2479   ti99_model = model_99_8;
2480   has_evpc = FALSE;
2481
2482   /* set up memory pointers */
2483   xRAM_ptr_8 = mem + offset_xram_8;
2484   ROM0_ptr_8 = mem + offset_rom0_8;
2485   ROM1_ptr_8 = ROM0_ptr_8 + 0x2000;
2486   ROM2_ptr_8 = ROM1_ptr_8 + 0x2000;
2487   ROM3_ptr_8 = ROM2_ptr_8 + 0x2000;
2488   sRAM_ptr_8 = mem + offset_sram_8;
2489
2490   /* Pull this one up here. */
2491   ti99_8_enable_rom_and_ports = 1;
2492
2493   console_GROMs.data_ptr = memory_region(machine, region_grom);
2494   create_grom_high2k(0x0000, 0x5fff);
2495
2496   multicart8 = machine->device("ti99_multicart");
2497   assert (multicart8 != NULL);
2498}
2499
2500/*
2501    ti99_init_machine(); called before ti99_load_rom...
2502*/
2503MACHINE_RESET( ti99_8 )
2504{
2505   /*console_GROMs.data_ptr = memory_region(machine, region_grom);*/
2506   console_GROMs.addr = 0;
2507   console_GROMs.buf = 0;
2508   console_GROMs.raddr_LSB = FALSE;
2509   console_GROMs.waddr_LSB = FALSE;
2510
2511   expansion_box = machine->device("per_exp_box");
2512
2513   ti99_8_enable_rom_and_ports = 1;      /* ??? maybe there is a pull-up */
2514   /* MZ: already setting this in driver init, otherwise machine locks up */
2515
2516   TMS9928A_reset();
2517
2518   /* clear keyboard interface state (probably overkill, but can't harm) */
2519   KeyCol = 0;
2520   AlphaLockLine = 0;
2521
2522   tms9901_set_single_int(machine->device("tms9901"), 12, 0);
2523
2524   xRAM_kind = RAM_99_8;
2525   has_speech = TRUE;
2526   has_ide = input_port_read(machine, "HDCTRL") & HD_IDE;
2527   has_rs232 = input_port_read(machine, "SERIAL") & SERIAL_TI;
2528   has_handset = FALSE;
2529
2530   has_mecmouse = input_port_read(machine, "HCI") & HCI_MECMOUSE;
2531
2532   has_hsgpl = input_port_read(machine, "EXTCARD") & (EXT_HSGPL_ON | EXT_HSGPL_FLASH);
2533   hsgpl_flash_mode = input_port_read(machine, "EXTCARD") & EXT_HSGPL_FLASH;
2534
2535   has_usb_sm = input_port_read(machine, "HDCTRL") & HD_USB;
2536   has_pcode = input_port_read(machine, "EXTCARD") & EXT_PCODE;
2537
2538   /* Get the GK settings once */
2539   gk_switch[1] = input_port_read(machine, "GKSWITCH1");
2540   gk_switch[2] = input_port_read(machine, "GKSWITCH2");
2541   gk_switch[3] = input_port_read(machine, "GKSWITCH3");
2542   gk_switch[4] = input_port_read(machine, "GKSWITCH4");
2543   gk_switch[5] = input_port_read(machine, "GKSWITCH5");
2544
2545   // Removes all card handlers
2546//  ti99_peb_init();
2547
2548   // set up optional expansion hardware
2549
2550   ti99_8_internal_dsr_reset(machine);
2551
2552   static const spchroms_interface speech_intf = { region_speech_rom };
2553   spchroms_config(machine, &speech_intf);
2554
2555   switch (input_port_read(machine, "DISKCTRL"))
2556   {
2557   case DISK_TIFDC:
2558      ti99_fdc_reset(machine);
2559      break;
2560#if HAS_99CCFDC
2561   case DISK_CC:
2562      ti99_ccfdc_reset(machine);
2563      break;
2564#endif
2565   case DISK_BWG:
2566      ti99_bwg_reset(machine);
2567      break;
2568   case DISK_HFDC:
2569      ti99_hfdc_reset(machine);
2570      break;
2571   case DISK_NONE:
2572      break;
2573   }
2574
2575   if (has_ide)
2576      ti99_ide_reset(machine, TRUE);
2577
2578   if (has_hsgpl)
2579      ti99_hsgpl_reset(machine);
2580   else
2581      hsgpl_crdena = 0;
2582
2583   if (has_usb_sm)
2584      ti99_usbsm_reset(machine, TRUE);
2585
2586   if (has_pcode)
2587      ti99_pcode_reset(machine);
2588
2589   /* initialize mechatronics mouse */
2590   mecmouse_sel = 0;
2591   mecmouse_read_y = 0;
2592   mecmouse_x = 0;
2593   mecmouse_y = 0;
2594}
2595
2596/*
2597    GROM read for TI-99/8
2598    For comments, see the handler for TI-99/4A
2599*/
2600static READ8_HANDLER ( ti99_grom_r8 )
2601{
2602   UINT8 reply, replycart;
2603
2604   cpu_adjust_icount(space->machine->firstcpu,-4);
2605
2606   if (offset & 2)
2607   {
2608      replycart = ti99_cartridge_grom_r(cartslots, offset);
2609      console_GROMs.waddr_LSB = FALSE;
2610
2611      if (console_GROMs.raddr_LSB)
2612      {
2613         reply = console_GROMs.addr & 0x00ff;
2614         console_GROMs.raddr_LSB = FALSE;
2615      }
2616      else
2617      {
2618         reply = (console_GROMs.addr>>8) & 0x00ff;
2619         console_GROMs.raddr_LSB = TRUE;
2620      }
2621      /* GROM address values must be globally unique. */
2622      assert (replycart == reply);
2623   }
2624   else
2625   {
2626      reply = GROM_dataread(space->machine, offset);
2627   }
2628   return reply;
2629}
2630
2631/*
2632    GROM write for TI-99/8
2633    For comments, see the handler for TI-99/4A
2634*/
2635static WRITE8_HANDLER ( ti99_grom_w8 )
2636{
2637   cpu_adjust_icount(space->machine->firstcpu,-4/*20+3*/);      /* from 4 to 23? */
2638
2639   if (offset & 2)
2640   {
2641      ti99_cartridge_grom_w(cartslots, offset, data);
2642      console_GROMs.raddr_LSB = FALSE;
2643      if (console_GROMs.waddr_LSB)
2644      {
2645         console_GROMs.addr = (console_GROMs.addr & 0xFF00) | (data & 0xFF);
2646
2647         GROM_dataread(space->machine, offset&0xfffc);
2648         console_GROMs.waddr_LSB = FALSE;
2649      }
2650      else
2651      {
2652         console_GROMs.addr = ((data<<8) & 0xFF00) | (console_GROMs.addr & 0xFF);
2653         console_GROMs.waddr_LSB = TRUE;
2654      }
2655
2656   }
2657   else
2658   {
2659      GRAM_datawrite(offset, data);
2660      console_GROMs.raddr_LSB = console_GROMs.waddr_LSB = FALSE;
2661   }
2662}
2663
2664READ8_HANDLER( ti99_8_r )
2665{
2666   /* Set the page. Page size is 4 KiB; page number are the high 4 bits. */
2667   int page = offset >> 12;
2668   UINT32 mapper_reg;
2669   UINT8 reply = 0;
2670
2671   if (ti99_8_enable_rom_and_ports)
2672   {
2673      //  This is only important for address access 0000-1fff and
2674      // 8000-9fff. Outside, the mapper mode is used.
2675      if ((offset >= 0x0000) && (offset < 0x2000))
2676      {
2677         /* ROM */
2678         reply = ROM0_ptr_8[offset & 0x1fff];
2679         return reply;
2680      }
2681      else if ((offset >= 0x8000) && (offset < 0xa000))
2682      {
2683         /* ti99 scratch pad and memory-mapped registers */
2684         /* 0x8000-0x9fff */
2685         switch ((offset - 0x8000) >> 10)
2686         {
2687         case 0:
2688            /* RAM: >8000 - >83ff */
2689            reply = sRAM_ptr_8[offset & 0x1fff];
2690            break;
2691
2692         case 1:
2693            // >8400 - >840f: sound (cannot read)
2694            // >8410 - >87ff: SRAM
2695            if (offset >= 0x8410)
2696               reply = sRAM_ptr_8[offset & 0x1fff];
2697            break;
2698
2699         case 2:
2700            /* VDP read + mapper status */
2701            if (offset < 0x8810)
2702            {
2703               if (! (offset & 1))
2704               {
2705                  if (offset & 2)
2706                     /* read VDP status >8802 */
2707                  reply = TMS9928A_register_r(space, 0);
2708                  else
2709                     /* read VDP RAM >8800 */
2710                  reply = TMS9928A_vram_r(space, 0);
2711               }
2712            }
2713            else
2714            {
2715               /* Read mapper >8810 */
2716               reply = ti99_8_mapper_status;
2717               ti99_8_mapper_status = 0;
2718            }
2719            break;
2720
2721         case 4:
2722            /* speech read: >9000 */
2723            if (! (offset & 1))
2724            {
2725               cpu_adjust_icount(space->machine->device("maincpu"),-16*4);      /* this is just a minimum, it can be more */
2726               reply = tms5220_status_r(space->machine->device("tms5220"), 0);
2727            }
2728            break;
2729
2730         case 6:
2731            /* GROM read: >9800 */
2732            if (! (offset & 1))
2733               reply = ti99_grom_r8(space, offset);
2734            break;
2735
2736         default:
2737            logerror("unmapped read offs=%d\n", (int) offset);
2738            break;
2739         }
2740         return reply;
2741      }
2742   }
2743
2744   mapper_reg = ti99_8_mapper_regs[page];
2745   offset = (mapper_reg + (offset & 0x0fff)) & 0x00ffffff;
2746
2747   if (offset < 0x010000) {
2748      UINT8 *mem = memory_region(space->machine, "maincpu")+ offset_xram_8;
2749      /* Read RAM */
2750      reply = mem[offset];
2751   }
2752
2753   if (offset >= 0xff0000)
2754   {
2755      switch ((offset >> 13) & 7)
2756      {
2757      default:
2758         /* should never happen */
2759      case 0:
2760         /* ff0000 - ff1fff: unassigned? */
2761      case 1:
2762         /* ff2000 - ff3fff: ? */
2763      case 4:
2764         /* ff8000 - ff9fff: internal DSR ROM? (normally enabled with a write to CRU >2700) */
2765      case 7:
2766         /* ffe000 - ffffff: ? */
2767         logerror("unmapped read page=%d offs=%d\n", (int) page, (int) offset);
2768         break;
2769
2770      case 2:
2771         /* ff4000 - ff5fff: DSR space */
2772         reply = ti99_8_peb_r(expansion_box, offset & 0x1fff);
2773         break;
2774
2775      case 3:
2776         /* ff6000 - ff7fff: cartridge ROM space */
2777         offset &= 0x1fff;
2778
2779         // We do not support hsgpl here. Just check the cartridges.
2780         reply = ti99_multicart8_r(multicart8, offset);
2781         break;
2782
2783      case 5:
2784         /* ffa000 - ffbfff: >2000 ROM (ROM1) */
2785         reply = ROM1_ptr_8[offset & 0x1fff];
2786         break;
2787
2788      case 6:
2789         /* ffc000 - ffdfff: >6000 ROM */
2790         reply = ROM3_ptr_8[offset & 0x1fff];
2791         break;
2792      }
2793   }
2794
2795   return reply;
2796}
2797
2798WRITE8_HANDLER ( ti99_8_w )
2799{
2800   int page = offset >> 12;
2801   UINT32 mapper_reg;
2802
2803   if (ti99_8_enable_rom_and_ports)
2804   {
2805      /* memory mapped ports enabled */
2806      if ((offset >= 0x0000) && (offset < 0x2000))
2807      {
2808         /* ROM? */
2809         return;
2810      }
2811      else if ((offset >= 0x8000) && (offset < 0xa000))
2812      {
2813         /* ti99 scratch pad and memory-mapped registers */
2814         /* 0x8000-0x9fff */
2815         switch ((offset - 0x8000) >> 10)
2816         {
2817         case 0:
2818            /* RAM */
2819            sRAM_ptr_8[offset & 0x1fff] = data;
2820            break;
2821
2822         case 1:
2823            /* sound write + RAM */
2824            if (offset < 0x8410)
2825               sn76496_w(space->machine->device("sn76496"), offset, data);
2826            else
2827               sRAM_ptr_8[offset & 0x1fff] = data;
2828            break;
2829
2830         case 2:
2831            /* VDP read + mapper control */
2832            if (offset >= 0x8810)
2833            {
2834               int file = (data >> 1) & 3;
2835               int i;
2836
2837               if (data & 1)
2838               {   /* load */
2839                  for (i=0; i<16; i++)
2840                  {
2841                     ti99_8_mapper_regs[i] = (sRAM_ptr_8[(file << 6) + (i << 2)] << 24)
2842                                       | (sRAM_ptr_8[(file << 6) + (i << 2) + 1] << 16)
2843                                       | (sRAM_ptr_8[(file << 6) + (i << 2) + 2] << 8)
2844                                       | sRAM_ptr_8[(file << 6) + (i << 2) + 3];
2845                  }
2846               }
2847               else
2848               {   /* save */
2849                  for (i=0; i<16; i++)
2850                  {
2851                     sRAM_ptr_8[(file << 6) + (i << 2)] = ti99_8_mapper_regs[i] >> 24;
2852                     sRAM_ptr_8[(file << 6) + (i << 2) + 1] = ti99_8_mapper_regs[i] >> 16;
2853                     sRAM_ptr_8[(file << 6) + (i << 2) + 2] = ti99_8_mapper_regs[i] >> 8;
2854                     sRAM_ptr_8[(file << 6) + (i << 2) + 3] = ti99_8_mapper_regs[i];
2855                  }
2856               }
2857            }
2858            break;
2859
2860         case 3:
2861            /* VDP write */
2862            if (! (offset & 1))
2863            {
2864               if (offset & 2)
2865                  /* read VDP status */
2866                  TMS9928A_register_w(space, 0, data);
2867               else
2868                  /* read VDP RAM */
2869                  TMS9928A_vram_w(space, 0, data);
2870            }
2871            break;
2872
2873         case 5:
2874            /* speech write */
2875            if (! (offset & 1))
2876            {
2877               cpu_adjust_icount(space->machine->device("maincpu"),-48*4);      /* this is just an approx. minimum, it can be much more */
2878
2879               // the stupid design of the tms5220 core means that ready is cleared when
2880               // there are 15 bytes in FIFO.  It should be 16.  Of course, if it were the
2881               // case, we would need to store the value on the bus, which would be more
2882               // complex.
2883               if (! tms5220_readyq_r(space->machine->device("tms5220")))
2884               {
2885                  attotime time_to_ready = double_to_attotime(tms5220_time_to_ready(space->machine->device("tms5220")));
2886                  double d = space->machine->device<cpu_device>("maincpu")->attotime_to_cycles(time_to_ready);
2887                  int cycles_to_ready = ((int) (d + 3)) & ~3;
2888
2889                  logerror("time to ready: %f -> %d\n", attotime_to_double(time_to_ready)
2890                     , (int) cycles_to_ready);
2891
2892                  cpu_adjust_icount(space->machine->device("maincpu"),-cycles_to_ready);
2893                  timer_set(space->machine, attotime_zero, NULL, 0, /*speech_kludge_callback*/NULL);
2894               }
2895
2896               tms5220_data_w(space->machine->device("tms5220"), offset, data);
2897            }
2898            break;
2899
2900         case 7:
2901            /* GPL write */
2902            if (! (offset & 1))
2903               ti99_grom_w8(space, offset, data);
2904            break;
2905
2906         default:
2907            logerror("unmapped write offs=%d data=%d\n", (int) offset, (int) data);
2908            break;
2909         }
2910         return;
2911      }
2912   }
2913
2914   mapper_reg = ti99_8_mapper_regs[page];
2915
2916   /* 4 KiB page size */
2917   offset = (mapper_reg + (offset & 0x0fff)) & 0x00ffffff;
2918
2919#if 0
2920   /* test write protect */
2921   if (mapper_reg & 0x80000000)
2922      ;
2923#endif
2924
2925   if (offset < 0x010000)
2926   {   /* Write RAM */
2927      xRAM_ptr_8[offset] = data;
2928   }
2929   else if (offset >= 0xff0000)
2930   {
2931      switch ((offset >> 13) & 7)
2932      {
2933      default:
2934         /* should never happen */
2935      case 0:
2936         /* unassigned??? */
2937      case 1:
2938         /* ??? */
2939      case 4:
2940         /* internal DSR ROM??? (normally enabled with a write to CRU >2700) */
2941      case 7:
2942         /* ??? */
2943         break;
2944
2945      case 2:
2946         /* DSR space */
2947         ti99_8_peb_w(expansion_box, offset & 0x1fff, data);
2948         break;
2949
2950      case 3:
2951         /* cartridge space */
2952         /* We do not support HSGPL for the 99/8 at this time. */
2953         ti99_multicart8_w(multicart8, offset & 0x1fff, data);
2954         break;
2955
2956      case 5:
2957         /* >2000 ROM (ROM1) */
2958         break;
2959
2960      case 6:
2961         /* >6000 ROM */
2962         break;
2963      }
2964   }
2965   else
2966   {
2967      logerror("unmapped write page=%d offs=%d\n", (int) page, (int) offset);
2968   }
2969}
2970
2971/*
2972    WRITE key column select (P0-P3)
2973*/
2974static WRITE8_DEVICE_HANDLER( ti99_8_KeyC )
2975{
2976   if (data)
2977      KeyCol |= 1 << offset;
2978   else
2979      KeyCol &= ~ (1 << offset);
2980
2981   if (has_mecmouse)
2982      mecmouse_select(KeyCol, 14, 15);
2983}
2984
2985static WRITE8_DEVICE_HANDLER( ti99_8_WCRUS )
2986{
2987   ti99_8_enable_rom_and_ports = data;
2988}
2989
2990static WRITE8_DEVICE_HANDLER( ti99_8_PTGEN )
2991{
2992   /* ... */
2993}
2994
2995/*
2996    TI 99/8 internal DSR support.
2997    Includes a few specific signals, and an extra ROM.
2998*/
2999
3000/* prototypes */
3001static void ti99_8_internal_dsr_cru_w(running_machine *machine, int offset, int data);
3002static  READ8_HANDLER(ti99_8_internal_dsr_r);
3003
3004
3005static const ti99_peb_card_handlers_t ti99_8_internal_dsr_handlers =
3006{
3007   NULL,
3008   ti99_8_internal_dsr_cru_w,
3009   ti99_8_internal_dsr_r,
3010   NULL
3011};
3012
3013/* pointer to the internal DSR ROM data */
3014static UINT8 *ti99_8_internal_DSR;
3015
3016
3017/* set up handlers, and set initial state */
3018static void ti99_8_internal_dsr_reset(running_machine *machine)
3019{
3020   ti99_8_internal_DSR = memory_region(machine, "maincpu") + offset_rom0_8 + 0x4000;
3021   ti99_peb_set_card_handlers(expansion_box, 0x2700, & ti99_8_internal_dsr_handlers);
3022}
3023
3024/* write CRU bit:
3025    bit0: enable/disable internal DSR ROM,
3026    bit1: hard reset */
3027static void ti99_8_internal_dsr_cru_w(running_machine *machine, int offset, int data)
3028{
3029   switch (offset)
3030   {
3031   case 1:
3032      /* hard reset -- not emulated */
3033      break;
3034   }
3035}
3036
3037/* read internal DSR ROM */
3038static  READ8_HANDLER(ti99_8_internal_dsr_r)
3039{
3040   return ti99_8_internal_DSR[offset];
3041}
3042
3043/*
3044    Read pins INT3*-INT7* of TI99's 9901.
3045
3046    signification:
3047     (bit 1: INT1 status)
3048     (bit 2: INT2 status)
3049     bits 3-4: unused?
3050     bit 5: ???
3051     bit 6-7: keyboard status bits 0 through 1
3052*/
3053static READ8_DEVICE_HANDLER( ti99_8_R9901_0 )
3054{
3055   int answer;
3056   static const char *const keynames[] = {
3057      "KEY0", "KEY1", "KEY2", "KEY3", "KEY4", "KEY5", "KEY6", "KEY7",
3058      "KEY8", "KEY9", "KEY10", "KEY11", "KEY12", "KEY13", "KEY14", "KEY15"
3059   };
3060
3061   if (has_mecmouse && (KeyCol == 15))
3062   {
3063      int buttons = input_port_read(device->machine, "MOUSE0") & 3;
3064
3065      answer = ((mecmouse_read_y ? mecmouse_y_buf : mecmouse_x_buf) << 7) & 0x80;
3066
3067      if (! (buttons & 1))
3068         /* action button */
3069         answer |= 0x40;
3070   }
3071   else
3072   {
3073      answer = (input_port_read(device->machine, keynames[KeyCol]) << 6) & 0xC0;
3074   }
3075
3076   return answer;
3077}
3078
3079const tms9901_interface tms9901reset_param_ti99_8 =
3080{
3081   TMS9901_INT1 | TMS9901_INT2 | TMS9901_INTC,   /* only input pins whose state is always known */
3082
3083   {   /* read handlers */
3084      ti99_8_R9901_0,
3085      ti99_8_R9901_1,
3086      ti99_R9901_2,
3087      ti99_R9901_3
3088   },
3089
3090   {   /* write handlers */
3091      ti99_8_KeyC,
3092      ti99_8_KeyC,
3093      ti99_8_KeyC,
3094      ti99_8_KeyC,
3095      ti99_8_WCRUS,
3096      ti99_8_PTGEN,
3097      ti99_CS_motor,
3098      NULL,
3099      ti99_audio_gate,
3100      ti99_CS_output,
3101      NULL,
3102      NULL,
3103      NULL,
3104      NULL,
3105      NULL,
3106      NULL
3107   },
3108
3109   /* interrupt handler */
3110   tms9901_interrupt_callback,
3111
3112   /* clock rate = 3.58MHz??? 2.68MHz??? */
3113   /*3579545.*/2684658.75
3114};
3115
3116
3117/**************************************************************************
3118    SGCPU (aka "TI-99/4P")
3119    Requires EVPC and HSGPL (with content)
3120***************************************************************************/
3121
3122/* True if SGCPU rom6 is enabled */
3123static int ti99_4p_internal_rom6_enable;
3124
3125/* Pointer to the memory area. */
3126static UINT16 *ti99_4p_mem;
3127
3128/* pointer to the internal DSR ROM data */
3129static UINT16 *ti99_4p_internal_DSR;
3130
3131/* Offset to the ROM6 bank. */
3132static offs_t rom6_bank_offset;
3133
3134static void ti99_4p_mapper_cru_w(running_machine *machine, int offset, int data);
3135static READ16_HANDLER(ti99_4p_mapper_r);
3136static WRITE16_HANDLER(ti99_4p_mapper_w);
3137static void ti99_4p_internal_dsr_cru_w(running_machine *machine, int offset, int data);
3138static READ16_HANDLER(ti99_4p_internal_dsr_r);
3139
3140static const ti99_peb_16bit_card_handlers_t ti99_4p_internal_dsr_handlers =
3141{
3142   NULL,
3143   ti99_4p_internal_dsr_cru_w,
3144   ti99_4p_internal_dsr_r,
3145   NULL
3146};
3147
3148static const ti99_peb_16bit_card_handlers_t ti99_4p_mapper_handlers =
3149{
3150   NULL,
3151   ti99_4p_mapper_cru_w,
3152   ti99_4p_mapper_r,
3153   ti99_4p_mapper_w
3154};
3155
3156static int ti99_4p_mapper_on;
3157static int ti99_4p_mapper_lookup[16];
3158
3159DRIVER_INIT( ti99_4p )
3160{
3161   ti99_model = model_99_4p;
3162   has_evpc = TRUE;
3163
3164   /* set up memory pointers */
3165   xRAM_ptr = (UINT16 *) (memory_region(machine, "maincpu") + offset_xram_4p);
3166}
3167
3168MACHINE_START( ti99_4p )
3169{
3170   UINT8* mem = memory_region(machine, "maincpu");
3171
3172   // Set up system ROM pointers. Must be set up here
3173   // so that the system can successfully reset (otherwise the reset
3174   // vector would be missing in 0x0000).
3175   memory_set_bankptr(machine, "bank1", mem + offset_rom0_4p);    // system ROM
3176
3177   ti99_floppy_controllers_init_all(machine);
3178   ti99_ide_init(machine);
3179   ti99_hsgpl_init(machine);
3180   ti99_usbsm_init(machine);
3181}
3182
3183/*
3184    Reset the machine.
3185*/
3186MACHINE_RESET( ti99_4p )
3187{
3188   address_space *space = cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM);
3189
3190   UINT8* mem = memory_region(machine, "maincpu");
3191
3192   expansion_box = machine->device("per_exp_box");
3193
3194   /* set up system ROM and scratch pad pointers */
3195   memory_set_bankptr(machine, "bank1", mem + offset_rom0_4p);   /* system ROM */
3196   memory_set_bankptr(machine, "bank2", mem + offset_sram_4p);   /* scratch pad */
3197   memory_set_bankptr(machine, "bank11", mem + offset_dram_4p);   /* extra RAM for debugger */
3198
3199   v9938_reset(0);
3200
3201   /* clear keyboard interface state (probably overkill, but can't harm) */
3202   KeyCol = 0;
3203   AlphaLockLine = 0;
3204
3205   tms9901_set_single_int(machine->device("tms9901"), 12, 0);
3206
3207   xRAM_kind = RAM_99_4P;
3208   has_speech = input_port_read(machine, "SPEECH");
3209   has_ide = input_port_read(machine, "HDCTRL") & HD_IDE;
3210   has_rs232 = input_port_read(machine, "SERIAL") & SERIAL_TI;
3211
3212   has_handset = FALSE;
3213   has_mecmouse = FALSE;        // mouse is connected to v9938
3214   has_hsgpl = TRUE;
3215   has_usb_sm = input_port_read(machine, "HDCTRL") & HD_USB;
3216   has_pcode = input_port_read(machine, "EXTCARD") & EXT_PCODE;
3217
3218   // set up optional expansion hardware
3219   ti99_4p_internal_dsr_reset(machine);
3220   ti99_4p_mapper_init(machine);
3221   ti99_hsgpl_reset(machine);
3222   ti99_evpc_reset(machine);
3223
3224   if (has_speech)
3225   {
3226      static const spchroms_interface speech_intf = { region_speech_rom };
3227      spchroms_config(machine, &speech_intf);
3228      memory_install_read16_handler(space, 0x9000, 0x93ff, 0, 0, ti99_rspeech_r);
3229      memory_install_write16_handler(space, 0x9400, 0x97ff, 0, 0, ti99_wspeech_w);
3230   }
3231   else
3232   {
3233      memory_install_read16_handler(space, 0x9000, 0x93ff, 0, 0, ti99_nop_8_r);
3234      memory_install_write16_handler(space, 0x9400, 0x97ff, 0, 0, ti99_nop_8_w);
3235   }
3236
3237
3238   switch (input_port_read(machine, "DISKCTRL"))
3239   {
3240   case DISK_TIFDC:
3241      ti99_fdc_reset(machine);
3242      break;
3243#if HAS_99CCFDC
3244   case DISK_CC:
3245      ti99_ccfdc_reset(machine);
3246      break;
3247#endif
3248   case DISK_BWG:
3249      ti99_bwg_reset(machine);
3250      break;
3251   case DISK_HFDC:
3252      ti99_hfdc_reset(machine);
3253      break;
3254   case DISK_NONE:
3255      break;
3256   }
3257
3258   if (has_ide)
3259      ti99_ide_reset(machine, FALSE);
3260
3261   if (has_usb_sm)
3262      ti99_usbsm_reset(machine, FALSE);
3263
3264   if (has_pcode)
3265      ti99_pcode_reset(machine);
3266}
3267
3268
3269/*
3270    SNUG SGCPU (a.k.a. 99/4p) Super AMS clone support.
3271    Compatible with Super AMS, but uses a 16-bit bus.
3272
3273    Up to 1Mb of SRAM.  Straightforward mapper, works with 4kb chunks.
3274*/
3275
3276/* set up handlers, and set initial state */
3277static void ti99_4p_mapper_init(running_machine *machine)
3278{
3279   int i;
3280   char bank_name[10];
3281   /* Not required at run-time */
3282   ti99_peb_set_16bit_card_handlers(expansion_box, 0x1e00, & ti99_4p_mapper_handlers);
3283
3284   ti99_4p_mapper_on = 0;
3285
3286   for (i=0; i<16; i++)
3287   {
3288      ti99_4p_mapper_lookup[i] = i << 11;
3289
3290      /* update bank base */
3291      switch (i)
3292      {
3293      case 2:
3294      case 3:
3295         sprintf(bank_name,"bank%d",3+(i-2));
3296         memory_set_bankptr(machine,bank_name, xRAM_ptr + (i<<11));
3297         break;
3298
3299      case 10:
3300      case 11:
3301      case 12:
3302      case 13:
3303      case 14:
3304      case 15:
3305         sprintf(bank_name,"bank%d",5+(i-10));
3306         memory_set_bankptr(machine,bank_name, xRAM_ptr + (i<<11));
3307         break;
3308      }
3309   }
3310}
3311
3312/*
3313    Write CRU bit:
3314    bit0: enable/disable mapper registers in DSR space,
3315    bit1: enable/disable address mapping
3316*/
3317static void ti99_4p_mapper_cru_w(running_machine *machine, int offset, int data)
3318{
3319   int i;
3320   char bank_name[10];
3321
3322   if (offset == 1)
3323   {
3324      if (ti99_4p_mapper_on != data)
3325      {
3326         ti99_4p_mapper_on = data;
3327
3328         for (i=0; i<16; i++)
3329         {
3330            /* update bank base */
3331            switch (i)
3332            {
3333            case 2:
3334            case 3:
3335               sprintf(bank_name,"bank%d",3+(i-2));
3336               memory_set_bankptr(machine,bank_name, xRAM_ptr + (ti99_4p_mapper_on ? (ti99_4p_mapper_lookup[i]) : (i<<11)));
3337               break;
3338
3339            case 10:
3340            case 11:
3341            case 12:
3342            case 13:
3343            case 14:
3344            case 15:
3345               sprintf(bank_name,"bank%d",5+(i-10));
3346               memory_set_bankptr(machine,bank_name, xRAM_ptr + (ti99_4p_mapper_on ? (ti99_4p_mapper_lookup[i]) : (i<<11)));
3347               break;
3348            }
3349         }
3350      }
3351   }
3352}
3353
3354/* read a mapper register */
3355static READ16_HANDLER(ti99_4p_mapper_r)
3356{
3357   return (ti99_4p_mapper_lookup[offset & 0xf] >> 3);
3358}
3359
3360/* write a mapper register */
3361static WRITE16_HANDLER(ti99_4p_mapper_w)
3362{
3363   int page = offset & 0xf;
3364   char bank_name[10];
3365   ti99_4p_mapper_lookup[page] = (data & 0xff00) << 3;
3366
3367   if (ti99_4p_mapper_on)
3368   {
3369      /* update bank base */
3370      switch (page)
3371      {
3372      case 2:
3373      case 3:
3374         sprintf(bank_name,"bank%d",3+(page-2));
3375         memory_set_bankptr(space->machine,bank_name, xRAM_ptr+ti99_4p_mapper_lookup[page]);
3376         break;
3377
3378      case 10:
3379      case 11:
3380      case 12:
3381      case 13:
3382      case 14:
3383      case 15:
3384         sprintf(bank_name,"bank%d",5+(page-10));
3385         memory_set_bankptr(space->machine,bank_name, xRAM_ptr+ti99_4p_mapper_lookup[page]);
3386         break;
3387      }
3388   }
3389}
3390
3391/*
3392    Internal DSR support.
3393    Includes a few specific signals, and an extra ROM.
3394*/
3395static void ti99_4p_internal_dsr_reset(running_machine *machine)
3396{
3397   // set up handlers, and set initial state
3398   UINT8* mem = memory_region(machine, "maincpu");
3399
3400   ti99_4p_internal_DSR = (UINT16 *) (mem + offset_rom4_4p);
3401   rom6_bank_offset = offset_rom6_4p;
3402   ti99_4p_mem = (UINT16 *)mem;
3403
3404   ti99_peb_set_16bit_card_handlers(expansion_box, 0x0f00, &ti99_4p_internal_dsr_handlers);
3405
3406   ti99_4p_internal_rom6_enable = 0;
3407   ti99_4p_peb_set_senila(expansion_box, 0);
3408   ti99_4p_peb_set_senilb(expansion_box, 0);
3409}
3410
3411/*
3412    Write CRU bit:
3413    bit0: enable/disable internal DSR ROM,
3414    bit1: enable/disable internal cartridge ROM
3415    bit2: set/clear senila
3416    bit3: set/clear senilb
3417*/
3418static void ti99_4p_internal_dsr_cru_w(running_machine *machine, int offset, int data)
3419{
3420   switch (offset)
3421   {
3422   case 1:
3423      ti99_4p_internal_rom6_enable = data;
3424      break;
3425   case 2:
3426      ti99_4p_peb_set_senila(expansion_box, data);
3427      break;
3428   case 3:
3429      ti99_4p_peb_set_senilb(expansion_box, data);
3430      break;
3431   case 4:
3432      /* 0: 16-bit (fast) memory timings */
3433      /* 1: 8-bit memory timings */
3434      break;
3435   case 5:
3436      /* if 0: "KBENA" mode (enable keyboard?) */
3437      /* if 1: "KBINH" mode (inhibit keyboard?) */
3438      break;
3439   }
3440}
3441
3442/*
3443    Read internal DSR ROM.
3444    Addresses 4000-5fff
3445*/
3446static READ16_HANDLER(ti99_4p_internal_dsr_r)
3447{
3448   return ti99_4p_internal_DSR[offset];
3449}
3450
3451/*
3452    SGCPU cartridge space: mapped either to internal ROM6 or to HSGPL.
3453    Addresses 6000-7fff
3454*/
3455READ16_HANDLER ( ti99_4p_cart_r )
3456{
3457   UINT16 value = 0;
3458   if (ti99_4p_internal_rom6_enable)
3459   {
3460      value = ti99_4p_mem[(rom6_bank_offset>>1) + offset];
3461   }
3462   else
3463   {
3464      cpu_adjust_icount(space->machine->device("maincpu"),-4);
3465      //  cpu_spinuntil_time(space->machine->firstcpu, ATTOTIME_IN_USEC(6));
3466
3467      if (hsgpl_crdena)
3468         /* hsgpl is enabled */
3469         value = ti99_hsgpl_rom6_r(space, offset, mem_mask);
3470   }
3471   return value;
3472}
3473
3474WRITE16_HANDLER ( ti99_4p_cart_w )
3475{
3476   if (ti99_4p_internal_rom6_enable)
3477   {
3478      // Switch ROMs
3479      if (offset & 1)
3480         rom6_bank_offset = offset_rom6b_4p;
3481      else
3482         rom6_bank_offset = offset_rom6_4p;
3483   }
3484   else
3485   {
3486      cpu_adjust_icount(space->machine->device("maincpu"),-4);
3487      //  cpu_spinuntil_time(space->machine->firstcpu, ATTOTIME_IN_USEC(6));
3488
3489      if (hsgpl_crdena)
3490         /* hsgpl is enabled */
3491         ti99_hsgpl_rom6_w(space, offset, data, mem_mask);
3492   }
3493}
3494
3495/*
3496    GROM read for TI-99/4p
3497*/
3498READ16_HANDLER ( ti99_4p_grom_r )
3499{
3500   UINT16 value = 0;
3501   // HSGPL is located on 8-bit bus
3502   cpu_adjust_icount(space->machine->device("maincpu"),-4);
3503   //  cpu_spinuntil_time(space->machine->firstcpu, ATTOTIME_IN_USEC(6));
3504
3505   // When crdena is false, we must still be able to query the address
3506   // counter (offset & 1)
3507   if (hsgpl_crdena || (offset & 1))
3508      value = ti99_hsgpl_gpl_r(space, offset, mem_mask);
3509
3510   return value;
3511}
3512
3513/*
3514    GROM write
3515*/
3516WRITE16_HANDLER ( ti99_4p_grom_w )
3517{
3518   // HSGPL is located on 8-bit bus
3519   cpu_adjust_icount(space->machine->device("maincpu"),-4);
3520   //  cpu_spinuntil_time(space->machine->firstcpu, ATTOTIME_IN_USEC(6));
3521
3522   if (hsgpl_crdena || (offset & 1))
3523      ti99_hsgpl_gpl_w(space, offset, data, mem_mask);
3524}
3525
src/mess/machine/ti99_4x.h
r9500r9501
1/*
2    header file for machine/ti99_4x.c
3*/
4#include "video/tms9928a.h"
5#include "machine/tms9901.h"
6
7#include "devices/ti99cart.h"
8#include "devices/cartslot.h"
9
10/* defines */
11
12#define HAS_99CCFDC 0
13
14/* region identifiers */
15#define region_grom "cons_grom"
16#define region_dsr "dsr"
17#define region_hsgpl "hsgpl"
18#define region_speech_rom "tms5220"
19
20/* offsets for "maincpu" */
21enum
22{
23   offset_sram = 0x2000,      /* scratch RAM (256 bytes) */
24   offset_cart = 0x2100,      /* cartridge ROM/RAM (2*8 kbytes) */
25   offset_xram = 0x6100,      /* extended RAM (32 kbytes - 512kb with myarc-like mapper, 1Mb with super AMS) */
26   region_cpu1_len = 0x106100   /* total len */
27};
28
29enum
30{
31   offset_rom0_4p = 0x4000,        // ROM0: 4000-5fff
32   offset_rom4_4p = 0xc000,        // ROM4: c000-dfff
33   offset_rom6_4p = 0x6000,        // ROM6: 6000-7fff (first bank)
34   offset_rom6b_4p= 0xe000,        // ROM6: e000-ffff (second bank)
35   offset_sram_4p = 0x10000,       // scratch RAM (1 KiB)
36   offset_dram_4p = 0x10400,       // extra ram for debugger (768 bytes)
37   offset_xram_4p = 0x10700,       // extended RAM (1Mb with super AMS compatible mapper)
38   region_cpu1_len_4p = 0x110700   // total len
39};
40
41enum
42{
43   offset_rom0_8 = 0x0000,         /*  system ROM (32kbytes, though hexbus DSR and pascal are missing) */
44   offset_cart_8 = 0x8000,         /* cartridge ROM/RAM (2*8 kbytes) */
45   offset_sram_8 = 0xc000,         /* scratch RAM (2kbytes) */
46   offset_xram_8 = 0xc800,         /* extended RAM (64kbytes, expandable to almost 16MBytes) */
47   region_cpu1_len_8 = 0x1c800      /* total len */
48};
49
50/* offsets for region_dsr */
51enum
52{
53   offset_fdc_dsr   = 0x0000,         /* TI FDC DSR (8kbytes) */
54   offset_ccfdc_dsr = offset_fdc_dsr   + 0x02000,   /* CorcComp FDC DSR (16kbytes) */
55   offset_bwg_dsr   = offset_ccfdc_dsr + 0x04000,   /* BwG FDC DSR (32kbytes) */
56   offset_bwg_ram   = offset_bwg_dsr   + 0x08000,   /* BwG FDC RAM (2kbytes) */
57   offset_hfdc_dsr  = offset_bwg_ram   + 0x00800,   /* HFDC FDC DSR (16kbytes) */
58   offset_hfdc_ram  = offset_hfdc_dsr  + 0x04000,   /* HFDC FDC RAM (32kbytes) */
59   offset_rs232_dsr = offset_hfdc_ram  + 0x08000,   /* TI RS232 DSR (4kbytes) */
60   offset_evpc_dsr  = offset_rs232_dsr + 0x01000,   /* EVPC DSR (64kbytes) */
61   offset_ide_ram   = offset_evpc_dsr  + 0x10000,   /* IDE card RAM (32 to 2Mbytes, we settled for 512kbytes) */
62   offset_ide_ram2  = offset_ide_ram   + 0x80000,   /* IDE RTC RAM (4kbytes) */
63   offset_pcode_rom = offset_ide_ram2  + 0x01000,  /* P-Code Card ROM (12KiB) */
64   offset_pcode_grom= offset_pcode_rom + 0x03000,  /* P-Code Card GROM (64KiB) */
65   region_dsr_len   = offset_pcode_grom+ 0x10000
66};
67
68/* offsets for region_hsgpl */
69enum
70{
71   offset_hsgpl_dsr  = 0x000000,               /* DSR (512kbytes) */
72   offset_hsgpl_grom = 0x080000,               /* GROM (1Mbytes) */
73   offset_hsgpl_rom6 = 0x180000,               /* ROM6 (512kbytes) */
74   offset_hsgpl_gram = 0x200000,               /* GRAM (128kbytes) */
75   offset_hsgpl_ram6 = 0x220000,               /* RAM6 (128kbytes, but only 64kbytes are used) */
76
77   region_hsgpl_len  = /*0x240000*/0x230000
78};
79
80/* GROM_port_t: descriptor for a port of 8 GROMs. Required by ti99_4x, ti99pcod */
81struct _GROM_port_t
82{
83   // pointer to GROM data
84   UINT8 *data_ptr;
85   // current address pointer for the active GROM in port (16 bits)
86   unsigned int addr;
87   // GROM data buffer
88   UINT8 buf;
89   // internal flip-flops that are set after the first access to the GROM
90   // address so that next access is mapped to the LSB, and cleared after each
91   // data access
92   char raddr_LSB, waddr_LSB;
93};
94typedef struct _GROM_port_t GROM_port_t;
95
96/*
97    Configuration values
98*/
99enum
100{
101   RAM_NONE = 0,
102   RAM_TI32,
103   RAM_SUPERAMS1024,
104   RAM_FOUNDATION128,
105   RAM_FOUNDATION512,
106   RAM_MYARC128,
107   RAM_MYARC512,
108   RAM_99_4P,
109   RAM_99_8
110};
111
112enum
113{
114   DISK_NONE = 0,
115   DISK_TIFDC,
116   DISK_BWG,
117   DISK_HFDC,
118   DISK_CC
119};
120
121enum
122{
123   HD_NONE = 0,
124   HD_IDE,
125   HD_WHTECH,
126   HD_USB = 4
127};
128
129enum
130{
131   SERIAL_NONE = 0,
132   SERIAL_TI
133};
134
135enum
136{
137   EXT_NONE = 0,
138   EXT_HSGPL_FLASH = 1,
139   EXT_HSGPL_ON = 2,
140   EXT_PCODE = 4
141};
142
143enum
144{
145   HCI_NONE = 0,
146   HCI_MECMOUSE = 1,
147   HCI_IR = 4
148};
149
150enum
151{
152   CART_AUTO = 0,
153   CART_1,
154   CART_2,
155   CART_3,
156   CART_4,
157   CART_GK = 15
158};
159
160enum
161{
162   GK_OFF = 0,
163   GK_NORMAL = 1,
164   GK_GRAM0 = 0,
165   GK_OPSYS = 1,
166   GK_GRAM12 = 0,
167   GK_TIBASIC = 1,
168   GK_BANK1 = 0,
169   GK_WP = 1,
170   GK_BANK2 = 2,
171   GK_LDON = 0,
172   GK_LDOFF = 1
173};
174
175
176/* Cartridge types */
177enum
178{
179   STANDARD,
180   EXBAS,
181   MINIMEM,
182   SUPERSPACE,
183   MBX
184};
185
186/* prototypes for machine code */
187
188DRIVER_INIT( ti99_4 );
189DRIVER_INIT( ti99_4a );
190DRIVER_INIT( ti99_4ev );
191DRIVER_INIT( ti99_8 );
192DRIVER_INIT( ti99_4p );
193
194MACHINE_START( ti99_4_60hz );
195MACHINE_START( ti99_4_50hz );
196MACHINE_START( ti99_4a_60hz );
197MACHINE_START( ti99_4a_50hz );
198MACHINE_START( ti99_4ev_60hz );
199MACHINE_START( ti99_4p );
200
201MACHINE_RESET( ti99 );
202MACHINE_RESET( ti99_4p );
203MACHINE_RESET( ti99_8 );
204
205/* For HSGPL */
206NVRAM_HANDLER( ti99 );
207INPUT_CHANGED( hsgpl_changed );
208
209/* For GRAM Kracker */
210INPUT_CHANGED( gk_changed );
211
212/* For EVPC */
213INPUT_CHANGED( evpc_changed );
214
215VIDEO_START( ti99_4ev );
216INTERRUPT_GEN( ti99_vblank_interrupt );
217INTERRUPT_GEN( ti99_4ev_hblank_interrupt );
218TIMER_DEVICE_CALLBACK( ti99_4ev_scanline_interrupt );
219
220void ti99_set_hsgpl_crdena(int data);
221void ti99_common_init(running_machine *machine, const TMS9928a_interface *gfxparm);
222int ti99_is_99_8(void);
223
224UINT8 get_gk_switch(int index);
225
226READ16_HANDLER( ti99_nop_8_r );
227WRITE16_HANDLER( ti99_nop_8_w );
228
229READ16_HANDLER( ti99_cart_r );
230WRITE16_HANDLER( ti99_cart_w );
231READ16_HANDLER( ti99_4p_cart_r );
232WRITE16_HANDLER( ti99_4p_cart_w );
233
234WRITE16_HANDLER( ti99_wsnd_w );
235
236READ16_HANDLER( ti99_rvdp_r );
237WRITE16_HANDLER( ti99_wvdp_w );
238READ16_HANDLER( ti99_rv38_r );
239WRITE16_HANDLER( ti99_wv38_w );
240
241READ16_HANDLER( ti99_grom_r );
242WRITE16_HANDLER( ti99_grom_w );
243READ16_HANDLER( ti99_4p_grom_r );
244WRITE16_HANDLER( ti99_4p_grom_w );
245
246void tms9901_set_int2(running_machine *machine, int state);
247void tms9901_set_int1(running_machine *machine, int state);
248
249READ8_HANDLER ( ti99_8_r );
250WRITE8_HANDLER ( ti99_8_w );
251
252extern const tms9901_interface tms9901reset_param_ti99_4x;
253extern const tms9901_interface tms9901reset_param_ti99_8;
254
255void ti99_clk_interrupt_callback(running_device *device, int state);
src/mess/machine/ti99/genboard.c
r9500r9501
1111#include "sound/sn76496.h"
1212#include "machine/mm58274c.h"
1313#include "peribox.h"
14#include "includes/geneve.h"
1514
1615#define KEYQUEUESIZE 256
1716#define MAXKEYMSGLENGTH 10
r9500r9501
4746   int    keyAutoRepeatTimer;
4847
4948   /* Mode flags */
50   int      palvideo;         // bit 5 +
51   int      capslock;         // bit 7 +
52   int      keyboard_clock;      // bit 8 +
53   int      keep_keybuf;      // bit 9 keyclear -
54   int      zero_wait;         // bit 15
49   int      palvideo;
50   int      capslock;
51   int      keyboard_clock;
52   int      keep_keybuf;
53   int      zero_wait;
5554
5655   /* GROM simulation */
5756   int      grom_address;
r9500r9501
6463   UINT8   *eprom;
6564
6665   /* Mapper */
67   int    geneve_mode;          // +
68   int      direct_mode;          // mapmode -
69   int      cartridge_size_8K;     // +
70   int      cartridge_secondpage;   // +
71   int      cartridge6_writable;    // protect -
72   int      cartridge7_writable;    // protect -
66   int    geneve_mode;
67   int      direct_mode;
68   int      cartridge_size_8K;
69   int      cartridge_secondpage;
70   int      cartridge6_writable;
71   int      cartridge7_writable;
7372   int      map[8];
7473
7574   int      line_count;
r9500r9501
9089   0x1c,   /* keypad enter */
9190   0x1d,   /* right control */
9291   0x38,   /* alt gr */
93   /* extra codes are 0x5b for Left Windows, 0x5c for Right Windows, 0x5d
94    for Menu, 0x5e for power, 0x5f for sleep, 0x63 for wake, but I doubt
95    any Geneve program would take advantage of these. */
92   // extra codes are 0x5b for Left Windows, 0x5c for Right Windows, 0x5d
93   // for Menu, 0x5e for power, 0x5f for sleep, 0x63 for wake, but I doubt
94   // any Geneve program would take advantage of these. */
9695
97   /* extended key that is equivalent to a non-extended key
98    with shift off */
96   // extended key that is equivalent to a non-extended key
97   // with shift off
9998   0x35,   /* pad slash */
10099
101   /* extended keys that are equivalent to non-extended keys
102    with numlock off */
100   // extended keys that are equivalent to non-extended keys
101   // with numlock off
103102   0x47,   /* home */
104103   0x48,   /* up */
105104   0x49,   /* page up */
r9500r9501
12481247
12491248   if (input_port_read(device->machine, "BOOTROM")==0)
12501249   {
1251      board->eprom = memory_region(device->machine, "maincpu") + offset_altrom_geneve;
1250      board->eprom = memory_region(device->machine, "maincpu") + 0x4000;
12521251   }
12531252}
12541253
src/mess/machine/ti99/genboard.h
r9500r9501
1010
1111extern const tms9901_interface tms9901_wiring_geneve;
1212void tms9901_gen_set_int2(running_machine *machine, int state);
13INTERRUPT_GEN( geneve_hblank_interrupt );
1314
1415/* device interface */
1516DECLARE_LEGACY_DEVICE( GENBOARD, genboard );
src/mess/includes/geneve.h
r9500r9501
1/*****************************************************************************
2 *
3 * includes/geneve.h
4 *
5 * header file for the Geneve driver
6 *
7 ****************************************************************************/
8
9#ifndef GENEVE_H_
10#define GENEVE_H_
11
12#include "machine/tms9901.h"
13
14/* defines */
15
16/* offsets for "maincpu" */
17enum
18{
19   offset_rom_geneve = 0x0000,         /* boot ROM (16 kbytes) */
20   offset_altrom_geneve = 0x4000,         /* alternative boot ROM (16 kbytes) */
21   offset_sram_geneve = 0x8000,      /* static RAM (32 or 64 kbytes) */
22   offset_dram_geneve = 0x18000,      /* dynamic RAM (512 kbytes) or SRAM (2MBytes) with Memex board and GenMod extension */
23   region_cpu1_len_geneve = 0x218000   /* total len */
24};
25
26
27/*----------- defined in machine/geneve.c -----------*/
28
29/* prototypes for machine code */
30
31DRIVER_INIT( geneve );
32DRIVER_INIT( genmod );
33
34MACHINE_START( geneve );
35MACHINE_RESET( geneve );
36
37VIDEO_START( geneve );
38INTERRUPT_GEN( geneve_hblank_interrupt );
39
40READ8_HANDLER ( geneve_r );
41WRITE8_HANDLER ( geneve_w );
42
43WRITE8_HANDLER ( geneve_peb_mode_cru_w );
44
45extern const tms9901_interface tms9901reset_param_ti99;
46void ti99_clk_interrupt_callback(running_device *device, int state);
47
48/* prototypes */
49void inta_callback(running_machine *machine, int state);
50void intb_callback(running_machine *machine, int state);
51
52#endif /* GENEVE_H_ */
src/mess/formats/ti99_dsk.c
r9500r9501
8686/*
8787    Determines whether we are using 80 track drives. This variable is
8888    necessary unless we get information about the dip
89    switch settings. It is set from 99_dsk.c, currenly the only client.
89    switch settings. It is set by the disk controller implementations
90    (bwg, hfdc, ti_fdc).
9091*/
9192static int use_80_track_drives = FALSE;
9293
r9500r9501
114115    need to be able to emulate 40 track drives and 80 track drives.
115116    This is set in the configuration, but the format has no direct access.
116117    So as a preliminary solution we use this global function which sets the
117    flag. This function is called by the controllers defined in 99_dsk.
118    flag. This function is called by the disk controller implementations
119    (bwg, hfdc, ti_fdc).
118120*/
119121void ti99_set_80_track_drives(int use80)
120122{
r9500r9501
126128#if 0
127129static void dump_contents(UINT8 *buffer, int length)
128130{
129        for (int i=0; i < length; i+=16)
130        {
131                for (int j=0; j < 16; j+=2)
132                {
133                        printf("%02x%02x ", buffer[i+j], buffer[i+j+1]);
134                }
135                printf("\n");
136        }
131   for (int i=0; i < length; i+=16)
132   {
133      for (int j=0; j < 16; j+=2)
134      {
135         printf("%02x%02x ", buffer[i+j], buffer[i+j+1]);
136      }
137      printf("\n");
138   }
137139}
138140#endif
139141
src/mess/drivers/geneve.c
r9500r9501
200200#include "emu.h"
201201#include "cpu/tms9900/tms9900.h"
202202#include "deprecat.h"
203#include "includes/geneve.h"
204203#include "machine/ti99/genboard.h"
205204#include "machine/tms9901.h"
206205#include "machine/ti99/videowrp.h"
r9500r9501
468467   MDRV_MACHINE_RESET( geneve )
469468
470469   /* video hardware */
471   MDRV_TI_V9938_ADD("video", 60, "screen", 2500, 512+32, (212+28)*2, tms9901_gen_set_int2)   
470   MDRV_TI_V9938_ADD("video", 60, "screen", 2500, 512+32, (212+28)*2, tms9901_gen_set_int2)
472471
473472   /* sound hardware */
474473   MDRV_SPEAKER_STANDARD_MONO("mono")
r9500r9501
492491
493492ROM_START(geneve)
494493   /*CPU memory space*/
495   ROM_REGION(region_cpu1_len_geneve, "maincpu", 0)
496   ROM_LOAD("genbt100.bin", offset_rom_geneve, 0x4000, CRC(8001e386) SHA1(b44618b54dabac3882543e18555d482b299e0109)) /* CPU ROMs */
497   ROM_LOAD_OPTIONAL("genbt090.bin", offset_altrom_geneve, 0x4000, CRC(b2e20df9) SHA1(2d5d09177afe97d63ceb3ad59b498b1c9e2153f7)) /* CPU ROMs */
494   ROM_REGION(0x8000, "maincpu", 0)
495   ROM_LOAD("genbt100.bin", 0x0000, 0x4000, CRC(8001e386) SHA1(b44618b54dabac3882543e18555d482b299e0109)) /* CPU ROMs */
496   ROM_LOAD_OPTIONAL("genbt090.bin", 0x4000, 0x4000, CRC(b2e20df9) SHA1(2d5d09177afe97d63ceb3ad59b498b1c9e2153f7)) /* CPU ROMs */
498497ROM_END
499498
500499ROM_START(genmod)
501500   /*CPU memory space*/
502   ROM_REGION(region_cpu1_len_geneve, "maincpu", 0)
503   ROM_LOAD("gnmbt100.bin", offset_rom_geneve, 0x4000, CRC(19b89479) SHA1(6ef297eda78dc705946f6494e9d7e95e5216ec47)) /* CPU ROMs */
501   ROM_REGION(0x8000, "maincpu", 0)
502   ROM_LOAD("gnmbt100.bin", 0x0000, 0x4000, CRC(19b89479) SHA1(6ef297eda78dc705946f6494e9d7e95e5216ec47)) /* CPU ROMs */
503   ROM_LOAD_OPTIONAL("genbt090.bin", 0x4000, 0x4000, CRC(b2e20df9) SHA1(2d5d09177afe97d63ceb3ad59b498b1c9e2153f7)) /* CPU ROMs */
504504ROM_END
505505
506506/*    YEAR  NAME      PARENT    COMPAT  MACHINE      INPUT    INIT       COMPANY     FULLNAME */

Previous 15994 Revisions Next


© 1998-2018 The MESS Team