procon_bypass_man 0.1.15 → 0.1.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|