Skip to content

Commit 175f68b

Browse files
committed
save ROM
1 parent e565665 commit 175f68b

File tree

2 files changed

+77
-0
lines changed

2 files changed

+77
-0
lines changed

FF4/FF4Rom.cs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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
}

FF4MapEdit/MainWindow.xaml.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,22 @@ private void OpenButton_Click(object sender, RoutedEventArgs e)
6363
LoadOverworld();
6464
}
6565

66+
private void SaveButton_Click(object sender, RoutedEventArgs e)
67+
{
68+
if (_map != null)
69+
{
70+
try
71+
{
72+
_rom.SaveOverworldMap(_map);
73+
_rom.Save(_filename);
74+
}
75+
catch (IndexOutOfRangeException ex) when (ex.Message.StartsWith("Overworld map data is too big"))
76+
{
77+
MessageBox.Show(ex.Message, "Error while saving");
78+
}
79+
}
80+
}
81+
6682
private void Tileset_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
6783
{
6884
int x, y;

0 commit comments

Comments
 (0)