1 // license:BSD-3-Clause
2 // copyright-holders:Bryan McPhail, David Haywood
3 #include "emu.h"
4 #include "includes/dynduke.h"
5 
6 
7 
8 /******************************************************************************/
9 
background_w(offs_t offset,uint16_t data,uint16_t mem_mask)10 void dynduke_state::background_w(offs_t offset, uint16_t data, uint16_t mem_mask)
11 {
12 	COMBINE_DATA(&m_back_data[offset]);
13 	m_bg_layer->mark_tile_dirty(offset);
14 }
15 
foreground_w(offs_t offset,uint16_t data,uint16_t mem_mask)16 void dynduke_state::foreground_w(offs_t offset, uint16_t data, uint16_t mem_mask)
17 {
18 	COMBINE_DATA(&m_fore_data[offset]);
19 	m_fg_layer->mark_tile_dirty(offset);
20 }
21 
text_w(offs_t offset,uint16_t data,uint16_t mem_mask)22 void dynduke_state::text_w(offs_t offset, uint16_t data, uint16_t mem_mask)
23 {
24 	COMBINE_DATA(&m_videoram[offset]);
25 	m_tx_layer->mark_tile_dirty(offset);
26 }
27 
TILE_GET_INFO_MEMBER(dynduke_state::get_bg_tile_info)28 TILE_GET_INFO_MEMBER(dynduke_state::get_bg_tile_info)
29 {
30 	int tile=m_back_data[tile_index];
31 	int color=tile >> 12;
32 
33 	tile=tile&0xfff;
34 
35 	tileinfo.set(1,
36 			tile+m_back_bankbase,
37 			color,
38 			0);
39 }
40 
TILE_GET_INFO_MEMBER(dynduke_state::get_fg_tile_info)41 TILE_GET_INFO_MEMBER(dynduke_state::get_fg_tile_info)
42 {
43 	int tile=m_fore_data[tile_index];
44 	int color=tile >> 12;
45 
46 	tile=tile&0xfff;
47 
48 	tileinfo.set(2,
49 			tile+m_fore_bankbase,
50 			color,
51 			0);
52 }
53 
TILE_GET_INFO_MEMBER(dynduke_state::get_tx_tile_info)54 TILE_GET_INFO_MEMBER(dynduke_state::get_tx_tile_info)
55 {
56 	int tile=m_videoram[tile_index];
57 	int color=(tile >> 8) & 0x0f;
58 
59 	tile = (tile & 0xff) | ((tile & 0xc000) >> 6);
60 
61 	tileinfo.set(0,
62 			tile,
63 			color,
64 			0);
65 }
66 
video_start()67 void dynduke_state::video_start()
68 {
69 	m_bg_layer = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(dynduke_state::get_bg_tile_info)), TILEMAP_SCAN_COLS,16,16,32,32);
70 	m_fg_layer = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(dynduke_state::get_fg_tile_info)), TILEMAP_SCAN_COLS,16,16,32,32);
71 	m_tx_layer = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(dynduke_state::get_tx_tile_info)), TILEMAP_SCAN_ROWS, 8, 8,32,32);
72 
73 	m_fg_layer->set_transparent_pen(15);
74 	m_tx_layer->set_transparent_pen(15);
75 
76 	save_item(NAME(m_back_bankbase));
77 	save_item(NAME(m_fore_bankbase));
78 	save_item(NAME(m_back_enable));
79 	save_item(NAME(m_fore_enable));
80 	save_item(NAME(m_sprite_enable));
81 	save_item(NAME(m_txt_enable));
82 	save_item(NAME(m_old_back));
83 	save_item(NAME(m_old_fore));
84 }
85 
gfxbank_w(offs_t offset,uint16_t data,uint16_t mem_mask)86 void dynduke_state::gfxbank_w(offs_t offset, uint16_t data, uint16_t mem_mask)
87 {
88 	if (ACCESSING_BITS_0_7)
89 	{
90 		if (data&0x01) m_back_bankbase=0x1000; else m_back_bankbase=0;
91 		if (data&0x10) m_fore_bankbase=0x1000; else m_fore_bankbase=0;
92 
93 		if (m_back_bankbase!=m_old_back)
94 			m_bg_layer->mark_all_dirty();
95 		if (m_fore_bankbase!=m_old_fore)
96 			m_fg_layer->mark_all_dirty();
97 
98 		m_old_back=m_back_bankbase;
99 		m_old_fore=m_fore_bankbase;
100 	}
101 }
102 
103 
control_w(offs_t offset,uint16_t data,uint16_t mem_mask)104 void dynduke_state::control_w(offs_t offset, uint16_t data, uint16_t mem_mask)
105 {
106 	if (ACCESSING_BITS_0_7)
107 	{
108 		// bit 0x80 toggles, maybe sprite buffering?
109 		// bit 0x40 is flipscreen
110 		// bit 0x20 not used?
111 		// bit 0x10 not used?
112 		// bit 0x08 is set on the title screen (sprite disable?)
113 		// bit 0x04 unused? txt disable?
114 		// bit 0x02 is used on the map screen (fore disable?)
115 		// bit 0x01 set when inserting coin.. bg disable?
116 
117 		if (data&0x1) m_back_enable = 0; else m_back_enable = 1;
118 		if (data&0x2) m_fore_enable=0; else m_fore_enable=1;
119 		if (data&0x4) m_txt_enable = 0; else m_txt_enable = 1;
120 		if (data&0x8) m_sprite_enable=0; else m_sprite_enable=1;
121 
122 		flip_screen_set(data & 0x40);
123 	}
124 }
125 
draw_sprites(bitmap_ind16 & bitmap,const rectangle & cliprect,int pri)126 void dynduke_state::draw_sprites(bitmap_ind16 &bitmap,const rectangle &cliprect,int pri)
127 {
128 	uint16_t *buffered_spriteram16 = m_spriteram->buffer();
129 	int offs,fx,fy,x,y,color,sprite;
130 
131 	if (!m_sprite_enable) return;
132 
133 	for (offs = 0x800-4;offs >= 0;offs -= 4)
134 	{
135 		/* Don't draw empty sprite table entries */
136 		if ((buffered_spriteram16[offs+3] >> 8)!=0xf) continue;
137 		if (((buffered_spriteram16[offs+2]>>13)&3)!=pri) continue;
138 
139 		fx= buffered_spriteram16[offs+0]&0x2000;
140 		fy= buffered_spriteram16[offs+0]&0x4000;
141 		y = buffered_spriteram16[offs+0] & 0xff;
142 		x = buffered_spriteram16[offs+2] & 0xff;
143 
144 		if (buffered_spriteram16[offs+2]&0x100) x=0-(0x100-x);
145 
146 		color = (buffered_spriteram16[offs+0]>>8)&0x1f;
147 		sprite = buffered_spriteram16[offs+1];
148 		sprite &= 0x3fff;
149 
150 		if (flip_screen()) {
151 			x=240-x;
152 			y=240-y;
153 			if (fx) fx=0; else fx=1;
154 			if (fy) fy=0; else fy=1;
155 		}
156 
157 		m_gfxdecode->gfx(3)->transpen(bitmap,cliprect,
158 				sprite,
159 				color,fx,fy,x,y,15);
160 	}
161 }
162 
draw_background(bitmap_ind16 & bitmap,const rectangle & cliprect,int pri)163 void dynduke_state::draw_background(bitmap_ind16 &bitmap, const rectangle &cliprect, int pri )
164 {
165 	/* The transparency / palette handling on the background layer is very strange */
166 	bitmap_ind16 &bm = m_bg_layer->pixmap();
167 	/* if we're disabled, don't draw */
168 	if (!m_back_enable)
169 	{
170 		bitmap.fill(m_palette->black_pen(), cliprect);
171 		return;
172 	}
173 
174 	int scrolly = ((m_scroll_ram[0x01]&0x30)<<4)+((m_scroll_ram[0x02]&0x7f)<<1)+((m_scroll_ram[0x02]&0x80)>>7);
175 	int scrollx = ((m_scroll_ram[0x09]&0x30)<<4)+((m_scroll_ram[0x0a]&0x7f)<<1)+((m_scroll_ram[0x0a]&0x80)>>7);
176 
177 	if (flip_screen())
178 	{
179 		scrolly = 256 - scrolly;
180 		scrollx = 256 - scrollx;
181 	}
182 
183 	for (int y=0;y<256;y++)
184 	{
185 		int realy = (y + scrolly) & 0x1ff;
186 		uint16_t const *const src = &bm.pix(realy);
187 		uint16_t *const dst = &bitmap.pix(y);
188 
189 
190 		for (int x=0;x<256;x++)
191 		{
192 			int realx = (x + scrollx) & 0x1ff;
193 			uint16_t srcdat = src[realx];
194 
195 			/* 0x01 - data bits
196 			   0x02
197 			   0x04
198 			   0x08
199 			   0x10 - extra colour bit? (first boss)
200 			   0x20 - priority over sprites
201 			   the old driver also had 'bg_palbase' but I don't see what it's for?
202 			*/
203 
204 			if ((srcdat & 0x20) == pri)
205 			{
206 				if (srcdat & 0x10) srcdat += 0x400;
207 				//if (srcdat & 0x10) srcdat += machine().rand()&0x1f;
208 
209 				srcdat = (srcdat & 0x000f) | ((srcdat & 0xffc0) >> 2);
210 				dst[x] = srcdat;
211 			}
212 
213 
214 		}
215 	}
216 }
217 
screen_update(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)218 uint32_t dynduke_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
219 {
220 	/* Setup the tilemaps */
221 	m_fg_layer->set_scrolly(0, ((m_scroll_ram[0x11]&0x30)<<4)+((m_scroll_ram[0x12]&0x7f)<<1)+((m_scroll_ram[0x12]&0x80)>>7) );
222 	m_fg_layer->set_scrollx(0, ((m_scroll_ram[0x19]&0x30)<<4)+((m_scroll_ram[0x1a]&0x7f)<<1)+((m_scroll_ram[0x1a]&0x80)>>7) );
223 	m_fg_layer->enable(m_fore_enable);
224 	m_tx_layer->enable(m_txt_enable);
225 
226 
227 	draw_background(bitmap, cliprect,0x00);
228 	draw_sprites(bitmap,cliprect,0); // Untested: does anything use it? Could be behind background
229 	draw_sprites(bitmap,cliprect,1);
230 	draw_background(bitmap, cliprect,0x20);
231 
232 	draw_sprites(bitmap,cliprect,2);
233 	m_fg_layer->draw(screen, bitmap, cliprect, 0,0);
234 	draw_sprites(bitmap,cliprect,3);
235 	m_tx_layer->draw(screen, bitmap, cliprect, 0,0);
236 
237 	return 0;
238 }
239