OXYGENHUB
◆ main openmsx / share / scripts / _vdp_access_test.tcl
3.3 KiB · Tcl · last changed chore(): initial commit 1 month ago source blame history raw
e8555c89 Andy McCall 1
namespace eval vdp_access_test {
2
3
# you can tweak these to test for other stuff
4
# TODO: make this flexible so the timing can be specified for each combination
5
# of ports and read/write
6
variable ioports {0x98 0x99}
7
variable cycle_max 29
8
# if you set this to true, you can also see OK I/O, but there are many of those!
9
variable debug false
10
# if you set this to true, openMSX will break when too fast access happens, so
11
# you can investigate what's going on with the debug commands (or debugger)
12
variable enable_break false
13
14
variable last_access_time 0
15
variable last_access_type
16
variable last_access_port
17
variable is_enabled false
18
variable watchpoint_write_id
19
variable watchpoint_read_id
20
variable address_list
21
22
set_help_text toggle_vdp_access_test \
23
"Report in the console when VDP I/O is done which could possibly cause data
24
corruption on the slowest VDP (TMS99xx), i.e. when time between successive I/O
25
was less than $cycle_max cycles and display was active. Note: this script is
26
not 100% accurate! Keep testing on a real MSX as well. The script has some
27
tuning options; edit the script to do so, it's explained at the top what can be
28
tuned."
29
30
proc check_time {access_type} {
31
	variable last_access_time
32
	variable last_access_type
33
	variable last_access_port
34
	variable cycle_max
35
	variable debug
36
	variable enable_break
37
	variable address_list
38
39
	set port [expr {$::wp_last_address & 255}]
40
	set current_time [machine_info time]
41
	set cycles [expr {round(3579545 * ($current_time - $last_access_time))}]
42
	set screen_enabled [expr {[debug read "VDP regs" 1] & 64}]
43
	set vblank [expr {[debug read "VDP status regs" 2] & 64}]
44
	set pc [format "%04x" [reg PC]]
45
	if {($cycles < $cycle_max) && $screen_enabled && !$vblank} {
46
		if {$pc ni $address_list} {
47
			set valuetext ""
48
			if {$access_type eq "write"} {
49
				set valuetext [format " (value 0x%02X)" $::wp_last_value]
50
			}
51
			puts [format "VDP $last_access_type on port 0x%02X followed by a $access_type${valuetext} on port 0x%02X on address $pc and time $current_time with too few cycles in between: $cycles (< $cycle_max)" $last_access_port $port]
52
			lappend address_list $pc
53
			set address_list [lsort $address_list]
54
			puts "Sorted list of addresses where too fast I/O is done: $address_list"
55
			if {$enable_break} {
56
				debug break
57
			}
58
		}
59
	} else {
60
		if {$debug} {
61
			if {!$screen_enabled} {
62
				set reason "screen is disabled"
63
			} elseif {$vblank} {
64
				set reason "in vblank"
65
			} else {
66
				set reason "last access was $cycles cycles ago, >= $cycle_max"
67
			}
68
			puts [format "VDP I/O $access_type to port 0x%02X OK on address: 0x$pc, $reason" $port]
69
		}
70
	}
71
	set last_access_time $current_time
72
	set last_access_port $port
73
	set last_access_type $access_type
74
}
75
76
proc toggle_vdp_access_test {} {
77
	variable is_enabled
78
	variable watchpoint_write_id
79
	variable watchpoint_read_id
80
	variable address_list
81
	variable ioports
82
83
	if {!$is_enabled} {
84
		set watchpoint_write_id [debug set_watchpoint write_io $ioports {} {vdp_access_test::check_time "write"}]
85
		set watchpoint_read_id  [debug set_watchpoint read_io  $ioports {} {vdp_access_test::check_time "read"}]
86
		set is_enabled true
87
		set address_list [list]
88
	} else {
89
		debug remove_watchpoint $watchpoint_write_id
90
		debug remove_watchpoint $watchpoint_read_id
91
		set is_enabled false
92
	}
93
}
94
95
namespace export toggle_vdp_access_test
96
97
} ;# namespace vdp_access_test
98
99
namespace import vdp_access_test::*