summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/video/lethalj.cpp
blob: 73e9dad414c173bd62c76df75bb5484ff4a0a47c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
/***************************************************************************

    The Game Room Lethal Justice hardware

***************************************************************************/

#include "emu.h"
#include "includes/lethalj.h"


#define BLITTER_SOURCE_WIDTH        1024
#define BLITTER_DEST_WIDTH          512
#define BLITTER_DEST_HEIGHT         512


/*************************************
 *
 *  Compute X/Y coordinates
 *
 *************************************/

inline void lethalj_state::get_crosshair_xy(int player, int *x, int *y)
{
	const rectangle &visarea = m_screen->visible_area();
	int width = visarea.width();
	int height = visarea.height();

	if (player)
	{
		*x = ((m_light1_x.read_safe(0) & 0xff) * width) / 255;
		*y = ((m_light1_y.read_safe(0) & 0xff) * height) / 255;
	}
	else
	{
		*x = ((m_light0_x.read_safe(0) & 0xff) * width) / 255;
		*y = ((m_light0_y.read_safe(0) & 0xff) * height) / 255;
	}
}



/*************************************
 *
 *  Gun input handling
 *
 *************************************/

READ16_MEMBER(lethalj_state::lethalj_gun_r)
{
	uint16_t result = 0;
	int beamx, beamy;

	switch (offset)
	{
		case 4:
		case 5:
			/* latch the crosshair position */
			get_crosshair_xy(offset - 4, &beamx, &beamy);
			m_gunx = beamx;
			m_guny = beamy;
			m_blank_palette = 1;
			break;

		case 6:
			result = m_gunx / 2;
			break;

		case 7:
			result = m_guny + 4;
			break;
	}
/*  logerror("%s:lethalj_gun_r(%d) = %04X\n", machine().describe_context(), offset, result); */
	return result;
}



/*************************************
 *
 *  video startup
 *
 *************************************/

void lethalj_state::video_start()
{
	/* allocate video RAM for screen */
	m_screenram = std::make_unique<uint16_t[]>(BLITTER_DEST_WIDTH * BLITTER_DEST_HEIGHT);

	/* predetermine blitter info */
	m_blitter_rows = m_blitter_base.length() / BLITTER_SOURCE_WIDTH;

	m_gen_ext1_int_timer = timer_alloc(TIMER_GEN_EXT1_INT);
}



/*************************************
 *
 *  Memory maps
 *
 *************************************/

void lethalj_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
	switch (id)
	{
	case TIMER_GEN_EXT1_INT:
		m_maincpu->set_input_line(0, ASSERT_LINE);
		break;
	default:
		throw emu_fatalerror("Unknown id in lethalj_state::device_timer");
	}
}


void lethalj_state::do_blit()
{
	int dsty = (int16_t)m_blitter_data[1];
	int srcx = (uint16_t)m_blitter_data[2];
	int srcy = (uint16_t)(m_blitter_data[3] + 1);
	int width = (uint16_t)m_blitter_data[5];
	int dstx = (int16_t)m_blitter_data[6];
	int height = (uint16_t)m_blitter_data[7];
	int y;
/*
    logerror("blitter data = %04X %04X %04X %04X %04X %04X %04X %04X\n",
            m_blitter_data[0], m_blitter_data[1], m_blitter_data[2], m_blitter_data[3],
            m_blitter_data[4], m_blitter_data[5], m_blitter_data[6], m_blitter_data[7]);
*/
	/* loop over Y coordinates */
	for (y = 0; y <= height; y++, srcy++, dsty++)
	{
		/* clip in Y */
		if (dsty >= 0 && dsty < BLITTER_DEST_HEIGHT/2)
		{
			uint16_t *source = m_blitter_base + ((srcy % m_blitter_rows) << 10);
			uint16_t *dest = m_screenram.get() + ((dsty + ((m_vispage ^ 1) << 8)) << 9);
			int sx = srcx;
			int dx = dstx;
			int x;

			/* loop over X coordinates */
			for (x = 0; x <= width; x++, sx++, dx++)
			{
				dx &= 0x1ff;

				int pix = source[sx & 0x3ff];
				if (pix)
					dest[dx] = pix;

			}
		}
	}
}


WRITE16_MEMBER(lethalj_state::blitter_w)
{
	/* combine the data */
	COMBINE_DATA(&m_blitter_data[offset]);

	/* blit on a write to offset 7, and signal an IRQ */
	if (offset == 7)
	{
		if (m_blitter_data[6] == 2 && m_blitter_data[7] == 2)
			m_vispage ^= 1;
		else
			do_blit();

		m_gen_ext1_int_timer->adjust(attotime::from_hz(XTAL(32'000'000)) * ((m_blitter_data[5] + 1) * (m_blitter_data[7] + 1)));
	}

	/* clear the IRQ on offset 0 */
	else if (offset == 0)
		m_maincpu->set_input_line(0, CLEAR_LINE);
}



/*************************************
 *
 *  video update
 *
 *************************************/

TMS340X0_SCANLINE_IND16_CB_MEMBER(lethalj_state::scanline_update)
{
	uint16_t *src = &m_screenram[(m_vispage << 17) | ((params->rowaddr << 9) & 0x3fe00)];
	uint16_t *dest = &bitmap.pix16(scanline);
	int coladdr = params->coladdr << 1;
	int x;

	/* blank palette: fill with white */
	if (m_blank_palette)
	{
		for (x = params->heblnk; x < params->hsblnk; x++)
			dest[x] = 0x7fff;
		if (scanline == screen.visible_area().max_y)
			m_blank_palette = 0;
		return;
	}

	/* copy the non-blanked portions of this scanline */
	for (x = params->heblnk; x < params->hsblnk; x++)
		dest[x] = src[coladdr++ & 0x1ff] & 0x7fff;
}