This file is indexed.

/usr/share/openmsx/scripts/soundchip_utils.tcl is in openmsx-data 0.8.2-2.1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  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
# Several utility procs for usage in other scripts
# don't export anything, just use it from the namespace,
# because these scripts aren't useful for console users
# and should therefore not be exported to the global
# namespace.
#
# These procs are specifically for sound chips.
#
# Born to prevent duplication between scripts for common stuff.

namespace eval soundchip_utils {

proc get_num_channels {soundchip} {
	set num 1
	while {[info exists ::${soundchip}_ch${num}_mute]} {
		incr num
	}
	expr {$num - 1}
}

# It is advised to cache the result of this proc for each channel of each sound device
# before using it, because then a lot will be pre-evaluated and at run time only the
# actual variable stuff will be evaluated.
# We cannot cache it here, because we don't know the names of the sound chips in the
# machine you are going to use this on.
# @param soundchip the name of the soundchip as it appears in the output of
# "machine_info sounddevice"
# @channel the channel for which you want the expression to get the volume, the
# first channel is channel 0 and the channels are the ones as they are output
# by the record_channels command.
# @return expression to calculate the volume of the device for that channel in
# range [0-1]; returns just 'x' in case the chip is not supported.
# @todo:
#  - frequency expressions for (some of?) the drum channels are not correct
#  - implement volume for MoonSound FM (tricky stuff)
#  - actually, don't use regs to calc volume but actual wave data (needs openMSX
#    changes)
#
proc get_volume_expr {soundchip channel} {
	switch [machine_info sounddevice $soundchip] {
		"PSG" {
			set regs "\"${soundchip} regs\""
			return "set keybits \[debug read $regs 7\]; set val \[debug read $regs [expr {$channel + 8}]\]; expr {(\$val & 0x10) ? 1.0 : ((\$val & 0xF) / 15.0) * !((\$keybits >> $channel) & (\$keybits >> [expr {$channel + 3}]) & 1)}"
		}
		"MoonSound wave-part" {
			set regs "\"${soundchip} regs\""
			return "expr {(\[debug read $regs [expr {$channel + 0x68}]\]) ? (127 - (\[debug read $regs [expr {$channel + 0x50}]\] >> 1)) / 127.0 : 0.0}";
		}
		"Konami SCC" -
		"Konami SCC+" {
			set regs "\"${soundchip} SCC\""
			return "expr {((\[debug read $regs [expr {$channel + 0xAA}]\] &0xF)) / 15.0 * ((\[debug read $regs 0xAF\] >> $channel) &1)}"
		}
		"MSX-MUSIC" {
			set regs "\"${soundchip} regs\""
			set vol_expr "(\[debug read $regs [expr {$channel + 0x30}]\] & 0x0F)"
			set keyon_expr "(\[debug read $regs [expr {$channel + 0x20}]\] & 0x10)"
			set music_mode_expr "$keyon_expr ? ((15 - $vol_expr) / 15.0) : 0.0"
			set rhythm_expr "\[debug read $regs 0x0E\]"
			if {$channel < 6} {
				# always melody channel
				return "expr {$music_mode_expr}"
			} elseif {$channel < 9} {
				# melody channel when not in rhythm mode
				return "expr {($rhythm_expr & 0x20) ? 0.0 : $music_mode_expr}"
			} elseif {$channel < 14} {
				# rhythm channel (when rhythm mode enabled)
				if {$channel < 12} {
					set vol_expr "(\[debug read $regs [expr {$channel + 0x30 - 3}]\] & 0x0F)"
				} else {
					set vol_expr "(\[debug read $regs [expr {$channel + 0x2E - 3}]\] >> 4)"
				}
				switch $channel {
					 9 {set mask 0x30} ;# BD
					10 {set mask 0x28} ;# SD
					11 {set mask 0x22} ;# T-CYM
					12 {set mask 0x21} ;# HH
					13 {set mask 0x24} ;# TOM
				}
				return "expr {($rhythm_expr & $mask) ? (15 - $vol_expr) / 15.0 : 0.0}"
			} else {
				error "Unknown channel: $channel for $soundchip!"
			}
		}
		"MSX-AUDIO" {
			set regs "\"${soundchip} regs\""
			set ofst [expr {0x43 + $channel + 5 * ($channel / 3)}]
			set keyon_expr "(\[debug read $regs [expr {$channel + 0xB0}]\] & 0x20)"
			set vol_expr {(63 - (\[debug read $regs $ofst\] & 63)) / 63.0}
			set music_mode_expr "($keyon_expr ? [subst $vol_expr] : 0.0)"
			set rhythm_expr "\[debug read $regs 0xBD\]"
			if {$channel < 6} {
				# always melody channel
				return "expr {$music_mode_expr}"
			} elseif {$channel < 9} {
				# melody channel when not in rhythm mode
				return "expr {($rhythm_expr & 0x20) ? 0.0 : $music_mode_expr}"
			} elseif {$channel < 14} {
				# rhythm channel (when rhythm mode enabled)
				switch $channel {
					 9 {set mask 0x30; set ofst 0x53} ;# BD  (slot 16)
					10 {set mask 0x28; set ofst 0x54} ;# SD  (slot 17)
					11 {set mask 0x22; set ofst 0x55} ;# CYM (slot 18)
					12 {set mask 0x21; set ofst 0x51} ;# HH  (slot 13)
					13 {set mask 0x24; set ofst 0x52} ;# TOM (slot 14)
				}
				return "expr {($rhythm_expr & $mask) ? [subst $vol_expr] : 0.0}"
			} elseif {$channel < 15} {
				# ADPCM
				# can we output 0 when no sample is playing?
				return "expr {\[debug read $regs 0x12\] / 255.0}"
			} else {
				error "Unknown channel: $channel for $soundchip!"
			}
		}
		default {
			return "x"
		}
	}
}

# It is advised to cache the result of this proc for each channel of each sound device
# before using it, because then a lot will be pre-evaluated and at run time only the
# actual variable stuff will be evaluated.
# We cannot cache it here, because we don't know the names of the sound chips in the
# machine you are going to use this on.
# @param soundchip the name of the soundchip as it appears in the output of
# "machine_info sounddevice"
# @channel the channel for which you want the expression to get the frequency, the
# first channel is channel 0 and the channels are the ones as they are output
# by the record_channels command.
# @return expression to calculate the frequency of the device for that channel in
# Hz; returns just 'x' in case the chip is not supported.
# @todo:
#  - implement frequency for MoonSound
#
proc get_frequency_expr {soundchip channel} {
	switch [machine_info sounddevice $soundchip] {
		"PSG" {
			set regs "\"${soundchip} regs\""
			set basefreq [expr {3579545.454545 / 32.0}]
			return "set val \[expr {\[debug read $regs \[expr {0 + ($channel * 2)}\]\] + 256 * ((\[debug read $regs \[expr {1 + ($channel * 2)}\]\]) & 15)}\]; expr {$basefreq/(\$val < 1 ? 1 : \$val)}"
		}
		"Konami SCC" -
		"Konami SCC+" {
			set regs "\"${soundchip} SCC\""
			set basefreq [expr {3579545.454545 / 32.0}]
			return "set val \[expr {\[debug read $regs \[expr {0xA0 + 0 + ($channel * 2)}\]\] + 256 * ((\[debug read $regs \[expr {0xA0 + 1 + ($channel * 2)}\]\]) & 15)}\]; expr {$basefreq/(\$val < 1 ? 1 : \$val)}"
		}
		"MSX-MUSIC" {
			set regs "\"${soundchip} regs\""
			set basefreq [expr {3579545.454545 / 72.0}]
			set factor [expr {$basefreq / (1 << 18)}]
			if {$channel >= 9} {
				#drums
				incr channel -3
			}
			return "expr {(\[debug read $regs [expr {$channel + 0x10}]\] + 256 * ((\[debug read $regs [expr {$channel + 0x20}]\]) & 1)) * $factor * (1 << (((\[debug read $regs [expr {$channel + 0x20}]\]) & 15) >> 1))}"
		}
		"MSX-AUDIO" {
			set regs "\"${soundchip} regs\""
			set basefreq [expr {3579545.454545 / 72.0}]
			if {$channel == 14} { ;# ADPCM
				set factor [expr {$basefreq / (1 << 16)}]
				return "expr {(\[debug read $regs 0x10\] + 256 * \[debug read $regs 0x11\]) * $factor / 10}";# /10 is just to make it fall a bit into a decent range...
			} else {
				set factor [expr {$basefreq / (1 << 19)}]
				if {$channel >= 9} {
					#drums
					incr channel -3
				}
				return "expr {(\[debug read $regs [expr {$channel + 0xA0}]\] + 256 * ((\[debug read $regs [expr {$channel + 0xB0}]\]) & 3)) * $factor * (1 << (((\[debug read $regs [expr {$channel + 0xB0}]\]) & 31) >> 2))}"
			}
		}
		default {
			return "x"
		}
	}
}

} ;# namespace soundchip_utils