z80_disassembler 0.3.1 → 0.3.6
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|