changeset 1146:3e24de8d8073

Add support for SMS controllers
author Michael Pavone <pavone@retrodev.com>
date Tue, 03 Jan 2017 21:18:52 -0800
parents 494234e7e88f
children 06468b25a543
files analyze_olp.py io.c io.h
diffstat 3 files changed, 80 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/analyze_olp.py	Tue Jan 03 21:18:42 2017 -0800
+++ b/analyze_olp.py	Tue Jan 03 21:18:52 2017 -0800
@@ -18,6 +18,16 @@
 def detect_low(sample, bit):
 	mask = 1 << bit
 	return not sample & mask
+	
+def get_value(sample, bits):
+	value = 0
+	for i in xrange(0, len(bits)):
+		bit = bits[i]
+		value |= (sample >> bit & 1) << i
+	return value
+	
+def swizzle_mode4(row, col):
+	return (col & 1) | (row << 1) | (col << 8 & 0xFE00)
 
 def analyze_delays(chanmap, datafile):
 	if 'M68K_CLK' in chanmap:
@@ -83,7 +93,61 @@
 						print 'RAM refresh at', clks, 'delta since last:', clks-prevRefresh
 					prevRefresh = clks
 			last = sample
-				
+			
+			
+table_start = 0x3800
+table_end = table_start + 0x600
+sat_start = 0x3F00 #0x3E00
+sat_xname = sat_start + 0x80
+sat_end = sat_start + 0x100
+
+
+def analyze_vram(chanmap, datafile):
+	address_bits = [chanmap['AD{0}'.format(i)] for i in xrange(0, 8)]
+	ras = chanmap['!RAS']
+	cas = chanmap['!CAS']
+	hsync = chanmap['!HSYNC']
+	state = 'begin'
+	last = False
+	for line in datafile.readlines():
+		line = line.strip()
+		if line and not line.startswith(';'):
+			sample,_,num = line.partition('@')
+			sample = int(sample, 16)
+			if not (last is False):
+				if detect_fall(last, sample, hsync):
+					print 'HSYNC low @ {0}'.format(num)
+				elif detect_rise(last, sample, hsync):
+					print 'HSYNC high @ {0}'.format(num)
+				if state == 'begin':
+					if detect_fall(last, sample, ras):
+						state = 'ras'
+						row = get_value(sample, address_bits)
+					elif detect_fall(last, sample, cas):
+						state = 'cas'
+				elif state == 'ras':
+					if detect_fall(last, sample, cas):
+						col = get_value(sample, address_bits)
+						address = swizzle_mode4(row, col)
+						
+						if address < table_end and address >= table_start:
+							offset = (address - table_start)/2
+							desc = 'Map Row {0} Col {1}'.format(offset / 32, offset & 31)
+						elif address >= sat_start and address < sat_xname:
+							offset = address - sat_start
+							desc = 'Sprite {0} Y Read'.format(offset)
+						elif address >= sat_xname and address < sat_end:
+							offset = address - sat_xname
+							desc = 'Sprite {0} X/Name Read'.format(offset / 2)
+						else:
+							desc = 'Tile {0} Row {1}'.format(address / 32, ((address / 4) & 7) + (0.5 if address & 2 else 0))
+						print '{0:02X}:{1:02X} - {2:04X} @ {3} - {4}'.format(row, col, address, num, desc)
+						state = 'begin'
+				elif state == 'cas':
+					if detect_fall(last, sample, ras):
+						print 'refresh @ {0}'.format(num)
+						state = 'begin'
+			last = sample
 
 def main(args):
 	if len(args) < 2:
@@ -98,7 +162,8 @@
 	for i in xrange(0, len(channels)):
 		chanmap[channels[i]] = i
 	datafile = olpfile.open('data.ols')
-	analyze_delays(chanmap, datafile)
+	#analyze_delays(chanmap, datafile)
+	analyze_vram(chanmap, datafile)
 	datafile.close()
 	#datafile = olpfile.open('data.ols')
 	#analyze_refresh(chanmap, datafile)
--- a/io.c	Tue Jan 03 21:18:42 2017 -0800
+++ b/io.c	Tue Jan 03 21:18:52 2017 -0800
@@ -25,6 +25,7 @@
 #define MIN_POLL_INTERVAL 6840
 
 const char * device_type_names[] = {
+	"SMS gamepad",
 	"3-button gamepad",
 	"6-button gamepad",
 	"Mega Mouse",
@@ -653,15 +654,15 @@
 	if (!strncmp(device_type, "gamepad", gamepad_len))
 	{
 		if (
-			(device_type[gamepad_len] != '3' && device_type[gamepad_len] != '6')
+			(device_type[gamepad_len] != '3' && device_type[gamepad_len] != '6' && device_type[gamepad_len] != '2')
 			|| device_type[gamepad_len+1] != '.' || device_type[gamepad_len+2] < '1'
 			|| device_type[gamepad_len+2] > '8' || device_type[gamepad_len+3] != 0
-		)
-		{
+		) {
 			warning("%s is not a valid gamepad type\n", device_type);
-		} else if (device_type[gamepad_len] == '3')
-		{
+		} else if (device_type[gamepad_len] == '3') {
 			port->device_type = IO_GAMEPAD3;
+		} else if (device_type[gamepad_len] == '2') {
+			port->device_type = IO_GAMEPAD2;
 		} else {
 			port->device_type = IO_GAMEPAD6;
 		}
@@ -803,7 +804,7 @@
 			}
 		} else
 #endif
-		if (ports[i].device_type == IO_GAMEPAD3 || ports[i].device_type == IO_GAMEPAD6) {
+		if (ports[i].device_type == IO_GAMEPAD3 || ports[i].device_type == IO_GAMEPAD6 || ports[i].device_type == IO_GAMEPAD2) {
 			printf("IO port %s connected to gamepad #%d with type '%s'\n", io_name(i), ports[i].device.pad.gamepad_num + 1, device_type_names[ports[i].device_type]);
 		} else {
 			printf("IO port %s connected to device '%s'\n", io_name(i), device_type_names[ports[i].device_type]);
@@ -821,7 +822,8 @@
 			for (int j = 0; j < 3; j++)
 			{
 				if ((ports[j].device_type == IO_GAMEPAD3
-					 || ports[j].device_type ==IO_GAMEPAD6)
+					 || ports[j].device_type == IO_GAMEPAD6
+					 || ports[j].device_type == IO_GAMEPAD2)
 					 && ports[j].device.pad.gamepad_num == num
 				)
 				{
@@ -1364,6 +1366,9 @@
 	}
 	switch (port->device_type)
 	{
+	case IO_GAMEPAD2:
+		input = ~port->input[GAMEPAD_TH1];
+		break;
 	case IO_GAMEPAD3:
 	{
 		input = port->input[th ? GAMEPAD_TH1 : GAMEPAD_TH0];
--- a/io.h	Tue Jan 03 21:18:42 2017 -0800
+++ b/io.h	Tue Jan 03 21:18:52 2017 -0800
@@ -10,6 +10,7 @@
 #include "romdb.h"
 
 enum {
+	IO_GAMEPAD2,
 	IO_GAMEPAD3,
 	IO_GAMEPAD6,
 	IO_MOUSE,