z80_disassembler 0.2.0 → 0.2.5

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: d7f95a1de1f1ce7c2d7f0f73cdc35d9cf01da5e9b013449a4e0afda390b52016
4
- data.tar.gz: 92691b15083cbefdd7ec726381041b5d0c297241e2e045e122d80cf38bb9f134
3
+ metadata.gz: 9970749ade07cf2808e1e6792d3c45f26d8325e6fc2fd492d6b3f88c4d843c40
4
+ data.tar.gz: ebbfd99ccff00c4e86e5a8e09e31774359c7798d13ed847c65d1b0e95ccf04e5
5
5
  SHA512:
6
- metadata.gz: c53a0786e539bffbb743b1a1048747b86419cb9b6f864a51427c06fd8081f9f5a7137de82b2e9158bac494b1d15c15ddfbe63b2f90e4b1a0e88010b4c0885b32
7
- data.tar.gz: 95538520de2115aa60e81e7549385b8ee0ca1fd916afb7d95d606b96ef26435418bdeedcefc1aaa32552435ebb2be1c3529a76327e71f973ca07c889fc35ed9f
6
+ metadata.gz: 8455ef820171b02eb4e886a7a37ef4dc43679c0c8bf4b777d9dc73e93732c4ec8899da13b4ea73d38f4704d5b8487ba42ab722cda462b11a7a33f7b46f68eefc
7
+ data.tar.gz: cecc4ee2168d08c0e1a373209f472cc78936f69e8f6ad067b04e9632e44c9d7291b3027215c5a6329d2226dfeb8a208b1aa28adb9c2ba6b56e400785f74e51c2
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 = 25108 # 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,9 +255,9 @@ 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)
178
- elsif @lambda && !@arg.include?('HL')
258
+ temp = @temp; @temp = nil; @prefix = nil
259
+ hl_to_xx(temp, @xx)
260
+ elsif @lambda && !@arg&.include?('HL')
179
261
  @prefix = 1; @temp
180
262
  else
181
263
  @prefix = 2; @temp
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Z80Disassembler
4
- VERSION = '0.2.0'
4
+ VERSION = '0.2.5'
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.0
4
+ version: 0.2.5
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-03 00:00:00.000000000 Z
11
+ date: 2021-06-12 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email:
@@ -30,7 +30,6 @@ files:
30
30
  - bin/setup
31
31
  - lib/z80_disassembler.rb
32
32
  - lib/z80_disassembler/version.rb
33
- - z80_disassembler-0.1.5.gem
34
33
  - z80_disassembler.gemspec
35
34
  homepage: ''
36
35
  licenses:
Binary file