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.
@@ -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