z80_disassembler 0.2.2 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6d345233ff0d5429ba5c05cdb82c304de2ef46b6ebe7761bda8b805c986c85e2
4
- data.tar.gz: e43f8bf8fd592ec156d5bb6c942e6847691e853701a65e2b0afdaffd827c626e
3
+ metadata.gz: 7fda0599a6e835b5063fc6115dcdc364cfc895b2a7cbf1dba8f57965698526a5
4
+ data.tar.gz: 705361c3aa8d088e967411643e9774a1d1cbc169a9e7ce57d8ffa8087a833f68
5
5
  SHA512:
6
- metadata.gz: 991885755e9d4fbe5128b6b81fdb5e4804d6921850acbf9e07bc8c0c66fb290d293ea32be1fc56c1a9da06d55a64d4100b2558f488999812ba832d9a8ab2434c
7
- data.tar.gz: db4bdd7cb73f1ba8bdf430c54578f02f1a74ca5de3373bf2b1e4dda855b400652fa0604ca6e1e7cd1b3b0a228f0f4aa79ffb22e9d1d4116c6a0663d625c73bc7
6
+ metadata.gz: 6b2b887c58d4bf48e32094f9753e71520ff3b1c12d7d7ab46870c0179628005b3e13be8c191c0fd305e78004c3b2b630833536fceb77ff49f004ed19cb17b59e
7
+ data.tar.gz: cfd8680fc373ed1031ffd89af3ad8ff7c1cdb67f6fa5e5aa53f15b9f1d4e172c7c5983f14d62914f2baa3e0d49249472f744cb851b69770c546205e51f3c4b5e
data/README.md CHANGED
@@ -28,8 +28,8 @@ Or install it yourself as:
28
28
  - example: parse.C >> parse.C.txt and compare with parse.txt
29
29
  ```ruby
30
30
  z = Z80Disassembler::Disassembler.new(params[:file], 32768)
31
- z.start # return [25114, "#621A", "LD IX,#6300", "DD 21 00 63", " ! c"
32
- z.text # return asm text " LD IX,link_1 ; #621A / 25114 ; DD 21 00 63 ; ! c ;"
31
+ z.start # return [ [25114, "#621A", "LD IX,#6300", "DD 21 00 63", " ! c"], [...], ... ]
32
+ z.text # return " LD IX,link_1 ; #621A / 25114 ; DD 21 00 63 ; ! c ;\n"
33
33
  ```
34
34
  ## Development
35
35
 
@@ -6,6 +6,8 @@ module Z80Disassembler
6
6
  class Error < StandardError; end
7
7
 
8
8
  class Disassembler
9
+ attr_reader :org
10
+
9
11
  # 0 1 2 3 4 5 6 7
10
12
  T_R = [ 'B', 'C', 'D', 'E', 'H', 'L', '(HL)', 'A'].freeze
11
13
  T_CC = [ 'NZ', 'Z', 'NC', 'C', 'PO', 'PE', 'P', 'M'].freeze
@@ -14,7 +16,6 @@ module Z80Disassembler
14
16
  T_IM = [ '0', '0/1', '1', '2', '0', '0/1', '1', '2'].freeze
15
17
  T_RP = [ 'BC', 'DE', 'HL', 'SP'].freeze
16
18
  T_RP2 = [ 'BC', 'DE', 'HL', 'AF'].freeze
17
-
18
19
  ASCII = [
19
20
  ' ', '!', '"', '#', '$', '%', '&', "'", '(', ')', '*', '+', ',', '-', '.', '/',
20
21
  '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?',
@@ -24,52 +25,83 @@ module Z80Disassembler
24
25
  'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~'
25
26
  ].freeze
26
27
 
27
- def initialize(file_name, addr = 32_768)
28
- @file_name = file_name; @addr = addr.to_i
28
+ def initialize(file, org = 32_768)
29
+ @file = file; @org = org.to_i
30
+ if file.original_filename[-3..-1] == '.$C'
31
+ File.open(@file) do |f|
32
+ z = f.read(17)
33
+ @file_name = "#{z[0..7]}.#{z[8]}"
34
+ @org = bytes_to_int(z[ 9..10])
35
+ @file_size = bytes_to_int(z[11..12])
36
+ @sectors = bytes_to_int(z[13..14])
37
+ checksum1 = bytes_to_int(z[15..16])
38
+ checksum2 = (z[0..14].sum * 257 + 105).to_s(16)[-4..-1].hex
39
+ @code = f.read(@file_size).bytes if checksum1 == checksum2
40
+ end
41
+ end
42
+ @code ||= File.open(@file).read.bytes
43
+ @file_size ||= @file.size
29
44
  @x = 0; @y = 0; @z = 0; @p = 0; @q = 0; @xx = nil
30
- @lambda = nil; @prefix = nil; @prev = nil
31
- @bytes = []; @ascii = []; @result = []
45
+ @lambda = nil; @prefix = nil; @prev = nil; @result = []
32
46
  end
33
47
 
34
48
  def start
35
- File.open(@file_name).each_byte do |byte|
49
+ addr = @org
50
+ bytes = []; ascii = []
51
+ @code.each do |byte|
36
52
  load_vars(byte)
37
53
  str = command_from_byte(byte)
38
54
  @prev = byte.to_s(16)
39
- @ascii << ((32..126).include?(byte) ? ASCII[byte - 32] : ' ')
40
- @bytes << @prev.rjust(2, '0').upcase
55
+ ascii << ((32..126).include?(byte) ? ASCII[byte - 32] : ' ')
56
+ bytes << @prev.rjust(2, '0').upcase
41
57
  next unless str
42
58
 
43
- @result << [@addr, "##{@addr.to_s(16)}".upcase, str, @bytes.join(' '), @ascii.join]
44
- @addr += @bytes.size
45
- @bytes = []
46
- @ascii = []
59
+ @result << [addr, "##{addr.to_s(16)}".upcase, str, bytes.join(' '), ascii.join]
60
+ addr += bytes.size
61
+ bytes = []
62
+ ascii = []
47
63
  end
48
64
  @result
49
65
  end
50
66
 
51
67
  def text
52
- org = @addr - @file_name.size
53
68
  hash_links = {}
69
+ del_links = []
54
70
  link_num = 0
55
- int_addrs = org..@addr
71
+ int_addrs = @org..(@org + @file_size)
56
72
  with_links = @result.select { |z| z[2] =~ /#[0-F]{4}/ && int_addrs.include?(z[2].split('#').last[0..3].hex) }
57
- with_links.each { |x| hash_links["##{x[2].split('#').last[0..3]}"] = "link_#{link_num += 1}" }
73
+ with_links.each do |x|
74
+ z = "##{x[2].split('#').last[0..3]}"
75
+ hash_links[z] = "link_#{link_num += 1}" unless hash_links[z]
76
+ end
77
+
78
+ code = @result.map do |addr, addr16, str, bytes, ascii|
79
+ del_links << hash_links[addr16] if hash_links[addr16]
80
+ link = (hash_links[addr16] || '').ljust(16, ' ')
81
+ adr = '#' + str.split('#').last[0..3]
82
+ string = hash_links.keys.include?(adr) ? str.sub(adr, hash_links[adr]) : str
83
+ "#{link} #{string.ljust(16, ' ')}; #{addr16.ljust(5, ' ')} / #{addr.to_s.ljust(5, ' ')} ; #{bytes.ljust(14, ' ')} ; #{ascii.ljust(4, ' ')} ;"
84
+ end.join("\n")
85
+
58
86
  [
59
- " device zxspectrum48",
60
- " ORG #{org}",
61
- "begin_file:\n"
62
- ].join("\n") +
63
- @result.map do |addr, addr16, str, bytes, ascii|
64
- link = (hash_links[addr16] || '').ljust(16, ' ')
65
- adr = '#' + str.split('#').last[0..3]
66
- string = hash_links.keys.include?(adr) ? str.sub(adr, hash_links[adr]) : str
67
- "#{link} #{string.ljust(16, ' ')}; #{addr16.ljust(5, ' ')} / #{addr.to_s.ljust(5, ' ')} ; #{bytes.ljust(14, ' ')} ; #{ascii.ljust(4, ' ')} ;"
68
- end.join("\n")
87
+ ' device zxspectrum48',
88
+ ' ORG #' + @org.to_s(16),
89
+ hash_links.map { |key, val| "#{val.ljust(16, ' ')} equ #{key}" unless del_links.include?(val) }.compact.join("\n"),
90
+ 'begin:',
91
+ code,
92
+ 'end:',
93
+ ' savesna "disasm.sna", begin',
94
+ ' savebin "disasm.C", begin, end - begin',
95
+ ''
96
+ ].join("\n")
69
97
  end
70
98
 
71
99
  private
72
100
 
101
+ def bytes_to_int(array)
102
+ array.bytes.reverse.map { |x| x.to_s(16).rjust(2, "0") }.join.hex
103
+ end
104
+
73
105
  def command_from_byte(byte)
74
106
  case @prefix
75
107
  when 'cb' then @prefix = nil; cb_prefix
@@ -88,6 +120,11 @@ module Z80Disassembler
88
120
  end
89
121
  resp = hl_to_xx(resp, @xx) unless @xx.nil?
90
122
  @xx = nil
123
+ if resp.include?('JR') || resp.include?('DJNZ')
124
+ z = resp.split('#')
125
+ z[1] = z[1].hex < 127 ? "$+#{z[1].hex}" : "$-#{255 - z[1].hex}"
126
+ resp = z.join
127
+ end
91
128
  resp
92
129
  else command
93
130
  end
@@ -133,8 +170,8 @@ module Z80Disassembler
133
170
  case @y
134
171
  when 0 then 'NOP'
135
172
  when 1 then 'EX AF, AF\''
136
- when 2 then calc_bytes(->(a, b){ "DJNZ ##{b}" }, nil, 1)
137
- when 3 then calc_bytes(->(a, b){ "JR ##{b}" }, nil, 1)
173
+ when 2 then calc_bytes(->(a, b){ "DJNZ ##{b}" }, nil, 1)
174
+ when 3 then calc_bytes(->(a, b){ "JR ##{b}" }, nil, 1)
138
175
  else calc_bytes(->(a, b){ "JR #{a},##{b}" }, T_CC[@y - 4], 1)
139
176
  end
140
177
  when 1 then @q ? "ADD HL,#{T_RP[@p]}" : calc_bytes(->(a, b){ "LD #{a},##{b}" }, T_RP[@p], 2)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Z80Disassembler
4
- VERSION = '0.2.2'
4
+ VERSION = '0.2.3'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: z80_disassembler
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - dvitvitskiy
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-06-06 00:00:00.000000000 Z
11
+ date: 2021-06-07 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email: