z80_disassembler 0.2.1 → 0.2.6

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: d89919a8e31426ffe53e01448701e22a11015ee15a2a750d294e6cc2b1d23b66
4
- data.tar.gz: 6fcb81e94bb2b94b8fffb5420585a6031445b12f8d05e59c632d20cc367f61ad
3
+ metadata.gz: aec8c298c96f675474f4497b21dcaa30916ee84d4d9497cb9955077492a82c8b
4
+ data.tar.gz: 743c39db53d628947ecb3ee2e2975429148502f9423a72ff1f932463d597607e
5
5
  SHA512:
6
- metadata.gz: a214c2d6f7d70af405911cd305a2213a327f00d33ace63e88c5a30d16bcfea243e6ff5f0a4175af176a7407514195a8ef9e97a5a240bb9a27d590ffae88d9669
7
- data.tar.gz: eb2dd90529f337f516691e5eacfcab0a619565baf008f4cfacb1b69a157a0edbb9e5e59eb0f7ec5e01da03a691d1c2d4a885f6caec8a1654fff4425b80611241
6
+ metadata.gz: ecfb066e24b951e0dc21faedc8943183f60bc0c4e1fe22ac865d47ba3ffcf25a95ecceda7a1f01beb7d2f2ba14c588c513c51bb7e939d3b341cf6df0a352d2da
7
+ data.tar.gz: 9be12ff8b4614e4c47fe6342f38d149b92a9a49d9bc09dea4d098435f34bd80b5d283cc809bce2ea4a7a84d0330f90b7e7013d541374cc5a909e8c4b9e2c8d64
data/README.md CHANGED
@@ -27,10 +27,10 @@ Or install it yourself as:
27
27
 
28
28
  - example: parse.C >> parse.C.txt and compare with parse.txt
29
29
  ```ruby
30
- Z80Disassembler::Disassembler.new(params[:file], 32768).start
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 " LD IX,link_1 ; #621A / 25114 ; DD 21 00 63 ; ! c ;\n"
31
33
  ```
32
- return hash { 32768=>["#8000", "PUSH IY", "fd e5"], 32770=>[...], ... }
33
-
34
34
  ## Development
35
35
 
36
36
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -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,133 @@ 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
- str = case @prefix
38
- when 'cb' then @prefix = nil; cb_prefix
39
- when 'ed' then @prefix = nil; ed_prefix
40
- when 'dd' then @xx = 'IX'; xx_prefix(byte)
41
- when 'fd' then @xx = 'IY'; xx_prefix(byte)
42
- when 'xx' then temp = @temp; @temp = nil; displacement(byte, temp)
43
- when 2 then @prefix -= 1; @temp = byte.to_s(16).rjust(2, '0').upcase; nil
44
- when 1
45
- resp = @lambda.call(@arg, byte.to_s(16).rjust(2, '0').upcase)
46
- @prefix = nil; temp = @temp; @temp = nil
47
- if temp && resp.include?(')')
48
- resp = @xx ? displacement(temp.hex, resp) : resp.sub(')', "#{temp})").sub('(', '(#')
49
- elsif temp
50
- resp += temp
51
- end
52
- resp = hl_to_xx(resp, @xx) unless @xx.nil?
53
- @xx = nil
54
- resp
55
- else command
56
- end
53
+ str = command_from_byte(byte)
57
54
  @prev = byte.to_s(16)
58
- @ascii << ((32..126).include?(byte) ? ASCII[byte - 32] : '_')
59
- @bytes << @prev.rjust(2, '0').upcase
55
+ ascii << ((32..126).include?(byte) ? ASCII[byte - 32] : ' ')
56
+ bytes << @prev.rjust(2, '0').upcase
60
57
  next unless str
61
58
 
62
- @result[@addr] = ["##{@addr.to_s(16)}".upcase, str, @bytes.join(' '), @ascii.join]
63
- @addr += @bytes.size
64
- @bytes = []
65
- @ascii = []
59
+ @result << [addr, "##{addr.to_s(16)}".upcase, str, bytes.join(' '), ascii.join]
60
+ addr += bytes.size
61
+ bytes = []
62
+ ascii = []
66
63
  end
67
64
  @result
68
65
  end
69
66
 
67
+ def text
68
+ hash_links = {}
69
+ del_links = []
70
+ link_num = 0
71
+ int_addrs = @org..(@org + @file_size)
72
+ @result.select { |z| z[2] =~ /#[0-F]{4}/ && int_addrs.include?(z[2].split('#').last[0..3].hex) }.each do |x|
73
+ z = "##{x[2].split('#').last[0..3]}"
74
+ hash_links[z] = "link_#{link_num += 1}" unless hash_links[z]
75
+ end
76
+ @result.select { |z| z[2] =~ /\$/ }.each do |x|
77
+ z = "##{ (x[0] + x[2].split('$').last.to_i).to_s(16).upcase }"
78
+ hash_links[z] = "link_#{link_num += 1}" unless hash_links[z]
79
+ end
80
+ code = @result.map do |addr, addr16, str, bytes, ascii|
81
+ del_links << hash_links[addr16] if hash_links[addr16]
82
+ link = (hash_links[addr16] ? (hash_links[addr16] + ':') : '').ljust(16, ' ')
83
+ substr, adr = if str.include?('$')
84
+ ["$#{str.split('$').last}", "##{(addr + str.split('$').last.to_i).to_s(16).upcase}"]
85
+ else
86
+ adr = "##{str.split('#').last[0..3]}"
87
+ [adr, adr]
88
+ end
89
+ string = hash_links.keys.include?(adr) ? str.sub(substr, hash_links[adr]) : str
90
+
91
+ "#{link} #{string.ljust(16, ' ')}; #{addr16.ljust(5, ' ')} / #{addr.to_s.ljust(5, ' ')} ; #{bytes.ljust(14, ' ')} ; #{ascii.ljust(4, ' ')} ;"
92
+ end.join("\n")
93
+
94
+ header = [
95
+ ";--- #{Date.today} --- https://rmda.su ",
96
+ '; _______ _/| __ ______ ____ ',
97
+ '; / __ // |/ \\\\ _ \ / \ ',
98
+ '; / _/ _// \\\\ \\\\ \\\\ \ \ ',
99
+ '; \___\ \\\\___\/___//______//__/\__\ ',
100
+ '; \__/ ',
101
+ ";--- size: #{@file_size} --- filename: #{@file_name} "
102
+ ]
103
+ [
104
+ *header,
105
+ ' device zxspectrum48',
106
+ ' ORG #' + @org.to_s(16),
107
+ hash_links.map { |key, val| "#{val.ljust(16, ' ')} equ #{key}" unless del_links.include?(val) }.compact.join("\n"),
108
+ 'begin:',
109
+ code,
110
+ 'end:',
111
+ ' savesna "disasm.sna", begin',
112
+ ' savebin "disasm.C", begin, end - begin',
113
+ ''
114
+ ].join("\n")
115
+ end
116
+
70
117
  private
71
118
 
119
+ def bytes_to_int(array)
120
+ array.bytes.reverse.map { |x| x.to_s(16).rjust(2, "0") }.join.hex
121
+ end
122
+
123
+ def command_from_byte(byte)
124
+ case @prefix
125
+ when 'cb' then @prefix = nil; cb_prefix
126
+ when 'ed' then @prefix = nil; ed_prefix
127
+ when 'dd' then @xx = 'IX'; xx_prefix(byte)
128
+ when 'fd' then @xx = 'IY'; xx_prefix(byte)
129
+ when 'xx' then temp = @temp; @temp = nil; displacement(byte, temp)
130
+ when 2 then @prefix -= 1; @temp = byte.to_s(16).rjust(2, '0').upcase; nil
131
+ when 1
132
+ resp = @lambda.call(@arg, byte.to_s(16).rjust(2, '0').upcase)
133
+ @prefix = nil; temp = @temp; @temp = nil
134
+ if temp && resp.include?('(HL)')
135
+ resp += temp
136
+ elsif temp && resp.include?(')')
137
+ # resp = @xx ? displacement(temp.hex, resp) :
138
+ resp = resp.sub(')', "#{temp})").sub('(', '(#')
139
+ elsif temp
140
+ resp += temp
141
+ end
142
+ resp = hl_to_xx(resp, @xx) unless @xx.nil?
143
+ if resp.include?('JR') || resp.include?('DJNZ')
144
+ z = resp.split('#')
145
+ z[1] = z[1].hex < 127 ? "$+#{z[1].hex + 2}" : "$-#{255 - z[1].hex - 1}"
146
+ resp = z.join
147
+ end
148
+ resp
149
+ else command
150
+ end
151
+ end
152
+
72
153
  def hl_to_xx(temp, reg)
154
+ @xx = nil
73
155
  if temp.include?('HL')
74
156
  temp.sub('HL', reg)
75
157
  elsif temp.include?(' L')
@@ -88,7 +170,7 @@ module Z80Disassembler
88
170
  def displacement(byte, temp)
89
171
  @prefix = nil
90
172
  byte -= 256 if byte > 127
91
- des = ['', "+#{byte.to_s(16)}", byte.to_s(16)][byte <=> 0]
173
+ des = ['', "+#{byte.to_s}", byte.to_s][byte <=> 0]
92
174
  temp.sub('HL', @xx + des)
93
175
  end
94
176
 
@@ -109,8 +191,8 @@ module Z80Disassembler
109
191
  case @y
110
192
  when 0 then 'NOP'
111
193
  when 1 then 'EX AF, AF\''
112
- when 2 then calc_bytes(->(a, b){ "DJNZ ##{b}" }, nil, 1)
113
- when 3 then calc_bytes(->(a, b){ "JR ##{b}" }, nil, 1)
194
+ when 2 then calc_bytes(->(a, b){ "DJNZ ##{b}" }, nil, 1)
195
+ when 3 then calc_bytes(->(a, b){ "JR ##{b}" }, nil, 1)
114
196
  else calc_bytes(->(a, b){ "JR #{a},##{b}" }, T_CC[@y - 4], 1)
115
197
  end
116
198
  when 1 then @q ? "ADD HL,#{T_RP[@p]}" : calc_bytes(->(a, b){ "LD #{a},##{b}" }, T_RP[@p], 2)
@@ -173,8 +255,8 @@ module Z80Disassembler
173
255
  if @temp&.include?('(')
174
256
  @prefix = 'xx'; nil
175
257
  elsif ['dd', 'fd'].include?(@prev) && @temp
176
- temp = @temp; @temp = nil; @prefix = nil; xx = @xx; @xx = nil
177
- hl_to_xx(temp, xx)
258
+ temp = @temp; @temp = nil; @prefix = nil
259
+ hl_to_xx(temp, @xx)
178
260
  elsif @lambda && !@arg&.include?('HL')
179
261
  @prefix = 1; @temp
180
262
  else
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Z80Disassembler
4
- VERSION = '0.2.1'
4
+ VERSION = '0.2.6'
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.1
4
+ version: 0.2.6
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-05 00:00:00.000000000 Z
11
+ date: 2021-06-12 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email: