mirror of
https://github.com/safiire/n65.git
synced 2025-02-01 08:33:27 +00:00
Adding usb everdrive transfer
This commit is contained in:
parent
709a501071
commit
5aec94a036
175
everdrive_transfer/everdrive.rb
Executable file
175
everdrive_transfer/everdrive.rb
Executable file
@ -0,0 +1,175 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
require 'libusb'
|
||||
require 'date'
|
||||
|
||||
class EverdriveIO
|
||||
class DeviceNotFound < StandardError; end
|
||||
|
||||
def initialize(vendor, product)
|
||||
@device = find_device(vendor, product)
|
||||
@input, @output = find_bulk_endpoints(device)
|
||||
@handle = device.open
|
||||
handle.claim_interface(input.interface)
|
||||
end
|
||||
|
||||
def inspect
|
||||
"#<#{self.class.name}: #{device.inspect}>"
|
||||
end
|
||||
|
||||
def close
|
||||
handle.close
|
||||
end
|
||||
|
||||
def read(length)
|
||||
handle.bulk_transfer(endpoint: input, dataIn: length)
|
||||
end
|
||||
|
||||
def write(data)
|
||||
handle.bulk_transfer(endpoint: output, dataOut: data)
|
||||
end
|
||||
|
||||
def read_u8
|
||||
read(1).ord
|
||||
end
|
||||
|
||||
def read_u16
|
||||
read(2).unpack('S').first
|
||||
end
|
||||
|
||||
def read_u32
|
||||
read(4).unpack('L').first
|
||||
end
|
||||
|
||||
def write_u8(u8)
|
||||
write(
|
||||
(u8 & 0xff).chr
|
||||
)
|
||||
end
|
||||
|
||||
def write_u16(u16)
|
||||
write(
|
||||
[
|
||||
(u16 & 0x00ff),
|
||||
(u16 & 0xff00) >> 8
|
||||
].pack('cc')
|
||||
)
|
||||
end
|
||||
|
||||
def write_u32(u32)
|
||||
write(
|
||||
[
|
||||
(u32 & 0x000000ff),
|
||||
(u32 & 0x0000ff00) >> 8,
|
||||
(u32 & 0x00ff0000) >> 32,
|
||||
(u32 & 0xff000000) >> 24,
|
||||
].pack('cccc')
|
||||
)
|
||||
end
|
||||
|
||||
def write_string(string)
|
||||
write_u16(string.length)
|
||||
write(string)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :input, :output, :handle, :device
|
||||
|
||||
def find_device(vendor, product)
|
||||
LIBUSB::Context.new.devices(idVendor: vendor, idProduct: product).first.tap do |device|
|
||||
raise(DeviceNotFound) if device.nil?
|
||||
end
|
||||
end
|
||||
|
||||
def find_bulk_endpoints(device)
|
||||
[
|
||||
device.endpoints.find { |ep| ep.transfer_type == :bulk && ep.direction == :in },
|
||||
device.endpoints.find { |ep| ep.transfer_type == :bulk && ep.direction == :out }
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
class Everdrive
|
||||
VENDOR = 0x0483
|
||||
PRODUCT = 0x5740
|
||||
STATUS_OK = 0xa500
|
||||
|
||||
FAT_WRITE = 0x02
|
||||
FAT_OPEN_ALWAYS = 0x10
|
||||
|
||||
CMD_F_FCLOSE = 0xCE;
|
||||
CMD_F_FOPN = 0xC9
|
||||
CMD_F_FWR = 0xCC
|
||||
CMD_RTC_GET = 0x14;
|
||||
CMD_STATUS = 0x10
|
||||
|
||||
|
||||
def initialize
|
||||
@everdrive = EverdriveIO.new(VENDOR, PRODUCT)
|
||||
p status_ok?
|
||||
end
|
||||
|
||||
def inspect
|
||||
"#<#{self.class.name}: #{@everdrive.inspect}>"
|
||||
end
|
||||
|
||||
def status_ok?
|
||||
everdrive.write(make_command(CMD_STATUS))
|
||||
everdrive.read_u16 == STATUS_OK
|
||||
end
|
||||
|
||||
def get_realtime_clock
|
||||
everdrive.write(make_command(CMD_RTC_GET))
|
||||
rtc = everdrive.read(6)
|
||||
|
||||
ary = rtc.split('').map{|c| ('%x' % c.ord).to_i }
|
||||
DateTime.new(ary[0] + 2000, ary[1], ary[2], ary[3], ary[4], ary[5])
|
||||
end
|
||||
|
||||
def test_write_file
|
||||
filename = '000-test.nes'
|
||||
File.open(filename, 'rb') do |fp|
|
||||
contents = fp.read
|
||||
p file_open(filename, FAT_OPEN_ALWAYS | FAT_WRITE)
|
||||
p file_write(contents, 0, contents.length)
|
||||
p file_close
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :everdrive
|
||||
|
||||
def file_open(filename, mode)
|
||||
puts 'file_open'
|
||||
everdrive.write(make_command(CMD_F_FOPN))
|
||||
everdrive.write_u8(mode)
|
||||
everdrive.write_string('000-test.nes')
|
||||
status_ok?
|
||||
end
|
||||
|
||||
def file_write(data, notsure, length)
|
||||
puts 'file_write'
|
||||
everdrive.write(make_command(CMD_F_FWR))
|
||||
everdrive.write_u32(data.length)
|
||||
everdrive.write(data)
|
||||
# other stuff txdataack instead, pay attention to blocksizes
|
||||
status_ok?
|
||||
end
|
||||
|
||||
def file_close
|
||||
puts 'file_close'
|
||||
everdrive.write(make_command(CMD_F_FCLOSE))
|
||||
status_ok?
|
||||
end
|
||||
|
||||
def make_command(command_code)
|
||||
data = ['+', '+'.ord ^ 0xff, command_code, command_code ^ 0xff].map { |b| (b.ord & 0xff).chr }.join
|
||||
end
|
||||
end
|
||||
|
||||
everdrive = Everdrive.new
|
||||
p everdrive.get_realtime_clock
|
||||
# p everdrive.test_write_file
|
Loading…
x
Reference in New Issue
Block a user