procon_bypass_man 0.1.15 → 0.1.16
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +3 -0
- data/Gemfile.lock +24 -6
- data/README.md +8 -0
- data/lib/ext/em_pure_ruby.rb +25 -0
- data/lib/procon_bypass_man/background.rb +0 -1
- data/lib/procon_bypass_man/buttons_setting_configuration/layer.rb +2 -6
- data/lib/procon_bypass_man/bypass/usb_hid_logger.rb +1 -1
- data/lib/procon_bypass_man/bypass.rb +13 -6
- data/lib/procon_bypass_man/commands/print_boot_message_command.rb +50 -1
- data/lib/procon_bypass_man/commands/print_message_command.rb +8 -0
- data/lib/procon_bypass_man/commands/run_remote_pbm_action_dispatch_command.rb +1 -1
- data/lib/procon_bypass_man/commands/send_reload_config_event_command.rb +1 -2
- data/lib/procon_bypass_man/commands.rb +1 -0
- data/lib/procon_bypass_man/configuration.rb +27 -0
- data/lib/procon_bypass_man/domains/binary/base.rb +11 -0
- data/lib/procon_bypass_man/domains/binary/has_immutable_binary.rb +5 -0
- data/lib/procon_bypass_man/domains/binary/has_mutable_binary.rb +5 -0
- data/lib/procon_bypass_man/domains/binary/inbound_procon_binary.rb +23 -0
- data/lib/procon_bypass_man/domains/binary/processing_procon_binary.rb +80 -0
- data/lib/procon_bypass_man/domains.rb +11 -0
- data/lib/procon_bypass_man/{plugin.rb → plugins.rb} +0 -0
- data/lib/procon_bypass_man/processor.rb +4 -5
- data/lib/procon_bypass_man/procon/button.rb +11 -0
- data/lib/procon_bypass_man/procon/button_collection.rb +2 -12
- data/lib/procon_bypass_man/procon/layer_changer.rb +3 -2
- data/lib/procon_bypass_man/procon/press_button_aware.rb +5 -4
- data/lib/procon_bypass_man/procon/user_operation.rb +46 -63
- data/lib/procon_bypass_man/procon/{analog_stick.rb → value_objects/analog_stick.rb} +3 -4
- data/lib/procon_bypass_man/procon/value_objects/procon_reader.rb +34 -0
- data/lib/procon_bypass_man/procon.rb +16 -14
- data/lib/procon_bypass_man/remote_pbm_action/{lib → commands}/update_remote_pbm_action_status_command.rb +0 -0
- data/lib/procon_bypass_man/remote_pbm_action/restore_pbm_setting.rb +1 -1
- data/lib/procon_bypass_man/{value_objects → remote_pbm_action/value_objects}/remote_pbm_action_object.rb +0 -0
- data/lib/procon_bypass_man/remote_pbm_action.rb +1 -1
- data/lib/procon_bypass_man/runner.rb +3 -3
- data/lib/procon_bypass_man/scheduler.rb +0 -7
- data/lib/procon_bypass_man/version.rb +1 -1
- data/lib/procon_bypass_man/websocket/pbm_job_client.rb +79 -0
- data/lib/procon_bypass_man.rb +12 -6
- data/procon_bypass_man.gemspec +2 -0
- data/project_template/app.rb +1 -1
- data/sig/main.rbs +15 -1
- metadata +45 -10
- data/lib/procon_bypass_man/background/jobs/fetch_and_run_remote_pbm_action_job.rb +0 -29
- data/lib/procon_bypass_man/boot_message.rb +0 -48
- data/lib/procon_bypass_man/commands/run_local_shell_command.rb +0 -6
- data/lib/procon_bypass_man/procon_reader.rb +0 -31
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ece30577af00d56afa2e2e0be7e09d8328c9d7f8cc96c2e49d207a2bb423b867
|
4
|
+
data.tar.gz: faf86731651a110fd63ce977f65b76f46c31fe6215a2512d4c3a1ba545fd4f81
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 313d36b543a7c539effaabb6fca121a5112b4076a196ad52386924f3e043ad25e52c5c880a710c1d8aafc66d4a647b3387cebe0b82391eb4ccffa10dd1f4af65
|
7
|
+
data.tar.gz: 55e7a87c35f972e8537654b86a1f5e1815ed22144a4097e1993ad986666f1111972ce8ce1a744e56196c16957a56c328ba510b6b19af4ff8961ac989d216af20
|
data/CHANGELOG.md
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,12 +1,16 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
procon_bypass_man (0.1.
|
4
|
+
procon_bypass_man (0.1.16)
|
5
|
+
action_cable_client
|
5
6
|
pbmenv
|
7
|
+
sorted_set
|
6
8
|
|
7
9
|
GEM
|
8
10
|
remote: https://rubygems.org/
|
9
11
|
specs:
|
12
|
+
action_cable_client (3.1.0)
|
13
|
+
websocket-eventmachine-client (>= 1.2.0)
|
10
14
|
activesupport (6.1.4.1)
|
11
15
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
12
16
|
i18n (>= 1.6, < 2)
|
@@ -17,6 +21,7 @@ GEM
|
|
17
21
|
coderay (1.1.3)
|
18
22
|
concurrent-ruby (1.1.9)
|
19
23
|
diff-lcs (1.4.4)
|
24
|
+
eventmachine (1.2.7)
|
20
25
|
ffi (1.15.4)
|
21
26
|
i18n (1.8.11)
|
22
27
|
concurrent-ruby (~> 1.0)
|
@@ -29,7 +34,7 @@ GEM
|
|
29
34
|
mustermann (1.1.1)
|
30
35
|
ruby2_keywords (~> 0.0.1)
|
31
36
|
parallel (1.21.0)
|
32
|
-
parser (3.0.2
|
37
|
+
parser (3.0.3.2)
|
33
38
|
ast (~> 2.4.1)
|
34
39
|
pbmenv (0.1.6)
|
35
40
|
pry (0.14.1)
|
@@ -44,7 +49,8 @@ GEM
|
|
44
49
|
rb-inotify (0.10.1)
|
45
50
|
ffi (~> 1.0)
|
46
51
|
rbs (1.7.1)
|
47
|
-
|
52
|
+
rbtree (0.4.4)
|
53
|
+
regexp_parser (2.2.0)
|
48
54
|
rexml (3.2.5)
|
49
55
|
rspec (3.10.0)
|
50
56
|
rspec-core (~> 3.10.0)
|
@@ -68,23 +74,27 @@ GEM
|
|
68
74
|
rubocop-ast (>= 1.12.0, < 2.0)
|
69
75
|
ruby-progressbar (~> 1.7)
|
70
76
|
unicode-display_width (>= 1.4.0, < 3.0)
|
71
|
-
rubocop-ast (1.
|
77
|
+
rubocop-ast (1.14.0)
|
72
78
|
parser (>= 3.0.1.1)
|
73
79
|
ruby-progressbar (1.11.0)
|
74
80
|
ruby2_keywords (0.0.5)
|
81
|
+
set (1.0.2)
|
75
82
|
sinatra (2.1.0)
|
76
83
|
mustermann (~> 1.0)
|
77
84
|
rack (~> 2.2)
|
78
85
|
rack-protection (= 2.1.0)
|
79
86
|
tilt (~> 2.0)
|
80
|
-
|
87
|
+
sorted_set (1.0.3)
|
88
|
+
rbtree
|
89
|
+
set (~> 1.0)
|
90
|
+
steep (0.47.0)
|
81
91
|
activesupport (>= 5.1)
|
82
92
|
language_server-protocol (>= 3.15, < 4.0)
|
83
93
|
listen (~> 3.0)
|
84
94
|
parallel (>= 1.0.0)
|
85
95
|
parser (>= 3.0)
|
86
96
|
rainbow (>= 2.2.2, < 4.0)
|
87
|
-
rbs (
|
97
|
+
rbs (~> 1.7.0)
|
88
98
|
terminal-table (>= 2, < 4)
|
89
99
|
terminal-table (3.0.2)
|
90
100
|
unicode-display_width (>= 1.1.1, < 3)
|
@@ -94,6 +104,14 @@ GEM
|
|
94
104
|
concurrent-ruby (~> 1.0)
|
95
105
|
unicode-display_width (2.1.0)
|
96
106
|
webrick (1.7.0)
|
107
|
+
websocket (1.2.9)
|
108
|
+
websocket-eventmachine-base (1.2.0)
|
109
|
+
eventmachine (~> 1.0)
|
110
|
+
websocket (~> 1.0)
|
111
|
+
websocket-native (~> 1.0)
|
112
|
+
websocket-eventmachine-client (1.3.0)
|
113
|
+
websocket-eventmachine-base (~> 1.0)
|
114
|
+
websocket-native (1.0.0)
|
97
115
|
zeitwerk (2.5.1)
|
98
116
|
|
99
117
|
PLATFORMS
|
data/README.md
CHANGED
@@ -34,6 +34,14 @@ Switch <-- (PBM): ZR連打
|
|
34
34
|
## Plugins
|
35
35
|
* https://github.com/splaplapla/procon_bypass_man-splatoon2
|
36
36
|
|
37
|
+
## 関連ソフトウェア
|
38
|
+
* サーバソフトウェア(WIP)
|
39
|
+
* https://github.com/splaplapla/procon_bypass_man_cloud
|
40
|
+
* このサーバからOS自体の再起動、設定ファイルの変更、PBMのバージョンアップができます
|
41
|
+
* 自分でホストティングしてください
|
42
|
+
* pbmenv
|
43
|
+
* バージョンマネージャー
|
44
|
+
|
37
45
|
## FAQ
|
38
46
|
* どうやって動かすの?
|
39
47
|
* このツールはRaspberry Pi4をUSBガジェットモードで起動して有線でプロコンとSwitchに接続して使います
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# https://github.com/eventmachine/eventmachine/pull/929 is not released yet.
|
2
|
+
# i will delete this patch if released.
|
3
|
+
module EventMachine
|
4
|
+
# @private
|
5
|
+
class Reactor
|
6
|
+
def run_timers
|
7
|
+
timers_to_delete = []
|
8
|
+
@timers.each {|t|
|
9
|
+
if t.first <= @current_loop_time
|
10
|
+
#@timers.delete t
|
11
|
+
timers_to_delete << t
|
12
|
+
EventMachine::event_callback "", TimerFired, t.last
|
13
|
+
else
|
14
|
+
break
|
15
|
+
end
|
16
|
+
}
|
17
|
+
timers_to_delete.map{|c| @timers.delete c}
|
18
|
+
timers_to_delete = nil
|
19
|
+
#while @timers.length > 0 and @timers.first.first <= now
|
20
|
+
# t = @timers.shift
|
21
|
+
# EventMachine::event_callback "", TimerFired, t.last
|
22
|
+
#end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -10,5 +10,4 @@ require "procon_bypass_man/background/jobs/report_reload_config_job"
|
|
10
10
|
require "procon_bypass_man/background/jobs/report_load_config_job"
|
11
11
|
require "procon_bypass_man/background/jobs/report_error_job"
|
12
12
|
require "procon_bypass_man/background/jobs/report_pressed_buttons_job"
|
13
|
-
require "procon_bypass_man/background/jobs/fetch_and_run_remote_pbm_action_job"
|
14
13
|
require "procon_bypass_man/background/jobs/sync_device_stats_job"
|
@@ -10,7 +10,6 @@ module ProconBypassMan
|
|
10
10
|
self.remaps = {}
|
11
11
|
self.left_analog_stick_caps = {}
|
12
12
|
self.disables = []
|
13
|
-
instance_eval(&block) if block_given?
|
14
13
|
end
|
15
14
|
|
16
15
|
# @param [Symbol] button
|
@@ -50,11 +49,8 @@ module ProconBypassMan
|
|
50
49
|
end
|
51
50
|
hash[:flip_interval] = interval
|
52
51
|
end
|
53
|
-
|
54
|
-
|
55
|
-
else
|
56
|
-
self.flips[button] = hash
|
57
|
-
end
|
52
|
+
|
53
|
+
self.flips[button] = hash
|
58
54
|
end
|
59
55
|
|
60
56
|
def macro(name, if_pressed: )
|
@@ -30,7 +30,7 @@ class ProconBypassMan::Bypass
|
|
30
30
|
|
31
31
|
ProconBypassMan.cache.fetch key: 'pressed_buttons_reporter', expires_in: 5 do
|
32
32
|
ProconBypassMan::ReportPressedButtonsJob.perform_async(
|
33
|
-
|
33
|
+
bypass_value.binary.to_procon_reader.to_hash
|
34
34
|
)
|
35
35
|
end
|
36
36
|
end
|
@@ -5,7 +5,7 @@ class ProconBypassMan::Bypass
|
|
5
5
|
|
6
6
|
class BypassValue < Struct.new(:binary, :sent)
|
7
7
|
def to_text
|
8
|
-
"#{binary.unpack
|
8
|
+
"#{binary.unpack.first} #{'x' unless sent}"
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
@@ -21,14 +21,14 @@ class ProconBypassMan::Bypass
|
|
21
21
|
def send_gadget_to_procon!
|
22
22
|
monitor.record(:start_function)
|
23
23
|
input = nil
|
24
|
-
self.bypass_value = BypassValue.new(
|
24
|
+
self.bypass_value = BypassValue.new(nil, sent = false)
|
25
25
|
|
26
26
|
run_callbacks(:send_gadget_to_procon) do
|
27
27
|
begin
|
28
28
|
break if $will_terminate_token
|
29
29
|
# TODO blocking readにしたいが、接続時のフェーズによって長さが違うので厳しい
|
30
30
|
input = self.gadget.read_nonblock(64)
|
31
|
-
self.bypass_value.binary = input
|
31
|
+
self.bypass_value.binary = ProconBypassMan::Domains::InboundProconBinary.new(binary: input)
|
32
32
|
rescue IO::EAGAINWaitReadable
|
33
33
|
monitor.record(:eagain_wait_readable_on_read)
|
34
34
|
sleep(0.001)
|
@@ -50,14 +50,14 @@ class ProconBypassMan::Bypass
|
|
50
50
|
def send_procon_to_gadget!
|
51
51
|
monitor.record(:start_function)
|
52
52
|
output = nil
|
53
|
-
self.bypass_value = BypassValue.new(
|
53
|
+
self.bypass_value = BypassValue.new(nil, sent = false)
|
54
54
|
|
55
55
|
run_callbacks(:send_procon_to_gadget) do
|
56
56
|
begin
|
57
57
|
break if $will_terminate_token
|
58
58
|
Timeout.timeout(1) do
|
59
59
|
output = self.procon.read(64)
|
60
|
-
self.bypass_value.binary = output
|
60
|
+
self.bypass_value.binary = ProconBypassMan::Domains::InboundProconBinary.new(binary: output)
|
61
61
|
end
|
62
62
|
rescue Timeout::Error
|
63
63
|
ProconBypassMan.logger.debug { "read timeout! do sleep. by send_procon_to_gadget!" }
|
@@ -72,8 +72,15 @@ class ProconBypassMan::Bypass
|
|
72
72
|
retry
|
73
73
|
end
|
74
74
|
|
75
|
+
# blocking readをしているのでnilが入ることはないが、雑なテストでnilが通るので分岐を入れる。できれば消したい
|
76
|
+
break if output.nil?
|
77
|
+
|
75
78
|
begin
|
76
|
-
self.gadget.write_nonblock(
|
79
|
+
self.gadget.write_nonblock(
|
80
|
+
ProconBypassMan::Processor.new(
|
81
|
+
ProconBypassMan::Domains::InboundProconBinary.new(binary: output)
|
82
|
+
).process
|
83
|
+
)
|
77
84
|
self.bypass_value.sent = true
|
78
85
|
rescue IO::EAGAINWaitReadable
|
79
86
|
monitor.record(:eagain_wait_readable_on_write)
|
@@ -1,7 +1,56 @@
|
|
1
1
|
class ProconBypassMan::PrintBootMessageCommand
|
2
|
+
class BootMessage
|
3
|
+
def initialize
|
4
|
+
@table = {}
|
5
|
+
@table[:ruby_version] = RUBY_VERSION
|
6
|
+
@table[:pbm_version] = ProconBypassMan::VERSION
|
7
|
+
@table[:pid] = $$
|
8
|
+
@table[:root_path] = ProconBypassMan.root
|
9
|
+
@table[:pid_path] = ProconBypassMan.pid_path
|
10
|
+
@table[:setting_path] = ProconBypassMan::ButtonsSettingConfiguration.instance.setting_path
|
11
|
+
@table[:uptime_from_boot] = ProconBypassMan::Uptime.from_boot
|
12
|
+
@table[:use_pbmenv] = !(!!`which pbmenv`.empty?)
|
13
|
+
@table[:session_id] = ProconBypassMan.session_id
|
14
|
+
@table[:device_id] = ProconBypassMan.device_id
|
15
|
+
|
16
|
+
# 開発中のHEADを取りたかったけど、Gem::Specification経由から取得する必要がありそう
|
17
|
+
# build_version = `git rev-parse --short HEAD`.chomp
|
18
|
+
# if build_version.empty?
|
19
|
+
# @table[:build_version] = 'release version'
|
20
|
+
# else
|
21
|
+
# @table[:build_version] = build_version
|
22
|
+
# end
|
23
|
+
|
24
|
+
# build version: #{@table[:build_version]}
|
25
|
+
end
|
26
|
+
|
27
|
+
# @return [String]
|
28
|
+
def to_s
|
29
|
+
booted_message = <<~EOF
|
30
|
+
----
|
31
|
+
RUBY_VERSION: #{@table[:ruby_version]}
|
32
|
+
ProconBypassMan::VERSION: #{@table[:pbm_version]}
|
33
|
+
pid: #{@table[:pid]}
|
34
|
+
root: #{@table[:root_path]}
|
35
|
+
pid_path: #{@table[:pid_path]}
|
36
|
+
setting_path: #{@table[:setting_path]}
|
37
|
+
uptime from boot: #{@table[:uptime_from_boot]} sec
|
38
|
+
use_pbmenv: #{@table[:use_pbmenv]}
|
39
|
+
session_id: #{ProconBypassMan.session_id}
|
40
|
+
device_id: #{ProconBypassMan.device_id}
|
41
|
+
----
|
42
|
+
EOF
|
43
|
+
end
|
44
|
+
|
45
|
+
# @return [Hash]
|
46
|
+
def to_hash
|
47
|
+
@table
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
2
51
|
# @return [void]
|
3
52
|
def self.execute
|
4
|
-
message =
|
53
|
+
message = BootMessage.new
|
5
54
|
ProconBypassMan::ReportBootJob.perform_async(message.to_hash)
|
6
55
|
ProconBypassMan::ReportLoadConfigJob.perform_async(ProconBypassMan.config.raw_setting)
|
7
56
|
puts message.to_s
|
@@ -13,7 +13,7 @@ class ProconBypassMan::RunRemotePbmActionDispatchCommand
|
|
13
13
|
when ProconBypassMan::RemotePbmAction::ACTION_RESTORE_SETTING
|
14
14
|
ProconBypassMan::RemotePbmAction::RestorePbmSettingAction.new(pbm_job_uuid: uuid).run!(job_args: job_args)
|
15
15
|
else
|
16
|
-
|
16
|
+
raise "#{action}は対応していないアクションです"
|
17
17
|
end
|
18
18
|
rescue ProconBypassMan::RemotePbmAction::ActionUnexpectedError => e
|
19
19
|
ProconBypassMan::SendErrorCommand.execute(error: e)
|
@@ -1,8 +1,7 @@
|
|
1
1
|
class ProconBypassMan::SendReloadConfigEventCommand
|
2
2
|
# @return [void]
|
3
3
|
def self.execute
|
4
|
-
|
5
|
-
ProconBypassMan.logger.info "設定ファイルの再読み込みができました"
|
4
|
+
ProconBypassMan::PrintMessageCommand.execute(text: "設定ファイルの再読み込みができました")
|
6
5
|
ProconBypassMan::ReportReloadConfigJob.perform_async(
|
7
6
|
ProconBypassMan.config.raw_setting
|
8
7
|
)
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require "procon_bypass_man/commands/print_boot_message_command"
|
2
|
+
require "procon_bypass_man/commands/print_message_command"
|
2
3
|
require "procon_bypass_man/commands/write_session_id_command"
|
3
4
|
require "procon_bypass_man/commands/write_device_id_command"
|
4
5
|
require "procon_bypass_man/commands/send_reload_config_event_command"
|
@@ -111,6 +111,33 @@ class ProconBypassMan::Configuration
|
|
111
111
|
@server_pool ||= ProconBypassMan::ServerPool.new(servers: api_servers)
|
112
112
|
end
|
113
113
|
|
114
|
+
# @return [String, NilClass]
|
115
|
+
def current_server
|
116
|
+
server_pool.server
|
117
|
+
end
|
118
|
+
|
119
|
+
# @return [String, NilClass]
|
120
|
+
def current_ws_server
|
121
|
+
if (uri = URI.parse(server_pool.server))
|
122
|
+
if uri.port == 443
|
123
|
+
return "ws://#{uri.host}"
|
124
|
+
else
|
125
|
+
return "ws://#{uri.host}:#{uri.port}"
|
126
|
+
end
|
127
|
+
end
|
128
|
+
rescue URI::InvalidURIError
|
129
|
+
nil
|
130
|
+
end
|
131
|
+
|
132
|
+
# @return [String, NilClass]
|
133
|
+
def current_ws_server_url
|
134
|
+
return unless current_ws_server
|
135
|
+
"#{current_ws_server}/websocket/"
|
136
|
+
end
|
137
|
+
|
138
|
+
# @return [Boolean]
|
139
|
+
def enable_ws?; !!current_server; end
|
140
|
+
|
114
141
|
# @return [Array<String>]
|
115
142
|
def api_servers
|
116
143
|
if !!ENV["API_SERVER"]
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# proconから取得したばかりのバイナリ
|
2
|
+
class ProconBypassMan::Domains::InboundProconBinary < ProconBypassMan::Domains::Binary::Base
|
3
|
+
include ProconBypassMan::Domains::HasImmutableBinary
|
4
|
+
|
5
|
+
# @return [String]
|
6
|
+
def raw
|
7
|
+
binary.dup
|
8
|
+
end
|
9
|
+
|
10
|
+
def unpack
|
11
|
+
binary.unpack("H*")
|
12
|
+
end
|
13
|
+
|
14
|
+
# @return [ProconBypassMan::ProconReader]
|
15
|
+
def to_procon_reader
|
16
|
+
ProconBypassMan::ProconReader.new(binary: binary)
|
17
|
+
end
|
18
|
+
|
19
|
+
# @return [Boolean]
|
20
|
+
def user_operation_data?
|
21
|
+
binary[0] == "\x30".b
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# バイナリの書き換えのみをする
|
2
|
+
class ProconBypassMan::Domains::ProcessingProconBinary < ProconBypassMan::Domains::Binary::Base
|
3
|
+
include ProconBypassMan::Domains::HasMutableBinary
|
4
|
+
|
5
|
+
ALL_ZERO_BIT = ["0"].pack("H*").freeze
|
6
|
+
|
7
|
+
# @return [String]
|
8
|
+
def raw
|
9
|
+
binary
|
10
|
+
end
|
11
|
+
|
12
|
+
def unpack
|
13
|
+
binary.unpack("H*")
|
14
|
+
end
|
15
|
+
|
16
|
+
def set_no_action!
|
17
|
+
binary[3] = ALL_ZERO_BIT
|
18
|
+
binary[4] = ALL_ZERO_BIT
|
19
|
+
binary[5] = ALL_ZERO_BIT
|
20
|
+
end
|
21
|
+
|
22
|
+
# @param [ProconBypassMan::Domains::ProcessingProconBinary]
|
23
|
+
# @return [ProconBypassMan::Domains::ProcessingProconBinary]
|
24
|
+
# アナログスティックは上書きし、ボタンだけマージする
|
25
|
+
def write_as_merge!(target_binary)
|
26
|
+
current_buttons = ProconBypassMan::ProconReader.new(binary: binary).pressing
|
27
|
+
target_buttons = ProconBypassMan::ProconReader.new(binary: target_binary.raw).pressing
|
28
|
+
|
29
|
+
set_no_action!
|
30
|
+
(current_buttons + target_buttons).uniq.each do |button|
|
31
|
+
write_as_press_button(button)
|
32
|
+
end
|
33
|
+
|
34
|
+
# override analog stick
|
35
|
+
tb = [target_binary.raw].pack("H*")
|
36
|
+
binary[6] = tb[6]
|
37
|
+
binary[7] = tb[7]
|
38
|
+
binary[8] = tb[8]
|
39
|
+
binary[9] = tb[9]
|
40
|
+
binary[10] = tb[10]
|
41
|
+
binary[11] = tb[11]
|
42
|
+
|
43
|
+
self
|
44
|
+
end
|
45
|
+
|
46
|
+
# @param [Symbol] button
|
47
|
+
def write_as_press_button(button)
|
48
|
+
raise "already pressing button(#{button})" if ProconBypassMan::PressButtonAware.new(binary).pressing_button?(button)
|
49
|
+
|
50
|
+
button_obj = ProconBypassMan::Procon::Button.new(button)
|
51
|
+
value = binary[button_obj.byte_position].unpack("H*").first.to_i(16) + (2**button_obj.bit_position)
|
52
|
+
binary[button_obj.byte_position] = ["%02X" % value.to_s].pack("H*")
|
53
|
+
end
|
54
|
+
|
55
|
+
# @param [Symbol] button
|
56
|
+
def write_as_unpress_button(button)
|
57
|
+
raise "not press button(#{button}) yet" if not ProconBypassMan::PressButtonAware.new(binary).pressing_button?(button)
|
58
|
+
|
59
|
+
button_obj = ProconBypassMan::Procon::Button.new(button)
|
60
|
+
value = binary[button_obj.byte_position].unpack("H*").first.to_i(16) - (2**button_obj.bit_position)
|
61
|
+
binary[button_obj.byte_position] = ["%02X" % value.to_s].pack("H*")
|
62
|
+
end
|
63
|
+
|
64
|
+
# @param [Symbol] button
|
65
|
+
def write_as_press_button_only(button)
|
66
|
+
set_no_action!
|
67
|
+
write_as_press_button(button)
|
68
|
+
end
|
69
|
+
|
70
|
+
# @param [Integer] cap
|
71
|
+
def write_as_apply_left_analog_stick_cap(cap: )
|
72
|
+
analog_stick_cap = ProconBypassMan::Procon::AnalogStickCap.new(binary)
|
73
|
+
binary[6..8] = analog_stick_cap.capped_position(cap_hypotenuse: cap).to_binary
|
74
|
+
end
|
75
|
+
|
76
|
+
# @return [ProconBypassMan::ProconReader]
|
77
|
+
def to_procon_reader
|
78
|
+
ProconBypassMan::ProconReader.new(binary: binary)
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module ProconBypassMan
|
2
|
+
module Domains
|
3
|
+
module Binary; end
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
require_relative "domains/binary/base"
|
8
|
+
require_relative "domains/binary/has_mutable_binary"
|
9
|
+
require_relative "domains/binary/has_immutable_binary"
|
10
|
+
require_relative "domains/binary/inbound_procon_binary"
|
11
|
+
require_relative "domains/binary/processing_procon_binary"
|
File without changes
|
@@ -1,16 +1,15 @@
|
|
1
1
|
class ProconBypassMan::Processor
|
2
|
-
|
2
|
+
|
3
|
+
# @param [ProconBypassMan::Domains::InboundProconBinary] binary
|
3
4
|
def initialize(binary)
|
4
5
|
@binary = binary
|
5
6
|
end
|
6
7
|
|
7
8
|
# @return [String] 加工後の入力データ
|
8
9
|
def process
|
9
|
-
|
10
|
-
return @binary
|
11
|
-
end
|
10
|
+
return @binary.raw unless @binary.user_operation_data?
|
12
11
|
|
13
|
-
procon = ProconBypassMan::Procon.new(@binary)
|
12
|
+
procon = ProconBypassMan::Procon.new(@binary.raw)
|
14
13
|
procon.apply!
|
15
14
|
procon.to_binary
|
16
15
|
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class ProconBypassMan::Procon::Button
|
2
|
+
class UnknownButtonFoundError < StandardError; end
|
3
|
+
|
4
|
+
attr_accessor :byte_position, :bit_position
|
5
|
+
|
6
|
+
def initialize(key)
|
7
|
+
b = ProconBypassMan::Procon::ButtonCollection::BUTTONS_MAP[key] or raise(UnknownButtonFoundError, '定義にないボタンです')
|
8
|
+
self.byte_position = b[:byte_position]
|
9
|
+
self.bit_position = b[:bit_position]
|
10
|
+
end
|
11
|
+
end
|
@@ -1,13 +1,4 @@
|
|
1
1
|
class ProconBypassMan::Procon::ButtonCollection
|
2
|
-
class Button
|
3
|
-
attr_accessor :byte_position, :bit_position
|
4
|
-
def initialize(key)
|
5
|
-
b = BUTTONS_MAP[key] or raise("undefined button")
|
6
|
-
self.byte_position = b[:byte_position]
|
7
|
-
self.bit_position = b[:bit_position]
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
2
|
# https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering/blob/ac8093c84194b3232acb675ac1accce9bcb456a3/bluetooth_hid_notes.md
|
12
3
|
#0) Input report ID
|
13
4
|
#1) Timer. Increments very fast. Can be used to estimate excess Bluetooth latency.
|
@@ -42,9 +33,8 @@ class ProconBypassMan::Procon::ButtonCollection
|
|
42
33
|
end
|
43
34
|
acc
|
44
35
|
}.freeze
|
36
|
+
|
45
37
|
BUTTONS = ProconBypassMan::Procon::ButtonCollection::BUTTONS_MAP.keys.freeze
|
46
38
|
|
47
|
-
|
48
|
-
Button.new(button_key)
|
49
|
-
end
|
39
|
+
LEFT_ANALOG_STICK = { byte_position: 6..8 }
|
50
40
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
class ProconBypassMan::Procon::LayerChanger
|
2
|
+
# @param [ProconBypassMan::Domains::ProcessingProconBinary] binary
|
2
3
|
def initialize(binary: )
|
3
|
-
@procon_reader =
|
4
|
+
@procon_reader = binary.to_procon_reader
|
4
5
|
end
|
5
6
|
|
6
7
|
# @return [Symbol]
|
@@ -35,6 +36,6 @@ class ProconBypassMan::Procon::LayerChanger
|
|
35
36
|
|
36
37
|
# @return [Boolean]
|
37
38
|
def pressed?(button: )
|
38
|
-
@procon_reader.
|
39
|
+
@procon_reader.pressing.include?(button)
|
39
40
|
end
|
40
41
|
end
|
@@ -1,13 +1,14 @@
|
|
1
|
-
class ProconBypassMan::
|
1
|
+
class ProconBypassMan::PressButtonAware
|
2
2
|
def initialize(binary)
|
3
3
|
@binary = binary
|
4
4
|
end
|
5
5
|
|
6
|
-
def
|
6
|
+
def pressing_button?(button)
|
7
|
+
button_obj = ProconBypassMan::Procon::Button.new(button)
|
7
8
|
@binary[
|
8
|
-
|
9
|
+
button_obj.byte_position
|
9
10
|
].unpack("H*").first.to_i(16).to_s(2).reverse[
|
10
|
-
|
11
|
+
button_obj.bit_position
|
11
12
|
] == '1'
|
12
13
|
end
|
13
14
|
end
|