1 // license:BSD-3-Clause
2 // copyright-holders:Olivier Galibert
3 #ifndef MAME_INCLUDES_MODEL1_H
4 #define MAME_INCLUDES_MODEL1_H
5 
6 #pragma once
7 
8 #include "audio/dsbz80.h"
9 #include "audio/segam1audio.h"
10 
11 #include "cpu/mb86233/mb86233.h"
12 #include "cpu/v60/v60.h"
13 #include "machine/i8251.h"
14 #include "machine/gen_fifo.h"
15 #include "machine/mb8421.h"
16 #include "machine/m1comm.h"
17 #include "machine/timer.h"
18 #include "video/segaic24.h"
19 
20 #include "emupal.h"
21 #include "screen.h"
22 
23 #include <glm/vec3.hpp>
24 
25 #include <functional>
26 
27 class model1_state : public driver_device
28 {
29 public:
model1_state(const machine_config & mconfig,device_type type,const char * tag)30 	model1_state(const machine_config &mconfig, device_type type, const char *tag)
31 		: driver_device(mconfig, type, tag)
32 		, m_maincpu(*this, "maincpu")
33 		, m_dpram(*this, "dpram")
34 		, m_m1audio(*this, M1AUDIO_TAG)
35 		, m_m1uart(*this, "m1uart")
36 		, m_m1comm(*this, "m1comm")
37 		, m_dsbz80(*this, DSBZ80_TAG)
38 		, m_tgp_copro(*this, "tgp_copro")
39 		, m_screen(*this, "screen")
40 		, m_copro_fifo_in(*this, "copro_fifo_in")
41 		, m_copro_fifo_out(*this, "copro_fifo_out")
42 		, m_poly_rom(*this, "polygons")
43 		, m_copro_tables(*this, "copro_tables")
44 		, m_copro_data(*this, "copro_data")
45 		, m_display_list0(*this, "display_list0")
46 		, m_display_list1(*this, "display_list1")
47 		, m_color_xlat(*this, "color_xlat")
48 		, m_paletteram16(*this, "palette")
49 		, m_palette(*this, "palette")
50 		, m_tiles(*this, "tile")
51 		, m_digits(*this, "digit%u", 0U)
52 		, m_outs(*this, "out%u", 0U)
53 	{
54 	}
55 
56 	void model1(machine_config &config);
57 	void vf(machine_config &config);
58 	void vr(machine_config &config);
59 	void vformula(machine_config &config);
60 	void swa(machine_config &config);
61 	void wingwar(machine_config &config);
62 	void wingwar360(machine_config &config);
63 	void netmerc(machine_config &config);
64 
65 	struct spoint_t
66 	{
67 		int32_t x = 0, y = 0;
68 	};
69 
70 	struct point_t
71 	{
72 		float x = 0, y = 0, z = 0;
73 		float xx = 0, yy = 0;
74 		spoint_t s;
75 	};
76 
77 	class quad_t
78 	{
79 	public:
quad_t()80 		quad_t() { }
quad_t(int ccol,float cz,point_t * p0,point_t * p1,point_t * p2,point_t * p3)81 		quad_t(int ccol, float cz, point_t* p0, point_t* p1, point_t* p2, point_t* p3)
82 			: p{ p0, p1, p2, p3 }
83 			, z(cz)
84 			, col(ccol)
85 		{
86 		}
87 
88 		int compare(const quad_t* other) const;
89 
90 		point_t *p[4] = { nullptr, nullptr, nullptr, nullptr };
91 		float z = 0;
92 		int col = 0;
93 	};
94 
95 private:
96 	// Machine
97 	virtual void machine_start() override;
98 	virtual void machine_reset() override;
99 
100 	void bank_w(offs_t offset, u16 data, u16 mem_mask = ~0);
101 
102 	TIMER_DEVICE_CALLBACK_MEMBER(model1_interrupt);
103 	IRQ_CALLBACK_MEMBER(irq_callback);
104 
105 	// TGP
106 	u16 fifoin_status_r();
107 
108 	u16 v60_copro_fifo_r(offs_t offset);
109 	void v60_copro_fifo_w(offs_t offset, u16 data);
110 	u16 v60_copro_ram_adr_r();
111 	void v60_copro_ram_adr_w(offs_t offset, u16 data, u16 mem_mask = ~0);
112 	u16 v60_copro_ram_r(offs_t offset);
113 	void v60_copro_ram_w(offs_t offset, u16 data, u16 mem_mask = ~0);
114 
115 	void copro_sincos_w(offs_t offset, u32 data, u32 mem_mask = ~0);
116 	u32 copro_sincos_r(offs_t offset);
117 	void copro_inv_w(offs_t offset, u32 data, u32 mem_mask = ~0);
118 	u32 copro_inv_r(offs_t offset);
119 	void copro_isqrt_w(offs_t offset, u32 data, u32 mem_mask = ~0);
120 	u32 copro_isqrt_r(offs_t offset);
121 	void copro_atan_w(offs_t offset, u32 data, u32 mem_mask = ~0);
122 	u32 copro_atan_r();
123 	void copro_data_w(offs_t offset, u32 data, u32 mem_mask = ~0);
124 	u32 copro_data_r(offs_t offset);
125 	void copro_ramadr_w(offs_t offset, u32 data, u32 mem_mask = ~0);
126 	u32 copro_ramadr_r(offs_t offset);
127 	void copro_ramdata_w(offs_t offset, u32 data, u32 mem_mask = ~0);
128 	u32 copro_ramdata_r(offs_t offset);
129 
130 	void copro_reset();
131 
132 	u32 m_copro_sincos_base;
133 	u32 m_copro_inv_base;
134 	u32 m_copro_isqrt_base;
135 	u32 m_copro_atan_base[4];
136 	u32 m_copro_data_base;
137 	u32 m_copro_ram_adr[4];
138 
139 	uint16_t m_r360_state;
140 	uint8_t r360_r();
141 	void r360_w(uint8_t data);
142 
143 	// Rendering
144 	virtual void video_start() override;
145 	u16 model1_listctl_r(offs_t offset);
146 	void model1_listctl_w(offs_t offset, u16 data, u16 mem_mask = ~0);
147 
148 	uint32_t screen_update_model1(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
149 	DECLARE_WRITE_LINE_MEMBER(screen_vblank_model1);
150 
151 	struct lightparam_t
152 	{
153 		float a = 0;
154 		float d = 0;
155 		float s = 0;
156 		int p = 0;
157 	};
158 
159 	class view_t
160 	{
161 	public:
view_t()162 		view_t() {
163 			light.x = 0;
164 			light.y = 0;
165 			light.z = 0;
166 		}
167 
168 		void init_translation_matrix();
169 
170 		void set_viewport(float xcenter, float ycenter, float xl, float xr, float yb, float yt);
171 		void set_lightparam(int index, float diffuse, float ambient, float specular, int power);
172 		void set_zoom(float x, float y);
173 		void set_light_direction(float x, float y, float z);
174 		void set_translation_matrix(float* mat);
175 		void set_view_translation(float x, float y);
176 
177 		void project_point(point_t *p) const;
178 		void project_point_direct(point_t *p) const;
179 
180 		void transform_vector(glm::vec3& p) const;
181 		void transform_point(point_t *p) const;
182 
183 		void recompute_frustum();
184 
185 		int xc = 0, yc = 0, x1 = 0, y1 = 0, x2 = 0, y2 = 0;
186 		float zoomx = 0, zoomy = 0, viewx = 0, viewy = 0;
187 		float a_bottom = 0, a_top = 0, a_left = 0, a_right = 0;
188 		float vxx = 0, vyy = 0, vzz = 0, ayy = 0, ayyc = 0, ayys = 0;
189 		float translation[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
190 		glm::vec3 light;
191 		lightparam_t lightparams[32];
192 	};
193 
194 	void model1_io(address_map &map);
195 	void model1_mem(address_map &map);
196 	void model1_comm_mem(address_map &map);
197 
198 	void copro_prog_map(address_map &map);
199 	void copro_data_map(address_map &map);
200 	void copro_external_map(address_map &map);
201 	void copro_io_map(address_map &map);
202 	void copro_rf_map(address_map &map);
203 
204 	void polhemus_map(address_map &map);
205 
206 	// Machine
207 	void irq_raise(int level);
208 	void irq_init();
209 	void irq_control_w(u8 data);
210 
211 	uint8_t m_irq_status;
212 	int m_last_irq;
213 
214 	// Devices
215 	required_device<v60_device> m_maincpu;          // V60
216 	required_device<mb8421_device> m_dpram;
217 	required_device<segam1audio_device> m_m1audio;  // Model 1 standard sound board
218 	required_device<i8251_device> m_m1uart;
219 	optional_device<m1comm_device> m_m1comm;        // Model 1 communication board
220 	optional_device<dsbz80_device> m_dsbz80;        // Digital Sound Board
221 	optional_device<mb86233_device> m_tgp_copro;
222 	required_device<screen_device> m_screen;
223 	required_device<generic_fifo_u32_device> m_copro_fifo_in, m_copro_fifo_out;
224 
225 	required_region_ptr<uint32_t> m_poly_rom;
226 	required_region_ptr<uint32_t> m_copro_tables;
227 	optional_memory_region        m_copro_data;
228 
229 	required_shared_ptr<uint16_t> m_display_list0;
230 	required_shared_ptr<uint16_t> m_display_list1;
231 	required_shared_ptr<uint16_t> m_color_xlat;
232 
233 	// Sound
234 	int m_sound_irq;
235 
236 	// TGP FIFO
237 	void    fifoout_push(uint32_t data);
238 	void    fifoout_push_f(float data);
239 	uint32_t  fifoin_pop();
240 	float   fifoin_pop_f();
241 	uint16_t  ram_get_i();
242 	float   ram_get_f();
243 	u32 m_v60_copro_fifo_r, m_v60_copro_fifo_w;
244 
245 	// TGP
246 	void    tgp_reset();
247 	class clipper_t
248 	{
249 	public:
clipper_t()250 		clipper_t()
251 			: m_isclipped(nullptr)
252 			, m_clip(nullptr)
253 		{
254 		}
255 
clipper_t(std::function<bool (view_t *,point_t *)> isclipped,std::function<void (view_t *,point_t *,point_t *,point_t *)> clip)256 		clipper_t(std::function<bool(view_t*, point_t*)> isclipped, std::function<void(view_t*, point_t*, point_t*, point_t*)> clip)
257 			: m_isclipped(isclipped)
258 			, m_clip(clip)
259 		{
260 		}
261 
262 		std::function<bool(view_t*, point_t*)> m_isclipped;
263 		std::function<void(view_t*, point_t*, point_t*, point_t*)> m_clip;
264 	};
265 
266 	std::unique_ptr<view_t> m_view;
267 	std::unique_ptr<point_t[]> m_pointdb;
268 	point_t *m_pointpt;
269 	std::unique_ptr<quad_t[]> m_quaddb;
270 	quad_t      *m_quadpt;
271 	std::unique_ptr<quad_t *[]> m_quadind;
272 
273 	uint16_t  m_v60_copro_ram_adr;
274 	uint16_t  m_v60_copro_ram_latch[2];
275 	std::unique_ptr<uint32_t[]> m_copro_ram_data;
276 	uint16_t  m_listctl[2];
277 	uint16_t  *m_glist;
278 	bool    m_render_done;
279 
280 	std::unique_ptr<uint16_t[]> m_tgp_ram;
281 	std::unique_ptr<uint32_t[]> m_poly_ram;
282 
283 	// Rendering helper functions
284 	uint32_t  readi(int adr) const;
285 	int16_t   readi16(int adr) const;
286 	float   readf(int adr) const;
287 	void    cross_product(point_t* o, const point_t* p, const point_t* q) const;
288 	float   view_determinant(const point_t *p1, const point_t *p2, const point_t *p3) const;
289 
290 	static bool fclip_isc_bottom(view_t*, point_t*);
291 	static bool fclip_isc_top(view_t*, point_t*);
292 	static bool fclip_isc_left(view_t*, point_t*);
293 	static bool fclip_isc_right(view_t*, point_t*);
294 	static void fclip_clip_bottom(view_t*, point_t*, point_t*, point_t*);
295 	static void fclip_clip_top(view_t*, point_t*, point_t*, point_t*);
296 	static void fclip_clip_left(view_t*, point_t*, point_t*, point_t*);
297 	static void fclip_clip_right(view_t*, point_t*, point_t*, point_t*);
298 
299 	// Rendering
300 	void    tgp_render(bitmap_rgb32 &bitmap, const rectangle &cliprect);
301 	void    tgp_scan();
302 
303 	void        sort_quads() const;
304 	void        unsort_quads() const;
305 	void        draw_quads(bitmap_rgb32 &bitmap, const rectangle &cliprect);
306 	static void recompute_frustum(view_t *view);
307 	static void draw_hline(bitmap_rgb32 &bitmap, int x1, int x2, int y, int color);
308 	static void draw_hline_moired(bitmap_rgb32 &bitmap, int x1, int x2, int y, int color);
309 	static void fill_slope(bitmap_rgb32 &bitmap, view_t *view, int color, int32_t x1, int32_t x2, int32_t sl1, int32_t sl2, int32_t y1, int32_t y2, int32_t *nx1, int32_t *nx2);
310 	static void fill_line(bitmap_rgb32 &bitmap, view_t *view, int color, int32_t y, int32_t x1, int32_t x2);
311 	void        fill_quad(bitmap_rgb32 &bitmap, view_t *view, const quad_t& q) const;
312 
313 	void    fclip_push_quad_next(int level, quad_t& q, point_t *p1, point_t *p2, point_t *p3, point_t *p4);
314 	void    fclip_push_quad(int level, quad_t& q);
315 
316 	static float    min4f(float a, float b, float c, float d);
317 	static float    max4f(float a, float b, float c, float d);
318 	static float    compute_specular(glm::vec3& normal, glm::vec3& light, float diffuse,int lmode);
319 
320 	int push_direct(int list_offset);
321 	int draw_direct(bitmap_rgb32 &bitmap, const rectangle &cliprect, int list_offset);
322 	int skip_direct(int list_offset) const;
323 	void    push_object(uint32_t tex_adr, uint32_t poly_adr, uint32_t size);
324 	void    draw_objects(bitmap_rgb32 &bitmap, const rectangle &cliprect);
325 
326 	void set_current_render_list();
327 	int     get_list_number();
328 	void    end_frame();
329 
330 	clipper_t m_clipfn[4];
331 
332 	// run-time rendering
333 	uint16_t* m_display_list_current;
334 
335 	optional_shared_ptr<uint16_t> m_paletteram16;
336 	required_device<palette_device> m_palette;
337 	required_device<segas24_tile_device> m_tiles;
338 
339 	// I/O related
340 	output_finder<2> m_digits;
341 	output_finder<8> m_outs;
342 	u8 dpram_r(offs_t offset);
343 	void gen_outputs_w(uint8_t data);
344 	void vf_outputs_w(uint8_t data);
345 	void vr_outputs_w(uint8_t data);
346 	void swa_outputs_w(uint8_t data);
347 	void wingwar_outputs_w(uint8_t data);
348 	void wingwar360_outputs_w(uint8_t data);
349 	void netmerc_outputs_w(uint8_t data);
350 	void drive_board_w(uint8_t data);
351 };
352 
353 #endif // MAME_INCLUDES_MODEL1_H
354