resedit 1.3.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b1b2afae945b0bfe8559010f9de3ecd21889a036
|
4
|
+
data.tar.gz: 9ec879c124f71706f9d5e90b988c88a1a7576457
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 85ac7bb3ccf16019f0314d6ffed992c47636ebe0a20451e4988a3afde9e03d67dea91dee2c0a003e619b018189538f962e45398bf6d058efde2796abdb85f6ea
|
7
|
+
data.tar.gz: 9cbbafcba61f4bc3fef2787a70f9c4e971d80edf508e56b979ee13e891a54431c110d0a1d94dd6dd7e2b1dd9980547a319c643a0c1ae36417468e2bfa5be59c5
|
data/bin/resedit
ADDED
data/lib/resedit.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
|
2
|
+
require 'resedit/font/font'
|
3
|
+
require 'resedit/font/font_char'
|
4
|
+
require 'resedit/image/image_factory'
|
5
|
+
require 'resedit/text/escaper'
|
6
|
+
require 'resedit/text/text'
|
7
|
+
require 'resedit/app/app'
|
8
|
+
require 'resedit/text/huffman'
|
9
|
+
require 'resedit/app/font_convert'
|
10
|
+
require 'resedit/app/text_convert'
|
11
|
+
require 'resedit/convert/bitconv'
|
12
|
+
require 'resedit/mz/mz'
|
13
|
+
|
14
|
+
|
15
|
+
module Resedit
|
16
|
+
VERSION = "1.3.1"
|
17
|
+
end
|
@@ -0,0 +1,160 @@
|
|
1
|
+
require 'resedit/app/std_commands'
|
2
|
+
require 'resedit/app/mz_command'
|
3
|
+
require 'resedit/app/colorizer'
|
4
|
+
require 'logger'
|
5
|
+
require 'readline'
|
6
|
+
|
7
|
+
module Resedit
|
8
|
+
|
9
|
+
class App
|
10
|
+
HIST_FILE = "~/.resedithist"
|
11
|
+
attr_reader :name, :version, :commands, :logger, :copyright, :cmdInterface, :shell, :col
|
12
|
+
|
13
|
+
def self.get()
|
14
|
+
return @@instance
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(name, version, commands, cmdInterface=true, copyright="(c) old-games.ru")
|
18
|
+
@@instance = self
|
19
|
+
@name, @version, @copyright = name, version, copyright
|
20
|
+
@cmdInterface = cmdInterface
|
21
|
+
@logger = Logger.new(STDOUT)
|
22
|
+
@logger.level= Logger::INFO
|
23
|
+
logger.formatter = proc { |severity, datetime, progname, msg|
|
24
|
+
msg
|
25
|
+
}
|
26
|
+
@shell = nil;
|
27
|
+
@commands = []
|
28
|
+
@commands += commands if commands
|
29
|
+
@commands += [HelpCommand.new(), VersionCommand.new(), ExitCommand.new(),
|
30
|
+
ScriptCommand.new(), MZCommand.new(), ShellCommand.new()]
|
31
|
+
@cmds={}
|
32
|
+
@commands.each{|c|
|
33
|
+
c.names.each{|n|
|
34
|
+
@cmds[n] = c;
|
35
|
+
}
|
36
|
+
}
|
37
|
+
@col = Colorizer.new(false)
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
def logd(fmt, *args)
|
42
|
+
@logger.debug(@col.gray(sprintf(fmt+"\n",*args)))
|
43
|
+
end
|
44
|
+
def log(fmt, *args)
|
45
|
+
@logger.info(sprintf(fmt+"\n",*args))
|
46
|
+
end
|
47
|
+
def loge(fmt, *args)
|
48
|
+
@logger.error(@col.red(sprintf(fmt+"\n",*args)))
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
def quit
|
53
|
+
begin
|
54
|
+
strt = Readline::HISTORY.length-64
|
55
|
+
open(File.expand_path(HIST_FILE),"w"){|f|
|
56
|
+
Readline::HISTORY.each.with_index{|ln,i|
|
57
|
+
f.write(ln+"\n") if i > strt
|
58
|
+
}
|
59
|
+
}
|
60
|
+
rescue
|
61
|
+
end
|
62
|
+
@stop=true
|
63
|
+
end
|
64
|
+
|
65
|
+
def setShell(sname)
|
66
|
+
sname=nil if sname.length==0
|
67
|
+
raise "Unknown shell: "+sname if sname && !@cmds[sname]
|
68
|
+
@shell = sname
|
69
|
+
end
|
70
|
+
|
71
|
+
def parseCommand(string)
|
72
|
+
cmd = []
|
73
|
+
string.split().each {|w|
|
74
|
+
if w[0]=='-' && w.length()>2 && w[1]!='-'
|
75
|
+
w[1..-1].each_char{|c|
|
76
|
+
cmd+=["-#{c}"]
|
77
|
+
}
|
78
|
+
else
|
79
|
+
cmd+=[w]
|
80
|
+
end
|
81
|
+
}
|
82
|
+
logd("parsing command #{cmd.to_s}")
|
83
|
+
return nil if cmd.length()==0 || cmd[0][0]=='#'
|
84
|
+
c = @cmds[cmd[0]]
|
85
|
+
raise "Unknown command: #{cmd[0]}" if !c
|
86
|
+
res=[]
|
87
|
+
prms = c.parseParams(cmd[1..-1])
|
88
|
+
return c,prms
|
89
|
+
end
|
90
|
+
|
91
|
+
|
92
|
+
def runCommand(string)
|
93
|
+
if @shell
|
94
|
+
cmd=string.split()[0]
|
95
|
+
if !@cmds[cmd] || !['Resedit::ExitCommand','Resedit::ShellCommand'].include?(@cmds[cmd].class.name)
|
96
|
+
string = @shell+" "+string
|
97
|
+
end
|
98
|
+
end
|
99
|
+
logd("running command %s", string)
|
100
|
+
cmd = parseCommand(string)
|
101
|
+
cmd[0].run(cmd[1])
|
102
|
+
end
|
103
|
+
|
104
|
+
|
105
|
+
def commandInterface()
|
106
|
+
@cmds['version'].run('')
|
107
|
+
begin
|
108
|
+
open(File.expand_path(HIST_FILE),"r").each_line {|ln|
|
109
|
+
ln.chomp!
|
110
|
+
Readline::HISTORY.push(ln) if ln.length>0
|
111
|
+
}
|
112
|
+
rescue
|
113
|
+
end
|
114
|
+
@stop=false
|
115
|
+
while(!@stop)
|
116
|
+
sh=@shell ? " "+@shell : ""
|
117
|
+
begin
|
118
|
+
cmd = Readline.readline("#{@name}#{sh}>", true)
|
119
|
+
Readline::HISTORY.pop if cmd=='' || (Readline::HISTORY.length>1 && cmd==Readline::HISTORY[-2])
|
120
|
+
runCommand(cmd)
|
121
|
+
rescue StandardError => e
|
122
|
+
puts @col.red("Error: #{e.to_s()}")
|
123
|
+
puts e.backtrace if App::get().logger.level == Logger::DEBUG
|
124
|
+
end
|
125
|
+
end
|
126
|
+
return 0
|
127
|
+
end
|
128
|
+
|
129
|
+
|
130
|
+
def run()
|
131
|
+
begin
|
132
|
+
if ARGV.length()==0
|
133
|
+
commandInterface() if @cmdInterface
|
134
|
+
if !@cmdInterface
|
135
|
+
puts "Command not specified. Known commands are:"
|
136
|
+
runCommand('help')
|
137
|
+
end
|
138
|
+
else
|
139
|
+
if (@cmds[ARGV[0]])
|
140
|
+
#check command
|
141
|
+
runCommand(ARGV.join(' '))
|
142
|
+
commandInterface() if @shell
|
143
|
+
elsif ARGV.length()==1 && File.exists?(ARGV[0])
|
144
|
+
#check script
|
145
|
+
runCommand('script '+ARGV[0])
|
146
|
+
else
|
147
|
+
raise "unknown command #{ARGV[0]}"
|
148
|
+
end
|
149
|
+
end
|
150
|
+
exit(0)
|
151
|
+
rescue StandardError => e
|
152
|
+
puts "Error: #{e.to_s()}"
|
153
|
+
puts e.backtrace
|
154
|
+
exit(1)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
end
|
159
|
+
|
160
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
module Resedit
|
2
|
+
|
3
|
+
class AppCommand
|
4
|
+
attr_reader :names, :type, :params
|
5
|
+
def initialize(names, type=:std)
|
6
|
+
@names, @continue = names, type
|
7
|
+
@names = [@names] if not @names.kind_of?(Array)
|
8
|
+
@opts = {}
|
9
|
+
@params = []
|
10
|
+
@ohash = {}
|
11
|
+
addOption('verbose','v',false, 'verbose output')
|
12
|
+
addOption('unverbose',nil,false, 'unverbose output')
|
13
|
+
addOption('quiet','q',false, 'supress output')
|
14
|
+
addOption('color',nil,false, 'set colored output')
|
15
|
+
addOption('uncolor',nil,false, 'unset colored output')
|
16
|
+
end
|
17
|
+
|
18
|
+
def addParam(name, descr, default = nil, type=:std)
|
19
|
+
@params +=[{:name => name, :def => default, :descr => descr}]
|
20
|
+
end
|
21
|
+
|
22
|
+
def addOption(longname, shortname, param, descr, type = :std, setter= proc{|val, opt| val})
|
23
|
+
@opts[longname] = {:name => longname, :param => param, :descr => descr, :type => type, :setter => setter}
|
24
|
+
@ohash[shortname] = longname if shortname
|
25
|
+
end
|
26
|
+
|
27
|
+
def parseParams(params)
|
28
|
+
res = {}
|
29
|
+
pidx = 0
|
30
|
+
idx=0
|
31
|
+
@params.each{|p|
|
32
|
+
res[p[:name]] = p[:def]
|
33
|
+
}
|
34
|
+
@opts.each{|k,o|
|
35
|
+
res[k] = o[:param]
|
36
|
+
}
|
37
|
+
while idx<params.length
|
38
|
+
p = params[idx]
|
39
|
+
idx+=1
|
40
|
+
if p[0]=='-'
|
41
|
+
val = true
|
42
|
+
s=p.split('=')
|
43
|
+
if s.length==2
|
44
|
+
val=s[1]
|
45
|
+
p=s[0]
|
46
|
+
end
|
47
|
+
if (p[1]=='-')
|
48
|
+
opt = @opts[p[2..-1]]
|
49
|
+
else
|
50
|
+
opt = @opts[@ohash[p[1..-1]]] || @opts[p[1..-1]]
|
51
|
+
end
|
52
|
+
raise "Unknown option #{p}" if !opt
|
53
|
+
if opt[:param]!=false and val==true
|
54
|
+
raise "No option #{p} value" if idx>=params.length
|
55
|
+
val = params[idx]
|
56
|
+
idx+=1
|
57
|
+
end
|
58
|
+
proc = opt[:setter]
|
59
|
+
res[opt[:name]] = proc.call(val, opt)
|
60
|
+
else
|
61
|
+
raise "Unknown param #{p}" if !@params[pidx]
|
62
|
+
if (@params[pidx][:type] == :text)
|
63
|
+
p = params[idx-1..-1]
|
64
|
+
idx=params.length
|
65
|
+
end
|
66
|
+
res[@params[pidx][:name]] = p
|
67
|
+
pidx+=1
|
68
|
+
end
|
69
|
+
end
|
70
|
+
@params.each{|p|
|
71
|
+
raise "Expected parameter #{p[:name]}" if res[p[:name]]==nil
|
72
|
+
}
|
73
|
+
return res
|
74
|
+
end
|
75
|
+
|
76
|
+
def run(params)
|
77
|
+
App::get().logger.level = Logger::DEBUG if params['verbose']
|
78
|
+
App::get().logger.level = Logger::INFO if params['unverbose']
|
79
|
+
App::get().logger.level = Logger::ERROR if params['quiet']
|
80
|
+
App::get().col.on = true if params['color']
|
81
|
+
App::get().col.on = false if params['uncolor']
|
82
|
+
job(params)
|
83
|
+
end
|
84
|
+
|
85
|
+
def job(params)
|
86
|
+
raise "Unimplemented command #{@names[0]}"
|
87
|
+
end
|
88
|
+
|
89
|
+
def logd(fmt, *args)
|
90
|
+
App::get().logd(fmt,*args)
|
91
|
+
end
|
92
|
+
def log(fmt, *args)
|
93
|
+
App::get().log(fmt,*args)
|
94
|
+
end
|
95
|
+
def loge(fmt, *args)
|
96
|
+
App::get().loge(fmt,*args)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Resedit
|
2
|
+
|
3
|
+
class Colorizer
|
4
|
+
GRAY = 90
|
5
|
+
RED = 91
|
6
|
+
GREEN = 92
|
7
|
+
YELLOW = 93
|
8
|
+
BLUE = 94
|
9
|
+
PURPLE = 95
|
10
|
+
CYAN = 96
|
11
|
+
WHITE = 97
|
12
|
+
|
13
|
+
attr_accessor :on
|
14
|
+
|
15
|
+
def initialize(on=true)
|
16
|
+
@on = on;
|
17
|
+
end
|
18
|
+
|
19
|
+
def color(col, text)
|
20
|
+
return text if !@on
|
21
|
+
return "\033[#{col}m#{text}\033[0m"
|
22
|
+
end
|
23
|
+
|
24
|
+
def gray(text) color(GRAY, text) end
|
25
|
+
def red(text) color(RED, text) end
|
26
|
+
def green(text) color(GREEN, text) end
|
27
|
+
def yellow(text) color(YELLOW, text) end
|
28
|
+
def blue(text) color(BLUE, text) end
|
29
|
+
def deep(text) color(PURPLE, text) end
|
30
|
+
def cyan(text) color(CYAN, text) end
|
31
|
+
def white(text) color(WHITE, text) end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'resedit/app/io_commands'
|
2
|
+
|
3
|
+
module Resedit
|
4
|
+
|
5
|
+
class FontConvertCommand < ConvertCommand
|
6
|
+
|
7
|
+
def initialize(fname)
|
8
|
+
super('font', fname)
|
9
|
+
@font = nil
|
10
|
+
end
|
11
|
+
|
12
|
+
def import(inname)
|
13
|
+
logd("importing font #{inname} to #{@resname}")
|
14
|
+
back = backup()
|
15
|
+
File.open(back,"rb"){|file|
|
16
|
+
@font = mkfont(file)
|
17
|
+
@font.load(inname+'.png')
|
18
|
+
StringIO.open("","w+b"){|stream|
|
19
|
+
pack(file, stream)
|
20
|
+
stream.seek(0)
|
21
|
+
File.open(@resname,"wb"){|out|
|
22
|
+
out.write(stream.read())
|
23
|
+
}
|
24
|
+
}
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
def export(outname)
|
30
|
+
logd("exporting font #{@resname} to #{outname}")
|
31
|
+
File.open(@resname, "rb"){|file|
|
32
|
+
@font = mkfont(file)
|
33
|
+
unpack(file) if @font
|
34
|
+
}
|
35
|
+
raise "Font not unpacked" if !@font
|
36
|
+
@font.save(outname+'.png')
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
def mkfont(file)
|
41
|
+
raise "Not implemented."
|
42
|
+
end
|
43
|
+
|
44
|
+
def pack(file, outstream)
|
45
|
+
raise "Not implemented."
|
46
|
+
end
|
47
|
+
|
48
|
+
def unpack(file)
|
49
|
+
raise "Not implemented."
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'resedit/app/app_command'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
module Resedit
|
5
|
+
|
6
|
+
class ExportCommand < AppCommand
|
7
|
+
def initialize(name)
|
8
|
+
super([name])
|
9
|
+
end
|
10
|
+
def job(params)
|
11
|
+
raise 'Not implemented'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
class ImportCommand < AppCommand
|
17
|
+
def initialize(name)
|
18
|
+
super([name])
|
19
|
+
end
|
20
|
+
def job(params)
|
21
|
+
raise 'Not implemented'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
class ConvertCommand < AppCommand
|
27
|
+
|
28
|
+
attr_reader :fname
|
29
|
+
|
30
|
+
|
31
|
+
def initialize(name, fname)
|
32
|
+
super([name])
|
33
|
+
addParam('action','import/export action')
|
34
|
+
addParam('file','file to import/export')
|
35
|
+
addOption('output','o',nil,'converted file name')
|
36
|
+
@fname=fname
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
def getOutName()
|
41
|
+
return File.basename(@resname,File.extname(@resname))
|
42
|
+
end
|
43
|
+
|
44
|
+
def backup()
|
45
|
+
bname=@resname+'.bak'
|
46
|
+
FileUtils.cp(@resname,bname) if ! File.exist?(bname)
|
47
|
+
return bname
|
48
|
+
end
|
49
|
+
|
50
|
+
def job(params)
|
51
|
+
@params=params
|
52
|
+
@resname=params['file']
|
53
|
+
fname = getOutName()
|
54
|
+
fname = params['output'] if params['output']
|
55
|
+
if params['action']=='import'
|
56
|
+
import(fname)
|
57
|
+
elsif params['action']=='export'
|
58
|
+
export(fname)
|
59
|
+
else
|
60
|
+
raise "Unknown action #{params['action']}. import or export expected."
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
def import(infile)
|
66
|
+
raise 'Not implemented'
|
67
|
+
end
|
68
|
+
|
69
|
+
def export(outfile)
|
70
|
+
raise 'Not implemented'
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|