Skip to content

Commit 39bec40

Browse files
committed
fix tileset shrink bug, edit tile properties
1 parent 30cecd8 commit 39bec40

File tree

6 files changed

+134
-7
lines changed

6 files changed

+134
-7
lines changed

FF4/FF4.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
<Compile Include="Map.cs" />
4949
<Compile Include="MapType.cs" />
5050
<Compile Include="Properties\AssemblyInfo.cs" />
51+
<Compile Include="TileProperties.cs" />
5152
<Compile Include="Tileset.cs" />
5253
</ItemGroup>
5354
<ItemGroup>

FF4/FF4Rom.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,12 +67,17 @@ public void LoadOverworldMap()
6767

6868
var subTiles = Get(OverworldSubTileGraphicsOffset, 32 * MapSubTileCount);
6969
var formations = Get(OverworldTileFormationsOffset, 4 * MapTileCount);
70+
7071
var paletteBytes = Get(OverworldPaletteOffset, 2 * 64);
7172
var palette = new ushort[64];
7273
Buffer.BlockCopy(paletteBytes, 0, palette, 0, 2 * 64);
7374
var paletteOffsets = Get(OverworldSubTilePaletteOffsetsOffset, MapSubTileCount);
7475

75-
Tileset = new Tileset(subTiles, formations, palette, paletteOffsets);
76+
var propertyBytes = Get(OverworldTilePropertiesOffset, MapTileCount*2);
77+
var tileProperties = new ushort[MapTileCount];
78+
Buffer.BlockCopy(propertyBytes, 0, tileProperties, 0, propertyBytes.Length);
79+
80+
Tileset = new Tileset(subTiles, formations, palette, paletteOffsets, tileProperties);
7681
}
7782

7883
public void SaveOverworldMap()
@@ -89,8 +94,12 @@ public void SaveOverworldMap()
8994
Map.GetCompressedData(out data, out pointers);
9095
Buffer.BlockCopy(pointers, 0, pointerBytes, 0, pointerBytes.Length);
9196

97+
byte[] propertyBytes = new byte[MapTileCount*2];
98+
Buffer.BlockCopy(Tileset.TileProperties, 0, propertyBytes, 0, propertyBytes.Length);
99+
92100
Put(OverworldRowDataOffset, data);
93101
Put(OverworldRowPointersOffset, pointerBytes);
102+
Put(OverworldTilePropertiesOffset, propertyBytes);
94103
}
95104
}
96105
}

FF4/TileProperties.cs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace FF4
8+
{
9+
[Flags]
10+
public enum WorldTileProperties
11+
{
12+
Walk = 0x0001,
13+
ChocoboWalk = 0x0002,
14+
BlackChocoboFly = 0x0004,
15+
BlackChocoboLand = 0x0008,
16+
Hovercraft = 0x0010,
17+
AirshipFly = 0x0020,
18+
Walk2 = 0x0040,
19+
BigWhaleFly = 0x0080,
20+
ObscuresHalf = 0x0800,
21+
AirshipLand = 0x1000,
22+
EnemyEncounters = 0x4000,
23+
Entrance = 0x8000
24+
}
25+
26+
[Flags]
27+
public enum AreaTileProperties
28+
{
29+
Walk = 0x0001,
30+
SavePoint = 0x0008,
31+
Damage = 0x0100,
32+
ObscuresAll = 0x0400,
33+
ObscuresHalf = 0x0800,
34+
Exit = 0x1000,
35+
Entrance = 0x8000
36+
}
37+
}

FF4/Tileset.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@ namespace FF4
99
public class Tileset
1010
{
1111
private readonly ushort[][] _tilesetBytes;
12+
public ushort[] TileProperties { get; private set; }
1213

1314
public ushort[] this[int tileIndex] => _tilesetBytes[tileIndex];
1415

15-
public Tileset(byte[] subTiles, byte[] formations, ushort[] palette, byte[] paletteOffsets)
16+
public Tileset(byte[] subTiles, byte[] formations, ushort[] palette, byte[] paletteOffsets, ushort[] tileProperties)
1617
{
1718
RgbToBgr(palette);
1819

@@ -30,6 +31,8 @@ public Tileset(byte[] subTiles, byte[] formations, ushort[] palette, byte[] pale
3031
subTileIndex = formations[i + 3 * tileCount];
3132
CopySubTileToTile(subTiles, 32 * subTileIndex, _tilesetBytes[i], 8 * 16 + 8, palette, paletteOffsets[subTileIndex]);
3233
}
34+
35+
TileProperties = tileProperties;
3336
}
3437

3538
private void CopySubTileToTile(byte[] subTiles, int subTilesOffset, ushort[] tile, int tileOffset, ushort[] palette, int paletteOffset)

FF4MapEdit/MainWindow.xaml

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,24 @@
1717
</Button>
1818
</ToolBar>
1919
</ToolBarTray>
20-
<Image x:Name="Tileset" HorizontalAlignment="Left" Height="128" Margin="10,35,0,0" VerticalAlignment="Top" Width="256" MouseLeftButtonUp="Tileset_MouseLeftButtonUp"/>
20+
<Image x:Name="Tileset" HorizontalAlignment="Left" Height="128" Margin="10,35,0,0" VerticalAlignment="Top" Width="256" MouseLeftButtonUp="Tileset_MouseLeftButtonUp" Stretch="None"/>
2121
<ScrollViewer HorizontalScrollBarVisibility="Auto" HorizontalAlignment="Left" Margin="271,35,0,0" VerticalAlignment="Top">
22-
<Image x:Name="Map" HorizontalAlignment="Left" Height="4096" Margin="0,0,0,0" VerticalAlignment="Top" Width="4096" MouseLeftButtonUp="Map_MouseLeftButtonUp" MouseLeftButtonDown="Map_MouseLeftButtonDown" MouseMove="Map_MouseMove"/>
22+
<Image x:Name="Map" HorizontalAlignment="Left" Height="4096" Margin="0,0,0,0" VerticalAlignment="Top" Width="4096" MouseLeftButtonUp="Map_MouseLeftButtonUp" MouseLeftButtonDown="Map_MouseLeftButtonDown" MouseMove="Map_MouseMove" Stretch="None"/>
2323
</ScrollViewer>
24-
<Label x:Name="SpaceUsedLabel" Content="" HorizontalAlignment="Left" Margin="10,168,0,0" VerticalAlignment="Top"/>
24+
<Label x:Name="SpaceUsedLabel" Content="" HorizontalAlignment="Left" Margin="10,433,0,0" VerticalAlignment="Top"/>
25+
<Grid x:Name="TilePropertiesGrid" HorizontalAlignment="Left" Margin="10,168,0,0" VerticalAlignment="Top" Width="256" Height="260" Visibility="Hidden">
26+
<CheckBox x:Name="WalkCheckBox" Content="Walk" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top"/>
27+
<CheckBox x:Name="ChocoboWalkCheckBox" Content="Chocobo Walk" HorizontalAlignment="Left" Margin="10,30,0,0" VerticalAlignment="Top"/>
28+
<CheckBox x:Name="BlackChocoboFlyCheckBox" Content="Black Chocobo Fly" HorizontalAlignment="Left" Margin="10,50,0,0" VerticalAlignment="Top"/>
29+
<CheckBox x:Name="BlackChocoboLandCheckBox" Content="Black Chocobo Land" HorizontalAlignment="Left" Margin="10,70,0,0" VerticalAlignment="Top"/>
30+
<CheckBox x:Name="HovercraftCheckBox" Content="Hovercraft" HorizontalAlignment="Left" Margin="10,90,0,0" VerticalAlignment="Top"/>
31+
<CheckBox x:Name="AirshipFlyCheckBox" Content="Airship Fly" HorizontalAlignment="Left" Margin="10,110,0,0" VerticalAlignment="Top"/>
32+
<CheckBox x:Name="Walk2CheckBox" Content="Walk 2?" HorizontalAlignment="Left" Margin="10,130,0,0" VerticalAlignment="Top"/>
33+
<CheckBox x:Name="BigWhaleFlyCheckBox" Content="Big Whale Fly" HorizontalAlignment="Left" Margin="10,150,0,0" VerticalAlignment="Top"/>
34+
<CheckBox x:Name="ObscuresHalfCheckBox" Content="Obscures Half" HorizontalAlignment="Left" Margin="10,170,0,0" VerticalAlignment="Top"/>
35+
<CheckBox x:Name="AirshipLandCheckBox" Content="Airship Land" HorizontalAlignment="Left" Margin="10,190,0,0" VerticalAlignment="Top"/>
36+
<CheckBox x:Name="EnemyEncountersCheckBox" Content="Enemy Encounters" HorizontalAlignment="Left" Margin="10,210,0,0" VerticalAlignment="Top"/>
37+
<CheckBox x:Name="EntranceCheckBox" Content="Entrance" HorizontalAlignment="Left" Margin="10,230,0,0" VerticalAlignment="Top"/>
38+
</Grid>
2539
</Grid>
2640
</Window>

FF4MapEdit/MainWindow.xaml.cs

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,44 @@ private int SpaceUsed
4343
public MainWindow()
4444
{
4545
InitializeComponent();
46+
47+
WalkCheckBox.Checked += (sender, e) => OnPropertyCheckBoxCheckChanged(WorldTileProperties.Walk, true);
48+
ChocoboWalkCheckBox.Checked += (sender, e) => OnPropertyCheckBoxCheckChanged(WorldTileProperties.ChocoboWalk, true);
49+
BlackChocoboFlyCheckBox.Checked += (sender, e) => OnPropertyCheckBoxCheckChanged(WorldTileProperties.BlackChocoboFly, true);
50+
BlackChocoboLandCheckBox.Checked += (sender, e) => OnPropertyCheckBoxCheckChanged(WorldTileProperties.BlackChocoboLand, true);
51+
HovercraftCheckBox.Checked += (sender, e) => OnPropertyCheckBoxCheckChanged(WorldTileProperties.Hovercraft, true);
52+
AirshipFlyCheckBox.Checked += (sender, e) => OnPropertyCheckBoxCheckChanged(WorldTileProperties.AirshipFly, true);
53+
Walk2CheckBox.Checked += (sender, e) => OnPropertyCheckBoxCheckChanged(WorldTileProperties.Walk2, true);
54+
BigWhaleFlyCheckBox.Checked += (sender, e) => OnPropertyCheckBoxCheckChanged(WorldTileProperties.BigWhaleFly, true);
55+
ObscuresHalfCheckBox.Checked += (sender, e) => OnPropertyCheckBoxCheckChanged(WorldTileProperties.ObscuresHalf, true);
56+
AirshipLandCheckBox.Checked += (sender, e) => OnPropertyCheckBoxCheckChanged(WorldTileProperties.AirshipLand, true);
57+
EnemyEncountersCheckBox.Checked += (sender, e) => OnPropertyCheckBoxCheckChanged(WorldTileProperties.EnemyEncounters, true);
58+
EntranceCheckBox.Checked += (sender, e) => OnPropertyCheckBoxCheckChanged(WorldTileProperties.Entrance, true);
59+
60+
WalkCheckBox.Unchecked += (sender, e) => OnPropertyCheckBoxCheckChanged(WorldTileProperties.Walk, false);
61+
ChocoboWalkCheckBox.Unchecked += (sender, e) => OnPropertyCheckBoxCheckChanged(WorldTileProperties.ChocoboWalk, false);
62+
BlackChocoboFlyCheckBox.Unchecked += (sender, e) => OnPropertyCheckBoxCheckChanged(WorldTileProperties.BlackChocoboFly, false);
63+
BlackChocoboLandCheckBox.Unchecked += (sender, e) => OnPropertyCheckBoxCheckChanged(WorldTileProperties.BlackChocoboLand, false);
64+
HovercraftCheckBox.Unchecked += (sender, e) => OnPropertyCheckBoxCheckChanged(WorldTileProperties.Hovercraft, false);
65+
AirshipFlyCheckBox.Unchecked += (sender, e) => OnPropertyCheckBoxCheckChanged(WorldTileProperties.AirshipFly, false);
66+
Walk2CheckBox.Unchecked += (sender, e) => OnPropertyCheckBoxCheckChanged(WorldTileProperties.Walk2, false);
67+
BigWhaleFlyCheckBox.Unchecked += (sender, e) => OnPropertyCheckBoxCheckChanged(WorldTileProperties.BigWhaleFly, false);
68+
ObscuresHalfCheckBox.Unchecked += (sender, e) => OnPropertyCheckBoxCheckChanged(WorldTileProperties.ObscuresHalf, false);
69+
AirshipLandCheckBox.Unchecked += (sender, e) => OnPropertyCheckBoxCheckChanged(WorldTileProperties.AirshipLand, false);
70+
EnemyEncountersCheckBox.Unchecked += (sender, e) => OnPropertyCheckBoxCheckChanged(WorldTileProperties.EnemyEncounters, false);
71+
EntranceCheckBox.Unchecked += (sender, e) => OnPropertyCheckBoxCheckChanged(WorldTileProperties.Entrance, false);
72+
}
73+
74+
private void OnPropertyCheckBoxCheckChanged(WorldTileProperties property, bool isChecked)
75+
{
76+
if (isChecked)
77+
{
78+
_rom.Tileset.TileProperties[_selectedTile] |= (ushort)property;
79+
}
80+
else
81+
{
82+
_rom.Tileset.TileProperties[_selectedTile] &= (ushort)~property;
83+
}
4684
}
4785

4886
private void OpenButton_Click(object sender, RoutedEventArgs e)
@@ -97,11 +135,19 @@ private void Tileset_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
97135

98136
_selectedTile = 16*y + x;
99137

138+
HighlightSelectedTile(x, y);
139+
140+
CheckTilePropertyBoxes();
141+
TilePropertiesGrid.Visibility = Visibility.Visible;
142+
}
143+
144+
private void HighlightSelectedTile(int x, int y)
145+
{
100146
var tileGroup = (DrawingGroup)((DrawingImage)Tileset.Source).Drawing;
101147
tileGroup.Children.Remove(_selectedTileDrawing);
102148

103149
var geometry = new GeometryGroup();
104-
geometry.Children.Add(new RectangleGeometry(new Rect(new Point(16*x, 16*y), new Size(16, 16))));
150+
geometry.Children.Add(new RectangleGeometry(new Rect(new Point(16*x + 1, 16*y + 1), new Size(14, 14))));
105151
_selectedTileDrawing = new GeometryDrawing
106152
{
107153
Geometry = geometry,
@@ -112,6 +158,24 @@ private void Tileset_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
112158
tileGroup.Children.Add(_selectedTileDrawing);
113159
}
114160

161+
private void CheckTilePropertyBoxes()
162+
{
163+
var tileProperties = (WorldTileProperties)_rom.Tileset.TileProperties[_selectedTile];
164+
165+
WalkCheckBox.IsChecked = tileProperties.HasFlag(WorldTileProperties.Walk);
166+
ChocoboWalkCheckBox.IsChecked = tileProperties.HasFlag(WorldTileProperties.ChocoboWalk);
167+
BlackChocoboFlyCheckBox.IsChecked = tileProperties.HasFlag(WorldTileProperties.BlackChocoboFly);
168+
BlackChocoboLandCheckBox.IsChecked = tileProperties.HasFlag(WorldTileProperties.BlackChocoboLand);
169+
HovercraftCheckBox.IsChecked = tileProperties.HasFlag(WorldTileProperties.Hovercraft);
170+
AirshipFlyCheckBox.IsChecked = tileProperties.HasFlag(WorldTileProperties.AirshipFly);
171+
Walk2CheckBox.IsChecked = tileProperties.HasFlag(WorldTileProperties.Walk2);
172+
BigWhaleFlyCheckBox.IsChecked = tileProperties.HasFlag(WorldTileProperties.BigWhaleFly);
173+
ObscuresHalfCheckBox.IsChecked = tileProperties.HasFlag(WorldTileProperties.ObscuresHalf);
174+
AirshipLandCheckBox.IsChecked = tileProperties.HasFlag(WorldTileProperties.AirshipLand);
175+
EnemyEncountersCheckBox.IsChecked = tileProperties.HasFlag(WorldTileProperties.EnemyEncounters);
176+
EntranceCheckBox.IsChecked = tileProperties.HasFlag(WorldTileProperties.Entrance);
177+
}
178+
115179
private void Map_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
116180
{
117181
if (_selectedTile == -1)
@@ -225,7 +289,6 @@ private void LoadOverworldTiles()
225289
}
226290

227291
Map.Source = new DrawingImage(rowGroup);
228-
Map.Stretch = Stretch.None;
229292
}
230293
}
231294
}

0 commit comments

Comments
 (0)