1 // license:BSD-3-Clause
2 // copyright-holders:Wilbert Pol
3 /***************************************************************************
4
5 IBM PC junior
6 Tandy 1000 Graphics Adapter (T1T) section
7
8 Note that in the IBM PC Junior world, the term 'vga' is not the 'vga' that
9 most people think of
10
11 ***************************************************************************/
12
13 #include "emu.h"
14 #include "pc_t1t.h"
15
16 #include "machine/ram.h"
17 #include "screen.h"
18
19
20 enum
21 {
22 T1000_TEXT_INTEN = 0,
23 T1000_TEXT_BLINK,
24 T1000_GFX_1BPP,
25 T1000_GFX_2BPP,
26 T1000_GFX_4BPP,
27 T1000_GFX_2BPP_TGA,
28 PCJX_TEXT,
29 PCJR_GFX_2BPP_HIGH
30 };
31
32
33 DEFINE_DEVICE_TYPE(PCVIDEO_T1000, pcvideo_t1000_device, "tandy_1000_graphics", "Tandy 1000 Graphics Adapter")
34 DEFINE_DEVICE_TYPE(PCVIDEO_PCJR, pcvideo_pcjr_device, "pcjr_graphics", "PC Jr Graphics Adapter")
35
pc_t1t_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock)36 pc_t1t_device::pc_t1t_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
37 device_t(mconfig, type, tag, owner, clock),
38 device_video_interface(mconfig, *this),
39 m_mc6845(*this, T1000_MC6845_NAME),
40 m_mode_control(0),
41 m_color_select(0),
42 m_status(0),
43 m_bank(0),
44 m_pc_framecnt(0),
45 m_displayram(nullptr),
46 m_chr_gen(nullptr),
47 m_chr_size(0),
48 m_ra_offset(0),
49 m_address_data_ff(0),
50 m_update_row_type(-1),
51 m_display_enable(0),
52 m_vsync(0),
53 m_palette_base(0),
54 m_palette(*this,"palette"),
55 m_ram(*this, ":" RAM_TAG),
56 m_vram(*this, "vram")
57 {
58 }
59
pcvideo_t1000_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)60 pcvideo_t1000_device::pcvideo_t1000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
61 : pc_t1t_device(mconfig, PCVIDEO_T1000, tag, owner, clock)
62 {
63 }
64
pcvideo_pcjr_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)65 pcvideo_pcjr_device::pcvideo_pcjr_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
66 : pc_t1t_device(mconfig, PCVIDEO_PCJR, tag, owner, clock),
67 m_pic8259(*this, ":pic8259"),
68 m_jxkanji(nullptr)
69 {
70 }
71
72
device_start()73 void pcvideo_t1000_device::device_start()
74 {
75 if(!m_ram->started())
76 throw device_missing_dependencies();
77 m_chr_gen = machine().root_device().memregion("gfx1")->base();
78 m_bank = 0;
79 m_chr_size = 1;
80 m_ra_offset = 256;
81 m_vram->space(0).install_ram(0, 128*1024 - 1, m_ram->pointer());
82 }
83
84
device_start()85 void pcvideo_pcjr_device::device_start()
86 {
87 if(!m_ram->started())
88 throw device_missing_dependencies();
89 m_chr_gen = machine().root_device().memregion("gfx1")->base();
90 m_bank = 0;
91 m_mode_control = 0x08;
92 m_chr_size = 8;
93 m_ra_offset = 1;
94 if(!strncmp(machine().system().name, "ibmpcjx", 7))
95 {
96 m_jxkanji = machine().root_device().memregion("kanji")->base();
97 m_vram->space(0).install_ram(0, 128*1024 - 1, memshare(":vram")->ptr()); // TODO: fix when this is really understood
98 }
99 else
100 {
101 m_jxkanji = nullptr;
102 m_vram->space(0).install_ram(0, 128*1024 - 1, m_ram->pointer());
103 }
104 }
105
106
107 /***************************************************************************
108
109 Static declarations
110
111 ***************************************************************************/
112
vram_map(address_map & map)113 void pc_t1t_device::vram_map(address_map &map)
114 {
115 map.unmap_value_high();
116 map(0x20000, 0x3ffff).noprw();
117 }
118
device_add_mconfig(machine_config & config)119 void pcvideo_t1000_device::device_add_mconfig(machine_config &config)
120 {
121 screen_device &screen(SCREEN(config, T1000_SCREEN_NAME, SCREEN_TYPE_RASTER));
122 screen.set_raw(XTAL(14'318'181),912,0,640,262,0,200);
123 screen.set_screen_update(T1000_MC6845_NAME, FUNC(mc6845_device::screen_update));
124
125 PALETTE(config, m_palette, FUNC(pcvideo_t1000_device::pcjr_palette), 32);
126
127 MC6845(config, m_mc6845, XTAL(14'318'181)/8);
128 m_mc6845->set_screen(T1000_SCREEN_NAME);
129 m_mc6845->set_show_border_area(false);
130 m_mc6845->set_char_width(8);
131 m_mc6845->set_update_row_callback(FUNC(pc_t1t_device::crtc_update_row));
132 m_mc6845->out_de_callback().set(FUNC(pc_t1t_device::t1000_de_changed));
133 m_mc6845->out_vsync_callback().set(FUNC(pcvideo_t1000_device::t1000_vsync_changed));
134
135 ADDRESS_MAP_BANK(config, m_vram).set_map(&pc_t1t_device::vram_map).set_options(ENDIANNESS_LITTLE, 8, 18, 0x4000);
136 }
137
138
device_add_mconfig(machine_config & config)139 void pcvideo_pcjr_device::device_add_mconfig(machine_config &config)
140 {
141 screen_device &screen(SCREEN(config, T1000_SCREEN_NAME, SCREEN_TYPE_RASTER));
142 screen.set_raw(XTAL(14'318'181), 912, 0, 640, 262, 0, 200);
143 screen.set_screen_update(T1000_MC6845_NAME, FUNC(mc6845_device::screen_update));
144
145 PALETTE(config, m_palette, FUNC(pcvideo_pcjr_device::pcjr_palette), 32);
146
147 MC6845(config, m_mc6845, XTAL(14'318'181)/16);
148 m_mc6845->set_screen(T1000_SCREEN_NAME);
149 m_mc6845->set_show_border_area(false);
150 m_mc6845->set_char_width(8);
151 m_mc6845->set_update_row_callback(FUNC(pcvideo_pcjr_device::crtc_update_row));
152 m_mc6845->out_de_callback().set(FUNC(pc_t1t_device::t1000_de_changed));
153 m_mc6845->out_vsync_callback().set(FUNC(pcvideo_pcjr_device::pcjr_vsync_changed));
154
155 ADDRESS_MAP_BANK(config, m_vram).set_map(&pc_t1t_device::vram_map).set_options(ENDIANNESS_LITTLE, 8, 18, 0x4000);
156 }
157
158
159 /***************************************************************************
160
161 Methods
162
163 ***************************************************************************/
164
165 /* Initialise the cga palette */
pcjr_palette(palette_device & palette) const166 void pc_t1t_device::pcjr_palette(palette_device &palette) const
167 {
168 static constexpr rgb_t tga_palette[16] =
169 {
170 { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0xaa }, { 0x00, 0xaa, 0x00 }, { 0x00, 0xaa, 0xaa },
171 { 0xaa, 0x00, 0x00 }, { 0xaa, 0x00, 0xaa }, { 0xaa, 0x55, 0x00 }, { 0xaa, 0xaa, 0xaa },
172 { 0x55, 0x55, 0x55 }, { 0x55, 0x55, 0xff }, { 0x55, 0xff, 0x55 }, { 0x55, 0xff, 0xff },
173 { 0xff, 0x55, 0x55 }, { 0xff, 0x55, 0xff }, { 0xff, 0xff, 0x55 }, { 0xff, 0xff, 0xff }
174 };
175
176 // colors
177 for (int i = 0; i < 16; i++)
178 palette.set_pen_color(i, tga_palette[i]);
179
180 /* b/w mode shades */
181 for (int i = 0; i < 16; i++)
182 palette.set_pen_color(16+i, pal4bit(i), pal4bit(i), pal4bit(i));
183 }
184
185
MC6845_UPDATE_ROW(pc_t1t_device::t1000_text_inten_update_row)186 MC6845_UPDATE_ROW( pc_t1t_device::t1000_text_inten_update_row )
187 {
188 rgb_t const *const palette = m_palette->palette()->entry_list_raw();
189 uint32_t *p = &bitmap.pix(y);
190
191 if ( y == 0 ) logerror("t1000_text_inten_update_row\n");
192 for (int i = 0; i < x_count; i++)
193 {
194 uint16_t offset = ( ( ma + i ) << 1 ) & 0x3fff;
195 uint8_t chr = m_displayram[ offset ];
196 uint8_t attr = m_displayram[ offset +1 ];
197 uint8_t data = m_chr_gen[ chr * m_chr_size + ra * m_ra_offset ];
198 uint16_t fg = m_palette_base + ( attr & 0x0F );
199 uint16_t bg = m_palette_base + ( ( attr >> 4 ) & 0x07 );
200
201 if ( i == cursor_x && ( m_pc_framecnt & 0x08 ) )
202 {
203 data = 0xFF;
204 }
205
206 *p++ = palette[BIT(data, 7) ? fg : bg];
207 *p++ = palette[BIT(data, 6) ? fg : bg];
208 *p++ = palette[BIT(data, 5) ? fg : bg];
209 *p++ = palette[BIT(data, 4) ? fg : bg];
210 *p++ = palette[BIT(data, 3) ? fg : bg];
211 *p++ = palette[BIT(data, 2) ? fg : bg];
212 *p++ = palette[BIT(data, 1) ? fg : bg];
213 *p++ = palette[BIT(data, 0) ? fg : bg];
214 }
215 }
216
217
MC6845_UPDATE_ROW(pc_t1t_device::t1000_text_blink_update_row)218 MC6845_UPDATE_ROW( pc_t1t_device::t1000_text_blink_update_row )
219 {
220 rgb_t const *const palette = m_palette->palette()->entry_list_raw();
221 uint32_t *p = &bitmap.pix(y);
222
223 for (int i = 0; i < x_count; i++)
224 {
225 uint16_t offset = ( ( ma + i ) << 1 ) & 0x3fff;
226 uint8_t chr = m_displayram[ offset ];
227 uint8_t attr = m_displayram[ offset +1 ];
228 uint8_t data = m_chr_gen[ chr * m_chr_size + ra * m_ra_offset ];
229 uint16_t fg = m_palette_base + ( attr & 0x0F );
230 uint16_t bg = m_palette_base + ( ( attr >> 4 ) & 0x07 );
231
232 if ( i == cursor_x )
233 {
234 if ( m_pc_framecnt & 0x08 )
235 {
236 data = 0xFF;
237 }
238 }
239 else
240 {
241 if ( ( attr & 0x80 ) && ( m_pc_framecnt & 0x10 ) )
242 {
243 data = 0x00;
244 }
245 }
246
247 *p++ = palette[BIT(data, 7) ? fg : bg];
248 *p++ = palette[BIT(data, 6) ? fg : bg];
249 *p++ = palette[BIT(data, 5) ? fg : bg];
250 *p++ = palette[BIT(data, 4) ? fg : bg];
251 *p++ = palette[BIT(data, 3) ? fg : bg];
252 *p++ = palette[BIT(data, 2) ? fg : bg];
253 *p++ = palette[BIT(data, 1) ? fg : bg];
254 *p++ = palette[BIT(data, 0) ? fg : bg];
255 }
256 }
257
MC6845_UPDATE_ROW(pcvideo_pcjr_device::pcjx_text_update_row)258 MC6845_UPDATE_ROW( pcvideo_pcjr_device::pcjx_text_update_row )
259 {
260 rgb_t const *const palette = m_palette->palette()->entry_list_raw();
261 uint32_t *p = &bitmap.pix(y);
262
263 for (int i = 0; i < x_count; i++)
264 {
265 uint16_t offset = ( ( ma + i ) << 1 ) & 0x3fff;
266 uint8_t chr = m_displayram[ offset ];
267 uint8_t attr = m_displayram[ offset +1 ];
268 uint16_t fg = m_palette_base + ( attr & 0x07 );
269 uint16_t bg = m_palette_base + ( ( attr >> 4 ) & 0x07 );
270 uint16_t code = chr & 0x1f;
271 if((attr & 0x88) == 0x88)
272 {
273 code = m_displayram[ offset - 2 ] & 0x1f;
274 code = (code << 8) + chr;
275 }
276 else if(attr & 0x80)
277 code = (code << 8) + m_displayram[ offset + 2 ];
278 else
279 code = chr;
280
281 uint8_t data;
282 if(ra < 16)
283 data = m_jxkanji[code * 16 * 2 + (ra * 2) + ((attr & 8)?1:0)];
284 else
285 data = ((i == cursor_x) && (m_pc_framecnt & 8)) ? 0xff: 0;
286
287 *p++ = palette[BIT(data, 7) ? fg : bg];
288 *p++ = palette[BIT(data, 6) ? fg : bg];
289 *p++ = palette[BIT(data, 5) ? fg : bg];
290 *p++ = palette[BIT(data, 4) ? fg : bg];
291 *p++ = palette[BIT(data, 3) ? fg : bg];
292 *p++ = palette[BIT(data, 2) ? fg : bg];
293 *p++ = palette[BIT(data, 1) ? fg : bg];
294 *p++ = palette[BIT(data, 0) ? fg : bg];
295 }
296 }
297
MC6845_UPDATE_ROW(pc_t1t_device::t1000_gfx_4bpp_update_row)298 MC6845_UPDATE_ROW( pc_t1t_device::t1000_gfx_4bpp_update_row )
299 {
300 rgb_t const *const palette = m_palette->palette()->entry_list_raw();
301 uint32_t *p = &bitmap.pix(y);
302 uint8_t const *const vid = m_displayram + ( ra << 13 );
303
304 for (int i = 0; i < x_count; i++)
305 {
306 uint16_t offset = ( ( ma + i ) << 1 ) & 0x1fff;
307 uint8_t data = vid[offset];
308
309 *p++ = palette[m_palette_base + m_reg.data[0x10 | (data >> 4)]];
310 *p++ = palette[m_palette_base + m_reg.data[0x10 | (data >> 4)]];
311 *p++ = palette[m_palette_base + m_reg.data[0x10 | (data & 0x0f)]];
312 *p++ = palette[m_palette_base + m_reg.data[0x10 | (data & 0x0f)]];
313
314 data = vid[offset + 1];
315
316 *p++ = palette[m_palette_base + m_reg.data[0x10 | (data >> 4)]];
317 *p++ = palette[m_palette_base + m_reg.data[0x10 | (data >> 4)]];
318 *p++ = palette[m_palette_base + m_reg.data[0x10 | (data & 0x0f)]];
319 *p++ = palette[m_palette_base + m_reg.data[0x10 | (data & 0x0f)]];
320 }
321 }
322
323
MC6845_UPDATE_ROW(pc_t1t_device::t1000_gfx_2bpp_update_row)324 MC6845_UPDATE_ROW( pc_t1t_device::t1000_gfx_2bpp_update_row )
325 {
326 rgb_t const *const palette = m_palette->palette()->entry_list_raw();
327 uint32_t *p = &bitmap.pix(y);
328 uint8_t const *const vid = m_displayram + ( ra << 13 );
329
330 for (int i = 0; i < x_count; i++)
331 {
332 uint16_t offset = ( ( ma + i ) << 1 ) & 0x1fff;
333 uint8_t data = vid[offset];
334
335 *p++ = palette[m_palette_base + m_reg.data[0x10 | ((data >> 6) & 0x03)]];
336 *p++ = palette[m_palette_base + m_reg.data[0x10 | ((data >> 4) & 0x03)]];
337 *p++ = palette[m_palette_base + m_reg.data[0x10 | ((data >> 2) & 0x03)]];
338 *p++ = palette[m_palette_base + m_reg.data[0x10 | ((data >> 0) & 0x03)]];
339
340 data = vid[offset + 1];
341
342 *p++ = palette[m_palette_base + m_reg.data[0x10 | ((data >> 6) & 0x03)]];
343 *p++ = palette[m_palette_base + m_reg.data[0x10 | ((data >> 4) & 0x03)]];
344 *p++ = palette[m_palette_base + m_reg.data[0x10 | ((data >> 2) & 0x03)]];
345 *p++ = palette[m_palette_base + m_reg.data[0x10 | ((data >> 0) & 0x03)]];
346 }
347 }
348
349
MC6845_UPDATE_ROW(pcvideo_pcjr_device::pcjr_gfx_2bpp_high_update_row)350 MC6845_UPDATE_ROW( pcvideo_pcjr_device::pcjr_gfx_2bpp_high_update_row )
351 {
352 rgb_t const *const palette = m_palette->palette()->entry_list_raw();
353 uint32_t *p = &bitmap.pix(y);
354 uint8_t const *const vid = m_displayram + ( ra << 13 );
355
356 for (int i = 0; i < x_count; i++)
357 {
358 uint16_t offset = ( ( ma + i ) << 1 ) & 0x1fff;
359 uint8_t data0 = vid[offset];
360 uint8_t data1 = vid[offset + 1];
361
362 *p++ = palette[m_palette_base + m_reg.data[0x10 | ((data0 >> 7) & 0x01) | ((data1 >> 6) & 0x02)]];
363 *p++ = palette[m_palette_base + m_reg.data[0x10 | ((data0 >> 6) & 0x01) | ((data1 >> 5) & 0x02)]];
364 *p++ = palette[m_palette_base + m_reg.data[0x10 | ((data0 >> 5) & 0x01) | ((data1 >> 4) & 0x02)]];
365 *p++ = palette[m_palette_base + m_reg.data[0x10 | ((data0 >> 4) & 0x01) | ((data1 >> 3) & 0x02)]];
366 *p++ = palette[m_palette_base + m_reg.data[0x10 | ((data0 >> 3) & 0x01) | ((data1 >> 2) & 0x02)]];
367 *p++ = palette[m_palette_base + m_reg.data[0x10 | ((data0 >> 2) & 0x01) | ((data1 >> 1) & 0x02)]];
368 *p++ = palette[m_palette_base + m_reg.data[0x10 | ((data0 >> 1) & 0x01) | ((data1 >> 0) & 0x02)]];
369 *p++ = palette[m_palette_base + m_reg.data[0x10 | ((data0 >> 0) & 0x01) | ((data1 << 1) & 0x02)]];
370 }
371 }
372
373
MC6845_UPDATE_ROW(pc_t1t_device::t1000_gfx_2bpp_tga_update_row)374 MC6845_UPDATE_ROW( pc_t1t_device::t1000_gfx_2bpp_tga_update_row )
375 {
376 rgb_t const *const palette = m_palette->palette()->entry_list_raw();
377 uint32_t *p = &bitmap.pix(y);
378 uint8_t const *const vid = m_displayram + ( ra << 13 );
379
380 if (y == 0) logerror("t1000_gfx_2bpp_tga_update_row\n");
381 for (int i = 0; i < x_count; i++)
382 {
383 uint16_t offset = ( ( ma + i ) << 1 ) & 0x1fff;
384 uint8_t data = vid[offset];
385 uint8_t data2 = vid[offset + 1] << 1;
386
387 *p++ = palette[m_reg.data[0x10 | (((data2 & 0x100) | (data & 0x80)) >> 7)]];
388 *p++ = palette[m_reg.data[0x10 | (((data2 & 0x080) | (data & 0x40)) >> 6)]];
389 *p++ = palette[m_reg.data[0x10 | (((data2 & 0x040) | (data & 0x20)) >> 5)]];
390 *p++ = palette[m_reg.data[0x10 | (((data2 & 0x020) | (data & 0x10)) >> 4)]];
391
392 *p++ = palette[m_reg.data[0x10 | (((data2 & 0x010) | (data & 0x08)) >> 3)]];
393 *p++ = palette[m_reg.data[0x10 | (((data2 & 0x008) | (data & 0x04)) >> 2)]];
394 *p++ = palette[m_reg.data[0x10 | (((data2 & 0x004) | (data & 0x02)) >> 1)]];
395 *p++ = palette[m_reg.data[0x10 | (((data2 & 0x002) | (data & 0x01)) >> 0)]];
396 }
397 }
398
399
MC6845_UPDATE_ROW(pc_t1t_device::t1000_gfx_1bpp_update_row)400 MC6845_UPDATE_ROW( pc_t1t_device::t1000_gfx_1bpp_update_row )
401 {
402 rgb_t const *const palette = m_palette->palette()->entry_list_raw();
403 uint32_t *p = &bitmap.pix(y);
404 uint8_t const *const vid = m_displayram + ( ra << 13 );
405 uint8_t fg = m_palette_base + m_reg.data[0x11];
406 uint8_t bg = m_palette_base + m_reg.data[0x10];
407
408 if (y == 0) logerror("t1000_gfx_1bpp_update_row\n");
409 for (int i = 0; i < x_count; i++)
410 {
411 uint16_t offset = ( ( ma + i ) << 1 ) & 0x1fff;
412 uint8_t data = vid[offset];
413
414 *p++ = palette[BIT(data, 7) ? fg : bg];
415 *p++ = palette[BIT(data, 6) ? fg : bg];
416 *p++ = palette[BIT(data, 5) ? fg : bg];
417 *p++ = palette[BIT(data, 4) ? fg : bg];
418 *p++ = palette[BIT(data, 3) ? fg : bg];
419 *p++ = palette[BIT(data, 2) ? fg : bg];
420 *p++ = palette[BIT(data, 1) ? fg : bg];
421 *p++ = palette[BIT(data, 0) ? fg : bg];
422
423 data = vid[offset + 1];
424
425 *p++ = palette[BIT(data, 7) ? fg : bg];
426 *p++ = palette[BIT(data, 6) ? fg : bg];
427 *p++ = palette[BIT(data, 5) ? fg : bg];
428 *p++ = palette[BIT(data, 4) ? fg : bg];
429 *p++ = palette[BIT(data, 3) ? fg : bg];
430 *p++ = palette[BIT(data, 2) ? fg : bg];
431 *p++ = palette[BIT(data, 1) ? fg : bg];
432 *p++ = palette[BIT(data, 0) ? fg : bg];
433 }
434 }
435
MC6845_UPDATE_ROW(pc_t1t_device::crtc_update_row)436 MC6845_UPDATE_ROW( pc_t1t_device::crtc_update_row )
437 {
438 if (m_update_row_type == -1)
439 return;
440
441 switch (m_update_row_type)
442 {
443 case T1000_TEXT_INTEN:
444 t1000_text_inten_update_row(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
445 break;
446 case T1000_TEXT_BLINK:
447 t1000_text_blink_update_row(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
448 break;
449 case T1000_GFX_1BPP:
450 t1000_gfx_1bpp_update_row(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
451 break;
452 case T1000_GFX_2BPP:
453 t1000_gfx_2bpp_update_row(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
454 break;
455 case T1000_GFX_2BPP_TGA:
456 t1000_gfx_2bpp_tga_update_row(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
457 break;
458 case T1000_GFX_4BPP:
459 t1000_gfx_4bpp_update_row(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
460 break;
461 }
462 }
463
464
MC6845_UPDATE_ROW(pcvideo_pcjr_device::crtc_update_row)465 MC6845_UPDATE_ROW( pcvideo_pcjr_device::crtc_update_row )
466 {
467 if (m_update_row_type == -1)
468 return;
469
470 switch (m_update_row_type)
471 {
472 case PCJX_TEXT:
473 pcjx_text_update_row(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
474 break;
475 case PCJR_GFX_2BPP_HIGH:
476 pcjr_gfx_2bpp_high_update_row(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
477 break;
478 default:
479 pc_t1t_device::crtc_update_row(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
480 break;
481 }
482 }
483
484
mode_switch()485 void pcvideo_t1000_device::mode_switch()
486 {
487 switch( m_mode_control & 0x3B )
488 {
489 case 0x08: case 0x09:
490 m_update_row_type = T1000_TEXT_INTEN;
491 break;
492 case 0x28: case 0x29:
493 m_update_row_type = T1000_TEXT_BLINK;
494 break;
495 case 0x0A: case 0x0B: case 0x2A: case 0x2B:
496 switch( m_bank & 0xc0 )
497 {
498 case 0x00:
499 case 0x40:
500 //logerror("t1t_gfx_2bpp - 1\n");
501 m_update_row_type = T1000_GFX_2BPP;
502 if ( m_color_select )
503 {
504 m_reg.data[0x10] = 0x00;
505 m_reg.data[0x11] = 0x0B;
506 m_reg.data[0x12] = 0x0D;
507 m_reg.data[0x13] = 0x0F;
508 }
509 else
510 {
511 m_reg.data[0x10] = 0x00;
512 m_reg.data[0x11] = 0x0A;
513 m_reg.data[0x12] = 0x0C;
514 m_reg.data[0x13] = 0x0E;
515 }
516 break;
517 case 0x80:
518 case 0xc0:
519 //logerror("t1t_gfx_4bpp\n");
520 m_update_row_type = T1000_GFX_4BPP;
521 break;
522 }
523 break;
524 case 0x18: case 0x19: case 0x1A: case 0x1B:
525 case 0x38: case 0x39: case 0x3A: case 0x3B:
526 switch( m_bank & 0xc0 )
527 {
528 case 0x00:
529 case 0x40:
530 //logerror("t1t_gfx_1bpp\n");
531 m_update_row_type = T1000_GFX_1BPP;
532 break;
533 case 0x80:
534 case 0xc0:
535 //logerror("t1t_gfx_2bpp - 2\n");
536 m_update_row_type = T1000_GFX_2BPP_TGA;
537 break;
538 }
539 break;
540 default:
541 m_update_row_type = -1;
542 break;
543 }
544 }
545
546
547 /* mode control 1 ( m_reg.data[0] ) */
548 /* bit0 - 0 = low bandwidth, 1 = high bandwidth */
549 /* bit1 - 0 = alpha, 1 = graphics */
550 /* bit2 - 0 = color, 1 = b/w */
551 /* bit3 - 0 = video disable, 1 = video enable */
552 /* bit4 - 1 = 16 color graphics */
553 /* mode control 2 ( m_reg.data[3] ) */
554 /* bit1 - 1 = enable blink */
555 /* bit3 - 1 = 2 color graphics */
556
pc_pcjr_mode_switch()557 void pcvideo_pcjr_device::pc_pcjr_mode_switch()
558 {
559 switch( m_reg.data[0] & 0x1A )
560 {
561 case 0x08: /* 01x0x */
562 if(m_jxkanji)
563 {
564 m_update_row_type = PCJX_TEXT;
565 break;
566 }
567 if ( m_reg.data[3] & 0x02 )
568 {
569 m_update_row_type = T1000_TEXT_BLINK;
570 }
571 else
572 {
573 m_update_row_type = T1000_TEXT_INTEN;
574 }
575 break;
576 case 0x0A: /* 01x1x */
577 /* By default use medium resolution mode */
578 m_update_row_type = T1000_GFX_2BPP;
579
580 /* Check for high resolution mode */
581 if ( ( m_bank & 0xc0 ) == 0xc0 )
582 m_update_row_type = PCJR_GFX_2BPP_HIGH;
583
584 /* Check for 640x200 b/w 2 shades mode */
585 if ( ( m_reg.data[0] & 0x04 ) && ( m_reg.data[3] & 0x08 ) )
586 {
587 m_update_row_type = T1000_GFX_1BPP;
588 }
589 break;
590 case 0x18: /* 11x0x - invalid?? */
591 m_update_row_type = -1;
592 break;
593 case 0x1A: /* 11x1x */
594 m_update_row_type = T1000_GFX_4BPP;
595 break;
596 default:
597 m_update_row_type = -1;
598 break;
599 }
600
601 /* Determine mc6845 input clock */
602 if ( m_reg.data[0] & 0x01 )
603 {
604 m_mc6845->set_unscaled_clock( XTAL(14'318'181)/8 );
605 }
606 else
607 {
608 m_mc6845->set_unscaled_clock( XTAL(14'318'181)/16 );
609 }
610
611 /* color or b/w? */
612 m_palette_base = ( m_reg.data[0] & 0x04 ) ? 16 : 0;
613 }
614
615
616 /*
617 * 3d8 rW T1T mode control register (see #P138)
618 */
mode_control_w(int data)619 void pcvideo_t1000_device::mode_control_w(int data)
620 {
621 m_mode_control = data;
622
623 mode_switch();
624 }
625
mode_control_r()626 int pc_t1t_device::mode_control_r()
627 {
628 int data = m_mode_control;
629 return data;
630 }
631
632 /*
633 * 3d9 ?W color select register on color adapter
634 */
color_select_w(int data)635 void pc_t1t_device::color_select_w(int data)
636 {
637 if (m_color_select == data)
638 return;
639 m_color_select = data;
640 }
641
color_select_r()642 int pc_t1t_device::color_select_r()
643 {
644 int data = m_color_select;
645 return data;
646 }
647
648 /* Bitfields for T1T status register:
649 * Bit(s) Description (Table P179)
650 * 7-6 not used
651 * 5-4 color EGA, color ET4000: diagnose video display feedback, select
652 * from color plane enable
653 * 4 holds current dot being displayed
654 * 3 in vertical retrace
655 * 2 (CGA,color EGA) light pen switch is off
656 * (MCGA,color ET4000) reserved (0)
657 * 1 (CGA,color EGA) positive edge from light pen has set trigger
658 * (MCGA,color ET4000) reserved (0)
659 * 0 display enabled
660 * =0 do not use memory
661 * =1 memory access without interfering with display
662 * (Genoa SuperEGA) horizontal or vertical retrace
663 */
status_r()664 int pc_t1t_device::status_r()
665 {
666 int data = m_vsync | m_status | m_display_enable;
667 /* HACK HACK HACK */
668 data |= ( m_display_enable ? 0x10 : 0x00 );
669 /* end HACK */
670 return data;
671 }
672
673 /*
674 * 3db -W light pen strobe reset (on any value)
675 */
lightpen_strobe_w(int data)676 void pc_t1t_device::lightpen_strobe_w(int data)
677 {
678 // pc_port[0x3db] = data;
679 }
680
681
682 /*
683 * 3da -W (mono EGA/mono VGA) feature control register
684 * (see PORT 03DAh-W for details; VGA, see PORT 03CAh-R)
685 */
vga_index_w(int data)686 void pc_t1t_device::vga_index_w(int data)
687 {
688 m_reg.index = data;
689 }
690
vga_data_w(int data)691 void pcvideo_t1000_device::vga_data_w(int data)
692 {
693 m_reg.data[m_reg.index] = data;
694
695 switch (m_reg.index)
696 {
697 case 0x00: /* mode control 1 */
698 break;
699 case 0x01: /* palette mask (bits 3-0) */
700 break;
701 case 0x02: /* border color (bits 3-0) */
702 break;
703 case 0x03: /* mode control 2 */
704 break;
705 case 0x04: /* reset register */
706 break;
707 /* palette array */
708 case 0x10: case 0x11: case 0x12: case 0x13:
709 case 0x14: case 0x15: case 0x16: case 0x17:
710 case 0x18: case 0x19: case 0x1a: case 0x1b:
711 case 0x1c: case 0x1d: case 0x1e: case 0x1f:
712 m_reg.data[m_reg.index] = data & 0x0F;
713 break;
714 }
715 }
716
717
pc_pcjr_vga_data_w(int data)718 void pcvideo_pcjr_device::pc_pcjr_vga_data_w(int data)
719 {
720 m_reg.data[m_reg.index] = data;
721
722 switch (m_reg.index)
723 {
724 case 0x00: /* mode control 1 */
725 /* bit0 - 0 = low bandwidth, 1 = high bandwidth */
726 /* bit1 - 0 = alpha, 1 = graphics */
727 /* bit2 - 0 = color, 1 = b/w */
728 /* bit3 - 0 = video disable, 1 = video enable */
729 /* bit4 - 1 = 16 color graphics */
730 pc_pcjr_mode_switch();
731 break;
732 case 0x01: /* palette mask (bits 3-0) */
733 break;
734 case 0x02: /* border color (bits 3-0) */
735 break;
736 case 0x03: /* mode control 2 */
737 /* bit1 - 1 = enable blink */
738 /* bit3 - 1 = 2 color graphics */
739 pc_pcjr_mode_switch();
740 break;
741 case 0x04: /* reset register */
742 break;
743 /* palette array */
744 case 0x10: case 0x11: case 0x12: case 0x13:
745 case 0x14: case 0x15: case 0x16: case 0x17:
746 case 0x18: case 0x19: case 0x1a: case 0x1b:
747 case 0x1c: case 0x1d: case 0x1e: case 0x1f:
748 m_reg.data[m_reg.index] = data & 0x0F;
749 break;
750 }
751 }
752
753
vga_data_r()754 int pc_t1t_device::vga_data_r()
755 {
756 int data = m_reg.data[m_reg.index];
757
758 switch (m_reg.index)
759 {
760 case 0x00: /* mode control 1 */
761 break;
762 case 0x01: /* palette mask (bits 3-0) */
763 break;
764 case 0x02: /* border color (bits 3-0) */
765 break;
766 case 0x03: /* mode control 2 */
767 break;
768 case 0x04: /* reset register */
769 break;
770 /* palette array */
771 case 0x10: case 0x11: case 0x12: case 0x13:
772 case 0x14: case 0x15: case 0x16: case 0x17:
773 case 0x18: case 0x19: case 0x1a: case 0x1b:
774 case 0x1c: case 0x1d: case 0x1e: case 0x1f:
775 break;
776 }
777 return data;
778 }
779
780 /*
781 * 3df RW display bank, access bank, mode
782 * bit 0-2 Identifies the page of main memory being displayed in units of 16K.
783 * 0: 0K, 1: 16K...7: 112K. In 32K modes (bits 6-7 = 2) only 0,2,4 and
784 * 6 are valid, as the next page will also be used.
785 * 3-5 Identifies the page of main memory that can be read/written at B8000h
786 * in units of 16K. 0: 0K, 1: 16K...7: 112K. In 32K modes (bits 6-7 = 2)
787 * only 0,2,4 and 6 are valid, as the next page will also be used.
788 * 6-7 Display mode. 0: Text, 1: 16K graphics mode (4,5,6,8)
789 * 2: 32K graphics mode (9,Ah)
790 */
bank_w(int data)791 void pcvideo_t1000_device::bank_w(int data)
792 {
793 int dram, vram;
794 if ((data&0xc0)==0xc0) /* needed for lemmings */
795 {
796 dram = (m_bank & 0x06);// | ((m_bank & 0x1800) >> 8);
797 vram = ((m_bank & 0x30) >> 3);// | ((m_bank & 0x6000) >> 10);
798 }
799 else
800 {
801 dram = (m_bank & 0x07);// | ((m_bank & 0x1800) >> 8);
802 vram = ((m_bank & 0x38) >> 3);// | ((m_bank & 0x6000) >> 10);
803 }
804 m_displayram = m_ram->pointer() + (dram << 14);
805 if(m_disable)
806 return;
807 m_vram->set_bank(vram);
808 if((m_bank & 0xc0) != (data & 0xc0))
809 mode_switch();
810 }
811
812
pc_pcjr_bank_w(int data)813 void pcvideo_pcjr_device::pc_pcjr_bank_w(int data)
814 {
815 int dram, vram;
816 m_bank = data;
817 /* it seems the video ram is mapped to the last 128K of main memory */
818 if ((data&0xc0)==0xc0) /* needed for lemmings */
819 {
820 dram = (data & 0x06);
821 vram = (data & 0x30) >> 3;
822 }
823 else
824 {
825 dram = (data & 0x07);
826 vram = (data & 0x38) >> 3;
827 }
828 m_vram->set_bank(vram);
829 m_displayram = m_ram->pointer() + (dram << 14);
830 if((m_bank & 0xc0) != (data & 0xc0))
831 pc_pcjr_mode_switch();
832 }
833
pc_pcjx_bank_w(int data)834 void pcvideo_pcjr_device::pc_pcjx_bank_w(int data)
835 {
836 int dram, vram;
837 m_bank = data;
838 if ((data&0xc0)==0xc0) /* needed for lemmings */
839 {
840 dram = (data & 0x06);
841 vram = (data & 0x30) >> 3;
842 }
843 else
844 {
845 dram = (data & 0x07);
846 vram = (data & 0x38) >> 3;
847 }
848 m_vram->set_bank(vram);
849 /* this certainly isn't correct but otherwise the memory test stomps on the vram */
850 m_displayram = (uint8_t *)memshare(":vram")->ptr() + (dram << 14);
851 if((m_bank & 0xc0) != (data & 0xc0))
852 pc_pcjr_mode_switch();
853 }
854
bank_r()855 int pc_t1t_device::bank_r()
856 {
857 return m_bank;
858 }
859
860 /*************************************************************************
861 *
862 * T1T
863 * Tandy 1000 / PCjr
864 *
865 *************************************************************************/
866
write(offs_t offset,uint8_t data)867 void pcvideo_t1000_device::write(offs_t offset, uint8_t data)
868 {
869 switch( offset )
870 {
871 case 0: case 2: case 4: case 6:
872 m_mc6845->address_w(data);
873 break;
874 case 1: case 3: case 5: case 7:
875 m_mc6845->register_w(data);
876 break;
877 case 8:
878 mode_control_w(data);
879 break;
880 case 9:
881 color_select_w(data);
882 break;
883 case 10:
884 vga_index_w(data);
885 break;
886 case 11:
887 lightpen_strobe_w(data);
888 break;
889 case 12:
890 break;
891 case 13:
892 m_bank = (data << 8) | (m_bank & 0xff);
893 bank_w(m_bank);
894 break;
895 case 14:
896 vga_data_w(data);
897 break;
898 case 15:
899 m_bank = (m_bank & 0xff00) | data;
900 bank_w(data);
901 break;
902 }
903 }
904
write(offs_t offset,uint8_t data)905 void pcvideo_pcjr_device::write(offs_t offset, uint8_t data)
906 {
907 switch( offset )
908 {
909 case 0: case 4:
910 m_mc6845->address_w(data);
911 break;
912 case 1: case 5:
913 m_mc6845->register_w(data);
914 break;
915 case 10:
916 if ( m_address_data_ff & 0x01 )
917 {
918 pc_pcjr_vga_data_w( data );
919 }
920 else
921 {
922 vga_index_w( data );
923 }
924 m_address_data_ff ^= 0x01;
925 break;
926 case 11:
927 lightpen_strobe_w(data);
928 break;
929 case 12:
930 break;
931 case 15:
932 if(m_jxkanji)
933 pc_pcjx_bank_w(data);
934 else
935 pc_pcjr_bank_w(data);
936 break;
937
938 default:
939 break;
940 }
941 }
942
943
read(offs_t offset)944 uint8_t pc_t1t_device::read(offs_t offset)
945 {
946 int data = 0xff;
947
948 switch( offset )
949 {
950 case 0: case 2: case 4: case 6:
951 /* return last written mc6845 address value here? */
952 break;
953
954 case 1: case 3: case 5: case 7:
955 data = m_mc6845->register_r();
956 break;
957
958 case 8:
959 data = mode_control_r();
960 break;
961
962 case 9:
963 data = color_select_r();
964 break;
965
966 case 10:
967 m_address_data_ff = 0;
968 data = status_r();
969 break;
970
971 case 11:
972 /* -W lightpen strobe reset */
973 break;
974
975 case 12:
976 case 13:
977 break;
978
979 case 14:
980 data = vga_data_r();
981 break;
982
983 case 15:
984 data = bank_r();
985 break;
986 }
987 return data;
988 }
989
WRITE_LINE_MEMBER(pc_t1t_device::t1000_de_changed)990 WRITE_LINE_MEMBER( pc_t1t_device::t1000_de_changed )
991 {
992 m_display_enable = state ? 1 : 0;
993 }
994
995
WRITE_LINE_MEMBER(pcvideo_t1000_device::t1000_vsync_changed)996 WRITE_LINE_MEMBER( pcvideo_t1000_device::t1000_vsync_changed )
997 {
998 m_vsync = state ? 8 : 0;
999 if ( state )
1000 {
1001 m_pc_framecnt++;
1002 }
1003 }
1004
WRITE_LINE_MEMBER(pcvideo_t1000_device::disable_w)1005 WRITE_LINE_MEMBER( pcvideo_t1000_device::disable_w )
1006 {
1007 if(state)
1008 m_vram->set_bank(8);
1009 else
1010 bank_w(m_bank);
1011 m_disable = state ? true : false;
1012 }
1013
WRITE_LINE_MEMBER(pcvideo_pcjr_device::pcjr_vsync_changed)1014 WRITE_LINE_MEMBER( pcvideo_pcjr_device::pcjr_vsync_changed )
1015 {
1016 m_vsync = state ? 8 : 0;
1017 if ( state )
1018 {
1019 m_pc_framecnt++;
1020 }
1021 m_pic8259->ir5_w(state);
1022 }
1023