You are not logged in.
The town map in RBGY is stored using RLE(Run Lenth Encoding) compression,
So for example you want to lay down 4 land tiles you would with out RLE
compression: 06 06 06 06, which RLE compression you write the Hexadecimal
number of the Tile down then the number of times you would like to lay it
down on the screen, e.g. 64.
I recomend repointing your maps data for saftey purposes as you may run out of
room and not realise that you are writing over important data.
The maps pointer is at:
Kanto's Map is between:
0 - Blank Tile (DONT USE!)
1 - Alternate Land Route Across
2 - Alternate Land Route Up
3 - Alternate Land mark
4 - Water
5 - Town
6 - Land
7 - White Title/Path
8 - North East Lands end
9 - North West Lands End
A - South West Lands End
B - South East Lands End
C - Land mark
D - One Sea Route Dot
E - Sea Dot Across
F - Sea Dot Up
I recomend doing your map in GSC first which uses no compression with its town
map, then use it as a guide to create your RBGY version, iv found it is easiest
to do it line by line, then when you have typed in each line indicate that you
have somehow so you know where you are, like I did with Crion for my Red hack
Line One - 48 91 61 81 44 A1 64 - Yes
Line Two - 41 91 61 81 42 91 61 51 62 45 64 - Yes
Line Three - 41 61 C1 61 41 91 62 71 61 51 81 44 A1 63 - Yes
Line Four - 41 A1 71 B1 41 61 73 61 71 B1 45 63 - Yes
Line Five - 42 C1 41 91 61 51 63 71 B1 45 A1 62 - Yes
Line Six - 42 71 91 75 61 51 61 81 45 62 - Yes
Line Seven - 42 71 61 71 61 51 61 71 61 71 62 45 A1 61 - Yes
Line Eight - 91 81 71 61 71 B1 F1 A1 71 61 C1 61 B1 47 - Yes
Line Nine - 72 51 72 41 F1 41 71 63 (49:Last tile 1st tile on L.10) - Yes
Line Ten - A1 61 B1 41 F1 91 71 51 71 C1 81 41 91 61 81 (47:Last 4 tiles
1st on line 11)
Line Eleven - 91 61 71 62 71 66 B1 42 91 - Yes
Line Twelve - 44 A1 61 C1 62 71 65 B1 42 91 61 - Yes
Line Thirteen - B1 61 A1 42 64 51 73 51 71 E3 C1 61 - Yes
Line Forteen - 61 51 71 E2 C1 62 B1 F1 A1 64 81 42 A1 61 - Yes
Line Fifteen - A1 62 81 41 A1 B1 42 F1 42 A1 B1 A1 B1 (45:Last tile 1st tile on
L.16) - Yes
Line Sixteen - A1 61 B1 45 F1 4F:Last 5 tiles 1st tiles on L.17) - Yes
Line Seventeen - 44 F1 4A - Yes
A big thankyou has to go out to a guy called Hyperhacker who first found the
maps location in the first place and how it is stored.
I can't answer your question, 80C, but I would like to expand on what Cartmic posted, since I just worked on the town map the other day.
Here is some more information about the town map:
To change the locations of the towns and routes, and possible re-point them if you change the names:
This was taken from the disassembly project:
ExternalMapEntries: ; 1c:5313 EMAP $2,$B,PalletTownName EMAP $2,$8,ViridianCityName EMAP $2,$3,PewterCityName EMAP $A,$2,CeruleanCityName EMAP $E,$5,LavenderTownName EMAP $A,$9,VermilionCityName EMAP $7,$5,CeladonCityName EMAP $8,$D,FuchsiaCityName EMAP $2,$F,CinnabarIslandName EMAP $0,$2,IndigoPlateauName EMAP $A,$5,SaffronCityName EMAP $0,$0,PalletTownName ; unused EMAP $2,$A,Route1Name EMAP $2,$6,Route2Name EMAP $4,$3,Route3Name EMAP $8,$2,Route4Name EMAP $A,$3,Route5Name EMAP $A,$8,Route6Name EMAP $8,$5,Route7Name EMAP $D,$5,Route8Name EMAP $D,$2,Route9Name EMAP $E,$4,Route10Name EMAP $C,$9,Route11Name EMAP $E,$9,Route12Name EMAP $D,$B,Route13Name EMAP $B,$C,Route14Name EMAP $A,$D,Route15Name EMAP $5,$5,Route16Name EMAP $4,$8,Route17Name EMAP $6,$D,Route18Name EMAP $6,$F,Route19Name EMAP $4,$F,Route20Name EMAP $2,$D,Route21Name EMAP $0,$8,Route22Name EMAP $0,$6,Route23Name EMAP $A,$1,Route24Name EMAP $B,$0,Route25Name InternalMapEntries: ; 1c:5382 IMAP $29,$2,$B,PalletTownName IMAP $2E,$2,$8,ViridianCityName IMAP $33,$2,$6,Route2Name IMAP $34,$2,$4,ViridianForestName IMAP $3B,$2,$3,PewterCityName IMAP $3E,$6,$2,MountMoonName IMAP $44,$A,$2,CeruleanCityName IMAP $45,$5,$2,Route4Name IMAP $46,$A,$2,CeruleanCityName IMAP $49,$A,$4,Route5Name IMAP $4C,$A,$6,Route6Name IMAP $4F,$9,$5,Route7Name IMAP $51,$B,$5,Route8Name IMAP $53,$E,$3,RockTunnelName IMAP $54,$F,$4,PowerPlantName IMAP $57,$D,$9,Route11Name IMAP $58,$E,$7,Route12Name IMAP $59,$C,$0,SeaCottageName IMAP $5F,$A,$9,VermilionCityName IMAP $69,$9,$A,SSAnneName IMAP $6D,$0,$4,VictoryRoadName IMAP $77,$0,$2,PokemonLeagueName IMAP $78,$A,$5,UndergroundPathName IMAP $79,$0,$2,PokemonLeagueName IMAP $7A,$A,$5,UndergroundPathName IMAP $8D,$7,$5,CeladonCityName IMAP $8E,$E,$5,LavenderTownName IMAP $95,$F,$5,PokemonTowerName IMAP $98,$E,$5,LavenderTownName IMAP $9C,$8,$D,FuchsiaCityName IMAP $9D,$8,$C,SafariZoneName IMAP $9F,$8,$D,FuchsiaCityName IMAP $A3,$5,$F,SeafoamIslandsName IMAP $A4,$A,$9,VermilionCityName IMAP $A5,$8,$D,FuchsiaCityName IMAP $A6,$2,$F,PokemonMansionName IMAP $AE,$2,$F,CinnabarIslandName IMAP $AF,$0,$2,IndigoPlateauName IMAP $B8,$A,$5,SaffronCityName IMAP $BA,$9,$D,Route15Name IMAP $BD,$4,$5,Route16Name IMAP $BE,$E,$A,Route12Name IMAP $C0,$7,$D,Route18Name IMAP $C1,$5,$F,SeafoamIslandsName IMAP $C2,$0,$7,Route22Name IMAP $C3,$0,$4,VictoryRoadName IMAP $C4,$E,$7,Route12Name IMAP $C5,$A,$9,VermilionCityName IMAP $C6,$3,$4,DiglettsCaveName IMAP $C7,$0,$4,VictoryRoadName IMAP $CF,$7,$5,RocketHQName IMAP $D6,$A,$5,SilphCoName IMAP $D9,$2,$F,PokemonMansionName IMAP $E2,$8,$C,SafariZoneName IMAP $E5,$9,$1,CeruleanCaveName IMAP $E6,$E,$5,LavenderTownName IMAP $E7,$A,$2,CeruleanCityName IMAP $E9,$E,$3,RockTunnelName IMAP $ED,$A,$5,SilphCoName IMAP $F8,$0,$2,PokemonLeagueName db $FF
The external maps work just as you'd expect, if you are in any of those towns/routes, it will look at that table and get the location and text string from the row that corresponds to the map you are in.
The first nibble (half-byte) is the Y location (from the top) [0-F]
The second nibble is the X location (from the left) [0-F]
Those are both combined into byte, so for pallet town, they combine and is displayed as $2B
The following word (2 bytes) is the pointer to the name of the location (in bank 1C, the names start at 1C:5473)
The internal maps are slightly different. The idea is that if you are not in one of the routes or towns, then you are in a building or a cave. Since these are not necessary shown on the map, the game looks through this table to determine which location (on the map) it should indicate you are at and which name it should display.
The first byte indicates the hexadecimal ID number for the map. (I'll get back to this)
The following byte is the Y/X location. (combined, as above)
The end word is the text pointer to the name of the location.
The game determines which row from the table to use by comparing to the ID of the map to the first byte in the row. If the map value is BELOW the value indicated, it will use that line. If not, it will check the next line.
For example, Viridian Forest is ID $33
The following lines are in the table:
IMAP $2E,$2,$8,ViridianCityName IMAP $33,$2,$6,Route2Name IMAP $34,$2,$4,ViridianForestName
The game compares the map id ($33) to the ID in the ID stored in the top line. $33 is not below $2E, so it checks the next line.
Again, $33 is not below $33 (they are equal), so it checks the value against the next line.
In this case, the map ID ($33) IS below the value in the row ($34), so it uses that row to display the location and name of Viridian Forest on the map.
As you can see, this allowed the for multiple buildings / caves to be grouped together to a single location and text pointer. For example, the SS Anne maps are from $5F-$68. The code in the game reads:
IMAP $5F,$A,$9,VermilionCityName IMAP $69,$9,$A,SSAnneName
In this case, all of the maps for the SS Anne will fail the check on the top line, but pass the check for the next line (they are all >= $5F and <$69).
To change the order that the towns/routes appear when you cycle through the map:
To do this, simply replace the values from 1C:4F11 - 4F41 to the ID's of the maps that you want to appear on the map, in order. If you don't want to use all of the spaces, replace the remaining ones with FE (when the game see an FE, it will skip to the next location)
To change the order that the towns appear when you cycle through the map while using FLY:
This starts are 1c:5070.
This one is a bit tricky, but I'll try to explain how it works:
First off, know that the bytes in ram that indicate which towns you can fly to are stored in D70B-D70C.
Second, know that the game stores the flyable map IDs in CD3D-CD49.
hl is then set to CD3D.
The first step is to set (hl) [this means the value stored at the pointer saved in hl] to FF, to indicate that it is the beginning of the list.
It then increments hl, so it now points to the first item in the list.
The game then checks each bit (starting with bit 0 of D70B, up to bit 2 of D70C) to see if it is set or not.
If it is set, it places the number of the bit [from 0-0B, where bit 0 if D70B = 0, and bit 2 of D70C = 2b] at the location that hl points to.
If it is not set, it places FE are the location that hl points to. [FE means skip to the next item]
It then increments hl to have it point to the next item in the list.
(it then loops and checks the next bit)
Finally, after it checks through all of the bits, it places FF at the location that hl points to, which is CD49. This shows that it is the end of the list.
Now, this code is hard to modify because it is a single loop and the map ID that is saved is simply one higher than the previous.
I recommend simply writing your own routine to check each town bit in the order that you want it to display. To do this, you first have to repoint the call to your custom script.
The call for this script is at 1c:4fb4.
At this location, you want to replace
Here is the example of the script that I have for my game. I have changed the order of the town appearances in the game, and the script checks each map in the order that I want them to appear in the flyable map list.
Script starts at 1c:7cd0: ld hl,cd3d ;load start location ld (hl),ff ;place beginning ff and increase hl inc hl ld bc,000c ;number of towns [I ADDED A TOWN, IF YOU ARE TO COPY THIS SCRIPT, USE ld bc,000b] ;this loop pre-sets every value in the array of towns (from CD3D-CD49, not inclusive) to FE 7cd9: ld (hl),fe ;place SKIP inc hl dec c jr nz,7cd9 ;loop if not at 0 ld (hl),ff ;place finisher ld hl,cd3e ;load first town location 7CE4: [TOWN1] ld a,(d70b) ;load Flyable Maps bit high into a bit 0,a ;town 1? jr z,7CEE ;jump to town 2 if not ld (hl),00 ;otherwise, load town 1 into hl and increase inc hl 7CEE: [TOWN2] bit 1,a ;town 2? jr z,7Cf5 ;jump to town3 if not ld (hl),01 ;otherwise, load town 2 into hl and increase inc hl 7CF5: [TOWN3] bit 2,a ;town 3? jr z,7CFC ;jump to town4 if not ld (hl),02 ;otherwise, load town 3 into hl and increase inc hl ;the following town is the first one that is out of place when compared to the original map order ;as you can see, I am checking for bit 0 of d70c. This corresponds to a map id of $08 ;The original function would be checking bit 3 of d70b, which corresponds to map id of $08 7CFC: [TOWN4] ld a,(d70c) ;load Flyable Maps bit low into a bit 0,a ;town 4? jr z,7D06 ;jump to town5 if not ld (hl),08 ;otherwise, load town 4 into hl and increase inc hl 7D06: [TOWN5] bit 2,a ;town 5? jr z,7D0D ;jump to town4 if not ld (hl),0a ;otherwise, load town 5 into hl and increase inc hl ;starting here, the map bits are now located back in byte D70B, so I have to load that back into a 7D0D: [TOWN6] ld a,(d70b) ;load Flyable Maps bit high into a bit 4,a ;town 6? jr z,7D17 ;jump to town7 if not ld (hl),04 ;otherwise, load town 6 into hl and increase inc hl ;This is the town I added (originally Route 16, map ID $1b) ;this location bit is never checked in the original routine, and is never set unless you change the script that sets the bits 7D17: [TOWN7] ld a,(d70c) ;load Flyable Maps bit low into a bit 3,a ;town 7? jr z,7D21 ;jump to town8 if not ld (hl),1b ;otherwise, load town 7 into hl and increase inc hl ;again, switch back to the first byte of the flyable maps 7D21: [TOWN8] ld a,(d70b) ;load Flyable Maps bit high into a bit 5,a ;town 8? jr z,7D2B ;jump to town9 if not ld (hl),05 ;otherwise, load town 8 into hl and increase inc hl 7D2B: [TOWN9] bit 6,a ;town 9? jr z,7D32 ;jump to town10 if not ld (hl),06 ;otherwise, load town 9 into hl and increase inc hl 7D32: [TOWN10] bit 3,a ;town 10? jr z,7D39 ;jump to town11 if not ld (hl),03 ;otherwise, load town10 into hl and increase inc hl 7D39: [TOWN11] bit 7,a ;town 11? jr z,7D40 ;jump to town12 if not ld (hl),07 ;otherwise, load town11 into hl and increase inc hl ;Unless you added a town, there should only be 11!!! 7D40: [TOWN12] ld a,(d70c) ;load Flyable Maps bit low into a bit 1,a ;town 12? ret z ;return if not ld (hl),09 ;otherwise, load town 12 into hl and increase ret
It's not necessarily the most efficient script, but it gets the job done. I hope that all made sense!
Last edited by pokeglitch (2013-03-29 04:45:44)
The code that calls the location of the map information starts at 1C:50CD:
1C:50CD: ld hl,C3A0 ;this is the top left corner of the visible screen 1C:50D0: ld de,5100 ;this is the start of the map table
If you want to be careful about not overwriting anything important, you can repoint it by replacing line at 1C:50D0 with
as long as the new map is in the same bank. There is more than enough free space at the end of bank 1C to fit your map.
BUT, you probably don't have to.
The map takes up the space from 1C:5100 to 1C:51AA. You can see this is the case because there is a 00 at 1C:51AA, and if you look at line 1C:50D3, the map is drawn until it reaches a 00
1C:50D3: ld a,(de) ;this loads the next byte of map information 1C:50D4: and a ;the AND operation always returns true unless a is 00, in which case it will return a 0 1C:50D5: jr z,50E9 ;if it returned a 0, then exit the loop
Last edited by pokeglitch (2013-03-29 04:44:15)
16-bit values are usually read in reverse. You would put in 90 6E in a hex editor.
You wanted to put it in at 0x710d1.
Last edited by comet (2013-03-29 21:45:41)
Looks, glad I could help. Did you manage to change the order of towns when viewing the town map or flying?
it will be simple to add the map to when you are navigating through the town map, but adding it to the map when flying might be tricky. In the example I posted for reodering the towns when flying, I added a new town, but I also had to expand the field in the RAM that the game reads from when navigating the map. So far, it hasn't caused any issues,but it might have overwritten something important. Still not sure.
but if you do do that, you also want to do the following:
at 1c:5068 [$071068] replace: ld hl,cd49 with: ld hl,cd4a ;one town was added, so the field got expanded by one byte
That line of code gets run when you reach you are at the beginning of the map and want try to move up the list. Since you are at the begining, it repoints you to the end and then moves up the list from there. This change repoints it to one byte further, because the list is one byte longer.
Last edited by pokeglitch (2013-03-30 16:14:40)
I simply had to replace $0B with $0C in the original location of the flight towns order located at 1c:5068, but I've got a very small bug that is identical of one of Pokemon Brown:
When I scroll the locations, if I return back with the reversed order (Pallet town, saffron, indigo etc.) the new town isn't showed, it is showed only if you scroll the locations in the right order.
PS: The Town Map location Order changes worked, thanks a lot.
I left this forum.