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