z80_disassembler 0.2.2 → 0.2.7

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6d345233ff0d5429ba5c05cdb82c304de2ef46b6ebe7761bda8b805c986c85e2
4
- data.tar.gz: e43f8bf8fd592ec156d5bb6c942e6847691e853701a65e2b0afdaffd827c626e
3
+ metadata.gz: 1978d7b54f457019351da2f76221d0f10d2670af3daef7584fe0b5ed1b2fbca1
4
+ data.tar.gz: bdfb0bd39eb724dbffd4958bfe27ccf814e472ebcbab22376cca2c09fedda7af
5
5
  SHA512:
6
- metadata.gz: 991885755e9d4fbe5128b6b81fdb5e4804d6921850acbf9e07bc8c0c66fb290d293ea32be1fc56c1a9da06d55a64d4100b2558f488999812ba832d9a8ab2434c
7
- data.tar.gz: db4bdd7cb73f1ba8bdf430c54578f02f1a74ca5de3373bf2b1e4dda855b400652fa0604ca6e1e7cd1b3b0a228f0f4aa79ffb22e9d1d4116c6a0663d625c73bc7
6
+ metadata.gz: c843df467fc7bbc7bdc8a58806ea8eebbef00aad80e1ec5901d07c0ea0b2aaf7c7c7353a22b406e1a1fe3c74a057ba75529bf7dda114e4fe96003023d352dbde
7
+ data.tar.gz: 609ada4bff4bb488015456b9134693c8d5426db2e575e6166bbb7ff9d72b820d086b3eac98ddc642b3dc3479c4c889fadc3de815805207a09efa6c25020e497a
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,101 @@ 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
56
- 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}" }
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
+ ]
58
103
  [
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")
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")
69
115
  end
70
116
 
71
117
  private
72
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
+
73
123
  def command_from_byte(byte)
74
124
  case @prefix
75
125
  when 'cb' then @prefix = nil; cb_prefix
@@ -81,19 +131,27 @@ module Z80Disassembler
81
131
  when 1
82
132
  resp = @lambda.call(@arg, byte.to_s(16).rjust(2, '0').upcase)
83
133
  @prefix = nil; temp = @temp; @temp = nil
84
- if temp && resp.include?(')')
85
- resp = @xx ? displacement(temp.hex, resp) : resp.sub(')', "#{temp})").sub('(', '(#')
134
+ if temp && resp.include?('(HL)')
135
+ @xx ? resp = displacement(temp.hex, resp) : resp += temp
136
+ elsif temp && resp.include?(')')
137
+ # resp = displacement(temp.hex, resp) if @xx
138
+ resp = resp.sub(')', "#{temp})").sub('(', '(#')
86
139
  elsif temp
87
140
  resp += temp
88
141
  end
89
142
  resp = hl_to_xx(resp, @xx) unless @xx.nil?
90
- @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
91
148
  resp
92
149
  else command
93
150
  end
94
151
  end
95
152
 
96
153
  def hl_to_xx(temp, reg)
154
+ @xx = nil
97
155
  if temp.include?('HL')
98
156
  temp.sub('HL', reg)
99
157
  elsif temp.include?(' L')
@@ -112,7 +170,7 @@ module Z80Disassembler
112
170
  def displacement(byte, temp)
113
171
  @prefix = nil
114
172
  byte -= 256 if byte > 127
115
- des = ['', "+#{byte.to_s(16)}", byte.to_s(16)][byte <=> 0]
173
+ des = ['+0', "+#{byte}", byte.to_s][byte <=> 0]
116
174
  temp.sub('HL', @xx + des)
117
175
  end
118
176
 
@@ -133,8 +191,8 @@ module Z80Disassembler
133
191
  case @y
134
192
  when 0 then 'NOP'
135
193
  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)
194
+ when 2 then calc_bytes(->(a, b){ "DJNZ ##{b}" }, nil, 1)
195
+ when 3 then calc_bytes(->(a, b){ "JR ##{b}" }, nil, 1)
138
196
  else calc_bytes(->(a, b){ "JR #{a},##{b}" }, T_CC[@y - 4], 1)
139
197
  end
140
198
  when 1 then @q ? "ADD HL,#{T_RP[@p]}" : calc_bytes(->(a, b){ "LD #{a},##{b}" }, T_RP[@p], 2)
@@ -158,7 +216,7 @@ module Z80Disassembler
158
216
  case @z
159
217
  when 0 then "RET #{T_CC[@y]}"
160
218
  when 1 then @q ? ['RET','EXX','JP HL','LD SP, HL'][@p] : "POP #{T_RP2[@p]}"
161
- when 2 then calc_bytes(->(a, b){ "JP #{a},#{b}" }, T_CC[@y], 2)
219
+ when 2 then calc_bytes(->(a, b){ "JP #{a},##{b}" }, T_CC[@y], 2)
162
220
  when 3
163
221
  case @y
164
222
  when 0 then calc_bytes(->(a, b){ "JP ##{b}" }, nil, 2)
@@ -197,8 +255,8 @@ module Z80Disassembler
197
255
  if @temp&.include?('(')
198
256
  @prefix = 'xx'; nil
199
257
  elsif ['dd', 'fd'].include?(@prev) && @temp
200
- temp = @temp; @temp = nil; @prefix = nil; xx = @xx; @xx = nil
201
- hl_to_xx(temp, xx)
258
+ temp = @temp; @temp = nil; @prefix = nil
259
+ hl_to_xx(temp, @xx)
202
260
  elsif @lambda && !@arg&.include?('HL')
203
261
  @prefix = 1; @temp
204
262
  else
@@ -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.7'
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.7
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-16 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email: