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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0da9e8c8ef97844c3eaecfca69c85fe1e0d953fc
4
- data.tar.gz: 81989859170a74f0c87f5c2fa869b888504a425f
3
+ metadata.gz: 86a1e014deb81957ade947e6c0e4e92fbb61ece9
4
+ data.tar.gz: 034dc05e5066e440ea4c40b2536807a3d915f8d5
5
5
  SHA512:
6
- metadata.gz: 42f4bb0288199f232d25a50d5a78818321cc3689ba33f301de98c2f064db30befbc99b9876ec64437b69aaf2e6fa74a159913329ba9296e476bac6242a032ae1
7
- data.tar.gz: 5f818eab58cec5f4926262015351143a1a3f9c96446540d0b527025a3bb18b3d4425a62ef2e5a132f1d150a8583da70cbe4413c072525df8779b2929dcf1febe
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
 
@@ -1,2 +1,8 @@
1
1
  require "ruby_gs/version"
2
2
  require "ruby_gs/save_file_reader"
3
+
4
+ ##
5
+ # Contains all of the structures and classes necessary for viewing and editing Pokemon Gold/Silver/Crystal save files.
6
+ module RubyGS
7
+
8
+ end
@@ -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
- attr_accessor :save, :gs, :filename
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
- @save.team.pokemon[slot].happiness = egg_cycles
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
- @save.team.pokemon[slot].happiness = 20
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 :current_box
35
- array :unused8, :type => :uint8, :initial_length => 0x2
36
- array :box_names, :type => :uint8, :initial_length => 126
37
- array :unused9, :type => :uint8, :initial_length => 0xE5
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 => 0x16
40
- array :dex_owned, :type => :uint8, :initial_length => 32
41
- array :dex_seen, :type => :uint8, :initial_length => 32
42
- array :footer, :type => :uint8, :initial_length => 0x559F
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
@@ -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
@@ -1,3 +1,3 @@
1
1
  module RubyGS
2
- VERSION = "0.1.2"
2
+ VERSION = "0.2.0"
3
3
  end
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.1.2
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-06 00:00:00.000000000 Z
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