z80_disassembler 0.2.2 → 0.2.7

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: 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: