summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/video/antic.h
blob: 2bc9420814582446375017b95322e14616c868bb (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
// license:GPL-2.0+
// copyright-holders:Juergen Buchmueller
/***************************************************************************

    Atari 400/800

    ANTIC video controller

    Juergen Buchmueller, June 1998

***************************************************************************/

#ifndef MAME_VIDEO_ANTIC_H
#define MAME_VIDEO_ANTIC_H

#pragma once

#include "video/gtia.h"


class antic_device : public device_t, public device_video_interface
{
private:
	static constexpr unsigned   VBL_END             = 8;    // vblank ends in this scanline
	static constexpr unsigned   VDATA_START         = 11;   // video display begins in this scanline
	static constexpr unsigned   VDATA_END           = 244;  // video display ends in this scanline
	static constexpr unsigned   VBL_START           = 248;  // vblank starts in this scanline

public:
	// total number of lines per frame (incl. vblank)
	static constexpr unsigned   TOTAL_LINES_60HZ    = 262;
	static constexpr unsigned   TOTAL_LINES_50HZ    = 312;

	// frame rates
	static constexpr double     FRAME_RATE_50HZ     = 1789790.0 / 114 / TOTAL_LINES_50HZ;
	static constexpr double     FRAME_RATE_60HZ     = 1789790.0 / 114 / TOTAL_LINES_60HZ;

	static constexpr unsigned   HWIDTH              = 48;   // total characters per line
	static constexpr unsigned   VHEIGHT             = 32;
	static constexpr unsigned   MIN_X               = ((HWIDTH - 42) / 2) * 8;
	static constexpr unsigned   MAX_X               = MIN_X + (42 * 8) - 1;
	static constexpr unsigned   MIN_Y               = VDATA_START;
	static constexpr unsigned   MAX_Y               = VDATA_END - 8 - 1;

	// construction/destruction
	antic_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);

	// device-level overrides
	virtual void device_start() override;
	virtual void device_reset() override;
	virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;

	template <typename T> void set_gtia_tag(T &&tag) { m_gtia.set_tag(std::forward<T>(tag)); }

	DECLARE_READ8_MEMBER( read );
	DECLARE_WRITE8_MEMBER( write );

	uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
	void generic_interrupt(int button_count);

private:
	static constexpr device_timer_id TIMER_CYCLE_STEAL = 0;
	static constexpr device_timer_id TIMER_ISSUE_DLI = 1;
	static constexpr device_timer_id TIMER_LINE_REND = 2;
	static constexpr device_timer_id TIMER_LINE_DONE = 3;

	static constexpr unsigned   HCHARS              = 44;   // visible characters per line
	static constexpr unsigned   VCHARS              = (VDATA_END - VDATA_START + 7) / 8;
	static constexpr unsigned   BUF_OFFS0           = (HWIDTH - HCHARS) / 2;

	struct ANTIC_R {
		uint8_t   antic00;    /* 00 nothing */
		uint8_t   antic01;    /* 01 nothing */
		uint8_t   antic02;    /* 02 nothing */
		uint8_t   antic03;    /* 03 nothing */
		uint8_t   antic04;    /* 04 nothing */
		uint8_t   antic05;    /* 05 nothing */
		uint8_t   antic06;    /* 06 nothing */
		uint8_t   antic07;    /* 07 nothing */
		uint8_t   antic08;    /* 08 nothing */
		uint8_t   antic09;    /* 09 nothing */
		uint8_t   antic0a;    /* 0a nothing */
		uint8_t   vcount;     /* 0b vertical (scanline) counter */
		uint8_t   penh;       /* 0c light pen horizontal pos */
		uint8_t   penv;       /* 0d light pen vertical pos */
		uint8_t   antic0e;    /* 0e nothing */
		uint8_t   nmist;      /* 0f NMI status */
	};  /* read registers */

	struct ANTIC_W {
		uint8_t   dmactl;     /* 00 write DMA control */
		uint8_t   chactl;     /* 01 write character control */
		uint8_t   dlistl;     /* 02 display list low */
		uint8_t   dlisth;     /* 03 display list high */
		uint8_t   hscrol;     /* 04 horz scroll */
		uint8_t   vscrol;     /* 05 vert scroll */
		uint8_t   pmbasl;     /* 06 player/missile base addr low */
		uint8_t   pmbash;     /* 07 player/missile base addr high */
		uint8_t   chbasl;     /* 08 character generator base addr low */
		uint8_t   chbash;     /* 09 character generator base addr high */
		uint8_t   wsync;      /* 0a wait for hsync */
		uint8_t   antic0b;    /* 0b nothing */
		uint8_t   antic0c;    /* 0c nothing */
		uint8_t   antic0d;    /* 0d nothing */
		uint8_t   nmien;      /* 0e NMI enable */
		uint8_t   nmires;     /* 0f NMI reset */
	};  /* write registers */

	/* per scanline buffer for video data (and optimization variables) */
	struct VIDEO {
		uint32_t  cmd;                /* antic command for this scanline */
		uint16_t  data[HWIDTH];       /* graphics data buffer (text through chargen) */
	};


	required_device<gtia_device> m_gtia;
	required_device<cpu_device> m_maincpu;
	optional_ioport m_djoy_b;
	optional_ioport m_artifacts;

	uint32_t m_tv_artifacts;
	int m_render1, m_render2, m_render3;

	inline void mode_0(address_space &space, VIDEO *video);
	inline void mode_2(address_space &space, VIDEO *video, int bytes, int erase);
	inline void mode_3(address_space &space, VIDEO *video, int bytes, int erase);
	inline void mode_4(address_space &space, VIDEO *video, int bytes, int erase);
	inline void mode_5(address_space &space, VIDEO *video, int bytes, int erase);
	inline void mode_6(address_space &space, VIDEO *video, int bytes, int erase);
	inline void mode_7(address_space &space, VIDEO *video, int bytes, int erase);
	inline void mode_8(address_space &space, VIDEO *video, int bytes, int erase);
	inline void mode_9(address_space &space, VIDEO *video, int bytes, int erase);
	inline void mode_a(address_space &space, VIDEO *video, int bytes, int erase);
	inline void mode_b(address_space &space, VIDEO *video, int bytes, int erase);
	inline void mode_c(address_space &space, VIDEO *video, int bytes, int erase);
	inline void mode_d(address_space &space, VIDEO *video, int bytes, int erase);
	inline void mode_e(address_space &space, VIDEO *video, int bytes, int erase);
	inline void mode_f(address_space &space, VIDEO *video, int bytes, int erase);
	inline void mode_gtia1(address_space &space, VIDEO *video, int bytes, int erase);
	inline void mode_gtia2(address_space &space, VIDEO *video, int bytes, int erase);
	inline void mode_gtia3(address_space &space, VIDEO *video, int bytes, int erase);

	uint32_t  m_cmd;                /* currently executed display list command */
	uint32_t  m_steal_cycles;       /* steal how many cpu cycles for this line ? */
	uint32_t  m_vscrol_old;         /* old vscrol value */
	uint32_t  m_hscrol_old;         /* old hscrol value */
	int32_t   m_modelines;          /* number of lines for current ANTIC mode */
	uint32_t  m_chbase;             /* character mode source base */
	uint32_t  m_chand;              /* character and mask (chactl) */
	uint32_t  m_chxor;              /* character xor mask (chactl) */
	uint32_t  m_scanline;           /* current scan line */
	uint32_t  m_pfwidth;            /* playfield width */
	uint32_t  m_dpage;              /* display list address page */
	uint32_t  m_doffs;              /* display list offset into page */
	uint32_t  m_vpage;              /* video data source page */
	uint32_t  m_voffs;              /* video data offset into page */
	uint32_t  m_pmbase_s;           /* p/m graphics single line source base */
	uint32_t  m_pmbase_d;           /* p/m graphics double line source base */
	ANTIC_R m_r;                  /* ANTIC read registers */
	ANTIC_W m_w;                  /* ANTIC write registers */
	uint8_t   m_cclock[256+32];     /* color clock buffer filled by ANTIC */
	uint8_t   m_pmbits[256+32];     /* player missile buffer filled by GTIA */
	std::unique_ptr<uint8_t[]>   m_prio_table[64];    /* player/missile priority tables */
	std::unique_ptr<VIDEO[]>     m_video;             /* video buffer */
	std::unique_ptr<uint32_t[]>  m_cclk_expand;       /* shared buffer for the following: */
	uint32_t  *m_pf_21;             /* 1cclk 2 color txt 2,3 */
	uint32_t  *m_pf_x10b;           /* 1cclk 4 color txt 4,5, gfx D,E */
	uint32_t  *m_pf_3210b2;         /* 1cclk 5 color txt 6,7, gfx 9,B,C */
	uint32_t  *m_pf_210b4;          /* 4cclk 4 color gfx 8 */
	uint32_t  *m_pf_210b2;          /* 2cclk 4 color gfx A */
	uint32_t  *m_pf_1b;             /* 1cclk hires gfx F */
	uint32_t  *m_pf_gtia1;          /* 1cclk gtia mode 1 */
	uint32_t  *m_pf_gtia2;          /* 1cclk gtia mode 2 */
	uint32_t  *m_pf_gtia3;          /* 1cclk gtia mode 3 */
	std::unique_ptr<uint8_t[]>   m_used_colors;       /* shared buffer for the following: */
	uint8_t   *m_uc_21;             /* used colors for txt (2,3) */
	uint8_t   *m_uc_x10b;           /* used colors for txt 4,5, gfx D,E */
	uint8_t   *m_uc_3210b2;         /* used colors for txt 6,7, gfx 9,B,C */
	uint8_t   *m_uc_210b4;          /* used colors for gfx 8 */
	uint8_t   *m_uc_210b2;          /* used colors for gfx A */
	uint8_t   *m_uc_1b;             /* used colors for gfx F */
	uint8_t   *m_uc_g1;             /* used colors for gfx GTIA 1 */
	uint8_t   *m_uc_g2;             /* used colors for gfx GTIA 2 */
	uint8_t   *m_uc_g3;             /* used colors for gfx GTIA 3 */
	std::unique_ptr<bitmap_ind16> m_bitmap;

	void prio_init();
	void cclk_init();

	void artifacts_gfx(uint8_t *src, uint8_t *dst, int width);
	void artifacts_txt(uint8_t *src, uint8_t *dst, int width);

	void linerefresh();
	int cycle();

	TIMER_CALLBACK_MEMBER( issue_dli );
	TIMER_CALLBACK_MEMBER( line_done );
	TIMER_CALLBACK_MEMBER( steal_cycles );
	TIMER_CALLBACK_MEMBER( scanline_render );

	void render(address_space &space, int param1, int param2, int param3);

	inline void LMS(int new_cmd);
	void scanline_dma(int param);
};


// device type definition
DECLARE_DEVICE_TYPE(ATARI_ANTIC, antic_device)

#endif // MAME_VIDEO_ANTIC_H