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 +4 -4
- data/README.md +2 -2
- data/lib/z80_disassembler.rb +93 -35
- data/lib/z80_disassembler/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1978d7b54f457019351da2f76221d0f10d2670af3daef7584fe0b5ed1b2fbca1
|
|
4
|
+
data.tar.gz: bdfb0bd39eb724dbffd4958bfe27ccf814e472ebcbab22376cca2c09fedda7af
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
|
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
|
|
data/lib/z80_disassembler.rb
CHANGED
|
@@ -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(
|
|
28
|
-
@
|
|
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
|
-
|
|
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
|
-
|
|
40
|
-
|
|
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 << [
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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
|
|
56
|
-
|
|
57
|
-
|
|
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
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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}"
|
|
137
|
-
when 3 then calc_bytes(->(a, b){ "JR ##{b}"
|
|
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}
|
|
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
|
|
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
|
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.
|
|
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-
|
|
11
|
+
date: 2021-06-16 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description:
|
|
14
14
|
email:
|