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