1 // license:GPL-2.0+
2 // copyright-holders:Raphael Nabet
3 /*****************************************************************************
4  *
5  * includes/pdp1.h
6  *
7  ****************************************************************************/
8 
9 #ifndef MAME_INCLUDES_PDP1_H
10 #define MAME_INCLUDES_PDP1_H
11 
12 #include "cpu/pdp1/pdp1.h"
13 #include "video/crt.h"
14 #include "emupal.h"
15 
16 /* defines for each bit and mask in input port "CSW" */
17 enum
18 {
19 	/* bit numbers */
20 	pdp1_control_bit = 0,
21 
22 	pdp1_extend_bit     = 1,
23 	pdp1_start_nobrk_bit= 2,
24 	pdp1_start_brk_bit  = 3,
25 	pdp1_stop_bit       = 4,
26 	pdp1_continue_bit   = 5,
27 	pdp1_examine_bit    = 6,
28 	pdp1_deposit_bit    = 7,
29 	pdp1_read_in_bit    = 8,
30 	pdp1_reader_bit     = 9,
31 	pdp1_tape_feed_bit  = 10,
32 	pdp1_single_step_bit= 11,
33 	pdp1_single_inst_bit= 12,
34 
35 	/* masks */
36 	pdp1_control = (1 << pdp1_control_bit),
37 	pdp1_extend = (1 << pdp1_extend_bit),
38 	pdp1_start_nobrk = (1 << pdp1_start_nobrk_bit),
39 	pdp1_start_brk = (1 << pdp1_start_brk_bit),
40 	pdp1_stop = (1 << pdp1_stop_bit),
41 	pdp1_continue = (1 << pdp1_continue_bit),
42 	pdp1_examine = (1 << pdp1_examine_bit),
43 	pdp1_deposit = (1 << pdp1_deposit_bit),
44 	pdp1_read_in = (1 << pdp1_read_in_bit),
45 	pdp1_reader = (1 << pdp1_reader_bit),
46 	pdp1_tape_feed = (1 << pdp1_tape_feed_bit),
47 	pdp1_single_step = (1 << pdp1_single_step_bit),
48 	pdp1_single_inst = (1 << pdp1_single_inst_bit)
49 };
50 
51 /* defines for each bit in input port pdp1_spacewar_controllers*/
52 #define ROTATE_LEFT_PLAYER1       0x01
53 #define ROTATE_RIGHT_PLAYER1      0x02
54 #define THRUST_PLAYER1            0x04
55 #define FIRE_PLAYER1              0x08
56 #define ROTATE_LEFT_PLAYER2       0x10
57 #define ROTATE_RIGHT_PLAYER2      0x20
58 #define THRUST_PLAYER2            0x40
59 #define FIRE_PLAYER2              0x80
60 #define HSPACE_PLAYER1            0x100
61 #define HSPACE_PLAYER2            0x200
62 
63 /* defines for each field in input port pdp1_config */
64 enum
65 {
66 	pdp1_config_extend_bit          = 0,
67 	pdp1_config_extend_mask         = 0x3,  /* 2 bits */
68 	pdp1_config_hw_mul_div_bit      = 2,
69 	pdp1_config_hw_mul_div_mask     = 0x1,
70 	/*pdp1_config_hw_obsolete_bit   = 3,
71 	pdp1_config_hw_obsolete_mask    = 0x1,*/
72 	pdp1_config_type_20_sbs_bit     = 4,
73 	pdp1_config_type_20_sbs_mask    = 0x1,
74 	pdp1_config_lightpen_bit        = 5,
75 	pdp1_config_lightpen_mask       = 0x1
76 };
77 
78 /* defines for each field in input port pdp1_lightpen_state */
79 enum
80 {
81 	pdp1_lightpen_down_bit          = 0,
82 	pdp1_lightpen_smaller_bit       = 1,
83 	pdp1_lightpen_larger_bit        = 2,
84 
85 	pdp1_lightpen_down              = (1 << pdp1_lightpen_down_bit),
86 	pdp1_lightpen_smaller           = (1 << pdp1_lightpen_smaller_bit),
87 	pdp1_lightpen_larger            = (1 << pdp1_lightpen_larger_bit)
88 };
89 
90 /* defines for our font */
91 enum
92 {
93 	pdp1_charnum = /*104*/128,  /* ASCII set + 8 special characters */
94 									/* for whatever reason, 104 breaks some characters */
95 
96 	pdp1_fontdata_size = 8 * pdp1_charnum
97 };
98 
99 enum
100 {
101 	/* size and position of crt window */
102 	crt_window_width = 512,
103 	crt_window_height = 512,
104 	crt_window_offset_x = 0,
105 	crt_window_offset_y = 0,
106 	/* size and position of operator control panel window */
107 	panel_window_width = 384,
108 	panel_window_height = 128,
109 	panel_window_offset_x = crt_window_width,
110 	panel_window_offset_y = 0,
111 	/* size and position of typewriter window */
112 	typewriter_window_width = 640,
113 	typewriter_window_height = 160,
114 	typewriter_window_offset_x = 0,
115 	typewriter_window_offset_y = crt_window_height
116 };
117 
118 enum
119 {
120 	total_width = crt_window_width + panel_window_width,
121 	total_height = crt_window_height + typewriter_window_height,
122 
123 	/* respect 4:3 aspect ratio to keep pixels square */
124 	virtual_width_1 = ((total_width+3)/4)*4,
125 	virtual_height_1 = ((total_height+2)/3)*3,
126 	virtual_width_2 = virtual_height_1*4/3,
127 	virtual_height_2 = virtual_width_1*3/4,
128 	virtual_width = (virtual_width_1 > virtual_width_2) ? virtual_width_1 : virtual_width_2,
129 	virtual_height = (virtual_height_1 > virtual_height_2) ? virtual_height_1 : virtual_height_2
130 };
131 
132 enum
133 {   /* refresh rate in Hz: can be changed at will */
134 	refresh_rate = 60
135 };
136 
137 /* Color codes */
138 enum
139 {
140 	/* first pen_crt_num_levels colors used for CRT (with remanence) */
141 	pen_crt_num_levels = 69,
142 	pen_crt_max_intensity = pen_crt_num_levels-1,
143 
144 	/* next colors used for control panel and typewriter */
145 	pen_black = pen_crt_num_levels,
146 	pen_white,
147 	pen_green,
148 	pen_dk_green,
149 	pen_red,
150 	pen_lt_gray,
151 
152 	/* color constants for control panel */
153 	pen_panel_bg = pen_black,
154 	pen_panel_caption = pen_white,
155 	color_panel_caption = 0,
156 	pen_switch_nut = pen_lt_gray,
157 	pen_switch_button = pen_white,
158 	pen_lit_lamp = pen_green,
159 	pen_unlit_lamp = pen_dk_green,
160 
161 	/* color constants for typewriter */
162 	pen_typewriter_bg = pen_white,
163 	color_typewriter_black = 1,
164 	color_typewriter_red = 2,
165 
166 	/* color constants used for light pen */
167 	pen_lightpen_nonpressed = pen_red,
168 	pen_lightpen_pressed = pen_green
169 };
170 
171 class pdp1_state;
172 
173 // tape reader device
174 class pdp1_readtape_image_device :  public device_t,
175 									public device_image_interface
176 {
177 public:
178 	// construction/destruction
179 	pdp1_readtape_image_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0U);
180 
st_ptr()181 	auto st_ptr() { return m_st_ptr.bind(); }
182 
183 	void iot_rpa(int op2, int nac, int mb, int &io, int ac);
184 	void iot_rpb(int op2, int nac, int mb, int &io, int ac);
185 	void iot_rrb(int op2, int nac, int mb, int &io, int ac);
186 
187 protected:
188 	// device-level overrides
189 	virtual void device_resolve_objects() override;
190 	virtual void device_start() override;
191 
192 	// image-level overrides
image_type()193 	virtual iodevice_t image_type() const noexcept override { return IO_PUNCHTAPE; }
194 
is_readable()195 	virtual bool is_readable()  const noexcept override { return true; }
is_writeable()196 	virtual bool is_writeable() const noexcept override { return false; }
is_creatable()197 	virtual bool is_creatable() const noexcept override { return false; }
must_be_loaded()198 	virtual bool must_be_loaded() const noexcept override { return false; }
is_reset_on_load()199 	virtual bool is_reset_on_load() const noexcept override { return false; }
file_extensions()200 	virtual const char *file_extensions() const noexcept override { return "tap,rim"; }
201 
202 	virtual image_init_result call_load() override;
203 	virtual void call_unload() override;
204 
205 public:
206 	TIMER_CALLBACK_MEMBER(reader_callback);
207 
208 	int tape_read(uint8_t *reply);
209 	void begin_tape_read(int binary, int nac);
210 
211 	required_device<pdp1_device> m_maincpu;
212 
213 	devcb_write_line m_st_ptr;
214 
215 	int m_motor_on; // 1-bit reader motor on
216 
217 	int m_rb;       // 18-bit reader buffer
218 	int m_rcl;      // 1-bit reader clutch
219 	int m_rc;       // 2-bit reader counter
220 	int m_rby;      // 1-bit reader binary mode flip-flop
221 	int m_rcp;      // 1-bit reader "need a completion pulse" flip-flop
222 
223 	emu_timer *m_timer;     // timer to simulate reader timing
224 };
225 
226 
227 
228 // tape puncher device
229 class pdp1_punchtape_image_device : public device_t,
230 									public device_image_interface
231 {
232 public:
233 	// construction/destruction
234 	pdp1_punchtape_image_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0U);
235 
st_ptp()236 	auto st_ptp() { return m_st_ptp.bind(); }
237 
238 	void iot_ppa(int op2, int nac, int mb, int &io, int ac);
239 	void iot_ppb(int op2, int nac, int mb, int &io, int ac);
240 
241 protected:
242 	// device-level overrides
243 	virtual void device_resolve_objects() override;
244 	virtual void device_start() override;
245 
246 	// image-level overrides
image_type()247 	virtual iodevice_t image_type() const noexcept override { return IO_PUNCHTAPE; }
248 
is_readable()249 	virtual bool is_readable()  const noexcept override { return false; }
is_writeable()250 	virtual bool is_writeable() const noexcept override { return true; }
is_creatable()251 	virtual bool is_creatable() const noexcept override { return true; }
must_be_loaded()252 	virtual bool must_be_loaded() const noexcept override { return false; }
is_reset_on_load()253 	virtual bool is_reset_on_load() const noexcept override { return false; }
file_extensions()254 	virtual const char *file_extensions() const noexcept override { return "tap,rim"; }
255 
256 	virtual image_init_result call_load() override;
257 	virtual void call_unload() override;
258 
259 public:
260 	TIMER_CALLBACK_MEMBER(puncher_callback);
261 
262 	void tape_write(uint8_t data);
263 
264 	required_device<pdp1_device> m_maincpu;
265 
266 	devcb_write_line m_st_ptp;
267 
268 	emu_timer *m_timer;     // timer to generate completion pulses
269 };
270 
271 
272 
273 // typewriter device
274 class pdp1_typewriter_device :   public device_t,
275 									public device_image_interface
276 {
277 public:
278 	// construction/destruction
279 	pdp1_typewriter_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0U);
280 
st_tyo()281 	auto st_tyo() { return m_st_tyo.bind(); }
st_tyi()282 	auto st_tyi() { return m_st_tyi.bind(); }
283 
284 	void iot_tyo(int op2, int nac, int mb, int &io, int ac);
285 	void iot_tyi(int op2, int nac, int mb, int &io, int ac);
286 
287 protected:
288 	// device-level overrides
289 	virtual void device_resolve_objects() override;
290 	virtual void device_start() override;
291 
292 	// image-level overrides
image_type()293 	virtual iodevice_t image_type() const noexcept override { return IO_PRINTER; }
294 
is_readable()295 	virtual bool is_readable()  const noexcept override { return false; }
is_writeable()296 	virtual bool is_writeable() const noexcept override { return true; }
is_creatable()297 	virtual bool is_creatable() const noexcept override { return true; }
must_be_loaded()298 	virtual bool must_be_loaded() const noexcept override { return false; }
is_reset_on_load()299 	virtual bool is_reset_on_load() const noexcept override { return false; }
file_extensions()300 	virtual const char *file_extensions() const noexcept override { return "typ"; }
301 
302 	virtual image_init_result call_load() override;
303 	virtual void call_unload() override;
304 
305 public:
306 	TIMER_CALLBACK_MEMBER(tyo_callback);
307 
308 	void linefeed();
309 	void drawchar(int character);
310 	void typewriter_out(uint8_t data);
311 
312 	void pdp1_keyboard();
313 
314 	required_device<pdp1_device> m_maincpu;
315 	required_device<pdp1_state> m_driver_state;
316 	required_ioport_array<4> m_twr;
317 
318 	devcb_write_line m_st_tyo;
319 	devcb_write_line m_st_tyi;
320 
321 	int m_tb;       // typewriter buffer
322 
323 	emu_timer *m_tyo_timer; // timer to generate completion pulses
324 
325 	int m_old_typewriter_keys[4];
326 	int m_color;
327 	bitmap_ind16 m_bitmap;
328 	int m_pos;
329 	int m_case_shift;
330 };
331 
332 // MIT parallel drum (mostly similar to type 23)
333 class pdp1_cylinder_image_device :  public device_t,
334 									public device_image_interface
335 {
336 public:
337 	// construction/destruction
338 	pdp1_cylinder_image_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0U);
339 
340 	void iot_dia(int op2, int nac, int mb, int &io, int ac);
341 	void iot_dba(int op2, int nac, int mb, int &io, int ac);
342 	void iot_dcc(int op2, int nac, int mb, int &io, int ac);
343 	void iot_dra(int op2, int nac, int mb, int &io, int ac);
344 
345 protected:
346 	// device-level overrides
347 	virtual void device_start() override;
348 
349 	// image-level overrides
image_type()350 	virtual iodevice_t image_type() const noexcept override { return IO_CYLINDER; }
351 
is_readable()352 	virtual bool is_readable()  const noexcept override { return true; }
is_writeable()353 	virtual bool is_writeable() const noexcept override { return true; }
is_creatable()354 	virtual bool is_creatable() const noexcept override { return true; }
must_be_loaded()355 	virtual bool must_be_loaded() const noexcept override { return false; }
is_reset_on_load()356 	virtual bool is_reset_on_load() const noexcept override { return false; }
file_extensions()357 	virtual const char *file_extensions() const noexcept override { return "drm"; }
358 
359 	virtual image_init_result call_load() override;
360 	virtual void call_unload() override;
361 
362 public:
363 	void set_il(int il);
364 	uint32_t drum_read(int field, int position);
365 	void drum_write(int field, int position, uint32_t data);
366 
367 	required_device<pdp1_device> m_maincpu;
368 
369 	int m_il;       // initial location (12-bit)
370 	int m_wc;       // word counter (12-bit)
371 	int m_wcl;      // word core location counter (16-bit)
372 	int m_rfb;      // read field buffer (5-bit)
373 	int m_wfb;      // write field buffer (5-bit)
374 
375 	int m_dba;
376 
377 	emu_timer *m_rotation_timer;// timer called each time dc is 0
378 	emu_timer *m_il_timer;      // timer called each time dc is il
379 };
380 
381 
382 struct lightpen_t
383 {
384 	char active;
385 	char down;
386 	short x, y;
387 	short radius;
388 };
389 
390 
391 class pdp1_state : public driver_device
392 {
393 public:
pdp1_state(const machine_config & mconfig,device_type type,const char * tag)394 	pdp1_state(const machine_config &mconfig, device_type type, const char *tag)
395 		: driver_device(mconfig, type, tag),
396 		m_maincpu(*this, "maincpu"),
397 		m_tape_reader(*this, "readt"),
398 		m_tape_puncher(*this, "punch"),
399 		m_typewriter(*this, "typewriter"),
400 		m_parallel_drum(*this, "drum"),
401 		m_gfxdecode(*this, "gfxdecode"),
402 		m_palette(*this, "palette"),
403 		m_crt(*this, "crt"),
404 		m_spacewar(*this, "SPACEWAR"),
405 		m_csw(*this, "CSW"),
406 		m_sense(*this, "SENSE"),
407 		m_tstadd(*this, "TSTADD"),
408 		m_twdmsb(*this, "TWDMSB"),
409 		m_twdlsb(*this, "TWDLSB"),
410 		m_cfg(*this, "CFG"),
411 		m_io_lightpen(*this, "LIGHTPEN"),
412 		m_lightx(*this, "LIGHTX"),
413 		m_lighty(*this, "LIGHTY")
414 	{ }
415 
416 	required_device<pdp1_device> m_maincpu;
417 	required_device<pdp1_readtape_image_device> m_tape_reader;
418 	required_device<pdp1_punchtape_image_device> m_tape_puncher;
419 	required_device<pdp1_typewriter_device> m_typewriter;
420 	required_device<pdp1_cylinder_image_device> m_parallel_drum;
421 	int m_io_status;
422 	emu_timer *m_dpy_timer;
423 	lightpen_t m_lightpen;
424 
425 	virtual void machine_start() override;
426 	virtual void machine_reset() override;
427 	virtual void video_start() override;
428 	void pdp1_palette(palette_device &palette) const;
429 	uint32_t screen_update_pdp1(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
430 	DECLARE_WRITE_LINE_MEMBER(screen_vblank_pdp1);
431 	INTERRUPT_GEN_MEMBER(pdp1_interrupt);
432 	TIMER_CALLBACK_MEMBER(dpy_callback);
433 	void pdp1_machine_stop();
434 	inline void pdp1_plot_pixel(bitmap_ind16 &bitmap, int x, int y, uint32_t color);
435 	void pdp1_plot(int x, int y);
436 	void pdp1_draw_led(bitmap_ind16 &bitmap, int x, int y, int state);
437 	void pdp1_draw_multipleled(bitmap_ind16 &bitmap, int x, int y, int value, int nb_bits);
438 	void pdp1_draw_switch(bitmap_ind16 &bitmap, int x, int y, int state);
439 	void pdp1_draw_multipleswitch(bitmap_ind16 &bitmap, int x, int y, int value, int nb_bits);
440 	void pdp1_draw_char(bitmap_ind16 &bitmap, char character, int x, int y, int color);
441 	void pdp1_draw_string(bitmap_ind16 &bitmap, const char *buf, int x, int y, int color);
442 	void pdp1_draw_panel_backdrop(bitmap_ind16 &bitmap);
443 	void pdp1_draw_panel(bitmap_ind16 &bitmap);
444 	void pdp1_update_lightpen_state(const lightpen_t *new_state);
445 	void pdp1_draw_circle(bitmap_ind16 &bitmap, int x, int y, int radius, int color_);
446 	void pdp1_erase_lightpen(bitmap_ind16 &bitmap);
447 	void pdp1_draw_lightpen(bitmap_ind16 &bitmap);
448 	void pdp1_lightpen();
449 
450 	template <int Mask> DECLARE_WRITE_LINE_MEMBER(io_status_w);
451 
452 	void pdp1(machine_config &config);
453 	void pdp1_map(address_map &map);
454 private:
455 	void iot_dpy(int op2, int nac, int mb, int &io, int ac);
456 
457 	void iot_011(int op2, int nac, int mb, int &io, int ac);
458 
459 	void iot_cks(int op2, int nac, int mb, int &io, int ac);
460 
461 	void io_start_clear();
462 
463 	pdp1_reset_param_t m_reset_param;
464 	int m_old_lightpen;
465 	int m_old_control_keys;
466 	int m_old_tw_keys;
467 	int m_old_ta_keys;
468 	bitmap_ind16 m_panel_bitmap;
469 	lightpen_t m_lightpen_state;
470 	lightpen_t m_previous_lightpen_state;
471 
472 public:
473 	required_device<gfxdecode_device> m_gfxdecode;
474 	required_device<palette_device> m_palette;
475 	required_device<crt_device> m_crt;
476 	required_ioport m_spacewar;
477 	required_ioport m_csw;
478 	required_ioport m_sense;
479 	required_ioport m_tstadd;
480 	required_ioport m_twdmsb;
481 	required_ioport m_twdlsb;
482 	required_ioport m_cfg;
483 	required_ioport m_io_lightpen;
484 	required_ioport m_lightx;
485 	required_ioport m_lighty;
486 };
487 
488 #endif // MAME_INCLUDES_PDP1_H
489