teek 0.1.1 → 0.1.2

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.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +46 -0
  3. data/Rakefile +161 -5
  4. data/ext/teek/extconf.rb +1 -1
  5. data/ext/teek/tcltkbridge.c +3 -0
  6. data/ext/teek/tcltkbridge.h +3 -0
  7. data/ext/teek/tkeventsource.c +195 -0
  8. data/ext/teek/tkphoto.c +169 -5
  9. data/ext/teek/tkwin.c +84 -0
  10. data/lib/teek/background_ractor4x.rb +32 -4
  11. data/lib/teek/photo.rb +232 -0
  12. data/lib/teek/version.rb +1 -1
  13. data/lib/teek.rb +3 -1
  14. data/sample/optcarrot/vendor/optcarrot/apu.rb +856 -0
  15. data/sample/optcarrot/vendor/optcarrot/config.rb +257 -0
  16. data/sample/optcarrot/vendor/optcarrot/cpu.rb +1162 -0
  17. data/sample/optcarrot/vendor/optcarrot/driver.rb +144 -0
  18. data/sample/optcarrot/vendor/optcarrot/mapper/cnrom.rb +14 -0
  19. data/sample/optcarrot/vendor/optcarrot/mapper/mmc1.rb +105 -0
  20. data/sample/optcarrot/vendor/optcarrot/mapper/mmc3.rb +153 -0
  21. data/sample/optcarrot/vendor/optcarrot/mapper/uxrom.rb +14 -0
  22. data/sample/optcarrot/vendor/optcarrot/nes.rb +105 -0
  23. data/sample/optcarrot/vendor/optcarrot/opt.rb +168 -0
  24. data/sample/optcarrot/vendor/optcarrot/pad.rb +92 -0
  25. data/sample/optcarrot/vendor/optcarrot/palette.rb +65 -0
  26. data/sample/optcarrot/vendor/optcarrot/ppu.rb +1468 -0
  27. data/sample/optcarrot/vendor/optcarrot/rom.rb +143 -0
  28. data/sample/optcarrot/vendor/optcarrot.rb +14 -0
  29. data/sample/optcarrot.rb +354 -0
  30. data/sample/paint/assets/bucket.png +0 -0
  31. data/sample/paint/assets/cursor.png +0 -0
  32. data/sample/paint/assets/eraser.png +0 -0
  33. data/sample/paint/assets/pencil.png +0 -0
  34. data/sample/paint/assets/spray.png +0 -0
  35. data/sample/paint/layer.rb +255 -0
  36. data/sample/paint/layer_manager.rb +179 -0
  37. data/sample/paint/paint_demo.rb +837 -0
  38. data/sample/paint/sparse_pixel_buffer.rb +202 -0
  39. data/sample/sdl2_demo.rb +318 -0
  40. metadata +29 -1
@@ -0,0 +1,257 @@
1
+ module Optcarrot
2
+ # config manager and logger
3
+ class Config
4
+ OPTIONS = {
5
+ optimization: {
6
+ opt_ppu: {
7
+ type: :opts,
8
+ desc: "select PPU optimizations",
9
+ candidates: PPU::OptimizedCodeBuilder::OPTIONS,
10
+ default: nil,
11
+ },
12
+ opt_cpu: {
13
+ type: :opts,
14
+ desc: "select CPU optimizations",
15
+ candidates: CPU::OptimizedCodeBuilder::OPTIONS,
16
+ default: nil,
17
+ },
18
+ opt: { shortcut: %w(--opt-ppu=all --opt-cpu=all) },
19
+ list_opts: { type: :info, desc: "list available optimizations" },
20
+ dump_ppu: { type: :info, desc: "print generated PPU source code" },
21
+ dump_cpu: { type: :info, desc: "print generated CPU source code" },
22
+ load_ppu: { type: "FILE", desc: "use generated PPU source code" },
23
+ load_cpu: { type: "FILE", desc: "use generated CPU source code" },
24
+ },
25
+ emulation: {
26
+ sprite_limit: { type: :switch, desc: "enable/disable sprite limit", default: false },
27
+ frames: { type: :int, desc: "execute N frames (0 = no limit)", default: 0, aliases: [:f, :frame] },
28
+ audio_sample_rate: { type: :int, desc: "set audio sample rate", default: 44100 },
29
+ audio_bit_depth: { type: :int, desc: "set audio bit depth", default: 16 },
30
+ nestopia_palette: { type: :switch, desc: "use Nestopia palette instead of de facto", default: false },
31
+ },
32
+ driver: {
33
+ video: { type: :driver, desc: "select video driver", candidates: Driver::DRIVER_DB[:video].keys },
34
+ audio: { type: :driver, desc: "select audio driver", candidates: Driver::DRIVER_DB[:audio].keys },
35
+ input: { type: :driver, desc: "select input driver", candidates: Driver::DRIVER_DB[:input].keys },
36
+ list_drivers: { type: :info, desc: "print available drivers" },
37
+ sdl2: { shortcut: %w(--video=sdl2 --audio=sdl2 --input=sdl2) },
38
+ sfml: { shortcut: %w(--video=sfml --audio=sfml --input=sfml) },
39
+ headless: { shortcut: %w(--video=none --audio=none --input=none) },
40
+ video_output: { type: "FILE", desc: "save video to file", default: "video.EXT" },
41
+ audio_output: { type: "FILE", desc: "save audio to file", default: "audio.wav" },
42
+ show_fps: { type: :switch, desc: "show fps in the right-bottom corner", default: true },
43
+ key_log: { type: "FILE", desc: "use recorded input file" },
44
+ # key_config: { type: "KEY", desc: "key configuration" },
45
+ },
46
+ profiling: {
47
+ print_fps: { type: :switch, desc: "print fps of last 10 frames", default: false },
48
+ print_p95fps: { type: :switch, desc: "print 95th percentile fps", default: false },
49
+ print_fps_history: { type: :switch, desc: "print all fps values for each frame", default: false },
50
+ print_video_checksum: { type: :switch, desc: "print checksum of the last video output", default: false },
51
+ stackprof: { shortcut: "--stackprof-mode=cpu", aliases: :p },
52
+ stackprof_mode: { type: "MODE", desc: "run under stackprof", default: nil },
53
+ stackprof_output: { type: "FILE", desc: "stackprof output file", default: "stackprof-MODE.dump" }
54
+ },
55
+ misc: {
56
+ benchmark: { shortcut: %w(--headless --print-fps --print-video-checksum --frames 180), aliases: :b },
57
+ loglevel: { type: :int, desc: "set loglevel", default: 1 },
58
+ quiet: { shortcut: "--loglevel=0", aliases: :q },
59
+ verbose: { shortcut: "--loglevel=2", aliases: :v },
60
+ debug: { shortcut: "--loglevel=3", aliases: :d },
61
+ version: { type: :info, desc: "print version" },
62
+ help: { type: :info, desc: "print this message", aliases: :h },
63
+ },
64
+ }
65
+
66
+ DEFAULT_OPTIONS = {}
67
+ OPTIONS.each_value do |opts|
68
+ opts.each do |id, opt|
69
+ next if opt[:shortcut]
70
+ DEFAULT_OPTIONS[id] = opt[:default] if opt.key?(:default)
71
+ attr_reader id
72
+ end
73
+ end
74
+ attr_reader :romfile
75
+
76
+ def initialize(opt)
77
+ opt = Parser.new(opt).options if opt.is_a?(Array)
78
+ DEFAULT_OPTIONS.merge(opt).each {|id, val| instance_variable_set(:"@#{ id }", val) }
79
+ end
80
+
81
+ def debug(msg)
82
+ puts "[DEBUG] " + msg if @loglevel >= 3
83
+ end
84
+
85
+ def info(msg)
86
+ puts "[INFO] " + msg if @loglevel >= 2
87
+ end
88
+
89
+ def warn(msg)
90
+ puts "[WARN] " + msg if @loglevel >= 1
91
+ end
92
+
93
+ def error(msg)
94
+ puts "[ERROR] " + msg
95
+ end
96
+
97
+ def fatal(msg)
98
+ puts "[FATAL] " + msg
99
+ abort
100
+ end
101
+
102
+ # command-line option parser
103
+ class Parser
104
+ def initialize(argv)
105
+ @argv = argv.dup
106
+ @options = DEFAULT_OPTIONS.dup
107
+ parse_option until @argv.empty?
108
+ error "ROM file is not given" unless @options[:romfile]
109
+ rescue Invalid => e
110
+ puts "[FATAL] #{ e }"
111
+ exit 1
112
+ end
113
+
114
+ attr_reader :options
115
+
116
+ class Invalid < RuntimeError; end
117
+
118
+ def error(msg)
119
+ raise Invalid, msg
120
+ end
121
+
122
+ def find_option(arg)
123
+ OPTIONS.each_value do |opts|
124
+ opts.each do |id_base, opt|
125
+ [id_base, *opt[:aliases]].each do |id|
126
+ id = id.to_s.tr("_", "-")
127
+ return opt, id_base if id.size == 1 && arg == "-#{ id }"
128
+ return opt, id_base if arg == "--#{ id }"
129
+ return opt, id_base, true if opt[:type] == :switch && arg == "--no-#{ id }"
130
+ end
131
+ end
132
+ end
133
+ return nil
134
+ end
135
+
136
+ def parse_option
137
+ arg, operand = @argv.shift.split("=", 2)
138
+ if arg =~ /\A-(\w{2,})\z/
139
+ args = $1.chars.map {|a| "-#{ a }" }
140
+ args.last << "=" << operand if operand
141
+ @argv.unshift(*args)
142
+ return
143
+ end
144
+ opt, id, no = find_option(arg)
145
+ if opt
146
+ if opt[:shortcut]
147
+ @argv.unshift(*opt[:shortcut])
148
+ return
149
+ elsif opt[:type] == :info
150
+ send(id)
151
+ exit
152
+ elsif opt[:type] == :switch
153
+ error "option `#{ arg }' doesn't allow an operand" if operand
154
+ @options[id] = !no
155
+ else
156
+ @options[id] = parse_operand(operand, arg, opt)
157
+ end
158
+ else
159
+ arg = @argv.shift if arg == "--"
160
+ error "invalid option: `#{ arg }'" if arg && arg.start_with?("-")
161
+ if arg
162
+ error "extra argument: `#{ arg }'" if @options[:romfile]
163
+ @options[:romfile] = arg
164
+ end
165
+ end
166
+ end
167
+
168
+ def parse_operand(operand, arg, opt)
169
+ type = opt[:type]
170
+ operand ||= @argv.shift
171
+ case type
172
+ when :opts
173
+ operand = operand.split(",").map {|s| s.to_sym }
174
+ when :driver
175
+ operand = operand.to_sym
176
+ error "unknown driver: `#{ operand }'" unless opt[:candidates].include?(operand)
177
+ when :int
178
+ begin
179
+ operand = Integer(operand)
180
+ rescue
181
+ error "option `#{ arg }' requires numerical operand"
182
+ end
183
+ end
184
+ operand
185
+ end
186
+
187
+ def help
188
+ tbl = ["Usage: #{ $PROGRAM_NAME } [OPTION]... FILE"]
189
+ long_name_width = 0
190
+ OPTIONS.each do |kind, opts|
191
+ tbl << "" << "#{ kind } options:"
192
+ opts.each do |id_base, opt|
193
+ short_name = [*opt[:aliases]][0]
194
+ switch = args = ""
195
+ case opt[:type]
196
+ when :switch then switch = "[no-]"
197
+ when :opts then args = "=OPTS,..."
198
+ when :driver then args = "=DRIVER"
199
+ when :int then args = "=N"
200
+ when String then args = "=" + opt[:type]
201
+ end
202
+ short_name = "-#{ switch }#{ short_name }, " if short_name && short_name.size == 1
203
+ long_name = "--" + switch + id_base.to_s.tr("_", "-") + args
204
+ if opt[:shortcut]
205
+ desc = "same as `#{ [*opt[:shortcut]].join(" ") }'"
206
+ else
207
+ desc = opt[:desc]
208
+ desc += " (default: #{ opt[:default] || "none" })" if opt.key?(:default)
209
+ end
210
+ long_name_width = [long_name_width, long_name.size].max
211
+ tbl << [short_name, long_name, desc]
212
+ end
213
+ end
214
+ tbl.each do |arg|
215
+ if arg.is_a?(String)
216
+ puts arg
217
+ else
218
+ short_name, long_name, desc = arg
219
+ puts " %4s%-*s %s" % [short_name, long_name_width, long_name, desc]
220
+ end
221
+ end
222
+ end
223
+
224
+ def version
225
+ puts "optcarrot #{ VERSION }"
226
+ end
227
+
228
+ def list_drivers
229
+ Driver::DRIVER_DB.each do |kind, drivers|
230
+ puts "#{ kind } drivers: #{ drivers.keys * " " }"
231
+ end
232
+ end
233
+
234
+ def list_opts
235
+ puts "CPU core optimizations:"
236
+ CPU::OptimizedCodeBuilder::OPTIONS.each do |opt|
237
+ puts " * #{ opt }"
238
+ end
239
+ puts
240
+ puts "PPU core optimizations:"
241
+ PPU::OptimizedCodeBuilder::OPTIONS.each do |opt|
242
+ puts " * #{ opt }"
243
+ end
244
+ puts
245
+ puts "(See `doc/internal.md' in detail.)"
246
+ end
247
+
248
+ def dump_ppu
249
+ puts PPU::OptimizedCodeBuilder.new(@options[:loglevel], @options[:opt_ppu] || []).build
250
+ end
251
+
252
+ def dump_cpu
253
+ puts CPU::OptimizedCodeBuilder.new(@options[:loglevel], @options[:opt_cpu] || []).build
254
+ end
255
+ end
256
+ end
257
+ end