1 // license:BSD-3-Clause
2 // copyright-holders:Gabriele D'Antona, F. Ulivi
3 
4 /***************************************************************************
5 
6 HP 9816
7 1982
8 MESS driver by friol (dantonag (at) gmail.com)
9 System reference mainly from O.De Smet
10 Driver started on 10/01/2012
11 
12 ===
13 
14 Memory map:
15 
16 000000-00ffff - system rom
17 428000-428fff - keyboard 8042 host status / data ports (8042 undumped)
18 510000-51ffff - videoram
19 530000-53ffff - graphic memory
20 5f0000-5f3fff - system PROM
21 xxxxxx-ffffff - system RAM
22 
23 ===
24 
25 - 0x408: startup code, 68000 registers test
26 - 0x1002: bootrom test
27 - 0x1d18: PROM test
28 - 0x103C: prints "bootrom failed"
29 - 0x1150: other boot test
30 - 0x1164: keyboard test
31 - 0x1202: post-kbd test
32 - 0x12c6: "loading memory" test
33 
34 ===
35 
36 TODO: boot tests fail
37 
38 ****************************************************************************/
39 
40 #include "emu.h"
41 #include "cpu/m68000/m68000.h"
42 #include "video/mc6845.h"
43 //#include "machine/ins8250.h"
44 #include "emupal.h"
45 #include "screen.h"
46 
47 #define HP9816_CHDIMX 8
48 #define HP9816_CHDIMY 16
49 #define HP9816_ROWX 80
50 #define HP9816_ROWY 25
51 
52 //
53 
54 static uint8_t prom16a[256] = {
55 	0x00,0x00,      // checksum
56 	0x00,           // 256 bytes idprom
57 		'2', '0', '1', '0', 'A', '0', '0', '0', '0', '0', '0',      // serial in ascii DDDDCSSSSSS date code, country, serial number
58 		'9', '8', '1', '6', 'A', ' ', ' ',                          // product number
59 	0xff,           // 8 bits processor board config
60 	0x01,           // keyboard 98203B
61 	0x02,           // CRT alpha see crtid for monitor
62 	0x03,           // HP-IB
63 	0x04,           // Graphics
64 	0xff,           // end
65 	0xff,
66 	0xff,
67 	0xff,
68 	0xff,
69 	0xff,
70 	0xff,
71 	0xff,
72 	0xff,
73 	0xff,
74 	0xff,
75 	0xff,
76 	0xff,0xfe,0x00,0x00,            // bottom minimum address for ram size
77 	0xff,0xff,                      // 16 required IO cards here not used
78 	0xff,0xff,
79 	0xff,0xff,
80 	0xff,0xff,
81 	0xff,0xff,
82 	0xff,0xff,
83 	0xff,0xff,
84 	0xff,0xff,
85 	0xff,0xff,
86 	0xff,0xff,
87 	0xff,0xff,
88 	0xff,0xff,
89 	0xff,0xff,
90 	0xff,0xff,
91 	0xff,0xff,
92 	0xff,0xff,
93 	0xff,0xff,0xff,0xff,            // boot msus to try before Boot list scan
94 	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,   // Boot file name
95 	0x00,0x00,0x00,0x00,            // delay in millisec before boot scan
96 	0x00,                           // owner byte, HP format
97 	0x00,                           // id prom revision byte : 0x00
98 	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,                                 // rest reserved at 0xFF
99 	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
100 	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
101 	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
102 	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
103 	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
104 	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
105 	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
106 	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
107 	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
108 };
109 
110 //
111 
112 class hp9k_state : public driver_device
113 {
114 public:
hp9k_state(const machine_config & mconfig,device_type type,const char * tag)115 	hp9k_state(const machine_config &mconfig, device_type type, const char *tag) :
116 		driver_device(mconfig, type, tag),
117 		m_maincpu(*this, "maincpu"),
118 		m_6845(*this, "mc6845"),
119 		m_gfxdecode(*this, "gfxdecode")
120 	{
121 		kbdBit=0;
122 		crtc_curreg=0;
123 		crtc_addrStartHi=0;
124 		crtc_addrStartLow=0;
125 		calc_prom_crc(prom16a);
126 	}
127 
128 	void hp9k(machine_config &config);
129 
130 	void init_hp9k();
131 
132 private:
133 
134 	int crtc_curreg;
135 	int crtc_addrStartHi;
136 	int crtc_addrStartLow;
137 
138 	void calc_prom_crc(uint8_t* prom);
139 	void putChar(uint8_t thec,int x,int y,bitmap_ind16 &bitmap);
140 
141 	uint8_t kbdBit;
142 
143 	required_device<cpu_device> m_maincpu;
144 	required_device<mc6845_device> m_6845;
145 
146 	uint8_t m_videoram[0x4000];
147 	uint8_t m_screenram[0x800];
148 
149 	uint16_t buserror_r();
150 	void buserror_w(uint16_t data);
151 
152 	uint16_t hp9k_videoram_r(offs_t offset, uint16_t mem_mask = ~0);
153 	void hp9k_videoram_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
154 
155 	uint16_t hp9k_prom_r(offs_t offset, uint16_t mem_mask = ~0);
156 	void hp9k_prom_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
157 
158 	uint16_t keyboard_r(offs_t offset, uint16_t mem_mask = ~0);
159 	void keyboard_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
160 
161 	uint16_t leds_r(offs_t offset, uint16_t mem_mask = ~0);
162 	void leds_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
163 
164 	void kbd_put(uint8_t data);
165 
166 	uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
167 
168 	required_device<gfxdecode_device> m_gfxdecode;
169 	void hp9k_mem(address_map &map);
170 };
171 
172 //
173 
calc_prom_crc(uint8_t * prom)174 void hp9k_state::calc_prom_crc(uint8_t* prom)
175 {
176 	int chksum;
177 	int i;
178 
179 	chksum = 0;
180 	for (i=0; i < 256; i+=2)
181 	{
182 		chksum += ((prom[i] << 8) | prom[i+1]);
183 		if (chksum&0x10000) chksum++;
184 		chksum&=0xffff;
185 	}
186 
187 	chksum=(chksum+1)&0xffff;
188 
189 	if (chksum!=0)
190 	{
191 		chksum=(0x10000-chksum);
192 		prom[0]=(uint8_t)(chksum>>8);
193 		prom[1]=(uint8_t)(chksum&0xff);
194 	}
195 }
196 
keyboard_r(offs_t offset,uint16_t mem_mask)197 uint16_t hp9k_state::keyboard_r(offs_t offset, uint16_t mem_mask)
198 {
199 	//printf("keyboard read at [%x] mask [%x]\n",offset,mem_mask);
200 	return 0x31;
201 }
202 
keyboard_w(offs_t offset,uint16_t data,uint16_t mem_mask)203 void hp9k_state::keyboard_w(offs_t offset, uint16_t data, uint16_t mem_mask)
204 {
205 	//printf("keyboard write of [%x] at [%x]\n",data,offset);
206 }
207 
leds_r(offs_t offset,uint16_t mem_mask)208 uint16_t hp9k_state::leds_r(offs_t offset, uint16_t mem_mask)
209 {
210 	//printf("warning: leds read at [%x] mm [%x]\n",offset,mem_mask);
211 	return 0;
212 }
213 
leds_w(offs_t offset,uint16_t data,uint16_t mem_mask)214 void hp9k_state::leds_w(offs_t offset, uint16_t data, uint16_t mem_mask)
215 {
216 	//printf("warning: leds write of [%x] at [%x] mm [%x]\n",data,offset,mem_mask);
217 }
218 
hp9k_prom_r(offs_t offset,uint16_t mem_mask)219 uint16_t hp9k_state::hp9k_prom_r(offs_t offset, uint16_t mem_mask)
220 {
221 	//if (mem_mask!=0xff) printf("read of PROM at [%x] mem_mask [%x]\n",offset,mem_mask);
222 	int k=prom16a[offset&0xff];
223 	if (mem_mask==0xff00) return (k<<8);
224 	else return k;
225 	//return 0;
226 }
227 
hp9k_prom_w(offs_t offset,uint16_t data,uint16_t mem_mask)228 void hp9k_state::hp9k_prom_w(offs_t offset, uint16_t data, uint16_t mem_mask)
229 {
230 	//printf("Error: write to prom\n");
231 }
232 
hp9k_videoram_r(offs_t offset,uint16_t mem_mask)233 uint16_t hp9k_state::hp9k_videoram_r(offs_t offset, uint16_t mem_mask)
234 {
235 	offset&=0x3fff;
236 
237 	//printf("videoram read at [%x] mem_mask [%x]\n",offset,mem_mask);
238 
239 	if (offset==0x0001)
240 	{
241 		//printf("m6845 read at [%x] mem_mask [%x]\n",offset,mem_mask);
242 		return m_6845->register_r();
243 	}
244 	else
245 	{
246 		if (mem_mask==0xff00)
247 		{
248 			return m_videoram[offset]<<8;
249 		}
250 		else
251 		{
252 			return m_videoram[offset];
253 		}
254 	}
255 }
256 
hp9k_videoram_w(offs_t offset,uint16_t data,uint16_t mem_mask)257 void hp9k_state::hp9k_videoram_w(offs_t offset, uint16_t data, uint16_t mem_mask)
258 {
259 	offset&=0x3fff;
260 
261 	if (offset==0x0000)
262 	{
263 		//printf("6845 address write [%x] at [%x] mask [%x]\n",data,offset,mem_mask);
264 		data&=0x1f;
265 		m_6845->address_w(data);
266 		crtc_curreg=data;
267 	}
268 	else if (offset==0x0001)
269 	{
270 		//printf("6845 register write [%x] at [%x] mask [%x]\n",data,offset,mem_mask);
271 		m_6845->register_w(data);
272 		if (crtc_curreg==0x0c) crtc_addrStartHi=data;
273 		if (crtc_curreg==0x0d) crtc_addrStartLow=data;
274 	}
275 	else
276 	{
277 		//printf("videoram write [%x] at [%x]\n",data,offset);
278 
279 		if (mem_mask==0xff00)
280 			{
281 				m_screenram[offset&0x7ff]=data>>8;
282 				m_videoram[offset&0x3fff]=data>>8;
283 
284 				//uint8_t *rom = machine().region("bootrom")->base();
285 				//rom[0x90B]=0x00;
286 			}
287 			else
288 			{
289 				m_screenram[offset&0x7ff]=data;
290 				m_videoram[offset&0x3fff]=data;
291 			}
292 	}
293 }
294 
buserror_r()295 uint16_t hp9k_state::buserror_r()
296 {
297 	m_maincpu->set_input_line(M68K_LINE_BUSERROR, ASSERT_LINE);
298 	m_maincpu->set_input_line(M68K_LINE_BUSERROR, CLEAR_LINE);
299 	return 0;
300 }
301 
buserror_w(uint16_t data)302 void hp9k_state::buserror_w(uint16_t data)
303 {
304 	m_maincpu->set_input_line(M68K_LINE_BUSERROR, ASSERT_LINE);
305 	m_maincpu->set_input_line(M68K_LINE_BUSERROR, CLEAR_LINE);
306 }
307 
hp9k_mem(address_map & map)308 void hp9k_state::hp9k_mem(address_map &map)
309 {
310 	map.unmap_value_high();
311 	map(0x000000, 0x000909).rom().region("bootrom", 0);
312 	map(0x00090a, 0x00090d).rw(FUNC(hp9k_state::leds_r), FUNC(hp9k_state::leds_w));
313 	map(0x00090e, 0x00ffff).rom().region("bootrom", 0x90e);
314 	map(0x010000, 0x427fff).rw(FUNC(hp9k_state::buserror_r), FUNC(hp9k_state::buserror_w));
315 	map(0x428000, 0x428fff).rw(FUNC(hp9k_state::keyboard_r), FUNC(hp9k_state::keyboard_w));
316 	map(0x429000, 0x50ffff).rw(FUNC(hp9k_state::buserror_r), FUNC(hp9k_state::buserror_w));
317 	map(0x510000, 0x51ffff).rw(FUNC(hp9k_state::hp9k_videoram_r), FUNC(hp9k_state::hp9k_videoram_w));
318 	map(0x520000, 0x52ffff).rw(FUNC(hp9k_state::buserror_r), FUNC(hp9k_state::buserror_w));
319 	map(0x530000, 0x53ffff).ram(); // graphic memory
320 	map(0x540000, 0x5effff).rw(FUNC(hp9k_state::buserror_r), FUNC(hp9k_state::buserror_w));
321 	map(0x5f0000, 0x5f3fff).rw(FUNC(hp9k_state::hp9k_prom_r), FUNC(hp9k_state::hp9k_prom_w));
322 	//map(0x5f0000, 0x5f3fff).rw(FUNC(hp9k_state::buserror_r), FUNC(hp9k_state::buserror_w));
323 	map(0x5f4000, 0xfbffff).rw(FUNC(hp9k_state::buserror_r), FUNC(hp9k_state::buserror_w));
324 	map(0xFC0000, 0xffffff).ram(); // system ram
325 }
326 
327 
328 /* Input ports */
INPUT_PORTS_START(hp9k)329 static INPUT_PORTS_START( hp9k )
330 INPUT_PORTS_END
331 
332 
333 void hp9k_state::init_hp9k()
334 {
335 }
336 
337 static const gfx_layout hp9k_charlayout =
338 {
339 	HP9816_CHDIMX, HP9816_CHDIMY,
340 	256,                    /* 256 characters */
341 	1,                  /* 1 bits per pixel */
342 	{ 0 },                  /* no bitplanes */
343 	/* x offsets */
344 	{ STEP8(0,1) },
345 	/* y offsets */
346 	{ STEP16(0,8) },
347 	8*16                    /* every char takes 16 bytes */
348 };
349 
350 static GFXDECODE_START( gfx_hp9k )
351 	GFXDECODE_ENTRY( "bootrom", 0x2000, hp9k_charlayout, 0, 1 )
352 GFXDECODE_END
353 
putChar(uint8_t thec,int x,int y,bitmap_ind16 & bitmap)354 void hp9k_state::putChar(uint8_t thec,int x,int y,bitmap_ind16 &bitmap)
355 {
356 	uint8_t const *const pchar=m_gfxdecode->gfx(0)->get_data(thec);
357 
358 	for (int py=0;py<HP9816_CHDIMY;py++)
359 	{
360 		for (int px=0;px<HP9816_CHDIMX;px++)
361 		{
362 			bitmap.pix((y*(HP9816_CHDIMY))+py,(x*(HP9816_CHDIMX))+px) = pchar[px+(py*8)];
363 		}
364 	}
365 }
366 
screen_update(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)367 uint32_t hp9k_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
368 {
369 	//uint8_t* pvram=&m_screenram[1];
370 
371 	int startAddr=((crtc_addrStartLow&0xff)|((crtc_addrStartHi<<8)))&0x3fff;
372 	int chStart=startAddr&0x1fff;
373 
374 	for (int r=0;r<HP9816_ROWY;r++)
375 	{
376 		for (int c=0;c<HP9816_ROWX;c++)
377 		{
378 			//uint8_t thec=pvram[((c+(r*80))+160+47)&0x7ff];
379 			//uint8_t thec=m_videoram[((c+(r*80))+startAddr)];
380 			uint8_t thec=m_screenram[chStart&0x7ff];
381 			putChar(thec,c,r,bitmap);
382 			chStart++;
383 		}
384 	}
385 
386 	//putChar(0x44,0,0,pscr);
387 	return 0;
388 }
389 
kbd_put(uint8_t data)390 void hp9k_state::kbd_put(uint8_t data)
391 {
392 	kbdBit=data;
393 }
394 
395 
hp9k(machine_config & config)396 void hp9k_state::hp9k(machine_config &config)
397 {
398 	/* basic machine hardware */
399 	M68000(config, m_maincpu, XTAL(8'000'000));
400 	m_maincpu->set_addrmap(AS_PROGRAM, &hp9k_state::hp9k_mem);
401 
402 	/* video hardware */
403 
404 	screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
405 	screen.set_refresh_hz(50);
406 	screen.set_vblank_time(ATTOSECONDS_IN_USEC(0));
407 	screen.set_size(HP9816_ROWX*HP9816_CHDIMX, HP9816_ROWY*HP9816_CHDIMY);
408 	screen.set_visarea(0, (HP9816_ROWX*HP9816_CHDIMX)-1, 0, (HP9816_ROWY*HP9816_CHDIMY)-1);
409 	screen.set_screen_update(FUNC(hp9k_state::screen_update));
410 	screen.set_palette("palette");
411 
412 	GFXDECODE(config, m_gfxdecode, "palette", gfx_hp9k);
413 	PALETTE(config, "palette", palette_device::MONOCHROME);
414 
415 	MC6845(config, m_6845, XTAL(16'000'000) / 16);
416 	m_6845->set_screen("screen");
417 	m_6845->set_show_border_area(false);
418 	m_6845->set_char_width(8);
419 }
420 
421 /* ROM definition */
422 ROM_START( hp9816 )
423 	ROM_REGION16_BE(0x10000, "bootrom", 0)
424 
425 	ROM_DEFAULT_BIOS("bios40")
426 	ROM_SYSTEM_BIOS(0, "bios40",  "Bios v4.0")
427 	ROMX_LOAD( "rom40.bin", 0x0000, 0x10000, CRC(36005480) SHA1(645a077ffd95e4c31f05cd8bbd6e4554b12813f1), ROM_BIOS(0) )
428 	ROM_SYSTEM_BIOS(1, "bios30",  "Bios v3.0")
429 	ROMX_LOAD( "rom30.bin", 0x0000, 0x10000, CRC(05c07e75) SHA1(3066a65e6137482041f9a77d09ee2289fe0974aa), ROM_BIOS(1) )
430 
431 ROM_END
432 
433 /* Driver */
434 
435 /*    YEAR  NAME    PARENT  COMPAT  MACHINE  INPUT  CLASS       INIT       COMPANY            FULLNAME   FLAGS */
436 COMP( 1982, hp9816, 0,      0,      hp9k,    hp9k,  hp9k_state, init_hp9k, "Hewlett Packard", "HP 9816", MACHINE_NOT_WORKING | MACHINE_NO_SOUND )
437