1 // license:BSD-3-Clause
2 // copyright-holders:Jonathan Gevaryahu
3 /***************************************************************************
4 
5         DEC VK100 'GIGI'
6 
7         12/05/2009 Skeleton driver.
8         28/07/2009 added Guru-readme(TM)
9         08/01/2012 Fleshed out driver.
10 
11         Todo:
12               * fix vector generator hardware enough to pass the startup self test
13                 the tests are described on page 6-5 thru 6-8 of the tech reference
14                 * hook up the bresenham DU/DVM/ERR stuff, currently only simple directional vectors work
15                 * hook up the vector and sync proms to the sync counter
16                 * figure out how the erase prom actually works at a hardware level
17                 * redump the vector prom, the first two bytes look bad
18               * figure out the correct meaning of systat b register - needed for communications selftest
19               * hook up smc com5016t baud generator to i8251 rx and tx clocks - begun
20 
21         Notes:
22               The directions for the DIR value are arranged, starting from the *
23               as the vector origin:
24                  3  2  1
25                   \ | /
26                    \|/
27                  4--*--0
28                    /|\
29                   / | \
30                  5  6  7
31 
32                The X and Y counters are techincally 12 bits long each, though
33                only the low 9 and 10 bits respectively are used for ram addressing.
34                The MSB bit of each counter does have a special purpose with
35                regards to the RAS/ERASE prom though, perhaps to detect an
36                underflow 000->FFF
37 
38  Tony DiCenzo, now the director of standards and architecture at Oracle, was on the team that developed the VK100
39  see http://startup.nmnaturalhistory.org/visitorstories/view.php?ii=79
40  Robert "Bob" C. Quinn was definitely lead engineer on the VT125
41  Robert "Bob" T. Collins was the lead engineer on the VK100
42  Pedro Ortiz (https://www.linkedin.com/pub/pedro-ortiz/16/68b/196) did the drafting for the enclosure and case
43 
44  The prototype name for the VK100 was 'SMAKY' (Smart Keyboard)
45 
46 ****************************************************************************/
47 /*
48 DEC VK100
49 DEC, 1982
50 
51 This is a VK100 terminal, otherwise known as a DEC Gigi graphics terminal.
52 There's a technical manual dated 1982 here:
53 http://web.archive.org/web/20091015205827/http://www.computer.museum.uq.edu.au/pdf/EK-VK100-TM-001%20VK100%20Technical%20Manual.pdf
54 Installation and owner's manual is at:
55 http://www.bitsavers.org/pdf/dec/terminal/gigi/EK-VK100-IN-002_GIGI_Terminal_Installation_and_Owners_Manual_Apr81.pdf
56 An enormous amount of useful info can be derived from the VT125 technical manual:
57 http://www.bitsavers.org/pdf/dec/terminal/vt100/EK-VT100-TM-003_VT100_Technical_Manual_Jul82.pdf starting on page 6-70, pdf page 316
58 And its schematics:
59 http://bitsavers.org/pdf/dec/terminal/vt125/MP01053_VT125_Mar82.pdf
60 
61 PCB Layout
62 ----------
63 
64 VK100 LOGICBOARD
65     |-------|    |---------|  |---------|    |-| |-| |-|  |-|
66 |---|-20 mA-|----|---EIA---|--|HARD-COPY|----|B|-|G|-|R|--|-|--DSW(8)--|
67 |                                                         BW           |
68 |                                                             POWER    |
69 |                 PR2                                                  |
70 |                           HD46505SP              4116 4116 4116 4116 |
71 |                                                                      |
72 |                                                  4116 4116 4116 4116 |
73 |      PR5        INTEL           ROM1                                 |
74 |         PR1 PR6 P8251A                           4116 4116 4116 4116 |
75 |                     45.6192MHz  ROM2  PR3                            |
76 |                                                  4116 4116 4116 4116 |
77 | 4116 4116 4116  INTEL           ROM3                                 |
78 |                 D8202A                                               |
79 | 4116 4116 4116       5.0688MHz  ROM4                       PR4       |
80 |                                                                      |
81 | 4116 4116       INTEL    SMC_5016T                            PIEZO  |
82 |                 D8085A                        IDC40   LM556   75452  |
83 |----------------------------------------------------------------------|
84 Notes:
85       ROM1 - TP-01 (C) DEC 23-031E4-00 (M) SCM91276L 8114
86       ROM2 - TP-01 (C) DEC 1980 23-017E4-00 MOSTEK MK36444N 8116
87       ROM3 - TP-01 (C) MICROSOFT 1979 23-018E4-00 MOSTEK MK36445N 8113
88       ROM4 - TP-01 (C) DEC 1980 23-190E2-00 P8316E AMD 35517 8117DPP
89 
90     LED meanings:
91     The LEDS on the vk100 (there are 7) are set up above the keyboard as:
92     Label: ON LINE   LOCAL     NO SCROLL BASIC     HARD-COPY L1        L2
93     Bit:   !d5       d5        !d4       !d3       !d2       !d1       !d0 (of port 0x68)
94 according to manual from http://www.bitsavers.org/pdf/dec/terminal/gigi/EK-VK100-IN-002_GIGI_Terminal_Installation_and_Owners_Manual_Apr81.pdf
95 where X = on, 0 = off, ? = variable (- = off)
96     - X 0 0 0 0 0 (0x1F) = Microprocessor error
97     X - 0 X X X X (0x30) "
98 
99     - X 0 0 0 0 X (0x1E) = ROM error
100     X - 0 0 ? ? ? (0x3x) "
101 1E 3F = rom error, rom 1 (0000-0fff)
102 1E 3E = rom error, rom 1 (1000-1fff)
103 1E 3D = rom error, rom 2 (2000-2fff)
104 1E 3C = rom error, rom 2 (3000-3fff)
105 1E 3B = rom error, rom 3 (4000-4fff)
106 1E 3A = rom error, rom 3 (5000-5fff)
107 1E 39 = rom error, rom 4 (6000-6fff)
108 
109     - X 0 0 0 X 0 (0x1D) = RAM error
110     X - 0 ? ? ? ? (0x3x) "
111 
112     - X 0 0 0 X X (0x1C) = CRT Controller error
113     X - 0 X X X X (0x30) "
114 This test writes 0xF to port 00 (crtc address reg) and writes a pattern to it
115 via port 01 (crtc data reg) then reads it back and checks to be sure the data
116 matches.
117 
118     - X 0 0 X 0 0 (0x1B) = CRT Controller time-out
119     X - 0 X X X X (0x30) "
120 This test writes 00 to all the crtc registers and checks to be sure an rst7.5
121 (vblank) interrupt fires on the 8085 within a certain time period.
122 
123     - X 0 0 X 0 X (0x1A) = Vector time-out error
124     X - 0 X X X X (0x30) "
125 Not sure exactly what this tests, likely tries firing the vector generator
126 state machine and sees if the GO bit ever finishes and goes back to 0
127 */
128 #include "emu.h"
129 
130 #include "bus/rs232/rs232.h"
131 #include "cpu/i8085/i8085.h"
132 #include "sound/beep.h"
133 #include "video/mc6845.h"
134 #include "machine/com8116.h"
135 #include "machine/i8251.h"
136 
137 #include "screen.h"
138 #include "speaker.h"
139 
140 #include "vk100.lh"
141 
142 
143 // named timer IDs
144 #define TID_I8251_RX 1
145 #define TID_I8251_TX 2
146 #define TID_SYNC 3
147 
148 // show messages related to writes to the 0x4x VG registers
149 #undef VG40_VERBOSE
150 // show messages related to writes to the 0x6x VG registers
151 #undef VG60_VERBOSE
152 // show messages related to LED/beeper writes
153 #undef LED_VERBOSE
154 // show messages related to KYBD writes
155 #undef KBD_VERBOSE
156 // debug the pattern reg
157 #undef PAT_DEBUG
158 // show reads from the two systat registers
159 #undef SYSTAT_A_VERBOSE
160 #undef SYSTAT_B_VERBOSE
161 
162 // debug state dump for the vector generator
163 #undef DEBUG_VG_STATE
164 
165 #define RS232_TAG       "rs232"
166 #define COM5016T_TAG    "com5016t"
167 
168 class vk100_state : public driver_device
169 {
170 public:
vk100_state(const machine_config & mconfig,device_type type,const char * tag)171 	vk100_state(const machine_config &mconfig, device_type type, const char *tag) :
172 		driver_device(mconfig, type, tag),
173 		m_maincpu(*this, "maincpu"),
174 		m_crtc(*this, "crtc"),
175 		m_speaker(*this, "beeper"),
176 		m_uart(*this, "i8251"),
177 		//m_i8251_rx_timer(nullptr),
178 		//m_i8251_tx_timer(nullptr),
179 		//m_sync_timer(nullptr),
180 
181 		m_capsshift(*this, "CAPSSHIFT"),
182 		m_dipsw(*this, "SWITCHES"),
183 		m_online_led(*this, "online_led"),
184 		m_local_led(*this, "local_led"),
185 		m_noscroll_led(*this, "noscroll_led"),
186 		m_basic_led(*this, "basic_led"),
187 		m_hardcopy_led(*this, "hardcopy_led"),
188 		m_l1_led(*this, "l1_led"),
189 		m_l2_led(*this, "l2_led")
190 	{
191 	}
192 
193 	void vk100(machine_config &config);
194 
195 	void init_vk100();
196 
197 private:
198 	enum
199 	{
200 		TIMER_EXECUTE_VG
201 	};
202 
203 	required_device<cpu_device> m_maincpu;
204 	required_device<mc6845_device> m_crtc;
205 	required_device<beep_device> m_speaker;
206 	required_device<i8251_device> m_uart;
207 	//required_device<> m_i8251_rx_timer;
208 	//required_device<> m_i8251_tx_timer;
209 	//required_device<> m_sync_timer;
210 
211 	required_ioport m_capsshift;
212 	required_ioport m_dipsw;
213 
214 	output_finder<> m_online_led;
215 	output_finder<> m_local_led;
216 	output_finder<> m_noscroll_led;
217 	output_finder<> m_basic_led;
218 	output_finder<> m_hardcopy_led;
219 	output_finder<> m_l1_led;
220 	output_finder<> m_l2_led;
221 
222 	uint8_t* m_vram;
223 	uint8_t* m_trans;
224 	uint8_t* m_pattern;
225 	uint8_t* m_dir;
226 	uint8_t* m_sync;
227 	uint8_t* m_vector;
228 	uint8_t* m_ras_erase;
229 	uint8_t m_dir_a6; // latched a6 of dir rom
230 	uint8_t m_cout; // carry out from vgERR adder
231 	uint8_t m_vsync; // vsync pin of crtc
232 	uint16_t m_vgX; // 12 bit X value for vector draw position
233 	uint16_t m_vgY; // 12 bit Y value for vector draw position
234 	uint16_t m_vgERR; // error register can cause carries which need to be caught
235 	uint8_t m_vgSOPS;
236 	uint8_t m_vgPAT;
237 	uint16_t m_vgPAT_Mask; // current mask for PAT
238 	uint8_t m_vgPMUL; // reload value for PMUL_Count
239 	uint8_t m_vgPMUL_Count;
240 	uint8_t m_vgDownCount; // down counter = number of pixels, loaded from vgDU on execute
241 #define VG_DU m_vgRegFile[0]
242 #define VG_DVM m_vgRegFile[1]
243 #define VG_DIR m_vgRegFile[2]
244 #define VG_WOPS m_vgRegFile[3]
245 	uint8_t m_vgRegFile[4];
246 	uint8_t m_VG_MODE; // 2 bits, latched on EXEC
247 	uint8_t m_vgGO; // activated on next SYNC pulse after EXEC
248 	uint8_t m_ACTS;
249 	uint8_t m_ADSR;
250 	ioport_port* m_col_array[16];
251 
252 	void vgLD_X(offs_t offset, uint8_t data);
253 	void vgLD_Y(offs_t offset, uint8_t data);
254 	void vgERR(uint8_t data);
255 	void vgSOPS(uint8_t data);
256 	void vgPAT(uint8_t data);
257 	void vgPMUL(uint8_t data);
258 	void vgREG(offs_t offset, uint8_t data);
259 	void vgEX(offs_t offset, uint8_t data);
260 	void KBDW(uint8_t data);
261 	uint8_t vk100_keyboard_column_r(offs_t offset);
262 	uint8_t SYSTAT_A(offs_t offset);
263 	uint8_t SYSTAT_B();
264 
265 	virtual void machine_start() override;
266 	virtual void video_start() override;
267 	TIMER_CALLBACK_MEMBER(execute_vg);
268 	DECLARE_WRITE_LINE_MEMBER(crtc_vsync);
269 	DECLARE_WRITE_LINE_MEMBER(i8251_rxrdy_int);
270 	DECLARE_WRITE_LINE_MEMBER(i8251_txrdy_int);
271 	DECLARE_WRITE_LINE_MEMBER(i8251_rts);
272 	uint8_t vram_read();
273 	uint8_t vram_attr_read();
274 	MC6845_UPDATE_ROW(crtc_update_row);
275 	void vram_write(uint8_t data);
276 
277 	void vk100_io(address_map &map);
278 	void vk100_mem(address_map &map);
279 
280 	virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
281 };
282 
283 // vram access functions:
284 	/* figure out vram address based on tech manual page 5-24:
285 	 * real address to 16-bit chunk a13 a12 | a11 a10 a9  a8 | a7  a6  a5  a4 | a3  a2  a1  a0
286 	 * X+Y input                    Y8  Y7  | Y6  Y5  Y4  Y3 | Y2  Y1  X9' X8'| X7' X6' X5' X4'
287 	 *          X3' and X2' choose a 4-bit block, X1 and X0 choose a bit within that.
288 	 * Figure out the ram address in address space "vram" based on this:
289 	 * vram is 0x8000 long (0x4000 16-bit blocks in sequence)
290 	 * so:
291 	 * vram: a14 a13 a12 | a11 a10 a9  a8 | a7  a6  a5  a4 | a3  a2  a1  a0
292 	 * vg:   Y8  Y7  Y6  | Y5  Y4  Y3  Y2 | Y1  X9' X8' X7'| X6' X5' X4'(x3') x2' x1 x0
293 	 *     X3' is handled by the nybbleNum statement, as is X2'
294 	 *     X1 and X0 are handled by the pattern rom directly:
295 	 *     x0 -> a0, x1 -> a1
296 	 *     this handles bits like:
297 	 *     x1 x0
298 	 *      0  0 -> bit 0
299 	 *      0  1 -> bit 1
300 	 *      1  0 -> bit 2
301 	 *      1  1 -> bit 3
302 	 */
303 
304 // returns one nybble from vram array based on X and Y regs
vram_read()305 uint8_t vk100_state::vram_read()
306 {
307 	// XFinal is (X'&0x3FC)|(X&0x3)
308 	uint16_t XFinal = m_trans[(m_vgX&0x3FC)>>2]<<2|(m_vgX&0x3); // appears correct
309 	// EA is the effective ram address for a 16-bit block
310 	uint16_t EA = ((m_vgY&0x1FE)<<5)|(XFinal>>4); // appears correct
311 	// block is the 16 bit block directly (note EA has to be <<1 to correctly index a byte)
312 	uint16_t block = m_vram[(EA<<1)+1] | (m_vram[(EA<<1)]<<8);
313 	// nybbleNum is which of the four nybbles within the block to address. should NEVER be 3!
314 	uint8_t nybbleNum = (XFinal&0xC)>>2;
315 	return (block>>(4*nybbleNum))&0xF;
316 }
317 
318 // returns the attribute nybble for the current pixel based on X and Y regs
vram_attr_read()319 uint8_t vk100_state::vram_attr_read()
320 {
321 	// XFinal is (X'&0x3FC)|(X&0x3)
322 	uint16_t XFinal = m_trans[(m_vgX&0x3FC)>>2]<<2|(m_vgX&0x3); // appears correct
323 	// EA is the effective ram address for a 16-bit block
324 	uint16_t EA = ((m_vgY&0x1FE)<<5)|(XFinal>>4); // appears correct
325 	// block is the 16 bit block directly (note EA has to be <<1 to correctly index a byte)
326 	uint16_t block = m_vram[(EA<<1)+1] | (m_vram[(EA<<1)]<<8);
327 	// nybbleNum is the attribute nybble, which in this case is always 3
328 	uint8_t nybbleNum = 3;
329 	return (block>>(4*nybbleNum))&0xF;
330 }
331 
332 // writes one nybble to vram array based on X and Y regs, and updates the attrib ram if needed
vram_write(uint8_t data)333 void vk100_state::vram_write(uint8_t data)
334 {
335 	// XFinal is (X'&0x3FC)|(X&0x3)
336 	uint16_t XFinal = m_trans[(m_vgX&0x3FC)>>2]<<2|(m_vgX&0x3); // appears correct
337 	// EA is the effective ram address for a 16-bit block
338 	uint16_t EA = ((m_vgY&0x1FE)<<5)|(XFinal>>4); // appears correct
339 	// block is the 16 bit block directly (note EA has to be <<1 to correctly index a byte)
340 	uint16_t block = m_vram[(EA<<1)+1] | (m_vram[(EA<<1)]<<8);
341 	// nybbleNum is which of the four nybbles within the block to address. should NEVER be 3!
342 	uint8_t nybbleNum = (XFinal&0xC)>>2;
343 	block &= ~((uint16_t)0xF<<(nybbleNum*4)); // mask out the part we want to replace
344 	block |= data<<(nybbleNum*4); // write the new part
345 	// NOTE: this next part may have to be made conditional on VG_MODE
346 	// check if the attribute nybble is supposed to be modified, and if so do so
347 	if (VG_WOPS&0x08) block = (block&0x0FFF)|(((uint16_t)VG_WOPS&0xF0)<<8);
348 	m_vram[(EA<<1)+1] = block&0xFF; // write block back to vram
349 	m_vram[(EA<<1)] = (block&0xFF00)>>8; // ''
350 }
351 
device_timer(emu_timer & timer,device_timer_id id,int param,void * ptr)352 void vk100_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
353 {
354 	switch (id)
355 	{
356 	case TIMER_EXECUTE_VG:
357 		execute_vg(ptr, param);
358 		break;
359 	default:
360 		throw emu_fatalerror("Unknown id in vk100_state::device_timer");
361 	}
362 }
363 
364 /* this is the "DIRECTION ROM"  == mb6309 (256x8, 82s135)
365  * see figure 5-24 on page 5-39
366  * It tells the direction and enable for counting on the X and Y counters
367  * and also handles the non-math related parts of the bresenham line algorithm
368  * control bits:
369  *            /CE1 ----- DCOUNT 0 H [verified via tracing]
370  *            /CE2 ----- ENA ERROR L [verified via tracing]
371  * addr bits: 76543210
372  *            ||||\\\\-- DIR (vgDIR register low 4 bits)
373  *            |||\------ C OUT aka ERROR CARRY (strobed in by STROBE L from the error counter's adder) [verified via tracing]
374  *            ||\------- Y0 (the otherwise unused lsb of the Y register, used for bresenham) [verified via tracing]
375  *            |\-------- feedback bit from d5 strobed by V CLK [verified via tracing]
376  *            \--------- GND; the second half of the prom is blank (0x00)
377  * data bits: 76543210
378  *            |||||||\-- ENA Y (enables change on Y counter)
379  *            ||||||\--- ENA X (enables change on X counter)
380  *            |||||\---- Y DIRECTION (high is count down, low is count up)
381  *            ||||\----- X DIRECTION (high is count down, low is count up)
382  *            |||\------ PIXEL WRT
383  *            ||\------- feedback bit to a6, this bit is held in PRESET/1 condition by GO being inactive, and if the vector prom is disabled it is pulled to 1 [verified via tracing and schematics]
384  *            |\-------- UNUSED, always 0
385  *            \--------- UNUSED, always 0
386  * The VT125 prom @ E41 is literally identical to this, the same exact part: 23-059B1
387  */
TIMER_CALLBACK_MEMBER(vk100_state::execute_vg)388 TIMER_CALLBACK_MEMBER(vk100_state::execute_vg)
389 {
390 	m_cout = 1; // hack for now
391 	uint8_t dirbyte = m_dir[(m_dir_a6<<6)|((m_vgY&1)<<5)|(m_cout<<4)|VG_DIR];
392 #ifdef DEBUG_VG_STATE
393 	static const char *const vg_functions[] = { "Move", "Dot", "Vector", "Erase" };
394 	fprintf(stderr, "VGMODE: %s; DIR: A:%02x; D:%02x; X: %03X; Y: %03X; DownCount: %02X\n", vg_functions[m_VG_MODE], ((m_dir_a6<<6)|((m_vgY&1)<<5)|(m_cout<<4)|VG_DIR), dirbyte, m_vgX, m_vgY, m_vgDownCount);
395 #endif
396 	m_dir_a6 = m_vgGO?((dirbyte&0x20)>>5):1;
397 	if (dirbyte&2) // ena_x is active
398 	{
399 		if (dirbyte&0x80) m_vgX--;
400 		else m_vgX++;
401 	}
402 	if (dirbyte&1) // ena_y is active
403 	{
404 		if (dirbyte&0x40) m_vgY--;
405 		else m_vgY++;
406 	}
407 	if (dirbyte&0x10) m_vgDownCount--; // decrement the down counter
408 	uint8_t thisNyb = vram_read(); // read in the nybble
409 	// pattern rom addressing is a complex mess. see the pattern rom def later in this file.
410 	uint8_t newNyb = m_pattern[((m_vgPAT&m_vgPAT_Mask)?0x200:0)|((VG_WOPS&7)<<6)|((m_vgX&3)<<4)|thisNyb]; // calculate new nybble based on pattern rom
411 	// finally write the block back to ram depending on the VG_MODE (sort of a hack until we get the vector and sync and dir roms all hooked up)
412 	// but only do it if the direction rom said so!
413 	switch (m_VG_MODE)
414 	{
415 		case 0: // move; adjusts the x and y but doesn't write anything. do nothing
416 			break;
417 		case 1: // dot: only write the LAST pixel in the chain? TODO: some fallthrough magic here?
418 			if ((m_vgDownCount) == 0x00)
419 			{
420 				if (dirbyte&0x10) vram_write(newNyb); // write out the modified nybble
421 			}
422 			break;
423 		case 2: // vec: draw the vector
424 				if (dirbyte&0x10) vram_write(newNyb); // write out the modified nybble
425 			break;
426 		case 3: // er: erase: special case here: wipe the entire screen (except for color/attrib?) and then set done.
427 			for (int i = 0; i < 0x8000; i++)
428 			{
429 				if (!(i&1)) // avoid stomping attribute
430 					m_vram[i] = m_vram[i]&0xF0;
431 				else // (i&1)
432 					m_vram[i] = 0;
433 			}
434 			m_vgGO = 0; // done
435 			break;
436 	}
437 	if ((m_vgDownCount) == 0x00) m_vgGO = 0; // check if the down counter hit terminal count (0), if so we're done.
438 	if (((++m_vgPMUL_Count)&0xF)==0) // if pattern multiplier counter overflowed
439 	{
440 		m_vgPMUL_Count = m_vgPMUL; // reload counter
441 		m_vgPAT_Mask >>= 1; // shift the mask
442 		if (m_vgPAT_Mask == 0) m_vgPAT_Mask = 0x80; // reset mask if it hits 0
443 	}
444 	if (m_vgGO) timer_set(attotime::from_hz(XTAL(45'619'200)/3/12/2), TIMER_EXECUTE_VG); // /3/12/2 is correct. the sync counter is clocked by the dot clock, despite the error on figure 5-21
445 }
446 
447 /* ports 0x40 and 0x41: load low and high bytes of vector gen X register */
vgLD_X(offs_t offset,uint8_t data)448 void vk100_state::vgLD_X(offs_t offset, uint8_t data)
449 {
450 	m_vgX &= 0xFF << ((1-offset)*8);
451 	m_vgX |= ((uint16_t)data) << (offset*8);
452 #ifdef VG40_VERBOSE
453 	logerror("VG: 0x%02X: X Reg loaded with %04X, new X value is %04X\n", 0x40+offset, ((uint16_t)data) << (offset*8), m_vgX);
454 #endif
455 }
456 
457 /* ports 0x42 and 0x43: load low and high bytes of vector gen Y register */
vgLD_Y(offs_t offset,uint8_t data)458 void vk100_state::vgLD_Y(offs_t offset, uint8_t data)
459 {
460 	m_vgY &= 0xFF << ((1-offset)*8);
461 	m_vgY |= ((uint16_t)data) << (offset*8);
462 #ifdef VG40_VERBOSE
463 	logerror("VG: 0x%02X: Y Reg loaded with %04X, new Y value is %04X\n", 0x42+offset, ((uint16_t)data) << (offset*8), m_vgY);
464 #endif
465 }
466 
467 /* port 0x44: "ERR" load bresenham line algorithm 'error' count */
vgERR(uint8_t data)468 void vk100_state::vgERR(uint8_t data)
469 {
470 	m_vgERR = data;
471 #ifdef VG40_VERBOSE
472 	logerror("VG: 0x44: ERR Reg loaded with %02X\n", m_vgERR);
473 #endif
474 }
475 
476 /* port 0x45: "SOPS" screen options
477  * (handled by 74LS273 @ E55, schematic sheet 10, all signals called 'VVG1 BDx' where x is 7 to 0)
478  * Blink   --Background color--    Blink   Serial  Serial  Reverse
479  * Enable  Green   Red     Blue    Control SL1     SL0     BG/FG
480  * d7      d6      d5      d4      d3      d2      d1      d0
481  * apparently, SLx: 00 = rs232/eia(J6), 01 = 20ma(J1), 10 = hardcopy(J7), 11 = test/loopback
482  * Serial Select (SLx) routing controls are rather complex, shown on schematic
483  * page 9:
484  * VDC2    |  I8251 pins                                                      |  SYSTAT_B bits
485  * SL1 SL0 |  8251RXD   8251RTS    8251TXD    8251/DTR    8251/DSR    8251CTS |  SYSTATB_ACTS   SYSTATB_ADSR
486  * 0   0      J6 /RXD   J6 /RTS    J6 TXD     J6 /DTR     J7 URTS     GND        J6 /CTS        J6 /DSR
487  * 0   1      J1 +-R    ACTS(loop) J1 +-T     J6 /DTR     J7 URTS     GND        8251RTS(loop)  J6 /DSR
488  * 1   0      J7 DRXD   J7 DRTS*   J7 DTXD    J6 /DTR     J7 URTS     GND        J7 /DCTS       J6 /DSR
489  * 1   1      8251TXD   ACTS(loop) 8251RXD    J6 /DTR     J7 URTS     GND        8251RTS(loop)  J6 /DSR
490  *                      * and UCTS, the pin drives both pins on J7
491  */
vgSOPS(uint8_t data)492 void vk100_state::vgSOPS(uint8_t data)
493 {
494 	m_vgSOPS = data;
495 #ifdef VG40_VERBOSE
496 	static const char *const serialDest[4] = { "EIA232", "20ma", "Hardcopy", "Loopback/test" };
497 	logerror("VG: 0x45: SOPS Reg loaded with %02X: Background KGRB: %d%d%d%d, Blink: %d, Serial select: %s, Reverse BG/FG: %d\n", m_vgSOPS, (m_vgSOPS>>7)&1, (m_vgSOPS>>6)&1, (m_vgSOPS>>5)&1, (m_vgSOPS>>4)&1, (m_vgSOPS>>3)&1, serialDest[(m_vgSOPS>>1)&3], m_vgSOPS&1);
498 #endif
499 }
500 
501 /* port 0x46: "PAT" load vg Pattern register */
vgPAT(uint8_t data)502 void vk100_state::vgPAT(uint8_t data)
503 {
504 	m_vgPAT = data;
505 #ifdef PAT_DEBUG
506 	for (int i = 7; i >= 0; i--)
507 	{
508 		printf("%s", (data&(1<<i))?"X":".");
509 	}
510 	printf("\n");
511 #endif
512 #ifdef VG40_VERBOSE
513 	logerror("VG: 0x46: PAT Reg loaded with %02X\n", m_vgPAT);
514 #endif
515 }
516 
517 /* port 0x47: "PMUL" load vg Pattern Multiply Register
518    The pattern multiply register loads a counter which counts reads from
519    the pattern register and increments on each one. if it overflows from
520    1111 to 0000 the pattern register is shifted right one bit and the
521    counter is reloaded from PMUL */
vgPMUL(uint8_t data)522 void vk100_state::vgPMUL(uint8_t data)
523 {
524 	m_vgPMUL = data;
525 #ifdef VG40_VERBOSE
526 	logerror("VG: 0x47: PMUL Reg loaded with %02X\n", m_vgPMUL);
527 #endif
528 }
529 
530 /* port 0x60: "DU" load vg vector major register */
531 /* port 0x61: "DVM" load vg vector minor register */
532 /* port 0x62: "DIR" load vg Direction register */
533 /* port 0x63: "WOPS" vector 'pixel' write options
534  * --Attributes to change --   Enable --  Functions --
535  * Blink  Green  Red    Blue   Attrib F1     F0     FN
536  *                             Change
537  * d7     d6     d5     d4     d3     d2     d1     d0
538  */
vgREG(offs_t offset,uint8_t data)539 void vk100_state::vgREG(offs_t offset, uint8_t data)
540 {
541 	m_vgRegFile[offset] = data;
542 #ifdef VG60_VERBOSE
543 	static const char *const regDest[4] = { "DU", "DVM", "DIR", "WOPS" };
544 	static const char *const wopsFunctions[] = { "Overlay", "Replace", "Complement", "Erase" };
545 	if (offset < 3) logerror("VG: 0x%02x: %s Reg loaded with %02X\n", (0x60+offset), regDest[offset], m_vgRegFile[offset]);
546 	else logerror("VG: 0x63: WOPS Reg loaded with %02X: KGRB %d%d%d%d, AttrChange %d, Function %s, Negate %d\n", data, (VG_WOPS>>7)&1, (VG_WOPS>>6)&1, (VG_WOPS>>5)&1, (VG_WOPS>>4)&1, (VG_WOPS>>3)&1, wopsFunctions[(VG_WOPS>>1)&3], VG_WOPS&1);
547 #endif
548 }
549 
550 
551 /* port 0x64: "EX MOV" execute a move (relative move of x and y using du/dvm/dir/err, no writing) */
552 /* port 0x65: "EX DOT" execute a dot (draw a dot at x,y?) */
553 /* port 0x66: "EX VEC" execute a vector (draw a vector from x,y to a destination using du/dvm/dir/err ) */
554 /* port 0x67: "EX ER" execute an erase (clear the screen to the bg color, i.e. fill vram with zeroes) */
vgEX(offs_t offset,uint8_t data)555 void vk100_state::vgEX(offs_t offset, uint8_t data)
556 {
557 #ifdef VG60_VERBOSE
558 	static const char *const ex_functions[] = { "Move", "Dot", "Vector", "Erase" };
559 	logerror("VG Execute %s 0x%02X written with %d\n", ex_functions[offset&3], 0x67+offset, data);
560 	//fprintf(stderr, "VG Execute %s 0x%02X written with %d\n", ex_functions[offset&3], 0x67+offset, data);
561 #endif
562 	m_vgPMUL_Count = m_vgPMUL; // load PMUL_Count
563 	m_vgPAT_Mask = 0x80;
564 	m_vgDownCount = VG_DU; // set down counter to length of major vector
565 	m_VG_MODE = offset&3;
566 	m_vgGO = 1;
567 	timer_set(attotime::zero, TIMER_EXECUTE_VG);
568 }
569 
570 
571 /* port 0x68: "KBDW" d7 is beeper, d6 is keyclick, d5-d0 are keyboard LEDS */
KBDW(uint8_t data)572 void vk100_state::KBDW(uint8_t data)
573 {
574 	m_online_led = BIT(data, 5) ? 1 : 0;
575 	m_local_led = BIT(data, 5) ? 0 : 1;
576 	m_noscroll_led = BIT(data, 4) ? 1 : 0;
577 	m_basic_led = BIT(data, 3) ? 1 : 0;
578 	m_hardcopy_led = BIT(data, 2) ? 1 : 0;
579 	m_l1_led = BIT(data, 1) ? 1 : 0;
580 	m_l2_led = BIT(data, 0) ? 1 : 0;
581 #ifdef LED_VERBOSE
582 	if (BIT(data, 6)) logerror("kb keyclick bit 6 set: not emulated yet (multivibrator)!\n");
583 #endif
584 	m_speaker->set_state(BIT(data, 7));
585 #ifdef LED_VERBOSE
586 	logerror("LED state: %02X: %s %s %s %s %s %s\n", data&0xFF, (data&0x20)?"------- LOCAL ":"ON LINE ----- ", (data&0x10)?"--------- ":"NO SCROLL ", (data&0x8)?"----- ":"BASIC ", (data&0x4)?"--------- ":"HARD-COPY ", (data&0x2)?"-- ":"L1 ", (data&0x1)?"-- ":"L2 ");
587 #endif
588 }
589 
590 /* port 0x6C: "BAUD" controls the smc com5016t dual baud generator which
591  * controls the divisors for the rx and tx clocks on the 8251 from the
592     5.0688Mhz cpu xtal.
593    It has 5v,12v on pins 2 and 9, pin 10 is NC.
594  * A later part that replaced this on the market is SMC COM8116(T)/8136(T), which
595     was a 5v-only part (pin 9 and 10 are NC, 10 is a clock out on the 8136.
596  *  Note that even on the SMC COM5016T version, SMC would allow the user
597      to mask their own dividers on custom ordered chips if desired.
598  *  The COM8116(T)/8136(T) came it at least 4 mask rom types meant for different
599      input clocks:
600      -000 or no mark for 5.0688Mhz (which exactly matches the table below) (synertek sy2661-3 also matches this exactly)
601      -003 is for 6.01835MHz
602      -005 is for 4.915200Mhz
603      -006 is for 5.0688Mhz but omits the 2000 baud entry, instead has 200,
604       and output frequencies are 2x as fast (meant for a 32X clock uart)
605      -013 is for 2.76480MHz
606      -013A is for 5.52960MHz
607      (several other unknown refclock masks appear on partscalper sites)
608     GI also made a clone of the 8116 5v chip called the AY-5-8116(T)/8136(T)
609      which had at least two masks: -000/no mark and -005, matching speeds above
610     WD made the WD1943 which is similarly 5v compatible, with -00, -05, -06 masks
611     The COM8046(T) has 5 bits for selection instead of 4, but still expects
612      a 5.0688MHz reference clock, and the second half of the table matches the
613      values below; the first half of the table is the values below /2, rounded
614      down (for uarts which need a clock rate of 32x baud instead of 16x).
615     WD's BR1941 is also functionally compatible but uses 5v,12v,-5v on pins 2,9,10
616  * The baud divisor lookup table has 16 entries, but only entries 2,5,6,7,A,C,E,F are documented/used in the vk100 tech manual
617  * The others are based on page 13 of http://www.hartetechnologies.com/manuals/Tarbell/Tarbell%20Z80%20CPU%20Board%20Model%203033.pdf
618  * D C B A   Divisor                                Expected Baud
619  * 0 0 0 0 - 6336 (5068800 / 6336 = 16*50         = 50 baud
620  * 0 0 0 1 - 4224 (5068800 / 4224 = 16*75)        = 75 baud
621  * 0 0 1 0 - 2880 (5068800 / 2880 = 16*110)       = 110 baud
622  * 0 0 1 1 - 2355 (5068800 / 2355 = 16*134.5223) ~= 134.5 baud
623  * 0 1 0 0 - 2112 (5068800 / 2112 = 16*150)       = 150 baud
624  * 0 1 0 1 - 1056 (5068800 / 1056 = 16*300)       = 300 baud
625  * 0 1 1 0 - 528  (5068800 / 528 = 16*600)        = 600 baud
626  * 0 1 1 1 - 264  (5068800 / 264 = 16*1200)       = 1200 baud
627  * 1 0 0 0 - 176  (5068800 / 176 = 16*1800)       = 1800 baud
628  * 1 0 0 1 - 158  (5068800 / 158 = 16*2005.0633) ~= 2000 baud
629  * 1 0 1 0 - 132  (5068800 / 132 = 16*2400)       = 2400 baud
630  * 1 0 1 1 - 88   (5068800 / 88 = 16*3600)        = 3600 baud
631  * 1 1 0 0 - 66   (5068800 / 66 = 16*4800)        = 4800 baud
632  * 1 1 0 1 - 44   (5068800 / 44 = 16*7200)        = 7200 baud
633  * 1 1 1 0 - 33   (5068800 / 33 = 16*9600)        = 9600 baud
634  * 1 1 1 1 - 16   (5068800 / 16 = 16*19800)      ~= 19200 baud
635  */
636 
637 /* port 0x40-0x47: "SYSTAT A"; various status bits, poorly documented in the tech manual
638  * /GO    VDM1   VDM1   VDM1   VDM1   Dip     RST7.5 GND***
639  *        BIT3   BIT2   BIT1   BIT0   Switch  VSYNC
640  * d7     d6     d5     d4     d3     d2      d1     d0
641   bit3, 2, 1, 0 are the 4 bits output from the VRAM 12->4 multiplexer
642    which are also inputs to the pattern rom; they are constantly updated
643    by the sync rom and related circuitry.
644   This is the only way the vram can be read by the cpu.
645   d7 is from the /Q output of the GO latch
646   d6,5,4,3 are from the 74ls298 at ic4 (right edge of pcb)
647   d2 is where the dipswitch values are read from, based on the offset
648   d1 is connected to 8085 rst7.5 (pin 7) and crtc pin 40 (VSYNC) [verified via tracing]
649   d0 is tied to GND [verified via tracing] but the schematics both tie it to GND
650      and call it LP FLAG, may be a leftover from development.
651 
652  31D reads and checks d7 in a loop
653  205 reads, xors with 0x55 (from reg D), ANDS result with 0x78 and branches if it is not zero (checking for bit pattern 1010?)
654  299 reads, rotates result right 3 times and ANDs the result with 0x0F
655  2A4 reads, rotates result left 1 time and ANDS the result with 0xF0
656 */
SYSTAT_A(offs_t offset)657 uint8_t vk100_state::SYSTAT_A(offs_t offset)
658 {
659 	uint8_t dipswitchLUT[8] = { 1,3,5,7,6,4,2,0 }; // the dipswitches map in a weird order to offsets
660 #ifdef SYSTAT_A_VERBOSE
661 	if (m_maincpu->pc() != 0x31D) logerror("0x%04X: SYSTAT_A Read!\n", m_maincpu->pc());
662 #endif
663 	return ((m_vgGO?0:1)<<7)|(vram_read()<<3)|(((m_dipsw->read()>>dipswitchLUT[offset])&1)?0x4:0)|(m_vsync?0x2:0);
664 }
665 
666 /* port 0x48: "SYSTAT B"; NOT documented in the tech manual at all.
667  * when in loopback/test mode, SYSTAT_B is read and expected the following, around 0x606:
668  * reset 8751, modewrite of 0x5E
669  * write command -> 0x20 (normal, normal, /RTS is 0, normal, normal, receive off, /DTR is 1, transmit off)
670  * read SYSTAT B (and xor with 0xe), expect d7 to be CLEAR or jump to error
671  * write command -> 0x05 (normal, normal, /RTS is 1, normal, normal, receive ON, /DTR is 0, transmit off)
672  * read SYSTAT B (and xor with 0xe), expect d7 to be SET or jump to error
673  * after this it does something and waits for an rxrdy interrupt
674 
675  shows the results of:
676  * ACTS (/CTS)  ADSR (/DSR)  GND    GND    ATTR3  ATTR2  ATTR1  ATTR0
677  * d7           d6           d5     d4     d3     d2     d1     d0
678  * the ACTS (inverse of DCTS) signal lives in one of these bits (see 5-62)
679  * it XORs the read of systat_b with the E register (which holds 0x6)
680  * and checks the result
681  * The 4 attribute ram bits for the cell being pointed at by the X and Y regs are readable as the low nybble.
682  * The DSR pin is readable as bit 6.
683  */
SYSTAT_B()684 uint8_t vk100_state::SYSTAT_B()
685 {
686 #ifdef SYSTAT_B_VERBOSE
687 	logerror("0x%04X: SYSTAT_B Read!\n", m_maincpu->pc());
688 #endif
689 	return (m_ACTS<<7)|(m_ADSR<<6)|vram_attr_read();
690 }
691 
vk100_keyboard_column_r(offs_t offset)692 uint8_t vk100_state::vk100_keyboard_column_r(offs_t offset)
693 {
694 	uint8_t code = m_col_array[offset&0xF]->read() | m_capsshift->read();
695 #ifdef KBD_VERBOSE
696 	logerror("Keyboard column %X read, returning %02X\n", offset&0xF, code);
697 #endif
698 	return code;
699 }
700 
vk100_mem(address_map & map)701 void vk100_state::vk100_mem(address_map &map)
702 {
703 	map.unmap_value_high();
704 	map(0x0000, 0x6fff).rom();
705 	map(0x7000, 0x700f).mirror(0x0ff0).r(FUNC(vk100_state::vk100_keyboard_column_r));
706 	map(0x8000, 0xbfff).ram();
707 }
708 
709 /*
710  * 8085 IO address map (x = ignored; * = selects address within this range; ? = not sure; ** = subparts check this bit)
711  * (a15 to a8 are latched the same value as a7-a0 on the 8080 and 8085)
712  * [this map is derived from extensive tracing as well as some guesswork, noted for the crtc, systat_b and the uart]
713    a7  a6  a5  a4  a3  a2  a1  a0
714    x   0   x   x   x   x   x   0     W     CRTC address
715    x   0   x   x   x   x   x   1     RW    CRTC register r/w
716    x   1   *   *   *   **  **  **        read area (rightmost 74ls138):
717    x   1   0   0   0   *   *   *     R     SYSTAT_A (a0-a3 chooses the bit of the dipswitches read via d3)
718    x   1   0   0   1   x   x   x     R     SYSTAT_B
719    x   1   0   1   0   x   x   0     R     i8251 UART data
720    x   1   0   1   0   x   x   1     R     i8251 UART status
721    x   1   0   1   1   x   x   x     R     unused
722    x   1   1   0   0   x   x   x     R     unused
723    x   1   1   0   1   x   x   x     R     unused
724    x   1   1   1   0   x   x   x     R     unused
725    x   1   1   1   1   x   x   x     R     unused
726    x   1   0   x   x   *   *   *         write area (right 74ls138):
727    x   1   0   x   x   0   0   0     W     X (low 8 bits)
728    x   1   0   x   x   0   0   1     W     X (high 4 bits)
729    x   1   0   x   x   0   1   0     W     Y (low 8 bits)
730    x   1   0   x   x   0   1   1     W     Y (high 4 bits)
731    x   1   0   x   x   1   0   0     W     ERR
732    x   1   0   x   x   1   0   1     W     SOPS
733    x   1   0   x   x   1   1   0     W     PAT
734    x   1   0   x   x   1   1   1     W     PMUL
735    x   1   1   *   *   *   **  **        write area (middle 74ls138):
736    x   1   1   0   0   0   **  **          write to register file 2x 74ls670:
737    x   1   1   0   0   0   0   0     W       DU
738    x   1   1   0   0   0   0   1     W       DVM
739    x   1   1   0   0   0   1   0     W       DIR
740    x   1   1   0   0   0   1   1     W       WOPS
741    x   1   1   0   0   1   *   *     W     set VG_MODE to * * XOR 3 and Execute (if GO is not active)
742    x   1   1   0   1   0   x   x     W     KYBDW
743    x   1   1   0   1   1   x   x     W     BAUD
744    x   1   1   1   0   0   x   0     W     i8251 UART data
745    x   1   1   1   0   0   x   1     W     i8251 UART control
746    x   1   1   1   0   1   x   x     W     unused
747    x   1   1   1   1   0   x   x     W     unused
748    x   1   1   1   1   1   x   x     W     unused
749 */
vk100_io(address_map & map)750 void vk100_state::vk100_io(address_map &map)
751 {
752 	map.unmap_value_high();
753 	map.global_mask(0xff); // guess, probably correct
754 	map(0x00, 0x00).mirror(0xBE).w(m_crtc, FUNC(mc6845_device::address_w));
755 	map(0x01, 0x01).mirror(0xBE).rw(m_crtc, FUNC(mc6845_device::register_r), FUNC(mc6845_device::register_w));
756 	// Comments are from page 118 (5-14) of http://web.archive.org/web/20091015205827/http://www.computer.museum.uq.edu.au/pdf/EK-VK100-TM-001%20VK100%20Technical%20Manual.pdf
757 	map(0x40, 0x41).mirror(0x98).w(FUNC(vk100_state::vgLD_X));  //LD X LO + HI 12 bits
758 	map(0x42, 0x43).mirror(0x98).w(FUNC(vk100_state::vgLD_Y));  //LD Y LO + HI 12 bits
759 	map(0x44, 0x44).mirror(0x98).w(FUNC(vk100_state::vgERR));    //LD ERR ('error' in bresenham algorithm)
760 	map(0x45, 0x45).mirror(0x98).w(FUNC(vk100_state::vgSOPS));   //LD SOPS (screen options (plus uart dest))
761 	map(0x46, 0x46).mirror(0x98).w(FUNC(vk100_state::vgPAT));    //LD PAT (pattern register)
762 	map(0x47, 0x47).mirror(0x98).w(FUNC(vk100_state::vgPMUL));   //LD PMUL (pattern multiplier)
763 	map(0x60, 0x63).mirror(0x80).w(FUNC(vk100_state::vgREG));     //LD DU, DVM, DIR, WOPS (register file)
764 	map(0x64, 0x67).mirror(0x80).w(FUNC(vk100_state::vgEX));    //EX MOV, DOT, VEC, ER
765 	map(0x68, 0x68).mirror(0x83).w(FUNC(vk100_state::KBDW));   //KBDW (probably mirror(0x03))
766 	map(0x6C, 0x6C).mirror(0x83).w(COM5016T_TAG, FUNC(com8116_device::stt_str_w));   //LD BAUD (baud rate clock divider setting for i8251 tx and rx clocks) (probably mirror(0x03))
767 	map(0x70, 0x71).mirror(0x82).w(m_uart, FUNC(i8251_device::write)); //LD COMD
768 	//map(0x74, 0x74).mirror(0x83).w(FUNC(vk100_state::unknown_74));
769 	//map(0x78, 0x78).mirror(0x83).w(FUNC(vk100_state::kbdw));   //KBDW ?(mirror?)
770 	//map(0x7C, 0x7C).mirror(0x83).w(FUNC(vk100_state::unknown_7C));
771 	map(0x40, 0x47).mirror(0x80).r(FUNC(vk100_state::SYSTAT_A)); // SYSTAT A (state machine done and last 4 bits of vram, as well as dipswitches)
772 	map(0x48, 0x48).mirror(0x87/*0x80*/).r(FUNC(vk100_state::SYSTAT_B)); // SYSTAT B (uart stuff)
773 	map(0x50, 0x51).mirror(0x86).r(m_uart, FUNC(i8251_device::read)); // UART O
774 	//map(0x58, 0x58).mirror(0x87).r(FUNC(vk100_state::unknown_58));
775 	//map(0x60, 0x60).mirror(0x87).r(FUNC(vk100_state::unknown_60));
776 	//map(0x68, 0x68).mirror(0x87).r(FUNC(vk100_state::unknown_68)); // NOT USED
777 	//map(0x70, 0x70).mirror(0x87).r(FUNC(vk100_state::unknown_70));
778 	//map(0x78, 0x7f).mirror(0x87).r(FUNC(vk100_state::unknown_78));
779 }
780 
781 /* Input ports */
782 static INPUT_PORTS_START( vk100 )
783 	// the dipswitches are common ground: when open (upward) the lines are pulled to 5v, otherwise they read as 0
784 	PORT_START("SWITCHES")
785 		PORT_DIPNAME( 0x01, 0x00, "Power Frequency" )           PORT_DIPLOCATION("SW:!1")
786 		PORT_DIPSETTING( 0x00, "60Hz" )
787 		PORT_DIPSETTING( 0x01, "50Hz" )
788 		PORT_DIPNAME( 0x02, 0x00, "Default Serial Port" )           PORT_DIPLOCATION("SW:!2")
789 		PORT_DIPSETTING( 0x00, "EIA port" )
790 		PORT_DIPSETTING( 0x02, "20ma port" )
791 		PORT_DIPNAME( 0x04, 0x00, "Default US/UK" )         PORT_DIPLOCATION("SW:!3")
792 		PORT_DIPSETTING( 0x00, "US" )
793 		PORT_DIPSETTING( 0x04, "UK" )
794 		PORT_DIPNAME( 0x18, 0x00, "Default Parity" )            PORT_DIPLOCATION("SW:!4,!5")
795 		PORT_DIPSETTING( 0x00, "Off" )
796 		PORT_DIPSETTING( 0x10, "Even" )
797 		PORT_DIPSETTING( 0x08, "Odd" )
798 		PORT_DIPSETTING( 0x18, "Do Not Use This Setting" )
799 		PORT_DIPNAME( 0xe0, 0x00, "Default Baud Rate" )         PORT_DIPLOCATION("SW:!6,!7,!8")
800 		PORT_DIPSETTING( 0x00, "110" )
801 		PORT_DIPSETTING( 0x80, "300" )
802 		PORT_DIPSETTING( 0x40, "600" )
803 		PORT_DIPSETTING( 0xc0, "1200" )
804 		PORT_DIPSETTING( 0x20, "2400" )
805 		PORT_DIPSETTING( 0xa0, "4800" )
806 		PORT_DIPSETTING( 0x60, "9600" )
807 		PORT_DIPSETTING( 0xe0, "19200" )
808 
809 	PORT_START("CAPSSHIFT") // CAPS LOCK and SHIFT appear as the high 2 bits on all rows
810 		PORT_BIT(0x3f, IP_ACTIVE_HIGH, IPT_UNUSED)
PORT_CODE(KEYCODE_LSHIFT)811 		PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Shift") PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT)
812 		PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_TOGGLE PORT_NAME("Caps lock") PORT_CODE(KEYCODE_CAPSLOCK)
813 	PORT_START("COL0")
814 		PORT_BIT(0x1f, IP_ACTIVE_LOW, IPT_UNUSED)
815 		PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_UNUSED) // row 0 bit 6 is always low, checked by keyboard test
816 		PORT_BIT(0xc0, IP_ACTIVE_HIGH, IPT_UNUSED) // all rows have these bits left low to save a mask op later
817 	PORT_START("COL1")
818 		PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Set Up") PORT_CODE(KEYCODE_F5)
819 		PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Esc") PORT_CODE(KEYCODE_ESC)
820 		PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Tab") PORT_CODE(KEYCODE_TAB)
821 		PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_UNUSED)
822 		PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Num Enter") PORT_CODE(KEYCODE_ENTER_PAD)
823 		PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("PF1/Hardcopy") PORT_CODE(KEYCODE_F1)
824 		PORT_BIT(0xc0, IP_ACTIVE_HIGH, IPT_UNUSED)
825 	PORT_START("COL2")
826 		PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("1") PORT_CODE(KEYCODE_1)
827 		PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Q") PORT_CODE(KEYCODE_Q)
828 		PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A") PORT_CODE(KEYCODE_A)
829 		PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("No scroll") PORT_CODE(KEYCODE_LALT)
830 		PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Num 1") PORT_CODE(KEYCODE_1_PAD)
831 		PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("PF2/Locator") PORT_CODE(KEYCODE_F2)
832 		PORT_BIT(0xc0, IP_ACTIVE_HIGH, IPT_UNUSED)
833 	PORT_START("COL3")
834 		PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("2") PORT_CODE(KEYCODE_2)
835 		PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("W") PORT_CODE(KEYCODE_W)
836 		PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("S") PORT_CODE(KEYCODE_S)
837 		PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Z") PORT_CODE(KEYCODE_Z)
838 		PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Num 2") PORT_CODE(KEYCODE_2_PAD)
839 		PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("PF3/Text") PORT_CODE(KEYCODE_F3)
840 		PORT_BIT(0xc0, IP_ACTIVE_HIGH, IPT_UNUSED)
841 	PORT_START("COL4")
842 		PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("3") PORT_CODE(KEYCODE_3)
843 		PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E") PORT_CODE(KEYCODE_E)
844 		PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D") PORT_CODE(KEYCODE_D)
845 		PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("X") PORT_CODE(KEYCODE_X)
846 		PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Num 3") PORT_CODE(KEYCODE_3_PAD)
847 		PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("PF4/Reset") PORT_CODE(KEYCODE_F4)
848 		PORT_BIT(0xc0, IP_ACTIVE_HIGH, IPT_UNUSED)
849 	PORT_START("COL5")
850 		PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("4") PORT_CODE(KEYCODE_4)
851 		PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("R") PORT_CODE(KEYCODE_R)
852 		PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F") PORT_CODE(KEYCODE_F)
853 		PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C") PORT_CODE(KEYCODE_C)
854 		PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Num 4") PORT_CODE(KEYCODE_4_PAD)
855 		PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Up") PORT_CODE(KEYCODE_UP)
856 		PORT_BIT(0xc0, IP_ACTIVE_HIGH, IPT_UNUSED)
857 	PORT_START("COL6")
858 		PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("5") PORT_CODE(KEYCODE_5)
859 		PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("T") PORT_CODE(KEYCODE_T)
860 		PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G") PORT_CODE(KEYCODE_G)
861 		PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("V") PORT_CODE(KEYCODE_V)
862 		PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Num 5") PORT_CODE(KEYCODE_5_PAD)
863 		PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Down") PORT_CODE(KEYCODE_DOWN)
864 		PORT_BIT(0xc0, IP_ACTIVE_HIGH, IPT_UNUSED)
865 	PORT_START("COL7")
866 		PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("6") PORT_CODE(KEYCODE_6)
867 		PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Y") PORT_CODE(KEYCODE_Y)
868 		PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("H") PORT_CODE(KEYCODE_H)
869 		PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B") PORT_CODE(KEYCODE_B)
870 		PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Num 6") PORT_CODE(KEYCODE_6_PAD)
871 		PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Left") PORT_CODE(KEYCODE_LEFT)
872 		PORT_BIT(0xc0, IP_ACTIVE_HIGH, IPT_UNUSED)
873 	PORT_START("COL8")
874 		PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("7") PORT_CODE(KEYCODE_7)
875 		PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("U") PORT_CODE(KEYCODE_U)
876 		PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("J") PORT_CODE(KEYCODE_J)
877 		PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Space") PORT_CODE(KEYCODE_SPACE)
878 		PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Num 7") PORT_CODE(KEYCODE_7_PAD)
879 		PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Right") PORT_CODE(KEYCODE_RIGHT)
880 		PORT_BIT(0xc0, IP_ACTIVE_HIGH, IPT_UNUSED)
881 	PORT_START("COL9")
882 		PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("8") PORT_CODE(KEYCODE_8)
883 		PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("I") PORT_CODE(KEYCODE_I)
884 		PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("K") PORT_CODE(KEYCODE_K)
885 		PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("N") PORT_CODE(KEYCODE_N)
886 		PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Num 8") PORT_CODE(KEYCODE_8_PAD)
887 		PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED)
888 		PORT_BIT(0xc0, IP_ACTIVE_HIGH, IPT_UNUSED)
889 	PORT_START("COLA")
890 		PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("9") PORT_CODE(KEYCODE_9)
891 		PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("O") PORT_CODE(KEYCODE_O)
892 		PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("L") PORT_CODE(KEYCODE_L)
893 		PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("M") PORT_CODE(KEYCODE_M)
894 		PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Num 9") PORT_CODE(KEYCODE_9_PAD)
895 		PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED)
896 		PORT_BIT(0xc0, IP_ACTIVE_HIGH, IPT_UNUSED)
897 	PORT_START("COLB")
898 		PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("0") PORT_CODE(KEYCODE_0)
899 		PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("P") PORT_CODE(KEYCODE_P)
900 		PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(";") PORT_CODE(KEYCODE_COLON)
901 		PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(",") PORT_CODE(KEYCODE_COMMA)
902 		PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Num 0") PORT_CODE(KEYCODE_0_PAD)
903 		PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED)
904 		PORT_BIT(0xc0, IP_ACTIVE_HIGH, IPT_UNUSED)
905 	PORT_START("COLC")
906 		PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("-") PORT_CODE(KEYCODE_MINUS)
907 		PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("[") PORT_CODE(KEYCODE_OPENBRACE)
908 		PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("'") PORT_CODE(KEYCODE_QUOTE)
909 		PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(".") PORT_CODE(KEYCODE_STOP)
910 		PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Num -") PORT_CODE(KEYCODE_MINUS_PAD)
911 		PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED)
912 		PORT_BIT(0xc0, IP_ACTIVE_HIGH, IPT_UNUSED)
913 	PORT_START("COLD")
914 		PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("=") PORT_CODE(KEYCODE_EQUALS)
915 		PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("]") PORT_CODE(KEYCODE_CLOSEBRACE)
916 		PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_UNUSED)
917 		PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("/") PORT_CODE(KEYCODE_SLASH)
918 		PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Num ,") PORT_CODE(KEYCODE_PLUS_PAD)
919 		PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED)
920 		PORT_BIT(0xc0, IP_ACTIVE_HIGH, IPT_UNUSED)
921 	PORT_START("COLE")
922 		PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("~") PORT_CODE(KEYCODE_TILDE)
923 		PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Delete") PORT_CODE(KEYCODE_DEL)
924 		PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("\\") PORT_CODE(KEYCODE_BACKSLASH)
925 		PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Line feed") PORT_CODE(KEYCODE_RALT)
926 		PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Num .") PORT_CODE(KEYCODE_DEL_PAD)
927 		PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED)
928 		PORT_BIT(0xc0, IP_ACTIVE_HIGH, IPT_UNUSED)
929 	PORT_START("COLF")
930 		PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Backspace") PORT_CODE(KEYCODE_BACKSPACE)
931 		PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Break") PORT_CODE(KEYCODE_F6)
932 		PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Return") PORT_CODE(KEYCODE_ENTER)
933 		PORT_BIT(0x18, IP_ACTIVE_LOW, IPT_UNUSED)
934 		PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Ctrl") PORT_CODE(KEYCODE_LCONTROL) PORT_CODE(KEYCODE_RCONTROL)
935 		PORT_BIT(0xc0, IP_ACTIVE_HIGH, IPT_UNUSED)
936 INPUT_PORTS_END
937 
938 
939 void vk100_state::machine_start()
940 {
941 	m_online_led.resolve();
942 	m_local_led.resolve();
943 	m_noscroll_led.resolve();
944 	m_basic_led.resolve();
945 	m_hardcopy_led.resolve();
946 	m_l1_led.resolve();
947 	m_l2_led.resolve();
948 
949 	m_online_led = 1;
950 	m_local_led = 0;
951 	m_noscroll_led = 1;
952 	m_basic_led = 1;
953 	m_hardcopy_led = 1;
954 	m_l1_led = 1;
955 	m_l2_led = 1;
956 	m_vsync = 0;
957 	m_dir_a6 = 1;
958 	m_cout = 0;
959 	m_vgX = 0;
960 	m_vgY = 0;
961 	m_vgERR = 0;
962 	m_vgSOPS = 0;
963 	m_vgPAT = 0;
964 	m_vgPAT_Mask = 0x80;
965 	m_vgPMUL = 0;
966 	m_vgPMUL_Count = 0;
967 	m_vgDownCount = 0;
968 	VG_DU = 0;
969 	VG_DVM = 0;
970 	VG_DIR = 0;
971 	VG_WOPS = 0;
972 	m_VG_MODE = 0;
973 	m_vgGO = 0;
974 	m_ACTS = 1;
975 	m_ADSR = 1;
976 	char kbdcol[8];
977 	// look up all 16 tags 'the slow way' but only once on reset
978 	for (int i = 0; i < 16; i++)
979 	{
980 		sprintf(kbdcol,"COL%X", i);
981 		m_col_array[i] = ioport(kbdcol);
982 	}
983 }
984 
WRITE_LINE_MEMBER(vk100_state::crtc_vsync)985 WRITE_LINE_MEMBER(vk100_state::crtc_vsync)
986 {
987 	m_maincpu->set_input_line(I8085_RST75_LINE, state? ASSERT_LINE : CLEAR_LINE);
988 	m_vsync = state;
989 }
990 
WRITE_LINE_MEMBER(vk100_state::i8251_rxrdy_int)991 WRITE_LINE_MEMBER(vk100_state::i8251_rxrdy_int)
992 {
993 	m_maincpu->set_input_line(I8085_RST65_LINE, state?ASSERT_LINE:CLEAR_LINE);
994 }
995 
WRITE_LINE_MEMBER(vk100_state::i8251_txrdy_int)996 WRITE_LINE_MEMBER(vk100_state::i8251_txrdy_int)
997 {
998 	m_maincpu->set_input_line(I8085_RST55_LINE, state?ASSERT_LINE:CLEAR_LINE);
999 }
1000 
WRITE_LINE_MEMBER(vk100_state::i8251_rts)1001 WRITE_LINE_MEMBER(vk100_state::i8251_rts)
1002 {
1003 	logerror("callback: RTS state changed to %d\n", state);
1004 	// TODO: only change this during loopback mode!
1005 	m_ACTS = state;
1006 }
1007 
init_vk100()1008 void vk100_state::init_vk100()
1009 {
1010 	// figure out how the heck to initialize the timers here
1011 	//m_i8251_rx_timer = timer_alloc(TID_I8251_RX);
1012 	//m_i8251_tx_timer = timer_alloc(TID_I8251_TX);
1013 	//m_i8251_sync_timer = timer_alloc(TID_SYNC);
1014 	//machine().scheduler().timer_set(attotime::from_hz(10000), FUNC(i8251_rx_clk));
1015 }
1016 
video_start()1017 void vk100_state::video_start()
1018 {
1019 	m_vram = memregion("vram")->base();
1020 	m_trans = memregion("trans")->base();
1021 	m_pattern = memregion("pattern")->base();
1022 	m_dir = memregion("dir")->base();
1023 	m_sync = memregion("sync")->base();
1024 	m_vector = memregion("vector")->base();
1025 	m_ras_erase = memregion("ras_erase")->base();
1026 }
1027 
MC6845_UPDATE_ROW(vk100_state::crtc_update_row)1028 MC6845_UPDATE_ROW( vk100_state::crtc_update_row )
1029 {
1030 	static const uint32_t colorTable[16] = {
1031 	0x000000, 0x0000FF, 0xFF0000, 0xFF00FF, 0x00FF00, 0x00FFFF, 0xFFFF00, 0xFFFFFF,
1032 	0x000000, 0x0000FF, 0xFF0000, 0xFF00FF, 0x00FF00, 0x00FFFF, 0xFFFF00, 0xFFFFFF };
1033 	static const uint32_t colorTable2[16] = {
1034 	0x000000, 0x0000FF, 0xFF0000, 0xFF00FF, 0x00FF00, 0x00FFFF, 0xFFFF00, 0xFFFFFF,
1035 	0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000 };
1036 	//printf("y=%d, ma=%04x, ra=%02x, x_count=%02x ", y, ma, ra, x_count);
1037 	/* figure out ram address based on tech manual page 5-23:
1038 	 * real address to 16-bit chunk a13  a12  a11 a10 a9  a8  a7  a6  a5  a4  a3  a2  a1  a0
1039 	 * crtc input                  MA11 MA10 MA9 MA8 MA7 MA6 RA1 RA0 MA5 MA4 MA3 MA2 MA1 MA0
1040 	 */
1041 	uint16_t EA = ((ma&0xfc0)<<2)|((ra&0x3)<<6)|(ma&0x3F);
1042 	// display the 64 different 12-bit-wide chunks
1043 	for (int i = 0; i < 64; i++)
1044 	{
1045 		uint16_t block = m_vram[(EA<<1)+(2*i)+1] | (m_vram[(EA<<1)+(2*i)]<<8);
1046 		uint32_t fgColor = (m_vgSOPS&0x08)?colorTable[(block&0xF000)>>12]:colorTable2[(block&0xF000)>>12];
1047 		uint32_t bgColor = (m_vgSOPS&0x08)?colorTable[(m_vgSOPS&0xF0)>>4]:colorTable2[(m_vgSOPS&0xF0)>>4];
1048 		// display a 12-bit wide chunk
1049 		for (int j = 0; j < 12; j++)
1050 		{
1051 			bitmap.pix(y, (12*i)+j) = (((block&(0x0001<<j))?1:0)^(m_vgSOPS&1))?fgColor:bgColor;
1052 		}
1053 	}
1054 }
1055 
1056 
vk100(machine_config & config)1057 void vk100_state::vk100(machine_config &config)
1058 {
1059 	/* basic machine hardware */
1060 	I8085A(config, m_maincpu, XTAL(5'068'800));
1061 	m_maincpu->set_addrmap(AS_PROGRAM, &vk100_state::vk100_mem);
1062 	m_maincpu->set_addrmap(AS_IO, &vk100_state::vk100_io);
1063 
1064 	/* video hardware */
1065 	screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
1066 	screen.set_raw(XTAL(45'619'200)/3, 882, 0, 720, 370, 0, 350 ); // fake screen timings for startup until 6845 sets real ones
1067 	screen.set_screen_update("crtc", FUNC(mc6845_device::screen_update));
1068 
1069 	MC6845(config, m_crtc, 45.6192_MHz_XTAL/3/12); // unknown variant
1070 	m_crtc->set_screen("screen");
1071 	m_crtc->set_show_border_area(false);
1072 	m_crtc->set_char_width(12);
1073 	m_crtc->set_update_row_callback(FUNC(vk100_state::crtc_update_row));
1074 	m_crtc->out_vsync_callback().set(FUNC(vk100_state::crtc_vsync));
1075 
1076 	/* i8251 uart */
1077 	I8251(config, m_uart, 0);
1078 	m_uart->txd_handler().set(RS232_TAG, FUNC(rs232_port_device::write_txd));
1079 	m_uart->dtr_handler().set(RS232_TAG, FUNC(rs232_port_device::write_dtr));
1080 	m_uart->rts_handler().set(RS232_TAG, FUNC(rs232_port_device::write_rts));
1081 	m_uart->rxrdy_handler().set(FUNC(vk100_state::i8251_rxrdy_int));
1082 	m_uart->txrdy_handler().set(FUNC(vk100_state::i8251_txrdy_int));
1083 
1084 	rs232_port_device &rs232(RS232_PORT(config, RS232_TAG, default_rs232_devices, nullptr));
1085 	rs232.rxd_handler().set(m_uart, FUNC(i8251_device::write_rxd));
1086 	rs232.dsr_handler().set(m_uart, FUNC(i8251_device::write_dsr));
1087 
1088 	com8116_device &dbrg(COM8116(config, COM5016T_TAG, 5.0688_MHz_XTAL));
1089 	dbrg.fr_handler().set(m_uart, FUNC(i8251_device::write_rxc));
1090 	dbrg.ft_handler().set(m_uart, FUNC(i8251_device::write_txc));
1091 
1092 	config.set_default_layout(layout_vk100);
1093 
1094 	SPEAKER(config, "mono").front_center();
1095 	BEEP(config, m_speaker, 116).add_route(ALL_OUTPUTS, "mono", 0.25); // 116 hz (page 172 of TM), but duty cycle is wrong here!
1096 }
1097 
1098 /* ROM definition */
1099 /* according to http://www.computer.museum.uq.edu.au/pdf/EK-VK100-TM-001%20VK100%20Technical%20Manual.pdf
1100 page 5-10 (pdf pg 114), The 4 firmware roms should go from 0x0000-0x1fff,
1101 0x2000-0x3fff, 0x4000-0x5fff and 0x6000-0x63ff; The last rom is actually a
1102 little bit longer and goes to 67ff.
1103 */
1104 ROM_START( vk100 )
1105 	ROM_REGION( 0x10000, "maincpu", ROMREGION_ERASEFF )
1106 	ROM_LOAD( "23-031e4-00.rom1.e53", 0x0000, 0x2000, CRC(c8596398) SHA1(a8dc833dcdfb7550c030ac3d4143e266b1eab03a))
1107 	ROM_LOAD( "23-017e4-00.rom2.e52", 0x2000, 0x2000, CRC(e857a01e) SHA1(914b2c51c43d0d181ffb74e3ea59d74e70ab0813))
1108 	ROM_LOAD( "23-018e4-00.rom3.e51", 0x4000, 0x2000, CRC(b3e7903b) SHA1(8ad6ed25cd9b04a9968aa09ab69ba526d35ca550))
1109 	ROM_LOAD( "23-190e2-00.rom4.e50", 0x6000, 0x1000, CRC(ad596fa5) SHA1(b30a24155640d32c1b47a3a16ea33cd8df2624f6)) // probably an overdump, e2 implies the size is 0x800 not 0x1000, and the end is all blank
1110 
1111 	ROM_REGION( 0x8000, "vram", ROMREGION_ERASE00 ) // 32k of vram
1112 
1113 	ROM_REGION( 0x400, "pattern", ROMREGION_ERASEFF )
1114 	/* This is the "PATTERN ROM", (1k*4, 82s137)
1115 	 * it contains a table of 4 output bits based on input of: (from figure 5-18):
1116 	 * 4 input bits bank-selected from RAM (a0, a1, a2, a3)
1117 	 * 2 select bits to choose one of the 4 bits, sourced from the X reg LSBs (a4, a5)
1118 	 * 3 pattern function bits from WOPS (F0 "N" is a6, F1 and F2 are a7 and a8
1119 	 * and one bit from the lsb of the pattern register shifter (a9)
1120 	 * control bits:
1121 	 *            /CE1 ----- GND [verified via tracing]
1122 	 *            /CE2 ----- GND [verified via tracing]
1123 	 * addr bits 9876543210
1124 	 *           ||||||\\\\- input from ram (A)
1125 	 *           ||||\\----- bit select (from x reg lsb)
1126 	 *           |||\------- negate (N) \___ low 3 bits of WOPS
1127 	 *           |\\-------- function   /
1128 	 *           \---------- pattern bit (P)
1129 	 * data bits: 3210
1130 	 *            \\\\-- output to ram (M), but gated by an io line from vector rom
1131 	 *    functions are:
1132 	 *    Overlay: M=A|(P^N)
1133 	 *    Replace: M=P^N
1134 	 *    Complement: M=A^(P^N)
1135 	 *    Erase: M=N
1136 	 */
1137 	ROM_LOAD( "wb8201_656f1.m1-7643-5.pr4.ic14", 0x0000, 0x0400, CRC(e8ecf59f) SHA1(49e9d109dad3d203d45471a3f4ca4985d556161f)) // label verified from nigwil's board
1138 
1139 	ROM_REGION(0x100, "trans", ROMREGION_ERASEFF )
1140 	/* this is the "TRANSLATOR ROM" described in figure 5-17 on page 5-27 (256*8, 82s135)
1141 	 * it contains a table of 256 values which skips every fourth value so 00 01 02 04 05 06 08.. etc, wraps at the end
1142 	 * control bits:
1143 	 *            /CE1 ----- GND [verified via tracing]
1144 	 *            /CE2 ----- GND [verified via tracing]
1145 	 * addr bits: 76543210
1146 	 *            \\\\\\\\- X9 thru X2
1147 	 * data bits: 76543210
1148 	 *            \\\\\\\\- X'9 thru X'2
1149 	 * The VT125 prom @ E60 is literally identical to this, the same exact part: 23-060B1
1150 	 */
1151 	ROM_LOAD( "wb---0_060b1.mmi6309.pr2.ic82", 0x0000, 0x0100, CRC(198317fc) SHA1(00e97104952b3fbe03a4f18d800d608b837d10ae)) // label verified from nigwil's board
1152 
1153 	ROM_REGION(0x100, "dir", ROMREGION_ERASEFF )
1154 		/* this is the "DIRECTION ROM"  == mb6309 (256x8, 82s135)
1155 		* see figure 5-24 on page 5-39
1156 		* It tells the direction and enable for counting on the X and Y counters
1157 		* and also handles the non-math related parts of the bresenham line algorithm
1158 		* control bits:
1159 		*            /CE1 ----- DCOUNT 0 H [verified via tracing]
1160 		*            /CE2 ----- ENA ERROR L [verified via tracing]
1161 		* addr bits: 76543210
1162 		*            ||||\\\\-- DIR (vgDIR register low 4 bits)
1163 		*            |||\------ C OUT aka ERROR CARRY (strobed in by STROBE L from the error counter's adder) [verified via tracing]
1164 		*            ||\------- Y0 (the otherwise unused lsb of the Y register, used for bresenham) [verified via tracing]
1165 		*            |\-------- feedback bit from d5 strobed by V CLK [verified via tracing]
1166 		*            \--------- GND; the second half of the prom is blank (0x00)
1167 		* data bits: 76543210
1168 		*            |||||||\-- ENA Y (enables change on X counter) [works with code]
1169 		*            ||||||\--- ENA X (enables change on Y counter) [works with code]
1170 		*            |||||\---- Y DIRECTION (high is count down, low is count up)
1171 		*            ||||\----- X DIRECTION (high is count down, low is count up)
1172 		*            |||\------ PIXEL WRT
1173 		*            ||\------- feedback bit to a6, this bit is held in PRESET/1 condition by GO being inactive, and if the vector prom is disabled it is pulled to 1 [verified via tracing and schematics]
1174 		*            |\-------- UNUSED, always 0
1175 		*            \--------- UNUSED, always 0
1176 		* The VT125 prom @ E41 is literally identical to this, the same exact part: 23-059B1
1177 		*/
1178 	ROM_LOAD( "wb8141_059b1.tbp18s22.pr5.ic111", 0x0000, 0x0100, CRC(4b63857a) SHA1(3217247d983521f0b0499b5c4ef6b5de9844c465))  // label verified from andy's board
1179 
1180 	ROM_REGION( 0x100, "ras_erase", ROMREGION_ERASEFF )
1181 	/* this is the "RAS/ERASE ROM" involved with driving the RAS lines and erasing VRAM dram (256*4, 82s129)
1182 	 * control bits:
1183 	 *            /CE1 ----- /WRITE aka WRITE L (pin 6 of vector rom after being latched by its ls273) [verified via tracing and vt125 schematic]
1184 	 *            /CE2 ----- /ENA WRITE aka ENA WRITE L [verified via tracing and vt125 schematic]
1185 	 *                       (INHIBIT WRITE L (pin 5 of ls74 to extreme left edge of translate prom) XOR STROBE D COUNT (pin 5 of ls74 near the 20ma port) (pin 3 of the ls86 above the crtc)
1186 	 * addr bits: 76543210
1187 	 *            |||||||\-- X'2 [verified via tracing]
1188 	 *            ||||||\--- X'3 [verified via tracing]
1189 	 *            |||||\---- register file bit 3/upper file MSB (DIR prom pin 4, ls191 2nd from left edge left of the hd46505 pin 9, upper ls670n pin 6, ls283 at the left edge left of the hd46505 pin 15) [verified via tracing]
1190 	 *            ||||\----- (Y8 NOR !(X10 NAND X9)) (pins 4,5,6 of ls32 left of 8085, and pins 1,2 of the ls04 in the lower left corner, pins 10,9,8 of the ls00 at the left edge drawn from the ls74 between the 8251 and 8202) [verified via tracing]
1191 	 *            |||\------ (X10 NOR Y10) (pins 10,9,8 of ls32 left of 8085) [verified via tracing]
1192 	 *            ||\------- X11 (D out of ls191 left of ls191 left of hd46505) [verified via tracing]
1193 	 *            |\-------- Y11 (D out of ls191 left of hd46505) [verified via tracing]
1194 	 *            \--------- ERASE L/d5 on the vector rom [verified via tracing]
1195 	 * data bits: 3210
1196 	 *            |||\-- /WE for VRAM Attribute bits
1197 	 *            ||\--- /WE for VRAM bits 0-3 (leftmost bits, first to be shifted out)
1198 	 *            |\---- /WE for VRAM bits 4-7
1199 	 *            \----- /WE for VRAM bits 8-11 (rightmost bits, last to be shifted out)
1200 	 * The VT125 prom E93 is mostly equivalent to the ras/erase prom; On the vt125 version, the inputs are:
1201 	 *  (X'10 NOR X'11)
1202 	 *  (Y9 NOR Y10)
1203 	 *  Y11
1204 	 *  X8 (aka PX8)
1205 	 *  X9 (aka PX9)
1206 	 *  ERASE L
1207 	 *  X'3
1208 	 *  X'2
1209 	 * and the outputs are:
1210 	 *  MWR 2
1211 	 *  MWR 1
1212 	 *  MWR 0
1213 	 * since the vt125 has ram laid out differently than the vk100 and
1214 	   only has 3 banks (but 2 planes of 3 banks), I (LN) assume there
1215 	   are four wr banks on the v100, one per nybble, and the X'3 and
1216 	   X'2 inputs lend credence to this.
1217 	 *
1218 	 */
1219 	ROM_LOAD( "wb8151_573a2.mmi6301.pr3.ic41", 0x0000, 0x0100, CRC(75885a9f) SHA1(c721dad6a69c291dd86dad102ed3a8ddd620ecc4)) // Stamp/silkscreen: "WB8151 // 573A2" (23-573A2), 82S129 equivalent @ E41
1220 	// label verified from nigwil's and andy's board
1221 
1222 	ROM_REGION( 0x100, "vector", ROMREGION_ERASEFF )
1223 	// WARNING: it is possible that the first two bytes of this prom are bad!
1224 	// The PROM on andy's board appears to be damaged, this will need to be redumped from another board.
1225 	/* this is the "VECTOR ROM" (256*8, 82s135) which runs the vector generator state machine
1226 	 * the vector rom bits are complex and are unfortunately poorly documented
1227 	 * in the tech manual. see figure 5-23.
1228 	 * control bits:
1229 	 *            /CE1 ----- /GO aka GO L [verified via tracing]
1230 	 *            /CE2 ----- GND [verified via tracing]
1231 	 * addr bits: 76543210
1232 	 *            ||||\\\\-- To sync counter, which counts 0xC 0x3 0x2 0x1 0x0 0x5 0x4 0xB 0xA 0x9 0x8 0xD in that order
1233 	 *            |||\------ (MODE 0 NAND GO) \_This effectively means when GO is low, these bits are both 1, when GO is high, these bits are the inverse of the MODE bits; this is DIFFERENT from the vt125, and was probably removed as unnecessary given that /GO is an enable for the vector rom anyway [verified via tracing]
1234 	 *            ||\------- (MODE 1 NAND GO) /
1235 	 *            |\-------- ? C OUT (when set, only one /LD ERROR pulse occurs instead of two)
1236 	 *            \--------- ? FINISH (/LD ERROR only goes active (low) when this is unset)
1237 	 *
1238 	 * data bits: 76543210
1239 	 *            |||||||\-- /WRITE aka WRITE L (fig 5-20, page 5-32, writes the post-pattern-converted value back to vram at X,Y)
1240 	 *            ||||||\--- DONE L [verified via tracing]
1241 	 *            |||||\---- VECTOR CLK aka V CLK [verified via tracing]
1242 	 *            ||||\----- /LD ERROR aka STROBE ERROR L (strobes the adder result value into the vgERR register)
1243 	 *            |||\------ D LOAD [by process of elimination and limited tracing]
1244 	 *            ||\------- ERASE L (latched, forces a4 on the sync rom low and also forces a7 on the ras/erase rom; the counter rom may be involved in blanking all of vram) [verified via tracing]
1245 	 *            |\-------- C0 aka C IN (high during DVM read, low otherwise, a carry in to the adder so DVM is converted from 1s to 2s complement)
1246 	 *            \--------- SHIFT ENA [verified via tracing]
1247 	 * The data bits all have pull-ups to +5v if the /CE1 pin is not low
1248 	 * According to the VT125 tech manual (vt100 tech manual rev 3, page 6-85) the 8 signals here are:
1249 	 * ERASE L - d5
1250 	 * SHIFT ENA - d7
1251 	 * C IN - d6
1252 	 * D LOAD - d4
1253 	 * WRITE L - d0
1254 	 * DONE L - d1
1255 	 * VECTOR CLK - d2
1256 	 * STROBE ERROR L - d3
1257 	 *
1258 	 * The VT125 prom E71 and its latch E70 is mostly equivalent to the vector prom, but the address order is different
1259 	 */
1260 	ROM_LOAD( "wb8146_058b1.mmi6309.pr1.ic99", 0x0000, 0x0100, BAD_DUMP CRC(71b01864) SHA1(e552f5b0bc3f443299282b1da7e9dbfec60e12bf))  // label verified from nigwil's and andy's board
1261 
1262 	ROM_REGION( 0x20, "sync", ROMREGION_ERASEFF )
1263 	/* this is the "SYNC ROM" == mb6331 (32x8, 82s123)
1264 	 * It generates the ram RAS/CAS and a few other signals, see figure 5-20 on page 5-32
1265 	 * The exact pins for each signal are not documented.
1266 	 * control bits:
1267 	 *            /CE1 -- GND(Unused)
1268 	 * addr bits: 43210
1269 	 *            |\\\\-- To sync counter, which counts 0xC 0x3 0x2 0x1 0x0 0x5 0x4 0xB 0xA 0x9 0x8 0xD in that order
1270 	 *            \------ comes from the gated ERASE L/d5 from the vector rom, only low during VG_MODE == ER (ERase Screen) [verified via tracing]
1271 	 *                      when high: the sync rom matches figure 5-20 (page 5-32) and 5-23 (page 5-38)
1272 	 *                      when low: RA/RB is fixed on WOPS in the register file
1273 	 *                                LD SHFR does NOT output pulses (effectively blanking the screen)
1274 	 *                                WRT/RD is held at /RD so vg to vram do nothing,
1275 	 *                                however while the crtc is refreshing the screen it instead is writing zeroes to every location
1276 	 * data bits: 76543210
1277 	 *            |||||||\-- WRT/RD (write high when x,y (vg) drives vram, read low when ma (crtc) drives vram)
1278 	 *            ||||||\--- /RAS (for vram)
1279 	 *            |||||\---- STROBE aka STROBE L aka VG STROBE(latches the carry bit from the adder to the direction rom AND causes the data at the X,Y address of vram to be read into the holding register before pattern is applied)
1280 	 *            ||||\----- LD SHFR (loads the 12-bit shift register of data to be shifted to screen)
1281 	 *            |||\------ /CAS (for vram)
1282 	 *            ||\------- RA\__selects which slot of the 8x4 register file (du, dvm, dir, or wops) is selected
1283 	 *            |\-------- RB/
1284 	 *            \--------- SYNC (latches the EXECUTE signal from an EXEC * write to activate the GO signal and enable the Vector rom) [verified via tracing]
1285 	 * The VT125 proms E64/E66 and their respective latches E65 and E83 are mostly equivalent to the sync rom
1286 	 */
1287 	ROM_LOAD( "wb8014_297a1.74s288.pr6.ic89", 0x0000, 0x0020, CRC(e2f7c566) SHA1(a4c3dc5d07667141ad799168a862cb3c489b4934)) // label verified from nigwil's and andy's board
1288 ROM_END
1289 
1290 /* Driver */
1291 
1292 /*    YEAR  NAME   PARENT  COMPAT  MACHINE  INPUT  STATE        INIT        COMPANY                          FULLNAME        FLAGS */
1293 COMP( 1980, vk100, 0,      0,      vk100,   vk100, vk100_state, init_vk100, "Digital Equipment Corporation", "VK100 'GIGI'", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND)
1294