resedit 1.3.1
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 +7 -0
- data/bin/resedit +11 -0
- data/lib/resedit.rb +17 -0
- data/lib/resedit/app/app.rb +160 -0
- data/lib/resedit/app/app_command.rb +100 -0
- data/lib/resedit/app/colorizer.rb +34 -0
- data/lib/resedit/app/font_convert.rb +54 -0
- data/lib/resedit/app/io_commands.rb +74 -0
- data/lib/resedit/app/mz_command.rb +192 -0
- data/lib/resedit/app/std_commands.rb +69 -0
- data/lib/resedit/app/text_convert.rb +60 -0
- data/lib/resedit/convert/bitconv.rb +48 -0
- data/lib/resedit/font/font.rb +82 -0
- data/lib/resedit/font/font_char.rb +49 -0
- data/lib/resedit/image/image.rb +47 -0
- data/lib/resedit/image/image_factory.rb +33 -0
- data/lib/resedit/image/png_image.rb +38 -0
- data/lib/resedit/mz/changeable.rb +248 -0
- data/lib/resedit/mz/hexwriter.rb +88 -0
- data/lib/resedit/mz/mz.rb +166 -0
- data/lib/resedit/mz/mz_body.rb +141 -0
- data/lib/resedit/mz/mz_header.rb +123 -0
- data/lib/resedit/mz/mzenv.rb +82 -0
- data/lib/resedit/text/conv_keybru.rb +84 -0
- data/lib/resedit/text/conv_table.rb +10 -0
- data/lib/resedit/text/escaper.rb +117 -0
- data/lib/resedit/text/format_text.rb +44 -0
- data/lib/resedit/text/format_xml.rb +46 -0
- data/lib/resedit/text/huffman.rb +190 -0
- data/lib/resedit/text/text.rb +73 -0
- metadata +86 -0
@@ -0,0 +1,192 @@
|
|
1
|
+
require 'resedit/app/app'
|
2
|
+
require 'resedit/app/app_command'
|
3
|
+
require 'resedit/mz/mz'
|
4
|
+
require 'resedit/mz/mzenv'
|
5
|
+
|
6
|
+
|
7
|
+
module Resedit
|
8
|
+
|
9
|
+
class MZCommand < AppCommand
|
10
|
+
def initialize
|
11
|
+
super(['mz'])
|
12
|
+
addParam('cmd', "mz command","")
|
13
|
+
addParam('p1', "mz command parameter","")
|
14
|
+
addParam('p2', "mz command parameter","")
|
15
|
+
addParam('p3', "mz command parameter","")
|
16
|
+
addParam('p4', "mz command parameter","")
|
17
|
+
addParam('p5', "mz command parameter","")
|
18
|
+
addOption('help', 'h', nil, 'help on mz commands')
|
19
|
+
@cmds = {
|
20
|
+
"help"=>[method(:help), "show help on mz commands", {"command" => "command to show help on"}],
|
21
|
+
"use"=>[method(:use), "select mz file", {"file" => "path to mz file"}],
|
22
|
+
"save"=>[method(:save), "save current file",{"filename" => "filename fir saving", "final"=>"don't save changes"}],
|
23
|
+
"close"=>[method(:close), "close file", {"file" => "path or id of file to close"}],
|
24
|
+
"print"=>[method(:info), "print info about mz objects", {"what" => "files/header/reloc/changes", "how" => "original/modified"}],
|
25
|
+
"append"=>[method(:append), "add bytes to current file", {"value" => "value", "type" => "value type", }],
|
26
|
+
"replace"=>[method(:replace), "replace added bytes", {"value" => "value", "type"=>"value type"}],
|
27
|
+
"change"=>[method(:change), "change bytes at offset", {"ofs" => "data ofset", "value" => "value", "disp" => "code/file", "type"=>"value type"}],
|
28
|
+
"revert"=>[method(:revert), "revert changes", {"ofs"=>"change offset/all"}],
|
29
|
+
"hex"=>[method(:hex), "print hex file", {"ofs" => "data offset", "size" => "data size", "how"=>"original/modified", "disp" => "code/file"}],
|
30
|
+
"dasm"=>[method(:dasm), "print disasm", {"ofs" => "data offset", "size" => "data size", "how"=>"original/modified"}],
|
31
|
+
}
|
32
|
+
@files = []
|
33
|
+
@cur = nil
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
def help(params)
|
38
|
+
if params['command']
|
39
|
+
raise "Unknown mz command: " + params['command'] if !@cmds[params['command']]
|
40
|
+
cmd = @cmds[params['command']]
|
41
|
+
puts(params['command'] + "\t-" + cmd[1])
|
42
|
+
if cmd[2]
|
43
|
+
puts
|
44
|
+
puts("params:")
|
45
|
+
cmd[2].each{|k,v|
|
46
|
+
puts k + "\t-" + v
|
47
|
+
}
|
48
|
+
end
|
49
|
+
else
|
50
|
+
puts("available mz commands:")
|
51
|
+
@cmds.each{|k,v|
|
52
|
+
puts k + "\t-" + v[1]
|
53
|
+
}
|
54
|
+
end
|
55
|
+
puts
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
def getfile(id)
|
60
|
+
return @cur if id == nil
|
61
|
+
i,res=MZEnv.instance.s2i_nt(id)
|
62
|
+
if res
|
63
|
+
raise "Bad file id: " + i.to_s if @files.length < i || i < 0
|
64
|
+
return @files[i]
|
65
|
+
end
|
66
|
+
@files.each{|mz|
|
67
|
+
return mz if mz.is?(id)
|
68
|
+
}
|
69
|
+
return nil
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
def info(params=nil)
|
74
|
+
what = params['what'] if params
|
75
|
+
if what == nil || what == "files"
|
76
|
+
if @files.length != 0
|
77
|
+
curid = -1
|
78
|
+
puts "Opened files:"
|
79
|
+
@files.each.with_index{|mz,i|
|
80
|
+
puts "#{i}:\t#{mz.path}"
|
81
|
+
curid=i if mz == @cur
|
82
|
+
}
|
83
|
+
puts "Current file: (#{curid}) #{@cur.path}"
|
84
|
+
puts
|
85
|
+
else
|
86
|
+
puts "No files opened"
|
87
|
+
end
|
88
|
+
else
|
89
|
+
raise "MZ file not loaded" if !@cur
|
90
|
+
@cur.print(what, params['how'])
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
def use(params)
|
96
|
+
App::get().col.on = true
|
97
|
+
mz = getfile(params['file'])
|
98
|
+
if mz==nil
|
99
|
+
mz = MZ.new(params['file'])
|
100
|
+
@files+=[mz]
|
101
|
+
end
|
102
|
+
@cur = mz
|
103
|
+
info()
|
104
|
+
end
|
105
|
+
|
106
|
+
|
107
|
+
def close(params)
|
108
|
+
mz = getfile(params['file'])
|
109
|
+
raise "File not found: "+fn if nil == fl
|
110
|
+
@files -= [mz]
|
111
|
+
@cur = nil if @cur == mz
|
112
|
+
mz.close()
|
113
|
+
mz = nil
|
114
|
+
@cur = @files[0] if !@cur && @files.length > 0
|
115
|
+
App::get().col.on = false if @files.length == 0
|
116
|
+
info()
|
117
|
+
end
|
118
|
+
|
119
|
+
|
120
|
+
def cur()
|
121
|
+
raise "No MZ selected." if !@cur
|
122
|
+
return @cur
|
123
|
+
end
|
124
|
+
|
125
|
+
|
126
|
+
def save(params)
|
127
|
+
cur().save(params['filename'], params['final'])
|
128
|
+
end
|
129
|
+
|
130
|
+
|
131
|
+
def append(params)
|
132
|
+
cur().append(params['value'], params['type'])
|
133
|
+
end
|
134
|
+
|
135
|
+
|
136
|
+
def replace(params)
|
137
|
+
cur().replace(params['value'], params['type'])
|
138
|
+
end
|
139
|
+
|
140
|
+
|
141
|
+
def change(params)
|
142
|
+
cur().change(params['ofs'], params['value'], params['disp'], params['type'])
|
143
|
+
end
|
144
|
+
|
145
|
+
|
146
|
+
def revert(params)
|
147
|
+
cur().revert(params['ofs'])
|
148
|
+
end
|
149
|
+
|
150
|
+
|
151
|
+
def hex(params)
|
152
|
+
cur().hex(params['ofs'], params['size'], params['how'], params['disp'])
|
153
|
+
end
|
154
|
+
|
155
|
+
|
156
|
+
def dasm(params)
|
157
|
+
cur().dasm(params['ofs'], params['size'], params['how'])
|
158
|
+
end
|
159
|
+
|
160
|
+
|
161
|
+
def job(params)
|
162
|
+
cmd = params['cmd']
|
163
|
+
if cmd.length==0 || File.exist?(cmd)
|
164
|
+
App::get().setShell('mz')
|
165
|
+
return if cmd.length == 0
|
166
|
+
params['p1'] = cmd
|
167
|
+
cmd = "use"
|
168
|
+
end
|
169
|
+
if cmd=="valueof"
|
170
|
+
cur().valueof(params['p1'], params['p2'])
|
171
|
+
return
|
172
|
+
end
|
173
|
+
if params['help']
|
174
|
+
params['command'] = params['help']
|
175
|
+
help(params)
|
176
|
+
return
|
177
|
+
end
|
178
|
+
raise "Unknown command: "+cmd if !@cmds[cmd]
|
179
|
+
scmd = @cmds[cmd]
|
180
|
+
if scmd[2]
|
181
|
+
scmd[2].keys.each.with_index{|k,i|
|
182
|
+
params[k] = params["p#{i+1}"]
|
183
|
+
params[k] = nil if params[k].length == 0
|
184
|
+
}
|
185
|
+
end
|
186
|
+
scmd[0].call(params)
|
187
|
+
end
|
188
|
+
|
189
|
+
|
190
|
+
end
|
191
|
+
|
192
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'resedit/app/app_command'
|
2
|
+
require 'resedit'
|
3
|
+
|
4
|
+
module Resedit
|
5
|
+
|
6
|
+
class VersionCommand < AppCommand
|
7
|
+
def initialize
|
8
|
+
super(['version','--version'])
|
9
|
+
end
|
10
|
+
def job(params)
|
11
|
+
log('%s v%s %s. Resedit v%s.',App::get().name, App.get().version, App::get().copyright, Resedit::VERSION)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class ExitCommand < AppCommand
|
16
|
+
def initialize
|
17
|
+
super(['quit','q', 'exit'])
|
18
|
+
end
|
19
|
+
def job(params)
|
20
|
+
App::get().quit();
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
class HelpCommand < AppCommand
|
26
|
+
def initialize
|
27
|
+
super(['help','--help','-h','/?'])
|
28
|
+
addParam('command', 'help on specific command', '')
|
29
|
+
end
|
30
|
+
def job(params)
|
31
|
+
App.get().commands.each{|c|
|
32
|
+
puts c.names[0]
|
33
|
+
}
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
class ScriptCommand < AppCommand
|
39
|
+
def initialize
|
40
|
+
super(['script', '--script', '-s'])
|
41
|
+
addParam('file', 'script file')
|
42
|
+
end
|
43
|
+
def job(params)
|
44
|
+
App::get().logd("running script %s", params['file']);
|
45
|
+
script = []
|
46
|
+
text=File.open(params['file']).read
|
47
|
+
text.gsub!(/\r\n?/, "\n")
|
48
|
+
text.each_line {|line|
|
49
|
+
script += [App.get().parseCommand(line.chomp())]
|
50
|
+
}
|
51
|
+
script.each{|cmd|
|
52
|
+
cmd[0].run(cmd[1]) if cmd
|
53
|
+
}
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
class ShellCommand < AppCommand
|
59
|
+
def initialize
|
60
|
+
super(['shell'])
|
61
|
+
addParam('shell', 'script file', "")
|
62
|
+
end
|
63
|
+
def job(params)
|
64
|
+
App::get().setShell(params['shell'])
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'resedit/app/io_commands'
|
2
|
+
|
3
|
+
module Resedit
|
4
|
+
|
5
|
+
class TextConvertCommand < ConvertCommand
|
6
|
+
|
7
|
+
def initialize(fname)
|
8
|
+
super('text', fname)
|
9
|
+
@font = nil
|
10
|
+
addOption('format','f',nil,'output file format')
|
11
|
+
addOption('encodinc','e',nil,'output file encoding')
|
12
|
+
end
|
13
|
+
|
14
|
+
def import(inname)
|
15
|
+
logd("importing text #{inname} to #{@resname}")
|
16
|
+
back = backup()
|
17
|
+
File.open(back,"rb"){|file|
|
18
|
+
@text = mktext(file, @params['format'], @params['encoding'])
|
19
|
+
@text.load(inname, linesCount())
|
20
|
+
StringIO.open("","w+b"){|stream|
|
21
|
+
pack(file, stream)
|
22
|
+
stream.seek(0)
|
23
|
+
File.open(@resname,"wb"){|out|
|
24
|
+
out.write(stream.read())
|
25
|
+
}
|
26
|
+
}
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
def export(outname)
|
32
|
+
logd("exporting txet #{@resname} to #{outname}")
|
33
|
+
File.open(@resname, "rb"){|file|
|
34
|
+
@text = mktext(file, @params['format'], @params['encoding'])
|
35
|
+
unpack(file) if @text
|
36
|
+
}
|
37
|
+
raise "Text not unpacked" if !@text
|
38
|
+
@text.save(outname)
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
def mktext(file, format, encoding)
|
43
|
+
raise "Not implemented."
|
44
|
+
end
|
45
|
+
|
46
|
+
def linesCount(file)
|
47
|
+
raise "Not implemented"
|
48
|
+
end
|
49
|
+
|
50
|
+
def pack(file, outstream)
|
51
|
+
raise "Not implemented."
|
52
|
+
end
|
53
|
+
|
54
|
+
def unpack(file)
|
55
|
+
raise "Not implemented."
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Resedit
|
2
|
+
|
3
|
+
class BitConverter
|
4
|
+
|
5
|
+
def self.bits2Bytes(bits, width)
|
6
|
+
i=0
|
7
|
+
res=[]
|
8
|
+
while i<bits.length
|
9
|
+
buf=0
|
10
|
+
cw=0
|
11
|
+
bsz=0
|
12
|
+
while cw<width
|
13
|
+
if bsz==0
|
14
|
+
buf = bits[i]
|
15
|
+
i+=1
|
16
|
+
bsz=8
|
17
|
+
end
|
18
|
+
bsz-=1
|
19
|
+
cw+=1
|
20
|
+
res << ((buf>>bsz) & 1)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
return res
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.bytes2Bits(bytes, rwidth, bwidth)
|
27
|
+
res=[]
|
28
|
+
for i in 0..(bytes.length/rwidth)-1
|
29
|
+
row=bytes[i*rwidth..i*rwidth+rwidth-1]
|
30
|
+
while row.length < bwidth*8
|
31
|
+
row << 0
|
32
|
+
end
|
33
|
+
b=0
|
34
|
+
for j in 0..row.length-1
|
35
|
+
b <<= 1
|
36
|
+
b |= row[j]
|
37
|
+
if (j+1)%8==0
|
38
|
+
res << (b & 0xFF)
|
39
|
+
b=0
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
return res
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'resedit/font/font_char'
|
2
|
+
require 'resedit/image/image_factory'
|
3
|
+
|
4
|
+
module Resedit
|
5
|
+
|
6
|
+
class Font
|
7
|
+
attr_reader :count, :width, :height
|
8
|
+
attr_accessor :gridColor, :charColor, :userData, :widthColor
|
9
|
+
|
10
|
+
# charWidth, charHeight, characters count
|
11
|
+
def initialize(width, height, count=256)
|
12
|
+
@width, @height, @count = width, height, count
|
13
|
+
@gridColor = 0xFFEEEEEE
|
14
|
+
@charColor = 0xFF000000
|
15
|
+
@bgColor = 0xFFFFFFFF
|
16
|
+
@widthColor = 0xFFFF0000
|
17
|
+
@chars = {}
|
18
|
+
@userData = nil
|
19
|
+
end
|
20
|
+
|
21
|
+
def setChar(id, data, width=nil)
|
22
|
+
width=@width if !width
|
23
|
+
@chars[id] = FontChar.new(@width, @height, id, data, width)
|
24
|
+
end
|
25
|
+
|
26
|
+
def getChar(id)
|
27
|
+
@chars[id].data if @chars[id]
|
28
|
+
end
|
29
|
+
|
30
|
+
def minChar
|
31
|
+
return @chars.keys().min
|
32
|
+
end
|
33
|
+
|
34
|
+
def maxChar
|
35
|
+
return @chars.keys().max
|
36
|
+
end
|
37
|
+
|
38
|
+
def charWidth(id)
|
39
|
+
return nil if !@chars[id]
|
40
|
+
return @chars[id].realWidth ? @chars[id].realWidth : @width
|
41
|
+
end
|
42
|
+
|
43
|
+
def save(filename)
|
44
|
+
rows = @count/16 + (@count%16 == 0 ? 0 : 1)
|
45
|
+
img = Resedit.createImage(@width*16+17 , @height*rows+rows+1, filename)
|
46
|
+
img.fill(@bgColor)
|
47
|
+
#draw grid
|
48
|
+
for i in 0..16
|
49
|
+
img.vline(i*(@width+1), gridColor)
|
50
|
+
end
|
51
|
+
for j in 0..rows
|
52
|
+
img.hline(j*(@height+1), gridColor)
|
53
|
+
end
|
54
|
+
#draw letters
|
55
|
+
@chars.each { |idx,c|
|
56
|
+
x = idx%16
|
57
|
+
y = idx/16
|
58
|
+
x += 1+x*@width
|
59
|
+
y += 1+y*@height
|
60
|
+
c.draw(img, @charColor, x, y, @widthColor)
|
61
|
+
}
|
62
|
+
img.save(filename)
|
63
|
+
end
|
64
|
+
|
65
|
+
def load(filename)
|
66
|
+
img = Resedit.loadImage(filename)
|
67
|
+
rows = @count/16 + (@count%16 == 0 ? 0 : 1)
|
68
|
+
raise "Wrong image size" if (img.width!=@width*16+17 || img.height!=@height*rows+rows+1)
|
69
|
+
for idx in 0..@count-1
|
70
|
+
x = idx%16
|
71
|
+
y = idx/16
|
72
|
+
x += 1+x*@width
|
73
|
+
y += 1+y*@height
|
74
|
+
c = FontChar.new(width,height,idx)
|
75
|
+
c.scan(img, @charColor, x, y, @widthColor)
|
76
|
+
@chars[c.index] = c if c.data
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|