Original source code

This commit is contained in:
suloku 2024-08-02 16:04:49 +02:00
parent 271ab34f0c
commit fe3c102f80
28 changed files with 3855 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/ClassicMap/bin
/ClassicMap/obj

20
ClassicMap.sln Normal file
View File

@ -0,0 +1,20 @@

Microsoft Visual Studio Solution File, Format Version 10.00
# Visual C# Express 2008
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClassicMap", "ClassicMap\ClassicMap.csproj", "{B4591C7A-5431-452F-92FB-91098E7CE7FC}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{B4591C7A-5431-452F-92FB-91098E7CE7FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B4591C7A-5431-452F-92FB-91098E7CE7FC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B4591C7A-5431-452F-92FB-91098E7CE7FC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B4591C7A-5431-452F-92FB-91098E7CE7FC}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

BIN
ClassicMap.suo Normal file

Binary file not shown.

View File

@ -0,0 +1,109 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{B4591C7A-5431-452F-92FB-91098E7CE7FC}</ProjectGuid>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>ClassicMap</RootNamespace>
<AssemblyName>ClassicMap</AssemblyName>
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkSubset>
</TargetFrameworkSubset>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="GBHL, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\GBHL\GBHL\bin\Debug\GBHL.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="FastPixel.cs" />
<Compile Include="Form1.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Form1.Designer.cs">
<DependentUpon>Form1.cs</DependentUpon>
</Compile>
<Compile Include="MapEvents.cs" />
<Compile Include="MapLoader.cs" />
<Compile Include="MapSaver.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<EmbeddedResource Include="Form1.resx">
<DependentUpon>Form1.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
<DesignTime>True</DesignTime>
</Compile>
<None Include="app.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<Compile Include="SpriteLoader.cs" />
<Compile Include="TextTable.cs" />
<Compile Include="TilesetLoader.cs" />
<Compile Include="TownMapLoader.cs" />
<Compile Include="WildPokemonLoader.cs" />
</ItemGroup>
<ItemGroup>
<None Include="Resources\warp.bmp" />
</ItemGroup>
<ItemGroup>
<None Include="Resources\person.bmp" />
</ItemGroup>
<ItemGroup>
<None Include="Resources\sign.bmp" />
</ItemGroup>
<ItemGroup>
<None Include="Resources\trigger.bmp" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -0,0 +1 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" />

172
ClassicMap/FastPixel.cs Normal file
View File

@ -0,0 +1,172 @@
using System;
using System.Drawing.Imaging;
using System.Drawing;
namespace ClassicMap
{
public class FastPixel
{
public byte[] rgbValues = new byte[4];
private BitmapData bmpData;
private IntPtr bmpPtr;
private bool locked = false;
private bool _isAlpha = false;
private Bitmap _bitmap;
private int _width;
private int _height;
public int Width
{
get { return this._width; }
}
public int Height
{
get { return this._height; }
}
public bool IsAlphaBitmap
{
get { return this._isAlpha; }
}
public Bitmap Bitmap
{
get { return this._bitmap; }
}
public FastPixel(Bitmap bitmap)
{
if ((bitmap.PixelFormat == (bitmap.PixelFormat | PixelFormat.Indexed)))
{
throw new Exception("Cannot lock an Indexed image.");
}
this._bitmap = bitmap;
this._isAlpha = (this.Bitmap.PixelFormat == (this.Bitmap.PixelFormat | PixelFormat.Alpha));
this._width = bitmap.Width;
this._height = bitmap.Height;
}
public void Lock()
{
if (this.locked)
{
throw new Exception("Bitmap already locked.");
}
Rectangle rect = new Rectangle(0, 0, this.Width, this.Height);
this.bmpData = this.Bitmap.LockBits(rect, ImageLockMode.ReadWrite, this.Bitmap.PixelFormat);
this.bmpPtr = this.bmpData.Scan0;
if (this.IsAlphaBitmap)
{
int bytes = (this.Width * this.Height) * 4;
// ERROR: Not supported in C#: ReDimStatement
System.Runtime.InteropServices.Marshal.Copy(this.bmpPtr, rgbValues, 0, this.rgbValues.Length);
}
else
{
int bytes = (this.Width * this.Height) * 3;
// ERROR: Not supported in C#: ReDimStatement
System.Runtime.InteropServices.Marshal.Copy(this.bmpPtr, rgbValues, 0, this.rgbValues.Length);
}
this.locked = true;
}
public void Unlock(bool setPixels)
{
if (!this.locked)
{
throw new Exception("Bitmap not locked.");
}
// Copy the RGB values back to the bitmap
if (setPixels) System.Runtime.InteropServices.Marshal.Copy(this.rgbValues, 0, this.bmpPtr, this.rgbValues.Length);
// Unlock the bits.
this.Bitmap.UnlockBits(bmpData);
this.locked = false;
}
public void Clear(Color colour)
{
if (!this.locked)
{
throw new Exception("Bitmap not locked.");
}
if (this.IsAlphaBitmap)
{
for (int index = 0; index <= this.rgbValues.Length - 1; index += 4)
{
this.rgbValues[index] = colour.B;
this.rgbValues[index + 1] = colour.G;
this.rgbValues[index + 2] = colour.R;
this.rgbValues[index + 3] = colour.A;
}
}
else
{
for (int index = 0; index <= this.rgbValues.Length - 1; index += 3)
{
this.rgbValues[index] = colour.B;
this.rgbValues[index + 1] = colour.G;
this.rgbValues[index + 2] = colour.R;
}
}
}
public void SetPixel(Point location, Color colour)
{
this.SetPixel(location.X, location.Y, colour);
}
public void SetPixel(int x, int y, Color colour)
{
if (!this.locked)
{
throw new Exception("Bitmap not locked.");
}
if (this.IsAlphaBitmap)
{
int index = ((y * this.Width + x) * 4);
this.rgbValues[index] = colour.B;
this.rgbValues[index + 1] = colour.G;
this.rgbValues[index + 2] = colour.R;
this.rgbValues[index + 3] = colour.A;
}
else
{
int index = ((y * this.Width + x) * 3);
this.rgbValues[index] = colour.B;
this.rgbValues[index + 1] = colour.G;
this.rgbValues[index + 2] = colour.R;
}
}
public Color GetPixel(Point location)
{
return this.GetPixel(location.X, location.Y);
}
public Color GetPixel(int x, int y)
{
if (!this.locked)
{
throw new Exception("Bitmap not locked.");
}
if (this.IsAlphaBitmap)
{
int index = ((y * this.Width + x) * 4);
int b = this.rgbValues[index];
int g = this.rgbValues[index + 1];
int r = this.rgbValues[index + 2];
int a = this.rgbValues[index + 3];
return Color.FromArgb(a, r, g, b);
}
else
{
int index = ((y * this.Width + x) * 3);
int b = this.rgbValues[index];
int g = this.rgbValues[index + 1];
int r = this.rgbValues[index + 2];
return Color.FromArgb(r, g, b);
}
}
}
}

1440
ClassicMap/Form1.Designer.cs generated Normal file

File diff suppressed because it is too large Load Diff

924
ClassicMap/Form1.cs Normal file
View File

@ -0,0 +1,924 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using GBHL;
using System.Text;
using System.IO;
using System.Windows.Forms;
using System.Drawing.Imaging;
namespace ClassicMap
{
public partial class Form1 : Form
{
private string romLocation = "";
private GBFile gb = null;
private TownMapLoader townMapLoader;
private TilesetLoader tilesetLoader;
private MapLoader mapLoader;
private WildPokemonLoader wildPokemonLoader;
private SpriteLoader spriteLoader;
private Bitmap townMapMarker;
private Bitmap townMap;
private Bitmap[] cachedTilesets;
private int selectedTile = 0;
private Point lastClick;
private ImageAttributes eventTransparency;
private ImageAttributes eventTTransparency;
private Rectangle eventRectangle = new Rectangle(0, 0, 16, 16);
private int selectedPerson = -1, selectedSign = -1, selectedWarp = -1, selectedWarpTo = -1;
private bool triggerPokemonEvents; //Ugh... Didn't want to have to resort to this. Probably don't, but oh well.
public static Color[] Palette = new Color[] { Color.White, Color.FromArgb(208, 208, 208), Color.FromArgb(168, 168, 168), Color.Black };
//Open File Dialogs
private OpenFileDialog openROM;
public Form1()
{
InitializeComponent();
//Initialize the Open File Dialogs
openROM = new OpenFileDialog();
openROM.Title = "Select a Pokemon Red/Blue ROM";
openROM.Filter = "All Supported Types|*.bin;*.gb";
ColorMatrix cm = new ColorMatrix();
cm.Matrix33 = (float).7;
eventTransparency = new ImageAttributes();
eventTransparency.SetColorMatrix(cm, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
ColorMatrix cm2 = new ColorMatrix();
cm2.Matrix33 = (float).6;
eventTTransparency = new ImageAttributes();
eventTTransparency.SetColorMatrix(cm2, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
}
private void openROMToolStripMenuItem_Click(object sender, EventArgs e)
{
if (openROM.ShowDialog() != DialogResult.OK)
return;
FileInfo f = new FileInfo(openROM.FileName);
bool enable = true;
if (f.IsReadOnly)
{
MessageBox.Show("Warning! ROM is read-only. You will not be able to save.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
enable = false;
}
try
{
BinaryReader br = new BinaryReader(File.OpenRead(openROM.FileName));
byte[] buffer = br.ReadBytes((int)br.BaseStream.Length);
br.Close();
gb = new GBFile(buffer);
if (enable)
saveROMToolStripMenuItem.Enabled = true;
}
catch (IOException ex)
{
MessageBox.Show("Error reading ROM.\n\n" + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
DoInitialLoading();
}
public void DoInitialLoading()
{
romLocation = openROM.FileName;
EnableFileWatcher();
BleControls(true);
lastClick = new Point(-1, -1);
triggerPokemonEvents = true;
townMapLoader = new TownMapLoader(gb);
tilesetLoader = new TilesetLoader(gb);
mapLoader = new MapLoader(gb);
wildPokemonLoader = new WildPokemonLoader(gb);
spriteLoader = new SpriteLoader(gb);
cachedTilesets = new Bitmap[256];
wildPokemonLoader.LoadPokemonNames();
foreach (string name in wildPokemonLoader.PokemonNames)
{
if (name == null)
continue;
cboGrassPokemon.Items.Add(name);
cboWaterPokemon.Items.Add(name);
}
townMap = townMapLoader.LoadMap();
townMapMarker = townMapLoader.LoadMarker();
nTownMap_ValueChanged(null, null);
LoadMap((int)nMap.Value);
}
private void EnableFileWatcher()
{
string[] parts = romLocation.Split('\\');
string f = "";
for (int i = 0; i < parts.Length - 1; i++)
f += parts[i] + "\\";
romWatcher.Path = f;
romWatcher.EnableRaisingEvents = true;
}
private void BleControls(bool b)
{
groupBox1.Enabled = b;
groupBox2.Enabled = b;
tabControl1.Enabled = b;
}
private void pTownMap_Paint(object sender, PaintEventArgs e)
{
}
private void nTownMap_ValueChanged(object sender, EventArgs e)
{
if (nTownMap.Value == 47)
nTownMap.Value = 0;
if (nTownMap.Value == -1)
nTownMap.Value = 46;
Bitmap b = new Bitmap(townMap);
if (sender == nMap)
{
pTownMap.Image = b;
return;
}
Graphics g = Graphics.FromImage(b);
int x = 0, y = 0;
byte map = gb.ReadByte(0x70F11 + (int)nTownMap.Value);
nMap.Value = map;
int namePointer = 0;
if (map <= 0x25)
{
gb.BufferLocation = 0x71313 + map * 3;
byte location = gb.ReadByte();
x = (location & 0xF) * 8 + 12;
y = (location >> 4) * 8 + 4;
namePointer = gb.ReadByte() + ((gb.ReadByte() - 0x40) * 0x100);
}
else
{
gb.BufferLocation = 0x71382;
while (true)
{
if (gb.ReadByte() > map)
{
byte location = gb.ReadByte();
x = (location & 0xF) * 8 + 12;
y = (location >> 4) * 8 + 4;
namePointer = gb.ReadByte() + ((gb.ReadByte() - 0x40) * 0x100);
break;
}
else
gb.BufferLocation += 3;
}
}
g.DrawImage(townMapMarker, x, y);
pTownMap.Image = b;
//Read the name
gb.BufferLocation = 0x70000 + namePointer;
byte by;
string text = "";
while ((by = gb.ReadByte()) != 0x50)
{
text = text + TextTable.GetString(by);
}
lblName.Text = "Map Name: " + text;
}
private void nMap_ValueChanged(object sender, EventArgs e)
{
nTownMap_ValueChanged(nMap, null);
if (!LoadMap((int)nMap.Value))
{
groupBox2.Enabled = false;
tabControl1.Enabled = false;
pMap.Image = pTileset.Image = pTile.Image = null;
lblMapHeader.Text = "";
this.BeginInvoke(new MethodInvoker(ShowMapError));
}
}
private void ShowMapError()
{
MessageBox.Show("Error loading map or tileset. Probably a map that isn't actually a map.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
public bool LoadMap(int map)
{
try
{
if (nMap.Value != map)
nMap.Value = map;
lastClick = new Point(-1, -1);
mapLoader.LoadMapHeader(map);
mapLoader.LoadLevelData();
wildPokemonLoader.LoadWildPokemon(map);
lblMapHeader.Text = "Header Location: 0x" + mapLoader.mapHeader.Location.ToString("X") +
"\nTileset: " + mapLoader.mapHeader.Tileset +
"\nWidth: " + mapLoader.mapHeader.Width +
"\nHeight: " + mapLoader.mapHeader.Height +
"\nLevel Data: 0x" + mapLoader.mapHeader.LevelData.ToString("X") +
"\nEvent Data: 0x" + mapLoader.mapHeader.EventData.ToString("X");
lblWildPokemon.Text = "Wild Pokemon: " + (wildPokemonLoader.rarityGrass > 0 ? "Grass" + (wildPokemonLoader.rarityWater > 0 ? "/Water" : "") : (wildPokemonLoader.rarityWater > 0 ? "Water" : "None"));
tbGrass.Value = wildPokemonLoader.rarityGrass;
lblGrassEncounter.Text = "Encounter Frequency: " + tbGrass.Value + "/255";
if (wildPokemonLoader.rarityGrass > 0)
{
grpGrass.Visible = true;
pnlGrass.Visible = false;
lstGrass.Items.Clear();
foreach (Pokemon p in wildPokemonLoader.grassPokemon)
{
lstGrass.Items.Add(wildPokemonLoader.PokemonNames[wildPokemonLoader.PokemonIndicies[p.id - 1]].Substring(4) + " - " + p.level.ToString());
}
if (lstGrass.SelectedIndex == 0)
lstGrass_SelectedIndexChanged(null, null);
else
lstGrass.SelectedIndex = 0;
}
else
{
pnlGrass.Visible = true;
grpGrass.Visible = false;
}
tbWater.Value = wildPokemonLoader.rarityWater;
lblWaterEncounter.Text = "Encounter Frequency: " + tbWater.Value + "/255";
if (wildPokemonLoader.rarityWater > 0)
{
grpWater.Visible = true;
pnlWater.Visible = false;
lstWater.Items.Clear();
foreach (Pokemon p in wildPokemonLoader.waterPokemon)
{
lstWater.Items.Add(wildPokemonLoader.PokemonNames[wildPokemonLoader.PokemonIndicies[p.id - 1]].Substring(4) + " - " + p.level.ToString());
}
if (lstWater.SelectedIndex == 0)
lstWater_SelectedIndexChanged(null, null);
else
lstWater.SelectedIndex = 0;
}
else
{
pnlWater.Visible = true;
grpWater.Visible = false;
}
if (cachedTilesets[mapLoader.mapHeader.Tileset] == null)
{
cachedTilesets[mapLoader.mapHeader.Tileset] = tilesetLoader.LoadTileset(mapLoader.mapHeader.Tileset);
}
pTileset.Image = cachedTilesets[mapLoader.mapHeader.Tileset];
UpdateSelectedTile();
DrawMap();
ResetSelects();
pnlPerson.Visible = false;
pnlWarp.Visible = false;
pnlSign.Visible = false;
pnlWarpTo.Visible = false;
nSelectedPerson.Maximum = mapLoader.people.Count - 1;
nSelectedWarp.Maximum = mapLoader.warps.Count - 1;
nSelectedSign.Maximum = mapLoader.signs.Count - 1;
nSelectedWarpTo.Maximum = mapLoader.warpTo.Count - 1;
pEventMap.Image = pMap.Image;
if (tabControl1.SelectedIndex == 0)
pEventMap.Invalidate();
BleControls(true);
return true;
}
catch (Exception)
{
return false;
}
}
private void Form1_Load(object sender, EventArgs e)
{
panel4.VerticalScroll.SmallChange = 32;
panel4.VerticalScroll.LargeChange = 128;
}
private void UpdateSelectedTile()
{
Bitmap b = new Bitmap(32, 32);
for (int y = 0; y < 32; y++)
for (int x = 0; x < 32; x++)
b.SetPixel(x, y, cachedTilesets[mapLoader.mapHeader.Tileset].GetPixel(x, selectedTile * 32 + y));
pTile.Image = b;
pTileset.Invalidate();
}
private void pTileset_MouseDown(object sender, MouseEventArgs e)
{
selectedTile = e.Y / 32;
UpdateSelectedTile();
pTileset.Invalidate();
}
private void pTileset_Paint(object sender, PaintEventArgs e)
{
if (pTileset.Image != null)
e.Graphics.DrawRectangle(Pens.Red, 0, selectedTile * 32, 31, 31);
}
private void DrawMap()
{
Bitmap b = new Bitmap(mapLoader.mapHeader.Width * 32, mapLoader.mapHeader.Height * 32);
FastPixel fp = new FastPixel(b);
fp.rgbValues = new byte[b.Width * b.Height * 4];
fp.Lock();
FastPixel source = new FastPixel(cachedTilesets[mapLoader.mapHeader.Tileset]);
source.rgbValues = new byte[source.Width * source.Height * 4];
source.Lock();
for (int ytile = 0; ytile < mapLoader.mapHeader.Height; ytile++)
{
for (int xtile = 0; xtile < mapLoader.mapHeader.Width; xtile++)
{
for (int y = 0; y < 32; y++)
{
for (int x = 0; x < 32; x++)
{
fp.SetPixel(xtile * 32 + x, ytile * 32 + y, source.GetPixel(x, mapLoader.LevelData[xtile, ytile] * 32 + y));
}
}
}
}
source.Unlock(false);
fp.Unlock(true);
pMap.Image = b;
}
private void DrawEvents(Graphics g)
{
foreach (WarpTo w in mapLoader.warpTo)
{
eventRectangle.X = w.x * 16;
eventRectangle.Y = w.y * 16;
g.DrawImage(ClassicMap.Properties.Resources.trigger, eventRectangle, 0, 0, 16, 16, GraphicsUnit.Pixel, eventTTransparency);
}
foreach (Warp w in mapLoader.warps)
{
eventRectangle.X = w.x * 16;
eventRectangle.Y = w.y * 16;
g.DrawImage(ClassicMap.Properties.Resources.warp, eventRectangle, 0, 0, 16, 16, GraphicsUnit.Pixel, eventTransparency);
}
foreach (Sign s in mapLoader.signs)
{
eventRectangle.X = s.x * 16;
eventRectangle.Y = s.y * 16;
g.DrawImage(ClassicMap.Properties.Resources.sign, eventRectangle, 0, 0, 16, 16, GraphicsUnit.Pixel, eventTransparency);
}
foreach (Person p in mapLoader.people)
{
eventRectangle.X = p.x * 16 - 64;
eventRectangle.Y = p.y * 16 - 64;
if (!spriteImagesToolStripMenuItem.Checked)
g.DrawImage(ClassicMap.Properties.Resources.person, eventRectangle, 0, 0, 16, 16, GraphicsUnit.Pixel, eventTransparency);
else
g.DrawImage(spriteLoader.LoadSprite(p.sprite), p.x * 16 - 64, p.y * 16 - 64);
}
if (selectedPerson != -1 && selectedPerson < mapLoader.people.Count)
g.DrawRectangle(Pens.Red, mapLoader.people[selectedPerson].x * 16 - 64, mapLoader.people[selectedPerson].y * 16 - 64, 16, 16);
else if (selectedWarp != -1 && selectedWarp < mapLoader.warps.Count)
g.DrawRectangle(Pens.Red, mapLoader.warps[selectedWarp].x * 16, mapLoader.warps[selectedWarp].y * 16, 16, 16);
else if (selectedSign != -1 && selectedSign < mapLoader.signs.Count)
g.DrawRectangle(Pens.Red, mapLoader.signs[selectedSign].x * 16, mapLoader.signs[selectedSign].y * 16, 16, 16);
else if (selectedWarpTo != -1 && selectedWarpTo < mapLoader.warpTo.Count)
g.DrawRectangle(Pens.Red, mapLoader.warpTo[selectedWarpTo].x * 16, mapLoader.warpTo[selectedWarpTo].y * 16, 16, 16);
}
private void Form1_Resize(object sender, EventArgs e)
{
tabControl1.Width = this.Width - 212;
tabControl1.Height = this.Height - 79;
panel4.Height = tabControl1.Height - 95;
pTile.Top = panel4.Top + panel4.Height + 15;
groupBox2.Height = this.Height - 346;
}
private void pMap_MouseDown(object sender, MouseEventArgs e)
{
panel2.Focus();
if (e.Button == MouseButtons.Left)
{
if (e.X < 0 || e.Y < 0 || e.X / 32 >= mapLoader.mapHeader.Width || e.Y / 32 >= mapLoader.mapHeader.Height)
return;
mapLoader.LevelData[e.X / 32, e.Y / 32] = (byte)selectedTile;
Graphics g = Graphics.FromImage(pMap.Image);
g.DrawImage(pTile.Image, e.X / 32 * 32, e.Y / 32 * 32);
pMap.Invalidate(new Rectangle(e.X / 32 * 32, e.Y / 32 * 32, 32, 32));
}
else if (e.Button == MouseButtons.Right)
{
selectedTile = mapLoader.LevelData[e.X / 32, e.Y / 32];
panel4.VerticalScroll.Value = selectedTile * 32 + (selectedTile > 0 ? 2 : 0);
panel4.VerticalScroll.Value = selectedTile * 32 + (selectedTile > 0 ? 2 : 0);
UpdateSelectedTile();
pTileset.Invalidate();
}
}
private void pMap_MouseMove(object sender, MouseEventArgs e)
{
SetPositionLabel(e.X, e.Y);
if (e.Button == MouseButtons.Left)
{
int x = e.X / 32 * 32;
int y = e.Y / 32 * 32;
if (x == lastClick.X && y == lastClick.Y)
return;
lastClick = new Point(x, y);
if (x < 0 || x / 32 >= mapLoader.mapHeader.Width || y < 0 || y / 32 >= mapLoader.mapHeader.Height)
return;
mapLoader.LevelData[x / 32, y / 32] = (byte)selectedTile;
Graphics g = Graphics.FromImage(pMap.Image);
g.DrawImage(pTile.Image, x, y);
pMap.Invalidate(new Rectangle(e.X / 32 * 32, e.Y / 32 * 32, 32, 32));
}
}
private void SetPositionLabel(int x, int y)
{
lblPosition.Text = "X: " + (x / 32).ToString() + " Y: " + (y / 32).ToString();
}
private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
{
lastClick = new Point(-1, -1);
if (tabControl1.SelectedIndex == 1)
pEventMap.Image = pMap.Image;
}
private void pEventMap_MouseMove(object sender, MouseEventArgs e)
{
SetPositionLabel(e.X * 2, e.Y * 2);
if (e.Button != MouseButtons.Left)
return;
if (e.X / 16 == lastClick.X && e.Y / 16 == lastClick.Y)
return;
lastClick = new Point(e.X / 16, e.Y / 16);
//Okay. So here we do Event x = mapLoader.eventGroup[selectedX];
//However, when I wrote this the events were structures, not classes.
//Because of this, variable could not be directly modified. This was changed later on.
if (selectedPerson != -1)
{
Person p = mapLoader.people[selectedPerson];
p.x = (byte)(4 + e.X / 16);
p.y = (byte)(4 + e.Y / 16);
mapLoader.people[selectedPerson] = p;
pEventMap.Invalidate();
}
else if (selectedWarp != -1)
{
Warp w = mapLoader.warps[selectedWarp];
w.x = (byte)(e.X / 16);
w.y = (byte)(e.Y / 16);
mapLoader.warps[selectedWarp] = w;
pEventMap.Invalidate();
}
else if (selectedSign != -1)
{
Sign s = mapLoader.signs[selectedSign];
s.x = (byte)(e.X / 16);
s.y = (byte)(e.Y / 16);
mapLoader.signs[selectedSign] = s;
pEventMap.Invalidate();
}
else if (selectedWarpTo != -1)
{
WarpTo w = mapLoader.warpTo[selectedWarpTo];
w.x = (byte)(e.X / 16);
w.y = (byte)(e.Y / 16);
mapLoader.warpTo[selectedWarpTo] = w;
pEventMap.Invalidate();
}
}
private void pEventMap_Paint(object sender, PaintEventArgs e)
{
DrawEvents(e.Graphics);
}
private void ResetSelects()
{
selectedPerson = -1;
selectedSign = -1;
selectedWarp = -1;
selectedWarpTo = -1;
}
private void pEventMap_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button != MouseButtons.Left && e.Button != MouseButtons.Right)
return;
panel1.Focus();
ResetSelects();
if ((selectedPerson = GetPersonIndex(e.X, e.Y)) != -1)
{
SelectPerson();
}
else if ((selectedWarp = GetWarpIndex(e.X, e.Y)) != -1)
{
SelectWarp();
}
else if ((selectedSign = GetSignIndex(e.X, e.Y)) != -1)
{
SelectSign();
}
else if ((selectedWarpTo = GetWarpToIndex(e.X, e.Y)) != -1)
{
SelectWarpTo();
}
else
{
pnlPerson.Visible = false;
}
pEventMap.Invalidate();
}
private void SelectPerson()
{
pnlPerson.Visible = true;
pnlWarp.Visible = false;
pnlSign.Visible = false;
pnlWarpTo.Visible = false;
nSelectedPerson.Value = selectedPerson;
nPersonPicture.Value = mapLoader.people[selectedPerson].sprite;
nPersonMovement1.Value = mapLoader.people[selectedPerson].movement;
nPersonMovement2.Value = mapLoader.people[selectedPerson].movement2;
nPersonPicture.Value = mapLoader.people[selectedPerson].sprite;
nPersonText.Value = (mapLoader.people[selectedPerson].text & 0x3F);
if ((mapLoader.people[selectedPerson].originalText & 0x40) != 0)
{
lblPersonItem.Enabled = false;
nPersonItem.Enabled = false;
lblPersonTrainer.Enabled = true;
nPersonTrainer.Enabled = true;
lblPersonPokemonSet.Enabled = true;
nPersonPokemonSet.Enabled = true;
nPersonTrainer.Value = mapLoader.people[selectedPerson].trainer;
nPersonPokemonSet.Value = mapLoader.people[selectedPerson].pokemonSet;
}
else if ((mapLoader.people[selectedPerson].originalText & 0x80) != 0)
{
lblPersonItem.Enabled = true;
nPersonItem.Enabled = true;
lblPersonTrainer.Enabled = false;
nPersonTrainer.Enabled = false;
lblPersonPokemonSet.Enabled = false;
nPersonPokemonSet.Enabled = false;
nPersonItem.Value = mapLoader.people[selectedPerson].item;
}
else
{
lblPersonItem.Enabled = false;
nPersonItem.Enabled = false;
lblPersonTrainer.Enabled = false;
nPersonTrainer.Enabled = false;
lblPersonPokemonSet.Enabled = false;
nPersonPokemonSet.Enabled = false;
}
}
public void SelectWarp()
{
pnlWarp.Visible = true;
pnlPerson.Visible = false;
pnlSign.Visible = false;
pnlWarpTo.Visible = false;
nSelectedWarp.Value = selectedWarp;
nWarpDest.Value = mapLoader.warps[selectedWarp].destPoint;
nWarpMap.Value = mapLoader.warps[selectedWarp].map;
}
public void SelectSign()
{
pnlSign.Visible = false;
pnlPerson.Visible = false;
pnlSign.Visible = true;
pnlWarpTo.Visible = false;
nSelectedSign.Value = selectedSign;
nSignText.Value = mapLoader.signs[selectedSign].text;
}
public void SelectWarpTo()
{
pnlWarp.Visible = false;
pnlPerson.Visible = false;
pnlSign.Visible = false;
pnlWarpTo.Visible = true;
nSelectedWarpTo.Value = selectedWarpTo;
nWarpToEvent.Value = mapLoader.warpTo[selectedWarpTo].address;
}
private int GetPersonIndex(int x, int y)
{
for (int i = mapLoader.people.Count - 1; i > -1; i--)
{
if (mapLoader.people[i].x - 4 == x / 16 && mapLoader.people[i].y - 4 == y / 16)
return i;
}
return -1;
}
private int GetWarpIndex(int x, int y)
{
for (int i = mapLoader.warps.Count - 1; i > -1; i--)
{
if (mapLoader.warps[i].x == x / 16 && mapLoader.warps[i].y == y / 16)
return i;
}
return -1;
}
private int GetSignIndex(int x, int y)
{
for (int i = mapLoader.signs.Count - 1; i > -1; i--)
{
if (mapLoader.signs[i].x == x / 16 && mapLoader.signs[i].y == y / 16)
return i;
}
return -1;
}
private int GetWarpToIndex(int x, int y)
{
for (int i = mapLoader.warpTo.Count - 1; i > -1; i--)
{
if (mapLoader.warpTo[i].x == x / 16 && mapLoader.warpTo[i].y == y / 16)
return i;
}
return -1;
}
private void button1_Click(object sender, EventArgs e)
{
int warp = (int)nWarpDest.Value;
if (!LoadMap((int)nWarpMap.Value))
{
ShowMapError();
return;
}
if (warp < mapLoader.warpTo.Count)
{
selectedWarpTo = warp;
SelectWarpTo();
}
else
MessageBox.Show("Destination point out of range.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
private void button2_Click(object sender, EventArgs e)
{
//Okay, this had me stumped for a few minutes.
//On the Pokemon Red notes, a basic formula was provided with very little detail.
//It turns out the x/y had to be their even numbers (block they were on).
//That wasn't specified so it threw me off.
//However, this works, as the original address was calculated successfully with all tests.
int address = 0xC6EF;
address += mapLoader.mapHeader.Width;
address += (mapLoader.mapHeader.Width + 6) * ((mapLoader.warpTo[selectedWarpTo].y / 2) * 2 / 2);
address += mapLoader.warpTo[selectedWarpTo].x / 2 * 2 / 2;
nWarpToEvent.Value = address;
}
private void pEventMap_MouseUp(object sender, MouseEventArgs e)
{
lastClick = new Point(-1, -1);
}
private void pMap_MouseUp(object sender, MouseEventArgs e)
{
lastClick = new Point(-1, -1);
}
private void nWarpToEvent_ValueChanged(object sender, EventArgs e)
{
mapLoader.warpTo[selectedWarpTo].address = (int)nWarpToEvent.Value;
}
private void nWarpDest_ValueChanged(object sender, EventArgs e)
{
mapLoader.warps[selectedWarp].destPoint = (byte)nWarpDest.Value;
}
private void nWarpMap_ValueChanged(object sender, EventArgs e)
{
mapLoader.warps[selectedWarp].map = (byte)nWarpMap.Value;
}
private void nPersonPicture_ValueChanged(object sender, EventArgs e)
{
mapLoader.people[selectedPerson].sprite = (byte)nPersonPicture.Value;
pEventMap.Invalidate();
}
private void nPersonMovement1_ValueChanged(object sender, EventArgs e)
{
mapLoader.people[selectedPerson].movement = (byte)nPersonMovement1.Value;
}
private void nPersonMovement2_ValueChanged(object sender, EventArgs e)
{
mapLoader.people[selectedPerson].movement2 = (byte)nPersonMovement2.Value;
}
private void nPersonText_ValueChanged(object sender, EventArgs e)
{
mapLoader.people[selectedPerson].text = (byte)nPersonText.Value;
}
private void nPersonTrainer_ValueChanged(object sender, EventArgs e)
{
mapLoader.people[selectedPerson].trainer = (byte)nPersonTrainer.Value;
}
private void nPersonPokemonSet_ValueChanged(object sender, EventArgs e)
{
mapLoader.people[selectedPerson].pokemonSet = (byte)nPersonPokemonSet.Value;
}
private void nPersonItem_ValueChanged(object sender, EventArgs e)
{
mapLoader.people[selectedPerson].item = (byte)nPersonItem.Value;
}
private void nSelectedPerson_ValueChanged(object sender, EventArgs e)
{
if (nSelectedPerson.Maximum == -1)
return;
selectedPerson = (int)nSelectedPerson.Value;
SelectPerson();
pEventMap.Invalidate();
}
private void nSelectedSign_ValueChanged(object sender, EventArgs e)
{
if (nSelectedSign.Maximum == -1)
return;
selectedSign = (int)nSelectedSign.Value;
SelectSign();
pEventMap.Invalidate();
}
private void nSignText_ValueChanged(object sender, EventArgs e)
{
mapLoader.signs[selectedSign].text = (byte)nSignText.Value;
}
private void nSelectedWarpTo_ValueChanged(object sender, EventArgs e)
{
if (nSelectedWarpTo.Maximum == -1)
return;
selectedWarpTo = (int)nSelectedWarpTo.Value;
SelectWarpTo();
pEventMap.Invalidate();
}
private void nSelectedWarp_ValueChanged(object sender, EventArgs e)
{
if (nSelectedWarp.Maximum == -1)
return;
selectedWarp = (int)nSelectedWarp.Value;
SelectWarp();
pEventMap.Invalidate();
}
private void saveROMToolStripMenuItem_Click(object sender, EventArgs e)
{
if (romLocation == "")
return;
MapSaver mapSaver = new MapSaver(gb, mapLoader, wildPokemonLoader);
mapSaver.Save((int)nMap.Value);
BinaryWriter bw = new BinaryWriter(File.Open(romLocation, FileMode.Open));
bw.Write(gb.Buffer);
bw.Close();
}
private void romWatcher_Changed(object sender, FileSystemEventArgs e)
{
if (e.FullPath != romLocation)
return;
FileInfo f = new FileInfo(romLocation);
if (!f.IsReadOnly)
saveROMToolStripMenuItem.Enabled = true;
else
{
MessageBox.Show("Warning! ROM has been changed to read-only. You cannot save until it is writable.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
saveROMToolStripMenuItem.Enabled = false;
}
}
private void lstGrass_SelectedIndexChanged(object sender, EventArgs e)
{
if (!triggerPokemonEvents)
return;
if (lstGrass.SelectedIndex == -1 && grpGrass.Visible)
lstGrass.SelectedIndex = 0;
nGrassLevel.Value = wildPokemonLoader.grassPokemon[lstGrass.SelectedIndex].level;
cboGrassPokemon.SelectedIndex = wildPokemonLoader.PokemonIndicies[wildPokemonLoader.grassPokemon[lstGrass.SelectedIndex].id - 1];
}
private void lstWater_SelectedIndexChanged(object sender, EventArgs e)
{
if (!triggerPokemonEvents)
return;
if (lstWater.SelectedIndex == -1 && grpWater.Visible)
lstWater.SelectedIndex = 0;
nWaterLevel.Value = wildPokemonLoader.waterPokemon[lstWater.SelectedIndex].level;
cboWaterPokemon.SelectedIndex = wildPokemonLoader.PokemonIndicies[wildPokemonLoader.waterPokemon[lstWater.SelectedIndex].id - 1];
}
private void cboGrassPokemon_SelectedIndexChanged(object sender, EventArgs e)
{
string s = cboGrassPokemon.SelectedItem.ToString().Substring(4) + " - " + (int)nGrassLevel.Value;
if ((string)lstGrass.Text == s)
return;
triggerPokemonEvents = false;
int id = int.Parse(cboGrassPokemon.SelectedItem.ToString().Substring(0, 2), System.Globalization.NumberStyles.HexNumber);
wildPokemonLoader.grassPokemon[lstGrass.SelectedIndex].id = (byte)(id + 1);
lstGrass.Items[lstGrass.SelectedIndex] = s;
triggerPokemonEvents = true;
}
private void nGrassLevel_ValueChanged(object sender, EventArgs e)
{
if (cboGrassPokemon.SelectedItem == null)
return;
string s = cboGrassPokemon.SelectedItem.ToString().Substring(4) + " - " + (int)nGrassLevel.Value;
if ((string)lstGrass.Text == s)
return;
triggerPokemonEvents = false;
wildPokemonLoader.grassPokemon[lstGrass.SelectedIndex].level = (byte)nGrassLevel.Value;
lstGrass.Items[lstGrass.SelectedIndex] = s;
triggerPokemonEvents = true;
}
private void tbGrass_Scroll(object sender, EventArgs e)
{
lblGrassEncounter.Text = "Encounter Frequency: " + tbGrass.Value + "/255";
wildPokemonLoader.rarityGrass = (byte)tbGrass.Value;
}
private void tbWater_Scroll(object sender, EventArgs e)
{
lblWaterEncounter.Text = "Encounter Frequency: " + tbWater.Value + "/255";
wildPokemonLoader.rarityWater = (byte)tbWater.Value;
}
private void cboWaterPokemon_SelectedIndexChanged(object sender, EventArgs e)
{
string s = cboWaterPokemon.SelectedItem.ToString().Substring(4) + " - " + (int)nWaterLevel.Value;
if ((string)lstWater.Text == s)
return;
triggerPokemonEvents = false;
int id = int.Parse(cboWaterPokemon.SelectedItem.ToString().Substring(0, 2), System.Globalization.NumberStyles.HexNumber);
wildPokemonLoader.waterPokemon[lstWater.SelectedIndex].id = (byte)(id + 1);
lstWater.Items[lstWater.SelectedIndex] = s;
triggerPokemonEvents = true;
}
private void nWaterLevel_ValueChanged(object sender, EventArgs e)
{
if (cboWaterPokemon.SelectedItem == null)
return;
string s = cboWaterPokemon.SelectedItem.ToString().Substring(4) + " - " + (int)nWaterLevel.Value;
if ((string)lstWater.Text == s)
return;
triggerPokemonEvents = false;
wildPokemonLoader.waterPokemon[lstWater.SelectedIndex].level = (byte)nWaterLevel.Value;
lstWater.Items[lstWater.SelectedIndex] = s;
triggerPokemonEvents = true;
}
private void spriteImagesToolStripMenuItem_Click(object sender, EventArgs e)
{
if (tabControl1.SelectedIndex == 1 && tabControl1.Enabled)
pEventMap.Invalidate();
}
}
}

159
ClassicMap/Form1.resx Normal file
View File

@ -0,0 +1,159 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="menuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="openROMToolStripMenuItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAALBQAA
CwUByY3ISQAAAjRJREFUOE+Fk19IU3EUx9eDcxiMkdmKohWkPjbBCBlMwx6EWkmDiLKndPSSmQ/ZluFa
s8CwhwqjDMpBj5ZzlQRpshFFZdof0sVihkrSIotade+2++13fte7bneLLnw453d+5/vl/O793SUAdNpn
aas+zmrrDIUFOnOJSfd+NjHB1ieT58SBnGYyyEfRkQIrw7v+dAnaXu5AVe8GsPU1bW9esbqJiWpIfGZ6
DyouWsikXr3/XwNqZqIHHVEn2ifrsexYUTzHYKS70MGABofSSEdpDNfAE92Jih4+hVXZ0yliSZIA6UYW
tVljhx4NIza0vKrDtuBGMvCqDcDFqeuQFMQ+BCdaqBGWzmKUdpmxb9QG19gWOIc3YU2nCcajBtofpwkg
JXsh/bjCyfBcXgciB2DxF+Pgs1o0MXHDYxuckUpUD5RzMcMkG3y5gAzj4aUV2vcAj0+P1T4Tdoc3Y1e4
EvZb5bAeNyB0Vn5n3CD9sQvfYm2I9CxHZoHMznNDgswDo/th9hqZuAxlJ4yY/zSI5MKQymDGh9hQLaZu
25FOdGfJsJygWmB4L1a5jQj1V0P4eRfTTw79MUi9c+PR5ZX4PO5CavYUw480izJyTvX0nB9v79VB+B5S
jurgRxDftPJCKub+Bx6IbI+I3tkK4etN3s//I0o+3N+Op1fXQnx9mCPw2LwY5Zpcb0Y0aEdi0v+3wYu+
UsQH7RDGXIs0sSjzSx2fuzDVX5UdX5kg3zXO+Zzaq67cxN/E55FzvSfetAAAAABJRU5ErkJggg==
</value>
</data>
<data name="saveROMToolStripMenuItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAALDgAA
Cw4BQL7hQQAAAU1JREFUOE/Vkz9Lw1AUxfWLVOlmpn4DB0uHruKkoUWbpAUdmknwG7gICgr+QZc2SBBB
0L1Fiy0JLRabOMT8TxQU50zHvGBdTIjUyQeHt5z7e+e+y50GMPWnQwDzCwdsKARBkCriI35SFz3+BQDH
SqnF5AHiI5BEgCzLSNKvAGlt/IMEE7ewuHSDza02jk+GaAgKmoKKRlPF6ZkS6hHCuQJRVJOnsLYqo1y+
B8d1wfMS6nwPtVoHlcot1jeksLAHmr4Dw8jxY2SYAVaWW/C8D7juO/RnF7pmwDJ02KaBh8EIFLWPYvEq
GUDTLTjOG6i53Ui6puPFM+G7BDBEJrONfF6MB7BhglKpDct6/QbYphUCLDiWhr7URza7g0LhIh5QrY7C
P+hE0ccJfN+BZxsw9CdIXQkzswRwGQuIlono6PA6UbncXuT5sUzjxZjk/gS/KNRyAFcG5wAAAABJRU5E
rkJggg==
</value>
</data>
<metadata name="statusStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>126, 17</value>
</metadata>
<metadata name="romWatcher.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>236, 17</value>
</metadata>
</root>

42
ClassicMap/MapEvents.cs Normal file
View File

@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ClassicMap
{
public class Person
{
public byte sprite;
public byte y;
public byte x;
public byte movement;
public byte movement2;
public byte text;
public byte originalText;
public byte trainer;
public byte pokemonSet;
public byte item;
}
public class Warp
{
public byte y;
public byte x;
public byte destPoint;
public byte map;
}
public class Sign
{
public byte y;
public byte x;
public byte text;
}
public class WarpTo
{
public int address;
public byte y;
public byte x;
}
}

145
ClassicMap/MapLoader.cs Normal file
View File

@ -0,0 +1,145 @@
using System;
using System.Collections.Generic;
using System.Text;
using GBHL;
namespace ClassicMap
{
public struct MapHeader
{
public int Location;
public byte Tileset;
public byte Width;
public byte Height;
public int LevelData;
public int EventData;
}
public class MapLoader
{
private GBFile gb;
public MapHeader mapHeader;
public byte[,] LevelData;
public byte borderTile;
public List<Warp> warps;
public List<Sign> signs;
public List<Person> people;
public List<WarpTo> warpTo;
public MapLoader(GBFile g)
{
gb = g;
}
public void LoadMapHeader(int map)
{
mapHeader = new MapHeader();
gb.BufferLocation = 0xC23D + map;
byte bank = gb.ReadByte();
gb.BufferLocation = 0x01AE + map * 2;
mapHeader.Location = bank * 0x4000 + gb.ReadByte() + ((gb.ReadByte() - 0x40) * 0x100);
gb.BufferLocation = mapHeader.Location;
mapHeader.Tileset = gb.ReadByte();
mapHeader.Height = gb.ReadByte();
mapHeader.Width = gb.ReadByte();
mapHeader.LevelData = bank * 0x4000 + gb.ReadByte() + ((gb.ReadByte() - 0x40) * 0x100);
gb.ReadWord();
gb.ReadWord();
LoadConnections();
mapHeader.EventData = bank * 0x4000 + gb.ReadByte() + ((gb.ReadByte() - 0x40) * 0x100);
LoadEvents();
}
public void LoadLevelData()
{
gb.BufferLocation = mapHeader.LevelData;
LevelData = new byte[mapHeader.Width, mapHeader.Height];
for (int y = 0; y < mapHeader.Height; y++)
{
for (int x = 0; x < mapHeader.Width; x++)
{
LevelData[x, y] = gb.ReadByte();
}
}
}
public void LoadConnections()
{
byte connection = gb.ReadByte();
if ((connection & (1 << 3)) != 0)
gb.BufferLocation += 11;
if ((connection & (1 << 2)) != 0)
gb.BufferLocation += 11;
if ((connection & (1 << 1)) != 0)
gb.BufferLocation += 11;
if ((connection & (1 << 0)) != 0)
gb.BufferLocation += 11;
}
public void LoadEvents()
{
gb.BufferLocation = mapHeader.EventData;
borderTile = gb.ReadByte();
warps = new List<Warp>();
byte warpCount = gb.ReadByte();
for (int i = 0; i < warpCount; i++)
{
Warp w = new Warp();
w.y = gb.ReadByte();
w.x = gb.ReadByte();
w.destPoint = gb.ReadByte();
w.map = gb.ReadByte();
warps.Add(w);
}
signs = new List<Sign>();
byte signCount = gb.ReadByte();
for (int i = 0; i < signCount; i++)
{
Sign s = new Sign();
s.y = gb.ReadByte();
s.x = gb.ReadByte();
s.text = gb.ReadByte();
signs.Add(s);
}
people = new List<Person>();
byte personCount = gb.ReadByte();
for (int i = 0; i < personCount; i++)
{
Person p = new Person();
p.sprite = gb.ReadByte();
p.y = gb.ReadByte();
p.x = gb.ReadByte();
p.movement = gb.ReadByte();
p.movement2 = gb.ReadByte();
p.text = gb.ReadByte();
p.originalText = p.text;
if ((p.text & 0x40) != 0)
{
p.trainer = gb.ReadByte();
p.pokemonSet = gb.ReadByte();
}
else if ((p.text & 0x80) != 0)
{
p.item = gb.ReadByte();
}
people.Add(p);
}
warpTo = new List<WarpTo>();
for (int i = 0; i < warpCount; i++)
{
WarpTo w = new WarpTo();
w.address = gb.ReadByte() + gb.ReadByte() * 0x100;
w.y = gb.ReadByte();
w.x = gb.ReadByte();
warpTo.Add(w);
}
}
}
}

138
ClassicMap/MapSaver.cs Normal file
View File

@ -0,0 +1,138 @@
using System;
using System.Collections.Generic;
using System.Text;
using GBHL;
namespace ClassicMap
{
public class MapSaver
{
private GBFile gb;
private MapLoader mapLoader;
private WildPokemonLoader wildPokemonLoader;
public MapSaver(GBFile g, MapLoader ml, WildPokemonLoader wpl)
{
gb = g;
mapLoader = ml;
wildPokemonLoader = wpl;
}
public void Save(int map)
{
//Save the map header
gb.BufferLocation = 0xC23D + map;
gb.WriteByte((byte)(mapLoader.mapHeader.Location / 0x4000));
gb.BufferLocation = 0x01AE + map * 2;
gb.WriteByte((byte)mapLoader.mapHeader.Location);
gb.WriteByte((byte)((((mapLoader.mapHeader.Location % 0x4000) >> 8) & 0xFF) + 0x40));
gb.BufferLocation = mapLoader.mapHeader.Location;
gb.WriteByte(mapLoader.mapHeader.Tileset);
gb.WriteByte(mapLoader.mapHeader.Height);
gb.WriteByte(mapLoader.mapHeader.Width);
gb.WriteByte((byte)mapLoader.mapHeader.LevelData);
gb.WriteByte((byte)((((mapLoader.mapHeader.LevelData % 0x4000) >> 8) & 0xFF) + 0x40));
gb.BufferLocation += 4;
//Skip connections for now
byte connection = gb.ReadByte();
if ((connection & (1 << 3)) != 0)
gb.BufferLocation += 11;
if ((connection & (1 << 2)) != 0)
gb.BufferLocation += 11;
if ((connection & (1 << 1)) != 0)
gb.BufferLocation += 11;
if ((connection & (1 << 0)) != 0)
gb.BufferLocation += 11;
gb.WriteByte((byte)mapLoader.mapHeader.EventData);
gb.WriteByte((byte)((((mapLoader.mapHeader.EventData % 0x4000) >> 8) & 0xFF) + 0x40));
//Save the level data
gb.BufferLocation = mapLoader.mapHeader.LevelData;
for (int y = 0; y < mapLoader.mapHeader.Height; y++)
{
for (int x = 0; x < mapLoader.mapHeader.Width; x++)
{
gb.WriteByte(mapLoader.LevelData[x, y]);
}
}
//Save the event data. Oh boy...
gb.BufferLocation = mapLoader.mapHeader.EventData;
gb.WriteByte(mapLoader.borderTile);
gb.WriteByte((byte)mapLoader.warps.Count);
foreach (Warp w in mapLoader.warps)
{
gb.WriteByte(w.y);
gb.WriteByte(w.x);
gb.WriteByte(w.destPoint);
gb.WriteByte(w.map);
}
gb.WriteByte((byte)mapLoader.signs.Count);
foreach (Sign s in mapLoader.signs)
{
gb.WriteByte(s.y);
gb.WriteByte(s.x);
gb.WriteByte(s.text);
}
gb.WriteByte((byte)mapLoader.people.Count);
foreach (Person p in mapLoader.people)
{
gb.WriteByte(p.sprite);
//These are already formatted.
gb.WriteByte(p.y);
gb.WriteByte(p.x);
gb.WriteByte(p.movement);
gb.WriteByte(p.movement2);
gb.WriteByte((byte)((p.text & 0x3F) | (p.originalText & 0xC0)));
if ((p.originalText & 0x40) != 0)
{
gb.WriteByte(p.trainer);
gb.WriteByte(p.pokemonSet);
}
else if ((p.originalText & 0x80) != 0)
{
gb.WriteByte(p.item);
}
}
foreach (WarpTo w in mapLoader.warpTo)
{
gb.WriteByte((byte)w.address);
gb.WriteByte((byte)(w.address >> 8));
gb.WriteByte(w.y);
gb.WriteByte(w.x);
}
//End of header stuff! Now to save wild Pokemon... Yaaaay...
//Also, for some very, very weird reason, the foreach loop doesn't work here.
//There are only 10 pokemon per array, yet some data wasn't saving properly.
gb.BufferLocation = wildPokemonLoader.wildPokemonLocation;
gb.WriteByte(wildPokemonLoader.rarityGrass);
if (wildPokemonLoader.rarityGrass > 0)
{
for(int i = 0; i < 10; i++)
{
Pokemon p = wildPokemonLoader.grassPokemon[i];
gb.WriteByte(p.level);
gb.WriteByte(p.id);
}
}
gb.WriteByte(wildPokemonLoader.rarityWater);
if (wildPokemonLoader.rarityWater > 0)
{
for (int i = 0; i < 10; i++)
{
Pokemon p = wildPokemonLoader.waterPokemon[i];
gb.WriteByte(p.level);
gb.WriteByte(p.id);
}
}
//Huh... That was a lot easier than I had expected.
}
}
}

20
ClassicMap/Program.cs Normal file
View File

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace ClassicMap
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}

View File

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("ClassicMap")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Charlie")]
[assembly: AssemblyProduct("ClassicMap")]
[assembly: AssemblyCopyright("Copyright © Charlie 2010")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("9209ff14-e984-40ac-a923-469a72483165")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@ -0,0 +1,91 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:2.0.50727.3603
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace ClassicMap.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ClassicMap.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
internal static System.Drawing.Bitmap person {
get {
object obj = ResourceManager.GetObject("person", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
internal static System.Drawing.Bitmap sign {
get {
object obj = ResourceManager.GetObject("sign", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
internal static System.Drawing.Bitmap trigger {
get {
object obj = ResourceManager.GetObject("trigger", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
internal static System.Drawing.Bitmap warp {
get {
object obj = ResourceManager.GetObject("warp", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
}
}

View File

@ -0,0 +1,133 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="person" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\person.bmp;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="sign" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\sign.bmp;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="trigger" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\trigger.bmp;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="warp" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\warp.bmp;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>

View File

@ -0,0 +1,30 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:2.0.50727.3603
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace ClassicMap.Properties
{
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "9.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
{
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default
{
get
{
return defaultInstance;
}
}
}
}

View File

@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

Binary file not shown.

After

Width:  |  Height:  |  Size: 824 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 824 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 824 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 824 B

View File

@ -0,0 +1,65 @@
using System;
using System.Collections.Generic;
using System.Text;
using GBHL;
using System.Drawing;
namespace ClassicMap
{
public class SpriteLoader
{
private GBFile gb;
public SpriteLoader(GBFile g)
{
gb = g;
}
public int CalculateTDA(int sprite)
{
return 0x17B27 + (sprite - 1) * 4;
}
public Bitmap LoadSprite(int sprite)
{
gb.BufferLocation = CalculateTDA(sprite);
int loc = gb.ReadByte() + ((gb.ReadByte() - 0x40) * 0x100);
int count = gb.ReadByte();
byte bank = gb.ReadByte();
if (bank * 0x4000 + loc + 256 >= 0x100000)
{
return new Bitmap(16, 16);
}
gb.BufferLocation = bank * 0x4000 + loc;
if (gb.BufferLocation < 0)
return new Bitmap(16, 16);
byte[, ,] tileData = new byte[32, 8, 8];
gb.ReadTiles(16, 2, gb.BufferLocation, ref tileData);
Bitmap b = new Bitmap(16, 16);
FastPixel fp = new FastPixel(b);
fp.rgbValues = new byte[1024];
fp.Lock();
for (int y = 0; y < 2; y++)
{
for (int x = 0; x < 2; x++)
{
for (int xx = 0; xx < 8; xx++)
{
for (int yy = 0; yy < 8; yy++)
{
fp.SetPixel(x * 8 + xx, y * 8 + yy, Form1.Palette[tileData[x + y * 2, xx, yy]]);
}
}
}
}
fp.Unlock(true);
b.MakeTransparent(Form1.Palette[0]);
return b;
}
}
}

41
ClassicMap/TextTable.cs Normal file
View File

@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ClassicMap
{
public class TextTable
{
public static string[] TextTableChars = new string[] {
" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ",
" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ",
" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ",
" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ",
" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "",
" ", "*", "A1", "A2", "POKe", "+", " ", "#", "$", " ", " ", " ", " ", " ", " ", " ",
" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ",
" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ",
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P",
"Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", " ", " ", ":", " ", " ", " ",
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p",
"q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "<22>", " ", "'l", "'s", "'t", "'v",
" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ",
" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ",
"'", "PK", "MN", "-", "'r", "'m", "?", "!", ".", " ", " ", " ", " ", " ", " ", " ",
" ", " ", " ", " ", ",", " ", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
};
public static string GetString(byte[] bytes)
{
string s = "";
foreach (byte b in bytes)
s += TextTableChars[b];
return s;
}
public static string GetString(byte b)
{
return TextTableChars[b];
}
}
}

View File

@ -0,0 +1,84 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using GBHL;
namespace ClassicMap
{
public class TilesetLoader
{
private GBFile gb;
private byte bank;
private int formationAddress;
private int graphicsAddress;
private byte[, ,] formation;
private byte[, ,] graphics;
public TilesetLoader(GBFile g)
{
gb = g;
}
public void LoadTilesetHeader(int tileset)
{
gb.BufferLocation = 0xC7BE + tileset * 12;
bank = gb.ReadByte();
formationAddress = bank * 0x4000 + gb.ReadByte() + ((gb.ReadByte() - 0x40) * 0x100);
graphicsAddress = bank * 0x4000 + gb.ReadByte() + ((gb.ReadByte() - 0x40) * 0x100);
}
public void LoadFormation()
{
formation = new byte[256, 4, 4];
gb.BufferLocation = formationAddress;
for (int i = 0; i < 256; i++)
{
for (int y = 0; y < 4; y++)
{
for (int x = 0; x < 4; x++)
{
formation[i, x, y] = gb.ReadByte();
}
}
}
}
public void LoadGraphics()
{
graphics = new byte[256, 8, 8];
gb.ReadTiles(16, 6, graphicsAddress, ref graphics);
}
public Bitmap LoadTileset(int tileset)
{
LoadTilesetHeader(tileset);
LoadFormation();
LoadGraphics();
Bitmap b = new Bitmap(32, 8192);
FastPixel fp = new FastPixel(b);
fp.rgbValues = new byte[32 * 8192 * 4];
fp.Lock();
for (int i = 0; i < 256; i++)
{
for (int ytile = 0; ytile < 4; ytile++)
{
for (int xtile = 0; xtile < 4; xtile++)
{
for (int y = 0; y < 8; y++)
{
for (int x = 0; x < 8; x++)
{
fp.SetPixel(xtile * 8 + x, i * 32 + ytile * 8 + y, Form1.Palette[graphics[formation[i, xtile, ytile], x, y]]);
}
}
}
}
}
fp.Unlock(true);
return b;
}
}
}

109
ClassicMap/TownMapLoader.cs Normal file
View File

@ -0,0 +1,109 @@
using System;
using System.Collections.Generic;
using System.Text;
using GBHL;
using System.Drawing;
namespace ClassicMap
{
//Well, here we load the town map and stuff.
//There are 2 very weak compressions which we take care of and then create the map.
public class TownMapLoader
{
private GBFile gb;
public byte[] data;
public byte[,,] tileData;
private int tileLocation = 0x125A8;
private int markerLocation = 0x70F40;
public TownMapLoader(GBFile g)
{
gb = g;
data = new byte[360];
}
public Bitmap LoadMap()
{
Bitmap b = new Bitmap(160, 144);
FastPixel fp = new FastPixel(b);
fp.rgbValues = new byte[160 * 144 * 4];
fp.Lock();
LoadData();
LoadTileData();
for (int i = 0; i < 360; i++)
{
for (int y = 0; y < 8; y++)
{
for (int x = 0; x < 8; x++)
{
fp.SetPixel((i % 20) * 8 + x, (i / 20) * 8 + y, Form1.Palette[tileData[data[i], x, y]]);
}
}
}
fp.Unlock(true);
return b;
}
public Bitmap LoadMarker()
{
byte[] decompressed = new byte[0x40];
gb.BufferLocation = markerLocation;
int index = 0;
for (int i = 0; i < 0x10; i++)
{
byte by = gb.ReadByte();
decompressed[index++] = by;
decompressed[index++] = by;
by = gb.ReadByte();
decompressed[index++] = by;
decompressed[index++] = by;
}
byte[, ,] markerData = new byte[4, 8, 8];
gb.ReadTiles(2, 2, decompressed, ref markerData);
Bitmap b = new Bitmap(16, 16);
FastPixel fp = new FastPixel(b);
fp.rgbValues = new byte[1024];
fp.Lock();
LoadData();
LoadTileData();
for (int i = 0; i < 4; i++)
{
for (int y = 0; y < 8; y++)
{
for (int x = 0; x < 8; x++)
{
fp.SetPixel((i % 2) * 8 + x, (i / 2) * 8 + y, Form1.Palette[markerData[i, x, y]]);
}
}
}
fp.Unlock(true);
b.MakeTransparent(Form1.Palette[0]);
return b;
}
public void LoadData()
{
gb.BufferLocation = 0x71100;
int index = 0;
while (true)
{
byte b = gb.ReadByte();
if (b == 0)
break;
int count = (b & 0xF);
for (int i = 0; i < count; i++)
{
data[index++] = (byte)((b >> 4)); //Initially did + 60, however we're not using tiles like that
}
}
}
public void LoadTileData()
{
tileData = new byte[32, 8, 8];
gb.ReadTiles(16, 2, tileLocation, ref tileData);
}
}
}

View File

@ -0,0 +1,84 @@
using System;
using System.Collections.Generic;
using System.Text;
using GBHL;
namespace ClassicMap
{
public class Pokemon
{
public byte level;
public byte id;
}
public class WildPokemonLoader
{
GBFile gb;
public byte rarityGrass;
public byte rarityWater;
public Pokemon[] grassPokemon;
public Pokemon[] waterPokemon;
public string[] PokemonNames;
public byte[] PokemonIndicies;
public int wildPokemonLocation;
public WildPokemonLoader(GBFile g)
{
gb = g;
}
public void LoadWildPokemon(int map)
{
gb.BufferLocation = 0xCEEB + map * 2;
gb.BufferLocation = 0xC000 + gb.ReadByte() + ((gb.ReadByte() - 0x40) * 0x100);
wildPokemonLocation = gb.BufferLocation;
rarityGrass = gb.ReadByte();
rarityWater = 0;
grassPokemon = new Pokemon[10];
waterPokemon = new Pokemon[10];
if (rarityGrass != 0)
{
for (int i = 0; i < 10; i++)
{
Pokemon p = new Pokemon();
p.level = gb.ReadByte();
p.id = gb.ReadByte();
grassPokemon[i] = p;
}
}
rarityWater = gb.ReadByte();
if (rarityWater == 0)
return;
for (int i = 0; i < 10; i++)
{
Pokemon p = new Pokemon();
p.level = gb.ReadByte();
p.id = gb.ReadByte();
waterPokemon[i] = p;
}
}
public void LoadPokemonNames()
{
gb.BufferLocation = 0x41024;
byte[] indicies = gb.ReadBytes(256);
PokemonIndicies = indicies;
string[] names = new string[256];
for (int i = 0; i < 191; i++)
{
gb.BufferLocation = 0x1C21E + (i * 10);
byte[] nameBytes = gb.ReadBytes(10);
string s = "";
for (int k = 0; k < 10; k++)
if (nameBytes[k] != 0x50)
s += TextTable.GetString(nameBytes[k]);
string ss = i.ToString("X");
if (ss.Length == 1)
ss = "0" + ss;
names[indicies[i]] = ss + " - " + s;
}
PokemonNames = names;
}
}
}

3
ClassicMap/app.config Normal file
View File

@ -0,0 +1,3 @@
<?xml version="1.0"?>
<configuration>
<startup><supportedRuntime version="v2.0.50727"/></startup></configuration>