Pokémon Essentials BES uses a text-to-binary compilation system to load game data efficiently. PBS (Pokémon Script) files are human-readable text files that get compiled into binary .dat files for fast runtime access.
The pbRgssOpen function handles reading from both regular files and encrypted RGSSAD archives:
def pbRgssOpen(filename, mode="rb") # Try to open from encrypted archive first if safeExists?("Game.rgssad") || safeExists?("Game.rgss2a") # Read from archive else # Read from regular file File.open(filename, mode) {|f| yield f } endend
In debug mode, files are read directly from disk. In release builds, they’re read from encrypted archives.
def csvfield!(str) ret="" str.sub!(/^\s*/,"") # Strip leading whitespace if str[0,1]=="\"" # Quoted field str[0,1]="" escaped=false fieldbytes=0 str.scan(/./) do |s| fieldbytes+=s.length break if s=="\"" && !escaped if s=="\\" && !escaped escaped=true else ret+=s escaped=false end end str[0,fieldbytes]="" else # Unquoted field if str[/,/] str[0,str.length]=$~.post_match ret=$~.pre_match else ret=str.clone str[0,str.length]="" end ret.gsub!(/\s+$/,"") # Strip trailing whitespace end return retend
def pbCheckByte(x,valuename) if x<0 || x>255 raise _INTL("The value \"{1}\" must be from 0 through 255, got {2}", valuename,x) endenddef pbCheckWord(x,valuename) if x<0 || x>65535 raise _INTL("The value \"{1}\" must be from 0 through 65535, got {2}", valuename,x) endenddef pbCheckSignedByte(x,valuename) if x<-128 || x>127 raise _INTL("The value \"{1}\" must be from -128 through 127, got {2}", valuename,x) endend
Enumerated values (like types, abilities) are converted to constants:
def checkEnumField(ret,enumer) if enumer.is_a?(Module) # Check if constant exists in module if ret=="" || !enumer.const_defined?(ret.to_sym) raise _INTL("Undefined value {1} in {2}",ret,enumer.name) end return enumer.const_get(ret.to_sym) elsif enumer.is_a?(Array) # Find index in array idx=findIndex(enumer){|item| ret==item} if idx<0 raise _INTL("Undefined value {1} (expected one of: {2})", ret,enumer.inspect) end return idx endend
Example:
# Parse "FIRE" to PBTypes::FIRE constanttype = csvEnumField!("FIRE", PBTypes, "Type1", section)# Returns: 10 (the numeric ID for FIRE type)
Some data uses serial record format for variable-length entries:
def readSerialRecords(filename) ret=[] return ret if !pbRgssExists?(filename) pbRgssOpen(filename,"rb"){|file| numrec=file.fgetdw>>3 curpos=0 for i in 0...numrec file.pos=curpos offset=file.fgetdw length=file.fgetdw record=SerialRecord.decode(file,offset,length) ret.push(record) curpos+=8 end } return retend
Serial Record Format
Serial records store variable-length data efficiently: