1 // license:BSD-3-Clause
2 // copyright-holders:Angelo Salese
3 /***************************************************************************
4 
5     Atari Jaguar "Blitter" device
6 
7     TODO:
8     - Stub device, port/rewrite from jagblit;
9     - actual codename/chip part number;
10     - has different revs, encapsulate;
11 
12 ***************************************************************************/
13 
14 #include "emu.h"
15 #include "jag_blitter.h"
16 
17 
18 
19 //**************************************************************************
20 //  GLOBAL VARIABLES
21 //**************************************************************************
22 
23 // device type definition
24 DEFINE_DEVICE_TYPE(JAG_BLITTER, jag_blitter_device, "jag_blitter", "Atari Jaguar Blitter")
25 
26 
27 //**************************************************************************
28 //  LIVE DEVICE
29 //**************************************************************************
30 
31 //-------------------------------------------------
32 //  jag_blitter_device - constructor
33 //-------------------------------------------------
34 
jag_blitter_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)35 jag_blitter_device::jag_blitter_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
36 	: device_t(mconfig, JAG_BLITTER, tag, owner, clock)
37 	, device_memory_interface(mconfig, *this)
38 	, m_space_config("regs", ENDIANNESS_BIG, 32, 8, 0, address_map_constructor(FUNC(jag_blitter_device::regs_map), this))
39 	, m_command_latch(0)
40 	, m_status_idle(true)
41 	, m_count_lines(0)
42 	, m_count_pixels(0)
43 {
44 	m_a1.base = 0;
45 	m_a1.xstep = 0;
46 	m_a1.ystep = 0;
47 }
48 
memory_space_config() const49 device_memory_interface::space_config_vector jag_blitter_device::memory_space_config() const
50 {
51 	return space_config_vector {
52 		std::make_pair(0, &m_space_config)
53 	};
54 }
55 
56 
57 //-------------------------------------------------
58 //  device_start - device-specific startup
59 //-------------------------------------------------
60 
device_start()61 void jag_blitter_device::device_start()
62 {
63 	save_item(NAME(m_status_idle));
64 	save_item(NAME(m_command_latch));
65 	save_item(NAME(m_count_lines));
66 	save_item(NAME(m_count_pixels));
67 	save_item(NAME(m_a1.base));
68 	save_item(NAME(m_a1.xstep));
69 	save_item(NAME(m_a1.ystep));
70 
71 	m_command_timer = timer_alloc(0);
72 }
73 
74 
75 //-------------------------------------------------
76 //  device_reset - device-specific reset
77 //-------------------------------------------------
78 
device_reset()79 void jag_blitter_device::device_reset()
80 {
81 	m_command_latch = 0;
82 	m_status_idle = true;
83 
84 	m_command_timer->adjust(attotime::never);
85 }
86 
87 //--------------------------------------------------
88 // core workings
89 //--------------------------------------------------
90 
91 /***************************************************************************
92     FUNCTION TABLES
93 ***************************************************************************/
94 
95 const jag_blitter_device::op_func jag_blitter_device::upda_ops[8] =
96 {
97 	&jag_blitter_device::op_nop,
98 	&jag_blitter_device::op_unemulated, // upda1f
99 	&jag_blitter_device::op_upda1,
100 	&jag_blitter_device::op_unemulated, // upda1 + upda1f
101 
102 	&jag_blitter_device::op_unemulated, // upda2
103 	&jag_blitter_device::op_unemulated, // upda1f + upda2
104 	&jag_blitter_device::op_unemulated, // upda1 + upda2
105 	&jag_blitter_device::op_unemulated  // upda1 + upda1f + upda2
106 };
107 
op_nop()108 void jag_blitter_device::op_nop()
109 {
110 	// do nothing for this step
111 }
112 
113 // common cases for unhandled, will be removed once everything is set
op_unemulated()114 void jag_blitter_device::op_unemulated()
115 {
116 	throw emu_fatalerror("%s: unhandled step with command latch %08x",m_command_latch);
117 }
118 
op_upda1()119 void jag_blitter_device::op_upda1()
120 {
121 	// ...
122 
123 }
124 
command_start()125 inline void jag_blitter_device::command_start()
126 {
127 	if (m_status_idle == false)
128 		throw emu_fatalerror("%s: inflight blitter trigger %08x", this->tag(), m_command_latch);
129 	m_status_idle = false;
130 	// TODO: to be removed, see below
131 	m_command_timer->adjust(attotime::from_ticks(m_count_lines * m_count_pixels, this->clock()));
132 }
133 
command_run()134 inline void jag_blitter_device::command_run()
135 {
136 	// TODO: need to single step, have different timings between pixel and phrase modes,
137 	// calculate collision detection, delay a bit the kickoff due of bus chain requests,
138 	// take more time by virtue of using additional steps, be a civilian or not depending
139 	// of BUSHI setting
140 
141 	printf("%08x\n",m_command_latch);
142 	// init
143 	m_a1.ptr = m_a1.base;
144 
145 	// ...
146 
147 	command_done();
148 }
149 
command_done()150 inline void jag_blitter_device::command_done()
151 {
152 	// m_status_idle = true;
153 	// ...
154 }
155 
device_timer(emu_timer & timer,device_timer_id id,int param,void * ptr)156 void jag_blitter_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
157 {
158 	command_run();
159 }
160 
161 //**************************************************************************
162 //  READ/WRITE HANDLERS
163 //**************************************************************************
164 
regs_map(address_map & map)165 void jag_blitter_device::regs_map(address_map &map)
166 {
167 	// $f02200
168 	map(0x00, 0x03).w(FUNC(jag_blitter_device::a1_base_w));
169 	map(0x10, 0x13).w(FUNC(jag_blitter_device::a1_ystep_w)).umask32(0xffff0000);
170 	map(0x10, 0x13).w(FUNC(jag_blitter_device::a1_xstep_w)).umask32(0x0000ffff);
171 	map(0x38, 0x3b).rw(FUNC(jag_blitter_device::status_r), FUNC(jag_blitter_device::command_w));
172 	map(0x3c, 0x3f).w(FUNC(jag_blitter_device::count_outer_w)).umask32(0xffff0000);
173 	map(0x3c, 0x3f).w(FUNC(jag_blitter_device::count_inner_w)).umask32(0x0000ffff);
174 }
175 
a1_base_w(offs_t offset,u32 data,u32 mem_mask)176 void jag_blitter_device::a1_base_w(offs_t offset, u32 data, u32 mem_mask)
177 {
178 	COMBINE_DATA(&m_a1.base);
179 	// align to phrase
180 	m_a1.base &= ~7;
181 }
182 
a1_xstep_w(offs_t offset,u16 data,u16 mem_mask)183 void jag_blitter_device::a1_xstep_w(offs_t offset, u16 data, u16 mem_mask)
184 {
185 	COMBINE_DATA(&m_a1.xstep);
186 }
187 
a1_ystep_w(offs_t offset,u16 data,u16 mem_mask)188 void jag_blitter_device::a1_ystep_w(offs_t offset, u16 data, u16 mem_mask)
189 {
190 	COMBINE_DATA(&m_a1.ystep);
191 }
192 
status_r()193 u32 jag_blitter_device::status_r()
194 {
195 	// TODO: stopped bit
196 	// TODO: diag bits 2-31
197 	return m_status_idle;
198 }
199 
command_w(offs_t offset,u32 data,u32 mem_mask)200 void jag_blitter_device::command_w(offs_t offset, u32 data, u32 mem_mask)
201 {
202 	COMBINE_DATA(&m_command_latch);
203 	// TODO: is it possible from 68k to write on this in byte units?
204 	// We may just do so in order to take endianness into account, or just delegate to the overlying bus framework,
205 	// may be a common problem with ALL video regs for that matter.
206 	if (ACCESSING_BITS_0_15)
207 		command_start();
208 }
209 
count_outer_w(offs_t offset,u16 data,u16 mem_mask)210 void jag_blitter_device::count_outer_w(offs_t offset, u16 data, u16 mem_mask)
211 {
212 	COMBINE_DATA(&m_count_lines);
213 	if (m_count_lines == 0)
214 	{
215 		// according to documentation, log it out
216 		m_count_lines = 0x10000;
217 		popmessage("Blitter: line count set to max, contact MAMEdev");
218 	}
219 }
220 
count_inner_w(offs_t offset,u16 data,u16 mem_mask)221 void jag_blitter_device::count_inner_w(offs_t offset, u16 data, u16 mem_mask)
222 {
223 	COMBINE_DATA(&m_count_pixels);
224 	if (m_count_pixels == 0)
225 	{
226 		// according to documentation, log it out
227 		m_count_pixels = 0x10000;
228 		popmessage("Blitter: pixel count set to max, contact MAMEdev");
229 	}
230 }
231 
iobus_r(offs_t offset,u32 mem_mask)232 u32 jag_blitter_device::iobus_r(offs_t offset, u32 mem_mask)
233 {
234 	return space().read_dword(offset*4, mem_mask);
235 }
236 
iobus_w(offs_t offset,u32 data,u32 mem_mask)237 void jag_blitter_device::iobus_w(offs_t offset, u32 data, u32 mem_mask)
238 {
239 	space().write_dword(offset*4, data, mem_mask);
240 }
241