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