z80_disassembler 0.3.1 → 0.3.6
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 +11 -7
- data/lib/z80_disassembler.rb +66 -61
- 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: 5823cf66cb0d52c7313ddb8659a0bda9b44c06569feaea6043af3b5481ca8025
|
4
|
+
data.tar.gz: 291863116b95b7397b901bb17ff66a15ab2ca2b0ac8148ad92cae57acf1ce7ba
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c15db9eb11f397f32d2fa27b86370baae9d3ec1726a73d5d472fd5b56c33e9dc85b3fbb5e5182ee38a254e981a60d767517c847f69fc75a9a374213f46891c93
|
7
|
+
data.tar.gz: 7a1ea4f6b42f360eac3e7ba9b6492b9857597bcbc92bbda9b392cf74979e27afbda9e1f0a6ff543e1c064bc627de5d0ed41fda750da5d29a1ac4a8d8269d8c8b
|
data/README.md
CHANGED
@@ -20,16 +20,20 @@ Or install it yourself as:
|
|
20
20
|
|
21
21
|
## Usage
|
22
22
|
|
23
|
-
|
24
|
-
```bash
|
25
|
-
sjasmplus parse.asm
|
26
|
-
```
|
23
|
+
* Example: zxn.ru/disasm - DEMO button
|
27
24
|
|
28
|
-
- example: parse.C >> parse.C.txt and compare with parse.txt
|
29
25
|
```ruby
|
30
26
|
z = Z80Disassembler::Disassembler.new(params[:file], 32768)
|
31
|
-
z.start
|
32
|
-
z.
|
27
|
+
text = z.start
|
28
|
+
z.file_size
|
29
|
+
z.org
|
30
|
+
file_name = 'tmp/disasm'
|
31
|
+
file = Tempfile.new(file_name)
|
32
|
+
file.write(text)
|
33
|
+
file.write(Z80Disassembler::Disassembler.compile_text(file_name))
|
34
|
+
file.close
|
35
|
+
compiled = system "sjasmplus --nologo #{file.path} 2> #{file_name}.log"
|
36
|
+
logs = File.open("#{file_name}.log").read.split("\n")
|
33
37
|
```
|
34
38
|
## Development
|
35
39
|
|
data/lib/z80_disassembler.rb
CHANGED
@@ -6,7 +6,7 @@ module Z80Disassembler
|
|
6
6
|
class Error < StandardError; end
|
7
7
|
|
8
8
|
class Disassembler
|
9
|
-
attr_reader :org, :file_size
|
9
|
+
attr_reader :org, :file_size, :rmda
|
10
10
|
|
11
11
|
# 0 1 2 3 4 5 6 7
|
12
12
|
T_R = [ 'B', 'C', 'D', 'E', 'H', 'L', '(HL)', 'A'].freeze
|
@@ -42,10 +42,22 @@ module Z80Disassembler
|
|
42
42
|
@code ||= File.open(@file).read.bytes
|
43
43
|
@file_size ||= @file.size
|
44
44
|
@x = 0; @y = 0; @z = 0; @p = 0; @q = 0; @xx = nil
|
45
|
-
@lambda = nil; @prefix = nil; @prev = nil
|
45
|
+
@lambda = nil; @prefix = nil; @prev = nil
|
46
|
+
@hash_links = {}; @del_links = []
|
47
|
+
@rmda = """
|
48
|
+
;--- #{Date.today} --- https://rmda.su
|
49
|
+
; _______ _/| __ ______ ____
|
50
|
+
; / __ // |/ \\\\ _ \\ / \\
|
51
|
+
; / _/ _// \\\\ \\\\ \\\\ \\ \\
|
52
|
+
; \\___\\ \\\\___\\/___//______//__/\\__\\
|
53
|
+
; \\__/
|
54
|
+
;--- size: #{@file_size}b #{"--- filename: #{@file_name}" if @file_name}
|
55
|
+
|
56
|
+
"""
|
46
57
|
end
|
47
58
|
|
48
59
|
def start
|
60
|
+
result = []
|
49
61
|
addr = @org
|
50
62
|
bytes = []; ascii = []
|
51
63
|
@code.each do |byte|
|
@@ -56,58 +68,51 @@ module Z80Disassembler
|
|
56
68
|
bytes << @prev.rjust(2, '0').upcase
|
57
69
|
next unless str
|
58
70
|
|
59
|
-
|
71
|
+
result << [addr, "##{addr.to_s(16)}".upcase, str, bytes.join(' '), ascii.join]
|
60
72
|
addr += bytes.size
|
61
73
|
bytes = []
|
62
74
|
ascii = []
|
63
75
|
end
|
64
|
-
@result
|
65
|
-
end
|
66
76
|
|
67
|
-
def text
|
68
|
-
hash_links = {}
|
69
|
-
del_links = []
|
70
77
|
link_num = 0
|
71
78
|
int_addrs = @org..(@org + @file_size)
|
72
|
-
|
79
|
+
result.select { |z| z[2] =~ /#[0-F]{4}/ && int_addrs.include?(z[2].split('#').last[0..3].hex) }.each do |x|
|
73
80
|
z = "##{x[2].split('#').last[0..3]}"
|
74
|
-
hash_links[z] = "link_#{link_num += 1}" unless hash_links[z]
|
81
|
+
@hash_links[z] = "link_#{link_num += 1}" unless @hash_links[z]
|
75
82
|
end
|
76
|
-
|
83
|
+
result.select { |z| z[2] =~ /\$/ }.each do |x|
|
77
84
|
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]
|
85
|
+
@hash_links[z] = "link_#{link_num += 1}" unless @hash_links[z]
|
79
86
|
end
|
80
|
-
code =
|
81
|
-
del_links << hash_links[addr16] if hash_links[addr16]
|
82
|
-
link = (hash_links[addr16] ? (hash_links[addr16] + ':') : '').ljust(16, ' ')
|
87
|
+
code = result.map do |addr_, addr16, str, bytes_, ascii_|
|
88
|
+
@del_links << @hash_links[addr16] if @hash_links[addr16]
|
89
|
+
link = (@hash_links[addr16] ? (@hash_links[addr16] + ':') : '').ljust(16, ' ')
|
83
90
|
substr, adr = if str.include?('$')
|
84
|
-
["$#{str.split('$').last}", "##{(
|
91
|
+
["$#{str.split('$').last}", "##{(addr_ + str.split('$').last.to_i).to_s(16).upcase}"]
|
85
92
|
else
|
86
93
|
adr = "##{str.split('#').last[0..3]}"
|
87
94
|
[adr, adr]
|
88
95
|
end
|
89
|
-
string = hash_links.keys.include?(adr) ? str.sub(substr, hash_links[adr]) : str
|
96
|
+
string = @hash_links.keys.include?(adr) ? str.sub(substr, @hash_links[adr]) : str
|
90
97
|
|
91
|
-
|
98
|
+
defb = bytes_.split(" ").map { |x| "##{x}"}.join(",")
|
99
|
+
"#{link} #{string.ljust(16, ' ')}; #{addr16.ljust(5, ' ')} / #{addr_.to_s.ljust(5, ' ')} ; #{ascii_.ljust(4, ' ')} ; #{defb}"
|
92
100
|
end.join("\n")
|
101
|
+
[
|
102
|
+
@rmda,
|
103
|
+
' device zxspectrum128',
|
104
|
+
' ORG #' + @org.to_s(16),
|
105
|
+
@hash_links.map { |key, val| "#{(val + ':').ljust(16, ' ')} EQU #{key}" unless @del_links.include?(val) }.compact.join("\n"),
|
106
|
+
'begin:',
|
107
|
+
code,
|
108
|
+
'end:',
|
109
|
+
''
|
110
|
+
].join("\n")
|
111
|
+
end
|
93
112
|
|
94
|
-
|
95
|
-
|
96
|
-
'; _______ _/| __ ______ ____ ',
|
97
|
-
'; / __ // |/ \\\\ _ \ / \ ',
|
98
|
-
'; / _/ _// \\\\ \\\\ \\\\ \ \ ',
|
99
|
-
'; \___\ \\\\___\/___//______//__/\__\ ',
|
100
|
-
'; \__/ ',
|
101
|
-
";--- size: #{@file_size} --- filename: #{@file_name} "
|
102
|
-
]
|
113
|
+
def self.compile_text(file_name)
|
114
|
+
name = file_name.split('/').last
|
103
115
|
[
|
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
116
|
'length equ end - begin',
|
112
117
|
'CODE = #AF',
|
113
118
|
'USR = #C0',
|
@@ -115,29 +120,28 @@ module Z80Disassembler
|
|
115
120
|
'CLEAR = #FD',
|
116
121
|
'RANDOMIZE = #F9',
|
117
122
|
' org #5C00',
|
118
|
-
'baszac
|
119
|
-
' dw linlen',
|
120
|
-
'linzac',
|
121
|
-
' db CLEAR, "8", #0E, 0, 0',
|
123
|
+
'baszac db 0,1', # Line number
|
124
|
+
' dw linlen', # Line length
|
125
|
+
'linzac db CLEAR, "8", #0E, 0, 0',
|
122
126
|
' dw begin - 1',
|
123
127
|
' db 0, ":"',
|
124
128
|
' db LOAD, "\""',
|
125
|
-
'codnam
|
129
|
+
'codnam ds 10, 32',
|
126
130
|
' org codnam',
|
127
131
|
' db "disasm"',
|
128
132
|
' org codnam + 10',
|
129
133
|
' db "\"", CODE, ":"',
|
130
134
|
' db RANDOMIZE, USR, "8", #0E, 0, 0',
|
131
|
-
' dw begin',
|
135
|
+
' dw begin', # call address
|
132
136
|
' db 0, #0D',
|
133
137
|
'linlen = $ - linzac',
|
134
138
|
'baslen = $ - baszac',
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
139
|
+
" emptytap '#{file_name}.tap'",
|
140
|
+
" savetap '#{file_name}.tap', BASIC, '#{name}', baszac, baslen, 1",
|
141
|
+
" savetap '#{file_name}.tap', CODE, '#{name}', begin, length, begin",
|
142
|
+
" savesna '#{file_name}.sna', begin",
|
143
|
+
" savebin '#{file_name}.bin', begin, length",
|
144
|
+
" savehob '#{file_name}.$C', '#{file_name}.bin', begin, length",
|
141
145
|
''
|
142
146
|
].join("\n")
|
143
147
|
end
|
@@ -145,13 +149,13 @@ module Z80Disassembler
|
|
145
149
|
private
|
146
150
|
|
147
151
|
def bytes_to_int(array)
|
148
|
-
array.bytes.reverse.map { |x| x.to_s(16).rjust(2,
|
152
|
+
array.bytes.reverse.map { |x| x.to_s(16).rjust(2, '0') }.join.hex
|
149
153
|
end
|
150
154
|
|
151
155
|
def command_from_byte(byte)
|
152
156
|
case @prefix
|
153
157
|
when 'cb' then @prefix = nil; cb_prefix
|
154
|
-
when 'ed' then @prefix = nil; ed_prefix
|
158
|
+
when 'ed' then @prefix = nil; ed_prefix(byte)
|
155
159
|
when 'dd' then @xx = 'IX'; xx_prefix(byte)
|
156
160
|
when 'fd' then @xx = 'IY'; xx_prefix(byte)
|
157
161
|
when 'xx' then temp = @temp; @temp = nil; displacement(byte, temp)
|
@@ -167,7 +171,7 @@ module Z80Disassembler
|
|
167
171
|
elsif temp
|
168
172
|
resp += temp
|
169
173
|
end
|
170
|
-
resp = hl_to_xx(resp
|
174
|
+
resp = hl_to_xx(resp) unless @xx.nil?
|
171
175
|
if resp.include?('JR') || resp.include?('DJNZ')
|
172
176
|
z = resp.split('#')
|
173
177
|
z[1] = z[1].hex < 127 ? "$+#{z[1].hex + 2}" : "$-#{255 - z[1].hex - 1}"
|
@@ -178,21 +182,22 @@ module Z80Disassembler
|
|
178
182
|
end
|
179
183
|
end
|
180
184
|
|
181
|
-
def hl_to_xx(temp
|
182
|
-
|
183
|
-
|
184
|
-
temp.sub('HL', reg)
|
185
|
+
def hl_to_xx(temp)
|
186
|
+
resp = if temp.include?('HL')
|
187
|
+
temp.sub('HL', @xx)
|
185
188
|
elsif temp.include?(' L')
|
186
|
-
temp.sub(' L', " #{
|
189
|
+
temp.sub(' L', " #{@xx}L")
|
187
190
|
elsif temp.include?(',L')
|
188
|
-
temp.sub(',L', ",#{
|
191
|
+
temp.sub(',L', ",#{@xx}L")
|
189
192
|
elsif temp.include?(' H')
|
190
|
-
temp.sub(' H', " #{
|
193
|
+
temp.sub(' H', " #{@xx}H")
|
191
194
|
elsif temp.include?(',H')
|
192
|
-
temp.sub(',H', ",#{
|
195
|
+
temp.sub(',H', ",#{@xx}H")
|
193
196
|
else
|
194
|
-
temp
|
197
|
+
@xx ? "DB ##{@xx == 'IX' ? 'DD' : 'FD'} ;\n#{''.ljust(16, ' ')} #{temp.ljust(16, ' ')}" : temp
|
195
198
|
end
|
199
|
+
@xx = nil
|
200
|
+
resp
|
196
201
|
end
|
197
202
|
|
198
203
|
def displacement(byte, temp)
|
@@ -284,7 +289,7 @@ module Z80Disassembler
|
|
284
289
|
@prefix = 'xx'; nil
|
285
290
|
elsif ['dd', 'fd'].include?(@prev) && @temp
|
286
291
|
temp = @temp; @temp = nil; @prefix = nil
|
287
|
-
hl_to_xx(temp
|
292
|
+
hl_to_xx(temp)
|
288
293
|
elsif @lambda && !@arg&.include?('HL')
|
289
294
|
@prefix = 1; @temp
|
290
295
|
else
|
@@ -296,7 +301,7 @@ module Z80Disassembler
|
|
296
301
|
["#{T_ROT[@y]} ", "BIT #{@y},", "RES #{@y},", "SET #{@y},"][@x] + T_R[@z]
|
297
302
|
end
|
298
303
|
|
299
|
-
def ed_prefix
|
304
|
+
def ed_prefix(byte)
|
300
305
|
if @x == 1
|
301
306
|
case @z
|
302
307
|
when 0 then "IN #{"#{T_R[@y]}," if @y != 6}(C)"
|
@@ -311,7 +316,7 @@ module Z80Disassembler
|
|
311
316
|
elsif @x == 2 && @z <= 3 && @y >= 4
|
312
317
|
[['LDI','CPI','INI','OUTI'],['LDD','CPD','IND','OUTD'],['LDIR','CPIR','INIR','OTIR'],['LDDR','CPDR','INDR','OTDR']][@y - 4][@z]
|
313
318
|
else
|
314
|
-
'
|
319
|
+
"#{'DB #ED'}, ##{byte.to_s(16).rjust(2, '0').upcase}"
|
315
320
|
end
|
316
321
|
end
|
317
322
|
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.3.
|
4
|
+
version: 0.3.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-
|
11
|
+
date: 2021-07-12 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description:
|
14
14
|
email:
|