1 // license:BSD-3-Clause
2 // copyright-holders:Fabio Priuli,Acho A. Tang, R. Belmont
3 /*
4 Konami 007342
5 ------
6 The 007342 manages 2 64x32 scrolling tilemaps with 8x8 characters, and
7 optionally generates timing clocks and interrupt signals. It uses 0x2000
8 bytes of RAM, plus 0x0200 bytes for scrolling, and a variable amount of ROM.
9 It cannot read the ROMs.
10 
11 control registers
12 000: ------x- INT control
13      ---x---- flip screen (TODO: doesn't work with thehustl)
14 001: Used for banking in Rock'n'Rage
15 002: -------x MSB of x scroll 1
16      ------x- MSB of x scroll 2
17      ---xxx-- layer 1 row/column scroll control
18               000 = disabled
19               010 = unknown (bladestl shootout between periods)
20               011 = 32 columns (Blades of Steel)
21               101 = 256 rows (Battlantis, Rock 'n Rage)
22      x------- enable sprite wraparound from bottom to top (see Blades of Steel
23               high score table)
24 003: x scroll 1
25 004: y scroll 1
26 005: x scroll 2
27 006: y scroll 2
28 007: not used
29 */
30 
31 #include "emu.h"
32 #include "k007342.h"
33 #include "konami_helper.h"
34 
35 //#define VERBOSE 1
36 #include "logmacro.h"
37 
38 
39 DEFINE_DEVICE_TYPE(K007342, k007342_device, "k007342", "K007342 Video Controller")
40 
k007342_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)41 k007342_device::k007342_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
42 	device_t(mconfig, K007342, tag, owner, clock),
43 	m_ram(nullptr),
44 	m_scroll_ram(nullptr),
45 	m_videoram_0(nullptr),
46 	m_videoram_1(nullptr),
47 	m_colorram_0(nullptr),
48 	m_colorram_1(nullptr),
49 	//m_tilemap[2];
50 	m_flipscreen(0),
51 	m_int_enabled(0),
52 	//m_regs[8],
53 	//m_scrollx[2],
54 	//m_scrolly[2],
55 	m_gfxdecode(*this, finder_base::DUMMY_TAG),
56 	m_callback(*this),
57 	m_gfxnum(0)
58 {
59 }
60 
61 //-------------------------------------------------
62 //  device_start - device-specific startup
63 //-------------------------------------------------
64 
device_start()65 void k007342_device::device_start()
66 {
67 	if(!m_gfxdecode->started())
68 		throw device_missing_dependencies();
69 
70 	// bind the init function
71 	m_callback.resolve();
72 
73 	m_tilemap[0] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(k007342_device::get_tile_info0)), tilemap_mapper_delegate(*this, FUNC(k007342_device::scan)), 8, 8, 64, 32);
74 	m_tilemap[1] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(k007342_device::get_tile_info1)), tilemap_mapper_delegate(*this, FUNC(k007342_device::scan)), 8, 8, 64, 32);
75 
76 	m_ram = make_unique_clear<uint8_t[]>(0x2000);
77 	m_scroll_ram = make_unique_clear<uint8_t[]>(0x0200);
78 
79 	m_colorram_0 = &m_ram[0x0000];
80 	m_colorram_1 = &m_ram[0x1000];
81 	m_videoram_0 = &m_ram[0x0800];
82 	m_videoram_1 = &m_ram[0x1800];
83 
84 	m_tilemap[0]->set_transparent_pen(0);
85 	m_tilemap[1]->set_transparent_pen(0);
86 
87 	save_pointer(NAME(m_ram), 0x2000);
88 	save_pointer(NAME(m_scroll_ram), 0x0200);
89 	save_item(NAME(m_int_enabled));
90 	save_item(NAME(m_flipscreen));
91 	save_item(NAME(m_scrollx));
92 	save_item(NAME(m_scrolly));
93 	save_item(NAME(m_regs));
94 }
95 
96 //-------------------------------------------------
97 //  device_reset - device-specific reset
98 //-------------------------------------------------
99 
device_reset()100 void k007342_device::device_reset()
101 {
102 	m_int_enabled = 0;
103 	m_flipscreen = 0;
104 	m_scrollx[0] = 0;
105 	m_scrollx[1] = 0;
106 	m_scrolly[0] = 0;
107 	m_scrolly[1] = 0;
108 
109 	for (int i = 0; i < 8; i++)
110 		m_regs[i] = 0;
111 }
112 
113 /*****************************************************************************
114     DEVICE HANDLERS
115 *****************************************************************************/
116 
read(offs_t offset)117 uint8_t k007342_device::read(offs_t offset)
118 {
119 	return m_ram[offset];
120 }
121 
write(offs_t offset,uint8_t data)122 void k007342_device::write(offs_t offset, uint8_t data)
123 {
124 	m_ram[offset] = data;
125 
126 	if (offset < 0x1000)    /* layer 0 */
127 		m_tilemap[0]->mark_tile_dirty(offset & 0x7ff);
128 	else                /* layer 1 */
129 		m_tilemap[1]->mark_tile_dirty(offset & 0x7ff);
130 }
131 
scroll_r(offs_t offset)132 uint8_t k007342_device::scroll_r(offs_t offset)
133 {
134 	return m_scroll_ram[offset];
135 }
136 
scroll_w(offs_t offset,uint8_t data)137 void k007342_device::scroll_w(offs_t offset, uint8_t data)
138 {
139 	m_scroll_ram[offset] = data;
140 }
141 
vreg_w(offs_t offset,uint8_t data)142 void k007342_device::vreg_w(offs_t offset, uint8_t data)
143 {
144 	switch(offset)
145 	{
146 		case 0x00:
147 			/* bit 1: INT control */
148 			m_int_enabled = data & 0x02;
149 			m_flipscreen = data & 0x10;
150 			m_tilemap[0]->set_flip(m_flipscreen ? (TILEMAP_FLIPY | TILEMAP_FLIPX) : 0);
151 			m_tilemap[1]->set_flip(m_flipscreen ? (TILEMAP_FLIPY | TILEMAP_FLIPX) : 0);
152 			break;
153 		case 0x01:  /* used for banking in Rock'n'Rage */
154 			if (data != m_regs[1])
155 				machine().tilemap().mark_all_dirty();
156 		case 0x02:
157 			m_scrollx[0] = (m_scrollx[0] & 0xff) | ((data & 0x01) << 8);
158 			m_scrollx[1] = (m_scrollx[1] & 0xff) | ((data & 0x02) << 7);
159 			break;
160 		case 0x03:  /* scroll x (register 0) */
161 			m_scrollx[0] = (m_scrollx[0] & 0x100) | data;
162 			break;
163 		case 0x04:  /* scroll y (register 0) */
164 			m_scrolly[0] = data;
165 			break;
166 		case 0x05:  /* scroll x (register 1) */
167 			m_scrollx[1] = (m_scrollx[1] & 0x100) | data;
168 			break;
169 		case 0x06:  /* scroll y (register 1) */
170 			m_scrolly[1] = data;
171 		case 0x07:  /* unused */
172 			break;
173 	}
174 	m_regs[offset] = data;
175 }
176 
tilemap_update()177 void k007342_device::tilemap_update( )
178 {
179 	/* update scroll */
180 	switch (m_regs[2] & 0x1c)
181 	{
182 		case 0x00:
183 		case 0x08:  /* unknown, blades of steel shootout between periods */
184 			m_tilemap[0]->set_scroll_rows(1);
185 			m_tilemap[0]->set_scroll_cols(1);
186 			m_tilemap[0]->set_scrollx(0, m_scrollx[0]);
187 			m_tilemap[0]->set_scrolly(0, m_scrolly[0]);
188 			break;
189 
190 		case 0x0c:  /* 32 columns */
191 			m_tilemap[0]->set_scroll_rows(1);
192 			m_tilemap[0]->set_scroll_cols(512);
193 			m_tilemap[0]->set_scrollx(0, m_scrollx[0]);
194 			for (int offs = 0; offs < 256; offs++)
195 				m_tilemap[0]->set_scrolly((offs + m_scrollx[0]) & 0x1ff,
196 						m_scroll_ram[2 * (offs / 8)] + 256 * m_scroll_ram[2 * (offs / 8) + 1]);
197 			break;
198 
199 		case 0x14:  /* 256 rows */
200 			m_tilemap[0]->set_scroll_rows(256);
201 			m_tilemap[0]->set_scroll_cols(1);
202 			m_tilemap[0]->set_scrolly(0, m_scrolly[0]);
203 			for (int offs = 0; offs < 256; offs++)
204 				m_tilemap[0]->set_scrollx((offs + m_scrolly[0]) & 0xff,
205 						m_scroll_ram[2 * offs] + 256 * m_scroll_ram[2 * offs + 1]);
206 			break;
207 
208 		default:
209 //          popmessage("unknown scroll ctrl %02x", m_regs[2] & 0x1c);
210 			break;
211 	}
212 
213 	m_tilemap[1]->set_scrollx(0, m_scrollx[1]);
214 	m_tilemap[1]->set_scrolly(0, m_scrolly[1]);
215 
216 #if 0
217 	{
218 		static int current_layer = 0;
219 
220 		if (machine.input().code_pressed_once(KEYCODE_Z)) current_layer = !current_layer;
221 		m_tilemap[current_layer]->enable(1);
222 		m_tilemap[!current_layer]->enable(0);
223 
224 		popmessage("regs:%02x %02x %02x %02x-%02x %02x %02x %02x:%02x",
225 			m_regs[0], m_regs[1], m_regs[2], m_regs[3],
226 			m_regs[4], m_regs[5], m_regs[6], m_regs[7],
227 			current_layer);
228 	}
229 #endif
230 }
231 
tilemap_draw(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect,int num,int flags,uint32_t priority)232 void k007342_device::tilemap_draw( screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int num, int flags, uint32_t priority )
233 {
234 	m_tilemap[num]->draw(screen, bitmap, cliprect, flags, priority);
235 }
236 
is_int_enabled()237 int k007342_device::is_int_enabled( )
238 {
239 	return m_int_enabled;
240 }
241 
242 
243 /***************************************************************************
244 
245   Callbacks for the TileMap code
246 
247 ***************************************************************************/
248 
249 /*
250   data format:
251   video RAM     xxxxxxxx    tile number (bits 0-7)
252   color RAM     x-------    tiles with priority over the sprites
253   color RAM     -x------    depends on external conections
254   color RAM     --x-----    flip Y
255   color RAM     ---x----    flip X
256   color RAM     ----xxxx    depends on external connections (usually color and banking)
257 */
258 
TILEMAP_MAPPER_MEMBER(k007342_device::scan)259 TILEMAP_MAPPER_MEMBER(k007342_device::scan)
260 {
261 	/* logical (col,row) -> memory offset */
262 	return (col & 0x1f) + ((row & 0x1f) << 5) + ((col & 0x20) << 5);
263 }
264 
get_tile_info(tile_data & tileinfo,int tile_index,int layer,uint8_t * cram,uint8_t * vram)265 void k007342_device::get_tile_info( tile_data &tileinfo, int tile_index, int layer, uint8_t *cram, uint8_t *vram )
266 {
267 	int color = cram[tile_index];
268 	int code = vram[tile_index];
269 	int flags = TILE_FLIPYX((color & 0x30) >> 4);
270 
271 	tileinfo.category = (color & 0x80) >> 7;
272 
273 	if (!m_callback.isnull())
274 		m_callback(layer, m_regs[1], &code, &color, &flags);
275 
276 
277 	tileinfo.set(m_gfxnum,
278 			code,
279 			color,
280 			flags);
281 }
282 
TILE_GET_INFO_MEMBER(k007342_device::get_tile_info0)283 TILE_GET_INFO_MEMBER(k007342_device::get_tile_info0)
284 {
285 	get_tile_info(tileinfo, tile_index, 0, m_colorram_0, m_videoram_0);
286 }
287 
TILE_GET_INFO_MEMBER(k007342_device::get_tile_info1)288 TILE_GET_INFO_MEMBER(k007342_device::get_tile_info1)
289 {
290 	get_tile_info(tileinfo, tile_index, 1, m_colorram_1, m_videoram_1);
291 }
292