ruby_gs 0.1.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|