diff --git a/About.dfm b/About.dfm new file mode 100644 index 0000000..cf57c1f --- /dev/null +++ b/About.dfm @@ -0,0 +1,169 @@ +object AboutDialog: TAboutDialog + Left = 0 + Top = 0 + BorderIcons = [biSystemMenu, biMinimize] + BorderStyle = bsSingle + Caption = 'About' + ClientHeight = 255 + ClientWidth = 417 + Color = clBtnFace + Font.Charset = DEFAULT_CHARSET + Font.Color = clWindowText + Font.Height = -11 + Font.Name = 'Tahoma' + Font.Style = [] + OldCreateOrder = False + PixelsPerInch = 96 + TextHeight = 13 + object Shape1: TShape + Left = 64 + Top = 0 + Width = 353 + Height = 216 + Pen.Color = clWhite + end + object Bevel1: TBevel + Left = 0 + Top = 216 + Width = 417 + Height = 2 + end + object Shape2: TShape + Left = 0 + Top = 0 + Width = 65 + Height = 217 + Brush.Color = clRed + Pen.Color = clSkyBlue + Pen.Style = psClear + Pen.Width = 0 + end + object AppNameLabel: TLabel + Left = 72 + Top = 8 + Width = 46 + Height = 13 + Caption = 'RedMap' + Color = clWhite + Font.Charset = ANSI_CHARSET + Font.Color = clWindowText + Font.Height = -11 + Font.Name = 'Tahoma' + Font.Style = [fsBold] + ParentColor = False + ParentFont = False + Transparent = False + end + object Label1: TLabel + Left = 72 + Top = 192 + Width = 271 + Height = 13 + Caption = 'Joint effort by Xeon, Koolboyman, and BlueSonic' + Color = clWhite + Font.Charset = DEFAULT_CHARSET + Font.Color = clWindowText + Font.Height = -11 + Font.Name = 'Tahoma' + Font.Style = [fsBold] + ParentColor = False + ParentFont = False + end + object VersionLabel: TLabel + Left = 72 + Top = 24 + Width = 79 + Height = 13 + Caption = 'Version 2.0 Beta' + Color = clWhite + ParentColor = False + end + object Image1: TImage + Left = 16 + Top = 16 + Width = 32 + Height = 32 + Picture.Data = { + 055449636F6E0000010002001010100000000000280100002600000020201000 + 00000000E80200004E0100002800000010000000200000000100040000000000 + C000000000000000000000001000000000000000000000000000800000800000 + 00808000800000008000800080800000C0C0C000808080000000FF0000FF0000 + 00FFFF00FF000000FF00FF00FFFF0000FFFFFF000000000000000000000F7000 + 000F7000880F7088880F7088880F7088880F70880000000000000000FFFFFFFF + FFFFFFFFF888888FF888888FFFFFFFFFFFFFFFFF0FFF00FF0F0FF00F00FF0F0F + 0F0F00FF0F0F0F0F00FF0F0F0F0F0F0F0F0F000F00FFF00F0F0FF0FF77777777 + 7777770700000000000000007777777777777777E7E7FFFF0000FFFF0000FFFF + 0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF + 0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF280000002000000040000000 + 0100040000000000800200000000000000000000100000000000000000000000 + 000080000080000000808000800000008000800080800000C0C0C00080808000 + 0000FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF0000000000 + 000000000000000000000000000F7000000F70000000000000000000880F7088 + 880F70888888888887000000880F7088880F7088888888888700000000000000 + 000000007777777777000000FFFFFFFFFFFFFFFFFFFFFFFFFF000000F888888F + F888888F77777777FF000000FFFFFFFFFFFFFFFF77777777770000000FFF00FF + 0F0FF00FF777778FFF00000000FF0F0F0F0F00FFFFFFFFFFFF0000000F0F0F0F + 00FF0F0F778F7777FF0000000F0F0F0F0F0F000F778F7777FF00000000FFF00F + 0F0FF0FFFFFFFFFFFF00000077777777777777077777778FFF00000000000000 + 000000007777778FFF0000007777777777777777FFFFFFFFFF000000F777778F + F777778FF777778FFF000000FFFFFFFFFFFFFFFFFFFFFFFFFF000000778F7777 + 778F7777778F7777FF000000778F7777778F7777778F7777FF000000FFFFFFFF + FFFFFFFFFFFFFFFFFF0000007777778F7777778F7777778FFF0000007777778F + 7777778F7777778FFF000000FFFFFFFFFFFFFFFFFFFFFFFFFF00000080000008 + 8000000880000008FF00000007F8F88007F8F88007F8F880FF0000000F7F8780 + 0F7F87800F7F8780FF0000000FF7F8F00FF7F8F00FF7F8F0FF0000000FFF7F80 + 0FFF7F800FFF7F80FF0000000FFFF7F00FFFF7F00FFFF7F0FF00000080000008 + 8000000880000008FF000000777777777777777777777777FF000000E7E7FFFF + 0000003F0000001F0000001F0000001F0000001F0000001F0000001F0000001F + 0000001F0000001F0000001F0000001F0000001F0000001F0000001F0000001F + 0000001F0000001F0000001F0000001F0000001F0000001F0000001F0000001F + 0000001F0000001F0000001F0000001F0000001F0000001F0000001F0D0A} + end + object Button1: TButton + Left = 336 + Top = 224 + Width = 75 + Height = 23 + Cancel = True + Caption = 'OK' + Default = True + ModalResult = 1 + TabOrder = 0 + end + object Memo1: TMemo + Left = 72 + Top = 48 + Width = 337 + Height = 137 + BorderStyle = bsNone + Lines.Strings = ( + 'Special thanks to BlueSonic (aka Jigglypuff) for letting me use ' + 'some of GoldMap to forge this frankenstein of a program. And ' + 'for putting up with all my questions regarding Delphi.' + '' + 'Koolboyman for the immense amount of data and information you ' + 'provided me. ' + '' + 'Tauwasser for showing me how the warp-to points, connection ' + 'data, and ram addresses where calculated. ' + '' + 'And also, tons of respect to the author of ZeroMap, you where ' + 'my inspiration for how to go about displaying the connected ' + 'maps.' + '' + 'This program is not endorsed or supported by Nintendo, and the ' + 'author is not affiliated with any other corporate entity.' + '' + 'This program is Freeware and provided "as is". The author ' + + 'cannot be held liable for damages any kind arising from it'#39's use' + + ' or ' + 'presence.' + '' + 'Pok'#233'mon is copyright of '#169'1995-2005 ' + 'Nintendo/Creatures Inc./GAME FREAK Inc.') + ReadOnly = True + ScrollBars = ssVertical + TabOrder = 1 + end +end diff --git a/About.pas b/About.pas new file mode 100644 index 0000000..0efd5da --- /dev/null +++ b/About.pas @@ -0,0 +1,33 @@ +unit About; + +interface + +uses + Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, + Dialogs, StdCtrls, pngimage, ExtCtrls; + +type + TAboutDialog = class(TForm) + Shape1: TShape; + Bevel1: TBevel; + Shape2: TShape; + AppNameLabel: TLabel; + Label1: TLabel; + VersionLabel: TLabel; + Image1: TImage; + Button1: TButton; + Memo1: TMemo; + private + { Private declarations } + public + { Public declarations } + end; + +var + AboutDialog: TAboutDialog; + +implementation + +{$R *.dfm} + +end. diff --git a/BlockEditor.dfm b/BlockEditor.dfm new file mode 100644 index 0000000..10adde9 Binary files /dev/null and b/BlockEditor.dfm differ diff --git a/BlockEditor.pas b/BlockEditor.pas new file mode 100644 index 0000000..88b4856 --- /dev/null +++ b/BlockEditor.pas @@ -0,0 +1,160 @@ +//****************************************************************************** +//GoldMap +//by BlueSonic (aka Jigglypuff) +//****************************************************************************** +unit BlockEditor; + +interface + +uses +SysUtils, Controls, Classes, Forms, StdCtrls, ExtCtrls, Graphics; + +type + TBlockEditorForm = class(TForm) + ScrollBox1: TScrollBox; + TileLabel: TLabel; + BlockLabel: TLabel; + UpdateButton: TButton; + AddressLabel: TLabel; + BlockEditBox: TImage; + BlockBox: TPaintBox; + TilePalette: TImage; + procedure FormCreate(Sender: TObject); + procedure BlockBoxMouseMove(Sender: TObject; Shift: TShiftState; X,Y: Integer); + procedure BlockBoxMouseDown(Sender: TObject; Button: TMouseButton;Shift: TShiftState; X, Y: Integer); + procedure LoadTile; + procedure SaveTile; + procedure UpdateTile; + procedure TilePaletteMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); + procedure TilePaletteMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); + procedure BlockEditBoxMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); + procedure UpdateButtonClick(Sender: TObject); + procedure BlockBoxPaint(Sender: TObject); + procedure BlockEditBoxMouseMove(Sender: TObject; Shift: TShiftState; X, + Y: Integer); + public + BlockStart,SelTile,TileNumber : Integer; + BlockData: array [0..15] of Byte; + end; + +implementation + +uses MapEditor; + +{$R *.DFM} + +procedure TBlockeditorForm.LoadTile; +begin + Rom.Position := BlockStart; + //loads block + Rom.Read(BlockData, SizeOf(BlockData)); +end; + +procedure TBlockeditorForm.SaveTile; +begin + Rom.Position := BlockStart; + //Saves block + Rom.Write(BlockData, SizeOf(BlockData)); +end; + +procedure TBlockeditorForm.UpdateTile; +var + X,Y,I: Integer; + TileX, TileY, TileNumber: Byte; +begin + I := 0; + //draws tiles into block + for Y := 0 to 3 do + for X := 0 to 3 do + begin + TileNumber := BlockData[I]; + //calculate x and y coordinate where to copy tile from, the tileset picture has 16 tiles per line + TileY := TileNumber div 16; + TileX := TileNumber mod 16; + //draw tile to block picture + BlockEditBox.Picture.Bitmap.Canvas.CopyRect(Rect(X*8,Y*8,X*8+8,Y*8+8),Tiles.Canvas,Rect(TileX*8,TileY*8,TileX*8+8,TileY*8+8)); + Inc(I); + end; +end; + +procedure TBlockEditorForm.FormCreate(Sender: TObject); +begin + //create block bitmap + BlockEditBox.Picture.Bitmap := TBitmap.Create; + BlockEditBox.Picture.Bitmap.Height := 32; + BlockEditBox.Picture.Bitmap.Width := 32; + BlockEditBox.Picture.Bitmap.PixelFormat := pf24bit; + //initalize other stuff + //BlockBox.Picture.Bitmap := MainForm.BlockPalette.Picture.Bitmap; + BlockBox.Height := MapEditorForm.BlockPalette.Height; + TilePalette.Picture.Graphic := Tiles; + //TilePalette.Height := Tiles.Height; + Caption := 'Block Editor - Tileset ' + IntToStr(LoadedTileset); + BlockStart := TilesetStart; + LoadTile; + UpdateTile; +end; + +procedure TBlockEditorForm.BlockBoxMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); +begin + BlockLabel.Caption := 'Block: $' + IntToHex(Y div 32, 2); + AddressLabel.Caption := 'Offset: $' + IntToHex(TilesetStart + ((Y div 32) * 16), 2); +end; + +procedure TBlockEditorForm.BlockBoxMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); +begin + BlockStart := TilesetStart + ((Y div 32) * 16); + TileNumber := Y div 32; + LoadTile; + UpdateTile; +end; + +procedure TBlockEditorForm.TilePaletteMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); +begin + TileLabel.Caption := 'Tile: $' + IntToHex((X div 8) + ((Y div 8) * 8), 2); +end; + +procedure TBlockEditorForm.TilePaletteMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); +begin + //gets tile where cursor is + SelPic := (X div 8) + ((Y div 8) * 8); +end; + +procedure TBlockEditorForm.BlockEditBoxMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); +begin + if Button = mbLeft then + begin + //puts selected tile into block + BlockData[(X div 8) + ((Y div 8) * 4)] := SelPic; + UpdateTile; + end + else + begin + SelPic := BlockData[(X div 8) + ((Y div 8) * 4)]; + end; +end; + +procedure TBlockEditorForm.UpdateButtonClick(Sender: TObject); +begin + SaveTile; + //draws edited tile into tileset + BlockPics[TileNumber].Canvas.Draw(0, 0, BlockEditBox.Picture.Bitmap); + //update block palette + MapEditorForm.DrawBlocks(MapEditorForm.BlockPalette.Canvas); + MapEditorForm.DrawBlocks(BlockBox.Canvas); + MapEditorForm.DrawMap(MapEditorForm.MapBox.Canvas); + RomModified := True; +end; + +procedure TBlockEditorForm.BlockBoxPaint(Sender: TObject); +begin + MapEditorForm.DrawBlocks(BlockBox.Canvas); +end; + +procedure TBlockEditorForm.BlockEditBoxMouseMove(Sender: TObject; + Shift: TShiftState; X, Y: Integer); +begin + TileLabel.Caption := 'Tile: $' + IntToHex(BlockData[(X div 8) + ((Y div 8) * 4)], 2); +end; + +end. diff --git a/Map.pas b/Map.pas new file mode 100644 index 0000000..65273df --- /dev/null +++ b/Map.pas @@ -0,0 +1,128 @@ +unit Map; + +interface + +uses ComCtrls,SysUtils,Dialogs,Classes; + +type + +TConnectionData = packed record + MapNumber: Byte; + MapDataPointer: Word; + MapLocationRamPointer: Word; + WidthHeightVisiblePart: Byte; + YChangePoint: Byte; + XChangePoint: Byte; + Unknown: Byte; + UnknownPointer: Word; +end; + +//Header 1 +TMapHeader = packed record + TilesetNumber: Byte; + Height: Byte; + Width: Byte; + DataPointer: Word; + ObjectScriptPointers: Word; + LevelScriptPointer: Word; + ConnectionDataControl: Byte; + ConnectionData: array [$00..$03] of TConnectionData; + ObjectDataPointer: Word; + BorderBlock: Byte; +end; + +const +Ln = #13#10; + +//table needed for encoding area names +Table: array [$00..$FF] of string[4] = ( +{ 0 1 2 3 4 5 6 7 8 9 A B C D E F } +{0}'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' , +{1}'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,' ' , +{2}'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' , +{3}'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' , +{4}'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,Ln , +{5}'#' ,Ln+Ln ,'HIRO','GARY','POKé',Ln ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' , +{6}'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' , +{7}'#' ,'#' ,'#' ,'#' ,'#' ,'…' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,' ' , +{8}'A' ,'B' ,'C' ,'D' ,'E' ,'F' ,'G' ,'H' ,'I' ,'J' ,'K' ,'L' ,'M' ,'N' ,'O' ,'P' , +{9}'Q' ,'R' ,'S' ,'T' ,'U' ,'V' ,'W' ,'X' ,'Y' ,'Z' ,'#' ,'#' ,':' ,'#' ,'#' ,'#' , +{A}'a' ,'b' ,'c' ,'d' ,'e' ,'f' ,'g' ,'h' ,'i' ,'j' ,'k' ,'l' ,'m' ,'n' ,'o' ,'p' , +{B}'q' ,'r' ,'s' ,'t' ,'u' ,'v' ,'w' ,'x' ,'y' ,'z' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' , +{C}'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' , +{D}'#' ,'''l' ,'''m' ,'''r' ,'''s' ,'''t' ,'''v' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' , +{E}'''' ,'#' ,'#' ,'-' ,'#' ,'#' ,'?' ,'!' ,'.' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' , +{F}'#' ,' ' ,'#' ,'#' ,',' ,'#' ,'0' ,'1' ,'2' ,'3' ,'4' ,'5' ,'6' ,'7' ,'8' ,'9' +); + +function GBPtrToFilePos(Bank: Byte; Addr: Word): Integer; overload; +function GBBank(Position: Integer): Byte; +procedure ReadMapHeaderLocations; +function GetMapHeader(MapIndex: Byte): TMapHeader; + +var + AreaNames: TStringList; + BankLocations: array [$00..$F9] of Byte; + MapHeaderOffsets: array [$00..$F9] of Word; + +implementation + +uses MapEditor; + +//converts rombank and, address in that bank, into romfile offset +function GBPtrToFilePos(Bank: Byte; Addr: Word): Integer; overload; +begin + Result := (Bank * $4000) + (Addr xor $4000); +end; + +//gives gameboy rombank number ar specified file offset +function GBBank(Position: Integer): Byte; +begin + Result := (Position div $4000); +end; + +procedure ReadMapHeaderLocations; +begin + Rom.Position := $C23D; + Rom.Read(BankLocations, $F9); + Rom.Position := $01AE; + Rom.Read(MapHeaderOffsets, $F9 * sizeof(Word)); +end; + +function GetMapHeader(MapIndex: Byte): TMapHeader; +var + TempHeader: TMapHeader; +begin + Rom.Position := GBPtrToFilePos(BankLocations[MapIndex], MapHeaderOffsets[MapIndex]); + + Rom.Read(TempHeader.TilesetNumber, 1); + Rom.Read(TempHeader.Height, 1); + Rom.Read(TempHeader.Width, 1); + Rom.Read(TempHeader.DataPointer, 2); + Rom.Read(TempHeader.ObjectScriptPointers, 2); + Rom.Read(TempHeader.LevelScriptPointer, 2); + Rom.Read(TempHeader.ConnectionDataControl, 1); + + if (TempHeader.ConnectionDataControl and $08) = $08 then + Rom.Read(TempHeader.ConnectionData[0], SizeOf(TConnectionData)); + + if (TempHeader.ConnectionDataControl and $04) = $04 then + Rom.Read(TempHeader.ConnectionData[1], SizeOf(TConnectionData)); + + if (TempHeader.ConnectionDataControl and $02) = $02 then + Rom.Read(TempHeader.ConnectionData[2], SizeOf(TConnectionData)); + + if (TempHeader.ConnectionDataControl and $01) = $01 then + Rom.Read(TempHeader.ConnectionData[3], SizeOf(TConnectionData)); + + Rom.Read(TempHeader.ObjectDataPointer, 2); + + Rom.Position := GBPtrToFilePos(BankLocations[MapIndex], + TempHeader.ObjectDataPointer); + + Rom.Read(TempHeader.BorderBlock, 1); + + Result := TempHeader; +end; + +end. diff --git a/MapEditor.ddp b/MapEditor.ddp new file mode 100644 index 0000000..4370276 Binary files /dev/null and b/MapEditor.ddp differ diff --git a/MapEditor.dfm b/MapEditor.dfm new file mode 100644 index 0000000..b63f98a --- /dev/null +++ b/MapEditor.dfm @@ -0,0 +1,1475 @@ +object MapEditorForm: TMapEditorForm + Left = 193 + Top = 122 + Width = 655 + Height = 699 + Caption = 'RedMap' + Color = clBtnFace + Font.Charset = DEFAULT_CHARSET + Font.Color = clWindowText + Font.Height = -11 + Font.Name = 'Tahoma' + Font.Style = [] + Menu = MainMenu1 + OldCreateOrder = False + OnCreate = FormCreate + PixelsPerInch = 96 + TextHeight = 13 + object PageControl1: TPageControl + Left = 0 + Top = 33 + Width = 639 + Height = 588 + ActivePage = TabSheet1 + Align = alClient + TabOrder = 0 + object TabSheet1: TTabSheet + Caption = 'Map' + object MapScrollBox: TScrollBox + Left = 0 + Top = 0 + Width = 582 + Height = 560 + HorzScrollBar.Tracking = True + VertScrollBar.Tracking = True + Align = alClient + BorderStyle = bsNone + TabOrder = 0 + Visible = False + object MapBox: TPaintBox + Left = 0 + Top = 0 + Width = 129 + Height = 121 + Cursor = crDrag + OnMouseDown = MapBoxMouseDown + OnMouseMove = MapBoxMouseMove + OnMouseUp = MapBoxMouseUp + OnPaint = MapBoxPaint + end + object shpHighlight: TShape + Left = 0 + Top = 0 + Width = 32 + Height = 32 + Brush.Color = 33023 + Enabled = False + Pen.Mode = pmMask + Pen.Style = psClear + Pen.Width = 0 + end + end + object BlockPaletteScrollBox: TScrollBox + Left = 582 + Top = 0 + Width = 49 + Height = 560 + HorzScrollBar.Tracking = True + VertScrollBar.Tracking = True + Align = alRight + BevelInner = bvNone + BevelOuter = bvNone + BorderStyle = bsNone + TabOrder = 1 + Visible = False + object BlockPalette: TPaintBox + Left = 0 + Top = 0 + Width = 32 + Height = 105 + Cursor = crHandPoint + OnMouseDown = BlockPaletteMouseDown + OnMouseMove = BlockPaletteMouseMove + OnPaint = BlockPalettePaint + end + end + end + object TabSheet2: TTabSheet + Caption = 'Events' + ImageIndex = 1 + object NoEventsLabel: TLabel + Left = 16 + Top = 16 + Width = 170 + Height = 13 + Caption = 'Events for this map are not loaded.' + Visible = False + WordWrap = True + end + object EventScrollBox: TScrollBox + Left = 0 + Top = 0 + Width = 631 + Height = 560 + HorzScrollBar.Tracking = True + VertScrollBar.Tracking = True + Align = alClient + BorderStyle = bsNone + TabOrder = 0 + Visible = False + object SignpostImage: TImage + Left = 256 + Top = 128 + Width = 32 + Height = 32 + Visible = False + end + object PeopleImage: TImage + Left = 296 + Top = 128 + Width = 32 + Height = 32 + Visible = False + end + object WarpImage: TImage + Left = 216 + Top = 128 + Width = 32 + Height = 32 + Visible = False + end + object EventBox: TPaintBox + Left = 0 + Top = 0 + Width = 100 + Height = 105 + end + object TriggerImage: TImage + Left = 336 + Top = 128 + Width = 32 + Height = 32 + Visible = False + end + end + end + object TabSheet3: TTabSheet + Caption = 'Wild Pok'#233'mon' + ImageIndex = 2 + object NoWildPkmnLabel: TLabel + Left = 8 + Top = 8 + Width = 449 + Height = 26 + Caption = + 'It seems this map does not have wild Pok'#233'mon data associated to ' + + 'it. Some maps do not have wild Pok'#233'mon at all (e.g. indoor place' + + 's).' + WordWrap = True + end + object LandGroup1: TGroupBox + Left = 8 + Top = 40 + Width = 385 + Height = 249 + Caption = 'Land Pok'#233'mon' + TabOrder = 0 + object OffsetLabel1: TLabel + Left = 200 + Top = 176 + Width = 35 + Height = 13 + Caption = 'Offset:' + end + object LandOffset1: TLabel + Left = 240 + Top = 176 + Width = 18 + Height = 13 + Caption = '$00' + end + object LandPkmnBox: TListBox + Left = 16 + Top = 24 + Width = 105 + Height = 137 + Hint = 'Wild Pok'#233'mon on land' + Style = lbOwnerDrawFixed + Enabled = False + Font.Charset = DEFAULT_CHARSET + Font.Color = clBlack + Font.Height = -11 + Font.Name = 'MS Sans Serif' + Font.Style = [] + ItemHeight = 13 + Items.Strings = ( + '' + '' + '' + '' + '' + '' + '' + '' + '' + '') + ParentFont = False + TabOrder = 0 + OnClick = LandPkmnBoxClick + end + object LandLevelBox: TListBox + Left = 128 + Top = 24 + Width = 41 + Height = 137 + Enabled = False + ItemHeight = 13 + TabOrder = 1 + end + object LandPkmnGroup: TGroupBox + Left = 200 + Top = 24 + Width = 169 + Height = 49 + Caption = 'Pokemon' + TabOrder = 2 + object LandPkmnCombo: TComboBox + Left = 8 + Top = 20 + Width = 153 + Height = 21 + Style = csDropDownList + Enabled = False + ItemHeight = 13 + TabOrder = 0 + Items.Strings = ( + '00 Missingno' + '01 Rydon' + '02 Kangaskahn' + '03 Nidoran M' + '04 Clefairy' + '05 Spearow' + '06 Voltorb' + '07 Nidoking' + '08 Slowbro' + '09 Ivysaur' + '0A Eggecutor' + '0B Licktung' + '0C Exegute' + '0D Grimer' + '0E Gengar' + '0F Nidoran F' + '10 Nidoqueen' + '11 Cubone' + '12 Ryhorn' + '13 Lapras' + '14 Arcanine' + '15 Mew' + '16 Gyrados' + '17 Shellder' + '18 Tentacool' + '19 Gastly' + '1A Scyther' + '1B Staryu' + '1C Blastoice' + '1D Pinser' + '1E Tangala' + '1F **Bad Pokemon**' + '20 **Bad Pokemon**' + '21 Growlithe' + '22 Onix' + '23 Fearow' + '24 Pidgey' + '25 Slowpoke' + '26 Kadabra' + '27 Graveler' + '28 Chansey' + '29 Machoke' + '2A Mr. Mime' + '2B Hitmonlee' + '2C Hitmonchan' + '2D Arbok' + '2E Parasect' + '2F Psyduck' + '30 Drowzee' + '31 Golom' + '32 **Bad Pokemon**' + '33 Magmar' + '34 **Bad Pokemon**' + '35 Electabuzz' + '36 Magneton' + '37 Koffing' + '38 **Bad Pokemon**' + '39 Mankey' + '3A Seel' + '3B Digglett' + '3C Tarous' + '3D **Bad Pokemon**' + '3E **Bad Pokemon**' + '3F **Bad Pokemon**' + '40 FarFetche'#39'd' + '41 Venonat' + '42 Dragonite' + '43 **Bad Pokemon**' + '44 **Bad Pokemon**' + '45 **Bad Pokemon**' + '46 Doduo' + '47 Poliwag' + '48 Jynx' + '49 Moltres' + '4A Articuno' + '4B Zapdos' + '4C Ditto' + '4D Meowth' + '4E Krabby' + '4F **Bad Pokemon**' + '50 **Bad Pokemon**' + '51 **Bad Pokemon**' + '52 Vulpix' + '53 Ninetails' + '54 Pikachu' + '55 Raichu' + '56 **Bad Pokemon**' + '57 **Bad Pokemon**' + '58 Dratini' + '59 Dragonair' + '5A Kabuto' + '5B Kabutops' + '5C Horsea' + '5D Seadra' + '5E **Bad Pokemon**' + '5F **Bad Pokemon**' + '60 Sandshrew' + '61 Sandslash' + '62 Omanyte' + '63 Omaster' + '64 Jigglypuff' + '65 Wigglytuff' + '66 Eevee' + '67 Flareon' + '68 Jolteon' + '69 Vaporeon' + '6A Machop' + '6B Zubat' + '6C Ekans' + '6D Paras' + '6E Poliwhirl' + '6F Poliwrath' + '70 Weedle' + '71 Kakuna' + '72 Beedril' + '73 **Bad Pokemon**' + '74 Dodrio' + '75 Primeape' + '76 Dugtrio' + '77 Venomoth' + '78 Dewgong' + '79 **Bad Pokemon**' + '7A **Bad Pokemon**' + '7B Caterpie' + '7C Metapod' + '7D Butterfree' + '7E Machamp' + '7F **Bad Pokemon**' + '80 Golduck' + '81 Hypno' + '82 Golbat' + '83 Mewtwo' + '84 Snorlax' + '85 Magikarp' + '86 **Bad Pokemon**' + '87 **Bad Pokemon**' + '88 Muk' + '89 **Bad Pokemon**' + '8A Kingler' + '8B Cloyster' + '8C **Bad Pokemon**' + '8D Electrode' + '8E Clefable' + '8F Weezing' + '90 Persian' + '91 Marowak' + '92 **Bad Pokemon**' + '93 Haunter' + '94 Abra' + '95 Alakazzam' + '96 Pidgeotto' + '97 Pidgeot' + '98 Starmie' + '99 Bulbasaur' + '9A Venusaur' + '9B Tentacruel' + '9C **Bad Pokemon**' + '9D Goldeen' + '9E Seaking' + '9F **Bad Pokemon**' + 'A0 **Bad Pokemon**' + 'A1 **Bad Pokemon**' + 'A2 **Bad Pokemon**' + 'A3 Ponyta' + 'A4 Rapidash' + 'A5 Rattata' + 'A6 Ratticate' + 'A7 Nidorino' + 'A8 Nidorina' + 'A9 Geodude' + 'AA Porygon' + 'AB Areodactyl' + 'AC **Bad Pokemon**' + 'AD Magnemite' + 'AE **Bad Pokemon**' + 'AF **Bad Pokemon**' + 'B0 Charmander' + 'B1 Squirtle' + 'B2 Charmeleon' + 'B3 Wartortle' + 'B4 Charizard' + 'B5 **Bad Pokemon**' + 'B6 **Bad Pokemon**' + 'B7 **Bad Pokemon**' + 'B8 **Bad Pokemon**' + 'B9 Oddish' + 'BA Gloom' + 'BB Vileplume' + 'BC Bellsprout' + 'BD Weepinbell' + 'BE Victreebell') + end + end + object LandLevelGroup: TGroupBox + Left = 200 + Top = 80 + Width = 169 + Height = 49 + Caption = 'Level' + TabOrder = 3 + object LandPkmnLevel: TSpinEdit + Left = 8 + Top = 19 + Width = 153 + Height = 22 + Hint = 'Pok'#233'mon'#39's level' + Enabled = False + MaxValue = 255 + MinValue = 1 + TabOrder = 0 + Value = 1 + end + end + object LandReplaceBtn: TButton + Left = 200 + Top = 136 + Width = 75 + Height = 25 + Caption = 'Replace' + Enabled = False + TabOrder = 4 + OnClick = LandReplaceBtnClick + end + object LandRateGroup: TGroupBox + Left = 16 + Top = 168 + Width = 169 + Height = 65 + Caption = 'Encounter Rate' + TabOrder = 5 + object Less1: TLabel + Left = 8 + Top = 48 + Width = 21 + Height = 13 + Caption = 'Less' + end + object More1: TLabel + Left = 136 + Top = 48 + Width = 24 + Height = 13 + Caption = 'More' + end + object LandPercent: TLabel + Left = 57 + Top = 48 + Width = 56 + Height = 13 + Alignment = taCenter + AutoSize = False + Caption = '%' + end + object LandRateTrack: TTrackBar + Left = 8 + Top = 16 + Width = 153 + Height = 33 + Enabled = False + Max = 100 + Min = 1 + Frequency = 10 + Position = 1 + TabOrder = 0 + OnExit = LandRateTrackExit + end + end + end + object WaterGroup1: TGroupBox + Left = 8 + Top = 304 + Width = 385 + Height = 249 + Caption = 'Water Pok'#233'mon' + TabOrder = 1 + object OffsetLabel2: TLabel + Left = 200 + Top = 176 + Width = 35 + Height = 13 + Caption = 'Offset:' + end + object WaterOffset1: TLabel + Left = 240 + Top = 176 + Width = 18 + Height = 13 + Caption = '$00' + end + object WaterPkmnBox: TListBox + Left = 16 + Top = 24 + Width = 105 + Height = 137 + Hint = 'Wild Pok'#233'mon on land' + Style = lbOwnerDrawFixed + Enabled = False + Font.Charset = DEFAULT_CHARSET + Font.Color = clBlack + Font.Height = -11 + Font.Name = 'MS Sans Serif' + Font.Style = [] + ItemHeight = 13 + Items.Strings = ( + '' + '' + '' + '' + '' + '' + '' + '' + '' + '') + ParentFont = False + TabOrder = 0 + OnClick = WaterPkmnBoxClick + end + object WaterLevelBox: TListBox + Left = 128 + Top = 24 + Width = 41 + Height = 137 + Enabled = False + ItemHeight = 13 + TabOrder = 1 + end + object WaterPkmnGroup: TGroupBox + Left = 200 + Top = 24 + Width = 169 + Height = 49 + Caption = 'Pokemon' + TabOrder = 2 + object WaterPkmnCombo: TComboBox + Left = 8 + Top = 20 + Width = 153 + Height = 21 + Style = csDropDownList + Enabled = False + ItemHeight = 13 + TabOrder = 0 + Items.Strings = ( + '00 Missingno' + '01 Rydon' + '02 Kangaskahn' + '03 Nidoran M' + '04 Clefairy' + '05 Spearow' + '06 Voltorb' + '07 Nidoking' + '08 Slowbro' + '09 Ivysaur' + '0A Eggecutor' + '0B Licktung' + '0C Exegute' + '0D Grimer' + '0E Gengar' + '0F Nidoran F' + '10 Nidoqueen' + '11 Cubone' + '12 Ryhorn' + '13 Lapras' + '14 Arcanine' + '15 Mew' + '16 Gyrados' + '17 Shellder' + '18 Tentacool' + '19 Gastly' + '1A Scyther' + '1B Staryu' + '1C Blastoice' + '1D Pinser' + '1E Tangala' + '1F **Bad Pokemon**' + '20 **Bad Pokemon**' + '21 Growlithe' + '22 Onix' + '23 Fearow' + '24 Pidgey' + '25 Slowpoke' + '26 Kadabra' + '27 Graveler' + '28 Chansey' + '29 Machoke' + '2A Mr. Mime' + '2B Hitmonlee' + '2C Hitmonchan' + '2D Arbok' + '2E Parasect' + '2F Psyduck' + '30 Drowzee' + '31 Golom' + '32 **Bad Pokemon**' + '33 Magmar' + '34 **Bad Pokemon**' + '35 Electabuzz' + '36 Magneton' + '37 Koffing' + '38 **Bad Pokemon**' + '39 Mankey' + '3A Seel' + '3B Digglett' + '3C Tarous' + '3D **Bad Pokemon**' + '3E **Bad Pokemon**' + '3F **Bad Pokemon**' + '40 FarFetche'#39'd' + '41 Venonat' + '42 Dragonite' + '43 **Bad Pokemon**' + '44 **Bad Pokemon**' + '45 **Bad Pokemon**' + '46 Doduo' + '47 Poliwag' + '48 Jynx' + '49 Moltres' + '4A Articuno' + '4B Zapdos' + '4C Ditto' + '4D Meowth' + '4E Krabby' + '4F **Bad Pokemon**' + '50 **Bad Pokemon**' + '51 **Bad Pokemon**' + '52 Vulpix' + '53 Ninetails' + '54 Pikachu' + '55 Raichu' + '56 **Bad Pokemon**' + '57 **Bad Pokemon**' + '58 Dratini' + '59 Dragonair' + '5A Kabuto' + '5B Kabutops' + '5C Horsea' + '5D Seadra' + '5E **Bad Pokemon**' + '5F **Bad Pokemon**' + '60 Sandshrew' + '61 Sandslash' + '62 Omanyte' + '63 Omaster' + '64 Jigglypuff' + '65 Wigglytuff' + '66 Eevee' + '67 Flareon' + '68 Jolteon' + '69 Vaporeon' + '6A Machop' + '6B Zubat' + '6C Ekans' + '6D Paras' + '6E Poliwhirl' + '6F Poliwrath' + '70 Weedle' + '71 Kakuna' + '72 Beedril' + '73 **Bad Pokemon**' + '74 Dodrio' + '75 Primeape' + '76 Dugtrio' + '77 Venomoth' + '78 Dewgong' + '79 **Bad Pokemon**' + '7A **Bad Pokemon**' + '7B Caterpie' + '7C Metapod' + '7D Butterfree' + '7E Machamp' + '7F **Bad Pokemon**' + '80 Golduck' + '81 Hypno' + '82 Golbat' + '83 Mewtwo' + '84 Snorlax' + '85 Magikarp' + '86 **Bad Pokemon**' + '87 **Bad Pokemon**' + '88 Muk' + '89 **Bad Pokemon**' + '8A Kingler' + '8B Cloyster' + '8C **Bad Pokemon**' + '8D Electrode' + '8E Clefable' + '8F Weezing' + '90 Persian' + '91 Marowak' + '92 **Bad Pokemon**' + '93 Haunter' + '94 Abra' + '95 Alakazzam' + '96 Pidgeotto' + '97 Pidgeot' + '98 Starmie' + '99 Bulbasaur' + '9A Venusaur' + '9B Tentacruel' + '9C **Bad Pokemon**' + '9D Goldeen' + '9E Seaking' + '9F **Bad Pokemon**' + 'A0 **Bad Pokemon**' + 'A1 **Bad Pokemon**' + 'A2 **Bad Pokemon**' + 'A3 Ponyta' + 'A4 Rapidash' + 'A5 Rattata' + 'A6 Ratticate' + 'A7 Nidorino' + 'A8 Nidorina' + 'A9 Geodude' + 'AA Porygon' + 'AB Areodactyl' + 'AC **Bad Pokemon**' + 'AD Magnemite' + 'AE **Bad Pokemon**' + 'AF **Bad Pokemon**' + 'B0 Charmander' + 'B1 Squirtle' + 'B2 Charmeleon' + 'B3 Wartortle' + 'B4 Charizard' + 'B5 **Bad Pokemon**' + 'B6 **Bad Pokemon**' + 'B7 **Bad Pokemon**' + 'B8 **Bad Pokemon**' + 'B9 Oddish' + 'BA Gloom' + 'BB Vileplume' + 'BC Bellsprout' + 'BD Weepinbell' + 'BE Victreebell') + end + end + object WaterLevelGroup: TGroupBox + Left = 200 + Top = 80 + Width = 169 + Height = 49 + Caption = 'Level' + TabOrder = 3 + object WaterPkmnLevel: TSpinEdit + Left = 8 + Top = 19 + Width = 153 + Height = 22 + Hint = 'Pok'#233'mon'#39's level' + Enabled = False + MaxValue = 255 + MinValue = 1 + TabOrder = 0 + Value = 1 + end + end + object WaterReplaceBtn: TButton + Left = 200 + Top = 136 + Width = 75 + Height = 25 + Caption = 'Replace' + Enabled = False + TabOrder = 4 + OnClick = WaterReplaceBtnClick + end + object WaterRateGroup: TGroupBox + Left = 16 + Top = 168 + Width = 169 + Height = 65 + Caption = 'Encounter Rate' + TabOrder = 5 + object Less2: TLabel + Left = 8 + Top = 48 + Width = 21 + Height = 13 + Caption = 'Less' + end + object More2: TLabel + Left = 136 + Top = 48 + Width = 24 + Height = 13 + Caption = 'More' + end + object WaterPercent: TLabel + Left = 57 + Top = 48 + Width = 56 + Height = 13 + Alignment = taCenter + AutoSize = False + Caption = '%' + end + object WaterRateTrack: TTrackBar + Left = 8 + Top = 16 + Width = 153 + Height = 33 + Enabled = False + Max = 100 + Min = 1 + Frequency = 10 + Position = 1 + TabOrder = 0 + OnExit = WaterRateTrackExit + end + end + end + end + object TabSheet4: TTabSheet + Caption = 'Headers' + ImageIndex = 3 + end + end + object StatusBar1: TStatusBar + Left = 0 + Top = 621 + Width = 639 + Height = 20 + Panels = < + item + Text = 'Ready.' + Width = 200 + end + item + Text = 'Start by opening a rom file from File->Open...' + Width = 50 + end> + end + object MapSelectPanel: TPanel + Left = 0 + Top = 0 + Width = 639 + Height = 33 + Align = alTop + BevelOuter = bvNone + TabOrder = 2 + Visible = False + object Label5: TLabel + Left = 8 + Top = 8 + Width = 56 + Height = 13 + Caption = 'Select Map:' + end + object MapSelectCombo: TComboBox + Left = 72 + Top = 4 + Width = 233 + Height = 21 + Style = csDropDownList + ItemHeight = 13 + TabOrder = 0 + OnChange = MapSelectComboChange + Items.Strings = ( + 'Pallet Town' + 'Viridian City' + 'Pewter City' + 'Cerulean City' + 'Lavender Town' + 'Vermilion City' + 'Celadon City' + 'Fuchsia City' + 'Cinnibar Island' + 'Indigo Plateau' + 'Saffron City' + '** Bad Map **' + 'Route 1' + 'Route 2' + 'Route 3' + 'Route 4' + 'Route 5' + 'Route 6' + 'Route 7' + 'Route 8' + 'Route 9' + 'Route 10' + 'Route 11' + 'Route 12' + 'Route 13' + 'Route 14' + 'Route 15' + 'Route 16' + 'Route 17' + 'Route 18' + 'Route 19' + 'Route 20' + 'Route 21' + 'Route 22' + 'Route 23' + 'Route 24' + 'Route 25' + 'Ash'#39's House F1' + 'Ash'#39's House F2' + 'Gary'#39's House' + 'Oak'#39's Lab' + 'Viridian Pok'#233'mon Center' + 'Viridian Mart' + 'Viridian School' + 'Viridian House' + 'Viridian Gym' + 'Digletts Cave (Route 2)' + 'Viridian Forest (Exit)' + 'Route 2 House' + 'Route 2 Gate' + 'Viridian Forest (Entrance)' + 'Viridian Forest' + 'Pewter City Museum F1' + 'Pewter City Museum F2' + 'Pewter City Gym' + 'Pewter City House' + 'Pewter City Mart' + 'Pewter City House' + 'Pewter City Pok'#233'mon Center' + 'Mt. Moon Cave (1)' + 'Mt. Moon Cave (2)' + 'Mt. Moon Cave (3)' + 'Cerulean House (Robbed)' + 'Cerulean House (2)' + 'Cerulean Pok'#233'mon Center' + 'Cerulean Gym' + 'Cerulean Bike Shop' + 'Cerulean Mart' + 'Mt. Moon Pok'#233'mon Center' + 'Cerulean House (Robbed) (Copy)' + 'Route 5 Gate' + 'Underground Tunnel Entrance (Route 5)' + 'Day Care Center' + 'Route 6 Gate' + 'Underground Tunnel Entrance (Route 6)' + 'Underground Tunnel Entrance (Route 6) (Copy)' + 'Route 7 Gate' + 'Underground Path Entrance (Route 7)' + 'Underground Path Entrance (Route 7) (Copy)' + 'Route 8 Gate' + 'Underground Path Entrance (Route 8)' + 'Rock Tunnel Pok'#233'mon Center' + 'Rock Tunnel (1)' + 'Power Plant' + 'Route 11 Gate' + 'Diglett'#39's Cave Entrance (Route 11)' + 'Route 11 Gate (Upstairs)' + 'Route 12 Gate' + 'Bill'#39's House' + 'Vermilion Pok'#233'mon Center' + 'Vermilion Pok'#233'mon Fan Club' + 'Vermilion Mart' + 'Vermilion Gym' + 'Vermilion House' + 'Vermilion Dock' + 'S.S. Anne (1)' + 'S.S. Anne (2)' + 'S.S. Anne (3)' + 'S.S. Anne (4)' + 'S.S. Anne (5)' + 'S.S. Anne (6)' + 'S.S. Anne (7)' + 'S.S. Anne (8)' + 'S.S. Anne (9)' + 'S.S. Anne (10)' + '** Bad Map **' + '** Bad Map **' + '** Bad Map **' + 'Victory Road (1)' + '** Bad Map **' + '** Bad Map **' + '** Bad Map **' + '** Bad Map **' + 'Elite Four Lance' + '** Bad Map **' + '** Bad Map **' + '** Bad Map **' + '** Bad Map **' + 'Hall of Fame Room' + 'Underground Path (N/S)' + 'Elite Four Gary' + 'Underground Path (W/E)' + 'Celadon Mart (1)' + 'Celadon Mart (2)' + 'Celadon Mart (3)' + 'Celadon Mart (4)' + 'Celadon Mart (6)' + 'Celadon Mart Elevator' + 'Celadon Mansion (1)' + 'Celadon Mansion (2)' + 'Celadon Mansion (3)' + 'Celadon Mansion (4)' + 'Celadon Mansion (5)' + 'Celadon Pokecenter' + 'Celadon Gym' + 'Celadon Game Corner' + 'Celadon Mart (5)' + 'Celadon Prize Room' + 'Celadon Diner' + 'Celadon House (2)' + 'Celadon Hotel' + 'Lavender Pokecenter' + 'Pokemon Tower (1)' + 'Pokemon Tower (2)' + 'Pokemon Tower (3)' + 'Pokemon Tower (4)' + 'Pokemon Tower (5)' + 'Pokemon Tower (6)' + 'Pokemon Tower (7)' + 'Lavender House (1)' + 'Lavender Mart' + 'Lavender House (2)' + 'Fuchsia Mart' + 'Fuchsia House (1)' + 'Fuchsia Pokecenter' + 'Fuchsia House (2)' + 'Safari Zone Entrance' + 'Fuchsia Gym' + 'Fuchsia Meeting Room' + 'Seafoam Islands (2)' + 'Seafoam Islands (3)' + 'Seafoam Islands (4)' + 'Seafoam Islands (5)' + 'Vermilion House (2)' + 'Fuchsia House (3)' + 'Mansion (1)' + 'Cinnibar Gym' + 'Lab (1)' + 'Lab (2)' + 'Lab (3)' + 'Lab (4)' + 'Cinnibar Pokecenter' + 'Cinnibar Mart' + 'Cinnibar Mart (Copy)' + 'Indigo Plateau Lobby' + 'Copycat'#39's House F1 ' + 'Copycat'#39's House F2' + 'Fighting Dojo' + 'Saffron Gym' + 'Saffron House (1)' + 'Saffron Mart' + 'Silph Co (1)' + 'Saffron Pokecenter' + 'Saffron House (2)' + 'Route 15 Gate' + 'Route 15 Gate Upstairs' + 'Route 16 Gate Map' + 'Route 16 Gate Upstairs' + 'Route 16 House' + 'Route 12 House' + 'Route 18 Gate' + 'Route 18 Gate Upstairs' + 'Seafoam Islands (1)' + 'Route 22 Gate' + 'Victory Road' + 'Route 12 Gate Upstairs' + 'Vermilion House (3)' + 'Diglett'#39's Cave' + 'Victory Road (3)' + 'Rocket Hideout (1)' + 'Rocket Hideout (2)' + 'Rocket Hideout (3)' + 'Rocket Hideout (4)' + 'Rocket Hideout (Elevator)' + '** Bad Map **' + '** Bad Map **' + '** Bad Map **' + 'Silph Co (2)' + 'Silph Co (3)' + 'Silph Co (4)' + 'Silph Co (5)' + 'Silph Co (6)' + 'Silph Co (7)' + 'Silph Co (8)' + 'Mansion (2)' + 'Mansion (3)' + 'Mansion (4)' + 'Safari Zone East' + 'Safari Zone North' + 'Safari Zone West' + 'Safari Zone Center' + 'Safari Zone Rest House (1)' + 'Safari Zone Secret House' + 'Safari Zone Rest House (2)' + 'Safari Zone Rest House (3)' + 'Safari Zone Rest House (4)' + 'Unknown Dungeon(2)' + 'Unknown Dungeon(3)' + 'Unknown Dungeon(1)' + 'Name Rater'#39's House' + 'Cerulean House (3)' + '** Bad Map **' + 'Rock Tunnel (2)' + 'Silph Co (9)' + 'Silph Co (10)' + 'Silph Co (11)' + 'Silph Co (Elevator)' + '** Bad Map **' + '** Bad Map **' + 'Battle Center' + 'Trade Center' + '** Bad Map **' + '** Bad Map **' + '** Bad Map **' + '** Bad Map **' + 'Elite Four Loreli' + 'Elite Four Bruno' + 'Elite Four Agatha' + 'Surf House (Yellow)' + '** Bad Map **' + '** Bad Map **' + '** Bad Map **' + '** Bad Map **' + '** Bad Map **' + '** Bad Map **') + end + end + object XPManifest1: TXPManifest + Left = 600 + Top = 584 + end + object MainMenu1: TMainMenu + Left = 568 + Top = 584 + object File1: TMenuItem + Caption = 'File' + object LoadRom1: TMenuItem + Caption = 'Open...' + Hint = 'Open a rom file to be edited.' + ShortCut = 16463 + OnClick = LoadRom1Click + end + object SaveRom1: TMenuItem + Caption = 'Save' + Enabled = False + Hint = 'Saves the currently opened rom to file.' + ShortCut = 16467 + OnClick = SaveRom1Click + end + object SaveRomAs1: TMenuItem + Caption = 'Save As...' + Enabled = False + Hint = 'Saves the currently opened rom to different file.' + end + object N1: TMenuItem + Caption = '-' + end + object LoadMap1: TMenuItem + Caption = 'Load Map...' + Hint = 'Loads map from file.' + end + object SaveMap1: TMenuItem + Caption = 'Save Map...' + Hint = 'Saves current map to file.' + end + object N2: TMenuItem + Caption = '-' + end + object Exit1: TMenuItem + Caption = 'Exit' + Hint = 'Bye-bye!' + OnClick = Exit1Click + end + end + object Edit1: TMenuItem + Caption = 'Edit' + object Undo1: TMenuItem + Caption = 'Undo' + ShortCut = 16474 + end + end + object Settings1: TMenuItem + Caption = 'Settings' + object Grid1: TMenuItem + Caption = 'Gridlines' + Hint = 'Show the gridlines in map editor, events and block palette.' + ShortCut = 16455 + OnClick = Grid1Click + end + object N4: TMenuItem + Caption = '-' + end + object Palette1: TMenuItem + Caption = 'Palette' + Hint = 'Change the color scheme GoldMap uses to display map.' + object Morning1: TMenuItem + Caption = 'Morning' + GroupIndex = 2 + RadioItem = True + end + object Day1: TMenuItem + Tag = 1 + Caption = 'Day' + Checked = True + GroupIndex = 2 + RadioItem = True + end + object Night1: TMenuItem + Tag = 2 + Caption = 'Night' + GroupIndex = 2 + RadioItem = True + end + object Darkness1: TMenuItem + Tag = 3 + Caption = 'Darkness' + GroupIndex = 2 + RadioItem = True + end + object Indoor1: TMenuItem + Tag = 4 + Caption = 'Indoor' + GroupIndex = 2 + RadioItem = True + end + end + end + object Tools: TMenuItem + Caption = 'Tools' + object BlockEditor1: TMenuItem + Caption = 'Block Editor...' + Enabled = False + Hint = 'Edit map building blocks.' + ShortCut = 16450 + OnClick = BlockEditor1Click + end + object ReconstructMap1: TMenuItem + Caption = 'Resize Map...' + Enabled = False + Hint = 'Change size of map, and relocate map data in rom.' + ShortCut = 16466 + end + object ReBuildEvents1: TMenuItem + Caption = 'Reconstruct Events...' + Enabled = False + Hint = 'Change number of events.' + ShortCut = 16453 + end + object N3: TMenuItem + Caption = '-' + end + object SaveMapPic1: TMenuItem + Caption = 'Save Picture of Map...' + Enabled = False + Hint = 'Save picture of map into file.' + ShortCut = 49229 + end + object SaveTilesetPic1: TMenuItem + Caption = 'Save Picture of Blocks...' + Enabled = False + Hint = 'Save picture of map building blocks into file.' + ShortCut = 49218 + end + object TryMap1: TMenuItem + Caption = 'Try Map...' + Enabled = False + Hint = + 'Allows you to manually specify map size and address to load it f' + + 'rom.' + ShortCut = 16468 + end + end + object Help1: TMenuItem + Caption = 'Help' + object About1: TMenuItem + Caption = 'About...' + Hint = 'About GoldMap.' + ShortCut = 112 + OnClick = About1Click + end + end + end + object SaveMapDialog: TSaveDialog + DefaultExt = 'map' + Filter = 'Maps (*.map)|*.map|All Files (*.*)|*.*' + Left = 536 + Top = 584 + end + object OpenRomDialog: TOpenDialog + Filter = 'GameBoy roms (*.gb),(*.gbc)|*.gb;*.gbc|Any file (*.*)|*.*' + Title = 'Select Pok'#233'mon Gold or Silver rom' + Left = 504 + Top = 552 + end + object SaveRomDialog: TSaveDialog + DefaultExt = 'gb' + Filter = 'GameBoy roms (*.GB),(*.GBC)|*.GB;*.GBC|All files (*.*)|*.*' + Title = 'Save rom' + Left = 536 + Top = 552 + end + object OpenMapDialog: TOpenDialog + DefaultExt = 'map' + Filter = 'Maps (*.map)|*.map|All Files (*.*)|*.*' + Left = 504 + Top = 584 + end + object ImageList1: TImageList + Left = 568 + Top = 552 + Bitmap = { + 494C010102000400040010001000FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600 + 0000000000003600000028000000400000001000000001002000000000000010 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00000000000000000000000000000000000000000000000000007F7F7F007F7F + 7F007F7F7F007F7F7F007F7F7F007F7F7F007F7F7F007F7F7F007F7F7F007F7F + 7F007F7F7F007F7F7F007F7F7F007F7F7F000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000038383800383838003838 + 3800383838003838380038383800383838003838380038383800383838003838 + 38003838380038383800383838007F7F7F000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000007F7F7F007F7F7F007F7F7F007F7F7F007F7F7F007F7F7F007F7F + 7F007F7F7F000000000000000000000000000000000038383800D0E0F000D0E0 + F000D0E0F000D0E0F000D0E0F000D0E0F000D0E0F000D0E0F000D0E0F000D0E0 + F000D0E0F000D0E0F000383838007F7F7F000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00007F7F7F000000000000000000000000000000000038383800D0E0F000F848 + 4800F8484800F8484800F8484800F8484800F8484800F8484800F8484800F848 + 4800F8484800D0E0F000383838007F7F7F000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000078F8000078F8000078F8000078F8000078F8000078F8000000 + 00007F7F7F000000000000000000000000000000000038383800D0E0F000F848 + 4800F8807800F8807800F8807800F8807800F8807800F8807800F8807800F880 + 7800F8484800D0E0F000383838007F7F7F000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000078F800003878000038780000387800003878000078F8000000 + 00007F7F7F000000000000000000000000000000000038383800D0E0F000F848 + 4800F8484800F8484800F8807800F8807800F8807800F8807800F8807800F880 + 7800F8484800D0E0F000383838007F7F7F000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000078F800003878000078F8000078F800003878000078F8000000 + 00007F7F7F000000000000000000000000000000000038383800D0E0F000F848 + 4800F8484800F8484800F8484800F8807800F8807800F8807800F8807800F848 + 4800F8484800D0E0F000383838007F7F7F000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000078F800003878000078F8000078F800003878000078F8000000 + 00007F7F7F000000000000000000000000000000000038383800D0E0F000F848 + 4800F8484800F8484800F8484800F8484800F8807800F8807800F8484800F848 + 4800F8484800D0E0F000383838007F7F7F000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000078F800003878000038780000387800003878000078F8000000 + 00007F7F7F000000000000000000000000000000000038383800D0E0F000F848 + 4800F8807800F8807800F8484800F8484800F8484800F8484800F8484800F848 + 4800F8484800D0E0F000383838007F7F7F000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000078F8000078F8000078F8000078F8000078F8000078F8000000 + 00007F7F7F000000000000000000000000000000000038383800D0E0F000F848 + 4800F8807800F8807800F8484800F8484800F8484800F8484800F8484800F848 + 4800F8484800D0E0F000383838007F7F7F000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000038383800D0E0F000F848 + 4800F8484800F8484800F8484800F8484800F8484800F8484800F8484800F848 + 4800F8484800D0E0F000383838007F7F7F000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000038383800D0E0F000D0E0 + F000D0E0F000D0E0F000D0E0F000D0E0F000D0E0F000D0E0F000D0E0F000D0E0 + F000D0E0F000D0E0F000383838007F7F7F000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000038383800383838003838 + 3800383838003838380038383800383838003838380038383800383838003838 + 3800383838003838380038383800000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000424D3E000000000000003E000000 + 2800000040000000100000000100010000000000800000000000000000000000 + 000000000000000000000000FFFFFF000180FFFF000000000180C00000000000 + 3FFC800000000000380480000000000030048000000000003004800000000000 + 3004800000000000F007800000000000F0078000000000003004800000000000 + 3004800000000000300C8000000000003FFC8000000000003FFC800100000000 + 0180FFFF000000000180FFFF0000000000000000000000000000000000000000 + 000000000000} + end +end diff --git a/MapEditor.pas b/MapEditor.pas new file mode 100644 index 0000000..0e7cc65 --- /dev/null +++ b/MapEditor.pas @@ -0,0 +1,1151 @@ +unit MapEditor; + +interface + +uses + Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, + Dialogs, ExtCtrls, Menus, XPMan, IniFiles, StdCtrls, Spin, ImgList, ComCtrls, + pngimage, Map, Tileset, About, Misc, BlockEditor; + +type + + TPointer = packed record + First: Byte; + Second: Byte; + end; + + TPokemon = packed record + Level: Byte; + Number: Byte; + end; + + TLandWildPkmn = packed record + Rate: Byte; + Pkmn: array [0..9] of TPokemon; + end; + + TWaterWildPkmn = packed record + Rate: Byte; + Pkmn: array [0..9] of TPokemon; + end; + + TMapEditorForm = class(TForm) + XPManifest1: TXPManifest; + MainMenu1: TMainMenu; + File1: TMenuItem; + LoadRom1: TMenuItem; + SaveRom1: TMenuItem; + SaveRomAs1: TMenuItem; + N1: TMenuItem; + LoadMap1: TMenuItem; + SaveMap1: TMenuItem; + N2: TMenuItem; + Exit1: TMenuItem; + Settings1: TMenuItem; + Grid1: TMenuItem; + N4: TMenuItem; + Palette1: TMenuItem; + Morning1: TMenuItem; + Day1: TMenuItem; + Night1: TMenuItem; + Darkness1: TMenuItem; + Indoor1: TMenuItem; + Tools: TMenuItem; + BlockEditor1: TMenuItem; + ReconstructMap1: TMenuItem; + ReBuildEvents1: TMenuItem; + N3: TMenuItem; + SaveMapPic1: TMenuItem; + SaveTilesetPic1: TMenuItem; + TryMap1: TMenuItem; + Help1: TMenuItem; + About1: TMenuItem; + SaveMapDialog: TSaveDialog; + OpenRomDialog: TOpenDialog; + SaveRomDialog: TSaveDialog; + OpenMapDialog: TOpenDialog; + PageControl1: TPageControl; + TabSheet1: TTabSheet; + MapScrollBox: TScrollBox; + MapBox: TPaintBox; + BlockPaletteScrollBox: TScrollBox; + BlockPalette: TPaintBox; + TabSheet2: TTabSheet; + NoEventsLabel: TLabel; + EventScrollBox: TScrollBox; + SignpostImage: TImage; + PeopleImage: TImage; + WarpImage: TImage; + EventBox: TPaintBox; + TriggerImage: TImage; + TabSheet3: TTabSheet; + NoWildPkmnLabel: TLabel; + LandGroup1: TGroupBox; + LandPkmnLevel: TSpinEdit; + LandPkmnBox: TListBox; + LandPkmnCombo: TComboBox; + StatusBar1: TStatusBar; + ImageList1: TImageList; + MapSelectPanel: TPanel; + MapSelectCombo: TComboBox; + Label5: TLabel; + shpHighlight: TShape; + TabSheet4: TTabSheet; + Edit1: TMenuItem; + Undo1: TMenuItem; + LandLevelBox: TListBox; + LandPkmnGroup: TGroupBox; + LandLevelGroup: TGroupBox; + LandReplaceBtn: TButton; + WaterGroup1: TGroupBox; + WaterPkmnBox: TListBox; + WaterLevelBox: TListBox; + WaterPkmnGroup: TGroupBox; + WaterPkmnCombo: TComboBox; + WaterLevelGroup: TGroupBox; + WaterPkmnLevel: TSpinEdit; + WaterReplaceBtn: TButton; + LandRateTrack: TTrackBar; + LandRateGroup: TGroupBox; + Less1: TLabel; + More1: TLabel; + LandPercent: TLabel; + WaterRateGroup: TGroupBox; + Less2: TLabel; + More2: TLabel; + WaterPercent: TLabel; + WaterRateTrack: TTrackBar; + OffsetLabel1: TLabel; + LandOffset1: TLabel; + OffsetLabel2: TLabel; + WaterOffset1: TLabel; + procedure BlockEditor1Click(Sender: TObject); + procedure Grid1Click(Sender: TObject); + procedure About1Click(Sender: TObject); + procedure BlockPaletteMouseMove(Sender: TObject; Shift: TShiftState; X, + Y: Integer); + procedure BlockPaletteMouseDown(Sender: TObject; Button: TMouseButton; + Shift: TShiftState; X, Y: Integer); + procedure MapBoxMouseUp(Sender: TObject; Button: TMouseButton; + Shift: TShiftState; X, Y: Integer); + procedure MapBoxMouseMove(Sender: TObject; Shift: TShiftState; X, + Y: Integer); + procedure MapBoxMouseDown(Sender: TObject; Button: TMouseButton; + Shift: TShiftState; X, Y: Integer); + procedure MapSelectComboChange(Sender: TObject); + procedure MapBoxPaint(Sender: TObject); + procedure BlockPalettePaint(Sender: TObject); + procedure TilesetComboDrawItem(Control: TWinControl; Index: Integer; + Rect: TRect; State: TOwnerDrawState); + procedure SpinEdit1Change(Sender: TObject); + procedure FormCreate(Sender: TObject); + procedure LoadRom1Click(Sender: TObject); + + + //saves currently open map, event and pokemon data to rom (in memory) and writes to file + procedure SaveRom(FileName: string); + + //loads specified map, tileset for map, map's events and pokemon + procedure LoadMap(MapIndex: byte); + //loads specified tileset + procedure LoadTileset(TilesetNumber: Byte); + //loads wild pokemon data for specified map + procedure LoadPokemon(MapIndex: Byte); + + //saves currently loaded map, map's events and pokemon + procedure SaveMap; + //draws tileset blocks from MapData into Canvas + procedure DrawMap(Canvas: TCanvas); + //draws the tileset blocks on Canvas + procedure DrawBlocks(Canvas: TCanvas); + //refreshes the wild pokemon data controls in Wild Pokemon tab + procedure UpdatePokemon; + procedure SavePokemon; + + function IsOutsideOfMapBounds(X, Y: Integer): Boolean; + procedure Exit1Click(Sender: TObject); + procedure SaveRom1Click(Sender: TObject); + procedure LandReplaceBtnClick(Sender: TObject); + procedure WaterReplaceBtnClick(Sender: TObject); + procedure LandPkmnBoxClick(Sender: TObject); + procedure WaterPkmnBoxClick(Sender: TObject); + procedure WaterRateTrackExit(Sender: TObject); + procedure LandRateTrackExit(Sender: TObject); + + private + { Private declarations } + public + { Public declarations } + end; + +var + MapEditorForm: TMapEditorForm; + LoadedTileset: Byte = 0; + LoadedMap: string = ''; + LoadedMapBank: Byte; + LoadedMapNum: Byte; + SelBlock, SelPic, MapStart, TilesetStart, PokemonStart, Blocks: Integer; + LoadedMapHeader: TMapHeader; + Rom: TMemoryStream = nil; + MapData: array of Byte; + BlockPics: array [0..255] of TBitmap; + Painting,DraggingEvent: Boolean; + Tiles: TBitmap; + MapModified: boolean; + RomModified: boolean; + DragOldX,DragOldY: Integer; + TilesetCache: array [0..23] of TBitmap; + ConnectionData: array [$00..$03] of TConnectionData; + ConnectedMapHeaders: array [$00..$03] of TMapHeader; + TopMapData: array of Byte; + BottomMapData: array of Byte; + LeftMapData: array of Byte; + RightMapData: array of Byte; + Pointer: TPointer; + LandWildPkmn: TLandWildPkmn; + WaterWildPkmn: TWaterWildPkmn; + Location: string; + +implementation + +{$R *.dfm} + +procedure TMapEditorForm.FormCreate(Sender: TObject); +begin + ControlStyle := ControlStyle + [csOpaque]; + MapScrollBox.ControlStyle := MapScrollBox.ControlStyle + [csOpaque]; + MapBox.ControlStyle := MapBox.ControlStyle + [csOpaque]; + + // Create the tileset graphic + Tiles := TBitmap.Create; + Tiles.Width := 16*16; + Tiles.Height := 16*6; + Tiles.PixelFormat := pf24bit; + + // Import for drawing grid. + MapBox.Canvas.Brush.Style := bsClear; + EventBox.Canvas.Brush.Style := bsClear; + BlockPalette.Canvas.Brush.Style := bsClear; +end; + +procedure TMapEditorForm.Grid1Click(Sender: TObject); +begin + //if grid is checked then it will be hidden + if Grid1.Checked then + Grid1.Checked := False + else + //if grid is unchecked then it will be shown + Grid1.Checked := True; + //PokemonIni.WriteBool('Settings','Grid',Grid1.Checked); + //show the grid if needed + if MapStart > 0 then + begin + DrawMap(MapBox.Canvas); + //DrawEvents(MainForm.EventBox.Canvas); + DrawBlocks(BlockPalette.Canvas); + end; +end; + +procedure TMapEditorForm.LoadRom1Click(Sender: TObject); +var + I: Integer; +begin + if OpenRomDialog.Execute then + begin + // Check if memory stream is null. + if Rom = nil then + Rom := TMemoryStream.Create; + + // Load TMemoryStream from file. + Rom.LoadFromFile(OpenRomDialog.FileName); + + ReadMapPallets; + + // Load up tileset combos. + for I := 0 to 23 do + begin + TilesetCache[I] := TBitmap.Create; + TilesetCache[I].Width := 128; + TilesetCache[I].Height := 48; + TilesetCache[I].PixelFormat := pf24bit; + ReadTilesetGraphics(GetTilesetHeader(I), TilesetCache[I]); + end; + + MapModified := False; + RomModified := False; + BlockEditor1.Enabled := False; + ReBuildEvents1.Enabled := False; + ReconstructMap1.Enabled := False; + SaveRom1.Enabled := True; + SaveRomAs1.Enabled := True; + //ReadAreaNames; + //ScanMapHeaders; + ReadMapHeaderLocations; + MapSelectPanel.Show; + StatusBar1.Panels[1].Text := 'ROM Loaded...'; + //LoadMap(0); + MapSelectCombo.ItemIndex := 0; + MapSelectComboChange(Sender); + end; +end; + +procedure TMapEditorForm.SpinEdit1Change(Sender: TObject); +begin + //ReadTilesetGraphics(GetTilesetHeader(SpinEdit1.Value), Tiles); + //TilePalette.Picture.Graphic := Tiles; +end; + +procedure TMapEditorForm.TilesetComboDrawItem(Control: TWinControl; + Index: Integer; Rect: TRect; State: TOwnerDrawState); +begin + with TComboBox(Control).Canvas do + begin + FillRect(Rect); + TextOut(Rect.Left,Rect.Top,'Tileset ' + IntToStr(Index) + ':'); + Draw((Rect.Right - Rect.Left) div 2 - 64, Rect.Top + 13, TilesetCache[Index]); + end; +end; + +procedure TMapEditorForm.LoadTileset(TilesetNumber: Byte); +label LoadingDone; +var + X, Y, Block, TileX, TileY: Integer; + TileNumber: Byte; + Temp: TBitmap; + TilesetHdr: TTilesetHeader; +begin + //if the tileset needed is already loaded, just exit + //if LoadedTileset = TilesetNumber then Exit; + + TilesetHdr := GetTilesetHeader(TilesetNumber); + TilesetStart := GBPtrToFilePos(TilesetHdr.BankNumber,TilesetHdr.TilesetArrangementPointer); + + if (TilesetStart = 0) or (GBPtrToFilePos(TilesetHdr.BankNumber,TilesetHdr.TilesetGraphicsPointer) = 0) then + begin + MessageDlg('Tileset information in rom seem to be corrupted. Loading will be cancelled.',mtError,[mbOK],0); + Abort; + end; + + Temp := TBitmap.Create; + Temp.Width := 16*16; + Temp.Height := 16*6; + Temp.PixelFormat := pf24bit; + + //Temp.LoadFromFile(ExtractFilePath(Application.ExeName) + 'Tileset' + IntToStr(TilesetNumber) + '.dib'); + ReadTilesetGraphics(GetTilesetHeader(TilesetNumber),Temp); + Tiles.Canvas.StretchDraw(Tiles.Canvas.ClipRect,Temp); + + //start loading + StatusBar1.Panels[0].Text := 'Loading Tileset ' + IntToStr(TilesetNumber) + ' please wait...'; + + //start reading the block data from rom & rendering the tiles + Rom.Position := TilesetStart; + Blocks := 255; + for Block := 0 to 255 do + begin + for Y := 0 to 3 do + for X := 0 to 3 do + begin + Rom.Read(TileNumber,1); + //create bitmap for block if not already existing + if BlockPics[Block] = nil then + begin + BlockPics[Block] := TBitmap.Create; + BlockPics[Block].Width := 32; + BlockPics[Block].Height := 32; + BlockPics[Block].PixelFormat := pf24bit; + end; + //calculate x and y coordinate where to copy tile from, the tileset picture has 16 tiles per line + TileY := TileNumber div 16; + TileX := TileNumber mod 16; + //draw tile to block picture + BlockPics[Block].Canvas.CopyRect(Rect(X*8,Y*8,X*8+8,Y*8+8),Tiles.Canvas,Rect(TileX*8,TileY*8,TileX*8+8,TileY*8+8)); + end; + end; + + BlockPalette.Height := 32 * Blocks; + BlockPaletteScrollBox.Show; + SelBlock := 1; + LoadedTileset := TilesetNumber; + + //updates blocks because tileset is changed + DrawBlocks(BlockPalette.Canvas); + + //enable editing blocks + BlockEditor1.Enabled := True; + StatusBar1.Panels[0].Text := 'Tileset ' + inttostr(TilesetNumber) + ' loaded.'; +end; + +procedure TMapEditorForm.About1Click(Sender: TObject); +begin + with TAboutDialog.Create(nil) do + begin + ShowModal; + Free; + end; +end; + +procedure TMapEditorForm.BlockEditor1Click(Sender: TObject); +begin + with TBlockEditorForm.Create(nil) do + begin + ShowModal; + Free; + end; +end; + +procedure TMapEditorForm.BlockPaletteMouseDown(Sender: TObject; + Button: TMouseButton; Shift: TShiftState; X, Y: Integer); +begin + SelBlock := (Y div 32); +end; + +procedure TMapEditorForm.BlockPaletteMouseMove(Sender: TObject; + Shift: TShiftState; X, Y: Integer); +begin + StatusBar1.Panels[0].Text := 'Block: $' + IntToHex(Y div 32 , 2) + ' Offset: $' + IntToHex(TilesetStart + ((Y div 32) * 16),0); +end; + +procedure TMapEditorForm.BlockPalettePaint(Sender: TObject); +begin + DrawBlocks(BlockPalette.Canvas); +end; + +procedure TMapEditorForm.DrawBlocks(Canvas: TCanvas); +var +I: Integer; +begin + Canvas.Brush.Style := bsClear; + //go through the block pictures and draw then on BlockPalette + for I := 0 to Blocks -1 do + begin + Canvas.Draw(0, I * 32, BlockPics[I]); + if Grid1.Checked then + Canvas.Rectangle(0, I * 32, 32 + 32, I * 32 + 32); + end; + //allow saving tileset picture + SaveTilesetPic1.Enabled := True; +end; + +procedure TMapEditorForm.DrawMap(Canvas: TCanvas); +var + X, Y: Integer; + MaxX, MaxY: Integer; + StartTileConnect, StartWriteConnect: Integer; + StartHeightWidthDifference: Integer; + StartX, StartY, EndX, EndY: Integer; + +begin + Canvas.Brush.Style := bsClear; + + MaxX := Canvas.ClipRect.Right div 32; + MaxY := Canvas.ClipRect.Bottom div 32; + + if MaxX >= LoadedMapHeader.Width then MaxX := LoadedMapHeader.Width-1; + if MaxY >= LoadedMapHeader.Height then MaxY := LoadedMapHeader.Height-1; + + for X := Canvas.ClipRect.Left div 32 to MaxX + 6 do + for Y := Canvas.ClipRect.Top div 32 to MaxY + 6 do + begin + if (X >= 3) and (Y >= 3) and (X <= MaxX + 3) and (Y <= MaxY + 3) then + begin + if (MapData[(Y-3) * LoadedMapHeader.Width + (X-3)] <= Blocks) then + Canvas.Draw(X * 32, Y * 32, BlockPics[MapData[(Y-3) * LoadedMapHeader.Width + (X-3)]]) + else + begin + // Invalid blocks detected + Canvas.Brush.Style := bsSolid; + Canvas.Rectangle(X * 32, Y * 32, X * 32 + 32, Y * 32 + 32); + Canvas.Brush.Style := bsClear; + end; + end + else + begin + Canvas.Draw(X * 32, Y * 32, BlockPics[LoadedMapHeader.BorderBlock]); + + // Top + if (LoadedMapHeader.ConnectionDataControl and $08) = $08 then + begin + StartTileConnect := (LoadedMapHeader.ConnectionData[0].MapDataPointer - $4000) - (ConnectedMapHeaders[0].DataPointer - $4000); + StartWriteConnect := LoadedMapHeader.ConnectionData[0].MapLocationRamPointer - $C6E8; + StartX := StartWriteConnect; + StartY := 0; + EndX := (LoadedMapHeader.ConnectionData[0].WidthHeightVisiblePart - 1) + StartWriteConnect; + EndY := StartY + 3; + + if (X >= StartX) and (Y >= StartY) and (X <= EndX) and (Y < EndY) then + begin + StartHeightWidthDifference := ConnectedMapHeaders[0].Width - LoadedMapHeader.ConnectionData[0].WidthHeightVisiblePart; + Canvas.Draw(X * 32, Y * 32, BlockPics[TopMapData[StartTileConnect + (Y * StartHeightWidthDifference) + (Y * LoadedMapHeader.ConnectionData[0].WidthHeightVisiblePart + (X - StartWriteConnect))]]); + end; + end; + + // Bottom + if (LoadedMapHeader.ConnectionDataControl and $04) = $04 then + begin + StartTileConnect := (LoadedMapHeader.ConnectionData[1].MapDataPointer - $4000) - (ConnectedMapHeaders[1].DataPointer - $4000); + StartWriteConnect := LoadedMapHeader.ConnectionData[1].MapLocationRamPointer - $C6E8; + StartX := StartWriteConnect - ((LoadedMapHeader.Width + 6) * (LoadedMapHeader.Height + 3)); + StartY := StartWriteConnect div (LoadedMapHeader.Width + 6); + EndX := StartX + (LoadedMapHeader.ConnectionData[1].WidthHeightVisiblePart - 1); + EndY := StartY + 3; + + if (X >= StartX) and (Y >= StartY) and (X <= EndX) and (Y < EndY) then + begin + StartHeightWidthDifference := ConnectedMapHeaders[1].Width - LoadedMapHeader.ConnectionData[1].WidthHeightVisiblePart; + Canvas.Draw(X * 32, Y * 32, BlockPics[BottomMapData[StartTileConnect + ((Y - StartY) * StartHeightWidthDifference) + ((Y - StartY) * LoadedMapHeader.ConnectionData[1].WidthHeightVisiblePart + (X - StartX))]]); + end; + end; + + // Left + if (LoadedMapHeader.ConnectionDataControl and $02) = $02 then + begin + StartTileConnect := (LoadedMapHeader.ConnectionData[2].MapDataPointer - $4000) - (ConnectedMapHeaders[2].DataPointer - $4000); + StartWriteConnect := LoadedMapHeader.ConnectionData[2].MapLocationRamPointer - $C6E8; + StartX := 0; + StartY := StartWriteConnect div (LoadedMapHeader.Width + 6); + EndX := (StartX + 3) - 1; + EndY := StartY + LoadedMapHeader.ConnectionData[2].WidthHeightVisiblePart; + + if (X >= StartX) and (Y >= StartY) and (X <= EndX) and (Y < EndY) then + begin + StartHeightWidthDifference := ConnectedMapHeaders[2].Width - LoadedMapHeader.ConnectionData[2].WidthHeightVisiblePart; + Canvas.Draw(X * 32, Y * 32, BlockPics[LeftMapData[StartTileConnect + ((Y - StartY) * StartHeightWidthDifference) + ((Y - StartY) * LoadedMapHeader.ConnectionData[2].WidthHeightVisiblePart + (X - StartX))]]); + end; + end; + + // Right + if (LoadedMapHeader.ConnectionDataControl and $01) = $01 then + begin + StartTileConnect := (LoadedMapHeader.ConnectionData[3].MapDataPointer - $4000) - (ConnectedMapHeaders[3].DataPointer - $4000); + StartWriteConnect := LoadedMapHeader.ConnectionData[3].MapLocationRamPointer - $C6E8; + + StartX := LoadedMapHeader.Width+3; + StartY := StartWriteConnect div (LoadedMapHeader.Width + 6); + EndX := (StartX + 3) - 1; + EndY := StartY + LoadedMapHeader.ConnectionData[3].WidthHeightVisiblePart; + + if (X >= StartX) and (Y >= StartY) and (X <= EndX) and (Y < EndY) then + begin + StartHeightWidthDifference := ConnectedMapHeaders[3].Width - LoadedMapHeader.ConnectionData[3].WidthHeightVisiblePart; + Canvas.Draw(X * 32, Y * 32, BlockPics[RightMapData[StartTileConnect + ((Y - StartY) * StartHeightWidthDifference) + ((Y - StartY) * LoadedMapHeader.ConnectionData[3].WidthHeightVisiblePart + (X - StartX))]]); + end; + end; + + end; + if Grid1.Checked then + Canvas.Rectangle(X * 32, Y * 32, X * 32 + 32, Y * 32 + 32); + end; +end; + +procedure TMapEditorForm.LoadMap(MapIndex: byte); +var + TempMapHeader: TMapHeader; + TempMapStart: Integer; + TempMapIndex: Byte; +begin + + //first check if we need to save previously loaded map + if MapModified then + case MessageDlg('Save changes?',mtConfirmation,mbYesNoCancel,0) of + mrYes: SaveMap; + mrCancel: Abort; + end; + + LoadedMapHeader := GetMapHeader(MapIndex); + + if (LoadedMapHeader.Width * LoadedMapHeader.Height = 0) then + begin + MessageDlg('There seems be error in map header. Map will not be loaded.',mtWarning,[mbOK],0); + Abort; + end; + + DebugString('LoadMap', IntToStr(Map.BankLocations[MapIndex])); + + // load palettes + if (MapIndex >= 0) and (MapIndex <= 10) then + begin + Palette[0] := WordToColor(RawMapPalettes[MapIndex+1][0]); + Palette[1] := WordToColor(RawMapPalettes[MapIndex+1][1]); + Palette[2] := WordToColor(RawMapPalettes[MapIndex+1][2]); + Palette[3] := WordToColor(RawMapPalettes[MapIndex+1][3]); + end + else + begin + // default + Palette[0] := WordToColor(RawMapPalettes[0][0]); + Palette[1] := WordToColor(RawMapPalettes[0][1]); + Palette[2] := WordToColor(RawMapPalettes[0][2]); + Palette[3] := WordToColor(RawMapPalettes[0][3]); + end; + + // Load the tileset + LoadTileset(LoadedMapHeader.TilesetNumber); + + // Set the pointer to the map data + MapStart := GBPtrToFilePos(Map.BankLocations[MapIndex], LoadedMapHeader.DataPointer); + + // Make sure ROM is big enough + if Rom.Size - Rom.Position < LoadedMapHeader.Width * LoadedMapHeader.Height then + begin + MessageDlg('Map is too big to be read from file.', mtWarning, [mbOK], 0); + Abort; + end; + + // Resize the map, and read the map data. + SetLength(MapData, LoadedMapHeader.Width * LoadedMapHeader.Height); + //read map data to array + Rom.Position := MapStart; + Rom.Read(MapData[0], LoadedMapHeader.Width * LoadedMapHeader.Height); + + // Load Top connection data + if (LoadedMapHeader.ConnectionDataControl and $08) = $08 then + begin + TempMapIndex := LoadedMapHeader.ConnectionData[0].MapNumber; + TempMapHeader := GetMapHeader(TempMapIndex); + TempMapStart := GBPtrToFilePos(Map.BankLocations[TempMapIndex], + TempMapHeader.DataPointer); + ConnectedMapHeaders[0] := TempMapHeader; + SetLength(TopMapData, TempMapHeader.Width * TempMapHeader.Height); + Rom.Position := TempMapStart; + Rom.Read(TopMapData[0], TempMapHeader.Width * TempMapHeader.Height); + end; + + // Load Bottom connection data + if (LoadedMapHeader.ConnectionDataControl and $04) = $04 then + begin + TempMapIndex := LoadedMapHeader.ConnectionData[1].MapNumber; + TempMapHeader := GetMapHeader(TempMapIndex); + TempMapStart := GBPtrToFilePos(Map.BankLocations[TempMapIndex], + TempMapHeader.DataPointer); + ConnectedMapHeaders[1] := TempMapHeader; + SetLength(BottomMapData, TempMapHeader.Width * TempMapHeader.Height); + Rom.Position := TempMapStart; + Rom.Read(BottomMapData[0], TempMapHeader.Width * TempMapHeader.Height); + end; + + // Load Left connection data + if (LoadedMapHeader.ConnectionDataControl and $02) = $02 then + begin + TempMapIndex := LoadedMapHeader.ConnectionData[2].MapNumber; + TempMapHeader := GetMapHeader(TempMapIndex); + TempMapStart := GBPtrToFilePos(Map.BankLocations[TempMapIndex], + TempMapHeader.DataPointer); + ConnectedMapHeaders[2] := TempMapHeader; + SetLength(LeftMapData, TempMapHeader.Width * TempMapHeader.Height); + Rom.Position := TempMapStart; + Rom.Read(LeftMapData[0], TempMapHeader.Width * TempMapHeader.Height); + end; + + // Load Right connection data + if (LoadedMapHeader.ConnectionDataControl and $01) = $01 then + begin + TempMapIndex := LoadedMapHeader.ConnectionData[3].MapNumber; + TempMapHeader := GetMapHeader(TempMapIndex); + TempMapStart := GBPtrToFilePos(Map.BankLocations[TempMapIndex], + TempMapHeader.DataPointer); + ConnectedMapHeaders[3] := TempMapHeader; + SetLength(RightMapData, TempMapHeader.Width * TempMapHeader.Height); + Rom.Position := TempMapStart; + Rom.Read(RightMapData[0], TempMapHeader.Width * TempMapHeader.Height); + end; + + //give MapBox right size + MapBox.Height := LoadedMapHeader.Height * 32 + (6 * 32); //Pad with 6 Blocks + MapBox.Width := LoadedMapHeader.Width * 32 + (6 * 32); //Pad with 6 Blocks + + //Show map + MapScrollBox.Hide; + MapScrollBox.Show; + MapScrollBox.ScrollInView(MapBox); + MapBox.Refresh; + + //TODO: Load events and pokemon + LoadedMapBank := Map.BankLocations[MapIndex]; + LoadedMapNum := MapIndex; + + MapModified := False; + SaveMapPic1.Enabled := True; + + LoadPokemon(MapIndex); + //hide event properties + //WarpForm.Hide; + //SignpostForm.Hide; + //PeopleForm.Hide; +end; + +procedure TMapEditorForm.LoadPokemon(MapIndex: Byte); +var + First: string; + Second: string; +begin + PokemonStart := 0; + LandWildPkmn.Rate := $00; + WaterWildPkmn.Rate := $00; + LandPkmnBox.Clear; + WaterPkmnBox.Clear; + + Rom.Position := $CEEB + (MapIndex * 2); + Rom.Read(Pointer,SizeOf(Pointer)); + + First := IntToStr(Pointer.Second + $80); + Second := IntToStr(Pointer.First); + Location := IntToHex(StrToInt(First),2) + IntToHex(StrToInt(Second),2); + Rom.Position := StrToInt('$' + Location); + Rom.Read(LandWildPkmn,SizeOf(TLandWildPkmn)); + LandOffset1.Caption := '$' + Location; + if (LandWildPkmn.Rate <> $00) then + begin + PokemonStart := StrToInt('$' + Location); + Rom.Position := StrToInt('$' + Location) + SizeOf(TLandWildPkmn); + Rom.Read(WaterWildPkmn,SizeOf(TWaterWildPkmn)); + WaterOffset1.Caption := '$' + IntToHex(StrToInt('$' + Location) + SizeOf(TLandWildPkmn),4); + end + else + begin + WaterOffset1.Caption := '$' + IntToHex(StrToInt('$' + Location) + $01,4); + Rom.Position := StrToInt('$' + Location) + $01; + Rom.Read(WaterWildPkmn,SizeOf(TWaterWildPkmn)); + if WaterWildPkmn.Rate <> $00 then + begin + PokemonStart := StrToInt('$' + Location) + $01; + end; + end; + + if (LandWildPkmn.Rate = $00) and (WaterWildPkmn.Rate = $00) then + begin + NoWildPkmnLabel.Show; + Exit; + end; + if LandWildPkmn.Rate <> $00 then + begin + LandPkmnBox.Enabled := True; + LandPkmnCombo.Enabled := True; + LandPkmnLevel.Enabled := True; + LandRateTrack.Enabled := True; + LandReplaceBtn.Enabled := True; + end + else + begin + LandPkmnBox.Enabled := False; + LandPkmnCombo.Enabled := False; + LandPkmnLevel.Enabled := False; + LandRateTrack.Enabled := False; + LandReplaceBtn.Enabled := False; + end; + if WaterWildPkmn.Rate <> $00 then + begin + WaterPkmnBox.Enabled := True; + WaterPkmnCombo.Enabled := True; + WaterPkmnLevel.Enabled := True; + WaterRateTrack.Enabled := True; + WaterReplaceBtn.Enabled := True; + end + else + begin + WaterPkmnBox.Enabled := False; + WaterPkmnCombo.Enabled := False; + WaterPkmnLevel.Enabled := False; + WaterRateTrack.Enabled := False; + WaterReplaceBtn.Enabled := False; + end; + NoWildPkmnLabel.Hide; + LandRateTrack.Position := LandWildPkmn.Rate; + LandPercent.Caption := IntToStr(LandWildPkmn.Rate) + '%'; + WaterRateTrack.Position := WaterWildPkmn.Rate; + WaterPercent.Caption := IntToStr(WaterWildPkmn.Rate) + '%'; + UpdatePokemon; +end; + +procedure TMapEditorForm.UpdatePokemon; +var + I: Integer; +begin + LandPkmnBox.Clear; + WaterPkmnBox.Clear; + LandLevelBox.Clear; + WaterLevelBox.Clear; + if LandWildPkmn.Rate <> $00 then + begin + for I := 0 to 9 do + begin + LandPkmnBox.AddItem(LandPkmnCombo.Items[LandWildPkmn.Pkmn[I].Number],LandPkmnBox); + LandLevelBox.AddItem(IntToStr(LandWildPkmn.Pkmn[I].Level),LandLevelBox); + end; + end; + if WaterWildPkmn.Rate <> $00 then + begin + for I := 0 to 9 do + begin + WaterPkmnBox.AddItem(WaterPkmnCombo.Items[WaterWildPkmn.Pkmn[I].Number],WaterPkmnBox); + WaterLevelBox.AddItem(IntToStr(WaterWildPkmn.Pkmn[I].Level),WaterLevelBox); + end; + end; +end; + +procedure TMapEditorForm.MapBoxMouseDown(Sender: TObject; Button: TMouseButton; + Shift: TShiftState; X, Y: Integer); +var + StartTileConnect, StartWriteConnect: Integer; + StartX, StartY, EndX, EndY: Integer; + BlockX, BlockY: Integer; +begin + + BlockX := X div 32; + BlockY := Y div 32; + + if IsOutsideOfMapBounds(X, Y) = false then + begin + //change block if mouse button is left + if Button = mbLeft then + begin + MapModified := True; + MapData[SelPic] := SelBlock; + MapBox.Canvas.Draw((X div 32) * 32, (Y div 32) * 32, BlockPics[SelBlock]); + //if gid is sellected, add it + if Grid1.Checked then + MapBox.Canvas.Rectangle(X div 32 * 32, Y div 32 * 32, + X div 32 * 32 + 32, Y div 32 * 32 + 32); + //enable painting for OnMouseMove + Painting := True; + end + else + begin + //other buttons will select the block at cursor + if (MapData[SelPic] <= Blocks) then + begin + BlockPaletteScrollBox.VertScrollBar.Position := 32 * MapData[SelPic]; + SelBlock := MapData[SelPic]; + end; + end; + end + else + begin + // check if we are over a top connection + if (LoadedMapHeader.ConnectionDataControl and $08) = $08 then + begin + StartTileConnect := (LoadedMapHeader.ConnectionData[0].MapDataPointer - $4000) - (ConnectedMapHeaders[0].DataPointer - $4000); + StartWriteConnect := LoadedMapHeader.ConnectionData[0].MapLocationRamPointer - $C6E8; + StartX := StartWriteConnect; + StartY := 0; + EndX := (LoadedMapHeader.ConnectionData[0].WidthHeightVisiblePart - 1) + StartWriteConnect; + EndY := StartY + 3; + if (BlockX >= StartX) and (BlockY >= StartY) and (BlockX <= EndX) and (BlockY < EndY) then + begin + MapSelectCombo.ItemIndex := LoadedMapHeader.ConnectionData[0].MapNumber; + MapSelectComboChange(Sender); + end; + end; + + // check if we are over a bottom connection + if (LoadedMapHeader.ConnectionDataControl and $04) = $04 then + begin + StartTileConnect := (LoadedMapHeader.ConnectionData[1].MapDataPointer - $4000) - (ConnectedMapHeaders[1].DataPointer - $4000); + StartWriteConnect := LoadedMapHeader.ConnectionData[1].MapLocationRamPointer - $C6E8; + StartX := StartWriteConnect - ((LoadedMapHeader.Width + 6) * (LoadedMapHeader.Height + 3)); + StartY := StartWriteConnect div (LoadedMapHeader.Width + 6); + EndX := StartX + (LoadedMapHeader.ConnectionData[1].WidthHeightVisiblePart - 1); + EndY := StartY + 3; + if (BlockX >= StartX) and (BlockY >= StartY) and (BlockX <= EndX) and (BlockY < EndY) then + begin + MapSelectCombo.ItemIndex := LoadedMapHeader.ConnectionData[1].MapNumber; + MapSelectComboChange(Sender); + end; + end; + + // Left + if (LoadedMapHeader.ConnectionDataControl and $02) = $02 then + begin + StartTileConnect := (LoadedMapHeader.ConnectionData[2].MapDataPointer - $4000) - (ConnectedMapHeaders[2].DataPointer - $4000); + StartWriteConnect := LoadedMapHeader.ConnectionData[2].MapLocationRamPointer - $C6E8; + StartX := 0; + StartY := StartWriteConnect div (LoadedMapHeader.Width + 6); + EndX := (StartX + 3) - 1; + EndY := StartY + LoadedMapHeader.ConnectionData[2].WidthHeightVisiblePart; + if (BlockX >= StartX) and (BlockY >= StartY) and (BlockX <= EndX) and (BlockY < EndY) then + begin + MapSelectCombo.ItemIndex := LoadedMapHeader.ConnectionData[2].MapNumber; + MapSelectComboChange(Sender); + end; + end; + + // Right + if (LoadedMapHeader.ConnectionDataControl and $01) = $01 then + begin + StartTileConnect := (LoadedMapHeader.ConnectionData[3].MapDataPointer - $4000) - (ConnectedMapHeaders[3].DataPointer - $4000); + StartWriteConnect := LoadedMapHeader.ConnectionData[3].MapLocationRamPointer - $C6E8; + StartX := LoadedMapHeader.Width+3; + StartY := StartWriteConnect div (LoadedMapHeader.Width + 6); + EndX := (StartX + 3) - 1; + EndY := StartY + LoadedMapHeader.ConnectionData[3].WidthHeightVisiblePart; + if (BlockX >= StartX) and (BlockY >= StartY) and (BlockX <= EndX) and (BlockY < EndY) then + begin + MapSelectCombo.ItemIndex := LoadedMapHeader.ConnectionData[3].MapNumber; + MapSelectComboChange(Sender); + end; + end; + end; +end; + +procedure TMapEditorForm.MapBoxMouseMove(Sender: TObject; Shift: TShiftState; X, + Y: Integer); +var + StartTileConnect, StartWriteConnect: Integer; + StartX, StartY, EndX, EndY: Integer; + BlockX, BlockY: Integer; +begin + + BlockX := X div 32; + BlockY := Y div 32; + + //Get block number where cursor is + SelPic := ((Y div 32)-3) * LoadedMapHeader.Width + ((X div 32)-3); + + //don't do anything with wrong coordinates + if (X < 0) or (Y < 0) or (SelPic >= (LoadedMapHeader.Width+3) * (LoadedMapHeader.Height+3)) then Exit; + + shpHighlight.Width := 32+1; + shpHighlight.Height := 32+1; + shpHighlight.Top := MapBox.Top + ((Y div 32) * 32); + shpHighlight.Left := MapBox.Left + (X div 32) * 32; + + if IsOutsideOfMapBounds(X, Y) = True then + begin + shpHighlight.Brush.Color := $80FF; + StatusBar1.Panels[0].Text := 'Border Tile (Read Only)'; + MapBox.Cursor := crDrag; + + // check if we are over a top connection + if (LoadedMapHeader.ConnectionDataControl and $08) = $08 then + begin + StartTileConnect := (LoadedMapHeader.ConnectionData[0].MapDataPointer - $4000) - (ConnectedMapHeaders[0].DataPointer - $4000); + StartWriteConnect := LoadedMapHeader.ConnectionData[0].MapLocationRamPointer - $C6E8; + StartX := StartWriteConnect; + StartY := 0; + EndX := (LoadedMapHeader.ConnectionData[0].WidthHeightVisiblePart - 1) + StartWriteConnect; + EndY := StartY + 3; + if (BlockX >= StartX) and (BlockY >= StartY) and (BlockX <= EndX) and (BlockY < EndY) then + begin + shpHighlight.Left := (StartX*32)-MapBox.Canvas.ClipRect.Left; + shpHighlight.Top := (StartY*32)-MapBox.Canvas.ClipRect.Top; + shpHighlight.Width := (LoadedMapHeader.ConnectionData[0].WidthHeightVisiblePart*32)+1; + shpHighlight.Height := (3*32)+1; + StatusBar1.Panels[0].Text := 'Connected Map #: ' + IntToStr(LoadedMapHeader.ConnectionData[0].MapNumber); + MapBox.Cursor := crHandPoint; + end; + end; + + // check if we are over a bottom connection + if (LoadedMapHeader.ConnectionDataControl and $04) = $04 then + begin + StartTileConnect := (LoadedMapHeader.ConnectionData[1].MapDataPointer - $4000) - (ConnectedMapHeaders[1].DataPointer - $4000); + StartWriteConnect := LoadedMapHeader.ConnectionData[1].MapLocationRamPointer - $C6E8; + StartX := StartWriteConnect - ((LoadedMapHeader.Width + 6) * (LoadedMapHeader.Height + 3)); + StartY := StartWriteConnect div (LoadedMapHeader.Width + 6); + EndX := StartX + (LoadedMapHeader.ConnectionData[1].WidthHeightVisiblePart - 1); + EndY := StartY + 3; + if (BlockX >= StartX) and (BlockY >= StartY) and (BlockX <= EndX) and (BlockY < EndY) then + begin + shpHighlight.Left := (StartX * 32) - MapBox.Canvas.ClipRect.Left; + shpHighlight.Top := (StartY * 32) - MapBox.Canvas.ClipRect.Top; + shpHighlight.Width := (LoadedMapHeader.ConnectionData[1].WidthHeightVisiblePart * 32)+1; + shpHighlight.Height := (3*32)+1; + StatusBar1.Panels[0].Text := 'Connected Map #: ' + IntToStr(LoadedMapHeader.ConnectionData[1].MapNumber); + MapBox.Cursor := crHandPoint; + end; + end; + + // Left + if (LoadedMapHeader.ConnectionDataControl and $02) = $02 then + begin + StartTileConnect := (LoadedMapHeader.ConnectionData[2].MapDataPointer - $4000) - (ConnectedMapHeaders[2].DataPointer - $4000); + StartWriteConnect := LoadedMapHeader.ConnectionData[2].MapLocationRamPointer - $C6E8; + StartX := 0; + StartY := StartWriteConnect div (LoadedMapHeader.Width + 6); + EndX := (StartX + 3) - 1; + EndY := StartY + LoadedMapHeader.ConnectionData[2].WidthHeightVisiblePart; + if (BlockX >= StartX) and (BlockY >= StartY) and (BlockX <= EndX) and (BlockY < EndY) then + begin + shpHighlight.Left := (StartX * 32) - MapBox.Canvas.ClipRect.Left; + shpHighlight.Top := (StartY * 32) - MapBox.Canvas.ClipRect.Top; + shpHighlight.Width := (3*32)+1; + shpHighlight.Height := (LoadedMapHeader.ConnectionData[2].WidthHeightVisiblePart * 32)+1; + StatusBar1.Panels[0].Text := 'Connected Map #: ' + IntToStr(LoadedMapHeader.ConnectionData[2].MapNumber); + MapBox.Cursor := crHandPoint; + end; + end; + + // Right + if (LoadedMapHeader.ConnectionDataControl and $01) = $01 then + begin + StartTileConnect := (LoadedMapHeader.ConnectionData[3].MapDataPointer - $4000) - (ConnectedMapHeaders[3].DataPointer - $4000); + StartWriteConnect := LoadedMapHeader.ConnectionData[3].MapLocationRamPointer - $C6E8; + StartX := LoadedMapHeader.Width+3; + StartY := StartWriteConnect div (LoadedMapHeader.Width + 6); + EndX := (StartX + 3) - 1; + EndY := StartY + LoadedMapHeader.ConnectionData[3].WidthHeightVisiblePart; + if (BlockX >= StartX) and (BlockY >= StartY) and (BlockX <= EndX) and (BlockY < EndY) then + begin + shpHighlight.Left := (StartX * 32) - MapBox.Canvas.ClipRect.Left; + shpHighlight.Top := (StartY * 32) - MapBox.Canvas.ClipRect.Top; + shpHighlight.Width := (3*32)+1; + shpHighlight.Height := (LoadedMapHeader.ConnectionData[3].WidthHeightVisiblePart * 32)+1; + StatusBar1.Panels[0].Text := 'Connected Map #: ' + IntToStr(LoadedMapHeader.ConnectionData[3].MapNumber); + MapBox.Cursor := crHandPoint; + end; + end; + end + else + begin + StatusBar1.Panels[0].Text := 'X: ' + IntToStr((X div 32)-3) + + ' Y: ' + IntToStr((Y div 32)-3) + + ' Block: $' + IntToHex(MapData[SelPic], 2) + + ' Offset: $' + IntToHex(MapStart + SelPic, 2); + shpHighlight.Brush.Color := clLime; + MapBox.Cursor := crDrag; + end; + + //If mouse left button is pressed block is changed + if Painting then + begin + MapData[SelPic] := SelBlock; + MapBox.Canvas.Draw(X div 32 * 32,Y div 32 * 32,BlockPics[SelBlock]); + //if grid is selected, add it + if Grid1.Checked then + MapBox.Canvas.Rectangle(X div 32 * 32, Y div 32 * 32, + X div 32 * 32 + 32, Y div 32 * 32 + 32); + end; +end; + +procedure TMapEditorForm.MapBoxMouseUp(Sender: TObject; Button: TMouseButton; + Shift: TShiftState; X, Y: Integer); +begin + Painting := False; +end; + +procedure TMapEditorForm.MapBoxPaint(Sender: TObject); +begin + DrawMap(MapBox.Canvas); +end; + +procedure TMapEditorForm.MapSelectComboChange(Sender: TObject); +begin + LoadMap(MapSelectCombo.ItemIndex); + //Tab := PageControl1.ActivePageIndex; + //PageControl1.ActivePageIndex := Tab; + //MapBoxPaint(nil); + //MapBox.Invalidate; + //MapScrollBox.Refresh; +end; + +function TMapEditorForm.IsOutsideOfMapBounds(X, Y: Integer): Boolean; +begin + if ((Y div 32) - 3 < 0) or ((X div 32) - 3 < 0) + or ((X div 32) - 3 >= LoadedMapHeader.Width) or ((Y div 32) - 3 >= LoadedMapHeader.Height) then + Result := True + else + Result := False; +end; + +procedure TMapEditorForm.Exit1Click(Sender: TObject); +begin + Close; +end; + +procedure TMapEditorForm.SaveRom1Click(Sender: TObject); +begin + SaveRom(OpenRomDialog.FileName); +end; + +procedure TMapEditorForm.SaveRom(FileName: string); +begin + if MapStart > 0 then + SaveMap; + //if (EventsAddr>0) then + // SaveEvents; + if PokemonStart > 0 then + SavePokemon; + Rom.SaveToFile(FileName); + RomModified := False; +end; + +procedure TMapEditorForm.SaveMap; +begin + //write map data + Rom.Position := MapStart; + Rom.Write(MapData[0],LoadedMapHeader.Width * LoadedMapHeader.Height); + //save other stuff + //SaveEvents; + //SavePokemon; + MapModified := False; + RomModified := True; +end; + +procedure TMapEditorForm.SavePokemon; +begin + if PokemonStart = 0 then + Exit; + + if LandWildPkmn.Rate <> $00 then + begin + Rom.Position := PokemonStart; + Rom.Write(LandWildPkmn,SizeOf(TLandWildPkmn)); + end; + if WaterWildPkmn.Rate <> $00 then + begin + if LandWildPkmn.Rate = $00 then + begin + Rom.Position := PokemonStart; + Rom.Write(WaterWildPkmn,SizeOf(TWaterWildPkmn)); + end + else + begin + Rom.Position := PokemonStart + SizeOf(TLandWildPkmn); + Rom.Write(WaterWildPkmn,SizeOf(TWaterWildPkmn)); + end; + end; +end; + +procedure TMapEditorForm.LandReplaceBtnClick(Sender: TObject); +begin + LandWildPkmn.Pkmn[LandPkmnBox.ItemIndex].Number := LandPkmnCombo.ItemIndex; + LandWildPkmn.Pkmn[LandPkmnBox.ItemIndex].Level := LandPkmnLevel.Value; + UpdatePokemon; + MapModified := True; +end; + +procedure TMapEditorForm.WaterReplaceBtnClick(Sender: TObject); +begin + WaterWildPkmn.Pkmn[WaterPkmnBox.ItemIndex].Number := WaterPkmnCombo.ItemIndex; + WaterWildPkmn.Pkmn[WaterPkmnBox.ItemIndex].Level := WaterPkmnLevel.Value; + UpdatePokemon; + MapModified := True; +end; + +procedure TMapEditorForm.LandPkmnBoxClick(Sender: TObject); +begin + LandPkmnCombo.ItemIndex := LandWildPkmn.Pkmn[LandPkmnBox.ItemIndex].Number; + LandPkmnLevel.Value := LandWildPkmn.Pkmn[LandPkmnBox.ItemIndex].Level; +end; + +procedure TMapEditorForm.WaterPkmnBoxClick(Sender: TObject); +begin + WaterPkmnCombo.ItemIndex := WaterWildPkmn.Pkmn[WaterPkmnBox.ItemIndex].Number; + WaterPkmnLevel.Value := WaterWildPkmn.Pkmn[WaterPkmnBox.ItemIndex].Level; +end; + +procedure TMapEditorForm.LandRateTrackExit(Sender: TObject); +begin + LandWildPkmn.Rate := LandRateTrack.Position; + LandPercent.Caption := IntToStr(LandRateTrack.Position) + '%'; + MapModified := True; +end; + +procedure TMapEditorForm.WaterRateTrackExit(Sender: TObject); +begin + WaterWildPkmn.Rate := WaterRateTrack.Position; + WaterPercent.Caption := IntToStr(WaterRateTrack.Position) + '%'; + MapModified := True; +end; + +end. diff --git a/Misc.pas b/Misc.pas new file mode 100644 index 0000000..343ab34 --- /dev/null +++ b/Misc.pas @@ -0,0 +1,30 @@ +unit Misc; + +interface + +uses Windows, Sysutils; + +procedure DebugString(aCaption, aText: string); + +implementation + + // GetFormatDT - Output = formated DateTime String +function GetFormatDT(aDateTime: TDateTime): string; +begin + Result := FormatDateTime('dd.mm.yy hh:nn:ss zzz', aDateTime); +end; + +// GetFormatT - Output = formated Time String +function GetFormatT(aDateTime: TDateTime): string; +begin + Result := FormatDateTime('hh:nn:ss zzz', aDateTime) +end; + +procedure DebugString(aCaption, aText: string); +begin + OutputDebugString(PChar(Format('[%s][%s] %s', + [aCaption, GetFormatDT(Now()), + aText]))); +end; + +end. diff --git a/Pokémap.ico b/Pokémap.ico new file mode 100644 index 0000000..6527f4e Binary files /dev/null and b/Pokémap.ico differ diff --git a/RedMap.bdsproj b/RedMap.bdsproj new file mode 100644 index 0000000..c893936 --- /dev/null +++ b/RedMap.bdsproj @@ -0,0 +1,170 @@ + + + + + + + + + + + + RedMap.dpr + + + 7.0 + + + 8 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 0 + 0 + 1 + 0 + 1 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 1 + 1 + 1 + True + True + WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; + + False + + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + False + False + False + True + True + True + True + True + True + + + + 0 + 0 + False + 1 + False + False + False + 16384 + 1048576 + 4194304 + + + + + + + + + vcl;rtl;vclx;dbrtl;vcldb;VclSmp;xmlrtl;vclie;inet;inetdbbde;inetdbxpress;PNGLib;madBasic_;madDisAsm_;madExcept_ + + + False + + + + + + False + + + True + False + + + False + False + 1 + 0 + 0 + 0 + False + False + False + False + False + 1033 + 1252 + + + + + 1.0.0.0 + + + + + + 1.0.0.0 + + + + diff --git a/RedMap.dof b/RedMap.dof new file mode 100644 index 0000000..9fedde4 --- /dev/null +++ b/RedMap.dof @@ -0,0 +1,132 @@ +[FileVersion] +Version=7.0 +[Compiler] +A=8 +B=0 +C=1 +D=1 +E=0 +F=0 +G=1 +H=1 +I=1 +J=0 +K=0 +L=1 +M=0 +N=1 +O=1 +P=1 +Q=0 +R=0 +S=0 +T=0 +U=0 +V=1 +W=0 +X=1 +Y=1 +Z=1 +ShowHints=1 +ShowWarnings=1 +UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; +NamespacePrefix= +SymbolDeprecated=1 +SymbolLibrary=1 +SymbolPlatform=1 +UnitLibrary=1 +UnitPlatform=1 +UnitDeprecated=1 +HResultCompat=1 +HidingMember=1 +HiddenVirtual=1 +Garbage=1 +BoundsError=1 +ZeroNilCompat=1 +StringConstTruncated=1 +ForLoopVarVarPar=1 +TypedConstVarPar=1 +AsgToTypedConst=1 +CaseLabelRange=1 +ForVariable=1 +ConstructingAbstract=1 +ComparisonFalse=1 +ComparisonTrue=1 +ComparingSignedUnsigned=1 +CombiningSignedUnsigned=1 +UnsupportedConstruct=1 +FileOpen=1 +FileOpenUnitSrc=1 +BadGlobalSymbol=1 +DuplicateConstructorDestructor=1 +InvalidDirective=1 +PackageNoLink=1 +PackageThreadVar=1 +ImplicitImport=1 +HPPEMITIgnored=1 +NoRetVal=1 +UseBeforeDef=1 +ForLoopVarUndef=1 +UnitNameMismatch=1 +NoCFGFileFound=1 +MessageDirective=1 +ImplicitVariants=1 +UnicodeToLocale=1 +LocaleToUnicode=1 +ImagebaseMultiple=1 +SuspiciousTypecast=1 +PrivatePropAccessor=1 +UnsafeType=0 +UnsafeCode=0 +UnsafeCast=0 +[Linker] +MapFile=0 +OutputObjs=0 +ConsoleApp=1 +DebugInfo=0 +RemoteSymbols=0 +MinStackSize=16384 +MaxStackSize=1048576 +ImageBase=4194304 +ExeDescription= +[Directories] +OutputDir= +UnitOutputDir= +PackageDLLOutputDir= +PackageDCPOutputDir= +SearchPath= +Packages= +Conditionals= +DebugSourceDirs= +UsePackages=0 +[Parameters] +RunParams= +HostApplication= +Launcher= +UseLauncher=0 +DebugCWD= +[Version Info] +IncludeVerInfo=0 +AutoIncBuild=0 +MajorVer=1 +MinorVer=0 +Release=0 +Build=0 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=0 +Locale=1033 +CodePage=1252 +[Version Info Keys] +CompanyName= +FileDescription= +FileVersion=1.0.0.0 +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion=1.0.0.0 +Comments= diff --git a/RedMap.dpr b/RedMap.dpr new file mode 100644 index 0000000..808e7bf --- /dev/null +++ b/RedMap.dpr @@ -0,0 +1,20 @@ +program RedMap; + +uses + Forms, + MapEditor in 'MapEditor.pas' {MapEditorForm}, + Tileset in 'Tileset.pas', + Map in 'Map.pas', + About in 'About.pas' {AboutDialog}, + Misc in 'Misc.pas', + BlockEditor in 'BlockEditor.pas' {BlockEditorForm}; + +{$R *.res} + +begin + Application.Initialize; + Application.Title := 'RedMap'; + Application.CreateForm(TMapEditorForm, MapEditorForm); + Application.CreateForm(TAboutDialog, AboutDialog); + Application.Run; +end. diff --git a/RedMap.res b/RedMap.res new file mode 100644 index 0000000..a931a4b Binary files /dev/null and b/RedMap.res differ diff --git a/Tileset.pas b/Tileset.pas new file mode 100644 index 0000000..7a08980 --- /dev/null +++ b/Tileset.pas @@ -0,0 +1,93 @@ +unit Tileset; + +interface + +uses Map, Classes, Dialogs, SysUtils, Graphics; + +type + TTilesetHeader = packed record + BankNumber: Byte; + TilesetArrangementPointer: Word; + TilesetGraphicsPointer: Word; + UnknownData: array [0..6] of Byte; + end; + +var + //Palette: array [0..3] of TColor = (clWhite,clLtGray,clDkGray,clBlack); + //Palette: array [0..3] of TColor = ($F8E8F8, $A8E058, $A0D0F8, $181010); + Palette: array [0..3] of TColor = ($F8E8F8, $58E0A8, $F8D0A0, $101018); + RawMapPalettes: array [0..12, 0..3] of Word; + +const Zero: Byte = 0; + +function GetTilesetHeader(TilesetNumber: Byte): TTilesetHeader; +function WordToColor(Value: Word): TColor; +procedure ReadTilesetGraphics(TilesetHeader: TTilesetHeader; Bmp: TBitmap); +procedure ReadMapPallets; + +implementation + +uses MapEditor; + +function GetTilesetHeader(TilesetNumber: Byte): TTilesetHeader; +begin + Rom.Position := $C7BE + ((TilesetNumber) * SizeOf(TTilesetHeader)); + Rom.Read(Result, SizeOf(TTilesetHeader)); +end; + +function WordToColor(Value: Word): TColor; +var + R,G,B: Byte; +begin + R := Round((((Value shr 00) and 31) / 31) * 255); + G := Round((((Value shr 05) and 31) / 31) * 255); + B := Round((((Value shr 10) and 31) / 31) * 255); + Result := R or (G shl 8) or (B shl 16); +end; + +//reads tile from Stream into Bmp and uses colors from Pal +procedure ReadTile(Stream: TStream; Bmp: TBitmap); +var + X,Y: Integer; + Data1,Data2: Byte; +begin + for Y := 0 to 7 do + begin + Stream.Read(Data1,1); + Stream.Read(Data2,1); + for X := 0 to 7 do + Bmp.Canvas.Pixels[X,Y] := Palette[((Data1 shr (7-X)) and 1) or (((Data2 shr (7-X)) and 1) shl 1)]; + end; +end; + +//reads tileset at specific address into Bmp +procedure ReadTilesetGraphics(TilesetHeader: TTilesetHeader; Bmp: TBitmap); +var + Tile: TBitmap; + TileCnt: Byte; + I: Integer; + +begin + + Tile := TBitmap.Create; + Tile.PixelFormat := pf24bit; + Tile.Width := 8; + Tile.Height := 8; + Rom.Position := GBPtrToFilePos(TilesetHeader.BankNumber, TilesetHeader.TilesetGraphicsPointer); + TileCnt := 0; + for I := 1 to 16 * 6 do + begin + ReadTile(Rom,Tile); + Bmp.Canvas.Draw((TileCnt mod 16) * 8, (TileCnt div 16) * 8, Tile); + Inc(TileCnt); + end; +end; + +procedure ReadMapPallets; +begin + Rom.Position := $72660; + Rom.Read(RawMapPalettes, 8*12); + +end; + +end. diff --git a/event-object.png b/event-object.png new file mode 100644 index 0000000..b88b089 Binary files /dev/null and b/event-object.png differ