ruby_gs 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +2 -1
- data/lib/ruby_gs.rb +6 -0
- data/lib/ruby_gs/save_file_reader.rb +30 -3
- data/lib/ruby_gs/structs/box_name.rb +23 -0
- data/lib/ruby_gs/structs/party_pokemon.rb +6 -0
- data/lib/ruby_gs/structs/pc_box.rb +22 -0
- data/lib/ruby_gs/structs/pc_pokemon.rb +38 -0
- data/lib/ruby_gs/structs/pokedex_data.rb +37 -0
- data/lib/ruby_gs/structs/save_file.rb +18 -8
- data/lib/ruby_gs/structs/team.rb +6 -0
- data/lib/ruby_gs/version.rb +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 86a1e014deb81957ade947e6c0e4e92fbb61ece9
|
|
4
|
+
data.tar.gz: 034dc05e5066e440ea4c40b2536807a3d915f8d5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0c1e4c3ad975fdd15928f17f1d9330fde3d626e53ab8e11b91b6b5d3273151ce9a36301ddb7da8268dd0a961578031fec2399c2eeb656a493f3cd48df2253b6f
|
|
7
|
+
data.tar.gz: 560afb309a8d9f174a043eb78448ea3416821c22cc9a594968a08540e12154ed4598152c5107d14cfe42a4342777eb461339d5774bbec03b2f376dcab3f2146b
|
data/README.md
CHANGED
|
@@ -35,6 +35,7 @@ frames = 20
|
|
|
35
35
|
saved_game.time_played = [hours, minutes, seconds, frames] # The amount of frames is not visible to the player and is rather inconsequential in general.
|
|
36
36
|
|
|
37
37
|
saved_game.item_pocket[3].kind = 1 # Change the 3rd item in our Item Pocket to a Master Ball.
|
|
38
|
+
|
|
38
39
|
saved_game.item_pocket[3].amount = 255 # Gotta make sure we have enough for our journey.
|
|
39
40
|
|
|
40
41
|
saved_game.write # This will write your changes directly to the same save file you opened initially.
|
|
@@ -49,7 +50,7 @@ saved_game.write "path/to/other/save/file.sav" # This will write your changes to
|
|
|
49
50
|
|
|
50
51
|
##TODO:
|
|
51
52
|
+ Support for Crystal.
|
|
52
|
-
+ Major refactoring
|
|
53
|
+
+ ~~Major refactoring.~~
|
|
53
54
|
+ Player Location editing.
|
|
54
55
|
+ Event Flag editing (and possibly documenting the purpose of each flag).
|
|
55
56
|
|
data/lib/ruby_gs.rb
CHANGED
|
@@ -5,12 +5,18 @@ module RubyGS
|
|
|
5
5
|
|
|
6
6
|
class SaveFileReader
|
|
7
7
|
|
|
8
|
+
|
|
9
|
+
##
|
|
10
|
+
# Reads a .sav file and builds a SaveFile object from its data.
|
|
8
11
|
def self.read(file)
|
|
9
12
|
raise "filename cannot be nil" if not file
|
|
10
13
|
SaveFile.new SaveFileGS.read(File.open(file,"r")), file, true # TODO: Detect whether save belongs to Gold/Silver or Crystal
|
|
11
14
|
end
|
|
12
15
|
|
|
16
|
+
##
|
|
17
|
+
# DEPRECATED: Calculates the checksum values for both regions within a save file.
|
|
13
18
|
def self.calc_checksums(file)
|
|
19
|
+
warn "[DEPRECATION] SaveFileReader::calc_checksums is deprecated. Please use SaveFileReader::correct_checksums! instead."
|
|
14
20
|
file.pos = 0
|
|
15
21
|
content = file.read.split("").map(&:ord)
|
|
16
22
|
c1 = content[0x2009..0x2D68].reduce(&:+)
|
|
@@ -19,6 +25,8 @@ module RubyGS
|
|
|
19
25
|
[c1.to_s(16),c2.to_s(16)]
|
|
20
26
|
end
|
|
21
27
|
|
|
28
|
+
##
|
|
29
|
+
# Calculates the checksum values within a save file and writes them to the save file.
|
|
22
30
|
def self.correct_checksums!(file)
|
|
23
31
|
file.pos = 0
|
|
24
32
|
content = file.read.split("").map(&:ord)
|
|
@@ -36,9 +44,18 @@ module RubyGS
|
|
|
36
44
|
|
|
37
45
|
end
|
|
38
46
|
|
|
47
|
+
##
|
|
48
|
+
# Represents a Gold/Silver/Crystal save file.
|
|
49
|
+
#
|
|
50
|
+
# @gs is set to true if the save file is from Gold/Silver and false otherwise.
|
|
51
|
+
#
|
|
52
|
+
# @filename is a string of the filename that the save file was originally read from.
|
|
53
|
+
#
|
|
54
|
+
# @save is the structure containing the save file's data and is delegated to SaveFile.
|
|
39
55
|
class SaveFile
|
|
40
56
|
|
|
41
|
-
|
|
57
|
+
attr_accessor :save
|
|
58
|
+
attr_reader :gs, :filename
|
|
42
59
|
|
|
43
60
|
def initialize save, filename, gs
|
|
44
61
|
@save, @gs, @filename = save, gs, filename
|
|
@@ -53,27 +70,37 @@ module RubyGS
|
|
|
53
70
|
end
|
|
54
71
|
end
|
|
55
72
|
|
|
73
|
+
##
|
|
74
|
+
# Writes the save structure to file.
|
|
75
|
+
#
|
|
76
|
+
# If loc is not provided, it will write directly to the original file.
|
|
56
77
|
def write(loc = @filename)
|
|
57
78
|
@save.write(File.open(loc, "wb"))
|
|
58
79
|
verify_checksums
|
|
59
80
|
end
|
|
60
81
|
|
|
82
|
+
##
|
|
83
|
+
# A convenience method for setting the species of a PartyPokemon in its structure and in the Team species_list.
|
|
61
84
|
def set_team_species slot, species
|
|
62
85
|
return if !(0..5).include? slot
|
|
63
86
|
@save.team.pokemon[slot].species.assign species
|
|
64
87
|
@save.team.species_list[slot].assign species
|
|
65
88
|
end
|
|
66
89
|
|
|
90
|
+
##
|
|
91
|
+
# A convenience method for turning a PartyPokemon into an Egg and setting the steps required to hatch it.
|
|
67
92
|
def set_team_egg slot, egg_cycles
|
|
68
93
|
raise "slot index must be between 0 and 5, inclusive" if !(0..5).include? slot
|
|
69
94
|
@save.team.species_list[slot] = 0xFD
|
|
70
|
-
|
|
95
|
+
@save.team.pokemon[slot].happiness = egg_cycles
|
|
71
96
|
end
|
|
72
97
|
|
|
98
|
+
##
|
|
99
|
+
# A convenience method for turning an Egg into a Pokemon.
|
|
73
100
|
def hatch_team_egg slot
|
|
74
101
|
raise "slot index must be between 0 and 5, inclusive" if !(0..5).include? slot
|
|
75
102
|
@save.team.species_list[slot].assign @save.team.pokemon[slot].species
|
|
76
|
-
|
|
103
|
+
@save.team.pokemon[slot].happiness = 20
|
|
77
104
|
end
|
|
78
105
|
|
|
79
106
|
def method_missing(sym, *args, &block)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
require_relative "../text_gs"
|
|
2
|
+
|
|
3
|
+
module RubyGS
|
|
4
|
+
|
|
5
|
+
##
|
|
6
|
+
# A String representing the name of a PC Box.
|
|
7
|
+
#
|
|
8
|
+
# It can only contain 8 visible characters, the 9th being a terminator.
|
|
9
|
+
#
|
|
10
|
+
class BoxName < BinData::Primitive
|
|
11
|
+
string :val, :length => 9, :pad_byte => 'P'
|
|
12
|
+
|
|
13
|
+
def get
|
|
14
|
+
TextGS.decode self.val[0..7]
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def set value
|
|
18
|
+
self.val = TextGS.encode value
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end
|
|
@@ -4,6 +4,12 @@ require_relative "caught_data"
|
|
|
4
4
|
|
|
5
5
|
module RubyGS
|
|
6
6
|
|
|
7
|
+
##
|
|
8
|
+
# Represents a Pokemon within your current party.
|
|
9
|
+
#
|
|
10
|
+
# Contains 16 more bytes of data pertaining to combat stats than a PC Pokemon structure.
|
|
11
|
+
# These are recalculated upon withdrawal from the PC.
|
|
12
|
+
#
|
|
7
13
|
class PartyPokemon < BinData::Record
|
|
8
14
|
endian :big
|
|
9
15
|
uint8 :species
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
require_relative "name_text"
|
|
2
|
+
require_relative "pc_pokemon"
|
|
3
|
+
|
|
4
|
+
module RubyGS
|
|
5
|
+
|
|
6
|
+
##
|
|
7
|
+
# Represents a Pokemon Box inside of the PC.
|
|
8
|
+
#
|
|
9
|
+
# It has an identical structure to the Team structure, but is much longer in length.
|
|
10
|
+
#
|
|
11
|
+
class PCBox < BinData::Record
|
|
12
|
+
endian :big
|
|
13
|
+
uint8 :unused
|
|
14
|
+
uint8 :amount
|
|
15
|
+
array :species_list, :type => :uint8, :initial_length => 21
|
|
16
|
+
array :pokemon, :type => :pc_pokemon, :initial_length => 20
|
|
17
|
+
array :ot_name, :type => :name_text, :initial_length => 20
|
|
18
|
+
array :name, :type => :name_text, :initial_length => 20
|
|
19
|
+
uint8 :unused2
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
require_relative "iv_data"
|
|
2
|
+
require_relative "pp_data"
|
|
3
|
+
require_relative "caught_data"
|
|
4
|
+
|
|
5
|
+
module RubyGS
|
|
6
|
+
|
|
7
|
+
##
|
|
8
|
+
# Represents the data describing a Pokemon stored within a PC Box.
|
|
9
|
+
#
|
|
10
|
+
# This is a stripped down version of the PartyPokemon structure as it lacks data on current combat stats.
|
|
11
|
+
#
|
|
12
|
+
class PCPokemon < BinData::Record
|
|
13
|
+
endian :big
|
|
14
|
+
uint8 :species
|
|
15
|
+
uint8 :held_item
|
|
16
|
+
uint8 :move_1
|
|
17
|
+
uint8 :move_2
|
|
18
|
+
uint8 :move_3
|
|
19
|
+
uint8 :move_4
|
|
20
|
+
uint16 :ot_id
|
|
21
|
+
bit :exp, :nbits => 24
|
|
22
|
+
uint16 :hp_ev
|
|
23
|
+
uint16 :attack_ev
|
|
24
|
+
uint16 :defense_ev
|
|
25
|
+
uint16 :speed_ev
|
|
26
|
+
uint16 :special_ev
|
|
27
|
+
iv_data :iv
|
|
28
|
+
pp_data :pp_1
|
|
29
|
+
pp_data :pp_2
|
|
30
|
+
pp_data :pp_3
|
|
31
|
+
pp_data :pp_4
|
|
32
|
+
uint8 :happiness
|
|
33
|
+
uint8 :pokerus
|
|
34
|
+
caught_data :caught # Crystal only; Filled with 0s otherwise.
|
|
35
|
+
uint8 :level
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
module RubyGS
|
|
4
|
+
|
|
5
|
+
##
|
|
6
|
+
# Represents a Pokemon who has been seen or caught.
|
|
7
|
+
FOUND = 1
|
|
8
|
+
##
|
|
9
|
+
# Represents a Pokemon who has not yet been seen or caught.
|
|
10
|
+
NOT_FOUND = 0
|
|
11
|
+
|
|
12
|
+
class PokedexArray < BinData::Array
|
|
13
|
+
|
|
14
|
+
def [] i
|
|
15
|
+
return @element_list[real_index(i)].snapshot
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def []= i, v
|
|
19
|
+
@element_list[real_index(i)].assign v
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def real_index n
|
|
25
|
+
return n if n % 8 == 0
|
|
26
|
+
((n / 8).floor+2)*8 - (n % 8)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
class PokedexData < BinData::Record
|
|
32
|
+
endian :big
|
|
33
|
+
pokedex_array :species, :type => :bit1, :initial_length => 251
|
|
34
|
+
array :unknown, :type => :bit1, :initial_length => 5
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
end
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
require_relative "team"
|
|
2
|
+
require_relative "pc_box"
|
|
2
3
|
require_relative "name_text"
|
|
4
|
+
require_relative "box_name"
|
|
3
5
|
require_relative "item_entry"
|
|
6
|
+
require_relative "pokedex_data"
|
|
4
7
|
|
|
5
8
|
module RubyGS
|
|
6
9
|
|
|
10
|
+
##
|
|
11
|
+
# Represents the structure and data of a Gold/Silver Pokemon cartridge SRAM
|
|
12
|
+
#
|
|
7
13
|
class SaveFileGS < BinData::Record
|
|
8
14
|
endian :big
|
|
9
15
|
array :unused, :type => :uint8, :initial_length => 0x2000
|
|
@@ -31,15 +37,19 @@ module RubyGS
|
|
|
31
37
|
array :ball_pocket, :type => :uint8, :initial_length => 26
|
|
32
38
|
array :pc_items, :type => :uint8, :initial_length => 102
|
|
33
39
|
array :unused7, :type => :uint8, :initial_length => 0x240
|
|
34
|
-
uint8 :
|
|
35
|
-
array :unused8, :type => :uint8, :initial_length =>
|
|
36
|
-
array :box_names, :type => :
|
|
37
|
-
array :unused9, :type => :uint8, :initial_length =>
|
|
40
|
+
uint8 :current_box_index
|
|
41
|
+
array :unused8, :type => :uint8, :initial_length => 0x3
|
|
42
|
+
array :box_names, :type => :box_name, :initial_length => 14
|
|
43
|
+
array :unused9, :type => :uint8, :initial_length => 0xE4
|
|
38
44
|
team :team
|
|
39
|
-
array :unused10, :type => :uint8, :initial_length =>
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
45
|
+
array :unused10, :type => :uint8, :initial_length => 0x15
|
|
46
|
+
pokedex_data :dex_owned
|
|
47
|
+
pokedex_data :dex_seen
|
|
48
|
+
array :unused11, :type => :uint8, :initial_length => 0x2E0
|
|
49
|
+
pc_box :current_box
|
|
50
|
+
array :unused12, :type => :uint8, :initial_length => 0xE44
|
|
51
|
+
array :pc_box, :type => :pc_box, :initial_length => 14
|
|
52
|
+
rest :rest
|
|
43
53
|
end
|
|
44
54
|
|
|
45
55
|
end
|
data/lib/ruby_gs/structs/team.rb
CHANGED
|
@@ -3,6 +3,12 @@ require_relative "party_pokemon"
|
|
|
3
3
|
|
|
4
4
|
module RubyGS
|
|
5
5
|
|
|
6
|
+
##
|
|
7
|
+
# Represents your party of Pokemon.
|
|
8
|
+
#
|
|
9
|
+
# Note that the species, nickname, and original trainer name of each Pokemon is stored separately
|
|
10
|
+
# from their respective structures, instead being stored directly within the Team structure.
|
|
11
|
+
#
|
|
6
12
|
class Team < BinData::Record
|
|
7
13
|
endian :big
|
|
8
14
|
uint8 :unused
|
data/lib/ruby_gs/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ruby_gs
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Conrad King
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2015-12-
|
|
11
|
+
date: 2015-12-12 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bindata
|
|
@@ -73,11 +73,15 @@ files:
|
|
|
73
73
|
- lib/ruby_gs.rb
|
|
74
74
|
- lib/ruby_gs/save_file_reader.rb
|
|
75
75
|
- lib/ruby_gs/structs.rb
|
|
76
|
+
- lib/ruby_gs/structs/box_name.rb
|
|
76
77
|
- lib/ruby_gs/structs/caught_data.rb
|
|
77
78
|
- lib/ruby_gs/structs/item_entry.rb
|
|
78
79
|
- lib/ruby_gs/structs/iv_data.rb
|
|
79
80
|
- lib/ruby_gs/structs/name_text.rb
|
|
80
81
|
- lib/ruby_gs/structs/party_pokemon.rb
|
|
82
|
+
- lib/ruby_gs/structs/pc_box.rb
|
|
83
|
+
- lib/ruby_gs/structs/pc_pokemon.rb
|
|
84
|
+
- lib/ruby_gs/structs/pokedex_data.rb
|
|
81
85
|
- lib/ruby_gs/structs/pp_data.rb
|
|
82
86
|
- lib/ruby_gs/structs/save_file.rb
|
|
83
87
|
- lib/ruby_gs/structs/team.rb
|