1 // license:BSD-3-Clause
2 // copyright-holders:David Haywood
3 /* helper functions for BFM SC4/5 set identification and layout file creation
4  - these are not strictly required by the emulation
5 
6  */
7 
8 #include "emu.h"
9 
10 //#define sc45helperlog printf
11 #define sc45helperlog machine.logerror
12 
13 // addrxor used for endianness stuff, mode used for when we have a missing pair half
find_project_string(running_machine & machine,int addrxor,int mode)14 int find_project_string(running_machine &machine, int addrxor, int mode)
15 {
16 	// search for the title
17 	const int strlength = 14;
18 	char title_string[] = "PROJECT NUMBER";
19 	uint8_t *src = machine.root_device().memregion( "maincpu" )->base();
20 	int size = machine.root_device().memregion( "maincpu" )->bytes();
21 
22 	int search_start = 0;
23 	int search_step = 1;
24 
25 	if (mode==1)
26 	{
27 		search_start = 0;
28 		search_step = 2;
29 	}
30 
31 	if (mode==2)
32 	{
33 		search_start = 1;
34 		search_step = 2;
35 	}
36 
37 	for (int i=0;i<size-strlength;i++)
38 	{
39 	//  sc45helperlog("%02x", src[i]);
40 
41 		int j;
42 		int found = 1;
43 		for (j=search_start;j<strlength;j+=search_step)
44 		{
45 			uint8_t rom = src[(i+j)^addrxor];
46 			uint8_t chr = title_string[j];
47 
48 			if (rom != chr)
49 			{
50 				found = 0;
51 				break;
52 			}
53 		}
54 
55 		if (found!=0)
56 		{
57 			int end=0;
58 			int count = 0;
59 			int blankcount = 0;
60 			sc45helperlog("ID String @ %08x\n", i);
61 
62 			if (mode==2)
63 			{
64 				count = -1;
65 			}
66 
67 			while (!end)
68 			{
69 				uint8_t rom;
70 				int addr;
71 				if (mode==0)
72 				{
73 					addr = (i+count)^addrxor;
74 					rom = src[addr];
75 				}
76 				else if (mode == 1)
77 				{
78 					addr = (i+count)^addrxor;
79 
80 					if (addr&1)
81 						rom = src[addr];
82 					else
83 						rom = '_';
84 				}
85 				else
86 				{
87 					addr = (i+count)^addrxor;
88 
89 					if (addr&1)
90 						rom = '_';
91 					else
92 						rom = src[addr];
93 				}
94 
95 
96 				//if (rom==0xff)
97 				//  end = 1;
98 				//else
99 				{
100 					if ((rom>=0x20) && (rom<0x7f))
101 					{
102 						sc45helperlog("%c", rom);
103 						blankcount = 0;
104 					}
105 					else
106 					{
107 						blankcount++;
108 						if (blankcount<10) sc45helperlog(" ");
109 					}
110 				}
111 
112 				count++;
113 
114 				if (count>=0x100)
115 					end = 1;
116 			}
117 			sc45helperlog("\n");
118 
119 			return 1;
120 		}
121 	}
122 
123 	return 0;
124 }
125 
126 // find where the button definitions are in the ROM to make creating input ports easier for games using common test mode code
127 // not ALL games have a comprehensive list, but enough do to make this a worthwile debugging aid.
128 
129 struct sc4inputinfo
130 {
131 	std::string name;
132 	bool used;
133 };
134 
135 sc4inputinfo sc4inputs[32][16];
136 
compare_input_code(running_machine & machine,int addr)137 bool compare_input_code(running_machine &machine, int addr)
138 {
139 	uint16_t *src = (uint16_t*)machine.root_device().memregion( "maincpu" )->base();
140 	uint16_t* rom = &src[addr];
141 
142 
143 	if ((rom[0] != 0x48e7) || (rom[1] != 0x3020) || (rom[2] != 0x322f) || (rom[3] != 0x0010) || (rom[4] != 0x227c))
144 		return false;
145 
146 	if ((rom[7] != 0x4242) || (rom[8] != 0x2449) || (rom[9] != 0x3639))
147 		return false;
148 
149 	return true;
150 }
151 
find_input_strings(running_machine & machine)152 int find_input_strings(running_machine &machine)
153 {
154 	for (int i = 0; i < 32; i++)
155 	{
156 		for (int j = 0; j < 16; j++)
157 		{
158 			sc4inputs[i][j].name = string_format("IN%d-%d", i, j);
159 			sc4inputs[i][j].used = false;
160 		}
161 	}
162 
163 
164 	int foundat = -1;
165 	uint32_t startblock = 0;
166 	uint32_t endblock = 0;
167 
168 	uint16_t *rom = (uint16_t*)machine.root_device().memregion( "maincpu" )->base();
169 	uint8_t *rom8 = machine.root_device().memregion( "maincpu" )->base();
170 
171 	for (int i=0;i<(0x100000-0x40)/2;i++)
172 	{
173 		bool found = compare_input_code(machine, i);
174 
175 		if (found==true)
176 		{
177 			startblock = (rom[i + 5] << 16) | rom[i + 6];
178 			endblock = (rom[i + 10] << 16) | rom[i + 11];
179 			sc45helperlog("------------ INPUTS -----------------\n");
180 			sc45helperlog("input strings found at %08x (start of ponter block %08x end of pointer block %08x\n", i*2, startblock, endblock);
181 			foundat = i;
182 
183 			if (endblock > startblock)
184 			{
185 				for (int j = startblock / 2; j < endblock / 2; j+=4)
186 				{
187 					uint16_t portpos = rom[j + 0];
188 					int port = (portpos & 0x1f);
189 					int pos = (portpos >> 5);
190 
191 					uint16_t unk2 = rom[j + 1];
192 					uint32_t stringaddr = (rom[j + 2] << 16) | rom[j + 3];
193 
194 					sc45helperlog("(port %02x position %02x) unk %04x addr %08x  ", port,pos, unk2, stringaddr);
195 					std::string tempstring;
196 
197 					for (int k = stringaddr; k < stringaddr + 6; k++)
198 					{
199 						uint8_t chr = rom8[k^1];
200 
201 						if ((chr == 0xff) || (chr == 0x00))
202 						{
203 							k = stringaddr + 6;
204 						}
205 						else
206 						{
207 							tempstring.push_back(chr);
208 						}
209 
210 					}
211 
212 					strtrimspace(tempstring);
213 					strmakelower(tempstring);
214 
215 
216 					//if (pos <= 5)
217 					{
218 						assert(pos >= 0 && pos < ARRAY_LENGTH(sc4inputs[port]));
219 						if (sc4inputs[port][pos].used == false)
220 						{
221 							sc4inputs[port][pos].used = true;
222 							sc4inputs[port][pos].name = tempstring;
223 						}
224 						else
225 						{
226 							printf("position already used?\n");
227 
228 							sc4inputs[port][pos].name.append(" OR ");
229 							sc4inputs[port][pos].name.append(tempstring);
230 						}
231 					}
232 					//else
233 					//{
234 					//  printf("invalid port position?\n");
235 					//}
236 
237 
238 
239 					sc45helperlog("%s", tempstring.c_str());
240 
241 					sc45helperlog("\n");
242 
243 				}
244 			}
245 
246 		}
247 	}
248 
249 	sc45helperlog("------------ INPUT STRUCTURE -----------------\n");
250 
251 	// i'm not sure exactly how many ports are valid for inputs, or if different
252 	// hardware can also be connected to them, buttons typically map in
253 	// ports 1,2, then jump to 8,9, and sometimes 10 (sc4dndys)
254 	// some games appear to have mistakes in their tables (sc4dndclc claims the
255 	// %age key maps over the dips?)
256 	// dips are on the motherboard and the 16 switches appear mapped at 16,17,18,19 split 5-5-5-1 (I'm assuming this can't move)
257 	// the green service mode button in port 20 is also on the motherboard (I'm assuming this can't move)
258 	//
259 	// sometimes an upper bit (0x100) is set for hopper related ports?
260 
261 	int ignoreports[32][16] =
262 	{
263 		{ -1, -1, -1, -1, -1, -1, -1, -1,    -1, -1, -1, -1, -1, -1, -1, -1, },
264 		{  1,  2,  3,  4,  5,  6, -1, -1,    -7, -1, -1, -1, -1, -1, -1, -1, }, // port 1
265 		{  7,  8,  9, 10, 11, 12, -1, -1,    -1, -1, -1, -1, -1, -1, -1, -1, }, // port 2
266 		{ -1, -1, -2, -2, -2, -1, -1, -1,    -1, -1, -1, -1, -1, -1, -1, -1, }, // many of the dutch games map inputs here instead of the stake key(!!)
267 		{ -1, -9, -1, -10,-8, -1, -1, -1,    -6, -1, -1, -1, -1, -1, -1, -1, }, // port 4
268 		{ -2, -2, -2, -2, -1, -1, -1, -1,    -1, -1, -1, -1, -1, -1, -1, -1, },
269 		{ -2, -2, -2, -2, -1, -1, -1, -1,    -1, -1, -1, -1, -1, -1, -1, -1, },
270 		{ 31, 32, 33, 34, 35, 36, -1, -1,    -1, -1, -1, -1, -1, -1, -1, -1, }, // port 7 (sc4cfqpse?)
271 		{ 13, 14, 15, 16, 17, 18, -1, -1,    -1, -1, -1, -1, -1, -1, -1, -1, }, // port 8
272 		{ 19, 20, 21, 22, 23, 24, -1, -1,    -1, -1, -1, -1, -1, -1, -1, -1, }, // port 9
273 		{ 25, 26, 27, 28, 29, 30, -1, -1,    -1, -1, -1, -1, -1, -1, -1, -1, }, // port 10
274 		{ -1, -1, -1, -1, -1, -1, -1, -1,    -1, -1, -1, -1, -1, -1, -1, -1, },
275 		{ -1, -1, -1, -1, -1, -1, -1, -1,    -1, -1, -1, -1, -1, -1, -1, -1, },
276 		{ -1, -1, -1, -1, -1, -1, -1, -1,    -1, -1, -1, -1, -1, -1, -1, -1, },
277 		{ -1, -1, -1, -1, -1, -1, -1, -1,    -1, -1, -1, -1, -1, -1, -1, -1, },
278 		{ -1, -1, -1, -1, -1, -1, -1, -1,    -1, -1, -1, -1, -1, -1, -1, -1, },
279 		{ -3, -3, -3, -3, -3, -1, -1, -1,    -5, -1, -1, -1, -1, -1, -1, -1, }, // port 16
280 		{ -3, -3, -3, -3, -3, -1, -1, -1,    -1, -1, -1, -1, -1, -1, -1, -1, }, // port 17
281 		{ -3, -3, -3, -3, -3, -1, -1, -1,    -1, -1, -1, -1, -1, -1, -1, -1, }, // port 18
282 		{ -3, -1, -1, -1, -1, -1, -1, -1,    -1, -1, -1, -1, -1, -1, -1, -1, }, // port 19
283 		{ -3, -2, -2, -2, -2, -1, -1, -1,    -1, -1, -1, -1, -1, -1, -1, -1, }, // port 20
284 		{ -1, -1, -1, -1, -1, -1, -1, -1,    -1, -1, -1, -1, -1, -1, -1, -1, },
285 		{ -1, -1, -1, -1, -1, -1, -1, -1,    -1, -1, -1, -1, -1, -1, -1, -1, },
286 		{ -1, -1, -1, -1, -1, -1, -1, -1,    -1, -1, -1, -1, -1, -1, -1, -1, },
287 		{ -1, -1, -1, -1, -1, -1, -1, -1,    -1, -1, -1, -1, -1, -1, -1, -1, },
288 		{ -1, -1, -1, -1, -1, -1, -1, -1,    -1, -1, -1, -1, -1, -1, -1, -1, },
289 		{ -1, -1, -1, -1, -1, -1, -1, -1,    -1, -1, -1, -1, -1, -1, -1, -1, },
290 		{ -1, -1, -1, -1, -1, -1, -1, -1,    -1, -1, -1, -1, -1, -1, -1, -1, },
291 		{ -1, -1, -1, -1, -1, -1, -1, -1,    -1, -1, -1, -1, -1, -1, -1, -1, },
292 		{ -1, -1, -1, -1, -1, -1, -1, -1,    -1, -1, -1, -1, -1, -1, -1, -1, },
293 		{ -1, -1, -1, -1, -1, -1, -1, -1,    -1, -1, -1, -1, -1, -1, -1, -1, },
294 		{ -1, -1, -1, -1, -1, -1, -1, -1,    -1, -1, -1, -1, -1, -1, -1, -1, }
295 	};
296 
297 	int buttons_used = 1;
298 
299 	printf("INPUT_PORTS_START( %s ) // this structure is generated\n", machine.system().name);
300 	printf("    PORT_INCLUDE( sc4_base )\n");
301 
302 	for (int i = 0; i < 32; i++)
303 	{
304 		int thisportused = 0;
305 
306 		for (int j = 0; j < 16; j++)
307 		{
308 			if (sc4inputs[i][j].used == true)
309 			{
310 				if (thisportused == 0)
311 				{
312 					printf("    PORT_MODIFY(\"IN-%d\")\n", i);
313 					thisportused = 1;
314 				}
315 
316 				if (ignoreports[i][j] > 0)
317 				{
318 					printf("    PORT_BIT( 0x%04x, IP_ACTIVE_HIGH, SC45_BUTTON_MATRIX_%d_%d ) PORT_NAME(\"%s\")\n", 1 << j, i,j/*ignoreports[i][j]*/, sc4inputs[i][j].name.c_str());
319 					buttons_used++;
320 				}
321 				else if (ignoreports[i][j] == -3)
322 				{
323 					printf("    // 0x%04x - \"%s\" // standard input (motherboard)\n", 1 << j, sc4inputs[i][j].name.c_str());
324 				}
325 				else if (ignoreports[i][j] == -2)
326 				{
327 					printf("    // 0x%04x - \"%s\" // standard input (expected here)\n", 1 << j, sc4inputs[i][j].name.c_str());
328 				}
329 				else if (ignoreports[i][j] == -1)
330 				{
331 					printf("    // 0x%04x - \"%s\" // unexpected here\n", 1 << j, sc4inputs[i][j].name.c_str());
332 				}
333 				else if (ignoreports[i][j] == -4)
334 				{
335 					printf("    // 0x%04x - \"%s\" // known extended input, mapping not understood\n", 1 << j, sc4inputs[i][j].name.c_str());
336 				}
337 				else if (ignoreports[i][j] == -5)
338 				{
339 					printf("    // 0x%04x - \"%s\" // known extended input, usually 'top up'\n", 1 << j, sc4inputs[i][j].name.c_str());
340 				}
341 				else if (ignoreports[i][j] == -6)
342 				{
343 					printf("    // 0x%04x - \"%s\" // known extended input, usually 'hopper low'\n", 1 << j, sc4inputs[i][j].name.c_str());
344 				}
345 				else if (ignoreports[i][j] == -7)
346 				{
347 					printf("    // 0x%04x - \"%s\" // known extended input, usually 'hopper fit'\n", 1 << j, sc4inputs[i][j].name.c_str());
348 				}
349 				else if (ignoreports[i][j] == -8)
350 				{
351 					printf("    // 0x%04x - \"%s\" // known extended(?) input, sometimes 'top up'\n", 1 << j, sc4inputs[i][j].name.c_str());
352 				}
353 				else if (ignoreports[i][j] == -9)
354 				{
355 					printf("    // 0x%04x - \"%s\" // known extended(?) input, sometimes 'hop hi'\n", 1 << j, sc4inputs[i][j].name.c_str());
356 				}
357 				else if (ignoreports[i][j] == -10)
358 				{
359 					printf("    // 0x%04x - \"%s\" // known extended(?) input, sometimes 'hop top'\n", 1 << j, sc4inputs[i][j].name.c_str());
360 				}
361 				buttons_used++;
362 			}
363 		}
364 	}
365 
366 	printf("INPUT_PORTS_END\n");
367 
368 	return foundat;
369 }
370 
371 struct lampinfo
372 {
373 	std::string lampname;
374 	std::string lampname_alt;
375 	bool used;
376 	int x, y;
377 	int width, height;
378 	bool draw_label;
379 	std::string lamptypename;
380 	int clickport;
381 	int clickmask;
382 };
383 
384 lampinfo lamps[16][16];
385 
set_clickable_temp(running_machine & machine,const std::string & teststring,int clickport,int clickmask)386 void set_clickable_temp(running_machine &machine, const std::string &teststring, int clickport, int clickmask)
387 {
388 	for (auto & lamp : lamps)
389 	{
390 		for (int x = 0; x < 16; x++)
391 		{
392 			if (!strcmp(teststring.c_str(), lamp[x].lampname_alt.c_str()))
393 			{
394 				lamp[x].clickport = clickport;
395 				lamp[x].clickmask = clickmask;
396 
397 				lamp[x].lamptypename = "buttonlamp";
398 			}
399 
400 		}
401 	}
402 }
403 
find_lamp_strings(running_machine & machine)404 int find_lamp_strings(running_machine &machine)
405 {
406 	int startblock = -1;
407 	int endblock = -1;
408 
409 
410 	if (!strcmp(machine.system().name, "sc4dnd"))
411 	{
412 		// these are for sc4dnd ONLY, need to work out how the code calculates them
413 		startblock = 0x1cac0;
414 		endblock =   0x1cf9a;
415 	}
416 	else if (!strcmp(machine.system().name, "sc4dndtp"))
417 	{
418 		startblock = 0x2175c;
419 		endblock = 0x21cb4;
420 	}
421 	else if (!strcmp(machine.system().name, "sc4dnddw"))
422 	{
423 		startblock = 0x18a8e;
424 		endblock = 0x18fc2;
425 	}
426 
427 	if (startblock == -1)
428 		return 0;
429 
430 
431 
432 	for (int y = 0; y < 16; y++)
433 	{
434 		for (int x = 0; x < 16; x++)
435 		{
436 			char tmp[32];
437 
438 			sprintf(tmp, "(%02d:%02d)", y, x);
439 
440 			lamps[y][x].lampname = std::string(tmp);
441 			lamps[y][x].used = false;
442 			lamps[y][x].y = (y * 28);
443 			lamps[y][x].x = 380 + (x * 24);
444 			lamps[y][x].draw_label = true;
445 			lamps[y][x].width = 23;
446 			lamps[y][x].height = 16;
447 			lamps[y][x].lamptypename = "unusedlamp";
448 			lamps[y][x].clickport = -1;
449 			lamps[y][x].clickmask = 0;
450 
451 		}
452 	}
453 
454 
455 
456 
457 
458 
459 
460 
461 	uint16_t *rom = (uint16_t*)machine.root_device().memregion( "maincpu" )->base();
462 	uint8_t *rom8 = machine.root_device().memregion( "maincpu" )->base();
463 
464 //  sc45helperlog("------------ LAMPS -----------------\n");
465 
466 	if (endblock > startblock)
467 	{
468 		for (int j = startblock / 2; j < endblock / 2; j+=3)
469 		{
470 			uint16_t portpos = rom[j + 0];
471 			int row = portpos & 0xf;
472 			int col = (portpos >> 4 ) & 0xf;
473 
474 			uint32_t stringaddr = (rom[j + 1] << 16) | rom[j + 2];
475 
476 			//sc45helperlog("(row %02d, col %02d, unused %02x) addr %08x  ", row,col, (portpos&0xff00)>>8, stringaddr);
477 
478 			std::string tempstring;
479 
480 			for (int k = stringaddr; k < stringaddr + 10; k++)
481 			{
482 				uint8_t chr = rom8[k^1];
483 
484 				if ((chr == 0xff) || (chr == 0x00))
485 				{
486 					k = stringaddr + 10;
487 				}
488 				else
489 				{
490 					tempstring.push_back(chr);
491 				}
492 
493 			}
494 
495 			if (lamps[row][col].used == false)
496 			{
497 				lamps[row][col].used = true;
498 				lamps[row][col].lampname = tempstring;
499 				lamps[row][col].lamptypename = "matrixlamp";
500 
501 				strtrimspace(lamps[row][col].lampname);
502 				strmakelower(lamps[row][col].lampname);
503 			}
504 			else
505 			{
506 				fatalerror("duplicate lamp?\n");
507 			}
508 
509 			//sc45helperlog("%s", tempstring.c_str());
510 
511 			//sc45helperlog("\n");
512 
513 		}
514 	}
515 
516 	// layout elements for each of the text labels
517 	int d = 0;
518 	for (auto & lamp : lamps)
519 	{
520 		//sc45helperlog("---ROW %02d---\n", y);
521 		for (int x = 0; x < 16; x++)
522 		{
523 			sc45helperlog("<element name=\"lamplabelel%d\"><text string=\"%s\"><color red=\"1.0\" green=\"1.0\" blue=\"1.0\" /></text></element>\n", d, lamp[x].lampname.c_str());
524 			d++;
525 		}
526 	}
527 
528 	sc45helperlog("\n\n");
529 	// print out some input text labels for specific rows
530 	d = 0;
531 	for (int y = 0; y < 7; y++)
532 	{
533 		int actualrows[] = { 1, 2, 7, 8, 9, 10, 20 };
534 		int realy = actualrows[y];
535 
536 		for (int x = 0; x < 6; x++)
537 		{
538 			sc45helperlog("<element name=\"inputlabel%d-%d\"><text string=\"%s\"><color red=\"1.0\" green=\"1.0\" blue=\"1.0\" /></text></element>\n", realy,x,sc4inputs[realy][x].name.c_str());
539 
540 		}
541 	}
542 	sc45helperlog("\n");
543 
544 
545 
546 
547 	// some stuff needed by the matrix layout
548 	sc45helperlog("<element name=\"matrixlamp\">\n");
549 	sc45helperlog("<rect state =\"0\"><bounds x=\"0\" y=\"0\" width=\"7\" height=\"7\" /><color red=\"0.7\" green=\"0.7\" blue=\"0.7\" /></rect>\n");
550 	sc45helperlog("<rect state =\"1\"><bounds x=\"0\" y=\"0\" width=\"7\" height=\"7\" /><color red=\"0.0\" green=\"0.0\" blue=\"1.0\" /></rect>\n");
551 	sc45helperlog("<rect state =\"2\"><bounds x=\"0\" y=\"0\" width=\"7\" height=\"7\" /><color red=\"0.0\" green=\"1.0\" blue=\"0.0\" /></rect>\n");
552 	sc45helperlog("</element>\n");
553 	sc45helperlog("<element name=\"unusedlamp\">\n");
554 	sc45helperlog("<rect state =\"0\"><bounds x=\"0\" y=\"0\" width=\"7\" height=\"7\" /><color red=\"0.2\" green=\"0.2\" blue=\"0.2\" /></rect>\n");
555 	sc45helperlog("<rect state =\"1\"><bounds x=\"0\" y=\"0\" width=\"7\" height=\"7\" /><color red=\"0.0\" green=\"0.0\" blue=\"0.5\" /></rect>\n");
556 	sc45helperlog("<rect state =\"2\"><bounds x=\"0\" y=\"0\" width=\"7\" height=\"7\" /><color red=\"0.0\" green=\"0.5\" blue=\"0.0\" /></rect>\n");
557 	sc45helperlog("</element>\n");
558 	sc45helperlog("<element name=\"reellamp\">\n");
559 	sc45helperlog("<rect state =\"0\"><bounds x=\"0\" y=\"0\" width=\"7\" height=\"7\" /><color red=\"0.1\" green=\"0.1\" blue=\"0.1\" /></rect>\n");
560 	sc45helperlog("<rect state =\"1\"><bounds x=\"0\" y=\"0\" width=\"7\" height=\"7\" /><color red=\"0.6\" green=\"0.6\" blue=\"0.6\" /></rect>\n");
561 	sc45helperlog("<rect state =\"2\"><bounds x=\"0\" y=\"0\" width=\"7\" height=\"7\" /><color red=\"0.6\" green=\"0.6\" blue=\"0.6\" /></rect>\n");
562 	sc45helperlog("</element>\n");
563 	sc45helperlog("<element name=\"buttonlamp\">\n");
564 	sc45helperlog("<rect state =\"0\"><bounds x=\"0\" y=\"0\" width=\"7\" height=\"7\" /><color red=\"0.6\" green=\"0.7\" blue=\"0.6\" /></rect>\n");
565 	sc45helperlog("<rect state =\"1\"><bounds x=\"0\" y=\"0\" width=\"7\" height=\"7\" /><color red=\"0.0\" green=\"1.0\" blue=\"0.0\" /></rect>\n");
566 	sc45helperlog("<rect state =\"2\"><bounds x=\"0\" y=\"0\" width=\"7\" height=\"7\" /><color red=\"0.0\" green=\"0.0\" blue=\"1.0\" /></rect>\n");
567 	sc45helperlog("</element>\n");
568 	sc45helperlog("<element name=\"button\">\n");
569 	sc45helperlog("<rect state =\"0\"><bounds x=\"0\" y=\"0\" width=\"7\" height=\"7\" /><color red=\"0.2\" green=\"0.8\" blue=\"0.2\" /></rect>\n");
570 	sc45helperlog("<rect state =\"1\"><bounds x=\"0\" y=\"0\" width=\"7\" height=\"7\" /><color red=\"0.2\" green=\"0.9\" blue=\"0.2\" /></rect>\n");
571 	sc45helperlog("<rect state =\"2\"><bounds x=\"0\" y=\"0\" width=\"7\" height=\"7\" /><color red=\"0.2\" green=\"1.0\" blue=\"0.2\" /></rect>\n");
572 	sc45helperlog("</element>\n");
573 	sc45helperlog("<element name=\"vfd0\">\n");
574 	sc45helperlog("<led14segsc><color red=\"0\" green=\"0.6\" blue=\"1.0\" /></led14segsc>\n");
575 	sc45helperlog("</element>\n");
576 	sc45helperlog("<element name=\"digit\" defstate=\"10\">\n");
577 	sc45helperlog("<led7seg><color red=\"1.0\" green=\"0.3\" blue=\"0.0\" /></led7seg>\n");
578 	sc45helperlog("</element>\n");
579 	sc45helperlog("<element name=\"Steppers\" defstate=\"0\">\n");
580 	sc45helperlog("<simplecounter maxstate=\"999\" digits=\"3\"><color red=\"1.0\" green=\"1.0\" blue=\"1.0\" /><bounds x=\"0\" y=\"0\" width=\"1\" height=\"1\" /></simplecounter>\n");
581 	sc45helperlog("</element>\n");
582 	sc45helperlog("\n\n");
583 
584 
585 	sc45helperlog("<view name=\"AWP Simulated Video (No Artwork)\">\n");
586 
587 	// copy the button strings so we can modify some for easier comparisons
588 	d = 0;
589 	for (auto & lamp : lamps)
590 	{
591 		for (int x = 0; x < 16; x++)
592 		{
593 			lamp[x].lampname_alt = lamp[x].lampname;
594 
595 			if (!strcmp(lamp[x].lampname_alt.c_str(), "hold2/hi")) lamp[x].lampname_alt = "hold2";
596 			if (!strcmp(lamp[x].lampname_alt.c_str(), "hold3/lo")) lamp[x].lampname_alt = "hold3";
597 			if (!strcmp(lamp[x].lampname_alt.c_str(), "chg stake")) lamp[x].lampname_alt = "chnge stk";
598 			if (!strcmp(lamp[x].lampname_alt.c_str(), "canc/coll")) lamp[x].lampname_alt = "cancel";
599 			if (!strcmp(lamp[x].lampname_alt.c_str(), "start")) lamp[x].lampname_alt = "strt exch";
600 
601 		}
602 	}
603 
604 
605 	// try to find some specific named elements and move them around
606 	d = 0;
607 
608 	for (int reel = 0; reel < 8; reel++)
609 	{
610 		char tempname[32];
611 		sprintf(tempname, "reel%d ", reel+1);
612 
613 
614 		for (int pos = 0; pos < 3; pos++)
615 		{
616 			char tempname2[64];
617 
618 			if (pos == 0) snprintf(tempname2, ARRAY_LENGTH(tempname2), "%stop", tempname);
619 			if (pos == 1) snprintf(tempname2, ARRAY_LENGTH(tempname2), "%smid", tempname);
620 			if (pos == 2) snprintf(tempname2, ARRAY_LENGTH(tempname2), "%sbot", tempname);
621 
622 
623 			for (auto & lamp : lamps)
624 			{
625 				for (int x = 0; x < 16; x++)
626 				{
627 					if (!strcmp(tempname2, lamp[x].lampname_alt.c_str()))
628 					{
629 						//sc45helperlog("%s found\n", tempname2);
630 						lamp[x].draw_label = false;
631 
632 						lamp[x].x = 0 + (50 * reel);
633 						lamp[x].y = 300 + (17 * pos);
634 						lamp[x].width = 50;
635 						lamp[x].height = 17;
636 						lamp[x].lamptypename = "reellamp";
637 
638 
639 					}
640 					else
641 					{
642 						//printf("%s:%s:\n", tempname2, lamps[y][x].lampname_alt.c_str());
643 					}
644 
645 				}
646 			}
647 		}
648 	}
649 
650 	// todo, find these by cross-referencing button names and lamp names instead
651 	{
652 		set_clickable_temp(machine, "cancel",    1, 0x01);
653 		set_clickable_temp(machine, "hold1",     1, 0x02);
654 		set_clickable_temp(machine, "hold2",     1, 0x04);
655 		set_clickable_temp(machine, "hold3",     1, 0x08);
656 		set_clickable_temp(machine, "hold4",     1, 0x10);
657 
658 		set_clickable_temp(machine, "chnge stk", 2, 0x01);
659 		set_clickable_temp(machine, "collect",   2, 0x02);
660 		set_clickable_temp(machine, "transfer",  2, 0x04);
661 
662 		set_clickable_temp(machine, "strt exch", 2, 0x10);
663 
664 		set_clickable_temp(machine, "nodeal",   8, 0x01);
665 		set_clickable_temp(machine, "deal",      8, 0x02);
666 		set_clickable_temp(machine, "cash bust", 8, 0x04);
667 
668 		// no 'refill' lamp?
669 
670 
671 	}
672 
673 
674 	// dump out basic matrix stuff in layout format
675 	d = 0;
676 	for (auto & lamp : lamps)
677 	{
678 		//sc45helperlog("---ROW %02d---\n", y);
679 		for (int x = 0; x < 16; x++)
680 		{
681 			if (lamp[x].clickport== -1) sc45helperlog("<bezel name=\"lamp%d\" element=\"%s\" state=\"0\"><bounds x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\"/></bezel>\n", d, lamp[x].lamptypename.c_str(), lamp[x].x, lamp[x].y, lamp[x].width, lamp[x].height);
682 			else sc45helperlog("<bezel name=\"lamp%d\" element=\"%s\" state=\"0\" inputtag=\"IN-%d\" inputmask=\"0x%02x\"><bounds x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" /></bezel>\n", d, lamp[x].lamptypename.c_str(), lamp[x].clickport, lamp[x].clickmask, lamp[x].x, lamp[x].y, lamp[x].width, lamp[x].height);
683 
684 			if (lamp[x].draw_label == false) sc45helperlog("<!-- Label not drawn\n");
685 			sc45helperlog("<bezel name=\"lamplabel%d\" element=\"lamplabelel%d\"><bounds x=\"%d\" y=\"%d\" width=\"%d\" height=\"10\" /></bezel>\n", d,d, lamp[x].x, lamp[x].y-10, lamp[x].width);
686 			if (lamp[x].draw_label == false) sc45helperlog("-->\n");
687 
688 			d++;
689 		}
690 	}
691 
692 	// print out a simple matrix of some of the most common inputs,
693 	d = 0;
694 	for (int y = 0; y < 7; y++)
695 	{
696 		int actualrows[] = { 1, 2, 7, 8, 9, 10, 20 };
697 		int realy = actualrows[y];
698 
699 		for (int x = 0; x < 6; x++)
700 		{
701 			sc45helperlog("<bezel name=\"input%d-%d\" element=\"button\" state=\"0\" inputtag=\"IN-%d\" inputmask=\"0x%02x\"><bounds x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" /></bezel>\n", realy,x, realy, 1<<x, 180+x*20, 0+y*20, 19, 10);
702 
703 			sc45helperlog("<bezel name=\"inputlab%d-%d\" element=\"inputlabel%d-%d\"><bounds x=\"%d\" y=\"%d\" width=\"%d\" height=\"10\" /></bezel>\n", realy,x,realy,x, 180+x*20,  0+(y*20)-10, 19);
704 
705 			d++;
706 		}
707 	}
708 
709 	sc45helperlog("\n");
710 
711 	// other layout debug stuff
712 	d = 0;
713 	int extrax = 0;
714 	for (int x = 0; x < 32; x++)
715 	{
716 		if (x % 5 == 0) extrax += 4;
717 
718 		for (int y = 0; y < 8; y++)
719 		{
720 			sc45helperlog("<bezel name=\"matrix%d\" element=\"matrixlamp\" state=\"0\"><bounds x=\"%d\" y=\"%d\" width=\"3\" height=\"3\" /></bezel>\n", d, (x*4)+extrax, 40+y*4);
721 			d++;
722 		}
723 	}
724 
725 	sc45helperlog("\n");
726 
727 	d = 0;
728 	for (int x = 0; x < 16; x++)
729 	{
730 		for (int y = 0; y < 2; y++)
731 		{
732 			sc45helperlog("<bezel name=\"digit%d\" element=\"digit\" state=\"0\"><bounds x=\"%d\" y=\"%d\" width=\"9\" height=\"19\"/></bezel>\n", d, (15*10)- (x * 10), 80+(y * 20));
733 			d++;
734 		}
735 	}
736 
737 	sc45helperlog("\n");
738 
739 	d = 0;
740 	for (int x = 0; x < 16; x++)
741 	{
742 		int y = 10;
743 
744 		sc45helperlog("<bezel name=\"vfd%d\" element=\"vfd0\" state=\"0\"><bounds x=\"%d\" y=\"%d\" width=\"9\" height=\"17\"/></bezel>\n", d, 0 + (x * 10), y);
745 		d++;
746 	}
747 
748 	{
749 		// write reel stuff to layouts
750 		// sc4dnd specific..
751 		int num_normal_reels = 4;
752 		int num_special_reels = 2;
753 		int current_reel = 0;
754 
755 		for (int i = 0; i < num_normal_reels + num_special_reels; i++)
756 		{
757 			int x = i * 50;
758 			int y = 300;
759 			sc45helperlog("<bezel name=\"reel%d\" element=\"Steppers\" state=\"0\"><bounds x=\"%d\" y=\"%d\" width=\"10\" height=\"5\" /></bezel>\n", current_reel+1, x+40, y+50);
760 			sc45helperlog("<bezel name=\"sreel%d\" element=\"SteppersReel%d\" state=\"0\"><bounds x=\"%d\" y=\"%d\" width=\"50\" height=\"50\" /></bezel>\n",  current_reel+1, current_reel+1, x, y);
761 
762 			current_reel++;
763 
764 		}
765 
766 
767 	}
768 
769 
770 
771 	sc45helperlog("</view>\n");
772 	sc45helperlog("</mamelayout>\n");
773 
774 
775 	return 0;
776 }
777 
778 
find_reel_strings(running_machine & machine)779 int find_reel_strings(running_machine &machine)
780 {
781 	int startblock = -1;
782 	int endblock = -1;
783 
784 	std::vector<int> reelsizes;
785 
786 	// these are for sc4dnd ONLY, need to work out how the code calculates them
787 
788 	// this list is 4 * 16 symbols for the regular reels, 12 symbols for the number spin, and 2 groups of 16 depending on jackpot/stake keys used for the prize reel
789 	// code that points at these is likely to be complex because it's conditional on the game code / mode..
790 	if (!strcmp(machine.system().name, "sc4dnd"))
791 	{
792 		reelsizes.push_back(16);
793 		reelsizes.push_back(16);
794 		reelsizes.push_back(16);
795 		reelsizes.push_back(16);
796 		reelsizes.push_back(12);
797 		reelsizes.push_back(16);
798 		reelsizes.push_back(16);
799 
800 		startblock = 0x8d74c;
801 	}
802 	else if (!strcmp(machine.system().name, "sc4dndtp"))
803 	{
804 		reelsizes.push_back(16);
805 		reelsizes.push_back(16);
806 		reelsizes.push_back(16);
807 		reelsizes.push_back(12);
808 		reelsizes.push_back(16);
809 		reelsizes.push_back(16);
810 		reelsizes.push_back(16);
811 
812 		startblock = 0x9d252;
813 	}
814 	else if (!strcmp(machine.system().name, "sc4dnddw"))
815 	{
816 		reelsizes.push_back(16);
817 		reelsizes.push_back(16);
818 		reelsizes.push_back(16);
819 		reelsizes.push_back(12);
820 		reelsizes.push_back(20);
821 		reelsizes.push_back(20);
822 		reelsizes.push_back(20);
823 
824 		startblock = 0x9b8c8;
825 	}
826 
827 
828 	int total_reel_symbols = 0;
829 
830 	for (auto & reelsize : reelsizes)
831 	{
832 		total_reel_symbols += reelsize;
833 	}
834 
835 	endblock =   startblock + 4 * (total_reel_symbols);
836 
837 
838 
839 	if (startblock == -1)
840 		return 0;
841 
842 
843 
844 
845 
846 	uint16_t *rom = (uint16_t*)machine.root_device().memregion( "maincpu" )->base();
847 	uint8_t *rom8 = machine.root_device().memregion( "maincpu" )->base();
848 
849 
850 
851 	sc45helperlog("------------ LAYOUT -----------------\n");
852 
853 	sc45helperlog("<?xml version=\"1.0\"?>\n");
854 	sc45helperlog("<mamelayout version=\"2\">\n");
855 
856 	if (endblock > startblock)
857 	{
858 		int which_reel = 0;
859 		int current_symbols = 0;
860 
861 
862 
863 		for (int j = startblock / 2; j < endblock / 2; j+=2)
864 		{
865 			if (current_symbols == 0)
866 			{
867 				int shifted = ((0x10000 / 16) * 11 ) + 692;
868 			//  sc45helperlog("REEL %d\n", which_reel+1);
869 				sc45helperlog("<element name=\"SteppersReel%d\" defstate=\"0\">\n", which_reel+1);
870 				sc45helperlog("<reel stateoffset=\"%d\" symbollist=\"", shifted);
871 			}
872 
873 			uint32_t stringaddr = (rom[j + 0] << 16) | rom[j + 1];
874 			stringaddr &= 0xfffff;
875 
876 			if (stringaddr >= (0x10000 - 16))
877 				continue;
878 
879 			//sc45helperlog("addr %08x  ", stringaddr);
880 
881 			std::string tempstring;
882 
883 			for (int k = stringaddr; k < stringaddr + 10; k++)
884 			{
885 				uint8_t chr = rom8[k^1];
886 
887 				if ((chr == 0xff) || (chr == 0x00))
888 				{
889 					k = stringaddr + 10;
890 				}
891 				else
892 				{
893 					tempstring.push_back(chr);
894 				}
895 
896 			}
897 
898 			strtrimspace(tempstring);
899 			strmakelower(tempstring);
900 
901 			if (tempstring[0] == '!')
902 			{
903 				strdelchr(tempstring,'!');
904 				tempstring.append("PND");
905 			}
906 
907 			sc45helperlog("%s", tempstring.c_str());
908 
909 
910 
911 			//sc45helperlog("\n");
912 
913 			current_symbols++;
914 			if (current_symbols == reelsizes[which_reel])
915 			{
916 				sc45helperlog("\"><color red=\"1.0\" green=\"1.0\" blue=\"1.0\" /><bounds x=\"0\" y=\"0\" width=\"1\" height=\"1\" /></reel>\n");
917 				sc45helperlog("</element>\n");
918 
919 				current_symbols = 0;
920 				which_reel++;
921 			}
922 			else
923 			{
924 				sc45helperlog(",");
925 			}
926 
927 
928 		}
929 	}
930 
931 	return 0;
932 }
933 
934 
bfm_sc45_layout_helper(running_machine & machine)935 void bfm_sc45_layout_helper(running_machine &machine)
936 {
937 	find_input_strings(machine);
938 	find_reel_strings(machine);
939 	find_lamp_strings(machine);
940 }
941