1
/*************************************************************************************************************
5
driver by Luca Elia (l.elia@tin.it)
8
Note: if MAME_DEBUG is defined, pressing Z with:
10
Q / W / E / R Shows Layer 0 / 1 / 2 / 3
13
Keys can be used together!
15
[ 4 Scrolling Layers ]
19
8 x 8 x 6 0x800 x 0x200
20
8 x 8 x 6 0x200 x 0x100
21
16x16 x 6 0x800 x 0x200
22
32x32 x 6 0x800 x 0x200
26
Each sprite is made of N x M tiles (up to 16 x 16 tiles).
33
RAM based priorities, with a per tile priority code
34
(the same sprite goes below some parts, and above others, of the same layer)
36
*************************************************************************************************************/
39
#include "includes/lordgun.h"
42
/***************************************************************************
46
***************************************************************************/
48
// xxxxBBBBGGGGRRRR, but repeat ecah color for each priority code (since we stuff it in the high bits of the pen)
49
WRITE16_HANDLER( lordgun_paletteram_w )
51
COMBINE_DATA(&space->machine().generic.paletteram.u16[offset]);
52
for (int pri = 0; pri < 8; pri++)
53
palette_set_color_rgb(space->machine(), offset+0x800*pri, pal4bit(data >> 0), pal4bit(data >> 4), pal4bit(data >> 8));
57
/***************************************************************************
61
***************************************************************************/
64
INLINE void get_tile_info(running_machine &machine, tile_data *tileinfo, tilemap_memory_index tile_index, int _N_)
66
lordgun_state *state = machine.driver_data<lordgun_state>();
67
UINT16 attr = state->m_vram[_N_][tile_index * 2 + 0 ];
68
UINT16 code = state->m_vram[_N_][ tile_index * 2 + 1 ];
69
UINT16 pri = (attr & 0x0e00) >> 9;
70
SET_TILE_INFO( _N_, code, ((attr & 0x0030) >> 4) + 0x10 + 0x4 * ((_N_ + 1) & 3) + pri*0x800/0x40, TILE_FLIPXY(attr >> 14));
73
static TILE_GET_INFO( get_tile_info_0 ) { get_tile_info(machine, tileinfo, tile_index, 0); }
74
static TILE_GET_INFO( get_tile_info_1 ) { get_tile_info(machine, tileinfo, tile_index, 1); }
75
static TILE_GET_INFO( get_tile_info_2 ) { get_tile_info(machine, tileinfo, tile_index, 2); }
76
static TILE_GET_INFO( get_tile_info_3 ) { get_tile_info(machine, tileinfo, tile_index, 3); }
78
INLINE void lordgun_vram_w(address_space *space, offs_t offset, UINT16 data, UINT16 mem_mask, int _N_)
80
lordgun_state *state = space->machine().driver_data<lordgun_state>();
81
COMBINE_DATA(&state->m_vram[_N_][offset]);
82
tilemap_mark_tile_dirty(state->m_tilemap[_N_], offset/2);
85
WRITE16_HANDLER( lordgun_vram_0_w ) { lordgun_vram_w(space, offset, data, mem_mask, 0); }
86
WRITE16_HANDLER( lordgun_vram_1_w ) { lordgun_vram_w(space, offset, data, mem_mask, 1); }
87
WRITE16_HANDLER( lordgun_vram_2_w ) { lordgun_vram_w(space, offset, data, mem_mask, 2); }
88
WRITE16_HANDLER( lordgun_vram_3_w ) { lordgun_vram_w(space, offset, data, mem_mask, 3); }
90
/***************************************************************************
94
***************************************************************************/
97
VIDEO_START( lordgun )
99
lordgun_state *state = machine.driver_data<lordgun_state>();
101
int w = machine.primary_screen->width();
102
int h = machine.primary_screen->height();
105
state->m_tilemap[0] = tilemap_create( machine, get_tile_info_0, tilemap_scan_rows,
109
state->m_tilemap[1] = tilemap_create( machine, get_tile_info_1, tilemap_scan_rows,
113
state->m_tilemap[2] = tilemap_create( machine, get_tile_info_2, tilemap_scan_rows,
117
state->m_tilemap[3] = tilemap_create( machine, get_tile_info_3, tilemap_scan_rows,
120
tilemap_set_scroll_rows(state->m_tilemap[0],1);
121
tilemap_set_scroll_cols(state->m_tilemap[0],1);
122
tilemap_set_transparent_pen(state->m_tilemap[0],0x3f);
125
tilemap_set_scroll_rows(state->m_tilemap[1],0x200);
126
tilemap_set_scroll_cols(state->m_tilemap[1],1);
127
tilemap_set_transparent_pen(state->m_tilemap[1],0x3f);
129
tilemap_set_scroll_rows(state->m_tilemap[2],1);
130
tilemap_set_scroll_cols(state->m_tilemap[2],1);
131
tilemap_set_transparent_pen(state->m_tilemap[2],0x3f);
133
tilemap_set_scroll_rows(state->m_tilemap[3],1);
134
tilemap_set_scroll_cols(state->m_tilemap[3],1);
135
tilemap_set_transparent_pen(state->m_tilemap[3],0x3f);
137
// Buffer bitmaps for 4 tilemaps (0-3) + sprites (4)
138
for (i = 0; i < 5; i++)
139
state->m_bitmaps[i] = auto_bitmap_alloc(machine, w, h, BITMAP_FORMAT_INDEXED16);
142
/***************************************************************************
146
***************************************************************************/
148
static const int lordgun_gun_x_table[] =
150
-100, 0x001,0x001,0x002,0x002,0x003,0x003,0x004,0x005,0x006,0x007,0x008,0x009,0x00A,0x00B,0x00C,
151
0x00D,0x00E,0x00F,0x010,0x011,0x012,0x013,0x014,0x015,0x016,0x017,0x018,0x019,0x01A,0x01B,0x01C,
152
0x01D,0x01E,0x01F,0x020,0x021,0x022,0x023,0x024,0x025,0x026,0x027,0x028,0x029,0x02A,0x02B,0x02C,
153
0x02D,0x02E,0x02F,0x030,0x031,0x032,0x033,0x034,0x035,0x036,0x037,0x038,0x039,0x03A,0x03B,0x03C,
154
0x03D,0x03E,0x03F,0x040,0x041,0x043,0x044,0x045,0x046,0x047,0x048,0x049,0x04A,0x04B,0x04C,0x04E,
155
0x04F,0x050,0x051,0x052,0x053,0x054,0x055,0x056,0x057,0x059,0x05A,0x05B,0x05C,0x05D,0x05E,0x05F,
156
0x060,0x061,0x05A,0x063,0x065,0x066,0x067,0x068,0x069,0x06A,0x06B,0x06C,0x06D,0x06E,0x06F,0x071,
157
0x072,0x074,0x075,0x077,0x078,0x07A,0x07B,0x07D,0x07E,0x080,0x081,0x083,0x085,0x087,0x089,0x08B,
158
0x08D,0x08E,0x08F,0x090,0x092,0x093,0x095,0x097,0x098,0x099,0x09A,0x09B,0x09C,0x09D,0x09E,0x0A0,
159
0x0A1,0x0A2,0x0A3,0x0A4,0x0A5,0x0A6,0x0A7,0x0A8,0x0A9,0x0AA,0x0AC,0x0AD,0x0AE,0x0AF,0x0B0,0x0B1,
160
0x0B2,0x0B3,0x0B4,0x0B5,0x0B6,0x0B8,0x0B9,0x0BA,0x0BB,0x0BC,0x0BD,0x0BE,0x0BF,0x0C0,0x0C1,0x0C2,
161
0x0C4,0x0C5,0x0C6,0x0C7,0x0C8,0x0C9,0x0CA,0x0CB,0x0CC,0x0CD,0x0CF,0x0D0,0x0D1,0x0D2,0x0D3,0x0D4,
162
0x0D5,0x0D6,0x0D7,0x0D8,0x0D9,0x0DB,0x0DC,0x0DD,0x0DE,0x0DF,0x0E0,0x0E1,0x0E2,0x0E3,0x0E4,0x0E5,
163
0x0E7,0x0E8,0x0E9,0x0EA,0x0EB,0x0EC,0x0ED,0x0EE,0x0EF,0x0F0,0x0F1,0x0F3,0x0F4,0x0F5,0x0F6,0x0F7,
164
0x0F8,0x0F9,0x0FA,0x0FB,0x0FC,0x0FE,0x0FF,0x100,0x101,0x102,0x103,0x104,0x105,0x106,0x107,0x108,
165
0x10A,0x10B,0x10C,0x10D,0x10E,0x10F,0x110,0x111,0x112,0x113,0x114,0x116,0x117,0x118,0x119,0x11A,
166
0x11B,0x11C,0x11D,0x11E,0x11F,0x120,0x122,0x123,0x124,0x125,0x126,0x127,0x128,0x129,0x12A,0x12B,
167
0x12C,0x12E,0x12F,0x130,0x131,0x132,0x133,0x134,0x135,0x136,0x137,0x139,0x13A,0x13B,0x13C,0x13D,
168
0x13E,0x13F,0x140,0x141,0x142,0x143,0x145,0x146,0x147,0x148,0x149,0x14A,0x14B,0x14C,0x14D,0x14E,
169
0x14F,0x151,0x152,0x153,0x154,0x155,0x156,0x157,0x158,0x159,0x15A,0x15B,0x15D,0x15E,0x15F,0x160,
170
0x161,0x162,0x163,0x164,0x165,0x166,0x167,0x169,0x16A,0x16B,0x16C,0x16D,0x16E,0x16F,0x170,0x171,
171
0x172,0x174,0x175,0x176,0x177,0x178,0x179,0x17A,0x17B,0x17C,0x17D,0x17E,0x17F,0x180,0x181,0x182,
172
0x183,0x184,0x185,0x186,0x187,0x188,0x189,0x18A,0x18B,0x18C,0x18D,0x18E,0x18F,0x190,0x191,0x192,
173
0x193,0x194,0x195,0x196,0x197,0x198,0x199,0x19A,0x19B,0x19C,0x19D,0x19E,0x19F,0x1A0,0x1A1,0x1A2,
174
0x1A3,0x1A4,0x1A5,0x1A6,0x1A7,0x1A8,0x1A9,0x1AA,0x1AB,0x1AC,0x1AD,0x1AE,0x1AF,0x1B0,0x1B1,0x1B2,
175
0x1B3,0x1B4,0x1B5,0x1B6,0x1B7,0x1B8,0x1B9,0x1BA,0x1BB,0x1BC,0x1BD,0x1BE,0x1BF,0x1BF
178
static const char *const gunnames[] = { "LIGHT0_X", "LIGHT1_X", "LIGHT0_Y", "LIGHT1_Y" };
180
float lordgun_crosshair_mapper(const input_field_config *field, float linear_value)
182
int x = linear_value - 0x3c;
184
if ( (x < 0) || (x > sizeof(lordgun_gun_x_table)/sizeof(lordgun_gun_x_table[0])) )
187
return lordgun_gun_x_table[x] * 1.0f / 0x1BF;
190
static void lorddgun_calc_gun_scr(running_machine &machine, int i)
192
lordgun_state *state = machine.driver_data<lordgun_state>();
193
// popmessage("%03x, %02x", input_port_read(machine, "LIGHT0_X"), input_port_read(machine, "LIGHT0_Y"));
195
int x = input_port_read(machine, gunnames[i]) - 0x3c;
197
if ( (x < 0) || (x > sizeof(lordgun_gun_x_table)/sizeof(lordgun_gun_x_table[0])) )
200
state->m_gun[i].scr_x = lordgun_gun_x_table[x];
201
state->m_gun[i].scr_y = input_port_read(machine, gunnames[i+2]);
204
void lordgun_update_gun(running_machine &machine, int i)
206
lordgun_state *state = machine.driver_data<lordgun_state>();
207
const rectangle &visarea = machine.primary_screen->visible_area();
209
state->m_gun[i].hw_x = input_port_read(machine, gunnames[i]);
210
state->m_gun[i].hw_y = input_port_read(machine, gunnames[i+2]);
212
lorddgun_calc_gun_scr(machine, i);
214
if ( (state->m_gun[i].scr_x < visarea.min_x) ||
215
(state->m_gun[i].scr_x > visarea.max_x) ||
216
(state->m_gun[i].scr_y < visarea.min_y) ||
217
(state->m_gun[i].scr_y > visarea.max_y) )
218
state->m_gun[i].hw_x = state->m_gun[i].hw_y = 0;
222
/***************************************************************************
229
0.w fedc ---- ---- ---- Number of Y Tiles - 1
230
---- ba98 7654 3210 Y
232
2.w f--- ---- ---- ---- Flip X
233
-e-- ---- ---- ---- Flip Y
235
---- ba9- ---- ---- Priority
236
---- ---8 ---- ---- End of Sprite List
237
---- ---- 7654 ---- Color
238
---- ---- ---- 3210 Number of X Tiles - 1
244
***************************************************************************/
246
static void draw_sprites(running_machine &machine, bitmap_t *bitmap, const rectangle *cliprect)
248
lordgun_state *state = machine.driver_data<lordgun_state>();
249
UINT16 *s = state->m_spriteram;
250
UINT16 *end = state->m_spriteram + state->m_spriteram_size/2;
252
for ( ; s < end; s += 8/2 )
254
int attr, code, color, pri;
255
int sx, nx, x, x0, x1, dx, flipx;
256
int sy, ny, y, y0, y1, dy, flipy;
263
// End of sprite list
267
flipx = attr & 0x8000;
268
flipy = attr & 0x4000;
269
pri = (attr & 0x0e00) >> 9;
270
color = (attr & 0x00f0) >> 4;
271
nx = (attr & 0x000f) + 1;
273
ny = ((sy & 0xf000) >> 12) + 1;
275
if ( flipx ) { x0 = nx - 1; x1 = -1; dx = -1; }
276
else { x0 = 0; x1 = nx; dx = +1; }
278
if ( flipy ) { y0 = ny - 1; y1 = -1; dy = -1; }
279
else { y0 = 0; y1 = ny; dy = +1; }
281
// Sign extend the position
283
sy = (sy & 0x7ff) - (sy & 0x800);
285
for (y = y0; y != y1; y += dy)
287
for (x = x0; x != x1; x += dx)
289
drawgfx_transpen( bitmap, cliprect, machine.gfx[4],
290
code, color + pri * 0x800/0x40,
292
sx + x * 0x10, sy + y * 0x10,
297
code += 1 - 0x10 * nx;
302
/***************************************************************************
306
Priorities are similar to those in igs011.c
308
There are 4 scrolling layers, plus sprites, with a per tile priority
311
Then there are 0x20000 bytes of priority RAM. Each word contains a
312
layer code (3-7), where 3 means sprites, and the rest are the tilemaps.
313
Actually, the layer code is repeated in both nibbles (e.g. 0x0033).
315
For each screen position, to determine which pixel to display, the video
316
chip associates a bit to the opacity of that pixel for each layer
317
(1 = transparent) to form an address into priority RAM.
318
So the bottom 5 bits of the priority RAM address depend on the layer opacities.
320
The higher order bits come from the priority of the pixels from each layer
321
(not all layers, actually, I guess to save on RAM size).
323
The priority RAM value at that address selects the topmost layer, that
324
gets sent to the screen.
326
***************************************************************************/
328
SCREEN_UPDATE( lordgun )
330
lordgun_state *state = screen->machine().driver_data<lordgun_state>();
331
int layers_ctrl = -1;
334
if (screen->machine().input().code_pressed(KEYCODE_Z))
338
if (screen->machine().input().code_pressed(KEYCODE_Q)) msk |= 1;
339
if (screen->machine().input().code_pressed(KEYCODE_W)) msk |= 2;
340
if (screen->machine().input().code_pressed(KEYCODE_E)) msk |= 4;
341
if (screen->machine().input().code_pressed(KEYCODE_R)) msk |= 8;
342
if (screen->machine().input().code_pressed(KEYCODE_A)) msk |= 16;
343
if (msk != 0) layers_ctrl &= msk;
347
if (state->m_whitescreen)
349
bitmap_fill(bitmap, cliprect, get_white_pen(screen->machine()));
357
tilemap_set_scrollx( state->m_tilemap[0], 0, *state->m_scroll_x[0] );
358
tilemap_set_scrolly( state->m_tilemap[0], 0, *state->m_scroll_y[0] );
360
for (y = 0; y < 0x200; y++)
361
tilemap_set_scrollx( state->m_tilemap[1], y, (*state->m_scroll_x[1]) + state->m_scrollram[y * 4/2 + 2/2]);
362
tilemap_set_scrolly( state->m_tilemap[1], 0, *state->m_scroll_y[1] );
364
tilemap_set_scrollx( state->m_tilemap[2], 0, *state->m_scroll_x[2] );
365
tilemap_set_scrolly( state->m_tilemap[2], 0, *state->m_scroll_y[2] );
367
tilemap_set_scrollx( state->m_tilemap[3], 0, *state->m_scroll_x[3] );
368
tilemap_set_scrolly( state->m_tilemap[3], 0, *state->m_scroll_y[3] );
372
// render each layer (0-3 tilemaps, 4 sprites) into a buffer bitmap.
373
// The priority code of each pixel will be stored into the high 3 bits of the pen
375
pen_t trans_pen = 0 * 0x800 + 0x3f; // pri = 0, pen = 3f (transparent)
378
for (l = 0; l < 5; l++)
379
bitmap_fill(state->m_bitmaps[l], cliprect, trans_pen);
381
if (layers_ctrl & 1) tilemap_draw(state->m_bitmaps[0], cliprect, state->m_tilemap[0], 0, 0);
382
if (layers_ctrl & 2) tilemap_draw(state->m_bitmaps[1], cliprect, state->m_tilemap[1], 0, 0);
383
if (layers_ctrl & 4) tilemap_draw(state->m_bitmaps[2], cliprect, state->m_tilemap[2], 0, 0);
384
if (layers_ctrl & 8) tilemap_draw(state->m_bitmaps[3], cliprect, state->m_tilemap[3], 0, 0);
385
if (layers_ctrl & 16) draw_sprites(screen->machine(), state->m_bitmaps[4], cliprect);
387
// copy to screen bitmap
389
// priority code (3-7) -> layer index (0-3, 4 for sprites)
390
const int pri2layer[8] = {0,0,0,4,3,0,1,2};
391
// layer index (0-3, 4 for sprites) -> priority address bit
392
const int layer2bit[5] = {0,1,2,4,3};
394
for (y = cliprect->min_y; y <= cliprect->max_y; y++)
396
for (x = cliprect->min_x; x <= cliprect->max_x; x++)
402
// bits 0-4: layer transparency
403
for (l = 0; l < 5; l++)
405
pens[l] = *BITMAP_ADDR16(state->m_bitmaps[l], y, x);
406
if (pens[l] == trans_pen)
407
pri_addr |= 1 << layer2bit[l];
410
// bits 05-07: layer 1 priority
411
pri_addr |= (pens[1]>>11) << 5;
412
// bits 08-10: sprites priority
413
pri_addr |= (pens[4]>>11) << 8;
414
// bits 11-13: layer 0 priority
415
pri_addr |= (pens[0]>>11) << 11;
416
// bit 14: layer 3 priority
417
pri_addr |= (pens[3]>>11) << 14;
421
l = pri2layer[state->m_priority_ram[pri_addr] & 7];
423
*BITMAP_ADDR16(bitmap, y, x) = pens[l];