snes_utils 0.1.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,158 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SnesUtils
4
+ module Superfx
5
+ class Definitions
6
+ HEX_DIGIT = '[0-9a-f]'
7
+ REG = "[rR](\\d{1,2})"
8
+ LNK = "([1-4])"
9
+ HEX = "\\$?(#{HEX_DIGIT})"
10
+ HEX8 = "\\$?(#{HEX_DIGIT}{1,2})"
11
+ HEX16 = "\\$?(#{HEX_DIGIT}{1,4})"
12
+
13
+ SINGLE_OPERAND_INSTRUCTIONS = %i[imp imm4 rn rm rel lnk].freeze
14
+ DOUBLE_OPERAND_INSTRUCTIONS = %i[rn_rn rn_imm8 rn_imm16 rn_addr rn_addrl addr_rn addrl_rn].freeze
15
+ REL_INSTRUCTIONS = %i[rel].freeze
16
+ BIT_INSTRUCTIONS = %i[].freeze
17
+ SFX_INSTRUCTIONS = %i[imm4 rn rm rn_rn rn_imm8 rn_imm16 rn_addr rn_addrl addr_rn addrl_rn].freeze
18
+ MOV_INSTRUCTIONS = %i[rn_rn]
19
+ SHORT_ADDR_INSTRUCTIONS = %i[rn_addr addr_rn]
20
+ INV_DEST_INSTRUCTIONS = %i[addr_rn addrl_rn]
21
+
22
+ MODES_REGEXES = {
23
+ imp: /^$/, # nothing
24
+ imm4: /^##{HEX}$/, # #0-f
25
+ lnk: /^##{LNK}$/, # #1-4
26
+ rn: /^#{REG}$/, # R1
27
+ rm: /^\(#{REG}\)$/, # (R1)
28
+ rel: /^#{HEX16}$/i, # label / 1234
29
+ rn_rn: /^#{REG},#{REG}$/, # R1, R2
30
+ rn_imm8: /^#{REG},##{HEX8}$/, # R1, #12
31
+ rn_imm16: /^#{REG},##{HEX16}$/, # R1, #1234
32
+ rn_addr: /^#{REG},\(#{HEX16}\)$/, # R1, (1234) ; -> actual data is 1234 / 2
33
+ rn_addrl: /^#{REG},\(#{HEX16}\)$/, # R1, (1234) ; label
34
+ addr_rn: /^\(#{HEX16}\),#{REG}$/, # (1234), R1 ; -> actual data is 1234 / 2
35
+ addrl_rn: /^\(#{HEX16}\),#{REG}$/, # (1234), R1 ; label
36
+ }.freeze
37
+
38
+ OPCODES_DATA = [
39
+ # From game pak ROM to register
40
+ { opcode: 0xef, mnemonic: 'GETB', mode: :imp, length: 1, alt: nil },
41
+ { opcode: 0xef, mnemonic: 'GETBH', mode: :imp, length: 2, alt: 0x3d },
42
+ { opcode: 0xef, mnemonic: 'GETBL', mode: :imp, length: 2, alt: 0x3e },
43
+ { opcode: 0xef, mnemonic: 'GETBS', mode: :imp, length: 2, alt: 0x3f },
44
+ { opcode: 0xdf, mnemonic: 'GETC', mode: :imp, length: 1, alt: nil },
45
+
46
+ # From game pak RAM to register
47
+ { opcode: 0x4, mnemonic: 'LDW', mode: :rm, length: 1, alt: nil },
48
+ { opcode: 0x4, mnemonic: 'LDB', mode: :rm, length: 1, alt: 0x3d },
49
+ { opcode: 0xf, mnemonic: 'LM', mode: :rn_addrl, length: 4, alt: 0x3d },
50
+ { opcode: 0xa, mnemonic: 'LMS', mode: :rn_addr, length: 3, alt: 0x3d },
51
+
52
+ # From register to game pak RAM
53
+ { opcode: 0x3, mnemonic: 'STW', mode: :rm, length: 1, alt: nil },
54
+ { opcode: 0x3, mnemonic: 'STB', mode: :rm, length: 2, alt: 0x3d },
55
+ { opcode: 0xf, mnemonic: 'SM', mode: :addrl_rn, length: 4, alt: 0x3e },
56
+ { opcode: 0xa, mnemonic: 'SMS', mode: :addr_rn, length: 3, alt: 0x3e },
57
+ { opcode: 0x90, mnemonic: 'SBK', mode: :imp, length: 1, alt: nil },
58
+
59
+ # From register to register
60
+ { opcode: 0x2010, mnemonic: 'MOVE', mode: :rn_rn, length: 2, alt: nil },
61
+ { opcode: 0x20b0, mnemonic: 'MOVES', mode: :rn_rn, length: 2, alt: nil },
62
+
63
+ # Immediate data to register
64
+ { opcode: 0xf, mnemonic: 'IWT', mode: :rn_imm16, length: 3, alt: nil },
65
+ { opcode: 0xa, mnemonic: 'IBT', mode: :rn_imm8, length: 2, alt: nil },
66
+
67
+ # Arithmetic operations
68
+ { opcode: 0x5, mnemonic: 'ADD', mode: :rn, length: 1, alt: nil },
69
+ { opcode: 0x5, mnemonic: 'ADD', mode: :imm4, length: 2, alt: 0x3e },
70
+ { opcode: 0x5, mnemonic: 'ADC', mode: :rn, length: 2, alt: 0x3d },
71
+ { opcode: 0x5, mnemonic: 'ADC', mode: :imm4, length: 2, alt: 0x3f },
72
+
73
+ { opcode: 0x6, mnemonic: 'SUB', mode: :rn, length: 1, alt: nil },
74
+ { opcode: 0x6, mnemonic: 'SUB', mode: :imm4, length: 2, alt: 0x3e },
75
+ { opcode: 0x6, mnemonic: 'SBC', mode: :rn, length: 2, alt: 0x3d },
76
+
77
+ { opcode: 0x6, mnemonic: 'CMP', mode: :rn, length: 2, alt: 0x3f },
78
+
79
+ { opcode: 0x8, mnemonic: 'MULT', mode: :rn, length: 1, alt: nil },
80
+ { opcode: 0x8, mnemonic: 'MULT', mode: :imm4, length: 2, alt: 0x3e },
81
+ { opcode: 0x8, mnemonic: 'UMULT', mode: :rn, length: 2, alt: 0x3d },
82
+ { opcode: 0x8, mnemonic: 'UMULT', mode: :imm4, length: 2, alt: 0x3f },
83
+ { opcode: 0x9f, mnemonic: 'FMULT', mode: :imp, length: 1, alt: nil },
84
+ { opcode: 0x9f, mnemonic: 'LMULT', mode: :imp, length: 2, alt: 0x3d },
85
+
86
+ { opcode: 0x96, mnemonic: 'DIV2', mode: :imp, length: 2, alt: 0x3d },
87
+
88
+ { opcode: 0xd, mnemonic: 'INC', mode: :rn, length: 1, alt: nil },
89
+ { opcode: 0xe, mnemonic: 'DEC', mode: :rn, length: 1, alt: nil },
90
+
91
+ # Logical operations
92
+ { opcode: 0x7, mnemonic: 'AND', mode: :rn, length: 1, alt: nil },
93
+ { opcode: 0x7, mnemonic: 'AND', mode: :imm4, length: 2, alt: 0x3e },
94
+ { opcode: 0xc, mnemonic: 'OR', mode: :rn, length: 1, alt: nil },
95
+ { opcode: 0xc, mnemonic: 'OR', mode: :imm4, length: 2, alt: 0x3e },
96
+ { opcode: 0x4f, mnemonic: 'NOT', mode: :imp, length: 1, alt: nil },
97
+ { opcode: 0xc, mnemonic: 'XOR', mode: :rn, length: 2, alt: 0x3d },
98
+ { opcode: 0xc, mnemonic: 'XOR', mode: :imm4, length: 2, alt: 0x3f },
99
+ { opcode: 0x7, mnemonic: 'BIC', mode: :rn, length: 2, alt: 0x3d },
100
+ { opcode: 0x7, mnemonic: 'BIC', mode: :imm4, length: 2, alt: 0x3f },
101
+
102
+ # Shift
103
+ { opcode: 0x96, mnemonic: 'ASR', mode: :imp, length: 1, alt: nil },
104
+ { opcode: 0x03, mnemonic: 'LSR', mode: :imp, length: 1, alt: nil },
105
+ { opcode: 0x04, mnemonic: 'ROL', mode: :imp, length: 1, alt: nil },
106
+ { opcode: 0x97, mnemonic: 'ROR', mode: :imp, length: 1, alt: nil },
107
+
108
+ # Byte transfer
109
+ { opcode: 0xc0, mnemonic: 'HIB', mode: :imp, length: 1, alt: nil },
110
+ { opcode: 0x9e, mnemonic: 'LOB', mode: :imp, length: 1, alt: nil },
111
+ { opcode: 0x70, mnemonic: 'MERGE', mode: :imp, length: 1, alt: nil },
112
+ { opcode: 0x95, mnemonic: 'SEX', mode: :imp, length: 1, alt: nil },
113
+ { opcode: 0x4d, mnemonic: 'SWAP', mode: :imp, length: 1, alt: nil },
114
+
115
+ # Jump, branch and loop
116
+ { opcode: 0x9, mnemonic: 'JMP', mode: :rn, length: 1, alt: nil },
117
+ { opcode: 0x9, mnemonic: 'LJMP', mode: :rn, length: 2, alt: 0x3d },
118
+ { opcode: 0x05, mnemonic: 'BRA', mode: :rel, length: 2, alt: nil },
119
+ { opcode: 0x06, mnemonic: 'BGE', mode: :rel, length: 2, alt: nil },
120
+ { opcode: 0x07, mnemonic: 'BLT', mode: :rel, length: 2, alt: nil },
121
+ { opcode: 0x08, mnemonic: 'BNE', mode: :rel, length: 2, alt: nil },
122
+ { opcode: 0x09, mnemonic: 'BEQ', mode: :rel, length: 2, alt: nil },
123
+ { opcode: 0x0a, mnemonic: 'BPL', mode: :rel, length: 2, alt: nil },
124
+ { opcode: 0x0b, mnemonic: 'BMI', mode: :rel, length: 2, alt: nil },
125
+ { opcode: 0x0c, mnemonic: 'BCC', mode: :rel, length: 2, alt: nil },
126
+ { opcode: 0x0d, mnemonic: 'BCS', mode: :rel, length: 2, alt: nil },
127
+ { opcode: 0x0e, mnemonic: 'BVC', mode: :rel, length: 2, alt: nil },
128
+ { opcode: 0x0f, mnemonic: 'BVS', mode: :rel, length: 2, alt: nil },
129
+ { opcode: 0x3c, mnemonic: 'LOOP', mode: :imp, length: 1, alt: nil },
130
+ { opcode: 0x9, mnemonic: 'LINK', mode: :imm4, length: 1, alt: nil },
131
+
132
+ # Bank set-up
133
+ { opcode: 0xdf, mnemonic: 'ROMB', mode: :imp, length: 2, alt: 0x3f },
134
+ { opcode: 0xdf, mnemonic: 'RAMB', mode: :imp, length: 2, alt: 0x3e },
135
+
136
+ # Plot related
137
+ { opcode: 0x4e, mnemonic: 'CMODE', mode: :imp, length: 2, alt: 0x3d },
138
+ { opcode: 0x4e, mnemonic: 'COLOR', mode: :imp, length: 1, alt: nil },
139
+ { opcode: 0x4c, mnemonic: 'PLOT', mode: :imp, length: 1, alt: nil },
140
+ { opcode: 0x4c, mnemonic: 'RPIX', mode: :imp, length: 2, alt: 0x3d },
141
+
142
+ # Prefix flag
143
+ { opcode: 0x3d, mnemonic: 'ALT1', mode: :imp, length: 1, alt: nil },
144
+ { opcode: 0x3e, mnemonic: 'ALT2', mode: :imp, length: 1, alt: nil },
145
+ { opcode: 0x3f, mnemonic: 'ALT3', mode: :imp, length: 1, alt: nil },
146
+
147
+ # Prefix register
148
+ { opcode: 0xb, mnemonic: 'FROM', mode: :rn, length: 1, alt: nil },
149
+ { opcode: 0x1, mnemonic: 'TO', mode: :rn, length: 1, alt: nil },
150
+ { opcode: 0x2, mnemonic: 'WITH', mode: :rn, length: 1, alt: nil },
151
+
152
+ # GSU Control
153
+ { opcode: 0x02, mnemonic: 'CACHE', mode: :imp, length: 1, alt: nil },
154
+ { opcode: 0x01, mnemonic: 'NOP', mode: :imp, length: 1, alt: nil },
155
+ { opcode: 0x00, mnemonic: 'STOP', mode: :imp, length: 1, alt: nil }].freeze
156
+ end
157
+ end
158
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SnesUtils
2
4
  module Wdc65816
3
5
  class Definitions
@@ -6,70 +8,70 @@ module SnesUtils
6
8
  HEX16 = "\\$?(#{HEX_DIGIT}{3,4})"
7
9
  HEX24 = "\\$?(#{HEX_DIGIT}{5,6})"
8
10
 
9
- SINGLE_OPERAND_INSTRUCTIONS = [:imm, :iml, :imm8, :imm16, :sr, :dp, :dpx, :dpy, :idp, :idx, :idy, :idl, :idly, :isy, :abs, :abx, :aby, :abl, :alx, :ind, :iax, :ial, :rel, :rell]
10
- DOUBLE_OPERAND_INSTRUCTIONS = [:bm]
11
- REL_INSTRUCTIONS = [:rel, :rell]
12
- BIT_INSTRUCTIONS = []
11
+ SINGLE_OPERAND_INSTRUCTIONS = %i[imm iml imm8 imm16 sr dp dpx dpy idp idx idy idl idly isy abs abx aby abl alx ind iax ial rel rell].freeze
12
+ DOUBLE_OPERAND_INSTRUCTIONS = [:bm].freeze
13
+ REL_INSTRUCTIONS = %i[rel rell].freeze
14
+ BIT_INSTRUCTIONS = [].freeze
13
15
 
14
16
  MODES_REGEXES = {
15
- acc: /^$/,
16
- imp: /^$/,
17
- imm: /^#{HEX8}$/i,
18
- iml: /^#{HEX16}$/i,
19
- imm8: /^##{HEX8}$/i,
17
+ acc: /^$/,
18
+ imp: /^$/,
19
+ imm: /^#{HEX8}$/i,
20
+ iml: /^#{HEX16}$/i,
21
+ imm8: /^##{HEX8}$/i,
20
22
  imm16: /^##{HEX16}$/i,
21
- sr: /^#{HEX8},S$/i,
22
- dp: /^#{HEX8}$/i,
23
- dpx: /^#{HEX8},X$/i,
24
- dpy: /^#{HEX8},Y$/i,
25
- idp: /^\(#{HEX8}\)$/i,
26
- idx: /^\(#{HEX8},X\)$/i,
27
- idy: /^\(#{HEX8}\),Y$/i,
28
- idl: /^\[#{HEX8}\]$/i,
29
- idly: /^\[#{HEX8}\],Y$/i,
30
- isy: /^\(#{HEX8},S\),Y$/i,
31
- abs: /^#{HEX16}$/i,
32
- abx: /^#{HEX16},X$/i,
33
- aby: /^#{HEX16},Y$/i,
34
- abl: /^#{HEX24}$/i,
35
- alx: /^#{HEX24},X$/i,
36
- ind: /^\(#{HEX16}\)$/i,
37
- iax: /^\(#{HEX16},X\)$/i,
38
- ial: /^\[#{HEX16}\]$/i,
39
- rel: /^#{HEX16}$/i,
40
- rell: /^#{HEX16}$/i,
41
- bm: /^#{HEX8},#{HEX8}$/i
42
- }
23
+ sr: /^#{HEX8},S$/i,
24
+ dp: /^#{HEX8}$/i,
25
+ dpx: /^#{HEX8},X$/i,
26
+ dpy: /^#{HEX8},Y$/i,
27
+ idp: /^\(#{HEX8}\)$/i,
28
+ idx: /^\(#{HEX8},X\)$/i,
29
+ idy: /^\(#{HEX8}\),Y$/i,
30
+ idl: /^\[#{HEX8}\]$/i,
31
+ idly: /^\[#{HEX8}\],Y$/i,
32
+ isy: /^\(#{HEX8},S\),Y$/i,
33
+ abs: /^#{HEX16}$/i,
34
+ abx: /^#{HEX16},X$/i,
35
+ aby: /^#{HEX16},Y$/i,
36
+ abl: /^#{HEX24}$/i,
37
+ alx: /^#{HEX24},X$/i,
38
+ ind: /^\(#{HEX16}\)$/i,
39
+ iax: /^\(#{HEX16},X\)$/i,
40
+ ial: /^\[#{HEX16}\]$/i,
41
+ rel: /^#{HEX16}$/i,
42
+ rell: /^#{HEX16}$/i,
43
+ bm: /^#{HEX8},#{HEX8}$/i
44
+ }.freeze
43
45
 
44
46
  MODES_FORMATS = {
45
- acc: "%s",
46
- imp: "%s",
47
- imm: "%s %02X",
48
- iml: "%s %02X",
49
- imm8: "%s #%02X",
50
- imm16: "%s #%04X",
51
- sr: "%s %02X,S",
52
- dp: "%s %02X",
53
- dpx: "%s %02X,X",
54
- dpy: "%s %02X,Y",
55
- idp: "%s (%02X)",
56
- idx: "%s (%02X,X)",
57
- idy: "%s (%02X),Y",
58
- idl: "%s [%02X]",
59
- idly: "%s [%02X],Y",
60
- isy: "%s (%02X,S),Y",
61
- abs: "%s %04X",
62
- abx: "%s %04X,X",
63
- aby: "%s %04X,Y",
64
- abl: "%s %06X",
65
- alx: "%s %06X,X",
66
- ind: "%s (%04X)",
67
- iax: "%s (%04X,X)",
68
- ial: "%s [%04X]",
69
- rel: "%s %04X {%s}",
70
- rell: "%s %04X {%s}",
71
- bm: "%s %02X,%02X"
72
- }
47
+ acc: '%s',
48
+ imp: '%s',
49
+ imm: '%s %02X',
50
+ iml: '%s %02X',
51
+ imm8: '%s #%02X',
52
+ imm16: '%s #%04X',
53
+ sr: '%s %02X,S',
54
+ dp: '%s %02X',
55
+ dpx: '%s %02X,X',
56
+ dpy: '%s %02X,Y',
57
+ idp: '%s (%02X)',
58
+ idx: '%s (%02X,X)',
59
+ idy: '%s (%02X),Y',
60
+ idl: '%s [%02X]',
61
+ idly: '%s [%02X],Y',
62
+ isy: '%s (%02X,S),Y',
63
+ abs: '%s %04X',
64
+ abx: '%s %04X,X',
65
+ aby: '%s %04X,Y',
66
+ abl: '%s %06X',
67
+ alx: '%s %06X,X',
68
+ ind: '%s (%04X)',
69
+ iax: '%s (%04X,X)',
70
+ ial: '%s [%04X]',
71
+ rel: '%s %04X {%s}',
72
+ rell: '%s %04X {%s}',
73
+ bm: '%s %02X,%02X'
74
+ }.freeze
73
75
 
74
76
  OPCODES_DATA = [{ opcode: 0x61, mnemonic: 'ADC', mode: :idx, length: 2 },
75
77
  { opcode: 0x63, mnemonic: 'ADC', mode: :sr, length: 2 },
@@ -1,22 +1,34 @@
1
1
  module SnesUtils
2
2
  class Png2Snes
3
- def initialize(file_path, bpp:4, alpha:nil)
3
+ CHAR_SIZE = 8
4
+
5
+ def initialize(file_path, bpp:4, alpha:nil, mode7: false, m7_palette_offset: nil)
4
6
  @file_path = file_path
5
7
  @file_dir = File.dirname(@file_path)
6
8
  @file_name = File.basename(@file_path, File.extname(@file_path))
7
9
  @image = ChunkyPNG::Image.from_file(@file_path)
8
- @pixels = pixels_to_bgr5
9
10
 
11
+ @mode7 = mode7
12
+
13
+ raise ArgumentError, 'Image width and height must be a multiple of sprite size' if (@image.width % CHAR_SIZE != 0) or (@image.height % CHAR_SIZE != 0)
14
+
15
+ @pixels = pixels_to_bgr5
10
16
  @palette = @pixels.uniq
11
- @char_size = 8
12
17
 
13
- raise ArgumentError, 'BPP must be 2, 4, or 8' unless [2, 4, 8].include? bpp
14
- @bpp = bpp
18
+ if @mode7
19
+ raise ArgumentError, 'mode 7 palette offset must be multiple of 16' if m7_palette_offset % 16 != 0
20
+ raise ArgumentError, 'mode 7 palette offset must be less than 112' if m7_palette_offset > 112
21
+ @m7_palette_offset = m7_palette_offset
15
22
 
16
- raise ArgumentError, 'Image width and height must be a multiple of sprite size' if (@image.width % @char_size != 0) or (@image.height % @char_size != 0)
23
+ unshift_alpha(alpha) if alpha
24
+ fill_palette
25
+ else
26
+ raise ArgumentError, 'BPP must be 2, 4, or 8' unless [2, 4, 8].include? bpp
27
+ @bpp = bpp
17
28
 
18
- alpha_first if alpha
19
- fill_palette
29
+ unshift_alpha(alpha) if alpha
30
+ fill_palette
31
+ end
20
32
  end
21
33
 
22
34
  def pixels_to_bgr5
@@ -29,17 +41,22 @@ module SnesUtils
29
41
  end
30
42
  end
31
43
 
32
- def alpha_first
44
+ def unshift_alpha(alpha)
45
+ @palette.unshift(alpha)
33
46
  end
34
47
 
35
48
  def fill_palette
36
- target_size = 2**@bpp
49
+ target_size = @mode7 ? mode_7_pal_size : 2**@bpp
37
50
  missing_colors = target_size - @palette.count
38
51
  raise ArgumentError, "Palette size too large for target BPP (#{@palette.count})" if missing_colors < 0
39
52
 
40
53
  @palette += [0] * missing_colors
41
54
  end
42
55
 
56
+ def mode_7_pal_size
57
+ 128 - @m7_palette_offset
58
+ end
59
+
43
60
  def write hex, file_path
44
61
  File.open(file_path, 'w+b') do |file|
45
62
  file.write([hex.join].pack('H*'))
@@ -48,7 +65,7 @@ module SnesUtils
48
65
 
49
66
  def write_palette
50
67
  palette_hex = @palette.map { |c| ('%04x' % c).scan(/.{2}/).reverse.join }
51
- write palette_hex, File.expand_path("#{@file_name}-pal.bin", @file_dir)
68
+ write palette_hex, File.expand_path("#{@file_name}.pal", @file_dir)
52
69
  end
53
70
 
54
71
  def pixel_indices
@@ -60,16 +77,20 @@ module SnesUtils
60
77
  def extract_sprites
61
78
  pixel_idx = pixel_indices
62
79
 
63
- sprite_per_row = @image.width / @char_size
64
- sprite_per_col = @image.height / @char_size
80
+ sprite_per_row = @image.width / CHAR_SIZE
81
+ sprite_per_col = @image.height / CHAR_SIZE
65
82
  sprite_per_sheet = sprite_per_row * sprite_per_col
66
83
 
67
84
  sprites = []
68
85
  (0..sprite_per_sheet-1).each do |s|
69
86
  sprite = []
70
- (0..@char_size-1).each do |r|
71
- offset = (s/sprite_per_row)*sprite_per_row * @char_size**2 + s % sprite_per_row * @char_size
72
- sprite += pixel_idx[offset + r*sprite_per_row*@char_size, @char_size]
87
+ (0..CHAR_SIZE-1).each do |r|
88
+ offset = (s/sprite_per_row)*sprite_per_row * CHAR_SIZE**2 + s % sprite_per_row * CHAR_SIZE
89
+ if @mode7
90
+ sprite += @pixels[offset + r*sprite_per_row*CHAR_SIZE, CHAR_SIZE]
91
+ else
92
+ sprite += pixel_idx[offset + r*sprite_per_row*CHAR_SIZE, CHAR_SIZE]
93
+ end
73
94
  end
74
95
  sprites.push(sprite)
75
96
  end
@@ -87,7 +108,11 @@ module SnesUtils
87
108
  end
88
109
 
89
110
  def write_image
90
- sprite_per_row = @image.width / @char_size
111
+ @mode7 ? write_image_m7 : write_image_m06
112
+ end
113
+
114
+ def write_image_m06
115
+ sprite_per_row = @image.width / CHAR_SIZE
91
116
  sprites = extract_sprites
92
117
  sprites_bitplanes = sprites.map { |s| extract_bitplanes s }
93
118
 
@@ -97,9 +122,9 @@ module SnesUtils
97
122
 
98
123
  bitplane_bits = ""
99
124
  sprite_bitplane_pairs.each do |bitplane|
100
- (0..@char_size-1).each do |r|
101
- offset = r*@char_size
102
- bitplane_bits += bitplane[0][offset, @char_size].join + bitplane[1][offset, @char_size].join
125
+ (0..CHAR_SIZE-1).each do |r|
126
+ offset = r*CHAR_SIZE
127
+ bitplane_bits += bitplane[0][offset, CHAR_SIZE].join + bitplane[1][offset, CHAR_SIZE].join
103
128
  end
104
129
  end
105
130
  image_bits += bitplane_bits
@@ -107,8 +132,15 @@ module SnesUtils
107
132
  end
108
133
 
109
134
  image_hex = image_bits.scan(/.{8}/).map { |b| "%02x" % b.to_i(2) }
110
- write image_hex, File.expand_path("#{@file_name}.bin", @file_dir)
135
+ write image_hex, File.expand_path("#{@file_name}.tiles", @file_dir)
111
136
  end
112
137
 
138
+ def write_image_m7
139
+ sprites = extract_sprites
140
+
141
+ indices = sprites.flatten.map { |color| "%02x" % (@palette.index(color) + @m7_palette_offset) }
142
+
143
+ write indices, File.expand_path("#{@file_name}.tiles", @file_dir)
144
+ end
113
145
  end
114
146
  end
data/lib/snes_utils.rb CHANGED
@@ -1,16 +1,16 @@
1
1
  require 'readline'
2
2
  require 'chunky_png'
3
- require 'matrix'
4
- require 'nokogiri'
5
-
6
- require 'byebug'
3
+ require 'csv'
7
4
 
8
5
  require 'mini_assembler/mini_assembler'
9
6
  require 'mini_assembler/definitions'
10
7
  require 'mini_assembler/wdc65816/definitions'
11
8
  require 'mini_assembler/spc700/definitions'
9
+ require 'mini_assembler/superfx/definitions'
12
10
  require 'png2snes/png2snes'
13
11
  require 'tmx2snes/tmx2snes'
14
12
 
13
+ require 'vas/vas'
14
+
15
15
  module SnesUtils
16
16
  end
@@ -14,14 +14,9 @@ module SnesUtils
14
14
  tnm = big_char ? 2 : 1 # big_char : 16x16 tiles. otherwise, 8x8 tiles
15
15
  row_offset = 16 * (tnm - 1) # Skip a row in case of 16x16 tiles ( tile #9 starts at index 32)
16
16
 
17
- doc = Nokogiri::XML(File.open(@file_path))
18
- csv_node = doc.xpath('//data').children.first.to_s
19
-
20
- csv = csv_node.split("\n").compact.reject { |e| e.empty? }.map { |row| row.split(',') }
21
-
22
- csv.each do |row|
17
+ CSV.foreach(@file_path) do |row|
23
18
  raise if row.length != 32
24
- @tilemap += row.map { |r| (r.to_i - 1)*tnm + row_offset * ((r.to_i - 1)/8).to_i }
19
+ @tilemap += row.map { |r| (r.to_i)*tnm + row_offset * ((r.to_i)/8).to_i }
25
20
  end
26
21
 
27
22
  raise if @tilemap.length != 32*32