1 // license:BSD-3-Clause
2 // copyright-holders:Ryan Holtz, David Haywood
3 /*****************************************************************************
4
5 SunPlus GCM394-series SoC peripheral emulation (Video)
6
7 This is very similar to spg2xx but with additional features, layers and modes
8
9 **********************************************************************/
10
11
12 #include "emu.h"
13 #include "generalplus_gpl16250soc_video.h"
14
15 DEFINE_DEVICE_TYPE(GCM394_VIDEO, gcm394_video_device, "gcm394_video", "GeneralPlus GPL16250 System-on-a-Chip (Video)")
16
17 #define LOG_GCM394_VIDEO_PALETTE (1U << 5)
18 #define LOG_GCM394_VIDEO_DMA (1U << 4)
19 #define LOG_GCM394_TMAP_EXTRA (1U << 3)
20 #define LOG_GCM394_TMAP (1U << 2)
21 #define LOG_GCM394_VIDEO (1U << 1)
22
23 #define VERBOSE (LOG_GCM394_TMAP | LOG_GCM394_VIDEO_DMA | LOG_GCM394_VIDEO |LOG_GCM394_VIDEO_PALETTE)
24
25 #include "logmacro.h"
26
27
gcm394_base_video_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock)28 gcm394_base_video_device::gcm394_base_video_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
29 device_t(mconfig, type, tag, owner, clock),
30 device_video_interface(mconfig, *this),
31 m_cpu(*this, finder_base::DUMMY_TAG),
32 m_screen(*this, finder_base::DUMMY_TAG),
33 m_video_irq_cb(*this),
34 m_palette(*this, "palette"),
35 m_gfxdecode(*this, "gfxdecode"),
36 m_space_read_cb(*this),
37 m_rowscroll(*this, "^rowscroll"),
38 m_rowzoom(*this, "^rowzoom"),
39 m_alt_extrasprite_hack(0),
40 m_alt_tile_addressing(0),
41 m_renderer(*this, "renderer")
42 {
43 }
44
gcm394_video_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)45 gcm394_video_device::gcm394_video_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
46 : gcm394_base_video_device(mconfig, GCM394_VIDEO, tag, owner, clock)
47 {
48 }
49
decodegfx(const char * tag)50 void gcm394_base_video_device::decodegfx(const char* tag)
51 {
52 if (!memregion(tag))
53 return;
54
55 uint8_t* gfxregion = memregion(tag)->base();
56 int gfxregionsize = memregion(tag)->bytes();
57
58 if (1)
59 {
60 gfx_layout obj_layout =
61 {
62 16,16,
63 0,
64 4,
65 { STEP4(0,1) },
66 { STEP16(0,4) },
67 { STEP16(0,4 * 16) },
68 16 * 16 * 4
69 };
70 obj_layout.total = gfxregionsize / (16 * 16 * 4 / 8);
71 m_gfxdecode->set_gfx(m_maxgfxelement, std::make_unique<gfx_element>(m_palette, obj_layout, gfxregion, 0, 0x10 * 0x10, 0));
72 m_maxgfxelement++;
73 }
74
75 if (1)
76 {
77 gfx_layout obj_layout =
78 {
79 32,16,
80 0,
81 4,
82 { STEP4(0,1) },
83 { STEP32(0,4) },
84 { STEP16(0,4 * 32) },
85 16 * 32 * 4
86 };
87 obj_layout.total = gfxregionsize / (16 * 32 * 4 / 8);
88 m_gfxdecode->set_gfx(m_maxgfxelement, std::make_unique<gfx_element>(m_palette, obj_layout, gfxregion, 0, 0x10 * 0x10, 0));
89 m_maxgfxelement++;
90 }
91
92 if (1)
93 {
94 gfx_layout obj_layout =
95 {
96 16,32,
97 0,
98 4,
99 { STEP4(0,1) },
100 { STEP16(0,4) },
101 { STEP32(0,4 * 16) },
102 32 * 16 * 4
103 };
104 obj_layout.total = gfxregionsize / (32 * 16 * 4 / 8);
105 m_gfxdecode->set_gfx(m_maxgfxelement, std::make_unique<gfx_element>(m_palette, obj_layout, gfxregion, 0, 0x10 * 0x10, 0));
106 m_maxgfxelement++;
107 }
108
109 if (1)
110 {
111 gfx_layout obj_layout =
112 {
113 32,32,
114 0,
115 4,
116 { STEP4(0,1) },
117 { STEP32(0,4) },
118 { STEP32(0,4 * 32) },
119 32 * 32 * 4
120 };
121 obj_layout.total = gfxregionsize / (32 * 32 * 4 / 8);
122 m_gfxdecode->set_gfx(m_maxgfxelement, std::make_unique<gfx_element>(m_palette, obj_layout, gfxregion, 0, 0x10 * 0x10, 0));
123 m_maxgfxelement++;
124 }
125
126 if (1)
127 {
128 gfx_layout obj_layout =
129 {
130 8,16,
131 0,
132 2,
133 { 0,1 },
134 { STEP8(0,2) },
135 { STEP16(0,2 * 8) },
136 8 * 16 * 2
137 };
138 obj_layout.total = gfxregionsize / (8 * 16 * 2 / 8);
139 m_gfxdecode->set_gfx(m_maxgfxelement, std::make_unique<gfx_element>(m_palette, obj_layout, gfxregion, 0, 0x40 * 0x10, 0));
140 m_maxgfxelement++;
141 }
142
143 if (1)
144 {
145 const uint32_t texlayout_xoffset[64] = { STEP64(0,2) };
146 const uint32_t texlayout_yoffset[32] = { STEP32(0,2 * 64) };
147
148 gfx_layout obj_layout =
149 {
150 64,32,
151 0,
152 2,
153 { 0,1 },
154 EXTENDED_XOFFS,
155 EXTENDED_YOFFS,
156 32 * 64 * 2,
157 texlayout_xoffset,
158 texlayout_yoffset
159 };
160 obj_layout.total = gfxregionsize / (16 * 32 * 2 / 8);
161 m_gfxdecode->set_gfx(m_maxgfxelement, std::make_unique<gfx_element>(m_palette, obj_layout, gfxregion, 0, 0x40 * 0x10, 0));
162 m_maxgfxelement++;
163 }
164
165 if (1)
166 {
167 gfx_layout obj_layout =
168 {
169 32,32,
170 0,
171 8,
172 { STEP8(0,1) },
173 { STEP32(0,8) },
174 { STEP32(0,8 * 32) },
175 32 * 32 * 8
176 };
177 obj_layout.total = gfxregionsize / (32 * 32 * 8 / 8);
178 m_gfxdecode->set_gfx(m_maxgfxelement, std::make_unique<gfx_element>(m_palette, obj_layout, gfxregion, 0, 0x10, 0));
179 m_maxgfxelement++;
180 }
181
182 if (1)
183 {
184 gfx_layout obj_layout =
185 {
186 32,32,
187 0,
188 6,
189 { 0,1,2,3,4,5 },
190 { STEP32(0,6) },
191 { STEP32(0,6 * 32) },
192 32 * 32 * 6
193 };
194 obj_layout.total = gfxregionsize / (32 * 32 * 6 / 8);
195 m_gfxdecode->set_gfx(m_maxgfxelement, std::make_unique<gfx_element>(m_palette, obj_layout, gfxregion, 0, 0x40, 0));
196 m_maxgfxelement++;
197 }
198 }
199
device_start()200 void gcm394_base_video_device::device_start()
201 {
202 m_video_irq_cb.resolve();
203
204 m_maxgfxelement = 0;
205
206 // debug helper only
207 if (memregion(":maincpu"))
208 decodegfx(":maincpu");
209
210 m_space_read_cb.resolve_safe(0);
211
212 m_screenpos_timer = timer_alloc(TIMER_SCREENPOS);
213 m_screenpos_timer->adjust(attotime::never);
214
215 save_item(NAME(m_page0_addr_lsb));
216 save_item(NAME(m_page0_addr_msb));
217 save_item(NAME(m_page1_addr_lsb));
218 save_item(NAME(m_page1_addr_msb));
219 save_item(NAME(m_707e_spritebank));
220 save_item(NAME(m_videodma_size));
221 save_item(NAME(m_videodma_dest));
222 save_item(NAME(m_videodma_source));
223 save_item(NAME(m_tmap0_regs));
224 save_item(NAME(m_tmap1_regs));
225 save_item(NAME(m_tmap2_regs));
226 save_item(NAME(m_tmap3_regs));
227 save_item(NAME(m_tmap0_scroll));
228 save_item(NAME(m_tmap1_scroll));
229 save_item(NAME(m_tmap2_scroll));
230 save_item(NAME(m_tmap3_scroll));
231 save_item(NAME(m_707f));
232 save_item(NAME(m_703a_palettebank));
233 save_item(NAME(m_video_irq_enable));
234 save_item(NAME(m_video_irq_status));
235 save_item(NAME(m_702a));
236 save_item(NAME(m_7030_brightness));
237 save_item(NAME(m_xirqpos));
238 save_item(NAME(m_yirqpos));
239 save_item(NAME(m_703c_tvcontrol1));
240 save_item(NAME(m_7042_sprite));
241 save_item(NAME(m_7080));
242 save_item(NAME(m_7081));
243 save_item(NAME(m_7082));
244 save_item(NAME(m_7083));
245 save_item(NAME(m_7084));
246 save_item(NAME(m_7085));
247 save_item(NAME(m_7086));
248 save_item(NAME(m_7087));
249 save_item(NAME(m_7088));
250 save_item(NAME(m_sprite_7022_gfxbase_lsb));
251 save_item(NAME(m_sprite_702d_gfxbase_msb));
252 save_item(NAME(m_page2_addr_lsb));
253 save_item(NAME(m_page2_addr_msb));
254 save_item(NAME(m_page3_addr_lsb));
255 save_item(NAME(m_page3_addr_msb));
256 save_item(NAME(m_spriteram));
257 save_item(NAME(m_paletteram));
258 save_item(NAME(m_maxgfxelement));
259 save_item(NAME(m_alt_tile_addressing));
260 }
261
device_reset()262 void gcm394_base_video_device::device_reset()
263 {
264 for (int i = 0; i < 4; i++)
265 {
266 m_tmap0_regs[i] = 0x0000;
267 m_tmap1_regs[i] = 0x0000;
268 m_tmap2_regs[i] = 0x0000;
269 m_tmap3_regs[i] = 0x0000;
270 m_tmap2_scroll[i] = 0x0000;
271 m_tmap3_scroll[i] = 0x0000;
272 }
273
274 for (int i = 0; i < 2; i++)
275 {
276 m_tmap0_scroll[i] = 0x0000;
277 m_tmap1_scroll[i] = 0x0000;
278 }
279
280 for (int i = 0; i < 0x400*2; i++)
281 {
282 m_spriteram[i] = 0x0000;
283 }
284
285 for (int i=0;i<0x100 * 0x10;i++)
286 m_paletteram[i] = machine().rand()&0x7fff;
287
288 m_707f = 0x0000;
289 m_703a_palettebank = 0x0000;
290 m_video_irq_enable = 0x0000;
291 m_video_irq_status = 0x0000;
292
293 m_702a = 0x0000;
294 m_7030_brightness = 0x0000;
295 m_xirqpos = 0x0000;
296 m_yirqpos = 0x0000;
297 m_703c_tvcontrol1 = 0x0000;
298
299 m_7042_sprite = 0x0000;
300
301 m_7080 = 0x0000;
302 m_7081 = 0x0000;
303 m_7082 = 0x0000;
304 m_7083 = 0x0000;
305 m_7084 = 0x0000;
306 m_7085 = 0x0000;
307 m_7086 = 0x0000;
308 m_7087 = 0x0000;
309 m_7088 = 0x0000;
310
311 m_707e_spritebank = 0x0000;
312 m_videodma_size = 0x0000;
313 m_videodma_dest = 0x0000;
314 m_videodma_source = 0x0000;
315
316 m_sprite_7022_gfxbase_lsb = 0;
317 m_sprite_702d_gfxbase_msb = 0;
318 m_page2_addr_lsb = 0;
319 m_page2_addr_msb = 0;
320 m_page3_addr_lsb = 0;
321 m_page3_addr_msb = 0;
322
323 m_renderer->set_video_spaces(m_cpuspace, m_cs_space, m_csbase);
324 }
325
screen_update(screen_device & screen,bitmap_rgb32 & bitmap,const rectangle & cliprect)326 uint32_t gcm394_base_video_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
327 {
328 // For jak_car2 and jak_gtg the palette entry for 'magenta' in the test mode is intentionally set to a transparent black pen
329 // (it is stored in the palette table in ROM that way, and copied directly) so the only way for the magenta entries on the screen
330 // to be correctly displayed is if there is a magenta BG pen to fall through to (or for another palette write to change the palette
331 // that is copied, but this does not appear to be the case). How the bg pen is set is unknown, it is not a regular palette entry.
332 // The 'bitmap test mode' in jak_car2 requires this to be black instead.
333
334 // jak_s500 briely sets pen 0 of the layer to magenta, but then ends up erasing it
335
336 const uint32_t page0_addr = (m_page0_addr_msb << 16) | m_page0_addr_lsb;
337 const uint32_t page1_addr = (m_page1_addr_msb << 16) | m_page1_addr_lsb;
338 const uint32_t page2_addr = (m_page2_addr_msb << 16) | m_page2_addr_lsb;
339 const uint32_t page3_addr = (m_page3_addr_msb << 16) | m_page3_addr_lsb;
340
341
342 if (0)
343 {
344 uint16_t attr0 = m_tmap0_regs[0];
345 uint16_t attr1 = m_tmap1_regs[0];
346 uint16_t attr2 = m_tmap2_regs[0];
347 uint16_t attr3 = m_tmap3_regs[0];
348 uint16_t ctrl0 = m_tmap0_regs[1];
349 uint16_t ctrl1 = m_tmap1_regs[1];
350 uint16_t ctrl2 = m_tmap2_regs[1];
351 uint16_t ctrl3 = m_tmap3_regs[1];
352
353 popmessage(
354 "p0ct u:%02x Bl:%d HC:%d Ycmp:%d Hcmp:%d RS:%d E:%d WP:%d Rg:%d Bm:%d gfxadr: %08x t:%04x p:%04x\n"
355 "p1ct u:%02x Bl:%d HC:%d Ycmp:%d Hcmp:%d RS:%d E:%d WP:%d Rg:%d Bm:%d gfxadr: %08x t:%04x p:%04x\n"
356 "p2ct u:%02x Bl:%d HC:%d Ycmp:%d Hcmp:%d RS:%d E:%d WP:%d Rg:%d Bm:%d gfxadr: %08x t:%04x p:%04x\n"
357 "p3ct u:%02x Bl:%d HC:%d Ycmp:%d Hcmp:%d RS:%d E:%d WP:%d Rg:%d Bm:%d gfxadr: %08x t:%04x p:%04x\n"
358 "p0attr dw:%01x dh:%01x Z:%d P:%d V:%d H:%d FY:%d FX:%d D:%d xs: %04x ys %04x\n"
359 "p1attr dw:%01x dh:%01x Z:%d P:%d V:%d H:%d FY:%d FX:%d D:%d xs: %04x ys %04x\n"
360 "p2attr dw:%01x dh:%01x Z:%d P:%d V:%d H:%d FY:%d FX:%d D:%d xs: %04x ys %04x\n"
361 "p3attr dw:%01x dh:%01x Z:%d P:%d V:%d H:%d FY:%d FX:%d D:%d xs: %04x ys %04x\n"
362 "palbank %04x 707e: %04x 707f: %04x tvc703c: %04x spr7042: %04x\n",
363 (ctrl0 & 0xfe00) >> 9, BIT(ctrl0, 8), BIT(ctrl0, 7), BIT(ctrl0, 6), BIT(ctrl0, 5), BIT(ctrl0, 4), BIT(ctrl0, 3), BIT(ctrl0, 2), BIT(ctrl0, 1), BIT(ctrl0, 0), page0_addr, m_tmap0_regs[2], m_tmap0_regs[3],
364 (ctrl1 & 0xfe00) >> 9, BIT(ctrl1, 8), BIT(ctrl1, 7), BIT(ctrl1, 6), BIT(ctrl1, 5), BIT(ctrl1, 4), BIT(ctrl1, 3), BIT(ctrl1, 2), BIT(ctrl1, 1), BIT(ctrl1, 0), page1_addr, m_tmap1_regs[2], m_tmap1_regs[3],
365 (ctrl2 & 0xfe00) >> 9, BIT(ctrl2, 8), BIT(ctrl2, 7), BIT(ctrl2, 6), BIT(ctrl2, 5), BIT(ctrl2, 4), BIT(ctrl2, 3), BIT(ctrl2, 2), BIT(ctrl2, 1), BIT(ctrl2, 0), page2_addr, m_tmap2_regs[2], m_tmap2_regs[3],
366 (ctrl3 & 0xfe00) >> 9, BIT(ctrl3, 8), BIT(ctrl3, 7), BIT(ctrl3, 6), BIT(ctrl3, 5), BIT(ctrl3, 4), BIT(ctrl3, 3), BIT(ctrl3, 2), BIT(ctrl3, 1), BIT(ctrl3, 0), page3_addr, m_tmap3_regs[2], m_tmap3_regs[3],
367 BIT(attr0, 15), BIT(attr0, 14), (attr0 >> 12) & 3, (attr0 >> 8) & 15, 8 << ((attr0 >> 6) & 3), 8 << ((attr0 >> 4) & 3), BIT(attr0, 3), BIT(attr0, 2), 2 * ((attr0 & 3) + 1), m_tmap0_scroll[0], m_tmap0_scroll[1],
368 BIT(attr1, 15), BIT(attr1, 14), (attr1 >> 12) & 3, (attr1 >> 8) & 15, 8 << ((attr1 >> 6) & 3), 8 << ((attr1 >> 4) & 3), BIT(attr1, 3), BIT(attr1, 2), 2 * ((attr1 & 3) + 1), m_tmap1_scroll[0], m_tmap1_scroll[1],
369 BIT(attr2, 15), BIT(attr2, 14), (attr2 >> 12) & 3, (attr2 >> 8) & 15, 8 << ((attr2 >> 6) & 3), 8 << ((attr2 >> 4) & 3), BIT(attr2, 3), BIT(attr2, 2), 2 * ((attr2 & 3) + 1), m_tmap2_scroll[0], m_tmap2_scroll[1],
370 BIT(attr3, 15), BIT(attr3, 14), (attr3 >> 12) & 3, (attr3 >> 8) & 15, 8 << ((attr3 >> 6) & 3), 8 << ((attr3 >> 4) & 3), BIT(attr3, 3), BIT(attr3, 2), 2 * ((attr3 & 3) + 1), m_tmap3_scroll[0], m_tmap3_scroll[1],
371 m_703a_palettebank, m_707e_spritebank, m_707f, m_703c_tvcontrol1, m_7042_sprite
372 );
373 }
374
375 //const uint16_t bgcol = 0x7c1f; // magenta
376 // const uint16_t bgcol = 0x0000; // black
377 bool highres;
378 if (m_707f & 0x0010)
379 {
380 highres = true;
381 m_screen->set_visible_area(0, 640-1, 0, 480-1);
382 }
383 else
384 {
385 highres = false;
386 m_screen->set_visible_area(0, 320-1, 0, 240-1);
387 }
388
389 address_space &mem = m_cpu->space(AS_PROGRAM);
390
391
392 const uint32_t sprites_addr = (m_sprite_702d_gfxbase_msb << 16) | m_sprite_7022_gfxbase_lsb;
393
394 for (uint32_t scanline = (uint32_t)cliprect.min_y; scanline <= (uint32_t)cliprect.max_y; scanline++)
395 {
396 m_renderer->new_line(cliprect);
397
398 for (int i = 0; i < 4; i++)
399 {
400 m_renderer->draw_page(true, true, m_alt_tile_addressing ? false : true, m_703a_palettebank, cliprect, scanline, i, page0_addr, m_tmap0_scroll, m_tmap0_regs, mem, m_paletteram, m_rowscroll, 0);
401 m_renderer->draw_page(true, true, m_alt_tile_addressing ? false : true, m_703a_palettebank, cliprect, scanline, i, page1_addr, m_tmap1_scroll, m_tmap1_regs, mem, m_paletteram, m_rowscroll, 1);
402 m_renderer->draw_page(true, true, m_alt_tile_addressing ? false : true, m_703a_palettebank, cliprect, scanline, i, page2_addr, m_tmap2_scroll, m_tmap2_regs, mem, m_paletteram, m_rowscroll, 2);
403 m_renderer->draw_page(true, true, m_alt_tile_addressing ? false : true, m_703a_palettebank, cliprect, scanline, i, page3_addr, m_tmap3_scroll, m_tmap3_regs, mem, m_paletteram, m_rowscroll, 3);
404
405 m_renderer->draw_sprites(true, true, m_alt_extrasprite_hack ? true : false, m_703a_palettebank, highres, cliprect, scanline, i, sprites_addr, mem, m_paletteram, m_spriteram, -1);
406 }
407
408 m_renderer->apply_saturation_and_fade(bitmap, cliprect, scanline);
409 }
410
411 return 0;
412 }
413
414
write_tmap_scroll(int tmap,uint16_t * regs,int offset,uint16_t data)415 void gcm394_base_video_device::write_tmap_scroll(int tmap, uint16_t* regs, int offset, uint16_t data)
416 {
417 switch (offset)
418 {
419 case 0x0: // Page X scroll
420 LOGMASKED(LOG_GCM394_TMAP, "%s: write_tmap_regs: Page %d X Scroll = %04x\n", machine().describe_context(), tmap, data);
421 regs[offset] = data;
422 break;
423
424 case 0x1: // Page Y scroll
425 LOGMASKED(LOG_GCM394_TMAP, "%s: write_tmap_regs: Page %d Y Scroll = %04x\n", machine().describe_context(), tmap, data);
426 regs[offset] = data;
427 break;
428 }
429 }
430
write_tmap_regs(int tmap,uint16_t * regs,int offset,uint16_t data)431 void gcm394_base_video_device::write_tmap_regs(int tmap, uint16_t* regs, int offset, uint16_t data)
432 {
433 switch (offset)
434 {
435 case 0x0: // Page Attributes
436 LOGMASKED(LOG_GCM394_TMAP, "%s: write_tmap_regs: Page %d Attributes = %04x (unk %01x: Depth:%d, Palette:%d, VSize:%d, HSize:%d, FlipY:%d, FlipX:%d, BPP:%d)\n", machine().describe_context(), tmap, data,
437 (data & 0xc000) >> 14, (data >> 12) & 3, (data >> 8) & 15, 8 << ((data >> 6) & 3), 8 << ((data >> 4) & 3), BIT(data, 3), BIT(data, 2), 2 * ((data & 3) + 1));
438 regs[offset] = data;
439 break;
440
441 case 0x1: // Page Control
442 LOGMASKED(LOG_GCM394_TMAP, "%s: write_tmap_regs: Page %d Control = %04x (unk:%02x Blend:%d, HiColor:%d, unk:%d, unk%d, RowScroll:%d, Enable:%d, Wallpaper:%d, RegSet:%d, Bitmap:%d)\n", machine().describe_context(), tmap, data,
443 (data & 0xfe00) >> 9, BIT(data, 8), BIT(data, 7), BIT(data, 6), BIT(data, 5), BIT(data, 4), BIT(data, 3), BIT(data, 2), BIT(data, 1), BIT(data, 0));
444 regs[offset] = data;
445 break;
446
447 case 0x2: // Page Tile Address
448 LOGMASKED(LOG_GCM394_TMAP, "%s: write_tmap_regs: Page %d Tile Address = %04x\n", machine().describe_context(), tmap, data);
449 regs[offset] = data;
450 break;
451
452 case 0x3: // Page Attribute Address
453 LOGMASKED(LOG_GCM394_TMAP, "%s: write_tmap_regs: Page %d Attribute Address = %04x\n", machine().describe_context(), tmap, data);
454 regs[offset] = data;
455 break;
456 }
457 }
458
459
460 // offsets 0,1,4,5,6,7 used in main IRQ code
461 // offsets 2,3 only cleared on startup
462
463 // Based on code analysis this seems to be the same as the regular tilemap regs, except for the addition of regs 2,3 which shift the remaining ones along.
464 // As the hardware appears to support ROZ these are probably 2 extra tile layers, with the 2 additional words being the ROZ parameters?
465
466
write_tmap_extrascroll(int tmap,uint16_t * regs,int offset,uint16_t data)467 void gcm394_base_video_device::write_tmap_extrascroll(int tmap, uint16_t* regs, int offset, uint16_t data)
468 {
469 switch (offset)
470 {
471 case 0x0: // Page X scroll
472 case 0x1: // Page Y scroll
473 write_tmap_scroll(tmap, regs, offset, data);
474 break;
475
476 case 0x2: //
477 LOGMASKED(LOG_GCM394_TMAP, "%s: write_tmap_regs: Page %d X Unk Rotation Zoom Attribute1 = %04x\n", machine().describe_context(), tmap, data);
478 regs[offset] = data;
479 break;
480
481 case 0x3:
482 LOGMASKED(LOG_GCM394_TMAP, "%s: write_tmap_regs: Page %d X Unk Rotation Zoom Attribute = %04x\n", machine().describe_context(), tmap, data);
483 regs[offset] = data;
484 break;
485
486 }
487 }
488
489
490 // **************************************** TILEMAP 0 *************************************************
491
tmap0_regs_r(offs_t offset)492 uint16_t gcm394_base_video_device::tmap0_regs_r(offs_t offset)
493 {
494 if (offset < 2)
495 {
496 return m_tmap0_scroll[offset];
497 }
498 else
499 {
500 return m_tmap0_regs[offset-2];
501 }
502 }
503
tmap0_regs_w(offs_t offset,uint16_t data)504 void gcm394_base_video_device::tmap0_regs_w(offs_t offset, uint16_t data)
505 {
506 LOGMASKED(LOG_GCM394_TMAP_EXTRA, "%s:gcm394_base_video_device::tmap0_regs_w %01x %04x\n", machine().describe_context(), offset, data);
507 if (offset < 2)
508 {
509 write_tmap_scroll(0, m_tmap0_scroll, offset, data);
510 }
511 else
512 {
513 write_tmap_regs(0, m_tmap0_regs, offset-2, data);
514 }
515 }
516
tmap0_tilebase_lsb_r()517 uint16_t gcm394_base_video_device::tmap0_tilebase_lsb_r()
518 {
519 return m_page0_addr_lsb;
520 }
521
tmap0_tilebase_lsb_w(uint16_t data)522 void gcm394_base_video_device::tmap0_tilebase_lsb_w(uint16_t data)
523 {
524 LOGMASKED(LOG_GCM394_TMAP, "%s:gcm394_base_video_device::tmap0_tilebase_lsb_w %04x\n", machine().describe_context(), data);
525 m_page0_addr_lsb = data;
526 LOGMASKED(LOG_GCM394_TMAP, "\t(tmap0 tilegfxbase is now %04x%04x)\n", m_page0_addr_msb, m_page0_addr_lsb);
527 }
528
tmap0_tilebase_msb_r()529 uint16_t gcm394_base_video_device::tmap0_tilebase_msb_r()
530 {
531 return m_page0_addr_msb;
532 }
533
tmap0_tilebase_msb_w(uint16_t data)534 void gcm394_base_video_device::tmap0_tilebase_msb_w(uint16_t data)
535 {
536 LOGMASKED(LOG_GCM394_TMAP, "%s:gcm394_base_video_device::tmap0_tilebase_msb_w %04x\n", machine().describe_context(), data);
537 m_page0_addr_msb = data;
538 LOGMASKED(LOG_GCM394_TMAP, "\t(tmap0 tilegfxbase is now %04x%04x)\n", m_page0_addr_msb, m_page0_addr_lsb);
539 }
540
541 // **************************************** TILEMAP 1 *************************************************
542
543
tmap1_regs_r(offs_t offset)544 uint16_t gcm394_base_video_device::tmap1_regs_r(offs_t offset)
545 {
546 if (offset < 2)
547 {
548 return m_tmap1_scroll[offset];
549 }
550 else
551 {
552 return m_tmap1_regs[offset-2];
553 }
554 }
555
tmap1_regs_w(offs_t offset,uint16_t data)556 void gcm394_base_video_device::tmap1_regs_w(offs_t offset, uint16_t data)
557 {
558 LOGMASKED(LOG_GCM394_TMAP_EXTRA, "%s:gcm394_base_video_device::tmap1_regs_w %01x %04x\n", machine().describe_context(), offset, data);
559 if (offset < 2)
560 {
561 write_tmap_scroll(1, m_tmap1_scroll, offset, data);
562 }
563 else
564 {
565 write_tmap_regs(1, m_tmap1_regs, offset-2, data);
566 }
567 }
568
tmap1_tilebase_lsb_r()569 uint16_t gcm394_base_video_device::tmap1_tilebase_lsb_r()
570 {
571 return m_page1_addr_lsb;
572 }
573
tmap1_tilebase_lsb_w(uint16_t data)574 void gcm394_base_video_device::tmap1_tilebase_lsb_w(uint16_t data)
575 {
576 LOGMASKED(LOG_GCM394_TMAP, "%s:gcm394_base_video_device::tmap1_tilebase_lsb_w %04x\n", machine().describe_context(), data);
577 m_page1_addr_lsb = data;
578 LOGMASKED(LOG_GCM394_TMAP, "\t(tmap1 tilegfxbase is now %04x%04x)\n", m_page1_addr_msb, m_page1_addr_lsb);
579 }
580
tmap1_tilebase_msb_r()581 uint16_t gcm394_base_video_device::tmap1_tilebase_msb_r()
582 {
583 return m_page1_addr_msb;
584 }
585
tmap1_tilebase_msb_w(uint16_t data)586 void gcm394_base_video_device::tmap1_tilebase_msb_w(uint16_t data)
587 {
588 LOGMASKED(LOG_GCM394_TMAP, "%s:gcm394_base_video_device::tmap1_tilebase_msb_w %04x\n", machine().describe_context(), data);
589 m_page1_addr_msb = data;
590 LOGMASKED(LOG_GCM394_TMAP, "\t(tmap1 tilegfxbase is now %04x%04x)\n", m_page1_addr_msb, m_page1_addr_lsb);
591 }
592
593 // **************************************** unknown video device 1 (another tilemap? roz? line? zooming sprite layer?) *************************************************
594
tmap2_regs_r(offs_t offset)595 uint16_t gcm394_base_video_device::tmap2_regs_r(offs_t offset)
596 {
597 if (offset < 4)
598 {
599 return m_tmap2_scroll[offset];
600 }
601 else
602 {
603 return m_tmap2_regs[offset-4];
604 }
605 }
606
tmap2_regs_w(offs_t offset,uint16_t data)607 void gcm394_base_video_device::tmap2_regs_w(offs_t offset, uint16_t data)
608 {
609 LOGMASKED(LOG_GCM394_TMAP_EXTRA, "%s:gcm394_base_video_device::tmap2_regs_w %01x %04x\n", machine().describe_context(), offset, data);
610 if (offset < 4)
611 {
612 write_tmap_extrascroll(2, m_tmap2_scroll, offset, data);
613 }
614 else
615 {
616 write_tmap_regs(2, m_tmap2_regs, offset-4, data);
617 }
618 }
619
tmap2_tilebase_lsb_r()620 uint16_t gcm394_base_video_device::tmap2_tilebase_lsb_r()
621 {
622 return m_page2_addr_lsb;
623 }
624
625
tmap2_tilebase_lsb_w(uint16_t data)626 void gcm394_base_video_device::tmap2_tilebase_lsb_w(uint16_t data)
627 {
628 LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::tmap2_tilebase_lsb_w %04x\n", machine().describe_context(), data);
629 m_page2_addr_lsb = data;
630 LOGMASKED(LOG_GCM394_TMAP, "\t(unk_vid1 tilegfxbase is now %04x%04x)\n", m_page2_addr_msb, m_page2_addr_lsb);
631 }
632
tmap2_tilebase_msb_r()633 uint16_t gcm394_base_video_device::tmap2_tilebase_msb_r()
634 {
635 return m_page2_addr_msb;
636 }
637
tmap2_tilebase_msb_w(uint16_t data)638 void gcm394_base_video_device::tmap2_tilebase_msb_w(uint16_t data)
639 {
640 LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::tmap2_tilebase_msb_w %04x\n", machine().describe_context(), data);
641 m_page2_addr_msb = data;
642 LOGMASKED(LOG_GCM394_TMAP, "\t(unk_vid1 tilegfxbase is now %04x%04x)\n", m_page2_addr_msb, m_page2_addr_lsb);
643 }
644
645 // **************************************** unknown video device 2 (another tilemap? roz? lines? zooming sprite layer?) *************************************************
646
tmap3_regs_r(offs_t offset)647 uint16_t gcm394_base_video_device::tmap3_regs_r(offs_t offset)
648 {
649 if (offset < 4)
650 {
651 return m_tmap3_scroll[offset];
652 }
653 else
654 {
655 return m_tmap3_regs[offset-4];
656 }
657 }
658
tmap3_regs_w(offs_t offset,uint16_t data)659 void gcm394_base_video_device::tmap3_regs_w(offs_t offset, uint16_t data)
660 {
661 LOGMASKED(LOG_GCM394_TMAP_EXTRA, "%s:gcm394_base_video_device::tmap3_regs_w %01x %04x\n", machine().describe_context(), offset, data);
662 if (offset < 4)
663 {
664 write_tmap_extrascroll(3, m_tmap3_scroll, offset, data);
665 }
666 else
667 {
668 write_tmap_regs(3, m_tmap3_regs, offset-4, data);
669 }
670 }
671
tmap3_tilebase_lsb_r()672 uint16_t gcm394_base_video_device::tmap3_tilebase_lsb_r()
673 {
674 return m_page3_addr_lsb;
675 }
676
677
tmap3_tilebase_lsb_w(uint16_t data)678 void gcm394_base_video_device::tmap3_tilebase_lsb_w(uint16_t data)
679 {
680 LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::tmap3_tilebase_lsb_w %04x\n", machine().describe_context(), data);
681 m_page3_addr_lsb = data;
682 LOGMASKED(LOG_GCM394_TMAP, "\t(unk_vid2 tilegfxbase is now %04x%04x)\n", m_page3_addr_msb, m_page3_addr_lsb);
683 }
684
tmap3_tilebase_msb_r()685 uint16_t gcm394_base_video_device::tmap3_tilebase_msb_r()
686 {
687 return m_page3_addr_msb;
688 }
689
690
tmap3_tilebase_msb_w(uint16_t data)691 void gcm394_base_video_device::tmap3_tilebase_msb_w(uint16_t data)
692 {
693 LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::tmap3_tilebase_msb_w %04x\n", machine().describe_context(), data);
694 m_page3_addr_msb = data;
695 LOGMASKED(LOG_GCM394_TMAP, "\t(unk_vid2 tilegfxbase is now %04x%04x)\n", m_page3_addr_msb, m_page3_addr_lsb);
696 }
697
698 // **************************************** sprite control registers *************************************************
699
700 // set to 001264c0 in wrlshunt, which point at the menu selectors (game names, arrows etc.)
701
sprite_7022_gfxbase_lsb_r()702 uint16_t gcm394_base_video_device::sprite_7022_gfxbase_lsb_r()
703 {
704 return m_sprite_7022_gfxbase_lsb;
705 }
706
sprite_7022_gfxbase_lsb_w(uint16_t data)707 void gcm394_base_video_device::sprite_7022_gfxbase_lsb_w(uint16_t data)
708 {
709 LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::sprite_7022_gfxbase_lsb_w %04x\n", machine().describe_context(), data);
710 m_sprite_7022_gfxbase_lsb = data;
711 LOGMASKED(LOG_GCM394_TMAP, "\t(sprite tilebase is now %04x%04x)\n", m_sprite_702d_gfxbase_msb, m_sprite_7022_gfxbase_lsb);
712 }
713
sprite_702d_gfxbase_msb_r()714 uint16_t gcm394_base_video_device::sprite_702d_gfxbase_msb_r()
715 {
716 return m_sprite_702d_gfxbase_msb;
717 }
718
sprite_702d_gfxbase_msb_w(uint16_t data)719 void gcm394_base_video_device::sprite_702d_gfxbase_msb_w(uint16_t data)
720 {
721 LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::sprite_702d_gfxbase_msb_w %04x\n", machine().describe_context(), data);
722 m_sprite_702d_gfxbase_msb = data;
723 LOGMASKED(LOG_GCM394_TMAP, "\t(sprite tilebase tilegfxbase is now %04x%04x)\n", m_sprite_702d_gfxbase_msb, m_sprite_7022_gfxbase_lsb);
724 }
725
sprite_7042_extra_r()726 uint16_t gcm394_base_video_device::sprite_7042_extra_r()
727 {
728 uint16_t retdata = m_7042_sprite;
729 LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::sprite_7042_extra_r (returning: %04x)\n", machine().describe_context(), retdata);
730 return retdata;
731 }
732
sprite_7042_extra_w(uint16_t data)733 void gcm394_base_video_device::sprite_7042_extra_w(uint16_t data)
734 {
735 LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::sprite_7042_extra_w %04x\n", machine().describe_context(), data);
736 m_7042_sprite = data;
737 m_renderer->set_video_reg_42(data);
738
739 //popmessage("extra modes %04x\n", data);
740 }
741
742
743 // **************************************** video DMA device *************************************************
744
video_dma_source_w(uint16_t data)745 void gcm394_base_video_device::video_dma_source_w(uint16_t data)
746 {
747 LOGMASKED(LOG_GCM394_VIDEO_DMA, "%s:gcm394_base_video_device::video_dma_source_w %04x\n", machine().describe_context(), data);
748 m_videodma_source = data;
749 }
750
video_dma_dest_w(uint16_t data)751 void gcm394_base_video_device::video_dma_dest_w(uint16_t data)
752 {
753 LOGMASKED(LOG_GCM394_VIDEO_DMA, "%s:gcm394_base_video_device::video_dma_dest_w %04x\n", machine().describe_context(), data);
754 m_videodma_dest = data;
755 }
756
video_dma_size_busy_r()757 uint16_t gcm394_base_video_device::video_dma_size_busy_r()
758 {
759 LOGMASKED(LOG_GCM394_VIDEO_DMA, "%s:gcm394_base_video_device::video_dma_size_busy_r\n", machine().describe_context());
760 return 0x0000;
761 }
762
video_dma_size_trigger_w(address_space & space,uint16_t data)763 void gcm394_base_video_device::video_dma_size_trigger_w(address_space &space, uint16_t data)
764 {
765 LOGMASKED(LOG_GCM394_VIDEO_DMA, "%s:gcm394_base_video_device::video_dma_size_trigger_w %04x\n", machine().describe_context(), data);
766 m_videodma_size = data;
767
768 LOGMASKED(LOG_GCM394_VIDEO_DMA, "%s: doing sprite / video DMA source %04x dest %04x size %04x value of 707e (bank) %04x value of 707f %04x\n", machine().describe_context(), m_videodma_source, m_videodma_dest, m_videodma_size, m_707e_spritebank, m_707f );
769
770 for (int i = 0; i <= m_videodma_size; i++)
771 {
772 uint16_t dat = space.read_word(m_videodma_source+i);
773 space.write_word(m_videodma_dest + i, dat);
774 }
775
776 m_videodma_size = 0x0000;
777
778 if (m_video_irq_enable & 4)
779 {
780 const uint16_t old = m_video_irq_status;
781 m_video_irq_status |= 4;
782 const uint16_t changed = old ^ (m_video_irq_enable & m_video_irq_status);
783 if (changed)
784 check_video_irq();
785 }
786 }
787
video_707e_spritebank_w(uint16_t data)788 void gcm394_base_video_device::video_707e_spritebank_w(uint16_t data)
789 {
790 LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_707e_spritebank_w %04x\n", machine().describe_context(), data);
791 m_707e_spritebank = data;
792 }
793
video_707c_r()794 uint16_t gcm394_base_video_device::video_707c_r()
795 {
796 LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_707c_r\n", machine().describe_context());
797 return 0x8000;
798 }
799
800 /* 707f is VERY important, lots of rendering codepaths in the code depend on the value it returns.
801
802 all operations in the code based on 707f are bit based, usually read register, set / clear a bit
803 and then write register, or read register and test an individual bit.
804
805 our current codeflow means that bits are only ever set, not cleared.
806
807 are the bits triggers? acks? enables? status flags?
808
809 in wrlshunt this ends up being set to 02f9 ---- --x- xxxx x--x
810 and in smartfp it ends up being set to 0065 ---- ---- -xx- -x-x
811
812 is this because wrlshunt uses more layers?
813 */
814
815
video_707f_r()816 uint16_t gcm394_base_video_device::video_707f_r()
817 {
818 uint16_t retdata = m_renderer->get_video_reg_7f();
819 LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_707f_r (returning %04x)\n", machine().describe_context(), retdata);
820 return retdata;
821 }
video_707f_w(uint16_t data)822 void gcm394_base_video_device::video_707f_w(uint16_t data)
823 {
824 LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_707f_w %04x\n", machine().describe_context(), data);
825
826 for (int i = 0; i < 16; i++)
827 {
828 uint16_t mask = 1 << i;
829
830 if ((m_707f & mask) != (data & mask))
831 {
832 if (data & mask)
833 {
834 LOGMASKED(LOG_GCM394_VIDEO, "\tbit %04x Low -> High\n", mask);
835 }
836 else
837 {
838 LOGMASKED(LOG_GCM394_VIDEO, "\tbit %04x High -> Low\n", mask);
839 }
840 }
841 }
842
843 m_707f = data;
844 m_renderer->set_video_reg_7f(data);
845 //popmessage("707f is %04x\n", data);
846 }
847
video_703a_palettebank_r()848 uint16_t gcm394_base_video_device::video_703a_palettebank_r()
849 {
850 LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_703a_palettebank_r\n", machine().describe_context());
851 return m_703a_palettebank;
852 }
853
video_703a_palettebank_w(uint16_t data)854 void gcm394_base_video_device::video_703a_palettebank_w(uint16_t data)
855 {
856 // I don't think bit 0 (0x01) is a bank select, it might be a 'mode select' for how the palette operates.
857 // neither lazertag or tkmag220 set it
858 // lazertag uses 2 banks (0 and 8)
859 // tkmag220 only uses 1 bank (0)
860
861 // ---- bb-s
862 // bb = write bank?
863 // s = sprite palette bank select?
864
865 LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_703a_palettebank_w %04x\n", machine().describe_context(), data);
866 m_703a_palettebank = data;
867 }
868
videoirq_source_enable_r()869 uint16_t gcm394_base_video_device::videoirq_source_enable_r()
870 {
871 LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::videoirq_source_enable_r\n", machine().describe_context());
872 return m_video_irq_enable;
873 }
874
videoirq_source_enable_w(uint16_t data)875 void gcm394_base_video_device::videoirq_source_enable_w(uint16_t data)
876 {
877 LOGMASKED(LOG_GCM394_VIDEO, "videoirq_source_enable_w: Video IRQ Enable = %04x (DMA:%d, Timing:%d, Blanking:%d)\n", data, BIT(data, 2), BIT(data, 1), BIT(data, 0));
878 const uint16_t old = m_video_irq_enable & m_video_irq_status;
879 m_video_irq_enable = data & 0x0007;
880 const uint16_t changed = old ^ (m_video_irq_enable & m_video_irq_status);
881 if (changed)
882 check_video_irq();
883 }
884
video_7063_videoirq_source_r()885 uint16_t gcm394_base_video_device::video_7063_videoirq_source_r()
886 {
887 LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_7063_videoirq_source_r\n", machine().describe_context());
888 return m_video_irq_status;
889 }
890
891
video_7063_videoirq_source_ack_w(uint16_t data)892 void gcm394_base_video_device::video_7063_videoirq_source_ack_w(uint16_t data)
893 {
894 LOGMASKED(LOG_GCM394_VIDEO, "video_7063_videoirq_source_ack_w: Video IRQ Acknowledge = %04x\n", data);
895 const uint16_t old = m_video_irq_enable & m_video_irq_status;
896 m_video_irq_status &= ~data;
897 const uint16_t changed = old ^ (m_video_irq_enable & m_video_irq_status);
898 if (changed)
899 check_video_irq();
900 }
901
video_702a_w(uint16_t data)902 void gcm394_base_video_device::video_702a_w(uint16_t data)
903 {
904 LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_702a_w %04x\n", machine().describe_context(), data);
905 m_702a = data;
906 m_renderer->set_video_reg_2a(data);
907 }
908
video_curline_r()909 uint16_t gcm394_base_video_device::video_curline_r()
910 {
911 LOGMASKED(LOG_GCM394_VIDEO, "%s: video_r: Current Line: %04x\n", machine().describe_context(), m_screen->vpos());
912 return m_screen->vpos();
913 }
914
915 // read in IRQ
video_7030_brightness_r()916 uint16_t gcm394_base_video_device::video_7030_brightness_r()
917 {
918 /* wrlshunt ends up doing an explicit jump to 0000 shortly after boot if you just return the value written here, however I think that is correct code flow and something else is wrong
919 as this simply looks like some kind of brightness register - there is code to decrease it from 0xff to 0x00 by 0x5 increments (waiting for it to hit 0x05) and code to do the reverse
920 either way it really looks like the data written should be read back.
921 */
922 uint16_t retdat = m_7030_brightness;
923 LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_7030_brightness_r (returning %04x)\n", machine().describe_context(), retdat);
924 return retdat;
925 }
926
video_7030_brightness_w(uint16_t data)927 void gcm394_base_video_device::video_7030_brightness_w(uint16_t data)
928 {
929 LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_7030_brightness_w %04x\n", machine().describe_context(), data);
930 m_7030_brightness = data;
931 m_renderer->set_video_reg_30(data);
932 }
933
update_raster_split_position()934 void gcm394_base_video_device::update_raster_split_position()
935 {
936 // this might need updating to handle higher res modes
937 LOGMASKED(LOG_GCM394_VIDEO, "update_raster_split_position: %04x,%04x\n", m_yirqpos, m_xirqpos);
938 if (m_xirqpos < 300 && m_yirqpos < 256)
939 {
940 // where does -19 come from? needed for raster on paccon xevious to fire at correct line for bg scrolling to be seamless
941 m_screenpos_timer->adjust(m_screen->time_until_pos(m_yirqpos-19, m_xirqpos));
942 //printf("setting irq timer for y:%d x:%d", m_yirqpos, m_xirqpos);
943 }
944 else
945 m_screenpos_timer->adjust(attotime::never);
946 }
947
split_irq_ypos_w(uint16_t data)948 void gcm394_base_video_device::split_irq_ypos_w(uint16_t data)
949 {
950 LOGMASKED(LOG_GCM394_VIDEO, "%s:split_irq_ypos_w %04x\n", machine().describe_context(), data);
951
952 m_yirqpos = data & 0x1ff;
953 update_raster_split_position();
954 }
955
split_irq_xpos_w(uint16_t data)956 void gcm394_base_video_device::split_irq_xpos_w(uint16_t data)
957 {
958 LOGMASKED(LOG_GCM394_VIDEO, "%s:split_irq_xpos_w %04x\n", machine().describe_context(), data);
959
960 m_xirqpos = data & 0x1ff;
961 update_raster_split_position();
962 }
963
video_703c_tvcontrol1_r()964 uint16_t gcm394_base_video_device::video_703c_tvcontrol1_r()
965 {
966 LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_703c_tvcontrol1_r\n", machine().describe_context());
967 return m_703c_tvcontrol1;
968 }
969
video_703c_tvcontrol1_w(uint16_t data)970 void gcm394_base_video_device::video_703c_tvcontrol1_w(uint16_t data)
971 {
972 LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_703c_tvcontrol1_w %04x\n", machine().describe_context(), data);
973 m_703c_tvcontrol1 = data;
974 m_renderer->set_video_reg_3c(data);
975 }
976
video_7051_r()977 uint16_t gcm394_base_video_device::video_7051_r()
978 {
979 /* related to what ends up crashing wrlshunt? */
980 uint16_t retdat = 0x03ff;
981 LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_7051_r (returning %04x)\n", machine().describe_context(), retdat);
982 return retdat;
983 }
984
video_70e0_r()985 uint16_t gcm394_base_video_device::video_70e0_r()
986 {
987 uint16_t retdat = machine().rand();
988 LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_70e0_r (returning %04x)\n", machine().describe_context(), retdat);
989 return retdat;
990 }
991
992
993 // this block get set once, in a single function, could be important
video_7080_w(uint16_t data)994 void gcm394_base_video_device::video_7080_w(uint16_t data) { LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_7080_w %04x\n", machine().describe_context(), data); m_7080 = data; }
video_7081_w(uint16_t data)995 void gcm394_base_video_device::video_7081_w(uint16_t data) { LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_7081_w %04x\n", machine().describe_context(), data); m_7081 = data; }
video_7082_w(uint16_t data)996 void gcm394_base_video_device::video_7082_w(uint16_t data) { LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_7082_w %04x\n", machine().describe_context(), data); m_7082 = data; }
video_7083_w(uint16_t data)997 void gcm394_base_video_device::video_7083_w(uint16_t data) { LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_7083_w %04x\n", machine().describe_context(), data); m_7083 = data; }
video_7084_w(uint16_t data)998 void gcm394_base_video_device::video_7084_w(uint16_t data) { LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_7084_w %04x\n", machine().describe_context(), data); m_7084 = data; }
video_7085_w(uint16_t data)999 void gcm394_base_video_device::video_7085_w(uint16_t data) { LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_7085_w %04x\n", machine().describe_context(), data); m_7085 = data; }
video_7086_w(uint16_t data)1000 void gcm394_base_video_device::video_7086_w(uint16_t data) { LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_7086_w %04x\n", machine().describe_context(), data); m_7086 = data; }
video_7087_w(uint16_t data)1001 void gcm394_base_video_device::video_7087_w(uint16_t data) { LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_7087_w %04x\n", machine().describe_context(), data); m_7087 = data; }
video_7088_w(uint16_t data)1002 void gcm394_base_video_device::video_7088_w(uint16_t data) { LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_7088_w %04x\n", machine().describe_context(), data); m_7088 = data; }
1003
video_7083_r()1004 uint16_t gcm394_base_video_device::video_7083_r() { LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_7083_r\n", machine().describe_context()); return m_7083; }
1005
spriteram_w(offs_t offset,uint16_t data)1006 void gcm394_base_video_device::spriteram_w(offs_t offset, uint16_t data)
1007 {
1008 // transfers an additional word for each sprite with this bit set (smartfp) or an entire extra bank (wrlshunt)
1009 // wrlshunt instead seems to base if it writes the extra data based on 707f so maybe this is more complex than banking
1010
1011 // however for 707e only 0/1 is written, and it also gets written before system DMA, so despite being in the video DMA
1012 // region seems to operate separate from that.
1013
1014 if (m_707e_spritebank == 0x0000)
1015 {
1016 m_spriteram[offset] = data;
1017 }
1018 else if (m_707e_spritebank == 0x0001)
1019 {
1020 m_spriteram[offset + 0x400] = data;
1021 }
1022 else
1023 {
1024 LOGMASKED(LOG_GCM394_VIDEO, "%s: spriteram_w %04x %04x unknown bank %04x\n", machine().describe_context(), offset, data, m_707e_spritebank);
1025 }
1026 }
1027
spriteram_r(offs_t offset)1028 uint16_t gcm394_base_video_device::spriteram_r(offs_t offset)
1029 {
1030 if (m_707e_spritebank == 0x0000)
1031 {
1032 return m_spriteram[offset];
1033 }
1034 else if (m_707e_spritebank == 0x0001)
1035 {
1036 return m_spriteram[offset + 0x400];
1037 }
1038 else
1039 {
1040 LOGMASKED(LOG_GCM394_VIDEO, "%s: spriteram_r %04x unknown bank %04x\n", machine().describe_context(), offset, m_707e_spritebank);
1041 return 0x0000;
1042 }
1043 }
1044
palette_w(offs_t offset,uint16_t data)1045 void gcm394_base_video_device::palette_w(offs_t offset, uint16_t data)
1046 {
1047 LOGMASKED(LOG_GCM394_VIDEO_PALETTE, "%s:gcm394_base_video_device::palette_w %04x : %04x (value of 0x703a is %04x)\n", machine().describe_context(), offset, data, m_703a_palettebank);
1048
1049 if (m_703a_palettebank & 0xfff0)
1050 {
1051 LOGMASKED(LOG_GCM394_VIDEO_PALETTE,"palette writes with m_703a_palettebank %04x\n", m_703a_palettebank);
1052 }
1053
1054
1055 offset |= (m_703a_palettebank & 0x000c) << 6;
1056 m_paletteram[offset] = data;
1057
1058 // for debug
1059 m_palette->set_pen_color(offset, rgb_t(
1060 (((data >> 10) & 0x1f)<<3),
1061 (((data >> 5) & 0x1f)<<3),
1062 (((data >> 0) & 0x1f)<<3)));
1063
1064 }
1065
palette_r(offs_t offset)1066 uint16_t gcm394_base_video_device::palette_r(offs_t offset)
1067 {
1068 if (m_703a_palettebank & 0xfff0)
1069 {
1070 LOGMASKED(LOG_GCM394_VIDEO_PALETTE,"palette read with m_703a_palettebank %04x\n", m_703a_palettebank);
1071 }
1072
1073 offset |= (m_703a_palettebank & 0x000c) << 6;
1074 return m_paletteram[offset];
1075 }
1076
video_701c_w(uint16_t data)1077 void gcm394_base_video_device::video_701c_w(uint16_t data)
1078 {
1079 LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_701c_w (unknown video reg?) %04x\n", machine().describe_context(), data);
1080 m_renderer->set_video_reg_1c(data);
1081 }
1082
video_701d_w(uint16_t data)1083 void gcm394_base_video_device::video_701d_w(uint16_t data)
1084 {
1085 LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_701d_w (unknown video reg?) %04x\n", machine().describe_context(), data);
1086 m_renderer->set_video_reg_1d(data);
1087 }
1088
video_701e_w(uint16_t data)1089 void gcm394_base_video_device::video_701e_w(uint16_t data)
1090 {
1091 LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_701e_w (unknown video reg?) %04x\n", machine().describe_context(), data);
1092 m_renderer->set_video_reg_1e(data);
1093 }
1094
1095
check_video_irq()1096 void gcm394_base_video_device::check_video_irq()
1097 {
1098 LOGMASKED(LOG_GCM394_VIDEO, "%ssserting Video IRQ (%04x, %04x)\n", (m_video_irq_status & m_video_irq_enable) ? "A" : "Dea", m_video_irq_status, m_video_irq_enable);
1099 m_video_irq_cb((m_video_irq_status & m_video_irq_enable) ? ASSERT_LINE : CLEAR_LINE);
1100 }
1101
WRITE_LINE_MEMBER(gcm394_base_video_device::vblank)1102 WRITE_LINE_MEMBER(gcm394_base_video_device::vblank)
1103 {
1104 if (!state)
1105 {
1106 m_video_irq_status &= ~1;
1107 LOGMASKED(LOG_GCM394_VIDEO, "Setting video IRQ status to %04x\n", m_video_irq_status);
1108 check_video_irq();
1109 return;
1110 }
1111
1112 if (m_video_irq_enable & 1)
1113 {
1114 // jak_prft expects 0x800 to be set in the status register or most of the main vblank code is skipped, why?
1115
1116 m_video_irq_status |= 1 | 0x800;
1117 LOGMASKED(LOG_GCM394_VIDEO, "Setting video IRQ status to %04x\n", m_video_irq_status);
1118 check_video_irq();
1119 }
1120 }
1121
device_timer(emu_timer & timer,device_timer_id id,int param,void * ptr)1122 void gcm394_base_video_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
1123 {
1124 switch (id)
1125 {
1126 case TIMER_SCREENPOS:
1127 {
1128 if (m_video_irq_enable & 2)
1129 {
1130 m_video_irq_status |= 2;
1131 check_video_irq();
1132 }
1133
1134 //printf("firing irq timer\n");
1135
1136 m_screen->update_partial(m_screen->vpos());
1137
1138 // fire again, jak_dbz pinball needs this
1139 m_screenpos_timer->adjust(m_screen->time_until_pos(m_yirqpos-19, m_xirqpos));
1140 break;
1141 }
1142 }
1143 }
1144
1145
GFXDECODE_START(gfx)1146 static GFXDECODE_START( gfx )
1147 GFXDECODE_END
1148
1149 void gcm394_base_video_device::device_add_mconfig(machine_config &config)
1150 {
1151 PALETTE(config, m_palette).set_format(palette_device::xRGB_555, 256*0x10);
1152 GFXDECODE(config, m_gfxdecode, m_palette, gfx);
1153
1154 SPG_RENDERER(config, m_renderer, 0);
1155 }
1156
1157
1158