Previous 15994 Revisions Next

r9547 Tuesday 9th November, 2010 at 17:15:46 UTC by Sandro Ronco
Converted EF9345 into c++ device
[src/mess/drivers]mc10.c vg5k.c
[src/mess/video]ef9345.c ef9345.h

src/mess/video/ef9345.c
r9546r9547
2121#define MODE12x80   3
2222#define MODE16x40   4
2323
24typedef struct _ef9345_t ef9345_t;
25struct _ef9345_t
24//**************************************************************************
25//  GLOBAL VARIABLES
26//**************************************************************************
27
28// devices
29const device_type EF9345 = ef9345_device_config::static_alloc_device_config;
30
31// default address map
32static ADDRESS_MAP_START( ef9345, 0, 8 )
33   AM_RANGE(0x0000, 0x3fff) AM_RAM
34ADDRESS_MAP_END
35
36//**************************************************************************
37//  device configuration
38//**************************************************************************
39
40//-------------------------------------------------
41//  ef9345_device_config - constructor
42//-------------------------------------------------
43
44ef9345_device_config::ef9345_device_config( const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock ):
45   device_config( mconfig, static_alloc_device_config, "ef9345", tag, owner, clock),
46   device_config_memory_interface(mconfig, *this),
47   m_space_config("videoram", ENDIANNESS_LITTLE, 8, 16, 0, NULL, *ADDRESS_MAP_NAME(ef9345))
2648{
27   screen_device *screen;         //screen we are acting on
49}
2850
29   UINT8 bf;                  //busy flag
30   UINT8 char_mode;            //40 or 80 chars for line
31   UINT8* charset;               //charset
32   UINT8 ram[0x4000];            //16Ko (logique) pour 8Ko (physique)
33   UINT8 acc_char[0x2000];         //8Ko (logique) polices accentuees
34   UINT8 registers[8];            //registers R0-R7
35   UINT8 state;               //status register
36   UINT8 TGS,MAT,PAT,DOR,ROR;      //registres acces indirect
37   UINT8 border[80];            //caractere du cadre
38   UINT8 *block;               //pointeur block courant
39   UINT8 *char_ptr[16];         //pointeurs polices de caracteres
40   UINT16 blink;               //etat du clignotement
41   UINT8 dial;                  //cadran en cours d'affichage
42   UINT16 last_dial[40];         //dernier cadran affiche
43   UINT8 latchc0;               //couleur c0 latchee
44   UINT16 latchm;               //attribut m(conceal) latche
45   UINT16 latchi;               //attribut i(insert) latche
46   UINT16 latchu;               //attribut u(underline) latche
4751
48   bitmap_t *screen_out;
52//-------------------------------------------------
53//  static_alloc_device_config - allocate a new
54//  configuration object
55//-------------------------------------------------
4956
50   emu_timer *busy_timer;
51   emu_timer *blink_timer;
52};
57device_config *ef9345_device_config::static_alloc_device_config( const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock )
58{
59   return global_alloc( ef9345_device_config( mconfig, tag, owner, clock ) );
60}
5361
54static TIMER_CALLBACK( ef9345_done );
5562
63//-------------------------------------------------
64//  alloc_device - allocate a new device object
65//-------------------------------------------------
5666
57INLINE _ef9345_t *get_safe_token(running_device *device)
67device_t *ef9345_device_config::alloc_device( running_machine &machine ) const
5868{
59   assert(device != NULL);
60   assert(device->type() == EF9345);
61   return (_ef9345_t *)downcast<legacy_device_base *>(device)->token();
69   return auto_alloc( &machine, ef9345_device( machine, *this ) );
6270}
6371
64/*-------------------------------------------------
65    set busy flag and timer to clear it
66-------------------------------------------------*/
67static void set_busy_flag(ef9345_t *ef9345, int period)
72//-------------------------------------------------
73//  memory_space_config - return a description of
74//  any address spaces owned by this device
75//-------------------------------------------------
76
77const address_space_config *ef9345_device_config::memory_space_config(int spacenum) const
6878{
69   ef9345->bf = 1;
79   return (spacenum == 0) ? &m_space_config : NULL;
80}
7081
71   timer_adjust_oneshot(ef9345->busy_timer, ATTOTIME_IN_USEC(period), 0);
82//-------------------------------------------------
83//  device_config_complete - perform any
84//  operations now that the configuration is
85//  complete
86//-------------------------------------------------
87
88void ef9345_device_config::device_config_complete()
89{
90   // inherit a copy of the static data
91   const ef9345_interface *intf = reinterpret_cast<const ef9345_interface *>(static_config());
92
93   if (intf != NULL)
94   {
95      *static_cast<ef9345_interface *>(this) = *intf;
96   }
97   // or initialize to defaults if none provided
98   else
99   {
100      screen_tag = NULL;
101   }
72102}
73103
74/*-------------------------------------------------
75    draw a char in 40 char line mode
76-------------------------------------------------*/
77void draw_char_40(ef9345_t *ef9345, UINT8 *c, int x, int y)
104
105//**************************************************************************
106//  INLINE HELPERS
107//**************************************************************************
108
109// calculate the internal RAM offset
110inline UINT16 ef9345_device::indexram(UINT8 r)
78111{
79   UINT16 i, j;
112   UINT8 x = registers[r];
113   UINT8 y = registers[r - 1];
114   if (y < 8)
115      y &= 1;
116   return ((x&0x3f) | ((x & 0x40) << 6) | ((x & 0x80) << 4) | ((y & 0x1f) << 6) | ((y & 0x20) << 8));
117}
80118
81   /* verify size limit */
82   if (y * 10 >= ef9345->screen->height() || x * 8 >= ef9345->screen->width())
83      return;
119// calculate the internal ROM offset
120inline UINT16 ef9345_device::indexrom(UINT8 r)
121{
122   UINT8 x = registers[r];
123   UINT8 y = registers[r - 1];
124   if (y < 8)
125      y &= 1;
126   return((x&0x3f)|((x&0x40)<<6)|((x&0x80)<<4)|((y&0x1f)<<6));
127}
84128
85   for(i = 0; i < 10; i++)
86      for(j = 0; j < 8; j++)
87            *BITMAP_ADDR16(ef9345->screen_out, y * 10 + i, x * 8 + j)  = c[8 * i + j] & 0x07;
129// increment x
130inline void ef9345_device::inc_x(UINT8 r)
131{
132   UINT8 i = (registers[r] & 0x3f) + 1;
133   if (i > 39)
134   {
135      i -= 40;
136      state |= 0x40;
137   }
138   registers[r] = (registers[r] & 0xc0) | i;
88139}
89140
90/*-------------------------------------------------
91    draw a char in 80 char line mode
92-------------------------------------------------*/
93void draw_char_80(ef9345_t *ef9345, UINT8 *c, int x, int y)
141// increment y
142inline void ef9345_device::inc_y(UINT8 r)
94143{
95   int i, j;
144   UINT8 i = (registers[r] & 0x1f) + 1;
145   if (i > 31)
146      i -= 24;
147   registers[r] = (registers[r] & 0xe0) | i;
148}
96149
97   /* verify size limit */
98   if (y * 10 >= ef9345->screen->height() || x * 6 >= ef9345->screen->width())
99      return;
100150
101   for(i = 0; i < 10; i++)
102      for(j = 0; j < 6; j++)
103            *BITMAP_ADDR16(ef9345->screen_out, y * 10 + i, x * 6 + j)  = c[6 * i + j] & 0x07;
151//**************************************************************************
152//  live device
153//**************************************************************************
154
155//-------------------------------------------------
156//  ef9345_device - constructor
157//-------------------------------------------------
158
159ef9345_device::ef9345_device( running_machine &_machine, const ef9345_device_config &config ) :
160    device_t(_machine, config),
161   device_memory_interface(_machine, config, *this),
162    m_config(config)
163{
104164}
105165
166//-------------------------------------------------
167//  device_start - device-specific startup
168//-------------------------------------------------
106169
107/*-------------------------------------------------
108    set then ef9345 mode
109-------------------------------------------------*/
110void set_ef9345_mode(ef9345_t *ef9345)
170void ef9345_device::device_start()
111171{
112   UINT8 i;
113   ef9345->char_mode = ((ef9345->PAT & 0x80) >> 5) | ((ef9345->TGS & 0xc0) >> 6);
114   UINT16 new_width = (ef9345->char_mode == MODE12x80 || ef9345->char_mode == MODE8x80) ? 492 : 336;
172   screen = machine->device<screen_device>(m_config.screen_tag);
115173
116   if (ef9345->screen->width() != new_width)
117   {
118      rectangle visarea = ef9345->screen->visible_area();
119      visarea.max_x = new_width - 1;
174   assert(screen != NULL);
120175
121      ef9345->screen->configure(new_width, ef9345->screen->height(), visarea, ef9345->screen->frame_period().attoseconds);
122   }
176   m_busy_timer = device_timer_alloc(*this, BUSY_TIMER);
177   m_blink_timer = device_timer_alloc(*this, BLINKING_TIMER);
123178
124   //couleur de bordure
125   for(i = 0; i < 80; i++)
126      ef9345->border[i] = ef9345->MAT & 0x07;
179   videoram = space(0);
180   charset = region();
127181
128   //polices (avec ram 8K)
129   ef9345->char_ptr[0x08] = ef9345->ram + ((ef9345->DOR & 0x07) << 11); //G'0
130   ef9345->char_ptr[0x09] = ef9345->char_ptr[0x08];                     //G'0 underlined
131   ef9345->char_ptr[0x0a] = ef9345->ram + ((ef9345->DOR & 0x30) << 8);  //G'10
132   ef9345->char_ptr[0x0b] = ef9345->char_ptr[0x0a] + 0x800;             //G'11
133   ef9345->char_ptr[0x0c] = ef9345->ram;                        //Quadrichrome
134   ef9345->char_ptr[0x0d] = ef9345->char_ptr[0x0c];
135   ef9345->char_ptr[0x0e] = ef9345->char_ptr[0x0c];
136   ef9345->char_ptr[0x0f] = ef9345->char_ptr[0x0c];
182   screen_out = auto_bitmap_alloc(machine, 496, screen->height() , BITMAP_FORMAT_INDEXED16);
137183
138   //adresse block memoire courant
139   i = ((ef9345->ROR & 0xf0) >> 4) | ((ef9345->ROR & 0x40) >> 5) | ((ef9345->ROR & 0x20) >> 3);
140   ef9345->block = ef9345->ram + 0x800 * (i & 0x0c);
184   timer_adjust_periodic(m_blink_timer, ATTOTIME_IN_MSEC(500), 0, ATTOTIME_IN_MSEC(500));
185
186   init_accented_chars();
187
188   state_save_register_device_item_array(this, 0, border);
189   state_save_register_device_item_array(this, 0, registers);
190   state_save_register_device_item_array(this, 0, last_dial);
191   state_save_register_device_item_array(this, 0, ram_base);
192   state_save_register_device_item(this, 0, bf);
193   state_save_register_device_item(this, 0, char_mode);
194   state_save_register_device_item(this, 0, state);
195   state_save_register_device_item(this, 0, TGS);
196   state_save_register_device_item(this, 0, MAT);
197   state_save_register_device_item(this, 0, PAT);
198   state_save_register_device_item(this, 0, DOR);
199   state_save_register_device_item(this, 0, ROR);
200   state_save_register_device_item(this, 0, block);
201   state_save_register_device_item(this, 0, blink);
202   state_save_register_device_item(this, 0, latchc0);
203   state_save_register_device_item(this, 0, latchm);
204   state_save_register_device_item(this, 0, latchi);
205   state_save_register_device_item(this, 0, latchu);
206
207   state_save_register_device_item_bitmap(this, 0, screen_out);
141208}
142209
143/*-------------------------------------------------
144    Initialize the ef9345 char_ptr
145-------------------------------------------------*/
146void init_char_prt(ef9345_t *ef9345)
210//-------------------------------------------------
211//  device_reset - device-specific reset
212//-------------------------------------------------
213void ef9345_device::device_reset()
147214{
148   int i, j;
149   //polices accentuees
150   for(j = 0; j < 0x10; j++)
151      for(i = 0; i < 0x200; i++)
152         ef9345->acc_char[(j << 9) + i] = ef9345->charset[0x0600 + i];
215   TGS = MAT = PAT = DOR = ROR = 0;
216   state = 0;
217   bf = 0;
218   block = 0;
219   blink = 0;
220   latchc0 = 0;
221   latchm = 0;
222   latchi = 0;
223   latchu = 0;
224   char_mode = 0;
153225
154   for(j = 0; j < 0x200; j += 0x40)
155      for(i = 0; i < 4; i++)
156      {
157         ef9345->acc_char[0x0200 + j + i +  4] |= 0x1c; //tilde
158         ef9345->acc_char[0x0400 + j + i +  4] |= 0x10; //aigu
159         ef9345->acc_char[0x0400 + j + i +  8] |= 0x08; //aigu
160         ef9345->acc_char[0x0600 + j + i +  4] |= 0x04; //grave
161         ef9345->acc_char[0x0600 + j + i +  8] |= 0x08; //grave
226   memset(last_dial, 0, ARRAY_LENGTH(last_dial) * sizeof(UINT8));
227   memset(registers, 0, ARRAY_LENGTH(registers) * sizeof(UINT8));
228   memset(border, 0, ARRAY_LENGTH(border) * sizeof(UINT8));
229   memset(border, 0, ARRAY_LENGTH(ram_base) * sizeof(UINT16));
162230
163         ef9345->acc_char[0x0a00 + j + i +  4] |= 0x1c; //tilde
164         ef9345->acc_char[0x0c00 + j + i +  4] |= 0x10; //aigu
165         ef9345->acc_char[0x0c00 + j + i +  8] |= 0x08; //aigu
166         ef9345->acc_char[0x0e00 + j + i +  4] |= 0x04; //grave
167         ef9345->acc_char[0x0e00 + j + i +  8] |= 0x08; //grave
231   bitmap_fill(screen_out, NULL, 0);
168232
169         ef9345->acc_char[0x1200 + j + i +  4] |= 0x08; //point
170         ef9345->acc_char[0x1400 + j + i +  4] |= 0x14; //trema
171         ef9345->acc_char[0x1600 + j + i + 32] |= 0x08; //cedille
172         ef9345->acc_char[0x1600 + j + i + 36] |= 0x04; //cedille
233   set_video_mode();
234}
173235
174         ef9345->acc_char[0x1a00 + j + i +  4] |= 0x08; //point
175         ef9345->acc_char[0x1c00 + j + i +  4] |= 0x14; //trema
176         ef9345->acc_char[0x1e00 + j + i + 32] |= 0x08; //cedille
177         ef9345->acc_char[0x1e00 + j + i + 36] |= 0x04; //cedille
178      }
236//-------------------------------------------------
237//  device_timer - handler timer events
238//-------------------------------------------------
239void ef9345_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
240{
241   switch(id)
242   {
243      case BUSY_TIMER:
244         bf = 0;
245         break;
179246
180   //initialisation des pointeurs de polices fixes
181   ef9345->char_ptr[0x00] = ef9345->charset;          //G0
182   ef9345->char_ptr[0x01] = ef9345->charset + 0x0800; //G0 underlined
183   ef9345->char_ptr[0x02] = ef9345->charset + 0x1000; //G11
184   ef9345->char_ptr[0x03] = ef9345->charset + 0x1800; //G10
185   ef9345->char_ptr[0x04] = ef9345->acc_char;          //G20
186   ef9345->char_ptr[0x05] = ef9345->acc_char + 0x0800; //G20 underlined
187   ef9345->char_ptr[0x06] = ef9345->acc_char + 0x1000; //G21
188   ef9345->char_ptr[0x07] = ef9345->acc_char + 0x1800; //G21 underlined
247      case BLINKING_TIMER:
248         blink = !blink;
249         break;
250   }
189251}
190252
191253
192/* calculate the internal RAM offset */
193UINT16 indexram(ef9345_t *ef9345, UINT8 r)
254// set busy flag and timer to clear it
255void ef9345_device::set_busy_flag(int period)
194256{
195   UINT8 x, y;
196   x = ef9345->registers[r];
197   y = ef9345->registers[r - 1];
198   if(y < 8)
199      y &= 1;
200   return ((x&0x3f) | ((x & 0x40) << 6) | ((x & 0x80) << 4) | ((y & 0x1f) << 6) | ((y & 0x20) << 8));
257   bf = 1;
258   timer_adjust_oneshot(m_busy_timer, ATTOTIME_IN_USEC(period), 0);
201259}
202260
203/* calculate the internal ROM offset */
204UINT16 indexrom(ef9345_t *ef9345, int r)
261// draw a char in 40 char line mode
262void ef9345_device::draw_char_40(UINT8 *c, UINT16 x, UINT16 y)
205263{
206   UINT8 x, y;
207   x = ef9345->registers[r];
208   y = ef9345->registers[r - 1];
209   if(y < 8)
210      y &= 1;
211   return((x&0x3f)|((x&0x40)<<6)|((x&0x80)<<4)|((y&0x1f)<<6));
264   //verify size limit
265   if (y * 10 >= screen->height() || x * 8 >= screen->width())
266      return;
267
268   for(int i = 0; i < 10; i++)
269      for(int j = 0; j < 8; j++)
270            *BITMAP_ADDR16(screen_out, y * 10 + i, x * 8 + j)  = c[8 * i + j] & 0x07;
212271}
213272
214//calcul de l'adresse du caractere x, y dans le block courant
215int indexblock(ef9345_t *ef9345, int x, int y)
273// draw a char in 80 char line mode
274void ef9345_device::draw_char_80(UINT8 *c, UINT16 x, UINT16 y)
216275{
217   int i, j;
218   i = x;
219   j = (y == 0) ? ((ef9345->TGS & 0x20) >> 5) : ((ef9345->ROR & 0x1f) + y - 1);
220   //partie droite d'un caractere en double largeur en mode 40 caracteres
221   if((ef9345->TGS & 0x80) == 0) if(x > 0)
222   {
223      if(ef9345->last_dial[x - 1] == 1) i--; //colonne precedente
224      if(ef9345->last_dial[x - 1] == 4) i--; //colonne precedente
225      if(ef9345->last_dial[x - 1] == 5) i--; //colonne precedente
226   }
276   // verify size limit
277   if (y * 10 >= screen->height() || x * 6 >= screen->width())
278      return;
227279
228   return 0x40 * j + i;
280   for(int i = 0; i < 10; i++)
281      for(int j = 0; j < 6; j++)
282            *BITMAP_ADDR16(screen_out, y * 10 + i, x * 6 + j)  = c[6 * i + j] & 0x07;
229283}
230284
231// Increment X
232void inc_x(ef9345_t *ef9345, int r)
285
286// set then ef9345 mode
287void ef9345_device::set_video_mode(void)
233288{
234   int i;
235   i = (ef9345->registers[r] & 0x3f) + 1;
236   if(i > 39)
289   char_mode = ((PAT & 0x80) >> 5) | ((TGS & 0xc0) >> 6);
290   UINT16 new_width = (char_mode == MODE12x80 || char_mode == MODE8x80) ? 492 : 336;
291
292   if (screen->width() != new_width)
237293   {
238      i -= 40;
239      ef9345->state |= 0x40;
294      rectangle visarea = screen->visible_area();
295      visarea.max_x = new_width - 1;
296
297      screen->configure(new_width, screen->height(), visarea, screen->frame_period().attoseconds);
240298   }
241   ef9345->registers[r] = (ef9345->registers[r] & 0xc0) | i;
299
300   //border color
301   memset(border, MAT & 0x07, ARRAY_LENGTH(border));
302
303   //set the base for the videoram charset
304   ram_base[0] = ((DOR & 0x07) << 11);
305   ram_base[1] = ram_base[0];
306   ram_base[2] = ((DOR & 0x30) << 8);
307   ram_base[3] = ram_base[2] + 0x0800;
308
309   //address of the current memory block
310   block = 0x0800 * ((((ROR & 0xf0) >> 4) | ((ROR & 0x40) >> 5) | ((ROR & 0x20) >> 3)) & 0x0c);
242311}
243312
244// Increment Y
245void inc_y(ef9345_t *ef9345, int r)
313// initialize the ef9345 accented chars
314void ef9345_device::init_accented_chars(void)
246315{
247   int i;
248   i = (ef9345->registers[r] & 0x1f) + 1;
249   if(i > 31)
250      i -= 24;
251   ef9345->registers[r] = (ef9345->registers[r] & 0xe0) | i;
316   UINT16 i, j;
317   for(j = 0; j < 0x10; j++)
318      for(i = 0; i < 0x200; i++)
319         acc_char[(j << 9) + i] = charset->u8(0x0600 + i);
320
321   for(j = 0; j < 0x200; j += 0x40)
322      for(i = 0; i < 4; i++)
323      {
324         acc_char[0x0200 + j + i +  4] |= 0x1c; //tilde
325         acc_char[0x0400 + j + i +  4] |= 0x10; //acute
326         acc_char[0x0400 + j + i +  8] |= 0x08; //acute
327         acc_char[0x0600 + j + i +  4] |= 0x04; //grave
328         acc_char[0x0600 + j + i +  8] |= 0x08; //grave
329
330         acc_char[0x0a00 + j + i +  4] |= 0x1c; //tilde
331         acc_char[0x0c00 + j + i +  4] |= 0x10; //acute
332         acc_char[0x0c00 + j + i +  8] |= 0x08; //acute
333         acc_char[0x0e00 + j + i +  4] |= 0x04; //grave
334         acc_char[0x0e00 + j + i +  8] |= 0x08; //grave
335
336         acc_char[0x1200 + j + i +  4] |= 0x08; //point
337         acc_char[0x1400 + j + i +  4] |= 0x14; //trema
338         acc_char[0x1600 + j + i + 32] |= 0x08; //cedilla
339         acc_char[0x1600 + j + i + 36] |= 0x04; //cedilla
340
341         acc_char[0x1a00 + j + i +  4] |= 0x08; //point
342         acc_char[0x1c00 + j + i +  4] |= 0x14; //trema
343         acc_char[0x1e00 + j + i + 32] |= 0x08; //cedilla
344         acc_char[0x1e00 + j + i + 36] |= 0x04; //cedilla
345      }
252346}
253347
254// Determination du cadran a afficher
255void Cadran(ef9345_t *ef9345, int x, int attrib)
348// read a char in charset or in videoram
349UINT8 ef9345_device::read_char(UINT8 index, UINT16 addr)
256350{
257   while(1)
258   {
259      if(x > 0)
260         if(ef9345->last_dial[x-1] == 1)
261         {ef9345->dial = 2; break;}         //cadran haut droit
262      if(x > 0)
263         if(ef9345->last_dial[x-1] == 5)
264            {ef9345->dial = 10; break;}      //moitie droite
265      if(ef9345->last_dial[x] == 1)
266         {ef9345->dial = 4; break;}         //cadran bas gauche
267      if(ef9345->last_dial[x] == 2)
268         {ef9345->dial = 8; break;}         //dial bas droit
269      if(ef9345->last_dial[x] == 3)
270         {ef9345->dial = 12; break;}         //moitie basse
271      if(attrib == 1)
272         {ef9345->dial = 5; break;}         //moitie gauche
273      if(attrib == 2)
274         {ef9345->dial = 3; break;}         //moitie haute
275      if(attrib == 3)
276         {ef9345->dial = 1; break;}         //dial haut gauche
277      ef9345->dial = 0; break;            //caractere complet
278   }
279   ef9345->last_dial[x] = ef9345->dial;
351   if (index < 0x04)
352      return charset->u8(0x0800*index + addr);
353   else if (index < 0x08)
354      return acc_char[0x0800*(index&3) + addr];
355   else if (index < 0x0c)
356      return videoram->read_byte(ram_base[index-8] + addr);
357   else
358      return videoram->read_byte(addr);
280359}
281360
282// zoom sur une partie d'un caractere
283void zoom(ef9345_t *ef9345, UINT8 *pix, int n)
361// calculate the dial position of the char
362UINT8 ef9345_device::get_dial(UINT8 x, UINT8 attrib)
284363{
285   //pix est le tableau des pixels (8x10=80)
286   //n definit la zone (zoomx2y2 pour cadran, zoomx2 ou zoomy2 pour moitie)
287   //cadran haut-gauche=1, haut-droit=2, bas-gauche=4, bas-droite=8
288   //moitie haute=3, basse=12, gauche=5, droite=10
289   int i, j;
290   if((n & 0x0a) == 0)
364   if (x > 0 && last_dial[x-1] == 1)       //top right
365      last_dial[x] = 2;
366   else if (x > 0 && last_dial[x-1] == 5)   //half right
367      last_dial[x] = 10;
368   else if (last_dial[x] == 1)            //bottom left
369      last_dial[x] = 4;
370   else if (last_dial[x] == 2)            //bottom right
371      last_dial[x] = 8;
372   else if (last_dial[x] == 3)            //lower half
373      last_dial[x] = 12;
374   else if (attrib == 1)               //Left half
375      last_dial[x] = 5;
376   else if (attrib == 2)               //half high
377      last_dial[x] = 3;
378   else if (attrib == 3)               //top left
379      last_dial[x] = 1;
380   else                            //none
381      last_dial[x] = 0;
382
383   return last_dial[x];
384}
385
386// zoom the char
387void ef9345_device::zoom(UINT8 *pix, UINT16 n)
388{
389   UINT8 i, j;
390   if ((n & 0x0a) == 0)
291391      for(i = 0; i < 80; i += 8) // 1, 4, 5
292392         for(j = 7; j > 0; j--)
293393            pix[i + j] = pix[i + j / 2];
294394
295   if((n & 0x05) == 0)
395   if ((n & 0x05) == 0)
296396      for(i = 0; i < 80; i += 8) // 2, 8, 10
297397         for(j =0 ; j < 7; j++)
298398            pix[i + j] = pix[i + 4 + j / 2];
299399
300   if((n & 0x0c) == 0)
400   if ((n & 0x0c) == 0)
301401      for(i = 0; i < 8; i++) // 1, 2, 3
302402         for(j = 9; j > 0; j--)
303403            pix[i + 8 * j] = pix[i + 8 * (j / 2)];
304   if((n & 0x03) == 0)
404
405   if ((n & 0x03) == 0)
305406      for(i = 0; i < 8; i++) // 4, 8, 12
306407         for(j = 0; j < 9; j++)
307408            pix[i + 8 * j] = pix[i + 40 + 8 * (j / 2)];
308409}
309410
310// Display bichrome character (40 columns)
311void Bichrome40(ef9345_t *ef9345, UINT8 *matrice, int iblock, int x, int y, int c0, int c1, int insert, int flash, int conceal, int negative, int underline)
411
412// calculate the address of the char x,y
413UINT16 ef9345_device::indexblock(UINT16 x, UINT16 y)
312414{
313   UINT8 i, j, pix[80];
415   UINT16 i = x, j;
416   j = (y == 0) ? ((TGS & 0x20) >> 5) : ((ROR & 0x1f) + y - 1);
314417
315   if(flash && ef9345->PAT & 0x40 && ef9345->blink)
316      c1 = c0;                              //flash
317   if(conceal && ef9345->PAT & 0x08)
318      c1 = c0;                                //conceal
319   if(negative)                              //negative
418   //right side of a double width character
419   if ((TGS & 0x80) == 0 && x > 0)
320420   {
421      if (last_dial[x - 1] == 1) i--;
422      if (last_dial[x - 1] == 4) i--;
423      if (last_dial[x - 1] == 5) i--;
424   }
425
426   return 0x40 * j + i;
427}
428
429// draw bichrome character (40 columns)
430void ef9345_device::bichrome40(UINT8 type, UINT16 address, UINT8 dial, UINT16 iblock, UINT16 x, UINT16 y, UINT8 c0, UINT8 c1, UINT8 insert, UINT8 flash, UINT8 hided, UINT8 negative, UINT8 underline)
431{
432   UINT16 i;
433   UINT8 pix[80];
434
435   if (flash && PAT & 0x40 && blink)
436      c1 = c0;               //flash
437   if (hided && PAT & 0x08)
438      c1 = c0;                 //hided
439   if (negative)               //negative
440   {
321441      i = c1;
322442      c1 = c0;
323443      c0 = i;
324444   }
325   //? v?rifier cf instructions en commentaires ci-dessous : insert = 0 ou 1 ??
326   if((ef9345->PAT & 0x30) == 0x30)
327      insert = 0;                              //active area mark
328   if(insert == 0)
329      c1 += 8;                                   //couleur etendue foreground
330   if((ef9345->PAT & 0x30) == 0x00)
331      insert = 1;                              //inlay
332   if(insert == 0)
333      c0 += 8;                                   //couleur etendue background
334445
446   if ((PAT & 0x30) == 0x30)
447      insert = 0;               //active area mark
448   if (insert == 0)
449      c1 += 8;                      //foreground color
450   if ((PAT & 0x30) == 0x00)
451      insert = 1;               //insert mode
452   if (insert == 0)
453      c0 += 8;                      //background color
335454
336   //affichage du curseur
337   i = (ef9345->registers[6] & 0x1f);
338   if(i < 8)
455   //draw the cursor
456   i = (registers[6] & 0x1f);
457   if (i < 8)
339458      i &= 1;
340459
341   if(iblock == 0x40 * i + (ef9345->registers[7] & 0x3f))   //position du curseur
460   if (iblock == 0x40 * i + (registers[7] & 0x3f))   //cursor position
342461   {
343      //affichage du curseur si ef9345->MAT 6 est positionne
344      //le clignotement depend de ef9345->MAT 5, la forme depend de ef9345->MAT 4
345      switch(ef9345->MAT & 0x70)
462      switch(MAT & 0x70)
346463      {
347      case 0x40:                             //00 = fixed complemented
464      case 0x40:               //00 = fixed complemented
348465         c0 = (23 - c0) & 15;
349466         c1 = (23 - c1) & 15;
350467         break;
351      case 0x50:                             //01 = fixed underlined
468      case 0x50:               //01 = fixed underlined
352469         underline = 1;
353470         break;
354      case 0x60:                             //10 = flash complemented
355         if(ef9345->blink)
471      case 0x60:               //10 = flash complemented
472         if (blink)
356473         {
357474            c0 = (23 - c0) & 15;
358475            c1 = (23 - c1) & 15;
359476         }
360477         break;
361      case 0x70:                             //11 = flash underlined
362         if(ef9345->blink)
478      case 0x70:               //11 = flash underlined
479         if (blink)
363480            underline = 1;
364481            break;
365482      }
366483   }
367484
368   //initialisation du tableau des pixels du caractere
369   j = 0;
370
371   for(i = 0; i < 10; i++)
485   // generate the pixel table
486   for(i = 0; i < 40; i+=4)
372487   {
373      pix[j++] = (*(matrice + 4 * i) & 0x01) ? c1 : c0;
374      pix[j++] = (*(matrice + 4 * i) & 0x02) ? c1 : c0;
375      pix[j++] = (*(matrice + 4 * i) & 0x04) ? c1 : c0;
376      pix[j++] = (*(matrice + 4 * i) & 0x08) ? c1 : c0;
377      pix[j++] = (*(matrice + 4 * i) & 0x10) ? c1 : c0;
378      pix[j++] = (*(matrice + 4 * i) & 0x20) ? c1 : c0;
379      pix[j++] = (*(matrice + 4 * i) & 0x40) ? c1 : c0;
380      pix[j++] = (*(matrice + 4 * i) & 0x80) ? c1 : c0;
488      UINT8 ch = read_char(type, address + i);
381489
490      for (UINT8 b=0; b<8; b++)
491         pix[i*2 + b] = (ch & (1<<b)) ? c1 : c0;
382492   }
383493
384   //caractere souligne
385   if(underline)
386      for(j = 72; j < 80; j++)
387         pix[j] = c1;
494   //draw the underline
495   if (underline)
496      memset(&pix[72], c1, 8);
388497
389   //affichage en fonction du cadran
390   //remarque : la double hauteur par le bit 7 du registre ef9345->MAT
391   //est prise en UINT8ge par la fonction d'affichage de l'ecran
392   //voir Displayscreen() dans le module de traitement de la video
393   if(ef9345->dial > 0)
394      zoom(ef9345, pix, ef9345->dial);
498   if (dial > 0)
499      zoom(pix, dial);
395500
396501   //doubles the height of the char
397   if (ef9345->MAT & 0x80)
398      zoom(ef9345, pix, (y & 0x01) ? 0x0c : 0x03);
502   if (MAT & 0x80)
503      zoom(pix, (y & 0x01) ? 0x0c : 0x03);
399504
400   draw_char_40(ef9345, pix, x + 1 , y + 1);
505   draw_char_40(pix, x + 1 , y + 1);
401506}
402507
403// Display quadrichrome character (40 columns)
404void Quadrichrome40(ef9345_t *ef9345, int c, int b, int a, int x, int y)
508// draw quadrichrome character (40 columns)
509void ef9345_device::quadrichrome40(UINT8 c, UINT8 b, UINT8 a, UINT16 x, UINT16 y)
405510{
406511   //C0-6= character code
407512   //B0= insert             not yet implemented !!!
r9546r9547
412517
413518   UINT8 i, j, n, col[8], pix[80];
414519   UINT8 lowresolution = (b & 0x02) >> 1, ramx, ramy, ramblock;
415   UINT8 *ramindex;
416   //pas de double hauteur ou largeur pour les quadrichromes
417   ef9345->last_dial[x] = 0;
418   //color table initialization (seules les couleurs 0-3 sont utilis?es)
419   j = 1; n = 0;
420   for(i = 0; i < 4; i++)
421      col[i] = 7; //blanc par defaut
520   UINT16 ramindex;
422521
423   for(i = 0; i < 8; i++)
522   //quadrichrome don't suppor double size
523   last_dial[x] = 0;
524
525   //initialize the color table
526   for(j = 1, n = 0, i = 0; i < 8; i++)
424527   {
425      if(a & j)
426         col[n++] = i;
528      col[n++] = (a & j) ? i : 7;
427529      j <<= 1;
428530   }
429531
430   //find block number i in ram
532   //find block number in ram
431533   ramblock = 0;
432   if(b & 0x20)   ramblock |= 4;      //B5
433   if(b & 0x08)   ramblock |= 2;      //B3
434   if(b & 0x10)   ramblock |= 1;      //B4
534   if (b & 0x20)   ramblock |= 4;      //B5
535   if (b & 0x08)   ramblock |= 2;      //B3
536   if (b & 0x10)   ramblock |= 1;      //B4
435537
436538   //find character address in ram
437   ramx = c & 0x03; ramy =(c & 0x7f) >> 2;
438   ramindex = ef9345->char_ptr[0x0c] + 0x800 * ramblock + 0x40 * ramy + ramx;
439   if(lowresolution) ramindex += 5 * (b & 0x04);
539   ramx = c & 0x03;
540   ramy =(c & 0x7f) >> 2;
541   ramindex = 0x0800 * ramblock + 0x40 * ramy + ramx;
542   if (lowresolution) ramindex += 5 * (b & 0x04);
440543
441544   //fill pixel table
442   j = 0; for(i = 0; i < 10; i++)
545   for(i = 0, j = 0; i < 10; i++)
443546   {
444      pix[j] = pix[j + 1] = col[(*(ramindex + 4 * (i >> lowresolution)) & 0x03) >> 0]; j += 2;
445      pix[j] = pix[j + 1] = col[(*(ramindex + 4 * (i >> lowresolution)) & 0x0c) >> 2]; j += 2;
446      pix[j] = pix[j + 1] = col[(*(ramindex + 4 * (i >> lowresolution)) & 0x30) >> 4]; j += 2;
447      pix[j] = pix[j + 1] = col[(*(ramindex + 4 * (i >> lowresolution)) & 0xc0) >> 6]; j += 2;
547      UINT8 ch = read_char(0x0c, ramindex + 4 * (i >> lowresolution));
548      pix[j] = pix[j + 1] = col[(ch & 0x03) >> 0]; j += 2;
549      pix[j] = pix[j + 1] = col[(ch & 0x0c) >> 2]; j += 2;
550      pix[j] = pix[j + 1] = col[(ch & 0x30) >> 4]; j += 2;
551      pix[j] = pix[j + 1] = col[(ch & 0xc0) >> 6]; j += 2;
448552   }
449553
450   draw_char_40(ef9345, pix, x + 1, y + 1);
554   draw_char_40(pix, x + 1, y + 1);
451555}
452556
453// Display bichrome character (80 columns)
454void Bichrome80(ef9345_t *ef9345, int c, int a, int x, int y)
557// draw bichrome character (80 columns)
558void ef9345_device::bichrome80(UINT8 c, UINT8 a, UINT16 x, UINT16 y)
455559{
456   UINT8 pix[60]; //tableau des pixels a afficher
457   int i, j, d, c0, c1;
458   c1 = (a & 1) ? (ef9345->DOR >> 4) & 7 : ef9345->DOR & 7; //foreground color = ef9345->DOR
459   c0 =  ef9345->MAT & 7;                           //background color = ef9345->MAT
560   UINT8 c0, c1, pix[60];
561   UINT16 i, j, d;
562   
563   c1 = (a & 1) ? (DOR >> 4) & 7 : DOR & 7; //foreground color = DOR
564   c0 =  MAT & 7;                           //background color = MAT
565
460566   switch(c & 0x80)
461567   {
462568   case 0: //alphanumeric G0 set
r9546r9547
465571      //A2: F = flash
466572      //A3: N = negative
467573      //C0-6: character code
468      j = 0;
469      if(a & 4) if(ef9345->PAT & 0x40) if(ef9345->blink) c1 = c0; //flash
470      if(a & 8) {i = c1; c1 = c0; c0 = i;}        //couleurs en mode inverse
471      d = ((c & 0x7f) >> 2) * 0x40 + (c & 0x03);  //deplacement dans table police
472      for(i = 0; i < 10; i++)
574
575      if ((a & 4) && (PAT & 0x40) && (blink))
576         c1 = c0;    //flash
577      if (a & 8)      //negative
473578      {
474         pix[j++] = (*(ef9345->charset + d + 4 * i) & 0x01) ? c1 : c0; pix[j++] = (*(ef9345->charset + d + 4 * i) & 0x02) ? c1 : c0;
475         pix[j++] = (*(ef9345->charset + d + 4 * i) & 0x04) ? c1 : c0; pix[j++] = (*(ef9345->charset + d + 4 * i) & 0x08) ? c1 : c0;
476         pix[j++] = (*(ef9345->charset + d + 4 * i) & 0x10) ? c1 : c0; pix[j++] = (*(ef9345->charset + d + 4 * i) & 0x20) ? c1 : c0;
579         i = c1;
580         c1 = c0;
581         c0 = i;
477582      }
478      if(a & 2) for(j = 54; j < 60; j++) pix[j] = c1; //underline
583
584      d = ((c & 0x7f) >> 2) * 0x40 + (c & 0x03);  //char position
585
586      for(i=0, j=0; i < 10; i++)
587      {
588         UINT8 ch = read_char(0, d + 4 * i);
589         for (UINT8 b=0; b<6; b++)
590            pix[j++] = (ch & (1<<b)) ? c1 : c0;
591      }
592
593      //draw the underline
594      if (a & 2)
595         memset(&pix[54], c1, 6);
596
479597      break;
480598   default: //dedicated mosaic set
481599      //A0: D = color set
r9546r9547
491609      pix[39] = (a & 0x02) ? c1 : c0;
492610      pix[48] = (a & 0x04) ? c1 : c0;
493611      pix[51] = (a & 0x08) ? c1 : c0;
612
494613      for(i = 0; i < 60; i += 12)
495614      {
496615         pix[i + 6] = pix[i];
497616         pix[i + 9] = pix[i + 3];
498617      }
618
499619      for(i = 0; i < 60; i += 3)
500620         pix[i + 2] = pix[i + 1] = pix[i];
621
501622      break;
502623   }
503   draw_char_80(ef9345, pix, x, y);
624
625   draw_char_80(pix, x, y);
504626}
505627
506
507// Affichage d'un caractere 16 bits 40 colonnes
508void makechar_16x40(ef9345_t *ef9345, int x, int y)
628// generate 16 bits 40 columns char
629void ef9345_device::makechar_16x40(UINT16 x, UINT16 y)
509630{
510   int i, a, b, type, c0, c1, f, m, n, u, iblock;
511   UINT8* matrice;
631   UINT8 a, b, c0, c1, i, f, m, n, u, type, dial;
632   UINT16 address, iblock;
512633
513   //recherche des octets b, a (precedent si double largeur)
514   iblock = (ef9345->MAT & 0x80 && y > 1) ? indexblock(ef9345, x, y / 2) : indexblock(ef9345, x, y);
515   a = ef9345->block[iblock];
516   b = ef9345->block[iblock + 0x800];
634   iblock = (MAT & 0x80 && y > 1) ? indexblock(x, y / 2) : indexblock(x, y);
635   a = videoram->read_byte(block + iblock);
636   b = videoram->read_byte(block + iblock + 0x0800);
517637
518   //determination attribut HL et numero du cadran a afficher
519   Cadran(ef9345, x, (a & 0x80) ? 0 : (((a & 0x20) >> 5) | ((a & 0x10) >> 3)));
638   dial = get_dial(x, (a & 0x80) ? 0 : (((a & 0x20) >> 5) | ((a & 0x10) >> 3)));
520639
521   //adresse de la matrice de definition du caractere
640   //type and address of the char
522641   type = ((b & 0x80) >> 4) | ((a & 0x80) >> 6);
523   matrice = ef9345->char_ptr[type] + ((b & 0x7f) >> 2) * 0x40 + (b & 0x03);
524   if((b & 0xe0) == 0x80)
525      matrice = ef9345->char_ptr[0x03]; //negative space
642   address = ((b & 0x7f) >> 2) * 0x40 + (b & 0x03);
526643
527   //attributs latches
528   if(x == 0) ef9345->latchm = ef9345->latchi = ef9345->latchu = ef9345->latchc0 = 0;
529   if(type == 4) {ef9345->latchm = b & 1; ef9345->latchi = (b & 2) >> 1; ef9345->latchu = (b & 4) >> 2;}
530   if(a & 0x80) ef9345->latchc0 = (a & 0x70) >> 4;
644    //negative space
645   if ((b & 0xe0) == 0x80)
646   {
647      address = 0;
648      type = 3;
649   }
531650
532   //attributs du caractere
533   c0 = ef9345->latchc0;               //background
651   //reset attributes latch
652   if (x == 0)
653      latchm = latchi = latchu = latchc0 = 0;
654
655   if (type == 4)
656   {
657      latchm = b & 1;
658      latchi = (b & 2) >> 1;
659      latchu = (b & 4) >> 2;
660   }
661
662   if (a & 0x80)
663      latchc0 = (a & 0x70) >> 4;
664
665   //char attributes
666   c0 = latchc0;                     //background
534667   c1 = a & 0x07;                     //foreground
535   i = ef9345->latchi;                  //insert mode
668   i = latchi;                        //insert mode
536669   f  = (a & 0x08) >> 3;               //flash
537   m = ef9345->latchm;                  //conceal
670   m = latchm;                        //hided
538671   n  = (a & 0x80) ? 0: ((a & 0x40) >> 6);   //negative
539   u = ef9345->latchu;                  //underline
672   u = latchu;                        //underline
540673
541   //affichage
542   Bichrome40(ef9345, matrice, iblock, x, y, c0, c1, i, f, m, n, u);
674   bichrome40(type, address, dial, iblock, x, y, c0, c1, i, f, m, n, u);
543675}
544676
545// Affichage d'un caractere 24 bits 40 colonnes
546void makechar_24x40(ef9345_t *ef9345, int x, int y)
677// generate 24 bits 40 columns char
678void ef9345_device::makechar_24x40(UINT16 x, UINT16 y)
547679{
548   int i, a, b, c, c0, c1, f, m, n, u, iblock;
549   UINT8* matrice;
680   UINT8 a, b, c, c0, c1, i, f, m, n, u, type, dial;
681   UINT16 address, iblock;
550682
551   //recherche des octets c, b, a
552   iblock = (ef9345->MAT & 0x80 && y > 1) ? indexblock(ef9345,x, y / 2) : indexblock(ef9345, x, y);
553   c = ef9345->block[iblock]; b = ef9345->block[iblock + 0x800]; a = ef9345->block[iblock + 0x1000];
554   if((b & 0xc0) == 0xc0) {Quadrichrome40(ef9345, c, b, a, x, y); return;}
683   iblock = (MAT & 0x80 && y > 1) ? indexblock(x, y / 2) : indexblock(x, y);
684   c = videoram->read_byte(block + iblock);
685   b = videoram->read_byte(block + iblock + 0x0800);
686   a = videoram->read_byte(block + iblock + 0x1000);
555687
556   //determination attribut HL et numero du cadran a afficher
557   Cadran(ef9345, x, (b & 0x02) + ((b & 0x08) >> 3));
688   if ((b & 0xc0) == 0xc0)
689   {
690      quadrichrome40(c, b, a, x, y);
691      return;
692   }
558693
559   //adresse de la matrice de definition du caractere
560   matrice = ef9345->char_ptr[(b & 0xf0) >> 4] + ((c & 0x7f) >> 2) * 0x40 + (c & 0x03);
694   dial = get_dial(x, (b & 0x02) + ((b & 0x08) >> 3));
561695
562   //attributs du caractere
563   c0 = a & 0x07;        //background
564   c1 = (a & 0x70) >> 4; //foreground
565   i = b & 0x01;         //insert
566   f = (a & 0x08) >> 3;  //flash
567   m = (b & 0x04) >> 2;  //conceal
568   n = (a & 0x80) >> 7;  //negative
569   u = (((b & 0x60) == 0) || ((b & 0xc0) == 0x40)) ? ((b & 0x10) >> 4) : 0;
696   //type and address of the char
697   address = ((c & 0x7f) >> 2) * 0x40 + (c & 0x03);
698   type = (b & 0xf0) >> 4;
570699
571   //affichage
572   Bichrome40(ef9345, matrice, iblock, x, y, c0, c1, i, f, m, n, u);
700   //char attributes
701   c0 = a & 0x07;               //background
702   c1 = (a & 0x70) >> 4;         //foreground
703   i = b & 0x01;               //insert
704   f = (a & 0x08) >> 3;         //flash
705   m = (b & 0x04) >> 2;         //hided
706   n = ((a & 0x80) >> 7);         //negative
707   u = (((b & 0x60) == 0) || ((b & 0xc0) == 0x40)) ? ((b & 0x10) >> 4) : 0; //underline
708
709   bichrome40(type, address, dial, iblock, x, y, c0, c1, i, f, m, n, u);
573710}
574711
712// generate 12 bits 80 columns char
713void ef9345_device::makechar_12x80(UINT16 x, UINT16 y)
714{
715   UINT16 iblock = indexblock(x, y);
716   bichrome80(videoram->read_byte(block + iblock), (videoram->read_byte(block + iblock + 0x1000) >> 4) & 0x0f, 2 * x + 1, y + 1);
717   bichrome80(videoram->read_byte(block + iblock + 0x0800), videoram->read_byte(block + iblock + 0x1000) & 0x0f, 2 * x + 2, y + 1);
718}
575719
576// Affichage de deux caracteres 12 bits 80 colonnes
577void makechar_12x80(ef9345_t *ef9345, int x, int y)
720void ef9345_device::draw_border(UINT16 line)
578721{
579   int iblock;
580   iblock = indexblock(ef9345, x, y);
581   Bichrome80(ef9345, ef9345->block[iblock], (ef9345->block[iblock + 0x1000] >> 4) & 0x0f, 2 * x + 1, y + 1);
582   Bichrome80(ef9345, ef9345->block[iblock + 0x800], ef9345->block[iblock + 0x1000] & 0x0f, 2 * x + 2, y + 1);
722   if (char_mode == MODE12x80 || char_mode == MODE8x80)
723      for(int i = 0; i < 82; i++)
724         draw_char_80(border, i, line);
725   else
726      for(int i = 0; i < 42; i++)
727         draw_char_40(border, i, line);
583728}
584729
585void makechar(ef9345_t *ef9345, int x, int y)
730void ef9345_device::makechar(UINT16 x, UINT16 y)
586731{
587   switch (ef9345->char_mode)
732   switch (char_mode)
588733   {
589734      case MODE24x40:
590         makechar_24x40(ef9345, x, y);
735         makechar_24x40(x, y);
591736         break;
592737      case MODEVAR40:
593         //TODO
594         break;
595738      case MODE8x80:
596         //TODO
739         logerror("Unemulated EF9345 mode: %02x\n", char_mode);
597740         break;
598741      case MODE12x80:
599         makechar_12x80(ef9345, x, y);
742         makechar_12x80(x, y);
600743         break;
601744      case MODE16x40:
602         makechar_16x40(ef9345, x, y);
745         makechar_16x40(x, y);
603746         break;
604747      default:
748         logerror("Unknown EF9345 mode: %02x\n", char_mode);
605749         break;
606750   }
607751}
608752
609// Lecture-ecriture en memoire EF9345
610void OCTwrite(ef9345_t *ef9345, int r, int i)
753// Execute EF9345 command
754void ef9345_device::ef9345_exec(UINT8 cmd)
611755{
612   set_busy_flag(ef9345, 4);
613   ef9345->ram[indexram(ef9345, r)] = ef9345->registers[1];
614   if(i == 0) return;
615   inc_x(ef9345, r);
616   if((ef9345->registers[r] & 0x3f) == 0 && r == 7)
617         inc_y(ef9345, 6);
618}
619void OCTread(ef9345_t *ef9345, int r, int i)
620{
621   set_busy_flag(ef9345, 4.5);
622   ef9345->registers[1] = ef9345->ram[indexram(ef9345, r)];
623   if(i == 0) return;
624   inc_x(ef9345, r);
756   state = 0;
757   if ((registers[5] & 0x3f) == 39) state |= 0x10; //S4(LXa) set
758   if ((registers[7] & 0x3f) == 39) state |= 0x20; //S5(LXm) set
625759
626   if((ef9345->registers[r] & 0x3f) == 0 && r == 7)
627      inc_y(ef9345, 6); //increment
628}
760   UINT16 a = indexram(7);
629761
630void KRGwrite(ef9345_t *ef9345, int i) //mode 40 caracteres 16 bits
631{
632   int a = indexram(ef9345, 7);
633   set_busy_flag(ef9345, 5.5);
634   ef9345->ram[a] = ef9345->registers[1];
635   ef9345->ram[a + 0x0800] = ef9345->registers[2];
636   if(i) inc_x(ef9345, 7);
637}
638void KRGread(ef9345_t *ef9345, int i)
639{
640   int a = indexram(ef9345, 7);
762   switch(cmd)
763   {
764      case 0x00:   //KRF: R1,R2,R3->ram
765      case 0x01:   //KRF: R1,R2,R3->ram + increment
766         set_busy_flag(4);
767         videoram->write_byte(a, registers[1]);
768         videoram->write_byte(a + 0x0800, registers[2]);
769         videoram->write_byte(a + 0x1000, registers[3]);
770         if (cmd&1) inc_x(7);
771         break;
772      case 0x02:   //KRG: R1,R2->ram
773      case 0x03:   //KRG: R1,R2->ram + increment
774         set_busy_flag(5.5);
775         videoram->write_byte(a, registers[1]);
776         videoram->write_byte(a + 0x0800, registers[2]);
777         if (cmd&1) inc_x(7);
778         break;
779      case 0x08:   //KRF: ram->R1,R2,R3
780      case 0x09:   //KRF: ram->R1,R2,R3 + increment
781         set_busy_flag(7.5);
782         registers[1] = videoram->read_byte(a);
783         registers[2] = videoram->read_byte(a + 0x0800);
784         registers[3] = videoram->read_byte(a + 0x1000);
785         if (cmd&1) inc_x(7);
786         break;
787      case 0x0a:   //KRG: ram->R1,R2
788      case 0x0b:   //KRG: ram->R1,R2 + increment
789         set_busy_flag(7.5);
790         registers[1] = videoram->read_byte(a);
791         registers[2] = videoram->read_byte(a + 0x0800);
792         if (cmd&1) inc_x(7);
793         break;
794      case 0x30:   //OCT: R1->RAM, main pointer
795      case 0x31:   //OCT: R1->RAM, main pointer + inc
796         set_busy_flag(4);
797         videoram->write_byte(indexram(7), registers[1]);
641798
642   set_busy_flag(ef9345, 7.5);
643   ef9345->registers[1] = ef9345->ram[a];
644   ef9345->registers[2] = ef9345->ram[a + 0x0800];
645   if(i) inc_x(ef9345, 7);
646}
799         if (cmd&1)
800         {
801            inc_x(7);
802            if ((registers[7] & 0x3f) == 0)
803               inc_y(6);
804         }
805         break;
806      case 0x34:   //OCT: R1->RAM, aux pointer
807      case 0x35:   //OCT: R1->RAM, aux pointer + inc
808         set_busy_flag(4);
809         videoram->write_byte(indexram(5), registers[1]);
647810
648void KRFwrite(ef9345_t *ef9345, int i) //mode 40 caracteres 24 bits
649{
650   int a = indexram(ef9345, 7);
811         if (cmd&1)
812            inc_x(5);
813         break;
814      case 0x38:   //OCT: RAM->R1, main pointer
815      case 0x39:   //OCT: RAM->R1, main pointer + inc
816         set_busy_flag(4.5);
817         registers[1] = videoram->read_byte(indexram(7));
651818
652   set_busy_flag(ef9345, 4);
653   ef9345->ram[a] = ef9345->registers[1];
654   ef9345->ram[a + 0x0800] = ef9345->registers[2];
655   ef9345->ram[a + 0x1000] = ef9345->registers[3];
656   if(i) inc_x(ef9345, 7);
657}
819         if (cmd&1)
820         {
821            inc_x(7);
658822
659void KRFread(ef9345_t *ef9345, int i)
660{
661   int a = indexram(ef9345, 7);
823            if ((registers[7] & 0x3f) == 0)
824               inc_y(6);
825         }
826         break;
827      case 0x3c:   //OCT: RAM->R1, aux pointer
828      case 0x3d:   //OCT: RAM->R1, aux pointer + inc
829         set_busy_flag(4.5);
830         registers[1] = videoram->read_byte(indexram(5));
662831
663   set_busy_flag(ef9345, 7.5);
664   ef9345->registers[1] = ef9345->ram[a];
665   ef9345->registers[2] = ef9345->ram[a + 0x0800];
666   ef9345->registers[3] = ef9345->ram[a + 0x1000];
667   if(i) inc_x(ef9345, 7);
668}
832         if (cmd&1)
833            inc_x(5);
834         break;
835      case 0x50:   //KRL: 80 UINT8 - 12 bits write
836      case 0x51:   //KRL: 80 UINT8 - 12 bits write + inc
837         set_busy_flag(12.5);
838         videoram->write_byte(a, registers[1]);
839         switch((a / 0x0800) & 1)
840         {
841            case 0:
842            {
843               UINT8 tmp_data = videoram->read_byte(a + 0x1000);
844               videoram->write_byte(a + 0x1000, (tmp_data & 0x0f) | (registers[3] & 0xf0));
845               break;
846            }
847            case 1:
848            {
849               UINT8 tmp_data = videoram->read_byte(a + 0x0800);
850               videoram->write_byte(a + 0x0800, (tmp_data & 0xf0) | (registers[3] & 0x0f));
851               break;
852            }
853         }
854         if (cmd&1)
855         {
856            if ((registers[7] & 0x80) == 0x00) {registers[7] |= 0x80; return;}
857            registers[7] &= 0x80;
858            inc_x(7);
859         }
860         break;
861      case 0x58:   //KRL: 80 UINT8 - 12 bits read
862      case 0x59:   //KRL: 80 UINT8 - 12 bits read + inc
863         set_busy_flag(11.5);
864         registers[1] = videoram->read_byte(a);
865         switch((a / 0x0800) & 1)
866         {
867            case 0:
868               registers[3] = videoram->read_byte(a + 0x1000);
869               break;
870            case 1:
871               registers[3] = videoram->read_byte(a + 0x0800);
872               break;
873         }
874         if (cmd&1)
875         {
876            if ((registers[7] & 0x80) == 0x00)
877            {
878               registers[7] |= 0x80;
879               break;;
880            }
881            registers[7] &= 0x80;
882            inc_x(7);
883         }
884         break;
885      case 0x80:   //IND: R1->ROM (impossible ?)
886         break;
887      case 0x81:   //IND: R1->TGS
888      case 0x82:   //IND: R1->MAT
889      case 0x83:   //IND: R1->PAT
890      case 0x84:   //IND: R1->DOR
891      case 0x87:   //IND: R1->ROR
892         set_busy_flag(2);
893         switch(cmd&7)
894         {
895            case 1:    TGS = registers[1]; break;
896            case 2:    MAT = registers[1]; break;
897            case 3:    PAT = registers[1]; break;
898            case 4:    DOR = registers[1]; break;
899            case 7:    ROR = registers[1]; break;
900         }
901         set_video_mode();
902         state &= 0x8f;  //reset S4(LXa), S5(LXm), S6(Al)
903         break;
904      case 0x88:   //IND: ROM->R1
905      case 0x89:   //IND: TGS->R1
906      case 0x8a:   //IND: MAT->R1
907      case 0x8b:   //IND: PAT->R1
908      case 0x8c:   //IND: DOR->R1
909      case 0x8f:   //IND: ROR->R1
910         set_busy_flag(3.5);
911         switch(cmd&7)
912         {
913            case 0:    registers[1] = charset->u8(indexrom(7) & 0x1fff);
914            case 1:    registers[1] = TGS; break;
915            case 2:    registers[1] = MAT; break;
916            case 3:    registers[1] = PAT; break;
917            case 4:    registers[1] = DOR; break;
918            case 7:    registers[1] = ROR; break;
919         }
920         state &= 0x8f;  //reset S4(LXa), S5(LXm), S6(Al)
921         break;
922      case 0x90:   //NOP: no operation
923      case 0x91:   //NOP: no operation
924      case 0x95:   //VRM: vertical sync mask reset
925      case 0x99:   //VSM: vertical sync mask set
926         break;
927      case 0xb0:   //INY: increment Y
928         set_busy_flag(2);
929         inc_y(6);
930         state &= 0x8f;  //reset S4(LXa), S5(LXm), S6(Al)
931         break;
932      case 0xd5:   //MVB: move buffer MP->AP stop
933      case 0xd6:   //MVB: move buffer MP->AP nostop
934      case 0xd9:   //MVB: move buffer AP->MP stop
935      case 0xda:   //MVB: move buffer AP->MP nostop
936      case 0xe5:   //MVD: move double buffer MP->AP stop
937      case 0xe6:   //MVD: move double buffer MP->AP nostop
938      case 0xe9:   //MVD: move double buffer AP->MP stop
939      case 0xea:   //MVD: move double buffer AP->MP nostop
940      case 0xf5:   //MVT: move triple buffer MP->AP stop
941      case 0xf6:   //MVT: move triple buffer MP->AP nostop
942      case 0xf9:   //MVT: move triple buffer AP->MP stop
943      case 0xfa:   //MVT: move triple buffer AP->MP nostop
944      {
945         UINT16 i, a1, a2;
946         UINT8 n = (cmd>>4) - 0x0c;
947         UINT8 r1 = (cmd&0x04) ? 7 : 5;
948         UINT8 r2 = (cmd&0x04) ? 5 : 7;
949         int busy = 2;
669950
670void KRLwrite(ef9345_t *ef9345, int i) //mode 80 caracteres 12 bits
671{
672   int a = indexram(ef9345, 7);
951         for(i = 0; i < 1280; i++)
952         {
953            a1 = indexram(r1); a2 = indexram(r2);
954            videoram->write_byte(a2, videoram->read_byte(a1));
673955
674   set_busy_flag(ef9345, 12.5);
675   ef9345->ram[a] = ef9345->registers[1];
676   switch((a / 0x800) & 1)
677   {
678   case 0: ef9345->ram[a + 0x1000] &= 0x0f;
679      ef9345->ram[a + 0x1000] |= (ef9345->registers[3] & 0xf0); break;
680   case 1: ef9345->ram[a + 0x0800] &= 0xf0;
681      ef9345->ram[a + 0x0800] |= (ef9345->registers[3] & 0x0f); break;
682   }
683   if(i)
684   {
685      if((ef9345->registers[7] & 0x80) == 0x00) {ef9345->registers[7] |= 0x80; return;}
686      ef9345->registers[7] &= 0x80;
687      inc_x(ef9345, 7);
688   }
689}
956            if (n > 1) videoram->write_byte(a2 + 0x0800, videoram->read_byte(a1 + 0x0800));
957            if (n > 2) videoram->write_byte(a2 + 0x1000, videoram->read_byte(a1 + 0x1000));
690958
691void KRLread(ef9345_t *ef9345, int i)
692{
693   int a = indexram(ef9345, 7);
959            inc_x(r1);
960            inc_x(r2);
961            if ((registers[5] & 0x3f) == 0 && (cmd&1))
962               break;
694963
695   set_busy_flag(ef9345, 11.5);
696   ef9345->registers[1] = ef9345->ram[a];
697   switch((a / 0x800) & 1)
698   {
699   case 0: ef9345->registers[3] = ef9345->ram[a + 0x1000]; break;
700   case 1: ef9345->registers[3] = ef9345->ram[a + 0x0800]; break;
701   }
702   if(i)
703   {
704      if((ef9345->registers[7] & 0x80) == 0x00) {ef9345->registers[7] |= 0x80; return;}
705      ef9345->registers[7] &= 0x80;
706      inc_x(ef9345, 7);
707   }
708}
964            if ((registers[7] & 0x3f) == 0)
965            {
966               if (cmd&1)
967                  break;
968               else
969               inc_y(6);
970            }
709971
710// Move buffer
711void MVB(ef9345_t *ef9345, int n, int r1, int r2, int s)
712{
713   //s=1 pour mode normal, s=0 pour remplir tout le buffer
714   int i, a1, a2;
715
716   set_busy_flag(ef9345, 2);
717   for(i = 0; i < 1280; i++)
718   {
719      a1 = indexram(ef9345, r1); a2 = indexram(ef9345, r2);
720      ef9345->ram[a2] = ef9345->ram[a1]; //ef9345_cycle += 16 * n;
721      if(n > 1) ef9345->ram[a2 + 0x0800] = ef9345->ram[a1 + 0x0800];
722      if(n > 2) ef9345->ram[a2 + 0x1000] = ef9345->ram[a1 + 0x1000];
723      inc_x(ef9345, r1); inc_x(ef9345, r2);
724      if((ef9345->registers[5] & 0x3f) == 0) {if(s) break;}
725      if((ef9345->registers[7] & 0x3f) == 0) {if(s) break; else inc_y(ef9345, 6);}
972            busy += 4 * n;
973         }
974         state &= 0x8f;  //reset S4(LXa), S5(LXm), S6(Al)
975         set_busy_flag(busy);
976      }
977      break;
978      case 0x05:   //CLF: Clear page 24 bits
979      case 0x07:   //CLG: Clear page 16 bits
980      case 0x40:   //KRC: R1 -> ram
981      case 0x41:   //KRC: R1 -> ram + inc
982      case 0x48:   //KRC: 80 characters - 8 bits
983      case 0x49:   //KRC: 80 characters - 8 bits
984      default:
985         logerror("Unemulated EF9345 cmd: %02x\n", cmd);
726986   }
727   ef9345->state &= 0x8f;  //reset S4(LXa), S5(LXm), S6(Al)
728987}
729988
730// Increment registre R6
731void INY(ef9345_t *ef9345)
732{
733   set_busy_flag(ef9345, 2);
734   inc_y(ef9345, 6);
735   ef9345->state &= 0x8f;  //reset S4(LXa), S5(LXm), S6(Al)
736}
737989
738// Lecture/Ecriture des registres indirects
739void INDwrite(ef9345_t *ef9345, int x)
740{
741   set_busy_flag(ef9345, 2);
742   switch(x)
743   {
744   case 1: ef9345->TGS = ef9345->registers[1]; break;
745   case 2: ef9345->MAT = ef9345->registers[1]; break;
746   case 3: ef9345->PAT = ef9345->registers[1]; break;
747   case 4: ef9345->DOR = ef9345->registers[1]; break;
748   case 7: ef9345->ROR = ef9345->registers[1]; break;
749   }
750   set_ef9345_mode(ef9345);
751   ef9345->state &= 0x8f;  //reset S4(LXa), S5(LXm), S6(Al)
752}
753
754void INDread(ef9345_t *ef9345, int x)
755{
756   set_busy_flag(ef9345, 3.5);
757   switch(x)
758   {
759   case 0: ef9345->registers[1] = ef9345->charset[indexrom(ef9345, 7) & 0x1fff]; break;
760   case 1: ef9345->registers[1] = ef9345->TGS; break;
761   case 2: ef9345->registers[1] = ef9345->MAT; break;
762   case 3: ef9345->registers[1] = ef9345->PAT; break;
763   case 4: ef9345->registers[1] = ef9345->DOR; break;
764   case 7: ef9345->registers[1] = ef9345->ROR; break;
765   case 8: ef9345->registers[1] = ef9345->ROR; break;
766   }
767   ef9345->state &= 0x8f;  //reset S4(LXa), S5(LXm), S6(Al)
768}
769
770// Execute EF9345 command
771void ef9345_exec(ef9345_t *ef9345, UINT8 cmd)
772{
773   ef9345->state = 0;
774   if((ef9345->registers[5] & 0x3f) == 39) ef9345->state |= 0x10; //S4(LXa) set
775   if((ef9345->registers[7] & 0x3f) == 39) ef9345->state |= 0x20; //S5(LXm) set
776
777   switch(cmd)
778   {
779      case 0x00:      KRFwrite(ef9345, 0);   break;      //KRF: R1,R2,R3->ram
780      case 0x01:      KRFwrite(ef9345, 1);   break;      //KRF: R1,R2,R3->ram + increment
781      case 0x02:      KRGwrite(ef9345, 0);   break;      //KRG: R1,R2->ram
782      case 0x03:      KRGwrite(ef9345, 1);   break;      //KRG: R1,R2->ram + increment
783      case 0x05:                        break;      //CLF: Clear page 24 bits
784      case 0x07:                        break;      //CLG: Clear page 16 bits
785      case 0x08:      KRFread(ef9345, 0);      break;      //KRF: ram->R1,R2,R3
786      case 0x09:      KRFread(ef9345, 1);      break;      //KRF: ram->R1,R2,R3 + increment
787      case 0x0a:      KRGread(ef9345, 0);      break;      //KRG: ram->R1,R2
788      case 0x0b:      KRGread(ef9345, 1);      break;      //KRG: ram->R1,R2 + increment
789      case 0x30:      OCTwrite(ef9345, 7, 0);   break;      //OCT: R1->RAM, main pointer
790      case 0x31:      OCTwrite(ef9345, 7, 1);   break;      //OCT: R1->RAM, main pointer + inc
791      case 0x34:      OCTwrite(ef9345, 5, 0);   break;      //OCT: R1->RAM, aux pointer
792      case 0x35:      OCTwrite(ef9345, 5, 1);   break;      //OCT: R1->RAM, aux pointer + inc
793      case 0x38:      OCTread(ef9345, 7, 0);   break;      //OCT: RAM->R1, main pointer
794      case 0x39:      OCTread(ef9345, 7, 1);   break;      //OCT: RAM->R1, main pointer + inc
795      case 0x3c:      OCTread(ef9345, 5, 0);   break;      //OCT: RAM->R1, aux pointer
796      case 0x3d:      OCTread(ef9345, 5, 1);   break;      //OCT: RAM->R1, aux pointer + inc
797      case 0x40:                        break;      //KRC: R1 -> ram
798      case 0x41:                        break;      //KRC: R1 -> ram + inc
799      case 0x48:                        break;      //KRC: 80 characters - 8 bits
800      case 0x49:                        break;      //KRC: 80 characters - 8 bits
801      case 0x50:      KRLwrite(ef9345, 0);   break;      //KRL: 80 UINT8 - 12 bits write
802      case 0x51:      KRLwrite(ef9345, 1);   break;      //KRL: 80 UINT8 - 12 bits write + inc
803      case 0x58:      KRLread(ef9345, 0);      break;      //KRL: 80 UINT8 - 12 bits read
804      case 0x59:      KRLread(ef9345, 1);      break;      //KRL: 80 UINT8 - 12 bits read + inc
805      case 0x80:                        break;      //IND: R1->ROM (impossible ?)
806      case 0x81:      INDwrite(ef9345, 1);   break;      //IND: R1->ef9345->TGS
807      case 0x82:      INDwrite(ef9345, 2);   break;      //IND: R1->ef9345->MAT
808      case 0x83:      INDwrite(ef9345, 3);   break;      //IND: R1->ef9345->PAT
809      case 0x84:      INDwrite(ef9345, 4);   break;      //IND: R1->ef9345->DOR
810      case 0x87:      INDwrite(ef9345, 7);   break;      //IND: R1->ef9345->ROR
811      case 0x88:      INDread(ef9345, 0);      break;      //IND: ROM->R1
812      case 0x89:      INDread(ef9345, 1);      break;      //IND: ef9345->TGS->R1
813      case 0x8a:      INDread(ef9345, 2);      break;      //IND: ef9345->MAT->R1
814      case 0x8b:      INDread(ef9345, 3);      break;      //IND: ef9345->PAT->R1
815      case 0x8c:      INDread(ef9345, 4);      break;      //IND: ef9345->DOR->R1
816      case 0x8f:      INDread(ef9345, 7);      break;      //IND: ef9345->ROR->R1
817      case 0x90:                        break;      //NOP: no operation
818      case 0x91:                        break;      //NOP: no operation
819      case 0x95:                        break;      //VRM: vertical sync mask reset
820      case 0x99:                        break;      //VSM: vertical sync mask set
821      case 0xb0:      INY(ef9345);         break;      //INY: increment Y
822      case 0xd5:      MVB(ef9345, 1, 7, 5, 1);   break;   //MVB: move buffer MP->AP stop
823      case 0xd6:      MVB(ef9345, 1, 7, 5, 0);   break;   //MVB: move buffer MP->AP nostop
824      case 0xd9:      MVB(ef9345, 1, 5, 7, 1);   break;   //MVB: move buffer AP->MP stop
825      case 0xda:      MVB(ef9345, 1, 5, 7, 0);   break;   //MVB: move buffer AP->MP nostop
826      case 0xe5:      MVB(ef9345, 2, 7, 5, 1);   break;   //MVD: move double buffer MP->AP stop
827      case 0xe6:      MVB(ef9345, 2, 7, 5, 0);   break;   //MVD: move double buffer MP->AP nostop
828      case 0xe9:      MVB(ef9345, 2, 5, 7, 1);   break;   //MVD: move double buffer AP->MP stop
829      case 0xea:      MVB(ef9345, 2, 5, 7, 0);   break;   //MVD: move double buffer AP->MP nostop
830      case 0xf5:      MVB(ef9345, 3, 7, 5, 1);   break;   //MVT: move triple buffer MP->AP stop
831      case 0xf6:      MVB(ef9345, 3, 7, 5, 0);   break;   //MVT: move triple buffer MP->AP nostop
832      case 0xf9:      MVB(ef9345, 3, 5, 7, 1);   break;   //MVT: move triple buffer AP->MP stop
833      case 0xfa:      MVB(ef9345, 3, 5, 7, 0);   break;   //MVT: move triple buffer AP->MP nostop
834      default:      logerror("Unemulated EF9345 cmd: %02x\n", cmd);
835   }
836}
837
838
839990/**************************************************************
840991            EF9345 interface
841992**************************************************************/
842993
843void video_update_ef9345(running_device *device, bitmap_t *bitmap, const rectangle *cliprect)
994void ef9345_device::video_update(bitmap_t *bitmap, const rectangle *cliprect)
844995{
845   ef9345_t *ef9345 = get_safe_token(device);
846   copybitmap(bitmap, ef9345->screen_out, 0, 0, 0, 0, cliprect);
996   copybitmap(bitmap, screen_out, 0, 0, 0, 0, cliprect);
847997}
848998
849
850READ8_DEVICE_HANDLER ( ef9345_r )
999void ef9345_device::update_scanline(UINT16 scanline)
8511000{
852   ef9345_t *ef9345 = get_safe_token(device);
1001   UINT16 i;
8531002
854   if(offset & 7)
855      return ef9345->registers[offset & 7];
856
857   if(ef9345->bf)
858      ef9345->state |= 0x80;
859   else
860      ef9345->state &= 0x7f;
861
862   return ef9345->state;
863}
864
865
866WRITE8_DEVICE_HANDLER ( ef9345_w )
867{
868   ef9345_t *ef9345 = get_safe_token(device);
869
870   ef9345->registers[offset & 7] = data;
871
872   if(offset & 8)
873      ef9345_exec(ef9345, ef9345->registers[0] & 0xff);
874}
875
876
877static TIMER_CALLBACK( ef9345_done )
878{
879   running_device *device = (running_device *)ptr;
880   ef9345_t *ef9345 = get_safe_token(device);
881
882   ef9345->bf = 0;
883}
884
885void draw_border(ef9345_t *ef9345, UINT8 line)
886{
887   UINT8 i;
888
889   if (ef9345->char_mode == MODE12x80 || ef9345->char_mode == MODE8x80)
890      for(i = 0; i < 82; i++)
891         draw_char_80(ef9345, ef9345->border, i, line);
892   else
893      for(i = 0; i < 42; i++)
894         draw_char_40(ef9345, ef9345->border, i, line);
895}
896
897void ef9345_scanline(running_device *device, UINT16 scanline)
898{
899   ef9345_t *ef9345 = get_safe_token(device);
900   UINT8 i;
901
9021003   if (scanline == 250)
903      ef9345->state &= 0xfb;
1004      state &= 0xfb;
9041005
905   set_busy_flag(ef9345, 104);
1006   set_busy_flag(104);
9061007
907   if (ef9345->char_mode == MODE12x80 || ef9345->char_mode == MODE8x80)
1008   if (char_mode == MODE12x80 || char_mode == MODE8x80)
9081009   {
909      draw_char_80(ef9345, ef9345->border, 0, (scanline / 10) + 1);
910      draw_char_80(ef9345, ef9345->border, 81, (scanline / 10) + 1);
1010      draw_char_80(border, 0, (scanline / 10) + 1);
1011      draw_char_80(border, 81, (scanline / 10) + 1);
9111012   }
9121013   else
9131014   {
914      draw_char_40(ef9345, ef9345->border, 0, (scanline / 10) + 1);
915      draw_char_40(ef9345, ef9345->border, 41, (scanline / 10) + 1);
1015      draw_char_40(border, 0, (scanline / 10) + 1);
1016      draw_char_40(border, 41, (scanline / 10) + 1);
9161017   }
9171018
918   if(scanline == 0)
1019   if (scanline == 0)
9191020   {
920      ef9345->state |= 0x04;
921      draw_border(ef9345, 0);
922      if(ef9345->PAT & 1)
1021      state |= 0x04;
1022      draw_border(0);
1023      if (PAT & 1)
9231024         for(i = 0; i < 40; i++)
924            makechar(ef9345, i, (scanline / 10));
1025            makechar(i, (scanline / 10));
9251026      else
9261027         for(i = 0; i < 42; i++)
927            draw_char_40(ef9345, ef9345->border, i, 1);
1028            draw_char_40(border, i, 1);
9281029   }
929   else if(scanline < 120)
1030   else if (scanline < 120)
9301031   {
931      if(ef9345->PAT & 2)
1032      if (PAT & 2)
9321033         for(i = 0; i < 40; i++)
933            makechar(ef9345, i, (scanline / 10));
1034            makechar(i, (scanline / 10));
9341035      else
935         draw_border(ef9345, scanline / 10);
1036         draw_border(scanline / 10);
9361037   }
937   else if(scanline < 250)
1038   else if (scanline < 250)
9381039   {
939      if(ef9345->PAT & 4)
1040      if (PAT & 4)
9401041         for(i = 0; i < 40; i++)
941            makechar(ef9345, i, (scanline / 10));
1042            makechar(i, (scanline / 10));
9421043      else
943         draw_border(ef9345, scanline / 10);
1044         draw_border(scanline / 10);
9441045
945      if(scanline == 240)
946         draw_border(ef9345, 26);
1046      if (scanline == 240)
1047         draw_border(26);
9471048   }
9481049}
9491050
950
951static TIMER_CALLBACK( blinking )
1051READ8_MEMBER( ef9345_device::data_r )
9521052{
953   running_device *device = (running_device *)ptr;
954   ef9345_t *ef9345 = get_safe_token(device);
1053   if (offset & 7)
1054      return registers[offset & 7];
9551055
956   ef9345->blink = (!ef9345->blink) & 0x01;
957}
1056   if (bf)
1057      state |= 0x80;
1058   else
1059      state &= 0x7f;
9581060
959
960/*-------------------------------------------------
961    DEVICE_RESET( ef9345 )
962-------------------------------------------------*/
963static DEVICE_RESET( ef9345 )
964{
965   ef9345_t *ef9345 = get_safe_token(device);
966
967   ef9345->TGS =  0;
968   ef9345->MAT =  0;
969   ef9345->PAT =  0;
970   ef9345->DOR =  0;
971   ef9345->ROR =  0;
972   ef9345->state = 0;
973   ef9345->bf = 0;
974   ef9345->blink = 0;
975   ef9345->dial = 0;
976   ef9345->latchc0 = 0;
977   ef9345->latchm = 0;
978   ef9345->latchi = 0;
979   ef9345->latchu = 0;
980   ef9345->char_mode = 0;
981
982   memset(ef9345->last_dial, 0, sizeof(ef9345->last_dial));
983   memset(ef9345->ram, 0, sizeof(ef9345->ram));
984   memset(ef9345->registers, 0, sizeof(ef9345->registers));
985   memset(ef9345->border, 0, sizeof(ef9345->border));
986
987   bitmap_fill(ef9345->screen_out, NULL, 0);
988
989   set_ef9345_mode(ef9345);
1061   return state;
9901062}
9911063
992
993/*-------------------------------------------------
994    DEVICE_START( ef9345 )
995-------------------------------------------------*/
996static DEVICE_START( ef9345 )
1064WRITE8_MEMBER( ef9345_device::data_w )
9971065{
998   ef9345_t *ef9345 = get_safe_token(device);
999   const ef9345_config *config = (ef9345_config*)device->baseconfig().static_config();
1066   registers[offset & 7] = data;
10001067
1001   /* validate arguments */
1002   assert(device != NULL);
1003
1004   ef9345->charset = memory_region(device->machine, config->charset);
1005
1006   ef9345->screen = device->machine->device<screen_device>(config->screen_tag);
1007   assert(ef9345->screen != NULL);
1008
1009   ef9345->busy_timer = timer_alloc(device->machine, ef9345_done, (void *)device);
1010   ef9345->blink_timer = timer_alloc(device->machine, blinking, (void *)device);
1011
1012   ef9345->screen_out = auto_bitmap_alloc(device->machine, 496, ef9345->screen->height() , BITMAP_FORMAT_INDEXED16);
1013
1014   timer_adjust_periodic(ef9345->blink_timer, ATTOTIME_IN_MSEC(500), 0, ATTOTIME_IN_MSEC(500));
1015
1016   init_char_prt(ef9345);
1017
1018   state_save_register_device_item_array(device, 0, ef9345->ram);
1019   state_save_register_device_item_array(device, 0, ef9345->border);
1020   state_save_register_device_item_array(device, 0, ef9345->registers);
1021   state_save_register_device_item_array(device, 0, ef9345->last_dial);
1022
1023   state_save_register_device_item(device, 0, ef9345->bf);
1024   state_save_register_device_item(device, 0, ef9345->char_mode);
1025   state_save_register_device_item(device, 0, ef9345->state);
1026   state_save_register_device_item(device, 0, ef9345->TGS);
1027   state_save_register_device_item(device, 0, ef9345->MAT);
1028   state_save_register_device_item(device, 0, ef9345->PAT);
1029   state_save_register_device_item(device, 0, ef9345->DOR);
1030   state_save_register_device_item(device, 0, ef9345->ROR);
1031   state_save_register_device_item(device, 0, ef9345->blink);
1032   state_save_register_device_item(device, 0, ef9345->dial);
1033   state_save_register_device_item(device, 0, ef9345->latchc0);
1034   state_save_register_device_item(device, 0, ef9345->latchm);
1035   state_save_register_device_item(device, 0, ef9345->latchi);
1036   state_save_register_device_item(device, 0, ef9345->latchu);
1037
1038   state_save_register_device_item_bitmap(device, 0, ef9345->screen_out);
1068   if (offset & 8)
1069      ef9345_exec(registers[0] & 0xff);
10391070}
1040
1041DEVICE_GET_INFO( ef9345 )
1042{
1043   switch (state)
1044   {
1045      /* --- the following bits of info are returned as 64-bit signed integers --- */
1046   case DEVINFO_INT_TOKEN_BYTES:               info->i = sizeof(ef9345_t);            break;
1047   case DEVINFO_INT_INLINE_CONFIG_BYTES:         info->i = sizeof(ef9345_config);      break;
1048
1049      /* --- the following bits of info are returned as pointers to data or functions --- */
1050   case DEVINFO_FCT_START:                     info->start = DEVICE_START_NAME(ef9345);   break;
1051   case DEVINFO_FCT_STOP:                     /* Nothing */                        break;
1052   case DEVINFO_FCT_RESET:                     info->reset = DEVICE_RESET_NAME(ef9345);   break;
1053   case DEVINFO_PTR_ROM_REGION:               /* Nothing */                        break;
1054
1055      /* --- the following bits of info are returned as NULL-terminated strings --- */
1056   case DEVINFO_STR_NAME:                     strcpy(info->s, "SGS Thomson EF9345");      break;
1057   case DEVINFO_STR_FAMILY:                  strcpy(info->s, "EF9345");               break;
1058   case DEVINFO_STR_VERSION:                  strcpy(info->s, "1.0");                  break;
1059   case DEVINFO_STR_SOURCE_FILE:               strcpy(info->s, __FILE__);               break;
1060   case DEVINFO_STR_CREDITS:                  strcpy(info->s, "Daniel Coulom");               break;
1061   }
1062}
1063
1064DEFINE_LEGACY_DEVICE(EF9345, ef9345);
src/mess/video/ef9345.h
r9546r9547
66
77*********************************************************************/
88
9
10#pragma once
11
912#ifndef __EF9345_H__
1013#define __EF9345_H__
1114
1215
13/***************************************************************************
14    MACROS
15***************************************************************************/
16#define MDRV_EF9345_ADD(_tag, _config) \
17   MDRV_DEVICE_ADD(_tag, EF9345, 0) \
18   MDRV_DEVICE_CONFIG(_config)
1619
17DECLARE_LEGACY_DEVICE(EF9345, ef9345);
20//**************************************************************************
21//  TYPE DEFINITIONS
22//**************************************************************************
1823
19/***************************************************************************
20    TYPE DEFINITIONS
21***************************************************************************/
24// ======================> ef9345_interface
2225
23typedef struct _ef9345_config ef9345_config;
24struct _ef9345_config
26struct ef9345_interface
2527{
26   const char *screen_tag;
27   const char *charset;
28   const char *screen_tag;      // screen we are acting on
2829};
2930
30/***************************************************************************
31    DEVICE CONFIGURATION MACROS
32***************************************************************************/
3331
34#define MDRV_EF9345_ADD(_tag, _config) \
35   MDRV_DEVICE_ADD(_tag, EF9345, 0) \
36   MDRV_DEVICE_CONFIG(_config)
32// ======================> ef9345_device_config
3733
38/***************************************************************************
39    FUNCTION PROTOTYPES
40***************************************************************************/
34class ef9345_device_config :   public device_config,
35                        public device_config_memory_interface,
36                                public ef9345_interface
37{
38    friend class ef9345_device;
4139
42void video_update_ef9345(running_device *device, bitmap_t *bitmap, const rectangle *cliprect);
43void ef9345_scanline(running_device *device, UINT16 scanline);
44READ8_DEVICE_HANDLER( ef9345_r );
45WRITE8_DEVICE_HANDLER( ef9345_w );
40    // construction/destruction
41    ef9345_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock);
4642
47#endif /* __EF9345_H__ */
43public:
44    // allocators
45    static device_config *static_alloc_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock);
46    virtual device_t *alloc_device(running_machine &machine) const;
47
48protected:
49   // device_config overrides
50   virtual void device_config_complete();
51
52   // device_config_memory_interface overrides
53   virtual const address_space_config *memory_space_config(int spacenum = 0) const;
54
55    // address space configurations
56   const address_space_config      m_space_config;
57};
58
59
60
61// ======================> ef9345_device
62
63class ef9345_device :   public device_t,
64                  public device_memory_interface
65{
66    friend class ef9345_device_config;
67
68    // construction/destruction
69    ef9345_device(running_machine &_machine, const ef9345_device_config &_config);
70
71public:
72   // device interface
73   READ8_MEMBER( data_r );
74   WRITE8_MEMBER( data_w );
75   void update_scanline(UINT16 scanline);
76   void video_update(bitmap_t *bitmap, const rectangle *cliprect);
77
78protected:
79    // device-level overrides
80    virtual void device_start();
81    virtual void device_reset();
82   virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
83   
84   // inline helper
85   inline UINT16 indexram(UINT8 r);
86   inline UINT16 indexrom(UINT8 r);
87   inline void inc_x(UINT8 r);
88   inline void inc_y(UINT8 r);
89
90private:
91
92   void set_busy_flag(int period);
93   void draw_char_40(UINT8 *c, UINT16 x, UINT16 y);
94   void draw_char_80(UINT8 *c, UINT16 x, UINT16 y);
95   void set_video_mode(void);
96   void init_accented_chars(void);
97   UINT8 read_char(UINT8 index, UINT16 addr);
98   UINT8 get_dial(UINT8 x, UINT8 attrib);
99   void zoom(UINT8 *pix, UINT16 n);
100   UINT16 indexblock(UINT16 x, UINT16 y);
101   void bichrome40(UINT8 type, UINT16 address, UINT8 dial, UINT16 iblock, UINT16 x, UINT16 y, UINT8 c0, UINT8 c1, UINT8 insert, UINT8 flash, UINT8 hided, UINT8 negative, UINT8 underline);
102   void quadrichrome40(UINT8 c, UINT8 b, UINT8 a, UINT16 x, UINT16 y);
103   void bichrome80(UINT8 c, UINT8 a, UINT16 x, UINT16 y);
104   void makechar(UINT16 x, UINT16 y);
105   void draw_border(UINT16 line);
106   void makechar_16x40(UINT16 x, UINT16 y);
107   void makechar_24x40(UINT16 x, UINT16 y);
108   void makechar_12x80(UINT16 x, UINT16 y);
109   void ef9345_exec(UINT8 cmd);
110
111   // internal state
112   const ef9345_device_config &m_config;
113   static const device_timer_id BUSY_TIMER = 0;
114   static const device_timer_id BLINKING_TIMER = 1;
115
116   const region_info *charset;
117   address_space *videoram;
118
119   screen_device *screen;         //screen we are acting on
120
121   UINT8 bf;                  //busy flag
122   UINT8 char_mode;            //40 or 80 chars for line
123   UINT8 acc_char[0x2000];         //accented chars
124   UINT8 registers[8];            //registers R0-R7
125   UINT8 state;               //status register
126   UINT8 TGS,MAT,PAT,DOR,ROR;      //indirect registers
127   UINT8 border[80];            //border color
128   UINT16 block;               //current memory block
129   UINT16 ram_base[4];            //index of ram charset
130   UINT8 blink;               //cursor status
131   UINT8 last_dial[40];         //last chars dial (for determinate the zoom position)
132   UINT8 latchc0;               //background color latch
133   UINT8 latchm;               //hided atribute latch
134   UINT8 latchi;               //insert atribute latch
135   UINT8 latchu;               //underline atribute latch
136
137   bitmap_t *screen_out;
138
139   // timers
140   emu_timer *m_busy_timer;
141   emu_timer *m_blink_timer;
142};
143
144// device type definition
145extern const device_type EF9345;
146
147#endif
src/mess/drivers/mc10.c
r9546r9547
2929      : driver_device(machine, config) { }
3030
3131   running_device *mc6847;
32   running_device *ef9345;
32   ef9345_device *ef9345;
3333   running_device *dac;
3434   running_device *cassette;
3535
r9546r9547
175175{
176176   mc10_state *state = screen->machine->driver_data<mc10_state>();
177177
178   video_update_ef9345(state->ef9345, bitmap, cliprect);
178   state->ef9345->video_update(bitmap, cliprect);
179179
180180   return 0;
181181}
r9546r9547
184184{
185185   mc10_state *state = timer.machine->driver_data<mc10_state>();
186186
187   ef9345_scanline(state->ef9345, (UINT16)param);
187   state->ef9345->update_scanline((UINT16)param);
188188}
189189
190190/***************************************************************************
r9546r9547
229229   mc10->keyboard_strobe = 0x00;
230230
231231   /* find devices */
232   mc10->ef9345 = machine->device("ef9345");
232   mc10->ef9345 = machine->device<ef9345_device>("ef9345");
233233   mc10->dac = machine->device("dac");
234234   mc10->cassette = machine->device("cassette");
235235
r9546r9547
273273   AM_RANGE(0x3000, 0x4fff) AM_RAMBANK("bank1") /* 8k internal ram */
274274   AM_RANGE(0x5000, 0x8fff) AM_RAMBANK("bank2") /* 16k memory expansion */
275275   AM_RANGE(0x9000, 0xafff) AM_NOP /* unused */
276   AM_RANGE(0xbf20, 0xbf29) AM_DEVREADWRITE("ef9345", ef9345_r, ef9345_w)
276   AM_RANGE(0xbf20, 0xbf29) AM_DEVREADWRITE_MODERN("ef9345", ef9345_device, data_r, data_w)
277277   AM_RANGE(0xbfff, 0xbfff) AM_READWRITE(alice32_bfff_r, alice32_bfff_w)
278278   AM_RANGE(0xc000, 0xffff) AM_ROM AM_REGION("maincpu", 0x0000) /* ROM */
279279ADDRESS_MAP_END
r9546r9547
515515   MDRV_RAM_EXTRA_OPTIONS("4K")
516516MACHINE_CONFIG_END
517517
518
519static const ef9345_config alice32_ef9345_config =
518static const ef9345_interface alice32_ef9345_config =
520519{
521   "screen",         /* screen we are acting on */
522   "ef9345"         /* charset */
520   "screen"         /* screen we are acting on */
523521};
524522
525523static MACHINE_CONFIG_START( alice32, mc10_state )
src/mess/drivers/vg5k.c
r9546r9547
5656   vg5k_state(running_machine &machine, const driver_device_config_base &config)
5757      : driver_device(machine, config) { }
5858
59   running_device *ef9345;
59   ef9345_device *ef9345;
6060   running_device *dac;
6161   running_device *printer;
6262   running_device *cassette;
6363
64   UINT8 ef9345_offset;
64   offs_t ef9345_offset;
6565};
6666
6767
r9546r9547
9393{
9494   vg5k_state *vg5k = space->machine->driver_data<vg5k_state>();
9595
96   return ef9345_r(vg5k->ef9345, vg5k->ef9345_offset);
96   return vg5k->ef9345->data_r(*space, vg5k->ef9345_offset, 0xff);
9797}
9898
9999
r9546r9547
101101{
102102   vg5k_state *vg5k = space->machine->driver_data<vg5k_state>();
103103
104   ef9345_w(vg5k->ef9345, vg5k->ef9345_offset, data);
104   vg5k->ef9345->data_w(*space, vg5k->ef9345_offset, data, 0xff);
105105}
106106
107107
r9546r9547
291291{
292292   vg5k_state *vg5k = timer.machine->driver_data<vg5k_state>();
293293
294   ef9345_scanline(vg5k->ef9345, (UINT16)param);
294   vg5k->ef9345->update_scanline((UINT16)param);
295295}
296296
297297
r9546r9547
299299{
300300   vg5k_state *vg5k = machine->driver_data<vg5k_state>();
301301
302   vg5k->ef9345 = machine->device("ef9345");
302   vg5k->ef9345 = machine->device<ef9345_device>("ef9345");
303303   vg5k->dac = machine->device("dac");
304304   vg5k->printer = machine->device("printer");
305305   vg5k->cassette = machine->device("cassette");
r9546r9547
324324{
325325   vg5k_state *vg5k = screen->machine->driver_data<vg5k_state>();
326326
327   video_update_ef9345(vg5k->ef9345, bitmap, cliprect);
327   vg5k->ef9345->video_update(bitmap, cliprect);
328328
329329   return 0;
330330}
r9546r9547
344344};
345345
346346static GFXDECODE_START( vg5k )
347   GFXDECODE_ENTRY( "gfx1", 0x2000, vg5k_charlayout, 0, 4 )
347   GFXDECODE_ENTRY( "ef9345", 0x2000, vg5k_charlayout, 0, 4 )
348348GFXDECODE_END
349349
350350static DRIVER_INIT( vg5k )
351351{
352   UINT8 *FNT = memory_region(machine, "gfx1");
352   UINT8 *FNT = memory_region(machine, "ef9345");
353353   UINT16 a,b,c,d,dest=0x2000;
354354
355355   /* Unscramble the chargen rom as the format is too complex for gfxdecode to handle unaided */
r9546r9547
370370}
371371
372372
373static const ef9345_config vg5k_ef9345_config =
373static const ef9345_interface vg5k_ef9345_config =
374374{
375   "screen",         /* screen we are acting on */
376   "gfx1"            /* charset */
375   "screen"         /* screen we are acting on */
377376};
378377
379378static const struct CassetteOptions vg5k_cassette_options =
r9546r9547
448447   ROM_SYSTEM_BIOS(1, "alt", "VG 5000 (alt)")
449448   ROMX_LOAD( "vg5k.rom", 0x0000, 0x4000, BAD_DUMP CRC(a6f4a0ea) SHA1(58eccce33cc21fc17bc83921018f531b8001eda3), ROM_BIOS(2) )   // from dcvg5k
450449
451   ROM_REGION( 0x4000, "gfx1", 0 )
450   ROM_REGION( 0x4000, "ef9345", 0 )
452451   ROM_LOAD( "charset.rom", 0x0000, 0x2000, BAD_DUMP CRC(b2f49eb3) SHA1(d0ef530be33bfc296314e7152302d95fdf9520fc) )         // from dcvg5k
453452ROM_END
454453

Previous 15994 Revisions Next


© 1998-2018 The MESS Team