@@ -12,6 +12,7 @@ public class FF4Rom : SnesRom
1212 {
1313 public const int OverworldRowPointersOffset = 0xB0000 ;
1414 public const int OverworldRowDataOffset = 0xB0480 ;
15+ public const int OverworldRowDataMaxLength = 0x4000 ;
1516 public const int OverworldRowCount = 256 ;
1617 public const int OverworldRowLength = 256 ;
1718 public const int OverworldSubTileGraphicsOffset = 0xE8000 ;
@@ -130,5 +131,65 @@ public ushort[] GetOverworldPalette()
130131
131132 return rows ;
132133 }
134+
135+ public void SaveOverworldMap ( byte [ , ] map )
136+ {
137+ var compressedBytes = new byte [ OverworldRowCount * OverworldRowLength ] ;
138+ ushort dataOffset = 0 ;
139+ var pointers = new ushort [ OverworldRowCount ] ;
140+
141+ for ( int y = 0 ; y < OverworldRowCount ; y ++ )
142+ {
143+ pointers [ y ] = dataOffset ;
144+ int x = 0 ;
145+ while ( x < OverworldRowLength )
146+ {
147+ if ( map [ y , x ] == 0x00 || map [ y , x ] == 0x10 || map [ y , x ] == 0x20 || map [ y , x ] == 0x30 )
148+ {
149+ compressedBytes [ dataOffset ++ ] = map [ y , x ] ;
150+ x += 4 ;
151+ }
152+ else if ( x == OverworldRowLength - 1 )
153+ {
154+ compressedBytes [ dataOffset ++ ] = map [ y , x ++ ] ;
155+ }
156+ else if ( map [ y , x + 1 ] == map [ y , x ] )
157+ {
158+ compressedBytes [ dataOffset ++ ] = ( byte ) ( map [ y , x ++ ] + 0x80 ) ;
159+
160+ byte repeatCount = 0 ;
161+ while ( x < OverworldRowLength && map [ y , x - 1 ] == map [ y , x ] )
162+ {
163+ x ++ ;
164+ repeatCount ++ ;
165+ }
166+ compressedBytes [ dataOffset ++ ] = repeatCount ;
167+ }
168+ else
169+ {
170+ compressedBytes [ dataOffset ++ ] = map [ y , x ++ ] ;
171+ }
172+ }
173+
174+ compressedBytes [ dataOffset ++ ] = 0xFF ;
175+ }
176+
177+ if ( dataOffset > OverworldRowDataMaxLength )
178+ {
179+ throw new IndexOutOfRangeException ( $ "Overworld map data is too big: { dataOffset } bytes used, { OverworldRowDataMaxLength } bytes allowed") ;
180+ }
181+
182+ var pointerBytes = new byte [ OverworldRowCount * 2 ] ;
183+ Buffer . BlockCopy ( pointers , 0 , pointerBytes , 0 , pointerBytes . Length ) ;
184+ Put ( OverworldRowPointersOffset , pointerBytes ) ;
185+
186+ var mapDataBytes = new byte [ OverworldRowDataMaxLength ] ;
187+ Buffer . BlockCopy ( compressedBytes , 0 , mapDataBytes , 0 , dataOffset ) ;
188+ while ( dataOffset < OverworldRowDataMaxLength )
189+ {
190+ mapDataBytes [ dataOffset ++ ] = 0xFF ;
191+ }
192+ Put ( OverworldRowDataOffset , mapDataBytes ) ;
193+ }
133194 }
134195}
0 commit comments