diff --git a/.classpath b/.classpath
new file mode 100755
index 000000000..07ca123c6
--- /dev/null
+++ b/.classpath
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/.gitignore b/.gitignore
new file mode 100755
index 000000000..608358cd8
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,23 @@
+*.NDS
+*.nds
+*.GB
+*.gb
+*.GBC
+*.gbc
+*.GBA
+*.gba
+*.RNDP
+*.rndp
+tmp_*
+*.sgm
+*.sav
+*.rtc
+*.sgb
+*.sn*
+*.rar
+*.zip
+config.ini
+*.pkm
+error_*.txt
+src/com/dabomstew/pkrandom/localtests
+bin
diff --git a/.project b/.project
new file mode 100755
index 000000000..a5742bed3
--- /dev/null
+++ b/.project
@@ -0,0 +1,17 @@
+
+
+ universal-pokemon-randomizer
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs
new file mode 100755
index 000000000..4824b8026
--- /dev/null
+++ b/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+encoding/=UTF-8
diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs
new file mode 100755
index 000000000..27ae71be0
--- /dev/null
+++ b/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,291 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=false
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
+org.eclipse.jdt.core.formatter.comment.line_length=80
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=80
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=tab
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_on_off_tags=true
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
diff --git a/.settings/org.eclipse.jdt.ui.prefs b/.settings/org.eclipse.jdt.ui.prefs
new file mode 100755
index 000000000..fc6d66ce4
--- /dev/null
+++ b/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,3 @@
+eclipse.preferences.version=1
+formatter_profile=_PokeRandomizer
+formatter_settings_version=12
diff --git a/README.md b/README.md
new file mode 100755
index 000000000..e69de29bb
diff --git a/settings/balanced.rnqs b/settings/balanced.rnqs
new file mode 100755
index 000000000..980a7cd48
--- /dev/null
+++ b/settings/balanced.rnqs
@@ -0,0 +1 @@
+ TBBhkCO4B8QH0AQLHIAICFBQCBAAAAAAAAAAAE1Bva2Vtb24gQmxhY2sgMiAoVSnuSji4ZSd9HahDq+5llTzy
\ No newline at end of file
diff --git a/settings/classic.rnqs b/settings/classic.rnqs
new file mode 100755
index 000000000..75f3d4782
--- /dev/null
+++ b/settings/classic.rnqs
@@ -0,0 +1 @@
+ TBBgkCO4B8QH0AQQgJAACFBRABAAAAAAAAAAAE1Bva2Vtb24gQmxhY2sgMiAoVSkNT2VRZSd9HahDq+5llTzy
\ No newline at end of file
diff --git a/settings/randomizer_race.rnqs b/settings/randomizer_race.rnqs
new file mode 100755
index 000000000..f9bb458b9
--- /dev/null
+++ b/settings/randomizer_race.rnqs
@@ -0,0 +1 @@
+ T5ph0Eu4B8QH0ARGGJAgECQk9BAAAAAAAAAAAE1Bva2Vtb24gQmxhY2sgMiAoVSmJEgBbZSd9HahDq+5llTzy
\ No newline at end of file
diff --git a/settings/super_randomizer_race.rnqs b/settings/super_randomizer_race.rnqs
new file mode 100755
index 000000000..95d1b8c70
--- /dev/null
+++ b/settings/super_randomizer_race.rnqs
@@ -0,0 +1 @@
+ T5qJyEu4B8QH0ARGGJAgECQk9AQAAAAAAAAAAE1Bva2Vtb24gQmxhY2sgMiAoVSkdR0elZSd9HahDq+5llTzy
\ No newline at end of file
diff --git a/settings/trainers_only.rnqs b/settings/trainers_only.rnqs
new file mode 100755
index 000000000..ff9096291
--- /dev/null
+++ b/settings/trainers_only.rnqs
@@ -0,0 +1 @@
+ TwBgEBO4B8QH0AQTdRAABFBRABAAAAAAAAAAAE1Bva2Vtb24gQmxhY2sgMiAoVSklePsNZSd9HahDq+5llTzy
\ No newline at end of file
diff --git a/src/com/dabomstew/pkrandom/CodeTweaks.java b/src/com/dabomstew/pkrandom/CodeTweaks.java
new file mode 100755
index 000000000..3b8d7707f
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/CodeTweaks.java
@@ -0,0 +1,9 @@
+package com.dabomstew.pkrandom;
+
+public class CodeTweaks {
+
+ public static final int BW_EXP_PATCH = 1;
+ public static final int NERF_X_ACCURACY = 2;
+ public static final int FIX_CRIT_RATE = 4;
+
+}
diff --git a/src/com/dabomstew/pkrandom/FileFunctions.java b/src/com/dabomstew/pkrandom/FileFunctions.java
new file mode 100755
index 000000000..5e2b69c64
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/FileFunctions.java
@@ -0,0 +1,177 @@
+package com.dabomstew.pkrandom;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.List;
+
+public class FileFunctions {
+
+ public static File fixFilename(File original, String defaultExtension) {
+ return fixFilename(original, defaultExtension, null);
+ }
+
+ // Behavior:
+ // if file has no extension, add defaultExtension
+ // if there are banned extensions & file has a banned extension, replace
+ // with defaultExtension
+ // else, leave as is
+ public static File fixFilename(File original, String defaultExtension,
+ List bannedExtensions) {
+ String filename = original.getName();
+ if (filename.lastIndexOf('.') >= filename.length() - 5
+ && filename.lastIndexOf('.') != filename.length() - 1
+ && filename.length() > 4 && filename.lastIndexOf('.') != -1) {
+ // valid extension, read it off
+ String ext = filename.substring(filename.lastIndexOf('.') + 1)
+ .toLowerCase();
+ if (bannedExtensions != null && bannedExtensions.contains(ext)) {
+ // replace with default
+ filename = filename.substring(0, filename.lastIndexOf('.') + 1)
+ + defaultExtension;
+ }
+ // else no change
+ } else {
+ // add extension
+ filename += "." + defaultExtension;
+ }
+ return new File(original.getAbsolutePath().replace(original.getName(),
+ "")
+ + filename);
+ }
+
+ private static List overrideFiles = Arrays.asList(new String[] {
+ "trainerclasses.txt", "trainernames.txt", "nicknames.txt" });
+
+ public static boolean configExists(String filename) {
+ if (overrideFiles.contains(filename)) {
+ File fh = new File("./" + filename);
+ if (fh.exists() && fh.canRead()) {
+ return true;
+ }
+ }
+ return FileFunctions.class
+ .getResource("/com/dabomstew/pkrandom/config/" + filename) != null;
+ }
+
+ public static InputStream openConfig(String filename)
+ throws FileNotFoundException {
+ if (overrideFiles.contains(filename)) {
+ File fh = new File("./" + filename);
+ if (fh.exists() && fh.canRead()) {
+ return new FileInputStream(fh);
+ }
+ }
+ return FileFunctions.class
+ .getResourceAsStream("/com/dabomstew/pkrandom/config/"
+ + filename);
+ }
+
+ public static byte[] getCodeTweakFile(String filename) throws IOException {
+ InputStream is = FileFunctions.class
+ .getResourceAsStream("/com/dabomstew/pkrandom/patches/"
+ + filename);
+ byte[] buf = new byte[is.available()];
+ is.read(buf);
+ is.close();
+ return buf;
+ }
+
+ public static byte[] downloadFile(String url) throws IOException {
+ BufferedInputStream in = new BufferedInputStream(
+ new URL(url).openStream());
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ byte[] buf = new byte[1024];
+ int count;
+ while ((count = in.read(buf, 0, 1024)) != -1) {
+ out.write(buf, 0, count);
+ }
+ in.close();
+ byte[] output = out.toByteArray();
+ return output;
+ }
+
+ public static void applyPatch(byte[] rom, String patchName)
+ throws IOException {
+ byte[] patch = getCodeTweakFile(patchName + ".ips");
+ // check sig
+ int patchlen = patch.length;
+ if (patchlen < 8 || patch[0] != 'P' || patch[1] != 'A'
+ || patch[2] != 'T' || patch[3] != 'C' || patch[4] != 'H') {
+ System.out.println("not a valid IPS file");
+ return;
+ }
+
+ // records
+ int offset = 5;
+ while (offset + 2 < patchlen) {
+ int writeOffset = readIPSOffset(patch, offset);
+ if (writeOffset == 0x454f46) {
+ // eof, done
+ System.out.println("patch successful");
+ return;
+ }
+ offset += 3;
+ if (offset + 1 >= patchlen) {
+ // error
+ System.out.println("abrupt ending to IPS file, entry cut off before size");
+ return;
+ }
+ int size = readIPSSize(patch, offset);
+ offset += 2;
+ if (size == 0) {
+ // RLE
+ if (offset + 1 >= patchlen) {
+ // error
+ System.out.println("abrupt ending to IPS file, entry cut off before RLE size");
+ return;
+ }
+ int rleSize = readIPSSize(patch, offset);
+ if(writeOffset + rleSize > rom.length) {
+ // error
+ System.out.println("trying to patch data past the end of the ROM file");
+ return;
+ }
+ offset += 2;
+ if (offset >= patchlen) {
+ // error
+ System.out.println("abrupt ending to IPS file, entry cut off before RLE byte");
+ return;
+ }
+ byte rleByte = patch[offset++];
+ for (int i = writeOffset; i < writeOffset + rleSize; i++) {
+ rom[i] = rleByte;
+ }
+ } else {
+ if (offset + size > patchlen) {
+ // error
+ System.out.println("abrupt ending to IPS file, entry cut off before end of data block");
+ return;
+ }
+ if(writeOffset + size > rom.length) {
+ // error
+ System.out.println("trying to patch data past the end of the ROM file");
+ return;
+ }
+ System.arraycopy(patch, offset, rom, writeOffset, size);
+ offset += size;
+ }
+ }
+ System.out.println("improperly terminated IPS file");
+ }
+
+ private static int readIPSOffset(byte[] data, int offset) {
+ return ((data[offset] & 0xFF) << 16) | ((data[offset + 1] & 0xFF) << 8)
+ | (data[offset + 2] & 0xFF);
+ }
+
+ private static int readIPSSize(byte[] data, int offset) {
+ return ((data[offset] & 0xFF) << 8) | (data[offset + 1] & 0xFF);
+ }
+}
diff --git a/src/com/dabomstew/pkrandom/RandomSource.java b/src/com/dabomstew/pkrandom/RandomSource.java
new file mode 100755
index 000000000..25364d9e2
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/RandomSource.java
@@ -0,0 +1,162 @@
+package com.dabomstew.pkrandom;
+
+/*----------------------------------------------------------------------------*/
+/*-- RandomSource.java - functions as a centralized source of randomness --*/
+/*-- to allow the same seed to produce the same random --*/
+/*-- ROM consistently. --*/
+/*-- --*/
+/*-- Part of "Universal Pokemon Randomizer" by Dabomstew --*/
+/*-- Pokemon and any associated names and the like are --*/
+/*-- trademark and (C) Nintendo 1996-2012. --*/
+/*-- --*/
+/*-- The custom code written here is licensed under the terms of the GPL: --*/
+/*-- --*/
+/*-- This program is free software: you can redistribute it and/or modify --*/
+/*-- it under the terms of the GNU General Public License as published by --*/
+/*-- the Free Software Foundation, either version 3 of the License, or --*/
+/*-- (at your option) any later version. --*/
+/*-- --*/
+/*-- This program is distributed in the hope that it will be useful, --*/
+/*-- but WITHOUT ANY WARRANTY; without even the implied warranty of --*/
+/*-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --*/
+/*-- GNU General Public License for more details. --*/
+/*-- --*/
+/*-- You should have received a copy of the GNU General Public License --*/
+/*-- along with this program. If not, see . --*/
+/*----------------------------------------------------------------------------*/
+
+import java.security.SecureRandom;
+import java.util.Random;
+
+public class RandomSource {
+
+ private static Random source = new Random();
+ private static int calls = 0;
+ private static Random instance = new RandomSourceInstance();
+
+ public static void reset() {
+ source = new Random();
+ calls = 0;
+ }
+
+ public static void seed(long seed) {
+ source.setSeed(seed);
+ calls = 0;
+ }
+
+ public static double random() {
+ calls++;
+ return source.nextDouble();
+ }
+
+ public static int nextInt(int size) {
+ calls++;
+ return source.nextInt(size);
+ }
+
+ public static void nextBytes(byte[] bytes) {
+ calls++;
+ source.nextBytes(bytes);
+ }
+
+ public static int nextInt() {
+ calls++;
+ return source.nextInt();
+ }
+
+ public static long nextLong() {
+ calls++;
+ return source.nextLong();
+ }
+
+ public static boolean nextBoolean() {
+ calls++;
+ return source.nextBoolean();
+ }
+
+ public static float nextFloat() {
+ calls++;
+ return source.nextFloat();
+ }
+
+ public static double nextDouble() {
+ calls++;
+ return source.nextDouble();
+ }
+
+ public static synchronized double nextGaussian() {
+ calls++;
+ return source.nextGaussian();
+ }
+
+ public static long pickSeed() {
+ long value = 0;
+ byte[] by = SecureRandom.getSeed(8);
+ for (int i = 0; i < by.length; i++) {
+ value += ((long) by[i] & 0xffL) << (8 * i);
+ }
+ return value;
+ }
+
+ public static Random instance() {
+ return instance;
+ }
+
+ public static int callsSinceSeed() {
+ return calls;
+ }
+
+ private static class RandomSourceInstance extends Random {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -4876737183441746322L;
+
+ @Override
+ public synchronized void setSeed(long seed) {
+ RandomSource.seed(seed);
+ }
+
+ @Override
+ public void nextBytes(byte[] bytes) {
+ RandomSource.nextBytes(bytes);
+ }
+
+ @Override
+ public int nextInt() {
+ return RandomSource.nextInt();
+ }
+
+ @Override
+ public int nextInt(int n) {
+ return RandomSource.nextInt(n);
+ }
+
+ @Override
+ public long nextLong() {
+ return RandomSource.nextLong();
+ }
+
+ @Override
+ public boolean nextBoolean() {
+ return RandomSource.nextBoolean();
+ }
+
+ @Override
+ public float nextFloat() {
+ return RandomSource.nextFloat();
+ }
+
+ @Override
+ public double nextDouble() {
+ return RandomSource.nextDouble();
+ }
+
+ @Override
+ public synchronized double nextGaussian() {
+ return RandomSource.nextGaussian();
+ }
+
+ }
+}
diff --git a/src/com/dabomstew/pkrandom/RomFunctions.java b/src/com/dabomstew/pkrandom/RomFunctions.java
new file mode 100755
index 000000000..9100d29e2
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/RomFunctions.java
@@ -0,0 +1,369 @@
+package com.dabomstew.pkrandom;
+
+/*----------------------------------------------------------------------------*/
+/*-- RomFunctions.java - contains functions useful throughout the program. --*/
+/*-- --*/
+/*-- Part of "Universal Pokemon Randomizer" by Dabomstew --*/
+/*-- Pokemon and any associated names and the like are --*/
+/*-- trademark and (C) Nintendo 1996-2012. --*/
+/*-- --*/
+/*-- The custom code written here is licensed under the terms of the GPL: --*/
+/*-- --*/
+/*-- This program is free software: you can redistribute it and/or modify --*/
+/*-- it under the terms of the GNU General Public License as published by --*/
+/*-- the Free Software Foundation, either version 3 of the License, or --*/
+/*-- (at your option) any later version. --*/
+/*-- --*/
+/*-- This program is distributed in the hope that it will be useful, --*/
+/*-- but WITHOUT ANY WARRANTY; without even the implied warranty of --*/
+/*-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --*/
+/*-- GNU General Public License for more details. --*/
+/*-- --*/
+/*-- You should have received a copy of the GNU General Public License --*/
+/*-- along with this program. If not, see . --*/
+/*----------------------------------------------------------------------------*/
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+import com.dabomstew.pkrandom.pokemon.Evolution;
+import com.dabomstew.pkrandom.pokemon.Pokemon;
+import com.dabomstew.pkrandom.romhandlers.RomHandler;
+
+public class RomFunctions {
+
+ public static final boolean[] bannedRandomMoves = new boolean[560],
+ bannedForDamagingMove = new boolean[560];
+ static {
+ bannedRandomMoves[144] = true; // Transform, glitched in RBY
+ bannedRandomMoves[165] = true; // Struggle, self explanatory
+
+ bannedForDamagingMove[120] = true; // SelfDestruct
+ bannedForDamagingMove[138] = true; // Dream Eater
+ bannedForDamagingMove[153] = true; // Explosion
+ bannedForDamagingMove[173] = true; // Snore
+ bannedForDamagingMove[206] = true; // False Swipe
+ bannedForDamagingMove[248] = true; // Future Sight
+ bannedForDamagingMove[252] = true; // Fake Out
+ bannedForDamagingMove[264] = true; // Focus Punch
+ bannedForDamagingMove[353] = true; // Doom Desire
+ bannedForDamagingMove[364] = true; // Feint
+ bannedForDamagingMove[387] = true; // Last Resort
+ bannedForDamagingMove[389] = true; // Sucker Punch
+
+ // new 160
+ bannedForDamagingMove[132] = true; // Constrict, overly weak
+ bannedForDamagingMove[99] = true; // Rage, lock-in in gen1
+ bannedForDamagingMove[205] = true; // Rollout, lock-in
+ bannedForDamagingMove[301] = true; // Ice Ball, Rollout clone
+
+ // make sure these cant roll
+ bannedForDamagingMove[39] = true; // Sonicboom
+ bannedForDamagingMove[82] = true; // Dragon Rage
+ bannedForDamagingMove[32] = true; // Horn Drill
+ bannedForDamagingMove[12] = true; // Guillotine
+ bannedForDamagingMove[90] = true; // Fissure
+ bannedForDamagingMove[329] = true; // Sheer Cold
+
+ }
+
+ public static Set getBasicOrNoCopyPokemon(RomHandler baseRom) {
+ List allPokes = baseRom.getPokemon();
+ List evos = baseRom.getEvolutions();
+
+ Set doCopyPokes = new TreeSet();
+ for (Evolution e : evos) {
+ if (e.carryStats) {
+ doCopyPokes.add(allPokes.get(e.to));
+ }
+ }
+ Set dontCopyPokes = new TreeSet();
+ for (Pokemon pkmn : allPokes) {
+ if (pkmn != null) {
+ if (doCopyPokes.contains(pkmn) == false) {
+ dontCopyPokes.add(pkmn);
+ }
+ }
+ }
+ return dontCopyPokes;
+ }
+
+ public static Set getFirstEvolutions(RomHandler baseRom) {
+ List allPokes = baseRom.getPokemon();
+ List evos = baseRom.getEvolutions();
+ Set basicPokemon = getBasicOrNoCopyPokemon(baseRom);
+
+ Set firstEvos = new TreeSet();
+ for (Evolution e : evos) {
+ if (basicPokemon.contains(allPokes.get(e.from))) {
+ firstEvos.add(allPokes.get(e.to));
+ }
+ }
+ return firstEvos;
+ }
+
+ public static Set getSecondEvolutions(RomHandler baseRom) {
+ List allPokes = baseRom.getPokemon();
+ List evos = baseRom.getEvolutions();
+ Set firstEvos = getFirstEvolutions(baseRom);
+
+ Set secondEvos = new TreeSet();
+ for (Evolution e : evos) {
+ if (firstEvos.contains(allPokes.get(e.from))) {
+ secondEvos.add(allPokes.get(e.to));
+ }
+ }
+ return secondEvos;
+ }
+
+ public static boolean pokemonHasEvo(RomHandler baseRom, Pokemon pkmn) {
+ List evos = baseRom.getEvolutions();
+ for (Evolution evo : evos) {
+ if (evo.from == pkmn.number) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static Pokemon evolvesFrom(RomHandler baseRom, Pokemon pkmn) {
+ List evos = baseRom.getEvolutions();
+ for (Evolution evo : evos) {
+ if (evo.to == pkmn.number) {
+ return baseRom.getPokemon().get(evo.from);
+ }
+ }
+ return null;
+ }
+
+ public static String camelCase(String original) {
+ char[] string = original.toLowerCase().toCharArray();
+ boolean docap = true;
+ for (int j = 0; j < string.length; j++) {
+ char current = string[j];
+ if (docap && Character.isLetter(current)) {
+ string[j] = Character.toUpperCase(current);
+ docap = false;
+ } else {
+ if (!docap && !Character.isLetter(current) && current != '\'') {
+ docap = true;
+ }
+ }
+ }
+ return new String(string);
+ }
+
+ public static int freeSpaceFinder(byte[] rom, byte freeSpace, int amount,
+ int offset) {
+ // by default align to 4 bytes to make sure things don't break
+ return freeSpaceFinder(rom, freeSpace, amount, offset, true);
+ }
+
+ public static int freeSpaceFinder(byte[] rom, byte freeSpace, int amount,
+ int offset, boolean longAligned) {
+ if (!longAligned) {
+ // Find 2 more than necessary and return 2 into it,
+ // to preserve stuff like FF terminators for strings
+ // 161: and FFFF terminators for movesets
+ byte[] searchNeedle = new byte[amount + 2];
+ for (int i = 0; i < amount + 2; i++) {
+ searchNeedle[i] = freeSpace;
+ }
+ return searchForFirst(rom, offset, searchNeedle) + 2;
+ } else {
+ // Find 5 more than necessary and return into it as necessary for
+ // 4-alignment,
+ // to preserve stuff like FF terminators for strings
+ // 161: and FFFF terminators for movesets
+ byte[] searchNeedle = new byte[amount + 5];
+ for (int i = 0; i < amount + 5; i++) {
+ searchNeedle[i] = freeSpace;
+ }
+ return (searchForFirst(rom, offset, searchNeedle) + 5) & ~3;
+ }
+ }
+
+ public static List search(byte[] haystack, byte[] needle) {
+ return search(haystack, 0, needle);
+ }
+
+ public static List search(byte[] haystack, int beginOffset,
+ byte[] needle) {
+ int currentMatchStart = beginOffset;
+ int currentCharacterPosition = 0;
+
+ int docSize = haystack.length;
+ int needleSize = needle.length;
+
+ int[] toFillTable = buildKMPSearchTable(needle);
+ List results = new ArrayList();
+
+ while ((currentMatchStart + currentCharacterPosition) < docSize) {
+
+ if (needle[currentCharacterPosition] == (haystack[currentCharacterPosition
+ + currentMatchStart])) {
+ currentCharacterPosition = currentCharacterPosition + 1;
+
+ if (currentCharacterPosition == (needleSize)) {
+ results.add(currentMatchStart);
+ currentCharacterPosition = 0;
+ currentMatchStart = currentMatchStart + needleSize;
+
+ }
+
+ } else {
+ currentMatchStart = currentMatchStart
+ + currentCharacterPosition
+ - toFillTable[currentCharacterPosition];
+
+ if (toFillTable[currentCharacterPosition] > -1) {
+ currentCharacterPosition = toFillTable[currentCharacterPosition];
+ }
+
+ else {
+ currentCharacterPosition = 0;
+
+ }
+
+ }
+ }
+ return results;
+ }
+
+ public static int searchForFirst(byte[] haystack, int beginOffset,
+ byte[] needle) {
+ int currentMatchStart = beginOffset;
+ int currentCharacterPosition = 0;
+
+ int docSize = haystack.length;
+ int needleSize = needle.length;
+
+ int[] toFillTable = buildKMPSearchTable(needle);
+
+ while ((currentMatchStart + currentCharacterPosition) < docSize) {
+
+ if (needle[currentCharacterPosition] == (haystack[currentCharacterPosition
+ + currentMatchStart])) {
+ currentCharacterPosition = currentCharacterPosition + 1;
+
+ if (currentCharacterPosition == (needleSize)) {
+ return currentMatchStart;
+ }
+
+ } else {
+ currentMatchStart = currentMatchStart
+ + currentCharacterPosition
+ - toFillTable[currentCharacterPosition];
+
+ if (toFillTable[currentCharacterPosition] > -1) {
+ currentCharacterPosition = toFillTable[currentCharacterPosition];
+ }
+
+ else {
+ currentCharacterPosition = 0;
+
+ }
+
+ }
+ }
+ return -1;
+ }
+
+ private static int[] buildKMPSearchTable(byte[] needle) {
+ int[] stable = new int[needle.length];
+ int pos = 2;
+ int j = 0;
+ stable[0] = -1;
+ stable[1] = 0;
+ while (pos < needle.length) {
+ if (needle[pos - 1] == needle[j]) {
+ stable[pos] = j + 1;
+ pos++;
+ j++;
+ } else if (j > 0) {
+ j = stable[j];
+ } else {
+ stable[pos] = 0;
+ pos++;
+ }
+ }
+ return stable;
+ }
+
+ public static String rewriteDescriptionForNewLineSize(String moveDesc,
+ String newline, int lineSize, StringSizeDeterminer ssd) {
+ // We rewrite the description we're given based on some new chars per
+ // line.
+ moveDesc = moveDesc.replace("-" + newline, "").replace(newline, " ");
+ // Keep spatk/spdef as one word on one line
+ moveDesc = moveDesc.replace("Sp. Atk", "Sp__Atk");
+ moveDesc = moveDesc.replace("Sp. Def", "Sp__Def");
+ moveDesc = moveDesc.replace("SP. ATK", "SP__ATK");
+ moveDesc = moveDesc.replace("SP. DEF", "SP__DEF");
+ String[] words = moveDesc.split(" ");
+ StringBuilder fullDesc = new StringBuilder();
+ StringBuilder thisLine = new StringBuilder();
+ int currLineWC = 0;
+ int currLineCC = 0;
+ int linesWritten = 0;
+ for (int i = 0; i < words.length; i++) {
+ // Reverse the spatk/spdef preservation from above
+ words[i] = words[i].replace("SP__", "SP. ");
+ words[i] = words[i].replace("Sp__", "Sp. ");
+ int reqLength = ssd.lengthFor(words[i]);
+ if (currLineWC > 0) {
+ reqLength++;
+ }
+ if (currLineCC + reqLength <= lineSize) {
+ // add to current line
+ if (currLineWC > 0) {
+ thisLine.append(' ');
+ }
+ thisLine.append(words[i]);
+ currLineWC++;
+ currLineCC += reqLength;
+ } else {
+ // Save current line, if applicable
+ if (currLineWC > 0) {
+ if (linesWritten > 0) {
+ fullDesc.append(newline);
+ }
+ fullDesc.append(thisLine.toString());
+ linesWritten++;
+ thisLine = new StringBuilder();
+ }
+ // Start the new line
+ thisLine.append(words[i]);
+ currLineWC = 1;
+ currLineCC = ssd.lengthFor(words[i]);
+ }
+ }
+
+ // If the last line has anything add it
+ if (currLineWC > 0) {
+ if (linesWritten > 0) {
+ fullDesc.append(newline);
+ }
+ fullDesc.append(thisLine.toString());
+ linesWritten++;
+ }
+
+ return fullDesc.toString();
+ }
+
+ public interface StringSizeDeterminer {
+ public int lengthFor(String encodedText);
+ }
+
+ public static class StringLengthSD implements StringSizeDeterminer {
+
+ @Override
+ public int lengthFor(String encodedText) {
+ return encodedText.length();
+ }
+
+ }
+
+}
diff --git a/src/com/dabomstew/pkrandom/config/Generation4.tbl b/src/com/dabomstew/pkrandom/config/Generation4.tbl
new file mode 100755
index 000000000..c4ca932dd
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/config/Generation4.tbl
@@ -0,0 +1,1148 @@
+0000=\x0000
+0001=\x0001
+0002=ã
+0003=ã‚
+0004=ãƒ
+0005=ã„
+0006=ã…
+0007=ã†
+0008=ã‡
+0009=ãˆ
+000A=ã‰
+000B=ãŠ
+000C=ã‹
+000D=ãŒ
+000E=ã
+000F=ãŽ
+0010=ã
+0011=ã
+0012=ã‘
+0013=ã’
+0014=ã“
+0015=ã”
+0016=ã•
+0017=ã–
+0018=ã—
+0019=ã˜
+001A=ã™
+001B=ãš
+001C=ã›
+001D=ãœ
+001E=ã
+001F=ãž
+0020=ãŸ
+0021=ã
+0022=ã¡
+0023=ã¢
+0024=ã£
+0025=ã¤
+0026=ã¥
+0027=ã¦
+0028=ã§
+0029=ã¨
+002A=ã©
+002B=ãª
+002C=ã«
+002D=ã¬
+002E=ã
+002F=ã®
+0030=ã¯
+0031=ã°
+0032=ã±
+0033=ã²
+0034=ã³
+0035=ã´
+0036=ãµ
+0037=ã¶
+0038=ã·
+0039=ã¸
+003A=ã¹
+003B=ãº
+003C=ã»
+003D=ã¼
+003E=ã½
+003F=ã¾
+0040=ã¿
+0041=ã‚€
+0042=ã‚
+0043=ã‚‚
+0044=ゃ
+0045=ã‚„
+0046=ã‚…
+0047=ゆ
+0048=ょ
+0049=よ
+004A=ら
+004B=ã‚Š
+004C=ã‚‹
+004D=れ
+004E=ã‚
+004F=ã‚
+0050=ã‚’
+0051=ã‚“
+0052=ã‚¡
+0053=ã‚¢
+0054=ã‚£
+0055=イ
+0056=ã‚¥
+0057=ウ
+0058=ェ
+0059=エ
+005A=ã‚©
+005B=オ
+005C=ã‚«
+005D=ガ
+005E=ã‚
+005F=ã‚®
+0060=ク
+0061=ã‚°
+0062=ケ
+0063=ゲ
+0064=コ
+0065=ã‚´
+0066=サ
+0067=ザ
+0068=ã‚·
+0069=ジ
+006A=ス
+006B=ズ
+006C=ã‚»
+006D=ゼ
+006E=ソ
+006F=ゾ
+0070=ã‚¿
+0071=ダ
+0072=ãƒ
+0073=ヂ
+0074=ッ
+0075=ツ
+0076=ヅ
+0077=テ
+0078=デ
+0079=ト
+007A=ド
+007B=ナ
+007C=ニ
+007D=ヌ
+007E=ãƒ
+007F=ノ
+0080=ãƒ
+0081=ãƒ
+0082=パ
+0083=ヒ
+0084=ビ
+0085=ピ
+0086=フ
+0087=ブ
+0088=プ
+0089=ヘ
+008A=ベ
+008B=ペ
+008C=ホ
+008D=ボ
+008E=ãƒ
+008F=マ
+0090=ミ
+0091=ãƒ
+0092=メ
+0093=モ
+0094=ャ
+0095=ヤ
+0096=ュ
+0097=ユ
+0098=ョ
+0099=ヨ
+009A=ラ
+009B=リ
+009C=ル
+009D=レ
+009E=ãƒ
+009F=ワ
+00A0=ヲ
+00A1=ン
+00A2=ï¼
+00A3=1
+00A4=ï¼’
+00A5=3
+00A6=ï¼”
+00A7=5
+00A8=ï¼–
+00A9=ï¼—
+00AA=8
+00AB=ï¼™
+00AC=A
+00AD=ï¼¢
+00AE=ï¼£
+00AF=D
+00B0=ï¼¥
+00B1=F
+00B2=G
+00B3=H
+00B4=I
+00B5=J
+00B6=K
+00B7=L
+00B8=ï¼
+00B9=ï¼®
+00BA=O
+00BB=ï¼°
+00BC=ï¼±
+00BD=ï¼²
+00BE=ï¼³
+00BF=ï¼´
+00C0=ï¼µ
+00C1=V
+00C2=ï¼·
+00C3=X
+00C4=ï¼¹
+00C5=Z
+00C6=ï½
+00C7=b
+00C8=c
+00C9=d
+00CA=ï½…
+00CB=f
+00CC=g
+00CD=h
+00CE=i
+00CF=j
+00D0=k
+00D1=l
+00D2=ï½
+00D3=n
+00D4=ï½
+00D5=ï½
+00D6=q
+00D7=ï½’
+00D8=s
+00D9=ï½”
+00DA=u
+00DB=ï½–
+00DC=ï½—
+00DD=x
+00DE=ï½™
+00DF=z
+00E0= (224)
+00E1=ï¼
+00E2=?
+00E3=ã€
+00E4=。
+00E5=…
+00E6=・
+00E7=ï¼
+00E8=「
+00E9=ã€
+00EA=『
+00EB=ã€
+00EC=(
+00ED=)
+00EE=♂
+00EF=♀
+00F0=+
+00F1=ー
+00F2=×
+00F3=÷
+00F4==
+00F5=~
+00F6=:
+00F7=ï¼›
+00F8=.
+00F9=,
+00FA=â™
+00FB=♣
+00FC=♥
+00FD=♦
+00FE=★
+00FF=â—Ž
+0100=â—‹
+0101=â–¡
+0102=â–³
+0103=â—‡
+0104=ï¼
+0105=♪
+0106=%
+0107=☀
+0108=â˜
+0109=☂
+010A=☃
+010B=\x010B
+010C=\x010C
+010D=\x010D
+010E=\x010E
+010F=⤴
+0110=⤵
+0111=\x0111
+0112=円
+0113=\x0113
+0114=\x0114
+0115=\x0115
+0116=✉
+0117=\x0117
+0118=\x0118
+0119=\x0119
+011A=\x011A
+011B=â†
+011C=↑
+011D=↓
+011E=→
+011F=\x011F
+0120=&
+0121=0
+0122=1
+0123=2
+0124=3
+0125=4
+0126=5
+0127=6
+0128=7
+0129=8
+012A=9
+012B=A
+012C=B
+012D=C
+012E=D
+012F=E
+0130=F
+0131=G
+0132=H
+0133=I
+0134=J
+0135=K
+0136=L
+0137=M
+0138=N
+0139=O
+013A=P
+013B=Q
+013C=R
+013D=S
+013E=T
+013F=U
+0140=V
+0141=W
+0142=X
+0143=Y
+0144=Z
+0145=a
+0146=b
+0147=c
+0148=d
+0149=e
+014A=f
+014B=g
+014C=h
+014D=i
+014E=j
+014F=k
+0150=l
+0151=m
+0152=n
+0153=o
+0154=p
+0155=q
+0156=r
+0157=s
+0158=t
+0159=u
+015A=v
+015B=w
+015C=x
+015D=y
+015E=z
+015F=À
+0160=Ã
+0161=Â
+0162=\x0162
+0163=Ä
+0164=\x0164
+0165=\x0165
+0166=Ç
+0167=È
+0168=É
+0169=Ê
+016A=Ë
+016B=Ì
+016C=Ã
+016D=ÃŽ
+016E=Ã
+016F=\x016F
+0170=Ñ
+0171=Ã’
+0172=Ó
+0173=Ô
+0174=\x0174
+0175=Ö
+0176=×
+0177=\x0177
+0178=Ù
+0179=Ú
+017A=Û
+017B=Ü
+017C=\x017C
+017D=\x017D
+017E=ß
+017F=Ã
+0180=á
+0181=â
+0182=\x0182
+0183=ä
+0184=\x0184
+0185=\x0185
+0186=ç
+0187=è
+0188=é
+0189=ê
+018A=ë
+018B=ì
+018C=Ã
+018D=î
+018E=ï
+018F=\x018F
+0190=ñ
+0191=ò
+0192=ó
+0193=ô
+0194=\x0194
+0195=ö
+0196=÷
+0197=\x0197
+0198=ù
+0199=ú
+019A=û
+019B=ü
+019C=\x019C
+019D=\x019D
+019E=\x019E
+019F=Å’
+01A0=Å“
+01A1=\x01A1
+01A2=\x01A2
+01A3=ª
+01A4=º
+01A5=ᵉʳ
+01A6=ʳᵉ
+01A7=ʳ
+01A8=Â¥
+01A9=¡
+01AA=¿
+01AB=!
+01AC=?
+01AD=,
+01AE=.
+01AF=…
+01B0=·
+01B1=/
+01B2=‘
+01B3='
+01B3=’
+01B4=“
+01B5=â€
+01B6=„
+01B7=«
+01B8=»
+01B9=(
+01BA=)
+01BB=♂
+01BC=♀
+01BD=+
+01BE=-
+01BF=*
+01C0=#
+01C1==
+01C2=\and
+01C3=~
+01C4=:
+01C5=;
+01C6=â™
+01C7=♣
+01C8=♥
+01C9=♦
+01CA=★
+01CB=â—Ž
+01CC=â—‹
+01CD=â–¡
+01CE=â–³
+01CF=â—‡
+01D0=@
+01D1=♪
+01D2=%
+01D3=☀
+01D4=â˜
+01D5=☂
+01D6=☃
+01D7=\x01D7
+01D8=\x01D8
+01D9=\x01D9
+01DA=\x01DA
+01DB=⤴
+01DC=⤵
+01DD=\x01DD
+01DE=
+01DF=\x01DF
+01E0=[PK]
+01E1=[MN]
+0401=ê°€
+0405=ê°ˆ
+0409=ê°‘
+040D=ê°•
+0413=개
+041B=ê°±
+041C=ê°¸
+0425=ê±°
+042B=ê²€
+0434=게
+0436=ê²”
+0439=겟
+044D=ê³
+044F=곤
+0451=골
+0455=ê³°
+0458=ê³µ
+0462=ê´‘
+0469=ê´´
+0476=구
+0478=êµ°
+047A=êµ´
+048B=ê·€
+0495=ê·¸
+0497=ê·¼
+0499=글
+04A0=기
+04A9=ê¹…
+04AC=까
+04AD=ê¹
+04B2=깜
+04B3=ê¹
+04B8=깨
+04C5=꺽
+04CA=ê»
+04DB=꼬
+04DF=ê¼´
+04E5=꽃
+04F5=꾸
+04F8=ê¿€
+0524=나
+0529=ë‚
+0535=ë‚´
+0539=냄
+0543=냥
+0544=너
+0551=네
+0565=ë…¸
+056A=놈
+056D=ë†
+0580=뇽
+0581=누
+0583=눈
+0598=ëŠ
+05A3=늪
+05A7=니
+05B1=다
+05B2=ë‹¥
+05B4=단
+05BB=ë‹´
+05C3=대
+05CD=ë”
+05CE=ë•
+05D8=ë©
+05DB=ë°
+05DE=ë¸
+05EB=ë„
+05EC=ë…
+05ED=ëˆ
+05EF=ëŒ
+05F5=ë™
+0604=ë‘
+0606=ë‘”
+0608=ë‘
+060B=ë‘¥
+061B=드
+061F=들
+0626=ë””
+0628=딘
+062A=딜
+062C=딥
+0632=ë”±
+0634=딸
+065B=ë˜
+0665=뚜
+0666=ëš
+0668=뚤
+0687=ë¼
+0688=ë½
+0689=란
+068A=ëž„
+068F=ëž‘
+0693=래
+0695=랜
+0697=램
+0698=ëž©
+06A1=러
+06A2=ëŸ
+06A3=런
+06A9=ë
+06AB=ë ˆ
+06AD=ë Œ
+06B1=ë ›
+06B4=ë ¥
+06C0=로
+06C1=ë¡
+06C3=롤
+06C5=ë¡
+06C7=롱
+06D8=룡
+06D9=루
+06DD=룸
+06EC=륙
+06F3=르
+06FE=리
+0700=린
+0701=릴
+0702=림
+0705=ë§
+0706=마
+0708=만
+070B=ë§
+070E=맘
+0711=ë§
+0715=매
+0717=맨
+0724=먹
+072E=ë©”
+0740=모
+0743=몬
+0749=몽
+0759=무
+075E=물
+0764=ë‰
+0770=뮤
+077A=미
+077E=ë°€
+0787=ë°”
+078D=발
+0791=ë°¤
+0794=ë°©
+0796=ë°°
+079C=뱃
+07A4=버
+07A5=ë²…
+07A6=번
+07AA=ë²”
+07AF=ë²
+07B3=벨
+07BC=별
+07C4=ë³´
+07C5=ë³µ
+07C8=ë³¼
+07DA=부
+07DB=ë¶
+07DC=분
+07DE=불
+07E1=ë¶
+07E4=붕
+07F0=ë·°
+07F6=브
+07F9=블
+07FD=비
+07FF=빈
+0800=빌
+081F=ë»
+0831=ë½€
+083B=뿌
+083E=ë¿”
+0841=ë¿¡
+0844=ì˜
+0849=ì‚
+0851=사
+0854=ì‚°
+0859=삼
+085D=ìƒ
+085F=새
+0860=색
+0868=샤
+0879=ì„
+087B=설
+0880=섯
+0882=성
+0884=세
+0885=섹
+0887=ì…€
+089A=소
+089D=ì†
+089E=솔
+08A0=솜
+08A3=송
+08BE=수
+08C2=ìˆ
+08C6=ìˆ
+08CC=ì‰
+08CF=쉘
+08DA=슈
+08E0=스
+08E3=슬
+08E9=시
+08EA=ì‹
+08EB=ì‹
+08ED=실
+0905=쌩
+0909=ì¬
+0914=ì˜
+0936=ì“°
+0942=씨
+094A=ì•„
+094C=안
+094F=알
+0953=ì•”
+095A=ì•
+095C=앤
+095F=앱
+0963=야
+0972=ì–´
+0977=ì–¼
+097F=ì—‰
+0983=ì—
+0986=ì—˜
+0987=ì—
+098B=ì—¬
+098E=ì—°
+0992=ì—¼
+0997=ì˜
+09A2=오
+09A4=온
+09AD=옹
+09AF=와
+09B2=왈
+09B7=왕
+09C6=ìš”
+09CD=ìš©
+09CE=ìš°
+09D1=울
+09D4=움
+09DA=ì›
+09E9=윈
+09EF=ìœ
+09F0=육
+09F1=윤
+09FB=ì„
+09FD=ìŒ
+0A0C=ì´
+0A0E=ì¸
+0A0F=ì¼
+0A13=ìž„
+0A14=ìž…
+0A17=잉
+0A19=잎
+0A1A=ìž
+0A21=ìž
+0A25=장
+0A27=재
+0A30=쟈
+0A36=ìŸ
+0A3A=ì €
+0A3C=ì „
+0A3F=ì
+0A44=ì œ
+0A47=ì ¤
+0A4C=ì ¸
+0A54=ì¡°
+0A72=죤
+0A74=주
+0A7D=중
+0A88=쥬
+0A8C=즈
+0A94=지
+0A95=ì§
+0A96=진
+0A98=질
+0AAB=짱
+0AEA=찌
+0AF3=ì°¨
+0AF8=ì°¸
+0B06=ì±™
+0B07=ì±
+0B10=ì²
+0B16=ì²´
+0B24=ì´ˆ
+0B2B=ì´
+0B37=쵸
+0B40=충
+0B4C=츄
+0B51=ì¸
+0B59=치
+0B5D=ì¹
+0B5F=침
+0B63=ì¹´
+0B65=칸
+0B6B=ìº
+0B73=캥
+0B80=컹
+0B81=ì¼€
+0B83=켄
+0B84=켈
+0B92=ì½”
+0B94=콘
+0B95=콜
+0BA5=ì¿
+0BA7=쿤
+0BB5=퀸
+0BBF=í¬
+0BC6=키
+0BC9=킬
+0BCD=킹
+0BCE=타
+0BCF=íƒ
+0BD7=탕
+0BD8=태
+0BE0=탱
+0BE3=í„°
+0BE5=í„´
+0BE8=í…€
+0BEC=í……
+0BED=테
+0BFA=í†
+0BFB=톡
+0BFC=톤
+0BFF=톱
+0C01=통
+0C0B=투
+0C22=트
+0C28=틈
+0C30=í‹°
+0C31=틱
+0C33=틸
+0C38=파
+0C3E=팜
+0C42=팡
+0C44=패
+0C46=팬
+0C4C=팽
+0C4F=í¼
+0C50=í½
+0C52=펄
+0C58=페
+0C5E=펫
+0C6B=í¬
+0C6C=í
+0C6E=í´
+0C72=í
+0C7C=푸
+0C80=í’€
+0C85=í’
+0C93=프
+0C95=플
+0C99=피
+0C9A=픽
+0CA0=í•‘
+0CA1=하
+0CA3=한
+0CA8=í•«
+0CAA=í•´
+0CAC=핸
+0CB7=헌
+0CBE=í—¤
+0CC1=í—¬
+0CCE=형
+0CD3=호
+0CDB=í™
+0CDD=í™”
+0CF4=후
+0D14=í‰
+0D17=í”
+0D27=히
+0402=ê°
+0403=ê°„
+0408=ê°
+0411=ê°š
+0414=ê°
+0429=걸
+042C=ê²
+043D=격
+0441=ê²°
+0446=ê²½
+045C=ê´€
+0471=êµ
+0479=êµ³
+0485=권
+049B=금
+04A4=길
+04A6=ê¹€
+04A8=깃
+04CB=ê»
+04FA=꿈
+04FF=ê¿”
+0503=ê¿°
+051C=ë¼
+0527=난
+0534=낳
+053D=냉
+0548=ë„
+0557=ë„·
+055E=ë…
+0566=ë…¹
+0567=ë…¼
+0568=놀
+059A=는
+059B=늘
+05A8=닉
+05B6=달
+05BF=당
+05C5=댄
+05D0=ë˜
+0605=ë‘‘
+060D=ë’€
+0624=등
+062D=딧
+0631=ë”°
+0639=ë•…
+063B=때
+0647=ë–¨
+0669=ëš«
+066D=ë›°
+068B=람
+06AC=ë ‰
+06B3=ë ¤
+06BB=ë ¹
+06BC=ë¡€
+06D3=료
+06EB=류
+06F7=름
+06FD=릎
+06FF=ë¦
+0704=릿
+0707=막
+071D=맹
+0723=머
+0726=ë©€
+072B=ë©
+0734=멧
+0739=ë©´
+073A=멸
+073D=명
+0741=목
+0746=몸
+075A=묵
+075B=묶
+075C=문
+077B=믹
+077C=민
+0788=ë°•
+078B=ë°˜
+078C=ë°›
+0790=ë°Ÿ
+0792=ë°¥
+079A=ë±€
+07A8=벌
+07AB=법
+07B1=벤
+07BA=ë²½
+07BB=ë³€
+07C7=본
+07C9=ë´„
+07CC=ë´‰
+0802=ë¹”
+0805=ë¹™
+0807=ë¹›
+081E=뺨
+082A=뼈
+0835=ë½
+083F=뿜
+0845=ìœ
+0856=ì‚´
+0867=ìƒ
+0870=ì„€
+0875=서
+0876=ì„
+089B=ì†
+08B6=쇼
+08BC=ìˆ
+08C0=순
+08C1=숟
+08C3=숨
+08D2=쉬
+08E6=습
+08E8=승
+08EE=ì‹«
+08EF=심
+08F4=싸
+094B=ì•…
+0954=ì••
+0959=ì•ž
+095B=ì•¡
+0962=앵
+096B=ì–‘
+0973=ì–µ
+0974=ì–¸
+097A=ì—„
+097B=ì—…
+098C=ì—
+098F=ì—´
+099B=예
+09A3=옥
+09D0=ìš´
+09D7=ì›…
+09D8=워
+09E0=웨
+09E5=웹
+09E7=위
+09F8=으
+09FA=ì€
+0A07=ì˜
+0A1B=ìž‘
+0A2B=ìž¼
+0A2F=ìŸ
+0A3B=ì
+0A3D=ì ˆ
+0A42=ì •
+0A46=ì
+0A48=ì ¬
+0A75=죽
+0A81=ì¥
+0A8E=즌
+0A9B=집
+0A9C=짓
+0A9E=짖
+0AA1=짜
+0AA2=ì§
+0AAC=째
+0AC5=쪼
+0AEB=ì°
+0AEF=ì°
+0AFE=채
+0B02=ì±”
+0B0D=처
+0B0F=천
+0B15=ì²
+0B1E=ì³
+0B29=ì´™
+0B30=최
+0B39=추
+0B3A=축
+0B3C=출
+0B3D=춤
+0B45=ì·¨
+0B66=ì¹¼
+0B77=커
+0B7B=컬
+0B7E=ì»·
+0B96=콤
+0BA0=쾌
+0BB3=퀴
+0BC2=í´
+0BC7=í‚¥
+0BD0=탄
+0BD1=탈
+0BD3=íƒ
+0BD9=íƒ
+0BE6=털
+0BEE=í…
+0BF0=í…”
+0BFE=톰
+0C16=튀
+0C1D=튜
+0C3B=íŒ
+0C3C=팔
+0C45=팩
+0C51=펀
+0C53=펌
+0C6D=í°
+0C82=í’ˆ
+0C96=í””
+0C9B=í•€
+0C9C=í•„
+0CA4=í•
+0CA5=í•¥
+0CA6=함
+0CA7=í•©
+0CA9=í•
+0CAE=í–„
+0CB0=í–‡
+0CB4=í–¥
+0CC9=혈
+0CCF=혜
+0CD4=혹
+0CD5=혼
+0CD6=홀
+0CDF=환
+0CE8=회
+0CEF=효
+0D06=휘
+0D0B=휩
+0D16=í‘
+0D1B=í™
+0D1D=í¡
+0D21=í¬
+0D22=í°
+0D2B=힘
+0416=ê°¤
+0427=ê±´
+0448=계
+045A=ê³¼
+047B=êµµ
+0492=규
+049C=급
+04A7=ê¹
+0512=ëˆ
+0526=ë‚š
+052A=ë‚¡
+052C=남
+05A1=능
+05A9=닌
+05BD=ë‹·
+0673=뜨
+0680=ë
+069B=ëž
+06CC=뢰
+06DC=룰
+06F5=른
+0710=맛
+0712=맞
+0716=맥
+071A=맵
+0730=멘
+0731=멜
+0732=멤
+0797=ë°±
+0798=ë°´
+07C0=병
+080B=빨
+0863=샘
+088D=ì…”
+0890=셜
+08B0=ì‡
+08BF=숙
+08C9=숲
+08DF=ìŠ
+08F1=싯
+0921=ì
+094E=ì•Š
+0964=약
+097C=ì—†
+0A16=있
+0A1C=ìž”
+0A1F=잘
+0A5F=좋
+0A77=줄
+0A9D=징
+0AFC=ì°½
+0B12=첩
+0B5B=친
+0B67=캄
+0B87=켓
+0BB4=퀵
+0BC1=í°
+0C24=튼
+0C26=í‹€
+0C59=펙
+0C5A=펜
+0C61=편
+0C66=í‰
+0C77=표
+0C7E=푼
+0CA2=í•™
+0CB2=í–‰
+0CB5=í—ˆ
+0CBA=í—˜
+0CE0=활
+0D2A=íž
+E000=\n
+25BC=\r
diff --git a/src/com/dabomstew/pkrandom/config/Generation5.tbl b/src/com/dabomstew/pkrandom/config/Generation5.tbl
new file mode 100755
index 000000000..8c3835503
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/config/Generation5.tbl
@@ -0,0 +1,46 @@
+2467=×
+2468=÷
+246C=…
+246D=♂
+246E=♀
+246F=â™
+2470=♣
+2471=♥
+2472=♦
+2473=★
+2474=â—Ž
+2475=â—‹
+2476=â–¡
+2477=â–³
+2478=â—‡
+2479=♪
+247A=☀
+247B=â˜
+247D=☂
+21D2=\[angry]
+21D4=\[turnup]
+2200=\[turndown]
+2203=\[zzz]
+2227=\[=)]
+2228=\[=D]
+2460=\[:)]
+2461=\[:D]
+2462=\[>:O]
+2463=\[:(]
+2464=\[turnup2]
+2465=\[turndown2]
+2466=\[zzz2]
+2469=\[er]
+246A=\[re]
+246B=\[corner]
+247E=\[:)s]
+247F=\[:Ds]
+2480=\[>:Os]
+2481=\[:(s]
+2482=\[turnups]
+2483=\[turndowns]
+2484=\[zzzs]
+2485=\[e]
+2486=\[PK]
+2487=\[MN]
+FFE2=\[>:O2]
diff --git a/src/com/dabomstew/pkrandom/config/gameboy_jap.tbl b/src/com/dabomstew/pkrandom/config/gameboy_jap.tbl
new file mode 100755
index 000000000..fce8c2f23
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/config/gameboy_jap.tbl
@@ -0,0 +1,179 @@
+05=ガ
+06=ã‚®
+07=ã‚°
+08=ゲ
+09=ã‚´
+0A=ザ
+0B=ジ
+0C=ズ
+0D=ゼ
+0E=ゾ
+0F=ダ
+10=ヂ
+11=ヅ
+12=デ
+13=ド
+19=ãƒ
+1A=ビ
+1B=ブ
+1C=ボ
+26=ãŒ
+27=ãŽ
+28=ã
+29=ã’
+2A=ã”
+2B=ã–
+2C=ã˜
+2D=ãš
+2E=ãœ
+2F=ãž
+30=ã
+31=ã¢
+32=ã¥
+33=ã§
+34=ã©
+3A=ã°
+3B=ã³
+3C=ã¶
+3D=ã¹
+3E=ã¼
+40=パ
+41=ピ
+42=プ
+43=ãƒ
+44=ã±
+45=ã´
+46=ã·
+47=ãº
+48=ã½
+54=ãƒã‚±ãƒ¢ãƒ³
+7F=
+80=ã‚¢
+81=イ
+82=ウ
+83=エ
+84=ã‚©
+85=ã‚«
+86=ã‚
+87=ク
+88=ケ
+89=コ
+8A=サ
+8B=ã‚·
+8C=ス
+8D=ã‚»
+8E=ソ
+8F=ã‚¿
+90=ãƒ
+91=ツ
+92=テ
+93=ト
+94=ナ
+95=ニ
+96=ヌ
+97=ãƒ
+98=ノ
+99=ãƒ
+9A=ヒ
+9B=フ
+9C=ホ
+9D=マ
+9E=ミ
+9F=ãƒ
+A0=メ
+A1=モ
+A2=ヤ
+A3=ユ
+A4=ヨ
+A5=ラ
+A6=ル
+A7=レ
+A8=ãƒ
+A9=ワ
+AA=ヲ
+AB=ン
+AC=ッ
+AD=ャ
+AE=ュ
+AF=ョ
+B0=ã‚£
+B1=ã‚
+B2=ã„
+B3=ã†
+B4=ãˆ
+B5=ãŠ
+B6=ã‹
+B7=ã
+B8=ã
+B9=ã‘
+BA=ã“
+BB=ã•
+BC=ã—
+BD=ã™
+BE=ã›
+BF=ã
+C0=ãŸ
+C1=ã¡
+C2=ã¤
+C3=ã¦
+C4=ã¨
+C5=ãª
+C6=ã«
+C7=ã¬
+C8=ã
+C9=ã®
+CA=ã¯
+CB=ã²
+CC=ãµ
+CD=ã¸
+CE=ã»
+CF=ã¾
+D0=ã¿
+D1=ã‚€
+D2=ã‚
+D3=ã‚‚
+D4=ã‚„
+D5=ゆ
+D6=よ
+D7=ら
+D8=ã‚Š
+D9=ã‚‹
+DA=れ
+DB=ã‚
+DC=ã‚
+DD=ã‚’
+DE=ã‚“
+DF=ã£
+E0=ゃ
+E1=ã‚…
+E2=ょ
+E3=ー
+E4=。
+E4=ã‚š
+E5=゙​
+E6=?
+E7=!
+E8=。
+E9=ã‚¡
+EB=ェ
+EF=♂
+F0=円
+F1=×
+F2=[.]
+F3=/
+F4=ã‚©
+F5=♀
+F6=0
+F7=1
+F8=2
+F9=3
+FA=4
+FB=5
+FC=6
+FD=7
+FE=8
+FF=9
+4F=\n
+51=\p
+55=\l
+57=\e
\ No newline at end of file
diff --git a/src/com/dabomstew/pkrandom/config/gba_english.tbl b/src/com/dabomstew/pkrandom/config/gba_english.tbl
new file mode 100755
index 000000000..82f4e3af7
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/config/gba_english.tbl
@@ -0,0 +1,159 @@
+00=
+01=À
+02=Ã
+03=Â
+04=Ç
+05=È
+06=É
+07=Ê
+08=Ë
+09=Ì
+0B=ÃŽ
+0C=Ã
+0D=Ã’
+0E=Ó
+0F=Ô
+10=Æ
+11=Ù
+12=Ú
+13=Û
+14=Ñ
+15=ß
+16=Ã
+17=á
+19=ç
+1A=è
+1B=é
+1C=ê
+1D=ë
+1E=ì
+20=î
+21=ï
+22=ò
+23=ó
+24=ô
+25=æ
+26=ù
+27=ú
+28=û
+29=ñ
+2A=º
+2B=ª
+2C=·
+2D=&
+2E=+
+34=[Lv]
+35==
+36=;
+51=¿
+52=¡
+53=[PK]
+54=[MN]
+55=[PO]
+56=[Ke]
+57=[BL]
+58=[OC]
+59=[K]
+5A=Ã
+5B=%
+5C=(
+5D=)
+68=â
+6F=Ã
+79=[U]
+7A=[D]
+7B=[L]
+7C=[R]
+A1=0
+A2=1
+A3=2
+A4=3
+A5=4
+A6=5
+A7=6
+A8=7
+A9=8
+AA=9
+AB=!
+AC=?
+AD=.
+AE=-
+AF=·
+B0=…
+B1=“
+B2=â€
+B3=‘
+B4=’
+B5=♂
+B6=♀
+B7=$
+B8=,
+B9=[x]
+BA=/
+BB=A
+BC=B
+BD=C
+BE=D
+BF=E
+C0=F
+C1=G
+C2=H
+C3=I
+C4=J
+C5=K
+C6=L
+C7=M
+C8=N
+C9=O
+CA=P
+CB=Q
+CC=R
+CD=S
+CE=T
+CF=U
+D0=V
+D1=W
+D2=X
+D3=Y
+D4=Z
+D5=a
+D6=b
+D7=c
+D8=d
+D9=e
+DA=f
+DB=g
+DC=h
+DD=i
+DE=j
+DF=k
+E0=l
+E1=m
+E2=n
+E3=o
+E4=p
+E5=q
+E6=r
+E7=s
+E8=t
+E9=u
+EA=v
+EB=w
+EC=x
+ED=y
+EE=z
+EF=[>]
+F0=:
+F1=Ä
+F2=Ö
+F3=Ü
+F4=ä
+F5=ö
+F6=ü
+F7=[u]
+F8=[d]
+F9=[l]
+FA=\l
+FB=\p
+FC=\c
+FE=\n
diff --git a/src/com/dabomstew/pkrandom/config/gba_jap.tbl b/src/com/dabomstew/pkrandom/config/gba_jap.tbl
new file mode 100755
index 000000000..4a873bda1
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/config/gba_jap.tbl
@@ -0,0 +1,254 @@
+00=
+01=ã‚
+02=ã„
+03=ã†
+04=ãˆ
+05=ãŠ
+06=ã‹
+07=ã
+08=ã
+09=ã‘
+0A=ã“
+0B=ã•
+0C=ã—
+0D=ã™
+0E=ã›
+0F=ã
+10=ãŸ
+11=ã¡
+12=ã¤
+13=ã¦
+14=ã¨
+15=ãª
+16=ã«
+17=ã¬
+18=ã
+19=ã®
+1A=ã¯
+1B=ã²
+1C=ãµ
+1D=ã¸
+1E=ã»
+1F=ã¾
+20=ã¿
+21=ã‚€
+22=ã‚
+23=ã‚‚
+24=ã‚„
+25=ゆ
+26=よ
+27=ら
+28=ã‚Š
+29=ã‚‹
+2A=れ
+2B=ã‚
+2C=ã‚
+2D=ã‚’
+2E=ã‚“
+2F=ã
+30=ãƒ
+31=ã…
+32=ã‡
+33=ã‰
+34=ゃ
+35=ã‚…
+36=ょ
+37=ãŒ
+38=ãŽ
+39=ã
+3A=ã’
+3B=ã”
+3C=ã–
+3D=ã˜
+3E=ãš
+3F=ãœ
+40=ãž
+41=ã
+42=ã¢
+43=ã¥
+44=ã§
+45=ã©
+46=ã°
+47=ã³
+48=ã¶
+49=ã¹
+4A=ã¼
+4B=ã±
+4C=ã´
+4D=ã·
+4E=ãº
+4F=ã½
+50=ã£
+51=ã‚¢
+52=イ
+53=ウ
+54=エ
+55=オ
+56=ã‚«
+57=ã‚
+58=ク
+59=ケ
+5A=コ
+5B=サ
+5C=ã‚·
+5D=ス
+5E=ã‚»
+5F=ソ
+60=ã‚¿
+61=ãƒ
+62=ツ
+63=テ
+64=ト
+65=ナ
+66=ニ
+67=ヌ
+68=ãƒ
+69=ノ
+6A=ãƒ
+6B=ヒ
+6C=フ
+6D=ヘ
+6E=ホ
+6F=マ
+70=ミ
+71=ãƒ
+72=メ
+73=モ
+74=ヤ
+75=ユ
+76=ヨ
+77=ラ
+78=リ
+79=ル
+7A=レ
+7B=ãƒ
+7C=ワ
+7D=ヲ
+7E=ン
+7F=ã‚¡
+80=ã‚£
+81=ã‚¥
+82=ェ
+83=ã‚©
+84=ャ
+85=ュ
+86=ョ
+87=ガ
+88=ã‚®
+89=ã‚°
+8A=ゲ
+8B=ã‚´
+8C=ザ
+8D=ジ
+8E=ズ
+8F=ゼ
+90=ゾ
+91=ダ
+92=ヂ
+93=ヅ
+94=デ
+95=ド
+96=ãƒ
+97=ビ
+98=ブ
+99=ベ
+9A=ボ
+9B=パ
+9C=ピ
+9D=プ
+9E=ペ
+9F=ãƒ
+A0=ッ
+A1=0
+A2=1
+A3=2
+A4=3
+A5=4
+A6=5
+A7=6
+A8=7
+A9=8
+AA=9
+AB=!
+AC=?
+AD=.
+AE=ー
+AF=ï½·
+B0=å°
+B1=ォ
+B2=ï½»
+B3=<
+B4=>
+B5=♂
+B6=♀
+B7=$
+B8=,
+B9=*
+BA=/
+BB=A
+BC=B
+BD=C
+BE=D
+BF=E
+C0=F
+C1=G
+C2=H
+C3=I
+C4=J
+C5=K
+C6=L
+C7=M
+C8=N
+C9=O
+CA=P
+CB=Q
+CC=R
+CD=S
+CE=T
+CF=U
+D0=V
+D1=W
+D2=X
+D3=Y
+D4=Z
+D5=a
+D6=b
+D7=c
+D8=d
+D9=e
+DA=f
+DB=g
+DC=h
+DD=i
+DE=j
+DF=k
+E0=l
+E1=m
+E2=n
+E3=o
+E4=p
+E5=q
+E6=r
+E7=s
+E8=t
+E9=u
+EA=v
+EB=w
+EC=x
+ED=y
+EE=z
+EF=[>]
+F0=:
+F1=ト
+F2=ï¾–
+F3=ワ
+F4=ä
+F5=ö
+F6=ü
+F7=[u]
+F8=[d]
+F9=[l]
+FA=\l
+FB=\p
+FC=\c
+FE=\n
diff --git a/src/com/dabomstew/pkrandom/config/gen1_offsets.ini b/src/com/dabomstew/pkrandom/config/gen1_offsets.ini
new file mode 100755
index 000000000..b87b5d2fb
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/config/gen1_offsets.ini
@@ -0,0 +1,707 @@
+[Red (U)]
+Game=POKEMON RED
+Version=0
+NonJapanese=1
+Type=RB
+ExtraTableFile=rby_english
+BWXPTweak=rb_en_bwxp
+XAccNerfTweak=rb_en_xaccnerf
+CritRateTweak=rb_en_critrate
+InternalPokemonCount=190
+PokedexOrder=0x41024
+PokemonNamesOffset=0x1C21E
+PokemonNamesLength=10
+PokemonStatsOffset=0x383DE
+MewStatsOffset=0x425B
+WildPokemonTableOffset=0xCEEB
+OldRodOffset=0xE252
+GoodRodOffset=0xE27F
+SuperRodTableOffset=0xE919
+MapNameTableOffset=0x71313
+MoveCount=165
+MoveDataOffset=0x38000
+MoveNamesOffset=0xB0000
+ItemNamesOffset=0x472B
+TypeEffectivenessOffset=0x3E474
+PokemonMovesetsTableOffset=0x3B05C
+StarterOffsets1=[0x1D126, 0x1CC84, 0x1D10E, 0x39CF8, 0x50FB3, 0x510DD]
+StarterOffsets2=[0x1D104, 0x19591, 0x1CC88, 0x1CDC8, 0x1D11F, 0x50FAF, 0x510D9, 0x51CAF, 0x6060E, 0x61450, 0x75F9E]
+StarterOffsets3=[0x1D115, 0x19599, 0x1CDD0, 0x1D130, 0x39CF2, 0x50FB1, 0x510DB, 0x51CB7, 0x60616, 0x61458, 0x75FA6]
+PatchPokedex=1
+CanChangeStarterText=1
+CanChangeTrainerText=1
+StarterPokedexOnOffset=0x5C0DC
+StarterPokedexOffOffset=0x5C0E6
+StarterPokedexBranchOffset=0x5E000
+PokedexRamOffset=0xD2F7
+TrainerDataTableOffset=0x39D3B
+TrainerDataClassCounts=[0, 13, 14, 18, 8, 9, 24, 7, 12, 14, 15, 9, 3, 0, 11, 15, 9, 7, 15, 4, 2, 8, 6, 17, 9, 9, 3, 0, 13, 3, 41, 10, 8, 1, 1, 1, 1, 1, 1, 1, 1, 5, 12, 3, 1, 24, 1, 1]
+ExtraTrainerMovesTableOffset=0x39D32
+GymLeaderMovesTableOffset=0x39D23
+TMMovesOffset=0x13773
+TrainerClassNamesOffsets=[0x27EC2, 0x399FF]
+IntroPokemonOffset=0x616D
+IntroCryOffset=0x1C73
+MapBanks=0xC23D
+MapAddresses=0x01AE
+SpecialMapList=0x46A40
+SpecialMapPointerTable=0x46A96
+HiddenItemRoutine=0x76688
+TradeTableOffset=0x71B7B
+TradeTableSize=10
+TradeNameLength=11
+TradesUnused=[2]
+StaticPokemonSupport=1
+StaticPokemonPokeballs=[0x1DD49, 0x5CF5F, 0x5CF17]
+StaticPokemonOverworlds=[0x1E3D5, 0x1E3DD, 0x1E3E5, 0x1E3ED, 0x1E3F5, 0x1E3FD, 0x1E405, 0x1E40D, 0x1E415, 0x468E8, 0x51963, 0x45F44, 0x59630, 0x59970]
+StaticPokemonFossils=[0x61064, 0x61068, 0x6106C]
+StaticPokemonGifts=[0x51DAD, 0x49320]
+StaticPokemonGameCorner[]=[0x52859,0x5298A] // Abra
+StaticPokemonGameCorner[]=[0x5285A,0x5298C] // Clefairy
+StaticPokemonGameCorner[]=[0x5285B,0x5298E] // Nidorina/Nidorino
+StaticPokemonGameCorner[]=[0x52864,0x52990] // Dratini/Pinsir
+StaticPokemonGameCorner[]=[0x52865,0x52992] // Scyther/Dratini
+StaticPokemonGameCorner[]=[0x52866,0x52994] // Porygon
+TMText[]=[6,0x0A0100,\pTM06 contains\n%m!\e]
+TMText[]=[11,0x98A7C,TM11 teaches\n%m!\e]
+TMText[]=[13,0x9CC22,contains\n%m!\e]
+TMText[]=[18,0x9C86F,TM18 is\n%m!\e]
+TMText[]=[21,0x9D521,\pTM21 contains\n%m.\e]
+TMText[]=[24,0x9C0F6,\pTM24 contains\n%m!\e]
+TMText[]=[27,0x96096,\pTM27 is\n%m!\e]
+TMText[]=[28,0x9875D,Those miserable\nROCKETs!\pLook what they\ndid here!\pThey stole a TM\nfor teaching\l[POKé]MON how to\l%m!\e]
+TMText[]=[28,0x987E3,I figure what's\nlost is lost!\pI decided to get\n%m\lwithout a TM!\e]
+TMText[]=[29,0xA253F,TM29 is\n%m!\e]
+TMText[]=[31,0xA168A,\pTM31 contains my\nfavorite,\l%m!\e]
+TMText[]=[34,0x980C1,\pA TM contains a\ntechnique that\lcan be taught to\l[POKé]MON!\pA TM is good only\nonce! So when you\luse one to teach\la new technique,\lpick the [POKé]MON\lcarefully!\pTM34 contains\n%m!\e]
+TMText[]=[36,0x824CA,TM36 is\n%m!\e]
+TMText[]=[38,0xA09BD,\pTM38 contains\n%m!\e]
+TMText[]=[39,0x8C8DA,TM39 is the move\n%m.\e]
+TMText[]=[41,0xA5B6F,TM41 teaches\n%m!\pMany [POKé]MON\ncan use it!\e]
+TMText[]=[42,0xA46AE,TM42 contains\n%m...\e]
+TMText[]=[46,0xA1DE1,\pTM46 is\n%m!\e]
+TMText[]=[48,0x9CCAD,contains\n%m!\e]
+TMText[]=[49,0x9CD31,\pTM49 is\n%m!\e]
+
+[Blue (U)]
+Game=POKEMON BLUE
+Version=0
+NonJapanese=1
+Type=RB
+CopyTMText=1
+CopyStaticPokemon=1
+CopyFrom=Red (U)
+BWXPTweak=rb_en_bwxp
+XAccNerfTweak=rb_en_xaccnerf
+CritRateTweak=rb_en_critrate
+HiddenItemRoutine=0x76689
+StarterOffsets2=[0x1D104, 0x19591, 0x1CC88, 0x1CDC8, 0x1D11F, 0x50FAF, 0x510D9, 0x51CAF, 0x6060E, 0x61450, 0x75F9F]
+StarterOffsets3=[0x1D115, 0x19599, 0x1CDD0, 0x1D130, 0x39CF2, 0x50FB1, 0x510DB, 0x51CB7, 0x60616, 0x61458, 0x75FA7]
+
+[Yellow (U)]
+Game=POKEMON YELLOW
+Version=0
+NonJapanese=1
+Type=Yellow
+CopyFrom=Red (U)
+BWXPTweak=yellow_en_bwxp
+XAccNerfTweak=yellow_en_xaccnerf
+CritRateTweak=yellow_en_critrate
+PokedexOrder=0x410B1
+PokemonNamesOffset=0xE8000
+MewStatsOffset=0
+MoveNamesOffset=0xBC000
+ItemNamesOffset=0x45B7
+WildPokemonTableOffset=0xCB95
+OldRodOffset=0xE0FF
+GoodRodOffset=0xE12C
+SuperRodTableOffset=0xF5EDA
+MapNameTableOffset=0x7139C
+TypeEffectivenessOffset=0x3E5FA
+PokemonMovesetsTableOffset=0x3B1E5
+StarterOffsets1=[0x18F19, 0x1CB41, 0x1CB66]
+StarterOffsets2=[0x3A28A]
+TrainerDataTableOffset=0x39DD1
+TrainerDataClassCounts=[0, 14, 15, 19, 8, 10, 25, 7, 12, 14, 15, 9, 3, 0, 11, 15, 9, 7, 15, 4, 2, 8, 6, 17, 9, 3, 3, 0, 13, 3, 49, 10, 8, 1, 1, 1, 1, 1, 1, 1, 1, 5, 10, 3, 1, 24, 1, 1]
+ExtraTrainerMovesTableOffset=0x39C6B
+GymLeaderMovesTableOffset=0
+TMMovesOffset=0x1232D
+TrainerClassNamesOffsets=[0x27E77, 0x3997E]
+IntroPokemonOffset=0x5EDB
+IntroCryOffset=0x1A4C
+MapBanks=0xFC3E4
+MapAddresses=0xFC1F2
+SpecialMapPointerTable=0xF268D
+HiddenItemRoutine=0x75F74
+TradeTableOffset=0x71C1D
+TradeTableSize=10
+TradeNameLength=11
+TradesUnused=[2,4,6]
+StaticPokemonSupport=1
+StaticPokemonPokeballs=[0x1D652, 0x5CE55, 0x5CE0D]
+StaticPokemonOverworlds=[0x1DCDF, 0x1DCE7, 0x1DCEF, 0x1DCF7, 0x1DCFF, 0x1DD07, 0x1DD0F, 0x1DD17, 0x1DD1F, 0x46B5A, 0x519A5, 0x461A5, 0x594CC, 0x5980C]
+StaticPokemonFossils=[0x61050, 0x61054, 0x61058]
+StaticPokemonGifts=[0x51DD6, 0xF21C0, 0x1CF8C, 0x515AF, 0xF1A45]
+StaticPokemonGameCorner[] = [0x527BA,0x528EA] // Abra
+StaticPokemonGameCorner[] = [0x527BB,0x528EC] // Vulpix
+StaticPokemonGameCorner[] = [0x527BC,0x528EE] // Wigglytuff
+StaticPokemonGameCorner[] = [0x527C5,0x528F0] // Scyther
+StaticPokemonGameCorner[] = [0x527C6,0x528F2] // Pinsir
+StaticPokemonGameCorner[] = [0x527C7,0x528F4] // Porygon
+TMText[]=[6,0x0B0EE4,\pTM06 contains\n%m!\e]
+TMText[]=[11,0xAB2D6,TM11 teaches\n%m!\e]
+TMText[]=[13,0xAE5CA,contains\n%m!\e]
+TMText[]=[18,0xAE3F3,TM18 is\n%m!\e]
+TMText[]=[21,0xAF141,\pTM21 contains\n%m.\e]
+TMText[]=[24,0xAD9FE,\pTM24 contains\n%m!\e]
+TMText[]=[27,0xA9BEC,\pTM27 is\n%m!\e]
+TMText[]=[28,0xAAEC4,Those miserable\nROCKETs!\pLook what they\ndid here!\pThey stole a TM\nfor teaching\l[POKé]MON how to\l%m!\e]
+TMText[]=[28,0xAAF4A,I figure what's\nlost is lost!\pI decided to get\n%m\lwithout a TM!\e]
+TMText[]=[29,0xB343D,TM29 is\n%m!\e]
+TMText[]=[31,0xB2593,\pTM31 contains my\nfavorite,\l%m!\e]
+TMText[]=[34,0xAA729,\pA TM contains a\ntechnique that\lcan be taught to\l[POKé]MON!\pA TM is good only\nonce! So when you\luse one to teach\la new technique,\lpick the [POKé]MON\lcarefully!\pTM34 contains\n%m!\e]
+TMText[]=[36,0x9A5B0,TM36 is\n%m!\e]
+TMText[]=[38,0xB17A1,\pTM38 contains\n%m!\e]
+TMText[]=[39,0xA1BDE,TM39 is the move\n%m.\e]
+TMText[]=[41,0xB5E1F,TM41 teaches\n%m!\pMany [POKé]MON\ncan use it!\e]
+TMText[]=[42,0xB48A0,TM42 contains\n%m...\e]
+TMText[]=[46,0xB2CEA,\pTM46 is\n%m!\e]
+TMText[]=[48,0xAE655,contains\n%m!\e]
+TMText[]=[49,0xAE6B7,\pTM49 is\n%m!\e]
+
+[Red (J)]
+Game=POKEMON RED
+Version=0
+NonJapanese=0
+Type=RB
+InternalPokemonCount=190
+PokedexOrder=0x4279A
+PokemonNamesOffset=0x39068
+PokemonNamesLength=5
+PokemonStatsOffset=0x38000
+MewStatsOffset=0x4200
+WildPokemonTableOffset=0xCF61
+OldRodOffset=0xE3A1
+GoodRodOffset=0xE3CE
+SuperRodTableOffset=0xEC24
+MapNameTableOffset=0x718AF
+MoveCount=165
+MoveNamesOffset=0x10000
+MoveDataOffset=0x39658
+ItemNamesOffset=0x433F
+TypeEffectivenessOffset=0x3E756
+PokemonMovesetsTableOffset=0x3B427
+StarterOffsets1=[0x1CBBF, 0x1C6C2, 0x1CBA7, 0x3A069, 0x514A1, 0x515CB]
+StarterOffsets2=[0x1CB9D, 0x19C66, 0x1C6C6, 0x1C806, 0x1CBB8, 0x5149D, 0x515C7, 0x52A1D, 0x606AD, 0x61F2D, 0x77003]
+StarterOffsets3=[0x1CBAE, 0x19C6E, 0x1C80E, 0x1CBC9, 0x3A063, 0x5149F, 0x515C9, 0x52A25, 0x606B5, 0x61F35, 0x7700B]
+PatchPokedex=0
+CanChangeStarterText=0
+CanChangeTrainerText=0
+TrainerDataTableOffset=0x3A0AC
+TrainerDataClassCounts=[0, 13, 14, 18, 8, 9, 24, 7, 12, 14, 15, 9, 3, 0, 11, 15, 9, 7, 15, 4, 2, 8, 6, 17, 9, 9, 3, 0, 13, 3, 41, 10, 8, 1, 1, 1, 1, 1, 1, 1, 1, 5, 12, 3, 1, 24, 1, 1]
+ExtraTrainerMovesTableOffset=0x3A0A3
+GymLeaderMovesTableOffset=0x3A094
+TMMovesOffset=0x12276
+TrainerClassNamesOffsets=[0x27F2A, 0x39D1C]
+IntroPokemonOffset=0x5FB1
+IntroCryOffset=0x716
+MapBanks=0xC883
+MapAddresses=0x1BCB
+SpecialMapList=0x47965
+SpecialMapPointerTable=0x479BB
+HiddenItemRoutine=0x77D78
+TradeTableOffset=0x72043
+TradeTableSize=10
+TradeNameLength=5
+TradesUnused=[2]
+StaticPokemonSupport=1
+StaticPokemonPokeballs=[0x1E771, 0x5E390, 0x5E330]
+StaticPokemonOverworlds=[0x1F0A7, 0x1F0AF, 0x1F0B7, 0x1F0BF, 0x1F0C7, 0x1F0CF, 0x1F0D7, 0x1F0DF, 0x1F0E7, 0x4780D, 0x526D4, 0x46C57, 0x59E34, 0x5A684]
+StaticPokemonFossils=[0x617D7, 0x617DB, 0x617DF]
+StaticPokemonGifts=[0x52B1B, 0x4A557]
+StaticPokemonGameCorner[]=[0x53C10,0x53D6A] // Abra
+StaticPokemonGameCorner[]=[0x53C11,0x53D6C] // Clefairy
+StaticPokemonGameCorner[]=[0x53C12,0x53D6E] // Nidorina/Nidorino
+StaticPokemonGameCorner[]=[0x53C1B,0x53D70] // Dratini/Pinsir
+StaticPokemonGameCorner[]=[0x53C1C,0x53D72] // Scyther/Dratini
+StaticPokemonGameCorner[]=[0x53C1D,0x53D74] // Porygon
+
+[Green (J)]
+Game=POKEMON GREEN
+Version=0
+NonJapanese=0
+Type=RB
+CopyStaticPokemon=1
+CopyFrom=Red (J)
+IntroPokemonOffset=0x5FB2
+
+[Green (J)(T-Eng)]
+Game=POKEMON GREEN
+Version=0
+NonJapanese=0
+CRCInHeader=0xF57E
+Type=RB
+CopyStaticPokemon=1
+CopyFrom=Green (J)
+ExtraTableFile=green_translation
+CanChangeTrainerText=1
+TrainerClassNamesOffsets=[0xB21BF]
+ItemNamesOffset=0xB1DB1
+MoveNamesOffset=0xB1657
+
+[Blue (J)]
+Game=POKEMON BLUE
+Version=0
+NonJapanese=0
+Type=RB
+CopyFrom=Red (J)
+PokedexOrder=0x42784
+PokemonNamesOffset=0x39446
+PokemonStatsOffset=0x383DE
+MewStatsOffset=0x425B
+OldRodOffset=0xE3C6
+GoodRodOffset=0xE3F3
+SuperRodTableOffset=0xEC49
+MapNameTableOffset=0x7189E
+MoveDataOffset=0x38000
+TypeEffectivenessOffset=0x3E75B
+ItemNamesOffset=0x4733
+StarterOffsets1=[0x1CBBF, 0x1C6C2, 0x1CBA7, 0x3A069, 0x514A1, 0x515CB]
+StarterOffsets2=[0x1CB9D, 0x19C5E, 0x1C6C6, 0x1C806, 0x1CBB8, 0x5149D, 0x515C7, 0x52A1F, 0x606AD, 0x61F2D, 0x77006]
+StarterOffsets3=[0x1CBAE, 0x19C66, 0x1C80E, 0x1CBC9, 0x3A063, 0x5149F, 0x515C9, 0x52A27, 0x606B5, 0x61F35, 0x7700E]
+TMMovesOffset=0x13C93
+TrainerClassNamesOffsets=[0x27EA1, 0x39DB5]
+IntroPokemonOffset=0x60C4
+IntroCryOffset=0x1C77
+MapBanks=0xC275
+MapAddresses=0x0167
+SpecialMapList=0x47965
+SpecialMapPointerTable=0x479BB
+HiddenItemRoutine=0x77D7B
+TradeTableOffset=0x72033
+TradeTableSize=10
+TradeNameLength=4
+TradesUnused=[2]
+StaticPokemonSupport=1
+StaticPokemonPokeballs=[0x1E771, 0x5E38F, 0x5E32F]
+StaticPokemonOverworlds=[0x1F0A7, 0x1F0AF, 0x1F0B7, 0x1F0BF, 0x1F0C7, 0x1F0CF, 0x1F0D7, 0x1F0DF, 0x1F0E7, 0x4780D, 0x526D6, 0x46C57, 0x5A079, 0x5A8C9]
+StaticPokemonFossils=[0x617D7, 0x617DB, 0x617DF]
+StaticPokemonGifts=[0x52B1D, 0x4A553]
+StaticPokemonGameCorner[]=[0x53C12,0x53D6C] // Abra
+StaticPokemonGameCorner[]=[0x53C13,0x53D6E] // Clefairy
+StaticPokemonGameCorner[]=[0x53C14,0x53D70] // Nidorina/Nidorino
+StaticPokemonGameCorner[]=[0x53C1D,0x53D72] // Dratini/Pinsir
+StaticPokemonGameCorner[]=[0x53C1E,0x53D74] // Scyther/Dratini
+StaticPokemonGameCorner[]=[0x53C1F,0x53D76] // Porygon
+
+[Yellow (J)]
+Game=POKEMON YELLOW
+Version=0
+NonJapanese=0
+Type=Yellow
+CopyFrom=Red (J)
+PokedexOrder=0x4282D
+PokemonNamesOffset=0x39462
+PokemonNamesLength=5
+PokemonStatsOffset=0x383DE
+MewStatsOffset=0
+WildPokemonTableOffset=0xCB91
+OldRodOffset=0xE214
+GoodRodOffset=0xE241
+SuperRodTableOffset=0xA4C7D
+MapNameTableOffset=0x713CA
+MoveDataOffset=0x38000
+TypeEffectivenessOffset=0x3E8EA
+PokemonMovesetsTableOffset=0x3B59C
+StarterOffsets1=[0x18F19, 0x1D0A7, 0x1D0CC]
+StarterOffsets2=[0x3A5FB]
+ItemNamesOffset=0x45C4
+CanChangeTrainerText=0
+TrainerDataTableOffset=0x3A142
+TrainerDataClassCounts=[0, 14, 15, 19, 8, 10, 25, 7, 12, 14, 15, 9, 3, 0, 11, 15, 9, 7, 15, 4, 2, 8, 6, 17, 9, 3, 3, 0, 13, 3, 49, 10, 8, 1, 1, 1, 1, 1, 1, 1, 1, 5, 10, 3, 1, 24, 1, 1]
+ExtraTrainerMovesTableOffset=0x39FDC
+GymLeaderMovesTableOffset=0
+TMMovesOffset=0x1286C
+TrainerClassNamesOffsets=[0x27E56, 0x39D34]
+IntroPokemonOffset=0x5E3A
+IntroCryOffset=0x1ABF
+MapBanks=0xFC3E4
+MapAddresses=0xFC1F2
+SpecialMapPointerTable=0xF2B7F
+HiddenItemRoutine=0x77C4D
+TradeTableOffset=0x71B77
+TradeTableSize=10
+TradeNameLength=5
+TradesUnused=[2,4,6]
+StaticPokemonSupport=1
+StaticPokemonPokeballs=[0x1E81D, 0x5E146, 0x5E0E6]
+StaticPokemonOverworlds=[0x1F155, 0x1F15D, 0x1F165, 0x1F16D, 0x1F175, 0x1F17D, 0x1F185, 0x1F18D, 0x1F195, 0x47AEB, 0x525B9, 0x46F24, 0x59E7A, 0x5A6CA]
+StaticPokemonFossils=[0x616A5, 0x616A9, 0x616AD]
+StaticPokemonGifts=[0x529E7, 0xF20D5, 0x1DB40, 0x51DFE, 0xF0C1F]
+StaticPokemonGameCorner[] = [0x53A1B,0x53B74] // Abra
+StaticPokemonGameCorner[] = [0x53A1C,0x53B76] // Vulpix
+StaticPokemonGameCorner[] = [0x53A1D,0x53B78] // Wigglytuff
+StaticPokemonGameCorner[] = [0x53A26,0x53B7A] // Scyther
+StaticPokemonGameCorner[] = [0x53A27,0x53B7C] // Pinsir
+StaticPokemonGameCorner[] = [0x53A28,0x53B7E] // Porygon
+
+[Red (F)]
+Game=POKEMON RED
+Version=0
+NonJapanese=1
+Type=RB
+CRCInHeader=0x7AFC
+CopyFrom=Red (U)
+ExtraTableFile=rby_freger
+OldRodOffset=0xE242
+GoodRodOffset=0xE26F
+SuperRodTableOffset=0xE909
+MapNameTableOffset=0x71317
+PokedexOrder=0x40FAA
+TypeEffectivenessOffset=0x3E489
+PokemonMovesetsTableOffset=0x3B05F
+ItemNamesOffset=0x472D
+StarterOffsets1=[0x1D126, 0x1CC84, 0x1D10E, 0x39CFB, 0x50FB3, 0x510DD]
+StarterOffsets2=[0x1D104, 0x19596, 0x1CC88, 0x1CDC8, 0x1D11F, 0x50FAF, 0x510D9, 0x51CB2, 0x6060E, 0x61450, 0x75FE0]
+StarterOffsets3=[0x1D115, 0x1959E, 0x1CDD0, 0x1D130, 0x39CF5, 0x50FB1, 0x510DB, 0x51CBA, 0x60616, 0x61458, 0x75FE8]
+CanChangeStarterText=0
+PokedexRamOffset=0xD2FC
+TrainerDataTableOffset=0x39D3E
+ExtraTrainerMovesTableOffset=0x39D35
+GymLeaderMovesTableOffset=0x39D26
+TMMovesOffset=0x13782
+TrainerClassNamesOffsets=[0x27EBF, 0x399FF]
+IntroPokemonOffset=0x6208
+IntroCryOffset=0x1C6F
+HiddenItemRoutine=0x766CA
+TradeTableOffset=0x71B4C
+StaticPokemonSupport=1
+StaticPokemonPokeballs=[0x1DD4C, 0x5CF57, 0x5CF0F]
+StaticPokemonOverworlds=[0x1E3D8, 0x1E3E0, 0x1E3E8, 0x1E3F0, 0x1E3F8, 0x1E400, 0x1E408, 0x1E410, 0x1E418, 0x468E8, 0x51966, 0x45F44, 0x59630, 0x59970]
+StaticPokemonFossils=[0x61064, 0x61068, 0x6106C]
+StaticPokemonGifts=[0x51DB0, 0x4931F]
+StaticPokemonGameCorner[]=[0x5285C,0x5298F] // Abra
+StaticPokemonGameCorner[]=[0x5285D,0x52991] // Clefairy
+StaticPokemonGameCorner[]=[0x5285E,0x52993] // Nidorina/Nidorino
+StaticPokemonGameCorner[]=[0x52867,0x52995] // Dratini/Pinsir
+StaticPokemonGameCorner[]=[0x52868,0x52997] // Scyther/Dratini
+StaticPokemonGameCorner[]=[0x52869,0x52999] // Porygon
+
+[Blue (F)]
+Game=POKEMON BLUE
+Version=0
+NonJapanese=1
+Type=RB
+CopyStaticPokemon=1
+CRCInHeader=0x56A4
+CopyFrom=Red (F)
+
+[Red (S)]
+Game=POKEMON RED
+Version=0
+NonJapanese=1
+Type=RB
+CRCInHeader=0x384A
+CopyFrom=Red (U)
+ExtraTableFile=rby_espita
+OldRodOffset=0xE254
+GoodRodOffset=0xE281
+SuperRodTableOffset=0xE91B
+MapNameTableOffset=0x71316
+PokedexOrder=0x40FB4
+TypeEffectivenessOffset=0x3E483
+PokemonMovesetsTableOffset=0x3B069
+ItemNamesOffset=0x472B
+StarterOffsets1=[0x1D126, 0x1CC84, 0x1D10E, 0x39D05, 0x50FB3, 0x510DD]
+StarterOffsets2=[0x1D104, 0x19596, 0x1CC88, 0x1CDC8, 0x1D11F, 0x50FAF, 0x510D9, 0x51CAB, 0x6060E, 0x61450, 0x76026]
+StarterOffsets3=[0x1D115, 0x1959E, 0x1CDD0, 0x1D130, 0x39CFF, 0x50FB1, 0x510DB, 0x51CB3, 0x60616, 0x61458, 0x7602E]
+CanChangeStarterText=0
+PokedexRamOffset=0xD2FC
+TrainerDataTableOffset=0x39D48
+ExtraTrainerMovesTableOffset=0x39D3F
+GymLeaderMovesTableOffset=0x39D30
+TMMovesOffset=0x13798
+TrainerClassNamesOffsets=[0x27ECB, 0x399FF]
+IntroPokemonOffset=0x61CC
+IntroCryOffset=0x1C72
+HiddenItemRoutine=0x76710
+TradeTableOffset=0x71B6B
+StaticPokemonSupport=1
+StaticPokemonPokeballs=[0x1DD4A, 0x5CF63, 0x5CF1B]
+StaticPokemonOverworlds=[0x1E3D6, 0x1E3DE, 0x1E3E6, 0x1E3EE, 0x1E3F6, 0x1E3FE, 0x1E406, 0x1E40E, 0x1E416, 0x468E8, 0x5195F, 0x45F44, 0x59630, 0x59970]
+StaticPokemonFossils=[0x61064, 0x61068, 0x6106C]
+StaticPokemonGifts=[0x51DA9, 0x49323]
+StaticPokemonGameCorner[]=[0x52856,0x52989] // Abra
+StaticPokemonGameCorner[]=[0x52857,0x5298B] // Clefairy
+StaticPokemonGameCorner[]=[0x52858,0x5298D] // Nidorina/Nidorino
+StaticPokemonGameCorner[]=[0x52861,0x5298F] // Dratini/Pinsir
+StaticPokemonGameCorner[]=[0x52862,0x52991] // Scyther/Dratini
+StaticPokemonGameCorner[]=[0x52863,0x52993] // Porygon
+
+[Blue (S)]
+Game=POKEMON BLUE
+Version=0
+NonJapanese=1
+Type=RB
+CopyStaticPokemon=1
+CRCInHeader=0x14D7
+CopyFrom=Red (S)
+
+
+[Red (G)]
+Game=POKEMON RED
+Version=0
+NonJapanese=1
+Type=RB
+CRCInHeader=0x5CDC
+CopyFrom=Red (U)
+ExtraTableFile=rby_freger
+OldRodOffset=0xE24B
+GoodRodOffset=0xE278
+SuperRodTableOffset=0xE912
+MapNameTableOffset=0x71310
+PokedexOrder=0x40F96
+TypeEffectivenessOffset=0x3E482
+PokemonMovesetsTableOffset=0x3B064
+ItemNamesOffset=0x472D
+StarterOffsets1=[0x1D126, 0x1CC84, 0x1D10E, 0x39D00, 0x50FB3, 0x510DD]
+StarterOffsets2=[0x1D104, 0x19596, 0x1CC88, 0x1CDC8, 0x1D11F, 0x50FAF, 0x510D9, 0x51CA8, 0x6060E, 0x61450, 0x75FF1]
+StarterOffsets3=[0x1D115, 0x1959E, 0x1CDD0, 0x1D130, 0x39CFA, 0x50FB1, 0x510DB, 0x51CB0, 0x60616, 0x61458, 0x75FF9]
+CanChangeStarterText=0
+PokedexRamOffset=0xD2FC
+TrainerDataTableOffset=0x39D43
+TrainerDataClassCounts=[0, 13, 14, 18, 8, 9, 24, 7, 12, 14, 15, 9, 3, 0, 11, 15, 9, 7, 15, 4, 2, 8, 6, 17, 9, 9, 3, 0, 13, 3, 41, 10, 8, 1, 1, 1, 1, 1, 1, 1, 1, 5, 12, 3, 1, 24, 1, 1]
+ExtraTrainerMovesTableOffset=0x39D3A
+GymLeaderMovesTableOffset=0x39D2B
+TMMovesOffset=0x13774
+TrainerClassNamesOffsets=[0x27EC3, 0x399FF]
+IntroPokemonOffset=0x6194
+IntroCryOffset=0x1C73
+HiddenItemRoutine=0x766D8
+TradeTableOffset=0x71B55
+StaticPokemonSupport=1
+StaticPokemonPokeballs=[0x1DD49, 0x5CF5D, 0x5CF15]
+StaticPokemonOverworlds=[0x1E3D5, 0x1E3DD, 0x1E3E5, 0x1E3ED, 0x1E3F5, 0x1E3FD, 0x1E405, 0x1E40D, 0x1E415, 0x468E8, 0x5195C, 0x45F44, 0x59630, 0x59970]
+StaticPokemonFossils=[0x61064, 0x61068, 0x6106C]
+StaticPokemonGifts=[0x51DA6, 0x49323]
+StaticPokemonGameCorner[]=[0x52851,0x52984] // Abra
+StaticPokemonGameCorner[]=[0x52852,0x52986] // Clefairy
+StaticPokemonGameCorner[]=[0x52853,0x52988] // Nidorina/Nidorino
+StaticPokemonGameCorner[]=[0x5285C,0x5298A] // Dratini/Pinsir
+StaticPokemonGameCorner[]=[0x5285D,0x5298C] // Scyther/Dratini
+StaticPokemonGameCorner[]=[0x5285E,0x5298E] // Porygon
+
+[Blue (G)]
+Game=POKEMON BLUE
+Version=0
+NonJapanese=1
+Type=RB
+CopyStaticPokemon=1
+CRCInHeader=0x2EBC
+CopyFrom=Red (G)
+HiddenItemRoutine=0x766D9
+StarterOffsets2=[0x1D104, 0x19596, 0x1CC88, 0x1CDC8, 0x1D11F, 0x50FAF, 0x510D9, 0x51CA8, 0x6060E, 0x61450, 0x75FF2]
+StarterOffsets3=[0x1D115, 0x1959E, 0x1CDD0, 0x1D130, 0x39CFA, 0x50FB1, 0x510DB, 0x51CB0, 0x60616, 0x61458, 0x75FFA]
+
+[Red (I)]
+Game=POKEMON RED
+Version=0
+NonJapanese=1
+Type=RB
+CRCInHeader=0x89D2
+CopyFrom=Red (U)
+ExtraTableFile=rby_espita
+OldRodOffset=0xE24C
+GoodRodOffset=0xE279
+SuperRodTableOffset=0xE913
+MapNameTableOffset=0x71313
+PokedexOrder=0x40FB6
+TypeEffectivenessOffset=0x3E477
+PokemonMovesetsTableOffset=0x3B096
+ItemNamesOffset=0x472D
+StarterOffsets1=[0x1D126, 0x1CC84, 0x1D10E, 0x39D20, 0x50FB3, 0x510DD]
+StarterOffsets2=[0x1D104, 0x19596, 0x1CC88, 0x1CDC8, 0x1D11F, 0x50FAF, 0x510D9, 0x51CAE, 0x6060E, 0x61450, 0x76015]
+StarterOffsets3=[0x1D115, 0x1959E, 0x1CDD0, 0x1D130, 0x39D1A, 0x50FB1, 0x510DB, 0x51CB6, 0x60616, 0x61458, 0x7601D]
+CanChangeStarterText=0
+PokedexRamOffset=0xD2FC
+TrainerDataTableOffset=0x39D63
+ExtraTrainerMovesTableOffset=0x39D5A
+GymLeaderMovesTableOffset=0x39D4B
+TMMovesOffset=0x13798
+TrainerClassNamesOffsets=[0x27ECD, 0x399FF]
+IntroPokemonOffset=0x61CC
+IntroCryOffset=0x1C73
+HiddenItemRoutine=0x766FF
+TradeTableOffset=0x71BBB
+StaticPokemonSupport=1
+StaticPokemonPokeballs=[0x1DD4A, 0x5CF5A, 0x5CF12]
+StaticPokemonOverworlds=[0x1E3D6, 0x1E3DE, 0x1E3E6, 0x1E3EE, 0x1E3F6, 0x1E3FE, 0x1E406, 0x1E40E, 0x1E416, 0x468E8, 0x51962, 0x45F44, 0x59630, 0x59970]
+StaticPokemonFossils=[0x61064, 0x61068, 0x6106C]
+StaticPokemonGifts=[0x51DAC, 0x49322]
+StaticPokemonGameCorner[]=[0x52858,0x5298C] // Abra
+StaticPokemonGameCorner[]=[0x52859,0x5298E] // Clefairy
+StaticPokemonGameCorner[]=[0x5285A,0x52990] // Nidorina/Nidorino
+StaticPokemonGameCorner[]=[0x52863,0x52992] // Dratini/Pinsir
+StaticPokemonGameCorner[]=[0x52864,0x52994] // Scyther/Dratini
+StaticPokemonGameCorner[]=[0x52865,0x52996] // Porygon
+
+[Blue (I)]
+Game=POKEMON BLUE
+Version=0
+NonJapanese=1
+Type=RB
+CopyStaticPokemon=1
+CRCInHeader=0x5E9C
+CopyFrom=Red (I)
+HiddenItemRoutine=0x766FD
+StarterOffsets2=[0x1D104, 0x19596, 0x1CC88, 0x1CDC8, 0x1D11F, 0x50FAF, 0x510D9, 0x51CAE, 0x6060E, 0x61450, 0x76013]
+StarterOffsets3=[0x1D115, 0x1959E, 0x1CDD0, 0x1D130, 0x39D1A, 0x50FB1, 0x510DB, 0x51CB6, 0x60616, 0x61458, 0x7601B]
+IntroPokemonOffset=0x61CB
+
+[Yellow (F)]
+Game=POKEMON YELAPSF
+Version=0
+NonJapanese=1
+Type=Yellow
+CopyFrom=Yellow (U)
+ExtraTableFile=rby_freger
+OldRodOffset=0xE0EF
+GoodRodOffset=0xE11C
+SuperRodTableOffset=0xF5ED4
+MapNameTableOffset=0x713A0
+PokedexOrder=0x41036
+TypeEffectivenessOffset=0x3E610
+PokemonMovesetsTableOffset=0x3B1E8
+ItemNamesOffset=0x45B8
+StarterOffsets2=[0x3A28D]
+TrainerDataTableOffset=0x39DD4
+ExtraTrainerMovesTableOffset=0x39C6E
+TMMovesOffset=0x1233C
+TrainerClassNamesOffsets=[0x27E74, 0x3997E]
+IntroPokemonOffset=0x5F64
+IntroCryOffset=0x1A48
+SpecialMapPointerTable=0xF25CF
+HiddenItemRoutine=0x75F69
+TradeTableOffset=0x71BEE
+StaticPokemonSupport=1
+StaticPokemonPokeballs=[0x1D655, 0x5CE4D, 0x5CE05]
+StaticPokemonOverworlds=[0x1DCE2, 0x1DCEA, 0x1DCF2, 0x1DCFA, 0x1DD02, 0x1DD0A, 0x1DD12, 0x1DD1A, 0x1DD22, 0x46B5A, 0x519A8, 0x461A5, 0x594CC, 0x5980C]
+StaticPokemonFossils=[0x61050, 0x61054, 0x61058]
+StaticPokemonGifts=[0x51DD9, 0xF2102, 0x1CF8C, 0x515B2, 0xF1987]
+StaticPokemonGameCorner[] = [0x527BD,0x528EF] // Abra
+StaticPokemonGameCorner[] = [0x527BE,0x528F1] // Vulpix
+StaticPokemonGameCorner[] = [0x527BF,0x528F3] // Wigglytuff
+StaticPokemonGameCorner[] = [0x527C8,0x528F5] // Scyther
+StaticPokemonGameCorner[] = [0x527C9,0x528F7] // Pinsir
+StaticPokemonGameCorner[] = [0x527CA,0x528F9] // Porygon
+
+[Yellow (G)]
+Game=POKEMON YELAPSD
+Version=0
+NonJapanese=1
+Type=Yellow
+CopyFrom=Yellow (U)
+ExtraTableFile=rby_freger
+OldRodOffset=0xE0F4
+GoodRodOffset=0xE121
+SuperRodTableOffset=0xF5ED3
+MapNameTableOffset=0x71399
+PokedexOrder=0x41023
+TypeEffectivenessOffset=0x3E609
+PokemonMovesetsTableOffset=0x3B1F2
+ItemNamesOffset=0x45B8
+StarterOffsets2=[0x3A297]
+TrainerDataTableOffset=0x39DDE
+ExtraTrainerMovesTableOffset=0x39C78
+TMMovesOffset=0x1232E
+TrainerClassNamesOffsets=[0x27E78, 0x3997E]
+IntroPokemonOffset=0x5EF0
+IntroCryOffset=0x1A51
+SpecialMapPointerTable=0xF25EE
+HiddenItemRoutine=0x75F6E
+TradeTableOffset=0x71BFC
+StaticPokemonSupport=1
+StaticPokemonPokeballs=[0x1D652, 0x5CE53, 0x5CE0B]
+StaticPokemonOverworlds=[0x1DCDF, 0x1DCE7, 0x1DCEF, 0x1DCF7, 0x1DCFF, 0x1DD07, 0x1DD0F, 0x1DD17, 0x1DD1F, 0x46B5A, 0x5199E, 0x461A5, 0x594CC, 0x5980C]
+StaticPokemonFossils=[0x61050, 0x61054, 0x61058]
+StaticPokemonGifts=[0x51DCF, 0xF2121, 0x1CF8C, 0x515A8, 0xF19A6]
+StaticPokemonGameCorner[] = [0x527B2,0x528E4] // Abra
+StaticPokemonGameCorner[] = [0x527B3,0x528E6] // Vulpix
+StaticPokemonGameCorner[] = [0x527B4,0x528E8] // Wigglytuff
+StaticPokemonGameCorner[] = [0x527BD,0x528EA] // Scyther
+StaticPokemonGameCorner[] = [0x527BE,0x528EC] // Pinsir
+StaticPokemonGameCorner[] = [0x527BF,0x528EE] // Porygon
+
+[Yellow (I)]
+Game=POKEMON YELAPSI
+Version=0
+NonJapanese=1
+Type=Yellow
+CopyFrom=Yellow (U)
+ExtraTableFile=rby_espita
+OldRodOffset=0xE103
+GoodRodOffset=0xE130
+SuperRodTableOffset=0xF5ECE
+MapNameTableOffset=0x7139C
+PokedexOrder=0x41043
+TypeEffectivenessOffset=0x3E60C
+PokemonMovesetsTableOffset=0x3B20D
+ItemNamesOffset=0x45B8
+StarterOffsets2=[0x3A2B2]
+TrainerDataTableOffset=0x39DF9
+ExtraTrainerMovesTableOffset=0x39C93
+TMMovesOffset=0x12352
+TrainerClassNamesOffsets=[0x27E82, 0x3997E]
+IntroPokemonOffset=0x5F2A
+IntroCryOffset=0x1A4C
+SpecialMapPointerTable=0xF2609
+HiddenItemRoutine=0x75F70
+TradeTableOffset=0x71C5D
+StaticPokemonSupport=1
+StaticPokemonPokeballs=[0x1D653, 0x5CE50, 0x5CE08]
+StaticPokemonOverworlds=[0x1DCE0, 0x1DCE8, 0x1DCF0, 0x1DCF8, 0x1DD00, 0x1DD08, 0x1DD10, 0x1DD18, 0x1DD20, 0x46B5A, 0x519A4, 0x461A5, 0x594CC, 0x5980C]
+StaticPokemonFossils=[0x61050, 0x61054, 0x61058]
+StaticPokemonGifts=[0x51DD5, 0xF213C, 0x1CF8C, 0x515AE, 0xF19C1]
+StaticPokemonGameCorner[] = [0x527B9,0x528EC] // Abra
+StaticPokemonGameCorner[] = [0x527BA,0x528EE] // Vulpix
+StaticPokemonGameCorner[] = [0x527BB,0x528F0] // Wigglytuff
+StaticPokemonGameCorner[] = [0x527C4,0x528F2] // Scyther
+StaticPokemonGameCorner[] = [0x527C5,0x528F4] // Pinsir
+StaticPokemonGameCorner[] = [0x527C6,0x528F6] // Porygon
+
+[Yellow (S)]
+Game=POKEMON YELAPSS
+Version=0
+NonJapanese=1
+Type=Yellow
+CopyFrom=Yellow (U)
+ExtraTableFile=rby_espita
+OldRodOffset=0xE102
+GoodRodOffset=0xE12F
+SuperRodTableOffset=0xF5ED2
+MapNameTableOffset=0x7139F
+PokedexOrder=0x41041
+TypeEffectivenessOffset=0x3E60A
+PokemonMovesetsTableOffset=0x3B1F2
+ItemNamesOffset=0x45B8
+StarterOffsets2=[0x3A297]
+TrainerDataTableOffset=0x39DDE
+ExtraTrainerMovesTableOffset=0x39C78
+TMMovesOffset=0x12352
+TrainerClassNamesOffsets=[0x27E80, 0x3997E]
+IntroPokemonOffset=0x5F22
+IntroCryOffset=0x1A4B
+SpecialMapPointerTable=0xF2609
+HiddenItemRoutine=0x75F6F
+TradeTableOffset=0x71C0D
+StaticPokemonSupport=1
+StaticPokemonPokeballs=[0x1D653, 0x5CE59, 0x5CE11]
+StaticPokemonOverworlds=[0x1DCE0, 0x1DCE8, 0x1DCF0, 0x1DCF8, 0x1DD00, 0x1DD08, 0x1DD10, 0x1DD18, 0x1DD20, 0x46B5A, 0x519A1, 0x461A5, 0x594CC, 0x5980C]
+StaticPokemonFossils=[0x61050, 0x61054, 0x61058]
+StaticPokemonGifts=[0x51DD2, 0xF213C, 0x1CF8C, 0x515AB, 0xF19C1]
+StaticPokemonGameCorner[] = [0x527B7,0x528E9] // Abra
+StaticPokemonGameCorner[] = [0x527B8,0x528EB] // Vulpix
+StaticPokemonGameCorner[] = [0x527B9,0x528ED] // Wigglytuff
+StaticPokemonGameCorner[] = [0x527C2,0x528EF] // Scyther
+StaticPokemonGameCorner[] = [0x527C3,0x528F1] // Pinsir
+StaticPokemonGameCorner[] = [0x527C4,0x528F3] // Porygon
\ No newline at end of file
diff --git a/src/com/dabomstew/pkrandom/config/gen2_offsets.ini b/src/com/dabomstew/pkrandom/config/gen2_offsets.ini
new file mode 100755
index 000000000..c4fb04608
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/config/gen2_offsets.ini
@@ -0,0 +1,604 @@
+[Gold (U)]
+Game=AAUE
+Version=0
+NonJapanese=1
+Type=GS
+ExtraTableFile=gsc_english
+BWXPTweak=gs_en_bwxp
+PokemonNamesOffset=0x1B0B74
+PokemonNamesLength=10
+PokemonStatsOffset=0x51B0B
+WildPokemonOffset=0x2AB35
+FishingWildsOffset=0x92A52
+HeadbuttWildsOffset=0xBA47C
+HeadbuttTableSize=7
+BCCWildsOffset=0x97BB8
+FleeingDataOffset=0x3C551
+MoveDataOffset=0x41AFF
+MoveNamesOffset=0x1B1574
+ItemNamesOffset=0x1B0000
+PokemonMovesetsTableOffset=0x427BD
+SupportsFourStartingMoves=0
+StarterOffsets1=[0x1800D2, 0x1800D4, 0x1800EB, 0x1800F6]
+StarterOffsets2=[0x180114, 0x180116, 0x18012D, 0x180138]
+StarterOffsets3=[0x180150, 0x180152, 0x180169, 0x180174]
+StarterHeldItems=[0x1800F8, 0x18013A, 0x180176]
+CanChangeStarterText=1
+CanChangeTrainerText=1
+TrainerClassAmount=0x42
+TrainerDataTableOffset=0x3993E
+TrainerDataClassCounts=[0, 1, 1, 1, 1, 1, 1, 1, 1, 15, 0, 1, 3, 1, 1, 1, 1, 1, 1, 1, 5, 1, 12, 18, 19, 15, 1, 19, 20, 16, 13, 31, 5, 2, 3, 1, 14, 22, 21, 19, 12, 12, 6, 2, 20, 9, 1, 3, 8, 5, 9, 4, 12, 21, 19, 2, 9, 7, 3, 12, 6, 8, 5, 1, 1, 2, 5]
+TMMovesOffset=0x11A66
+TrainerClassNamesOffset=0x1B0955
+IntroSpriteOffset=0x5FDE
+IntroCryOffset=0x6061
+MapHeaders=0x940ED
+LandmarkTableOffset=0x92382
+LandmarkCount=95
+TradeTableOffset=0xFCC24
+TradeTableSize=6
+TradeNameLength=11
+TradeOTLength=11
+TradesUnused=[]
+StaticPokemonSupport=1
+GameCornerPokemonNameLength=11
+StaticPokemonOverworlds=[0x111775, 0x114DBD, 0x114DE8, 0x114E13, 0x11C1B6, 0x124F7A, 0x12E1D6, 0x13D2AB, 0x16E929]
+StaticPokemonRocketBase=[0x1146FE, 0x114711, 0x114724]
+StaticPokemonGifts=[0x73E6, 0x119F20, 0x15924F, 0x1599FC, 0x15CC10]
+StaticPokemonRoamers=[0x2A7D8, 0x2A7DD, 0x2A7E2]
+StaticPokemonGameCorner[]=[0x15E8B7, 0x15E93D] // Abra
+StaticPokemonGameCorner[]=[0x15E8E5, 0x15E94D] // Ekans
+StaticPokemonGameCorner[]=[0x15E913, 0x15E95D] // Dratini
+StaticPokemonGameCorner[]=[0x15E99C, 0x15EA22] // Abra
+StaticPokemonGameCorner[]=[0x15E9CA, 0x15EA32] // Sandshrew
+StaticPokemonGameCorner[]=[0x15E9F8, 0x15EA42] // Dratini
+StaticPokemonGameCorner[]=[0x179B9C, 0x179C22] // Mr.Mime
+StaticPokemonGameCorner[]=[0x179BCA, 0x179C32] // Eevee
+StaticPokemonGameCorner[]=[0x179BF8, 0x179C42] // Porygon
+StaticPokemonCopy[]=[0x11C1B6,0x11C1C1] // Silver Lugia
+StaticPokemonCopy[]=[0x16E929,0x16E934] // Silver Ho-Oh
+TMText[]=[1,0x1755D0,That is\n%m.\e]
+TMText[]=[3,0x17933A,TM03 is\n%m.\pIt's a terrifying\nmove!\e]
+TMText[]=[5,0x12CC1A,WROOOAR!\nIT'S %m!\e]
+TMText[]=[6,0x17031D,JANINE: You're so\ntough! I have a \lspecial gift!\pIt's %m!\e]
+TMText[]=[7,0x151346,MANAGER: TM07 is\nmy %m.\pIt's a powerful\ntechnique!\e]
+TMText[]=[8,0x12E465,That happens to be\n%m.\pIf any rocks are\nin your way, find\lROCK SMASH!\e]
+TMText[]=[10,0x14D5B5,Do you see it? It\n is %m!\e]
+TMText[]=[11,0x10DEC0,It's %m.\nUse it wisely.\e]
+TMText[]=[12,0x15F058,It's %m.\pUse it on\nenemy [POKé]MON.\e]
+TMText[]=[13,0x14519F,That there's\n%m.\pIt's a rare move.\e]
+TMText[]=[16,0x1456C0,That TM contains\n%m.\pIt demonstrates\nthe harshness of\lwinter.\e]
+TMText[]=[19,0x17A052,ERIKA: That was a\ndelightful match.\pI felt inspired.\nPlease, I wish you\lto have this TM.\pIt's %m.\pIt is a wonderful\nmove!\pPlease use it if\nit pleases you…\e]
+TMText[]=[23,0x144387,…That teaches\n%m.\e]
+TMText[]=[24,0x11C6D7,That contains\n%m.\pIf you don't want\nit, you don't have\lto take it.\e]
+TMText[]=[24,0x14C4A8,That contains\n%m.\pIf you don't want\nit, you don't have\lto take it.\e]
+TMText[]=[29,0x184B57,TM29 is\n%m.\pIt may be\nuseful.\e]
+TMText[]=[30,0x1493D7,It's %m.\pUse it if it\nappeals to you.\e]
+TMText[]=[31,0x1583B6,By using a TM, a\n[POKé]MON will\pinstantly learn a\nnew move.\pThink before you\nact--a TM can be\lused only once.\pTM31 contains\n%m.\e]
+TMText[]=[37,0x18244E,TM37 happens to be\n%m.\pIt's for advanced\ntrainers only.\pUse it if you\ndare. Good luck!\e]
+TMText[]=[42,0x138344,TM42 contains\n%m…\p…Zzz…\e]
+TMText[]=[45,0x15C308,It's %m!\pIsn't it just per-\nfect for a cutie\llike me?\e]
+TMText[]=[49,0x155061,TM49 contains\n%m.\pIsn't it great?\nI discovered it!\e]
+TMText[]=[50,0x129DBC,TM50 is\n%m.\pOoooh…\nIt's scary…\pI don't want to\nhave bad dreams.\e]
+
+[Silver (U)]
+Game=AAXE
+Version=0
+NonJapanese=1
+Type=GS
+CopyTMText=1
+CopyFrom=Gold (U)
+BWXPTweak=gs_en_bwxp
+StaticPokemonSupport=1
+StaticPokemonOverworlds=[0x111775, 0x114DBD, 0x114DE8, 0x114E13, 0x11C1B6, 0x124F7A, 0x12E1D6, 0x13D2AB, 0x16E929]
+StaticPokemonRocketBase=[0x1146FE, 0x114711, 0x114724]
+StaticPokemonGifts=[0x73AC, 0x119F20, 0x15924F, 0x1599FC, 0x15CC10]
+StaticPokemonRoamers=[0x2A7D8, 0x2A7DD, 0x2A7E2]
+StaticPokemonGameCorner[]=[0x15E8B7, 0x15E93D] // Abra
+StaticPokemonGameCorner[]=[0x15E8E5, 0x15E94D] // Ekans
+StaticPokemonGameCorner[]=[0x15E913, 0x15E95D] // Dratini
+StaticPokemonGameCorner[]=[0x15E99C, 0x15EA22] // Abra
+StaticPokemonGameCorner[]=[0x15E9CA, 0x15EA32] // Sandshrew
+StaticPokemonGameCorner[]=[0x15E9F8, 0x15EA42] // Dratini
+StaticPokemonGameCorner[]=[0x179B9C, 0x179C22] // Mr.Mime
+StaticPokemonGameCorner[]=[0x179BCA, 0x179C32] // Eevee
+StaticPokemonGameCorner[]=[0x179BF8, 0x179C42] // Porygon
+StaticPokemonCopy[]=[0x11C1B6,0x11C1C1] // Silver Lugia
+StaticPokemonCopy[]=[0x16E929,0x16E934] // Silver Ho-Oh
+
+[Crystal (U)]
+Game=BYTE
+Version=0
+NonJapanese=1
+Type=Crystal
+ExtraTableFile=gsc_english
+BWXPTweak=crystal_en_bwxp
+PokemonNamesOffset=0x53384
+PokemonNamesLength=10
+PokemonStatsOffset=0x51424
+WildPokemonOffset=0x2A5E9
+FishingWildsOffset=0x924E3
+HeadbuttWildsOffset=0xB82FA
+HeadbuttTableSize=13
+BCCWildsOffset=0x97D87
+FleeingDataOffset=0x3C59A
+MoveDataOffset=0x41AFC
+MoveNamesOffset=0x1C9F29
+ItemNamesOffset=0x1C8000
+PokemonMovesetsTableOffset=0x425B1
+SupportsFourStartingMoves=1
+StarterOffsets1=[0x78C7F, 0x78C81, 0x78C98, 0x78CA3]
+StarterOffsets2=[0x78CC1, 0x78CC3, 0x78CDA, 0x78CE5]
+StarterOffsets3=[0x78CFD, 0x78CFF, 0x78D16, 0x78D21]
+StarterHeldItems=[0x78CA5, 0x78CE7, 0x78D23]
+CanChangeStarterText=1
+CanChangeTrainerText=1
+TrainerClassAmount=0x43
+TrainerDataTableOffset=0x39999
+TrainerDataClassCounts=[0, 1, 1, 1, 1, 1, 1, 1, 1, 15, 0, 1, 3, 1, 1, 1, 1, 1, 1, 1, 5, 1, 14, 24, 19, 17, 1, 20, 21, 17, 15, 31, 5, 2, 3, 1, 19, 25, 21, 19, 13, 14, 6, 2, 22, 9, 1, 3, 8, 6, 9, 4, 12, 26, 22, 2, 12, 7, 3, 14, 6, 10, 6, 1, 1, 2, 5, 1]
+TMMovesOffset=0x1167A
+TrainerClassNamesOffset=0x2C1EF
+IntroSpriteOffset=0x5FD2
+IntroCryOffset=0x6050
+MapHeaders=0x94000
+LandmarkTableOffset=0x1CA8C3
+LandmarkCount=96
+TradeTableOffset=0xFCE58
+TradeTableSize=7
+TradeNameLength=11
+TradeOTLength=11
+TradesUnused=[]
+StaticPokemonSupport=1
+GameCornerPokemonNameLength=11
+StaticPokemonOverworlds=[0x5A324, 0x6D105, 0x6D130, 0x6D15B, 0x18C52A, 0x7006E, 0x194068, 0x1AA9B8, 0x77256, 0x1850EA]
+StaticPokemonRocketBase=[0x6CA43, 0x6CA56, 0x6CA69]
+StaticPokemonGifts=[0x730A, 0x7E22A, 0x694E2, 0x69D65, 0x54C06, 0x18D1D7]
+StaticPokemonOddEgg=[0x1FB56E, 0x1FB5A9, 0x1FB5E4, 0x1FB61F, 0x1FB65A, 0x1FB695, 0x1FB6D0, 0x1FB70B, 0x1FB746, 0x1FB781, 0x1FB7BC, 0x1FB7F7, 0x1FB832, 0x1FB86D]
+StaticPokemonRoamers=[0x2A2A1, 0x2A2A6]
+StaticPokemonGameCorner[]=[0x56D34, 0x56DBA] // Abra
+StaticPokemonGameCorner[]=[0x56D62, 0x56DCA] // Cubone
+StaticPokemonGameCorner[]=[0x56D90, 0x56DDA] // Wobbuffet
+StaticPokemonGameCorner[]=[0x727FB, 0x72881] // Pikachu
+StaticPokemonGameCorner[]=[0x72829, 0x72891] // Porygon
+StaticPokemonGameCorner[]=[0x72857, 0x728A1] // Larvitar
+MoveTutorMoves=[0x492B4, 0x492B7, 0x492B1]
+MoveTutorMenuOffset=0x19896C
+MoveTutorMenuNewSpace=0x19BB00
+TMText[]=[1,0x9D8DB,That is\n%m.\e]
+TMText[]=[3,0x71DB4,TM03 is\n%m.\pIt's a terrifying\nmove!\e]
+TMText[]=[5,0x19118D,WROOOAR!\nIT'S %m!\e]
+TMText[]=[6,0x196003,JANINE: You're so\ntough! I have a \lspecial gift!\pIt's %m!\e]
+TMText[]=[7,0x1893F5,MANAGER: TM07 is\nmy %m.\pIt's a powerful\ntechnique!\e]
+TMText[]=[8,0x19452D,That happens to be\n%m.\pIf any rocks are\nin your way, find\lROCK SMASH!\e]
+TMText[]=[10,0x19A5DF,Do you see it? It\n is %m!\e]
+TMText[]=[11,0x5E822,It's %m.\nUse it wisely.\e]
+TMText[]=[12,0x62DF7,It's %m.\pUse it on\nenemy [POKé]MON.\e]
+TMText[]=[13,0x9D1C8,That there's\n%m.\pIt's a rare move.\e]
+TMText[]=[16,0x199DF0,That TM contains\n%m.\pIt demonstrates\nthe harshness of\lwinter.\e]
+TMText[]=[19,0x72CB1,ERIKA: That was a\ndelightful match.\pI felt inspired.\nPlease, I wish you\lto have this TM.\pIt's %m.\pIt is a wonderful\nmove!\pPlease use it if\nit pleases you…\e]
+TMText[]=[23,0x9C3A6,…That teaches\n%m.\e]
+TMText[]=[24,0x18CA0E,That contains\n%m.\pIf you don't want\nit, you don't have\lto take it.\e]
+TMText[]=[24,0x1951D2,That contains\n%m.\pIf you don't want\nit, you don't have\lto take it.\e]
+TMText[]=[29,0x18A7BC,TM29 is\n%m.\pIt may be\nuseful.\e]
+TMText[]=[30,0x9A0ED,It's %m.\pUse it if it\nappeals to you.\e]
+TMText[]=[31,0x68649,By using a TM, a\n[POKé]MON will\pinstantly learn a\nnew move.\pThink before you\nact--a TM can be\lused only once.\pTM31 contains\n%m.\e]
+TMText[]=[37,0x7B490,TM37 happens to be\n%m.\pIt's for advanced\ntrainers only.\pUse it if you\ndare. Good luck!\e]
+TMText[]=[42,0x1A9D87,TM42 contains\n%m…\p…Zzz…\e]
+TMText[]=[45,0x54303,It's %m!\pIsn't it just per-\nfect for a cutie\llike me?\e]
+TMText[]=[49,0x18EEFB,TM49 contains\n%m.\pIsn't it great?\nI discovered it!\e]
+TMText[]=[50,0x1A5897,TM50 is\n%m.\pOoooh…\nIt's scary…\pI don't want to\nhave bad dreams.\e]
+
+[Crystal (U 1.1)]
+Game=BYTE
+Version=1
+NonJapanese=1
+Type=GS
+CopyStaticPokemon=1
+CopyFrom=Crystal (U)
+BWXPTweak=crystal_en_bwxp
+
+[Gold (J 1.0)]
+Game=AAUJ
+Version=0
+NonJapanese=0
+Type=GS
+PokemonNamesOffset=0x53A09
+PokemonNamesLength=5
+PokemonStatsOffset=0x51AA9
+WildPokemonOffset=0x2AC1B
+FishingWildsOffset=0x929A1
+HeadbuttWildsOffset=0xBA47C
+HeadbuttTableSize=7
+BCCWildsOffset=0x97BDC
+FleeingDataOffset=0x3C551
+MoveDataOffset=0x41C6D
+MoveNamesOffset=0x4163E
+ItemNamesOffset=0x7293
+PokemonMovesetsTableOffset=0x4295F
+SupportsFourStartingMoves=0
+StarterOffsets1=[0x4E598, 0x4E59A, 0x4E5B1, 0x4E5BC]
+StarterOffsets2=[0x4E5DA, 0x4E5DC, 0x4E5F3, 0x4E5FE]
+StarterOffsets3=[0x4E616, 0x4E618, 0x4E62F, 0x4E63A]
+StarterHeldItems=[0x4E5BE, 0x4E600, 0x4E63C]
+CanChangeStarterText=0
+CanChangeTrainerText=0
+TrainerClassAmount=0x42
+TrainerDataTableOffset=0x3995C
+TrainerDataClassCounts=[0, 1, 1, 1, 1, 1, 1, 1, 1, 15, 0, 1, 3, 1, 1, 1, 1, 1, 1, 1, 5, 1, 12, 18, 19, 15, 1, 19, 20, 16, 13, 31, 5, 2, 3, 1, 14, 22, 21, 19, 12, 12, 6, 2, 20, 9, 1, 3, 8, 5, 9, 4, 12, 21, 19, 2, 9, 7, 3, 12, 6, 8, 5, 1, 1, 2, 5]
+TMMovesOffset=0x11A00
+TrainerClassNamesOffset=0x2D2D6
+IntroSpriteOffset=0x5FEC
+IntroCryOffset=0x60ED
+MapHeaders=0x940ED
+LandmarkTableOffset=0x924B6
+LandmarkCount=95
+TradeTableOffset=0xFCC23
+TradeTableSize=6
+TradeNameLength=4
+TradeOTLength=3
+TradesUnused=[]
+StaticPokemonSupport=0
+
+[Gold (J 1.1)]
+Game=AAUJ
+Version=1
+NonJapanese=0
+Type=GS
+CopyFrom=Gold (J 1.0)
+
+[Silver (J 1.0)]
+Game=AAXJ
+Version=0
+NonJapanese=0
+Type=GS
+CopyFrom=Gold (J 1.0)
+
+[Silver (J 1.1)]
+Game=AAXJ
+Version=1
+NonJapanese=0
+Type=GS
+CopyFrom=Silver (J 1.0)
+
+[Crystal (J)]
+Game=BXTJ
+Version=0
+NonJapanese=0
+Type=Crystal
+PokemonNamesOffset=0x5341A
+PokemonNamesLength=5
+PokemonStatsOffset=0x514BA
+WildPokemonOffset=0x2A60C
+FishingWildsOffset=0x92A56
+HeadbuttWildsOffset=0xB82DA
+HeadbuttTableSize=13
+BCCWildsOffset=0x97D49
+FleeingDataOffset=0x3C599
+MoveDataOffset=0x41C6A
+MoveNamesOffset=0x4163B
+ItemNamesOffset=0x70FA
+PokemonMovesetsTableOffset=0x42753
+SupportsFourStartingMoves=0
+StarterOffsets1=[0x6E294, 0x6E296, 0x6E2AD, 0x6E2B8]
+StarterOffsets2=[0x6E2D6, 0x6E2D8, 0x6E2EF, 0x6E2FA]
+StarterOffsets3=[0x6E312, 0x6E314, 0x6E32B, 0x6E336]
+StarterHeldItems=[0x6E2BA, 0x6E2FC, 0x6E338]
+CanChangeStarterText=0
+CanChangeTrainerText=0
+TrainerClassAmount=0x43
+TrainerDataTableOffset=0x399BA
+TrainerDataClassCounts=[0, 1, 1, 1, 1, 1, 1, 1, 1, 15, 0, 1, 3, 1, 1, 1, 1, 1, 1, 1, 5, 1, 14, 24, 19, 17, 1, 20, 21, 17, 15, 31, 5, 2, 3, 1, 19, 25, 21, 19, 13, 14, 6, 2, 22, 9, 1, 3, 8, 6, 9, 4, 12, 26, 22, 2, 12, 7, 3, 14, 6, 10, 6, 1, 1, 2, 5, 1]
+TMMovesOffset=0x11614
+TrainerClassNamesOffset=0x2D319
+MapHeaders=0x94000
+LandmarkTableOffset=0x92557
+LandmarkCount=96
+TradeTableOffset=0xFCE57
+TradeTableSize=7
+TradeNameLength=4
+TradeOTLength=3
+TradesUnused=[]
+StaticPokemonSupport=0
+IntroSpriteOffset=0x5FC2
+IntroCryOffset=0x60BE
+MoveTutorMoves=[0x49206, 0x49209, 0x49203]
+
+[Gold (F)]
+Game=AAUF
+Version=0
+NonJapanese=1
+Type=GS
+CopyFrom=Gold (U)
+ExtraTableFile=gsc_freger
+PokemonNamesOffset=0x1B0BC5
+PokemonStatsOffset=0x51B10
+WildPokemonOffset=0x2ABB2
+FishingWildsOffset=0x92454
+BCCWildsOffset=0x97BD7
+MoveDataOffset=0x41B0A
+MoveNamesOffset=0x1B15C5
+PokemonMovesetsTableOffset=0x427C8
+TMMovesOffset=0x11A65
+TrainerClassNamesOffset=0x1B0995
+IntroSpriteOffset=0x6013
+IntroCryOffset=0x6096
+LandmarkTableOffset=0x9C02D
+LandmarkCount=95
+StaticPokemonSupport=1
+CanChangeStarterText=0
+GameCornerPokemonNameLength=11
+StaticPokemonOverworlds=[0x1117EA, 0x114DA7, 0x114DD2, 0x114DFD, 0x11C1B6, 0x125055, 0x12E13B, 0x13D1AF, 0x16E929]
+StaticPokemonRocketBase=[0x11470A, 0x11471D, 0x114730]
+StaticPokemonGifts=[0x741B, 0x119EC2, 0x159572, 0x16035E, 0x15CEB9]
+StaticPokemonRoamers=[0x2A855, 0x2A85A, 0x2A85F]
+StaticPokemonCopy[]=[0x11C1B6,0x11C1C1] // Silver Lugia
+StaticPokemonCopy[]=[0x16E929,0x16E934] // Silver Ho-Oh
+
+[Silver (F)]
+Game=AAXF
+Version=0
+NonJapanese=1
+Type=GS
+CopyFrom=Gold (F)
+
+[Gold (G)]
+Game=AAUD
+Version=0
+NonJapanese=1
+Type=GS
+CopyFrom=Gold (U)
+ExtraTableFile=gsc_freger
+PokemonNamesOffset=0x1B0B6B
+PokemonStatsOffset=0x51B00
+WildPokemonOffset=0x2ABB5
+FishingWildsOffset=0x9245F
+BCCWildsOffset=0x97BD7
+MoveDataOffset=0x41AF2
+MoveNamesOffset=0x1B156B
+PokemonMovesetsTableOffset=0x427B0
+TMMovesOffset=0x11A5D
+TrainerClassNamesOffset=0x1B0946
+IntroSpriteOffset=0x6016
+IntroCryOffset=0x6099
+LandmarkTableOffset=0x9C02D
+LandmarkCount=95
+StaticPokemonSupport=1
+CanChangeStarterText=0
+GameCornerPokemonNameLength=11
+StaticPokemonOverworlds=[0x111A2C, 0x114E62, 0x114E8D, 0x114EB8, 0x11C1B6, 0x125104, 0x12E5FE, 0x13D4EE, 0x16EC32]
+StaticPokemonRocketBase=[0x114719, 0x11472C, 0x11473F]
+StaticPokemonGifts=[0x741D, 0x11A249, 0x159680, 0x1603CA, 0x15CE51]
+StaticPokemonRoamers=[0x2A858, 0x2A85D, 0x2A862]
+StaticPokemonCopy[]=[0x11C1B6,0x11C1C1] // Silver Lugia
+StaticPokemonCopy[]=[0x16EC32,0x16EC3D] // Silver Ho-Oh
+
+[Silver (G)]
+Game=AAXD
+Version=0
+NonJapanese=1
+Type=GS
+CopyFrom=Gold (G)
+
+[Gold (S)]
+Game=AAUS
+Version=0
+NonJapanese=1
+Type=GS
+CopyFrom=Gold (U)
+ExtraTableFile=gsc_espita
+PokemonNamesOffset=0x1B0BB8
+PokemonStatsOffset=0x51B19
+WildPokemonOffset=0x2ABA0
+FishingWildsOffset=0x92464
+BCCWildsOffset=0x97BCF
+MoveDataOffset=0x41B10
+MoveNamesOffset=0x1B15B8
+PokemonMovesetsTableOffset=0x427CE
+TMMovesOffset=0x11A79
+TrainerClassNamesOffset=0x1B098B
+StaticPokemonSupport=1
+CanChangeStarterText=0
+IntroSpriteOffset=0x6022
+IntroCryOffset=0x60A5
+LandmarkTableOffset=0x9C02D
+LandmarkCount=95
+GameCornerPokemonNameLength=11
+StaticPokemonOverworlds=[0x111717, 0x114DD9, 0x114E04, 0x114E2F, 0x11C1B6, 0x124F53, 0x12E1D3, 0x13D2BE, 0x16E98D]
+StaticPokemonRocketBase=[0x11470D, 0x114720, 0x114733]
+StaticPokemonGifts=[0x742E, 0x119F0B, 0x15935C, 0x160329, 0x15CC68]
+StaticPokemonRoamers=[0x2A843, 0x2A848, 0x2A84D]
+StaticPokemonCopy[]=[0x11C1B6,0x11C1C1] // Silver Lugia
+StaticPokemonCopy[]=[0x16E98D,0x16E998] // Silver Ho-Oh
+
+[Silver (S)]
+Game=AAXS
+Version=0
+NonJapanese=1
+Type=GS
+CopyFrom=Gold (S)
+
+[Gold (I)]
+Game=AAUI
+Version=0
+NonJapanese=1
+Type=GS
+CopyFrom=Gold (U)
+ExtraTableFile=gsc_espita
+PokemonNamesOffset=0x1B0BD2
+PokemonStatsOffset=0x51B19
+WildPokemonOffset=0x2AB99
+FishingWildsOffset=0x92447
+BCCWildsOffset=0x97BD5
+MoveDataOffset=0x41AFE
+MoveNamesOffset=0x1B15D2
+PokemonMovesetsTableOffset=0x427BC
+TMMovesOffset=0x11A65
+TrainerClassNamesOffset=0x1B099A
+IntroSpriteOffset=0x6011
+IntroCryOffset=0x6094
+LandmarkTableOffset=0x9C02D
+LandmarkCount=95
+StaticPokemonSupport=1
+CanChangeStarterText=0
+GameCornerPokemonNameLength=11
+StaticPokemonOverworlds=[0x1117CF, 0x114DF8, 0x114E23, 0x114E4E, 0x11C1B6, 0x124F0F, 0x12E26A, 0x13D2D9, 0x16E958]
+StaticPokemonRocketBase=[0x1146DA, 0x1146ED, 0x114700]
+StaticPokemonGifts=[0x7418, 0x119EF3, 0x1593B0, 0x160332, 0x15CC91]
+StaticPokemonRoamers=[0x2A83C, 0x2A841, 0x2A846]
+StaticPokemonCopy[]=[0x11C1B6,0x11C1C1] // Silver Lugia
+StaticPokemonCopy[]=[0x16E958,0x16E963] // Silver Ho-Oh
+
+[Silver (I)]
+Game=AAXI
+Version=0
+NonJapanese=1
+Type=GS
+CopyFrom=Gold (I)
+
+[Crystal (F)]
+Game=BYTF
+Version=0
+NonJapanese=1
+Type=Crystal
+CopyFrom=Crystal (U)
+ExtraTableFile=gsc_freger
+PokemonNamesOffset=0x53377
+PokemonStatsOffset=0x51417
+WildPokemonOffset=0x2A5F2
+FishingWildsOffset=0x924FA
+HeadbuttWildsOffset=0xB830C
+BCCWildsOffset=0x97D88
+MoveDataOffset=0x41B07
+MoveNamesOffset=0x1C9F96
+PokemonMovesetsTableOffset=0x425BC
+SupportsFourStartingMoves=1
+StarterOffsets1=[0x78C67, 0x78C69, 0x78C80, 0x78C8B]
+StarterOffsets2=[0x78CA9, 0x78CAB, 0x78CC2, 0x78CCD]
+StarterOffsets3=[0x78CE5, 0x78CE7, 0x78CFE, 0x78D09]
+StarterHeldItems=[0x78C8D, 0x78CCF, 0x78D0B]
+TMMovesOffset=0x11679
+TrainerClassNamesOffset=0x2C1EF
+IntroSpriteOffset=0x5FEC
+IntroCryOffset=0x606A
+LandmarkTableOffset=0x1CA97F
+LandmarkCount=96
+StaticPokemonSupport=1
+CanChangeStarterText=0
+GameCornerPokemonNameLength=11
+StaticPokemonOverworlds=[0x5A403, 0x6D111, 0x6D13C, 0x6D167, 0x18C521, 0x7006E, 0x194068, 0x1AA8ED, 0x7727F, 0x1851CF]
+StaticPokemonRocketBase=[0x6CA7F, 0x6CA92, 0x6CAA5]
+StaticPokemonGifts=[0x7324, 0x7E1C2, 0x697B9, 0x69FF3, 0x54E6C, 0x18D1A6]
+StaticPokemonOddEgg=[0x1FB56E, 0x1FB5A9, 0x1FB5E4, 0x1FB61F, 0x1FB65A, 0x1FB695, 0x1FB6D0, 0x1FB70B, 0x1FB746, 0x1FB781, 0x1FB7BC, 0x1FB7F7, 0x1FB832, 0x1FB86D]
+StaticPokemonRoamers=[0x2A2AA, 0x2A2AF]
+MoveTutorMoves=[0x49212, 0x49215, 0x4920F]
+
+[Crystal (G)]
+Game=BYTD
+Version=0
+NonJapanese=1
+Type=Crystal
+CopyFrom=Crystal (U)
+ExtraTableFile=gsc_freger
+PokemonNamesOffset=0x5336E
+PokemonStatsOffset=0x5140E
+WildPokemonOffset=0x2A5FE
+FishingWildsOffset=0x92502
+HeadbuttWildsOffset=0xB830C
+BCCWildsOffset=0x97D88
+MoveDataOffset=0x41AEC
+MoveNamesOffset=0x1C9E9D
+PokemonMovesetsTableOffset=0x425A1
+SupportsFourStartingMoves=1
+StarterOffsets1=[0x78DFA, 0x78DFC, 0x78E13, 0x78E1E]
+StarterOffsets2=[0x78E3C, 0x78E3E, 0x78E55, 0x78E60]
+StarterOffsets3=[0x78E78, 0x78E7A, 0x78E91, 0x78E9C]
+StarterHeldItems=[0x78E20, 0x78E62, 0x78E9E]
+TMMovesOffset=0x11671
+TrainerClassNamesOffset=0x2C1EF
+IntroSpriteOffset=0x5FF3
+IntroCryOffset=0x6071
+LandmarkTableOffset=0x1CA8E5
+LandmarkCount=96
+StaticPokemonSupport=1
+CanChangeStarterText=0
+GameCornerPokemonNameLength=11
+StaticPokemonOverworlds=[0x5A6DB, 0x6D1FC, 0x6D227, 0x6D252, 0x18C5C5, 0x7006E, 0x194068, 0x1AAEC2, 0x77626, 0x185310]
+StaticPokemonRocketBase=[0x6CAB0, 0x6CAC3, 0x6CAD6]
+StaticPokemonGifts=[0x732B, 0x7E585, 0x69927, 0x6A2C8, 0x54E5A, 0x18D34F]
+StaticPokemonOddEgg=[0x1FB56E, 0x1FB5A9, 0x1FB5E4, 0x1FB61F, 0x1FB65A, 0x1FB695, 0x1FB6D0, 0x1FB70B, 0x1FB746, 0x1FB781, 0x1FB7BC, 0x1FB7F7, 0x1FB832, 0x1FB86D]
+StaticPokemonRoamers=[0x2A2B6, 0x2A2BB]
+MoveTutorMoves=[0x49213, 0x49216, 0x49210]
+
+[Crystal (S)]
+Game=BYTS
+Version=0
+NonJapanese=1
+Type=Crystal
+CopyFrom=Crystal (U)
+ExtraTableFile=gsc_espita
+PokemonNamesOffset=0x5338D
+PokemonStatsOffset=0x5142D
+WildPokemonOffset=0x2A5F0
+FishingWildsOffset=0x9250C
+HeadbuttWildsOffset=0xB830C
+BCCWildsOffset=0x97D80
+MoveDataOffset=0x41B0F
+MoveNamesOffset=0x1CA045
+PokemonMovesetsTableOffset=0x425C4
+SupportsFourStartingMoves=1
+StarterOffsets1=[0x78C70, 0x78C72, 0x78C89, 0x78C94]
+StarterOffsets2=[0x78CB2, 0x78CB4, 0x78CCB, 0x78CD6]
+StarterOffsets3=[0x78CEE, 0x78CF0, 0x78D07, 0x78D12]
+StarterHeldItems=[0x78C96, 0x78CD8, 0x78D14]
+TMMovesOffset=0x1168D
+TrainerClassNamesOffset=0x2C1EF
+IntroSpriteOffset=0x5FF1
+IntroCryOffset=0x606F
+LandmarkTableOffset=0x1CAAB4
+LandmarkCount=96
+StaticPokemonSupport=1
+CanChangeStarterText=0
+GameCornerPokemonNameLength=11
+StaticPokemonOverworlds=[0x5A3F1, 0x6D158, 0x6D183, 0x6D1AE, 0x18C54D, 0x7006E, 0x194068, 0x1AAA6F, 0x77257, 0x185139]
+StaticPokemonRocketBase=[0x6CA79, 0x6CA8C, 0x6CA9F]
+StaticPokemonGifts=[0x7329, 0x7E1F7, 0x695F2, 0x69E73, 0x54C5B, 0x18D224]
+StaticPokemonOddEgg=[0x1FB56D, 0x1FB5A8, 0x1FB5E3, 0x1FB61E, 0x1FB659, 0x1FB694, 0x1FB6CF, 0x1FB70A, 0x1FB745, 0x1FB780, 0x1FB7BB, 0x1FB7F6, 0x1FB831, 0x1FB86C]
+StaticPokemonRoamers=[0x2A2A8, 0x2A2AD]
+MoveTutorMoves=[0x49211, 0x49214, 0x4920E]
+
+[Crystal (I)]
+Game=BYTI
+Version=0
+NonJapanese=1
+Type=Crystal
+CopyFrom=Crystal (U)
+ExtraTableFile=gsc_espita
+PokemonNamesOffset=0x53393
+PokemonStatsOffset=0x51433
+WildPokemonOffset=0x2A5E0
+FishingWildsOffset=0x924F6
+HeadbuttWildsOffset=0xB830C
+BCCWildsOffset=0x97D86
+MoveDataOffset=0x41AFB
+MoveNamesOffset=0x1C9E86
+PokemonMovesetsTableOffset=0x425B0
+SupportsFourStartingMoves=1
+StarterOffsets1=[0x78CD4, 0x78CD6, 0x78CED, 0x78CF8]
+StarterOffsets2=[0x78D16, 0x78D18, 0x78D2F, 0x78D3A]
+StarterOffsets3=[0x78D52, 0x78D54, 0x78D6B, 0x78D76]
+StarterHeldItems=[0x78CFA, 0x78D3C, 0x78D78]
+TMMovesOffset=0x11679
+TrainerClassNamesOffset=0x2C1EF
+IntroSpriteOffset=0x5FEB
+IntroCryOffset=0x6069
+LandmarkTableOffset=0x1CA8B4
+LandmarkCount=96
+StaticPokemonSupport=1
+CanChangeStarterText=0
+GameCornerPokemonNameLength=11
+StaticPokemonOverworlds=[0x5A361, 0x6D16F, 0x6D19A, 0x6D1C5, 0x18C534, 0x7006E, 0x194068, 0x1AAA77, 0x772B8, 0x185187]
+StaticPokemonRocketBase=[0x6CA47, 0x6CA5A, 0x6CA6D]
+StaticPokemonGifts=[0x7323, 0x7E217, 0x69651, 0x69E5A, 0x54CA2, 0x18D1C3]
+StaticPokemonOddEgg=[0x1FB56E, 0x1FB5A9, 0x1FB5E4, 0x1FB61F, 0x1FB65A, 0x1FB695, 0x1FB6D0, 0x1FB70B, 0x1FB746, 0x1FB781, 0x1FB7BC, 0x1FB7F7, 0x1FB832, 0x1FB86D]
+StaticPokemonRoamers=[0x2A298, 0x2A29D]
+MoveTutorMoves=[0x49215, 0x49218, 0x49212]
\ No newline at end of file
diff --git a/src/com/dabomstew/pkrandom/config/gen3_offsets.ini b/src/com/dabomstew/pkrandom/config/gen3_offsets.ini
new file mode 100755
index 000000000..ab14b6c47
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/config/gen3_offsets.ini
@@ -0,0 +1,1806 @@
+[Ruby (U)]
+Game=AXVE
+Version=0
+Type=Ruby
+TableFile=gba_english
+FreeSpace=0x700000
+PokemonNameLength=11
+PokemonStats=0x1FEC34
+PokemonMovesets=0x207BCC
+PokemonTMHMCompat=0x1FD0F8
+PokemonEvolutions=0x203B90
+StarterPokemon=0x3F76C4
+StarterItems=0x821AA
+TrainerData=0x1F04FC
+TrainerEntrySize=40
+TrainerCount=0x2B6
+TrainerClassNames=0x1F0208
+TrainerClassCount=58
+TrainerClassNameLength=13
+TrainerNameLength=12
+ItemData=0x3C5564
+ItemCount=348
+ItemEntrySize=44
+MoveData=0x1FB138
+MoveDescriptions=0x3C09D8
+MoveNameLength=13
+MoveNames=0x1F8320
+AbilityNameLength=13
+AbilityNames=0x1FA248
+TmMoves=0x376504
+IntroCryOffset=0xA506
+IntroSpriteOffset=0xB2B8
+IntroPaletteOffset=0xB2C4
+IntroOtherOffset=0xB286
+PokemonFrontSprites=0x1E8354
+PokemonNormalPalettes=0x1EA5B4
+MapBankCount=0x22
+MapBankSizes=[54,5,5,6,7,7,8,7,7,13,8,17,10,24,13,13,14,2,2,2,3,1,1,1,86,44,12,2,1,13,1,1,3,1]
+ItemBallPic=59
+TradeTableOffset=0x215AC4
+TradeTableSize=3
+TradesUnused=[]
+StaticPokemonSupport=1
+StaticPokemon[]=[0x157663, 0x157691] // Lileep
+StaticPokemon[]=[0x1576B6, 0x1576E4] // Anorith
+StaticPokemon[]=[0x1A04A3, 0x15DE26, 0x15DE2D] // Groudon
+StaticPokemon[]=[0x15CB89, 0x15CB92] // Regirock
+StaticPokemon[]=[0x15EFA1, 0x15EFAA] // Regice
+StaticPokemon[]=[0x15F054, 0x15F05D] // Registeel
+StaticPokemon[]=[0x160BCE, 0x160BF4] // Latias (Southern Island)
+StaticPokemon[]=[0x15F319, 0x15F320] // Rayquaza
+StaticPokemon[]=[0x1A05E2, 0x1A05EB] // Kecleons on OW (7)
+StaticPokemon[]=[0x1518E8, 0x1518F1] // Kecleon w/ Steven
+StaticPokemon[]=[0x15E903, 0x15E90A] // Voltorb 1
+StaticPokemon[]=[0x15E921, 0x15E928] // Voltorb 2
+StaticPokemon[]=[0x15E93F, 0x15E946] // Voltorb 3
+StaticPokemon[]=[0x1A0500, 0x1A0507] // Electrode 1
+StaticPokemon[]=[0x1A051E, 0x1A0525] // Electrode 2
+StaticPokemon[]=[0x14E79A] // Wynaut Egg
+StaticPokemon[]=[0x15AAAF, 0x15AABF] // Beldum
+StaticPokemon[]=[0x163D99] // Castform
+
+[Ruby (E)]
+Game=AXVE
+Version=1
+Type=Ruby
+CopyFrom=Ruby (U)
+PokemonStats=0x1FEC4C
+PokemonMovesets=0x207BE4
+PokemonTMHMCompat=0x1FD110
+PokemonEvolutions=0x203BA8
+StarterPokemon=0x3F76E0
+StarterItems=0x821CA
+TrainerData=0x1F0514
+TrainerClassNames=0x1F0220
+ItemData=0x3C5580
+MoveData=0x1FB150
+MoveDescriptions=0x3C09F4
+MoveNames=0x1F8338
+AbilityNames=0x1FA260
+TmMoves=0x37651C
+PokemonFrontSprites=0x1E836C
+PokemonNormalPalettes=0x1EA5CC
+TradeTableOffset=0x215ADC
+StaticPokemonSupport=1
+StaticPokemon[]=[0x157683, 0x1576B1]
+StaticPokemon[]=[0x1576D6, 0x157704]
+StaticPokemon[]=[0x1A04C3, 0x15DE46, 0x15DE4D]
+StaticPokemon[]=[0x15CBA9, 0x15CBB2]
+StaticPokemon[]=[0x15EFC1, 0x15EFCA]
+StaticPokemon[]=[0x15F074, 0x15F07D]
+StaticPokemon[]=[0x160BEE, 0x160C14]
+StaticPokemon[]=[0x15F339, 0x15F340]
+StaticPokemon[]=[0x1A0602, 0x1A060B]
+StaticPokemon[]=[0x151908, 0x151911]
+StaticPokemon[]=[0x15E923, 0x15E92A]
+StaticPokemon[]=[0x15E941, 0x15E948]
+StaticPokemon[]=[0x15E95F, 0x15E966]
+StaticPokemon[]=[0x1A0520, 0x1A0527]
+StaticPokemon[]=[0x1A053E, 0x1A0545]
+StaticPokemon[]=[0x14E7BA]
+StaticPokemon[]=[0x15AACF, 0x15AADF]
+StaticPokemon[]=[0x163DB9]
+
+[Ruby (U/E) 1.2]
+Game=AXVE
+Version=2
+Type=Ruby
+CopyStaticPokemon=1
+CopyFrom=Ruby (E)
+
+[Sapphire (U)]
+Game=AXPE
+Version=0
+Type=Sapp
+CopyFrom=Ruby (U)
+PokemonStats=0x1FEBC4
+PokemonMovesets=0x207B5C
+PokemonTMHMCompat=0x1FD088
+PokemonEvolutions=0x203B20
+StarterPokemon=0x3F771C
+TrainerData=0x1F048C
+TrainerClassNames=0x1F0198
+ItemData=0x3C55BC
+MoveData=0x1FB0C8
+MoveDescriptions=0x3C0A30
+MoveNames=0x1F82B0
+AbilityNames=0x1FA1D8
+TmMoves=0x376494
+PokemonFrontSprites=0x1E82E4
+PokemonNormalPalettes=0x1EA544
+TradeTableOffset=0x215A54
+StaticPokemonSupport=1
+StaticPokemon[]=[0x1575F3, 0x157621] // Lileep
+StaticPokemon[]=[0x157646, 0x157674] // Anorith
+StaticPokemon[]=[0x1A0433, 0x15DDB6, 0x15DDBD] // Kyogre
+StaticPokemon[]=[0x15CB19, 0x15CB22] // Regirock
+StaticPokemon[]=[0x15EF31, 0x15EF3A] // Regice
+StaticPokemon[]=[0x15EFE4, 0x15EFED] // Registeel
+StaticPokemon[]=[0x160B5E, 0x160B84] // Latios (Southern Island)
+StaticPokemon[]=[0x15F2A9, 0x15F2B0] // Rayquaza
+StaticPokemon[]=[0x1A0572, 0x1A057B] // Kecleons on OW (7)
+StaticPokemon[]=[0x15187C, 0x151885] // Kecleon w/ Steven
+StaticPokemon[]=[0x15E893, 0x15E89A] // Voltorb 1
+StaticPokemon[]=[0x15E8B1, 0x15E8B8] // Voltorb 2
+StaticPokemon[]=[0x15E8CF, 0x15E8D6] // Voltorb 3
+StaticPokemon[]=[0x1A0490, 0x1A0497] // Electrode 1
+StaticPokemon[]=[0x1A04AE, 0x1A04B5] // Electrode 2
+StaticPokemon[]=[0x14E72E] // Wynaut Egg
+StaticPokemon[]=[0x15AA3F, 0x15AA4F] // Beldum
+StaticPokemon[]=[0x163D29] // Castform
+
+[Sapphire (E)]
+Game=AXPE
+Version=1
+Type=Sapp
+CopyFrom=Sapphire (U)
+PokemonStats=0x1FEBDC
+PokemonMovesets=0x207B74
+PokemonTMHMCompat=0x1FD0A0
+PokemonEvolutions=0x203B38
+StarterPokemon=0x3F773C
+StarterItems=0x821CA
+TrainerData=0x1F04A4
+TrainerClassNames=0x1F01B0
+ItemData=0x3C55DC
+MoveData=0x1FB0E0
+MoveDescriptions=0x3C0A50
+MoveNames=0x1F82C8
+AbilityNames=0x1FA1F0
+TmMoves=0x3764AC
+PokemonFrontSprites=0x1E82FC
+PokemonNormalPalettes=0x1EA55C
+TradeTableOffset=0x215A6C
+StaticPokemonSupport=1
+StaticPokemon[]=[0x157613, 0x157641]
+StaticPokemon[]=[0x157666, 0x157694]
+StaticPokemon[]=[0x1A0453, 0x15DDD6, 0x15DDDD]
+StaticPokemon[]=[0x15CB39, 0x15CB42]
+StaticPokemon[]=[0x15EF51, 0x15EF5A]
+StaticPokemon[]=[0x15F004, 0x15F00D]
+StaticPokemon[]=[0x160B7E, 0x160BA4]
+StaticPokemon[]=[0x15F2C9, 0x15F2D0]
+StaticPokemon[]=[0x1A0592, 0x1A059B]
+StaticPokemon[]=[0x15189C, 0x1518A5]
+StaticPokemon[]=[0x15E8B3, 0x15E8BA]
+StaticPokemon[]=[0x15E8D1, 0x15E8D8]
+StaticPokemon[]=[0x15E8EF, 0x15E8F6]
+StaticPokemon[]=[0x1A04B0, 0x1A04B7]
+StaticPokemon[]=[0x1A04CE, 0x1A04D5]
+StaticPokemon[]=[0x14E74E]
+StaticPokemon[]=[0x15AA5F, 0x15AA6F]
+StaticPokemon[]=[0x163D49]
+
+[Sapphire (U/E) 1.2]
+Game=AXPE
+Version=2
+Type=Sapp
+CopyStaticPokemon=1
+CopyFrom=Sapphire (E)
+
+[Emerald (U)]
+Game=BPEE
+Version=0
+Type=Em
+TableFile=gba_english
+FreeSpace=0xE40000
+PokemonNameLength=11
+PokemonStats=0x3203E8
+PokemonMovesets=0x329380
+PokemonTMHMCompat=0x31E8A0
+PokemonEvolutions=0x325344
+StarterPokemon=0x5B1DF8
+StarterItems=0xB117A
+TrainerData=0x310030
+TrainerEntrySize=40
+TrainerCount=0x357
+TrainerClassNames=0x30FCD4
+TrainerClassCount=66
+TrainerClassNameLength=13
+TrainerNameLength=12
+ItemEntrySize=44
+ItemCount=376
+MoveDescriptions=0x61C524
+MoveNameLength=13
+AbilityNameLength=13
+TmMoves=0x615B94
+TmMovesDuplicate=0x616040
+MoveTutorData=0x61500C
+MoveTutorMoves=30
+ItemImages=0x614410
+TmPals=[0xDB5E94, 0xDB5DF4, 0xDB604C, 0xDB5EBC, 0xDB5FD4, 0xDB6024, 0xDB5F0C, 0xDB5FFC, 0xDB5F84, 0xDB5FFC, 0xDB5F34, 0xDB5E44, 0xDB5F0C, 0xDB5FAC, 0xDB5E6C, 0xDB5EE4, 0xDB5E1C, 0xDB5F5C]
+IntroCryOffset=0x30B0C
+IntroSpriteOffset=0x31924
+MapBankCount=0x22
+MapBankSizes=[57,5,5,6,7,8,9,7,7,14,8,17,10,23,13,15,15,2,2,2,3,1,1,1,108,61,89,2,1,13,1,1,2,1]
+ItemBallPic=59
+TradeTableOffset=0x338ED0
+TradeTableSize=4
+TradesUnused=[]
+StaticPokemonSupport=1
+StaticPokemon[]=[0x211A1C, 0x211A41, 0x211A44, 0x211AC6, 0x211AD4] // Lileep
+StaticPokemon[]=[0x211A2E, 0x211AE4, 0x211AE7, 0x211B69, 0x211B77] // Anorith
+StaticPokemon[]=[0x23B032, 0x23B040, 0x23B095] // Kyogre
+StaticPokemon[]=[0x23B103, 0x23B111, 0x23B166] // Groudon
+StaticPokemon[]=[0x22DA06, 0x22DA0F, 0x22DA55] // Regirock
+StaticPokemon[]=[0x238F5C, 0x238F65, 0x238FAB] // Regice
+StaticPokemon[]=[0x23905E, 0x239067, 0x2390AD] // Registeel
+StaticPokemon[]=[0x239725, 0x23972E, 0x239774] // Rayquaza
+StaticPokemon[]=[0x272384, 0x27238D] // Kecleons on OW (7)
+StaticPokemon[]=[0x1F56D6, 0x1F56DF] // Kecleon w/ Steven
+StaticPokemon[]=[0x2377B2, 0x2377B9] // Voltorb 1
+StaticPokemon[]=[0x2377FF, 0x237806] // Voltorb 2
+StaticPokemon[]=[0x23784C, 0x237853] // Voltorb 3
+StaticPokemon[]=[0x2339EE, 0x2339F5] // Electrode 1
+StaticPokemon[]=[0x233A3B, 0x233A42] // Electrode 2
+StaticPokemon[]=[0x242D1B, 0x242D29] // Sudowoodo in Battle Frontier
+StaticPokemon[]=[0x242BA7]
+StaticPokemon[]=[0x242BBA] // Latias/Latios on Southern Island
+StaticPokemon[]=[0x267FE7, 0x267FF7, 0x268041, 0x26804C] // Deoxys on Birth Island
+StaticPokemon[]=[0x267E0D, 0x267E47, 0x267E9C, 0x267EA7] // Mew on Faraway Island
+StaticPokemon[]=[0x26919F, 0x2691CE, 0x26921D, 0x269228] // Ho-Oh on Navel Rock
+StaticPokemon[]=[0x2692E7, 0x2692F2, 0x26933C, 0x269347] // Lugia on Navel Rock
+StaticPokemon[]=[0x1EA783] // Wynaut Egg
+StaticPokemon[]=[0x222868, 0x22286B, 0x2228ED, 0x2228FE] // Beldum
+StaticPokemon[]=[0x270058, 0x27005B] // Castform
+
+[Fire Red (U) 1.0]
+Game=BPRE
+Version=0
+Type=FRLG
+TableFile=gba_english
+FreeSpace=0x800000
+PokemonNameLength=11
+PokemonStats=0x2547A0
+PokemonMovesets=0x25D7B8
+PokemonTMHMCompat=0x252BD0
+PokemonEvolutions=0x25977C
+BattleTrappersBanned=[55,56,57,58,59]
+StarterPokemon=0x169BB5
+TrainerData=0x23EAC8
+TrainerEntrySize=40
+TrainerCount=0x2E7
+TrainerClassNames=0x23E558
+TrainerClassCount=107
+TrainerClassNameLength=13
+TrainerNameLength=12
+ItemEntrySize=44
+ItemCount=374
+MoveDescriptions=0x4886E8
+MoveNameLength=13
+AbilityNameLength=13
+TmMoves=0x45A5A4
+TmMovesDuplicate=0x45A80C
+MoveTutorData=0x459B60
+MoveTutorMoves=15
+ItemImages=0x3D4294
+TmPals=[0xE91E64, 0xE91DC4, 0xE9201C, 0xE91E8C, 0xE91FA4, 0xE91FF4, 0xE91EDC, 0xE91FCC, 0xE91F54, 0xE91FCC, 0xE91F04, 0xE91E14, 0xE91EDC, 0xE91F7C, 0xE91E3C, 0xE91EB4, 0xE91DEC, 0xE91F2C]
+IntroCryOffset=0x12FB38
+IntroSpriteOffset=0x130FA0
+IntroOtherOffset=0x130F4C
+MapBankCount=0x2B
+MapBankSizes=[5,123,60,66,4,6,8,10,6,8,20,10,8,2,10,4,2,2,2,1,1,2,2,3,2,3,2,1,1,1,1,7,5,5,8,8,5,5,1,1,1,2,1]
+ItemBallPic=92
+TradeTableOffset=0x26CF8C
+TradeTableSize=9
+TradesUnused=[]
+StaticPokemonSupport=1
+StaticPokemon[]=[0x16C472, 0x16C475, 0x16C4B5, 0x16C4E9] // Eevee in Celadon Mansion
+StaticPokemon[]=[0x16EC0C, 0x16EC13] // Hitmonlee in Fighting Dojo
+StaticPokemon[]=[0x16EC52, 0x16EC59] // Hitmonchan in Fighting Dojo
+StaticPokemon[]=[0x163840, 0x163847] // Electrode in The Power Plant
+StaticPokemon[]=[0x16389E, 0x1638A5] // Electrode in The Power Plant
+StaticPokemon[]=[0x1637CC, 0x1637D3, 0x163827] // Zapdos in the Power Plant
+StaticPokemon[]=[0x1631C0, 0x1631C7, 0x16321B] // Articuno in the Seafoams
+StaticPokemon[]=[0x163B47, 0x163B4E, 0x163BA2] // Moltres in Mt.Ember
+StaticPokemon[]=[0x16250A, 0x16251E, 0x162564] // Mewtwo in Unk. Dungeon
+StaticPokemon[]=[0x168049, 0x168050] // Sleeping Snorlax (12)
+StaticPokemon[]=[0x168156, 0x16815D] // Sleeping Snorlax (16)
+StaticPokemon[]=[0x163CBC, 0x163CC2] // Hypno in Berry Forest
+StaticPokemon[]=[0x1652E6, 0x1652F6, 0x165340, 0x16534B] // Deoxys on Birth Island
+StaticPokemon[]=[0x16503C, 0x16506B, 0x1650BA, 0x1650C5] // Ho-Oh on Navel Rock
+StaticPokemon[]=[0x16518A, 0x165195, 0x1651DF, 0x1651EA] // Lugia on Navel Rock
+StaticPokemon[]=[0x16E7E5, 0x16E7E9, 0x16E7F4, 0x16E6E6] // Old Amber
+StaticPokemon[]=[0x16E75B, 0x16E75F, 0x16E76A, 0x16E66A] // Helix Fossil
+StaticPokemon[]=[0x16E7A0, 0x16E7A4, 0x16E7AF, 0x16E6A8] // Dome Fossil
+StaticPokemon[]=[0x161AE1, 0x161B20, 0x161B53] // Lapras in Silph. Co
+StaticPokemon[]=[0x16F7C6, 0x16F885] // Magikarp in Mt.Moon Center
+StaticPokemon[]=[0x16CC18, 0x16CC94] // Abra
+StaticPokemon[]=[0x16CC28, 0x16CC9F] // Clefairy
+StaticPokemon[]=[0x16CC48, 0x16CCB5] // Scyther
+StaticPokemon[]=[0x16CC38, 0x16CCAA] // Dratini
+StaticPokemon[]=[0x16CC58, 0x16CCC0] // Porygon
+
+[Leaf Green (U) 1.0]
+Game=BPGE
+Version=0
+Type=FRLG
+CopyFrom=Fire Red (U) 1.0
+PokemonStats=0x25477C
+PokemonMovesets=0x25D798
+PokemonTMHMCompat=0x252BAC
+PokemonEvolutions=0x25975C
+StarterPokemon=0x169B91
+TrainerData=0x23EAA4
+TrainerClassNames=0x23E534
+MoveDescriptions=0x487FC4
+TmMoves=0x459FC4
+TmMovesDuplicate=0x45A22C
+MoveTutorData=0x459580
+ItemImages=0x3D40D0
+TmPals=[0xE91EE4, 0xE91E44, 0xE9209C, 0xE91F0C, 0xE92024, 0xE92074, 0xE91F5C, 0xE9204C, 0xE91FD4, 0xE9204C, 0xE91F84, 0xE91E94, 0xE91F5C, 0xE91FFC, 0xE91EBC, 0xE91F34, 0xE91E6C, 0xE91FAC]
+IntroCryOffset=0x12FB10
+IntroSpriteOffset=0x130F78
+IntroOtherOffset=0x130F24
+TradeTableOffset=0x26CF6C
+StaticPokemonSupport=1
+StaticPokemon[]=[0x16C44E, 0x16C451, 0x16C491, 0x16C4C5] // Eevee in Celadon Mansion
+StaticPokemon[]=[0x16EBE8, 0x16EBEF] // Hitmonlee in Fighting Dojo
+StaticPokemon[]=[0x16EC2E, 0x16EC35] // Hitmonchan in Fighting Dojo
+StaticPokemon[]=[0x16381C, 0x163823] // Electrode in The Power Plant
+StaticPokemon[]=[0x16387A, 0x163881] // Electrode in The Power Plant
+StaticPokemon[]=[0x1637A8, 0x1637AF, 0x163803] // Zapdos in the Power Plant
+StaticPokemon[]=[0x16319C, 0x1631A3, 0x1631F7] // Articuno in the Seafoams
+StaticPokemon[]=[0x163B23, 0x163B2A, 0x163B7E] // Moltres in Mt.Ember
+StaticPokemon[]=[0x1624E6, 0x1624FA, 0x162540] // Mewtwo in Unk. Dungeon
+StaticPokemon[]=[0x168025, 0x16802C] // Sleeping Snorlax (12)
+StaticPokemon[]=[0x168132, 0x168139] // Sleeping Snorlax (16)
+StaticPokemon[]=[0x163C98, 0x163C9E] // Hypno in Berry Forest
+StaticPokemon[]=[0x1652C2, 0x1652D2, 0x16531C, 0x165327] // Deoxys on Birth Island
+StaticPokemon[]=[0x165018, 0x165047, 0x165096, 0x1650A1] // Ho-Oh on Navel Rock
+StaticPokemon[]=[0x165166, 0x165171, 0x1651BB, 0x1651C6] // Lugia on Navel Rock
+StaticPokemon[]=[0x16E7C1, 0x16E7C5, 0x16E7D0, 0x16E6C2] // Old Amber
+StaticPokemon[]=[0x16E737, 0x16E73B, 0x16E746, 0x16E646] // Helix Fossil
+StaticPokemon[]=[0x16E77C, 0x16E780, 0x16E78B, 0x16E684] // Dome Fossil
+StaticPokemon[]=[0x161ABD, 0x161AFC, 0x161B2F] // Lapras in Silph. Co
+StaticPokemon[]=[0x16F7A2, 0x16F861] // Magikarp in Mt.Moon Center
+StaticPokemon[]=[0x16CBF4, 0x16CC70] // Abra
+StaticPokemon[]=[0x16CC04, 0x16CC7B] // Clefairy
+StaticPokemon[]=[0x16CC14, 0x16CCA7] // Pinsir
+StaticPokemon[]=[0x16CC24, 0x16CC86] // Dratini
+StaticPokemon[]=[0x16CC34, 0x16CC9C] // Porygon
+
+[Fire Red (U) 1.1]
+Game=BPRE
+Version=1
+Type=FRLG
+CopyFrom=Fire Red (U) 1.0
+PokemonStats=0x254810
+PokemonMovesets=0x25D828
+PokemonTMHMCompat=0x252C40
+PokemonEvolutions=0x2597EC
+StarterPokemon=0x169C2D
+TrainerData=0x23EB38
+TrainerClassNames=0x23E5C8
+MoveDescriptions=0x488748
+TmMoves=0x45A604
+TmMovesDuplicate=0x45A86C
+MoveTutorData=0x459BC0
+ItemImages=0x3D4304
+TmPals=[0xE91E64, 0xE91DC4, 0xE9201C, 0xE91E8C, 0xE91FA4, 0xE91FF4, 0xE91EDC, 0xE91FCC, 0xE91F54, 0xE91FCC, 0xE91F04, 0xE91E14, 0xE91EDC, 0xE91F7C, 0xE91E3C, 0xE91EB4, 0xE91DEC, 0xE91F2C]
+IntroCryOffset=0x12FBB0
+IntroSpriteOffset=0x131018
+IntroOtherOffset=0x130FC4
+TradeTableOffset=0x26CFFC
+StaticPokemonSupport=1
+StaticPokemon[]=[0x16C4EA, 0x16C4ED, 0x16C52D, 0x16C561]
+StaticPokemon[]=[0x16EC84, 0x16EC8B]
+StaticPokemon[]=[0x16ECCA, 0x16ECD1]
+StaticPokemon[]=[0x1638B8, 0x1638BF]
+StaticPokemon[]=[0x163916, 0x16391D]
+StaticPokemon[]=[0x163844, 0x16384B, 0x16389F]
+StaticPokemon[]=[0x163238, 0x16323F, 0x163293]
+StaticPokemon[]=[0x163BBF, 0x163BC6, 0x163C1A]
+StaticPokemon[]=[0x162582, 0x162596, 0x1625DC]
+StaticPokemon[]=[0x1680C1, 0x1680C8]
+StaticPokemon[]=[0x1681CE, 0x1681D5]
+StaticPokemon[]=[0x163D34, 0x163D3A]
+StaticPokemon[]=[0x16535E, 0x16536E, 0x1653B8, 0x1653C3]
+StaticPokemon[]=[0x1650B4, 0x1650E3, 0x165132, 0x16513D]
+StaticPokemon[]=[0x165202, 0x16520D, 0x165257, 0x165262]
+StaticPokemon[]=[0x16E85D, 0x16E861, 0x16E86C, 0x16E75E]
+StaticPokemon[]=[0x16E7D3, 0x16E7D7, 0x16E7E2, 0x16E6E2]
+StaticPokemon[]=[0x16E818, 0x16E81C, 0x16E827, 0x16E720]
+StaticPokemon[]=[0x161B59, 0x161B98, 0x161BCB]
+StaticPokemon[]=[0x16F83E, 0x16F8FD]
+StaticPokemon[]=[0x16CC90, 0x16CD0C]
+StaticPokemon[]=[0x16CCA0, 0x16CD17]
+StaticPokemon[]=[0x16CCC0, 0x16CD2D]
+StaticPokemon[]=[0x16CCB0, 0x16CD22]
+StaticPokemon[]=[0x16CCD0, 0x16CD38]
+
+[Leaf Green (U) 1.1]
+Game=BPGE
+Version=1
+Type=FRLG
+CopyFrom=Leaf Green (U) 1.0
+PokemonStats=0x2547EC
+PokemonMovesets=0x25D808
+PokemonTMHMCompat=0x252C1C
+PokemonEvolutions=0x2597CC
+StarterPokemon=0x169C09
+TrainerData=0x23EB14
+TrainerClassNames=0x23E5A4
+MoveDescriptions=0x488034
+TmMoves=0x45A034
+TmMovesDuplicate=0x45A29C
+MoveTutorData=0x4595F0
+ItemImages=0x3D4140
+TmPals=[0xE91EE4, 0xE91E44, 0xE9209C, 0xE91F0C, 0xE92024, 0xE92074, 0xE91F5C, 0xE9204C, 0xE91FD4, 0xE9204C, 0xE91F84, 0xE91E94, 0xE91F5C, 0xE91FFC, 0xE91EBC, 0xE91F34, 0xE91E6C, 0xE91FAC]
+IntroCryOffset=0x12FB88
+IntroSpriteOffset=0x130FF0
+IntroOtherOffset=0x130F9C
+TradeTableOffset=0x26CFDC
+StaticPokemonSupport=1
+StaticPokemon[]=[0x16C4C6, 0x16C4C9, 0x16C509, 0x16C53D]
+StaticPokemon[]=[0x16EC60, 0x16EC67]
+StaticPokemon[]=[0x16ECA6, 0x16ECAD]
+StaticPokemon[]=[0x163894, 0x16389B]
+StaticPokemon[]=[0x1638F2, 0x1638F9]
+StaticPokemon[]=[0x163820, 0x163827, 0x16387B]
+StaticPokemon[]=[0x163214, 0x16321B, 0x16326F]
+StaticPokemon[]=[0x163B9B, 0x163BA2, 0x163BF6]
+StaticPokemon[]=[0x16255E, 0x162572, 0x1625B8]
+StaticPokemon[]=[0x16809D, 0x1680A4]
+StaticPokemon[]=[0x1681AA, 0x1681B1]
+StaticPokemon[]=[0x163D10, 0x163D16]
+StaticPokemon[]=[0x16533A, 0x16534A, 0x165394, 0x16539F]
+StaticPokemon[]=[0x165090, 0x1650BF, 0x16510E, 0x165119]
+StaticPokemon[]=[0x1651DE, 0x1651E9, 0x165233, 0x16523E]
+StaticPokemon[]=[0x16E839, 0x16E83D, 0x16E848, 0x16E73A]
+StaticPokemon[]=[0x16E7AF, 0x16E7B3, 0x16E7BE, 0x16E6BE]
+StaticPokemon[]=[0x16E7F4, 0x16E7F8, 0x16E803, 0x16E6FC]
+StaticPokemon[]=[0x161B35, 0x161B74, 0x161BA7]
+StaticPokemon[]=[0x16F81A, 0x16F8D9]
+StaticPokemon[]=[0x16CC6C, 0x16CCE8]
+StaticPokemon[]=[0x16CC7C, 0x16CCF3]
+StaticPokemon[]=[0x16CC8C, 0x16CD1F]
+StaticPokemon[]=[0x16CC9C, 0x16CCFE]
+StaticPokemon[]=[0x16CCAC, 0x16CD14]
+
+[Ruby (F)]
+Game=AXVF
+Version=0
+Type=Ruby
+CopyFrom=Ruby (U)
+PokemonStats=0x207080
+PokemonMovesets=0x210018
+PokemonTMHMCompat=0x205544
+PokemonEvolutions=0x20BFDC
+StarterPokemon=0x3FF3F4
+StarterItems=0x826C6
+TrainerData=0x1F8904
+TrainerClassNames=0x1F8610
+ItemData=0x3CCFC4
+MoveData=0x203584
+MoveDescriptions=0x3C8434
+MoveNames=0x200728
+AbilityNames=0x202694
+TmMoves=0x37D168
+PokemonFrontSprites=0x1F075C
+PokemonNormalPalettes=0x1F29BC
+IntroCryOffset=0xA6DA
+IntroSpriteOffset=0xB48C
+IntroPaletteOffset=0xB498
+IntroOtherOffset=0xB45A
+TradeTableOffset=0x21DF10
+StaticPokemonSupport=1
+StaticPokemon[]=[0x157B23, 0x157B51]
+StaticPokemon[]=[0x157B76, 0x157BA4]
+StaticPokemon[]=[0x1A58A8, 0x15E2E6, 0x15E2ED]
+StaticPokemon[]=[0x15D049, 0x15D052]
+StaticPokemon[]=[0x15F461, 0x15F46A]
+StaticPokemon[]=[0x15F514, 0x15F51D]
+StaticPokemon[]=[0x16108E, 0x1610B4]
+StaticPokemon[]=[0x15F7D9, 0x15F7E0]
+StaticPokemon[]=[0x1A59E7, 0x1A59F0]
+StaticPokemon[]=[0x151DA8, 0x151DB1]
+StaticPokemon[]=[0x15EDC3, 0x15EDCA]
+StaticPokemon[]=[0x15EDE1, 0x15EDE8]
+StaticPokemon[]=[0x15EDFF, 0x15EE06]
+StaticPokemon[]=[0x1A5905, 0x1A590C]
+StaticPokemon[]=[0x1A5923, 0x1A592A]
+StaticPokemon[]=[0x14EC5A]
+StaticPokemon[]=[0x15AF6F, 0x15AF7F]
+StaticPokemon[]=[0x164259]
+
+[Ruby (F) 1.1]
+Game=AXVF
+Version=1
+Type=Ruby
+CopyStaticPokemon=1
+CopyFrom=Ruby (F)
+
+[Sapphire (F)]
+Game=AXPF
+Version=0
+Type=Sapp
+CopyFrom=Ruby (F)
+PokemonStats=0x207010
+PokemonMovesets=0x20FFA8
+PokemonTMHMCompat=0x2054D4
+PokemonEvolutions=0x20BF6C
+StarterPokemon=0x3FEF24
+TrainerData=0x1F8894
+TrainerClassNames=0x1F85A0
+ItemData=0x3CCAF4
+MoveData=0x203514
+MoveDescriptions=0x3C7F64
+MoveNames=0x2006B8
+AbilityNames=0x202624
+TmMoves=0x37D0F8
+PokemonFrontSprites=0x1F06EC
+PokemonNormalPalettes=0x1F294C
+TradeTableOffset=0x21DEA0
+StaticPokemonSupport=1
+StaticPokemon[]=[0x157AB3, 0x157AE1]
+StaticPokemon[]=[0x157B06, 0x157B34]
+StaticPokemon[]=[0x1A5838, 0x15E276, 0x15E27D]
+StaticPokemon[]=[0x15CFD9, 0x15CFE2]
+StaticPokemon[]=[0x15F3F1, 0x15F3FA]
+StaticPokemon[]=[0x15F4A4, 0x15F4AD]
+StaticPokemon[]=[0x16101E, 0x161044]
+StaticPokemon[]=[0x15F769, 0x15F770]
+StaticPokemon[]=[0x1A5977, 0x1A5980]
+StaticPokemon[]=[0x151D3C, 0x151D45]
+StaticPokemon[]=[0x15ED53, 0x15ED5A]
+StaticPokemon[]=[0x15ED71, 0x15ED78]
+StaticPokemon[]=[0x15ED8F, 0x15ED96]
+StaticPokemon[]=[0x1A5895, 0x1A589C]
+StaticPokemon[]=[0x1A58B3, 0x1A58BA]
+StaticPokemon[]=[0x14EBEE]
+StaticPokemon[]=[0x15AEFF, 0x15AF0F]
+StaticPokemon[]=[0x1641E9]
+
+[Sapphire (F) 1.1]
+Game=AXPF
+Version=1
+Type=Sapp
+CopyStaticPokemon=1
+CopyFrom=Sapphire (F)
+
+[Emerald (F)]
+Game=BPEF
+Version=0
+Type=Em
+CopyFrom=Emerald (U)
+PokemonStats=0x327F58
+PokemonMovesets=0x330EF0
+PokemonTMHMCompat=0x326410
+PokemonEvolutions=0x32CEB4
+StarterPokemon=0x5B63E4
+StarterItems=0xB118E
+TrainerData=0x317B60
+TrainerClassNames=0x317804
+MoveDescriptions=0x620920
+TmMoves=0x619F1C
+TmMovesDuplicate=0x61A3C8
+MoveTutorData=0x619394
+ItemImages=0x618798
+TmPals=[0xDB5F6C, 0xDB5ECC, 0xDB6124, 0xDB5F94, 0xDB60AC, 0xDB60FC, 0xDB5FE4, 0xDB60D4, 0xDB605C, 0xDB60D4, 0xDB600C, 0xDB5F1C, 0xDB5FE4, 0xDB6084, 0xDB5F44, 0xDB5FBC, 0xDB5EF4, 0xDB6034]
+IntroCryOffset=0x30B0C
+IntroSpriteOffset=0x31924
+TradeTableOffset=0x340A54
+StaticPokemonSupport=1
+StaticPokemon[]=[0x2142C0, 0x2142E5, 0x2142E8, 0x21436A, 0x214378]
+StaticPokemon[]=[0x2142D2, 0x214388, 0x21438B, 0x21440D, 0x21441B]
+StaticPokemon[]=[0x23FEE1, 0x23FEEF, 0x23FF44]
+StaticPokemon[]=[0x23FFB2, 0x23FFC0, 0x240015]
+StaticPokemon[]=[0x231B1F, 0x231B28, 0x231B6E]
+StaticPokemon[]=[0x23DC62, 0x23DC6B, 0x23DCB1]
+StaticPokemon[]=[0x23DD64, 0x23DD6D, 0x23DDB3]
+StaticPokemon[]=[0x23E449, 0x23E452, 0x23E498]
+StaticPokemon[]=[0x277645, 0x27764E]
+StaticPokemon[]=[0x1F68F4, 0x1F68FD]
+StaticPokemon[]=[0x23C389, 0x23C390]
+StaticPokemon[]=[0x23C3D6, 0x23C3DD]
+StaticPokemon[]=[0x23C423, 0x23C42A]
+StaticPokemon[]=[0x23827E, 0x238285]
+StaticPokemon[]=[0x2382CB, 0x2382D2]
+StaticPokemon[]=[0x247FC7, 0x247FD5]
+StaticPokemon[]=[0x247E53]
+StaticPokemon[]=[0x247E66]
+StaticPokemon[]=[0x26CE61, 0x26CE71, 0x26CEBB, 0x26CEC6]
+StaticPokemon[]=[0x26CC78, 0x26CCB2, 0x26CD07, 0x26CD12]
+StaticPokemon[]=[0x26E00D, 0x26E03C, 0x26E08B, 0x26E096]
+StaticPokemon[]=[0x26E155, 0x26E160, 0x26E1AA, 0x26E1B5]
+StaticPokemon[]=[0x1EB1A5]
+StaticPokemon[]=[0x22607E, 0x226081, 0x226103, 0x226114]
+StaticPokemon[]=[0x275296, 0x275299]
+
+[Ruby (G)]
+Game=AXVD
+Version=0
+Type=Ruby
+CopyFrom=Ruby (U)
+PokemonStats=0x20BC04
+PokemonMovesets=0x214B9C
+PokemonTMHMCompat=0x20A0C8
+PokemonEvolutions=0x210B60
+StarterPokemon=0x403BF0
+StarterItems=0x825DE
+TrainerData=0x1FD478
+TrainerClassNames=0x1FD184
+ItemData=0x3D13DC
+MoveData=0x208108
+MoveDescriptions=0x3CC978
+MoveNames=0x20529C
+AbilityNames=0x207218
+TmMoves=0x381CEC
+PokemonFrontSprites=0x1F52D0
+PokemonNormalPalettes=0x1F7530
+IntroCryOffset=0xA6DA
+IntroSpriteOffset=0xB48C
+IntroPaletteOffset=0xB498
+IntroOtherOffset=0xB45A
+TradeTableOffset=0x222A94
+StaticPokemonSupport=1
+StaticPokemon[]=[0x157A3B, 0x157A69]
+StaticPokemon[]=[0x157A8E, 0x157ABC]
+StaticPokemon[]=[0x1A8695, 0x15E1FE, 0x15E205]
+StaticPokemon[]=[0x15CF61, 0x15CF6A]
+StaticPokemon[]=[0x15F379, 0x15F382]
+StaticPokemon[]=[0x15F42C, 0x15F435]
+StaticPokemon[]=[0x160FA6, 0x160FCC]
+StaticPokemon[]=[0x15F6F1, 0x15F6F8]
+StaticPokemon[]=[0x1A87D4, 0x1A87DD]
+StaticPokemon[]=[0x151CC0, 0x151CC9]
+StaticPokemon[]=[0x15ECDB, 0x15ECE2]
+StaticPokemon[]=[0x15ECF9, 0x15ED00]
+StaticPokemon[]=[0x15ED17, 0x15ED1E]
+StaticPokemon[]=[0x1A86F2, 0x1A86F9]
+StaticPokemon[]=[0x1A8710, 0x1A8717]
+StaticPokemon[]=[0x14EB72]
+StaticPokemon[]=[0x15AE87, 0x15AE97]
+StaticPokemon[]=[0x164171]
+
+[Ruby (G) 1.1]
+Game=AXVD
+Version=1
+Type=Ruby
+CopyStaticPokemon=1
+CopyFrom=Ruby (G)
+
+[Sapphire (G)]
+Game=AXPD
+Version=0
+Type=Sapp
+CopyFrom=Ruby (G)
+PokemonStats=0x20BB98
+PokemonMovesets=0x214B30
+PokemonTMHMCompat=0x20A05C
+PokemonEvolutions=0x210AF4
+StarterPokemon=0x403B5C
+TrainerData=0x1FD40C
+TrainerClassNames=0x1FD118
+ItemData=0x3D1348
+MoveData=0x20809C
+MoveDescriptions=0x3CC8E4
+MoveNames=0x20523D
+AbilityNames=0x2071AC
+TmMoves=0x381C80
+PokemonFrontSprites=0x1F5264
+PokemonNormalPalettes=0x1F74C4
+TradeTableOffset=0x222A28
+StaticPokemonSupport=1
+StaticPokemon[]=[0x1579CF, 0x1579FD]
+StaticPokemon[]=[0x157A22, 0x157A50]
+StaticPokemon[]=[0x1A8629, 0x15E192, 0x15E199]
+StaticPokemon[]=[0x15CEF5, 0x15CEFE]
+StaticPokemon[]=[0x15F30D, 0x15F316]
+StaticPokemon[]=[0x15F3C0, 0x15F3C9]
+StaticPokemon[]=[0x160F3A, 0x160F60]
+StaticPokemon[]=[0x15F685, 0x15F68C]
+StaticPokemon[]=[0x1A8768, 0x1A8771]
+StaticPokemon[]=[0x151C58, 0x151C61]
+StaticPokemon[]=[0x15EC6F, 0x15EC76]
+StaticPokemon[]=[0x15EC8D, 0x15EC94]
+StaticPokemon[]=[0x15ECAB, 0x15ECB2]
+StaticPokemon[]=[0x1A8686, 0x1A868D]
+StaticPokemon[]=[0x1A86A4, 0x1A86AB]
+StaticPokemon[]=[0x14EB0A]
+StaticPokemon[]=[0x15AE1B, 0x15AE2B]
+StaticPokemon[]=[0x164105]
+
+[Sapphire (G) 1.1]
+Game=AXPD
+Version=1
+Type=Sapp
+CopyStaticPokemon=1
+CopyFrom=Sapphire (G)
+
+[Emerald (G)]
+Game=BPED
+Version=0
+Type=Em
+CopyFrom=Emerald (U)
+PokemonStats=0x334DA8
+PokemonMovesets=0x33DD40
+PokemonTMHMCompat=0x333260
+PokemonEvolutions=0x339D04
+StarterPokemon=0x5C2FB0
+StarterItems=0xBE59E
+TrainerData=0x3249A0
+TrainerClassNames=0x324644
+MoveDescriptions=0x62DA80
+TmMoves=0x62705C
+TmMovesDuplicate=0x627508
+MoveTutorData=0x6264D4
+ItemImages=0x6258D8
+TmPals=[0xDB5FA4, 0xDB5F04, 0xDB615C, 0xDB5FCC, 0xDB60E4, 0xDB6134, 0xDB601C, 0xDB610C, 0xDB6094, 0xDB610C, 0xDB6044, 0xDB5F54, 0xDB601C, 0xDB60BC, 0xDB5F7C, 0xDB5FF4, 0xDB5F2C, 0xDB606C]
+IntroCryOffset=0x30B10
+IntroSpriteOffset=0x31928
+TradeTableOffset=0x34D89C
+StaticPokemonSupport=1
+StaticPokemon[]=[0x215CD3, 0x215CF8, 0x215CFB, 0x215D7D, 0x215D8B]
+StaticPokemon[]=[0x215CE5, 0x215D9B, 0x215D9E, 0x215E20, 0x215E2E]
+StaticPokemon[]=[0x24354E, 0x24355C, 0x2435B1]
+StaticPokemon[]=[0x24361F, 0x24362D, 0x243682]
+StaticPokemon[]=[0x234815, 0x23481E, 0x234864]
+StaticPokemon[]=[0x2411BD, 0x2411C6, 0x24120C]
+StaticPokemon[]=[0x2412BF, 0x2412C8, 0x24130E]
+StaticPokemon[]=[0x2419BC, 0x2419C5, 0x241A0B]
+StaticPokemon[]=[0x27DA85, 0x27DA8E]
+StaticPokemon[]=[0x1F7227, 0x1F7230]
+StaticPokemon[]=[0x23F82B, 0x23F832]
+StaticPokemon[]=[0x23F878, 0x23F87F]
+StaticPokemon[]=[0x23F8C5, 0x23F8CC]
+StaticPokemon[]=[0x23B4C0, 0x23B4C7]
+StaticPokemon[]=[0x23B50D, 0x23B514]
+StaticPokemon[]=[0x24B918, 0x24B926]
+StaticPokemon[]=[0x24B7A4]
+StaticPokemon[]=[0x24B7B7]
+StaticPokemon[]=[0x272CA4, 0x272CB4, 0x272CFE, 0x272D09]
+StaticPokemon[]=[0x272AB8, 0x272AF2, 0x272B47, 0x272B52]
+StaticPokemon[]=[0x273F63, 0x273F92, 0x273FE1, 0x273FEC]
+StaticPokemon[]=[0x2740AB, 0x2740B6, 0x274100, 0x27410B]
+StaticPokemon[]=[0x1EB5E8]
+StaticPokemon[]=[0x228813, 0x228816, 0x228898, 0x2288A9]
+StaticPokemon[]=[0x27B588, 0x27B58B]
+
+[Ruby (S)]
+Game=AXVS
+Version=0
+Type=Ruby
+CopyFrom=Ruby (U)
+PokemonStats=0x2039B0
+PokemonMovesets=0x20C948
+PokemonTMHMCompat=0x201E74
+PokemonEvolutions=0x20890C
+StarterPokemon=0x3FB50C
+StarterItems=0x82666
+TrainerData=0x1F521C
+TrainerClassNames=0x1F4F28
+ItemData=0x3C8FFC
+MoveData=0x1FFEB4
+MoveDescriptions=0x3C4504
+MoveNames=0x1FD040
+AbilityNames=0x1FEFC4
+TmMoves=0x379A9C
+PokemonFrontSprites=0x1ED074
+PokemonNormalPalettes=0x1EF2D4
+IntroCryOffset=0xA6D2
+IntroSpriteOffset=0xB484
+IntroPaletteOffset=0xB490
+IntroOtherOffset=0xB452
+TradeTableOffset=0x21A840
+StaticPokemonSupport=1
+StaticPokemon[]=[0x157B5F, 0x157B8D]
+StaticPokemon[]=[0x157BB2, 0x157BE0]
+StaticPokemon[]=[0x1A376D, 0x15E322, 0x15E329]
+StaticPokemon[]=[0x15D085, 0x15D08E]
+StaticPokemon[]=[0x15F49D, 0x15F4A6]
+StaticPokemon[]=[0x15F550, 0x15F559]
+StaticPokemon[]=[0x1610CA, 0x1610F0]
+StaticPokemon[]=[0x15F815, 0x15F81C]
+StaticPokemon[]=[0x1A38AC, 0x1A38B5]
+StaticPokemon[]=[0x151DE4, 0x151DED]
+StaticPokemon[]=[0x15EDFF, 0x15EE06]
+StaticPokemon[]=[0x15EE1D, 0x15EE24]
+StaticPokemon[]=[0x15EE3B, 0x15EE42]
+StaticPokemon[]=[0x1A37CA, 0x1A37D1]
+StaticPokemon[]=[0x1A37E8, 0x1A37EF]
+StaticPokemon[]=[0x14EC96]
+StaticPokemon[]=[0x15AFAB, 0x15AFBB]
+StaticPokemon[]=[0x164295]
+
+[Ruby (S) 1.1]
+Game=AXVS
+Version=1
+Type=Ruby
+CopyStaticPokemon=1
+CopyFrom=Ruby (S)
+
+[Sapphire (S)]
+Game=AXPS
+Version=0
+Type=Sapp
+CopyFrom=Ruby (S)
+PokemonStats=0x203940
+PokemonMovesets=0x20C8D8
+PokemonTMHMCompat=0x201E04
+PokemonEvolutions=0x20889C
+StarterPokemon=0x3FB248
+TrainerData=0x1F51AC
+TrainerClassNames=0x1F4EB8
+ItemData=0x3C8D38
+MoveData=0x1FFE44
+MoveDescriptions=0x3C4240
+MoveNames=0x1FCFD0
+AbilityNames=0x1FEF54
+TmMoves=0x379A2C
+PokemonFrontSprites=0x1ED004
+PokemonNormalPalettes=0x1EF264
+TradeTableOffset=0x21A7D0
+StaticPokemonSupport=1
+StaticPokemon[]=[0x157AEF, 0x157B1D]
+StaticPokemon[]=[0x157B42, 0x157B70]
+StaticPokemon[]=[0x1A36FD, 0x15E2B2, 0x15E2B9]
+StaticPokemon[]=[0x15D015, 0x15D01E]
+StaticPokemon[]=[0x15F42D, 0x15F436]
+StaticPokemon[]=[0x15F4E0, 0x15F4E9]
+StaticPokemon[]=[0x16105A, 0x161080]
+StaticPokemon[]=[0x15F7A5, 0x15F7AC]
+StaticPokemon[]=[0x1A383C, 0x1A3845]
+StaticPokemon[]=[0x151D78, 0x151D81]
+StaticPokemon[]=[0x15ED8F, 0x15ED96]
+StaticPokemon[]=[0x15EDAD, 0x15EDB4]
+StaticPokemon[]=[0x15EDCB, 0x15EDD2]
+StaticPokemon[]=[0x1A375A, 0x1A3761]
+StaticPokemon[]=[0x1A3778, 0x1A377F]
+StaticPokemon[]=[0x14EC2A]
+StaticPokemon[]=[0x15AF3B, 0x15AF4B]
+StaticPokemon[]=[0x164225]
+
+[Sapphire (S) 1.1]
+Game=AXPS
+Version=1
+Type=Sapp
+CopyStaticPokemon=1
+CopyFrom=Sapphire (S)
+
+[Emerald (S)]
+Game=BPES
+Version=0
+Type=Em
+CopyFrom=Emerald (U)
+PokemonStats=0x3266A4
+PokemonMovesets=0x32F63C
+PokemonTMHMCompat=0x324B5C
+PokemonEvolutions=0x32B600
+StarterPokemon=0x5B49FC
+StarterItems=0xBE596
+TrainerData=0x316294
+TrainerClassNames=0x315F38
+MoveDescriptions=0x61EE38
+TmMoves=0x6189D4
+TmMovesDuplicate=0x618E80
+MoveTutorData=0x617E4C
+ItemImages=0x617250
+TmPals=[0xDB5F00, 0xDB5E60, 0xDB60B8, 0xDB5F28, 0xDB6040, 0xDB6090, 0xDB5F78, 0xDB6068, 0xDB5FF0, 0xDB6068, 0xDB5FA0, 0xDB5EB0, 0xDB5F78, 0xDB6018, 0xDB5ED8, 0xDB5F50, 0xDB5E88, 0xDB5FC8]
+IntroCryOffset=0x30B0C
+IntroSpriteOffset=0x31924
+TradeTableOffset=0x33F1AC
+StaticPokemonSupport=1
+StaticPokemon[]=[0x21307F, 0x2130A4, 0x2130A7, 0x213129, 0x213137]
+StaticPokemon[]=[0x213091, 0x213147, 0x21314A, 0x2131CC, 0x2131DA]
+StaticPokemon[]=[0x23DCC5, 0x23DCD3, 0x23DD28]
+StaticPokemon[]=[0x23DD96, 0x23DDA4, 0x23DDF9]
+StaticPokemon[]=[0x22FD3F, 0x22FD48, 0x22FD8E]
+StaticPokemon[]=[0x23BB32, 0x23BB3B, 0x23BB81]
+StaticPokemon[]=[0x23BC34, 0x23BC3D, 0x23BC83]
+StaticPokemon[]=[0x23C305, 0x23C30E, 0x23C354]
+StaticPokemon[]=[0x276188, 0x276191]
+StaticPokemon[]=[0x1F5CDA, 0x1F5CE3]
+StaticPokemon[]=[0x23A38F, 0x23A396]
+StaticPokemon[]=[0x23A3DC, 0x23A3E3]
+StaticPokemon[]=[0x23A429, 0x23A430]
+StaticPokemon[]=[0x236418, 0x23641F]
+StaticPokemon[]=[0x236465, 0x23646C]
+StaticPokemon[]=[0x245C8C, 0x245C9A]
+StaticPokemon[]=[0x245B18]
+StaticPokemon[]=[0x245B2B]
+StaticPokemon[]=[0x26B948, 0x26B958, 0x26B9A2, 0x26B9AD]
+StaticPokemon[]=[0x26B75A, 0x26B794, 0x26B7E9, 0x26B7F4]
+StaticPokemon[]=[0x26CBEA, 0x26CC19, 0x26CC68, 0x26CC73]
+StaticPokemon[]=[0x26CD32, 0x26CD3D, 0x26CD87, 0x26CD92]
+StaticPokemon[]=[0x1EA97A]
+StaticPokemon[]=[0x22477B, 0x22477E, 0x224800, 0x224811]
+StaticPokemon[]=[0x273D60, 0x273D63]
+
+[Ruby (I)]
+Game=AXVI
+Version=0
+Type=Ruby
+CopyFrom=Ruby (U)
+PokemonStats=0x20090C
+PokemonMovesets=0x2098A4
+PokemonTMHMCompat=0x1FEDD0
+PokemonEvolutions=0x205868
+StarterPokemon=0x3F8714
+StarterItems=0x8257E
+TrainerData=0x1F2198
+TrainerClassNames=0x1F1EA4
+ItemData=0x3C5FF8
+MoveData=0x1FCE10
+MoveDescriptions=0x3C158C
+MoveNames=0x1F9FBC
+AbilityNames=0x1FBF20
+TmMoves=0x3769F4
+PokemonFrontSprites=0x1E9FF0
+PokemonNormalPalettes=0x1EC250
+IntroCryOffset=0xA6D2
+IntroSpriteOffset=0xB484
+IntroPaletteOffset=0xB490
+IntroOtherOffset=0xB452
+TradeTableOffset=0x21779C
+StaticPokemonSupport=1
+StaticPokemon[]=[0x157A87, 0x157AB5]
+StaticPokemon[]=[0x157ADA, 0x157B08]
+StaticPokemon[]=[0x1A0E4D, 0x15E24A, 0x15E251]
+StaticPokemon[]=[0x15CFAD, 0x15CFB6]
+StaticPokemon[]=[0x15F3C5, 0x15F3CE]
+StaticPokemon[]=[0x15F478, 0x15F481]
+StaticPokemon[]=[0x160FF2, 0x161018]
+StaticPokemon[]=[0x15F73D, 0x15F744]
+StaticPokemon[]=[0x1A0F8C, 0x1A0F95]
+StaticPokemon[]=[0x151D0C, 0x151D15]
+StaticPokemon[]=[0x15ED27, 0x15ED2E]
+StaticPokemon[]=[0x15ED45, 0x15ED4C]
+StaticPokemon[]=[0x15ED63, 0x15ED6A]
+StaticPokemon[]=[0x1A0EAA, 0x1A0EB1]
+StaticPokemon[]=[0x1A0EC8, 0x1A0ECF]
+StaticPokemon[]=[0x14EBBE]
+StaticPokemon[]=[0x15AED3, 0x15AEE3]
+StaticPokemon[]=[0x1641BD]
+
+[Ruby (I) 1.1]
+Game=AXVI
+Version=1
+Type=Ruby
+CopyStaticPokemon=1
+CopyFrom=Ruby (I)
+
+[Sapphire (I)]
+Game=AXPI
+Version=0
+Type=Sapp
+CopyFrom=Ruby (I)
+PokemonStats=0x20089C
+PokemonMovesets=0x209834
+PokemonTMHMCompat=0x1FED60
+PokemonEvolutions=0x2057F8
+StarterPokemon=0x3F83B8
+TrainerData=0x1F2128
+TrainerClassNames=0x1F1E34
+ItemData=0x3C5C9C
+MoveData=0x1FCDA0
+MoveDescriptions=0x3C1230
+MoveNames=0x1F9F4C
+AbilityNames=0x1FBEB0
+TmMoves=0x376984
+PokemonFrontSprites=0x1E9F80
+PokemonNormalPalettes=0x1EC1E0
+TradeTableOffset=0x21772C
+StaticPokemonSupport=1
+StaticPokemon[]=[0x157A17, 0x157A45]
+StaticPokemon[]=[0x157A6A, 0x157A98]
+StaticPokemon[]=[0x1A0DDD, 0x15E1DA, 0x15E1E1]
+StaticPokemon[]=[0x15CF3D, 0x15CF46]
+StaticPokemon[]=[0x15F355, 0x15F35E]
+StaticPokemon[]=[0x15F408, 0x15F411]
+StaticPokemon[]=[0x160F82, 0x160FA8]
+StaticPokemon[]=[0x15F6CD, 0x15F6D4]
+StaticPokemon[]=[0x1A0F1C, 0x1A0F25]
+StaticPokemon[]=[0x151CA0, 0x151CA9]
+StaticPokemon[]=[0x15ECB7, 0x15ECBE]
+StaticPokemon[]=[0x15ECD5, 0x15ECDC]
+StaticPokemon[]=[0x15ECF3, 0x15ECFA]
+StaticPokemon[]=[0x1A0E3A, 0x1A0E41]
+StaticPokemon[]=[0x1A0E58, 0x1A0E5F]
+StaticPokemon[]=[0x14EB52]
+StaticPokemon[]=[0x15AE63, 0x15AE73]
+StaticPokemon[]=[0x16414D]
+
+[Sapphire (I) 1.1]
+Game=AXPI
+Version=1
+Type=Sapp
+CopyStaticPokemon=1
+CopyFrom=Sapphire (I)
+
+[Emerald (I)]
+Game=BPEI
+Version=0
+Type=Em
+CopyFrom=Emerald (U)
+PokemonStats=0x31FDE8
+PokemonMovesets=0x328D80
+PokemonTMHMCompat=0x31E2A0
+PokemonEvolutions=0x324D44
+StarterPokemon=0x5AE994
+StarterItems=0xBE596
+TrainerData=0x30F9F4
+TrainerClassNames=0x30F698
+MoveDescriptions=0x619038
+TmMoves=0x612730
+TmMovesDuplicate=0x612BDC
+MoveTutorData=0x611BA8
+ItemImages=0x610FAC
+TmPals=[0xDB5FA4, 0xDB5F04, 0xDB615C, 0xDB5FCC, 0xDB60E4, 0xDB6134, 0xDB601C, 0xDB610C, 0xDB6094, 0xDB610C, 0xDB6044, 0xDB5F54, 0xDB601C, 0xDB60BC, 0xDB5F7C, 0xDB5FF4, 0xDB5F2C, 0xDB606C]
+IntroCryOffset=0x30B10
+IntroSpriteOffset=0x31928
+TradeTableOffset=0x3388CC
+StaticPokemonSupport=1
+StaticPokemon[]=[0x211669, 0x21168E, 0x211691, 0x211713, 0x211721]
+StaticPokemon[]=[0x21167B, 0x211731, 0x211734, 0x2117B6, 0x2117C4]
+StaticPokemon[]=[0x23B0B6, 0x23B0C4, 0x23B119]
+StaticPokemon[]=[0x23B187, 0x23B195, 0x23B1EA]
+StaticPokemon[]=[0x22D8D2, 0x22D8DB, 0x22D921]
+StaticPokemon[]=[0x239092, 0x23909B, 0x2390E1]
+StaticPokemon[]=[0x239194, 0x23919D, 0x2391E3]
+StaticPokemon[]=[0x23983F, 0x239848, 0x23988E]
+StaticPokemon[]=[0x271FDB, 0x271FE4]
+StaticPokemon[]=[0x1F51E3, 0x1F51EC]
+StaticPokemon[]=[0x23794B, 0x237952]
+StaticPokemon[]=[0x237998, 0x23799F]
+StaticPokemon[]=[0x2379E5, 0x2379EC]
+StaticPokemon[]=[0x233AB2, 0x233AB9]
+StaticPokemon[]=[0x233AFF, 0x233B06]
+StaticPokemon[]=[0x242D25, 0x242D33]
+StaticPokemon[]=[0x242BB1]
+StaticPokemon[]=[0x242BC4]
+StaticPokemon[]=[0x267A89, 0x267A99, 0x267AE3, 0x267AEE]
+StaticPokemon[]=[0x2678A1, 0x2678DB, 0x267930, 0x26793B]
+StaticPokemon[]=[0x268C5D, 0x268C8C, 0x268CDB, 0x268CE6]
+StaticPokemon[]=[0x268DA5, 0x268DB0, 0x268DFA, 0x268E05]
+StaticPokemon[]=[0x1EA261]
+StaticPokemon[]=[0x222657, 0x22265A, 0x2226DC, 0x2226ED]
+StaticPokemon[]=[0x26FC1D, 0x26FC20]
+
+[Fire Red (F)]
+Game=BPRF
+Version=0
+Type=FRLG
+CopyFrom=Fire Red (U) 1.0
+PokemonStats=0x24EBF0
+PokemonMovesets=0x257C08
+PokemonTMHMCompat=0x24D020
+PokemonEvolutions=0x253BCC
+StarterPokemon=0x169BDC
+TrainerData=0x238ED4
+TrainerClassNames=0x238964
+MoveDescriptions=0x47E7DC
+TmMoves=0x453BA8
+TmMovesDuplicate=0x453E10
+MoveTutorData=0x453164
+ItemImages=0x3CE114
+TmPals=[0xE91DB8, 0xE91D18, 0xE91F70, 0xE91DE0, 0xE91EF8, 0xE91F48, 0xE91E30, 0xE91F20, 0xE91EA8, 0xE91F20, 0xE91E58, 0xE91D68, 0xE91E30, 0xE91ED0, 0xE91D90, 0xE91E08, 0xE91D40, 0xE91E80]
+IntroCryOffset=0x12FC44
+IntroSpriteOffset=0x1310AC
+IntroOtherOffset=0x131058
+TradeTableOffset=0x2673DC
+StaticPokemonSupport=1
+StaticPokemon[]=[0x16C49A, 0x16C49D, 0x16C4DD, 0x16C511]
+StaticPokemon[]=[0x16EC34, 0x16EC3B]
+StaticPokemon[]=[0x16EC7A, 0x16EC81]
+StaticPokemon[]=[0x163862, 0x163869]
+StaticPokemon[]=[0x1638C0, 0x1638C7]
+StaticPokemon[]=[0x1637EE, 0x1637F5, 0x163849]
+StaticPokemon[]=[0x1631E2, 0x1631E9, 0x16323D]
+StaticPokemon[]=[0x163B69, 0x163B70, 0x163BC4]
+StaticPokemon[]=[0x16252C, 0x162540, 0x162586]
+StaticPokemon[]=[0x16806D, 0x168073]
+StaticPokemon[]=[0x168179, 0x16817F]
+StaticPokemon[]=[0x163CDE, 0x163CE4]
+StaticPokemon[]=[0x16530A, 0x16531A, 0x165364, 0x16536F]
+StaticPokemon[]=[0x165060, 0x16508F, 0x1650DE, 0x1650E9]
+StaticPokemon[]=[0x1651AE, 0x1651B9, 0x165203, 0x16520E]
+StaticPokemon[]=[0x16E80D, 0x16E811, 0x16E81C, 0x16E70E]
+StaticPokemon[]=[0x16E783, 0x16E787, 0x16E792, 0x16E692]
+StaticPokemon[]=[0x16E7C8, 0x16E7CC, 0x16E7D7, 0x16E6D0]
+StaticPokemon[]=[0x161AFD, 0x161B3F, 0x161B75]
+StaticPokemon[]=[0x16F7EE, 0x16F8B0]
+StaticPokemon[]=[0x16CC40, 0x16CCBC]
+StaticPokemon[]=[0x16CC50, 0x16CCC7]
+StaticPokemon[]=[0x16CC70, 0x16CCDD]
+StaticPokemon[]=[0x16CC60, 0x16CCD2]
+StaticPokemon[]=[0x16CC80, 0x16CCE8]
+
+[Leaf Green (F)]
+Game=BPGF
+Version=0
+Type=FRLG
+CopyFrom=Fire Red (F)
+PokemonStats=0x24EBCC
+PokemonMovesets=0x257BE8
+PokemonTMHMCompat=0x24CFFC
+PokemonEvolutions=0x253BAC
+StarterPokemon=0x169BB8
+TrainerData=0x238EB0
+TrainerClassNames=0x238940
+MoveDescriptions=0x47D504
+TmMoves=0x452968
+TmMovesDuplicate=0x452BD0
+MoveTutorData=0x451F24
+ItemImages=0x3CDF50
+TmPals=[0xE91E38, 0xE91D98, 0xE91FF0, 0xE91E60, 0xE91F78, 0xE91FC8, 0xE91EB0, 0xE91FA0, 0xE91F28, 0xE91FA0, 0xE91ED8, 0xE91DE8, 0xE91EB0, 0xE91F50, 0xE91E10, 0xE91E88, 0xE91DC0, 0xE91F00]
+IntroCryOffset=0x12FC1C
+IntroSpriteOffset=0x131084
+IntroOtherOffset=0x131030
+TradeTableOffset=0x2673BC
+StaticPokemonSupport=1
+StaticPokemon[]=[0x16C476, 0x16C479, 0x16C4B9, 0x16C4ED] // Eevee in Celadon Mansion
+StaticPokemon[]=[0x16EC10, 0x16EC17] // Hitmonlee in Fighting Dojo
+StaticPokemon[]=[0x16EC56, 0x16EC5D] // Hitmonchan in Fighting Dojo
+StaticPokemon[]=[0x16383E, 0x163845] // Electrode in The Power Plant
+StaticPokemon[]=[0x16389C, 0x1638A3] // Electrode in The Power Plant
+StaticPokemon[]=[0x1637CA, 0x1637D1, 0x163825] // Zapdos in the Power Plant
+StaticPokemon[]=[0x1631BE, 0x1631C5, 0x163219] // Articuno in the Seafoams
+StaticPokemon[]=[0x163B45, 0x163B4C, 0x163BA0] // Moltres in Mt.Ember
+StaticPokemon[]=[0x162508, 0x16251C, 0x162562] // Mewtwo in Unk. Dungeon
+StaticPokemon[]=[0x168049, 0x16804F] // Sleeping Snorlax (12)
+StaticPokemon[]=[0x168155, 0x16815B] // Sleeping Snorlax (16)
+StaticPokemon[]=[0x163CBA, 0x163CC0] // Hypno in Berry Forest
+StaticPokemon[]=[0x1652E6, 0x1652F6, 0x165340, 0x16534B] // Deoxys on Birth Island
+StaticPokemon[]=[0x16503C, 0x16506B, 0x1650BA, 0x1650C5] // Ho-Oh on Navel Rock
+StaticPokemon[]=[0x16518A, 0x165195, 0x1651DF, 0x1651EA] // Lugia on Navel Rock
+StaticPokemon[]=[0x16E7E9, 0x16E7ED, 0x16E7F8, 0x16E6EA] // Old Amber
+StaticPokemon[]=[0x16E75F, 0x16E763, 0x16E76E, 0x16E66E] // Helix Fossil
+StaticPokemon[]=[0x16E7A4, 0x16E7A8, 0x16E7B3, 0x16E6AC] // Dome Fossil
+StaticPokemon[]=[0x161AD9, 0x161B1B, 0x161B51] // Lapras in Silph. Co
+StaticPokemon[]=[0x16F7CA, 0x16F88C] // Magikarp in Mt.Moon Center
+StaticPokemon[]=[0x16CC1C, 0x16CC98] // Abra
+StaticPokemon[]=[0x16CC2C, 0x16CCA3] // Clefairy
+StaticPokemon[]=[0x16CC3C, 0x16CCCF] // Pinsir
+StaticPokemon[]=[0x16CC4C, 0x16CCAE] // Dratini
+StaticPokemon[]=[0x16CC5C, 0x16CCC4] // Porygon
+
+[Fire Red (G)]
+Game=BPRD
+Version=0
+Type=FRLG
+CopyFrom=Fire Red (U) 1.0
+PokemonStats=0x2546C4
+PokemonMovesets=0x25D6DC
+PokemonTMHMCompat=0x252AF4
+PokemonEvolutions=0x2596A0
+StarterPokemon=0x169B20
+TrainerData=0x23E998
+TrainerClassNames=0x23E428
+MoveDescriptions=0x486BEC
+TmMoves=0x45B670
+TmMovesDuplicate=0x45B8D8
+MoveTutorData=0x45AC2C
+ItemImages=0x3D3BE8
+TmPals=[0xE91E84, 0xE91DE4, 0xE9203C, 0xE91EAC, 0xE91FC4, 0xE92014, 0xE91EFC, 0xE91FEC, 0xE91F74, 0xE91FEC, 0xE91F24, 0xE91E34, 0xE91EFC, 0xE91F9C, 0xE91E5C, 0xE91ED4, 0xE91E0C, 0xE91F4C]
+IntroCryOffset=0x12FB88
+IntroSpriteOffset=0x130FF0
+IntroOtherOffset=0x130F9C
+TradeTableOffset=0x26CEB0
+StaticPokemonSupport=1
+StaticPokemon[]=[0x16C3DE, 0x16C3E1, 0x16C421, 0x16C455]
+StaticPokemon[]=[0x16EB78, 0x16EB7F]
+StaticPokemon[]=[0x16EBBE, 0x16EBC5]
+StaticPokemon[]=[0x1637A6, 0x1637AD]
+StaticPokemon[]=[0x163804, 0x16380B]
+StaticPokemon[]=[0x163732, 0x163739, 0x16378D]
+StaticPokemon[]=[0x163126, 0x16312D, 0x163181]
+StaticPokemon[]=[0x163AAD, 0x163AB4, 0x163B08]
+StaticPokemon[]=[0x162470, 0x162484, 0x1624CA]
+StaticPokemon[]=[0x167FB1, 0x167FB7]
+StaticPokemon[]=[0x1680BD, 0x1680C3]
+StaticPokemon[]=[0x163C22, 0x163C28]
+StaticPokemon[]=[0x16524E, 0x16525E, 0x1652A8, 0x1652B3]
+StaticPokemon[]=[0x164FA4, 0x164FD3, 0x165022, 0x16502D]
+StaticPokemon[]=[0x1650F2, 0x1650FD, 0x165147, 0x165152]
+StaticPokemon[]=[0x16E751, 0x16E755, 0x16E760, 0x16E652]
+StaticPokemon[]=[0x16E6C7, 0x16E6CB, 0x16E6D6, 0x16E5D6]
+StaticPokemon[]=[0x16E70C, 0x16E710, 0x16E71B, 0x16E614]
+StaticPokemon[]=[0x161A41, 0x161A83, 0x161AB9]
+StaticPokemon[]=[0x16F732, 0x16F7F4]
+StaticPokemon[]=[0x16CB84, 0x16CC00]
+StaticPokemon[]=[0x16CB94, 0x16CC0B]
+StaticPokemon[]=[0x16CBB4, 0x16CC21]
+StaticPokemon[]=[0x16CBA4, 0x16CC16]
+StaticPokemon[]=[0x16CBC4, 0x16CC2C]
+
+[Leaf Green (G)]
+Game=BPGD
+Version=0
+Type=FRLG
+CopyFrom=Fire Red (G)
+PokemonStats=0x2546A0
+PokemonMovesets=0x25D6BC
+PokemonTMHMCompat=0x252AD0
+PokemonEvolutions=0x259680
+StarterPokemon=0x169AFC
+TrainerData=0x23E974
+TrainerClassNames=0x23E404
+MoveDescriptions=0x485D58
+TmMoves=0x45A874
+TmMovesDuplicate=0x45AADC
+MoveTutorData=0x459E30
+ItemImages=0x3D3A24
+TmPals=[0xE91F04, 0xE91E64, 0xE920BC, 0xE91F2C, 0xE92044, 0xE92094, 0xE91F7C, 0xE9206C, 0xE91FF4, 0xE9206C, 0xE91FA4, 0xE91EB4, 0xE91F7C, 0xE9201C, 0xE91EDC, 0xE91F54, 0xE91E8C, 0xE91FCC]
+IntroCryOffset=0x12FB60
+IntroSpriteOffset=0x130FC8
+IntroOtherOffset=0x130F74
+TradeTableOffset=0x26CE90
+StaticPokemonSupport=1
+StaticPokemon[]=[0x16C3BA, 0x16C3BD, 0x16C3FD, 0x16C431] // Eevee in Celadon Mansion
+StaticPokemon[]=[0x16EB54, 0x16EB5B] // Hitmonlee in Fighting Dojo
+StaticPokemon[]=[0x16EB9A, 0x16EBA1] // Hitmonchan in Fighting Dojo
+StaticPokemon[]=[0x163782, 0x163789] // Electrode in The Power Plant
+StaticPokemon[]=[0x1637E0, 0x1637E7] // Electrode in The Power Plant
+StaticPokemon[]=[0x16370E, 0x163715, 0x163769] // Zapdos in the Power Plant
+StaticPokemon[]=[0x163102, 0x163109, 0x16315D] // Articuno in the Seafoams
+StaticPokemon[]=[0x163A89, 0x163A90, 0x163AE4] // Moltres in Mt.Ember
+StaticPokemon[]=[0x16244C, 0x162460, 0x1624A6] // Mewtwo in Unk. Dungeon
+StaticPokemon[]=[0x167F8D, 0x167F93] // Sleeping Snorlax (12)
+StaticPokemon[]=[0x168099, 0x16809F] // Sleeping Snorlax (16)
+StaticPokemon[]=[0x163BFE, 0x163C04] // Hypno in Berry Forest
+StaticPokemon[]=[0x16522A, 0x16523A, 0x165284, 0x16528F] // Deoxys on Birth Island
+StaticPokemon[]=[0x164F80, 0x164FAF, 0x164FFE, 0x165009] // Ho-Oh on Navel Rock
+StaticPokemon[]=[0x1650CE, 0x1650D9, 0x165123, 0x16512E] // Lugia on Navel Rock
+StaticPokemon[]=[0x16E72D, 0x16E731, 0x16E73C, 0x16E62E] // Old Amber
+StaticPokemon[]=[0x16E6A3, 0x16E6A7, 0x16E6B2, 0x16E5B2] // Helix Fossil
+StaticPokemon[]=[0x16E6E8, 0x16E6EC, 0x16E6F7, 0x16E5F0] // Dome Fossil
+StaticPokemon[]=[0x161A1D, 0x161A5F, 0x161A95] // Lapras in Silph. Co
+StaticPokemon[]=[0x16F70E, 0x16F7D0] // Magikarp in Mt.Moon Center
+StaticPokemon[]=[0x16CB60, 0x16CBDC] // Abra
+StaticPokemon[]=[0x16CB70, 0x16CBE7] // Clefairy
+StaticPokemon[]=[0x16CB80, 0x16CC13] // Pinsir
+StaticPokemon[]=[0x16CB90, 0x16CBF2] // Dratini
+StaticPokemon[]=[0x16CBA0, 0x16CC08] // Porygon
+
+[Fire Red (S)]
+Game=BPRS
+Version=0
+Type=FRLG
+CopyFrom=Fire Red (U) 1.0
+PokemonStats=0x24FF68
+PokemonMovesets=0x258F80
+PokemonTMHMCompat=0x24E398
+PokemonEvolutions=0x254F44
+StarterPokemon=0x169C4C
+TrainerData=0x23A234
+TrainerClassNames=0x239CC4
+MoveDescriptions=0x47EF78
+TmMoves=0x454C1C
+TmMovesDuplicate=0x454E84
+MoveTutorData=0x4541D8
+ItemImages=0x3CF48C
+TmPals=[0xE91D98, 0xE91CF8, 0xE91F50, 0xE91DC0, 0xE91ED8, 0xE91F28, 0xE91E10, 0xE91F00, 0xE91E88, 0xE91F00, 0xE91E38, 0xE91D48, 0xE91E10, 0xE91EB0, 0xE91D70, 0xE91DE8, 0xE91D20, 0xE91E60]
+IntroCryOffset=0x12FCB4
+IntroSpriteOffset=0x13111C
+IntroOtherOffset=0x1310C8
+TradeTableOffset=0x268754
+StaticPokemonSupport=1
+StaticPokemon[]=[0x16C50A, 0x16C50D, 0x16C54D, 0x16C581]
+StaticPokemon[]=[0x16ECA4, 0x16ECAB]
+StaticPokemon[]=[0x16ECEA, 0x16ECF1]
+StaticPokemon[]=[0x1638D2, 0x1638D9]
+StaticPokemon[]=[0x163930, 0x163937]
+StaticPokemon[]=[0x16385E, 0x163865, 0x1638B9]
+StaticPokemon[]=[0x163252, 0x163259, 0x1632AD]
+StaticPokemon[]=[0x163BD9, 0x163BE0, 0x163C34]
+StaticPokemon[]=[0x16259C, 0x1625B0, 0x1625F6]
+StaticPokemon[]=[0x1680DD, 0x1680E3]
+StaticPokemon[]=[0x1681E9, 0x1681EF]
+StaticPokemon[]=[0x163D4E, 0x163D54]
+StaticPokemon[]=[0x16537A, 0x16538A, 0x1653D4, 0x1653DF]
+StaticPokemon[]=[0x1650D0, 0x1650FF, 0x16514E, 0x165159]
+StaticPokemon[]=[0x16521E, 0x165229, 0x165273, 0x16527E]
+StaticPokemon[]=[0x16E87D, 0x16E881, 0x16E88C, 0x16E77E]
+StaticPokemon[]=[0x16E7F3, 0x16E7F7, 0x16E802, 0x16E702]
+StaticPokemon[]=[0x16E838, 0x16E83C, 0x16E847, 0x16E740]
+StaticPokemon[]=[0x161B6D, 0x161BAF, 0x161BE5]
+StaticPokemon[]=[0x16F85E, 0x16F920]
+StaticPokemon[]=[0x16CCB0, 0x16CD2C]
+StaticPokemon[]=[0x16CCC0, 0x16CD37]
+StaticPokemon[]=[0x16CCE0, 0x16CD4D]
+StaticPokemon[]=[0x16CCD0, 0x16CD42]
+StaticPokemon[]=[0x16CCF0, 0x16CD58]
+
+[Leaf Green (S)]
+Game=BPGS
+Version=0
+Type=FRLG
+CopyFrom=Fire Red (S)
+PokemonStats=0x24FF44
+PokemonMovesets=0x258F60
+PokemonTMHMCompat=0x24E374
+PokemonEvolutions=0x254F24
+StarterPokemon=0x169C28
+TrainerData=0x23A210
+TrainerClassNames=0x239CA0
+MoveDescriptions=0x47E670
+TmMoves=0x4543AC
+TmMovesDuplicate=0x454614
+MoveTutorData=0x453968
+ItemImages=0x3CF2C8
+TmPals=[0xE91E18, 0xE91D78, 0xE91FD0, 0xE91E40, 0xE91F58, 0xE91FA8, 0xE91E90, 0xE91F80, 0xE91F08, 0xE91F80, 0xE91EB8, 0xE91DC8, 0xE91E90, 0xE91F30, 0xE91DF0, 0xE91E68, 0xE91DA0, 0xE91EE0]
+IntroCryOffset=0x12FC8C
+IntroSpriteOffset=0x1310F4
+IntroOtherOffset=0x1310A0
+TradeTableOffset=0x268734
+StaticPokemonSupport=1
+StaticPokemon[]=[0x16C4E6, 0x16C4E9, 0x16C529, 0x16C55D] // Eevee in Celadon Mansion
+StaticPokemon[]=[0x16EC80, 0x16EC87] // Hitmonlee in Fighting Dojo
+StaticPokemon[]=[0x16ECC6, 0x16ECCD] // Hitmonchan in Fighting Dojo
+StaticPokemon[]=[0x1638AE, 0x1638B5] // Electrode in The Power Plant
+StaticPokemon[]=[0x16390C, 0x163913] // Electrode in The Power Plant
+StaticPokemon[]=[0x16383A, 0x163841, 0x163895] // Zapdos in the Power Plant
+StaticPokemon[]=[0x16322E, 0x163235, 0x163289] // Articuno in the Seafoams
+StaticPokemon[]=[0x163BB5, 0x163BBC, 0x163C10] // Moltres in Mt.Ember
+StaticPokemon[]=[0x162578, 0x16258C, 0x1625D2] // Mewtwo in Unk. Dungeon
+StaticPokemon[]=[0x1680B9, 0x1680BF] // Sleeping Snorlax (12)
+StaticPokemon[]=[0x1681C5, 0x1681CB] // Sleeping Snorlax (16)
+StaticPokemon[]=[0x163D2A, 0x163D30] // Hypno in Berry Forest
+StaticPokemon[]=[0x165356, 0x165366, 0x1653B0, 0x1653BB] // Deoxys on Birth Island
+StaticPokemon[]=[0x1650AC, 0x1650DB, 0x16512A, 0x165135] // Ho-Oh on Navel Rock
+StaticPokemon[]=[0x1651FA, 0x165205, 0x16524F, 0x16525A] // Lugia on Navel Rock
+StaticPokemon[]=[0x16E859, 0x16E85D, 0x16E868, 0x16E75A] // Old Amber
+StaticPokemon[]=[0x16E7CF, 0x16E7D3, 0x16E7DE, 0x16E6DE] // Helix Fossil
+StaticPokemon[]=[0x16E814, 0x16E818, 0x16E823, 0x16E71C] // Dome Fossil
+StaticPokemon[]=[0x161B49, 0x161B8B, 0x161BC1] // Lapras in Silph. Co
+StaticPokemon[]=[0x16F83A, 0x16F8FC] // Magikarp in Mt.Moon Center
+StaticPokemon[]=[0x16CC8C, 0x16CD08] // Abra
+StaticPokemon[]=[0x16CC9C, 0x16CD13] // Clefairy
+StaticPokemon[]=[0x16CCAC, 0x16CD3F] // Pinsir
+StaticPokemon[]=[0x16CCBC, 0x16CD1E] // Dratini
+StaticPokemon[]=[0x16CCCC, 0x16CD34] // Porygon
+
+[Fire Red (I)]
+Game=BPRI
+Version=0
+Type=FRLG
+CopyFrom=Fire Red (U) 1.0
+PokemonStats=0x24D880
+PokemonMovesets=0x256898
+PokemonTMHMCompat=0x24BCB0
+PokemonEvolutions=0x25285C
+StarterPokemon=0x169B60
+TrainerData=0x237B6C
+TrainerClassNames=0x2375FC
+MoveDescriptions=0x47C174
+TmMoves=0x451580
+TmMovesDuplicate=0x4517E8
+MoveTutorData=0x450B3C
+ItemImages=0x3CCDA4
+TmPals=[0xE91DD4, 0xE91D34, 0xE91F8C, 0xE91DFC, 0xE91F14, 0xE91F64, 0xE91E4C, 0xE91F3C, 0xE91EC4, 0xE91F3C, 0xE91E74, 0xE91D84, 0xE91E4C, 0xE91EEC, 0xE91DAC, 0xE91E24, 0xE91D5C, 0xE91E9C]
+IntroCryOffset=0x12FBC8
+IntroSpriteOffset=0x131030
+IntroOtherOffset=0x130FDC
+TradeTableOffset=0x26606C
+StaticPokemonSupport=1
+StaticPokemon[]=[0x16C41E, 0x16C421, 0x16C461, 0x16C495]
+StaticPokemon[]=[0x16EBB8, 0x16EBBF]
+StaticPokemon[]=[0x16EBFE, 0x16EC05]
+StaticPokemon[]=[0x1637E6, 0x1637ED]
+StaticPokemon[]=[0x163844, 0x16384B]
+StaticPokemon[]=[0x163772, 0x163779, 0x1637CD]
+StaticPokemon[]=[0x163166, 0x16316D, 0x1631C1]
+StaticPokemon[]=[0x163AED, 0x163AF4, 0x163B48]
+StaticPokemon[]=[0x1624B0, 0x1624C4, 0x16250A]
+StaticPokemon[]=[0x167FF1, 0x167FF7]
+StaticPokemon[]=[0x1680FD, 0x168103]
+StaticPokemon[]=[0x163C62, 0x163C68]
+StaticPokemon[]=[0x16528E, 0x16529E, 0x1652E8, 0x1652F3]
+StaticPokemon[]=[0x164FE4, 0x165013, 0x165062, 0x16506D]
+StaticPokemon[]=[0x165132, 0x16513D, 0x165187, 0x165192]
+StaticPokemon[]=[0x16E791, 0x16E795, 0x16E7A0, 0x16E692]
+StaticPokemon[]=[0x16E707, 0x16E70B, 0x16E716, 0x16E616]
+StaticPokemon[]=[0x16E74C, 0x16E750, 0x16E75B, 0x16E654]
+StaticPokemon[]=[0x161A81, 0x161AC3, 0x161AF9]
+StaticPokemon[]=[0x16F772, 0x16F834]
+StaticPokemon[]=[0x16CBC4, 0x16CC40]
+StaticPokemon[]=[0x16CBD4, 0x16CC4B]
+StaticPokemon[]=[0x16CBF4, 0x16CC61]
+StaticPokemon[]=[0x16CBE4, 0x16CC56]
+StaticPokemon[]=[0x16CC04, 0x16CC6C]
+
+[Leaf Green (I)]
+Game=BPGI
+Version=0
+Type=FRLG
+CopyFrom=Fire Red (I)
+PokemonStats=0x24D85C
+PokemonMovesets=0x256878
+PokemonTMHMCompat=0x24BC8C
+PokemonEvolutions=0x25283C
+StarterPokemon=0x169B3C
+TrainerData=0x237B48
+TrainerClassNames=0x2375D8
+MoveDescriptions=0x47B90C
+TmMoves=0x450DB0
+TmMovesDuplicate=0x451018
+MoveTutorData=0x45036C
+ItemImages=0x3CCBE0
+TmPals=[0xE91E54, 0xE91DB4, 0xE9200C, 0xE91E7C, 0xE91F94, 0xE91FE4, 0xE91ECC, 0xE91FBC, 0xE91F44, 0xE91FBC, 0xE91EF4, 0xE91E04, 0xE91ECC, 0xE91F6C, 0xE91E2C, 0xE91EA4, 0xE91DDC, 0xE91F1C]
+IntroCryOffset=0x12FBA0
+IntroSpriteOffset=0x131008
+IntroOtherOffset=0x130FB4
+TradeTableOffset=0x26604C
+StaticPokemonSupport=1
+StaticPokemon[]=[0x16C3FA, 0x16C3FD, 0x16C43D, 0x16C471] // Eevee in Celadon Mansion
+StaticPokemon[]=[0x16EB94, 0x16EB9B] // Hitmonlee in Fighting Dojo
+StaticPokemon[]=[0x16EBDA, 0x16EBE1] // Hitmonchan in Fighting Dojo
+StaticPokemon[]=[0x1637C2, 0x1637C9] // Electrode in The Power Plant
+StaticPokemon[]=[0x163820, 0x163827] // Electrode in The Power Plant
+StaticPokemon[]=[0x16374E, 0x163755, 0x1637A9] // Zapdos in the Power Plant
+StaticPokemon[]=[0x163142, 0x163149, 0x16319D] // Articuno in the Seafoams
+StaticPokemon[]=[0x163AC9, 0x163AD0, 0x163B24] // Moltres in Mt.Ember
+StaticPokemon[]=[0x16248C, 0x1624A0, 0x1624E6] // Mewtwo in Unk. Dungeon
+StaticPokemon[]=[0x167FCD, 0x167FD3] // Sleeping Snorlax (12)
+StaticPokemon[]=[0x1680D9, 0x1680DF] // Sleeping Snorlax (16)
+StaticPokemon[]=[0x163C3E, 0x163C44] // Hypno in Berry Forest
+StaticPokemon[]=[0x16526A, 0x16527A, 0x1652C4, 0x1652CF] // Deoxys on Birth Island
+StaticPokemon[]=[0x164FC0, 0x164FEF, 0x16503E, 0x165049] // Ho-Oh on Navel Rock
+StaticPokemon[]=[0x16510E, 0x165119, 0x165163, 0x16516E] // Lugia on Navel Rock
+StaticPokemon[]=[0x16E76D, 0x16E771, 0x16E77C, 0x16E66E] // Old Amber
+StaticPokemon[]=[0x16E6E3, 0x16E6E7, 0x16E6F2, 0x16E5F2] // Helix Fossil
+StaticPokemon[]=[0x16E728, 0x16E72C, 0x16E737, 0x16E630] // Dome Fossil
+StaticPokemon[]=[0x161A5D, 0x161A9F, 0x161AD5] // Lapras in Silph. Co
+StaticPokemon[]=[0x16F74E, 0x16F810] // Magikarp in Mt.Moon Center
+StaticPokemon[]=[0x16CBA0, 0x16CC1C] // Abra
+StaticPokemon[]=[0x16CBB0, 0x16CC27] // Clefairy
+StaticPokemon[]=[0x16CBC0, 0x16CC53] // Pinsir
+StaticPokemon[]=[0x16CBD0, 0x16CC32] // Dratini
+StaticPokemon[]=[0x16CBE0, 0x16CC48] // Porygon
+
+[Ruby (J)]
+Game=AXVJ
+Version=0
+Type=Ruby
+TableFile=gba_jap
+FreeSpace=0x661000
+PokemonNameLength=6
+PokemonStats=0x1D09E8
+PokemonMovesets=0x1D9980
+PokemonTMHMCompat=0x1CEEAC
+PokemonEvolutions=0x1D5944
+StarterPokemon=0x3D25C8
+StarterItems=0x7F072
+TrainerData=0x1C4C94
+TrainerEntrySize=32
+TrainerCount=0x2B6
+TrainerClassNames=0x1C4A14
+TrainerClassCount=58
+TrainerClassNameLength=11
+TrainerNameLength=6
+ItemData=0x39A648
+ItemEntrySize=40
+ItemCount=348
+MoveData=0x1CCEEC
+MoveNameLength=8
+MoveNames=0x1CACFC
+AbilityNameLength=8
+AbilityNames=0x1CBC44
+TmMoves=0x35017C
+IntroCryOffset=0x7AAA
+IntroSpriteOffset=0x8838
+IntroPaletteOffset=0x8844
+IntroOtherOffset=0x8806
+PokemonFrontSprites=0x1BCB60
+PokemonNormalPalettes=0x1BEDC0
+MapBankCount=0x22
+MapBankSizes=[54,5,5,6,7,7,8,7,7,13,8,17,10,24,13,13,14,2,2,2,3,1,1,1,86,44,12,2,1,13,1,1,3,1]
+ItemBallPic=59
+TradeTableOffset=0x1E9C48
+TradeTableSize=3
+TradesUnused=[]
+StaticPokemonSupport=1
+StaticPokemon[]=[0x162B23, 0x162B50] // Lileep
+StaticPokemon[]=[0x162B75, 0x162BA2] // Anorith
+StaticPokemon[]=[0x174A01, 0x1800AD, 0x1749FA] // Groudon
+StaticPokemon[]=[0x171D3A, 0x171D43] // Regirock
+StaticPokemon[]=[0x1767CC, 0x1767D5] // Regice
+StaticPokemon[]=[0x17687F, 0x176888] // Registeel
+StaticPokemon[]=[0x179434, 0x17945A] // Latias (Southern Island)
+StaticPokemon[]=[0x176B44, 0x176B4B] // Rayquaza
+StaticPokemon[]=[0x1801EC, 0x1801F5] // Kecleons on OW (7)
+StaticPokemon[]=[0x153337, 0x153340] // Kecleon w/ Steven
+StaticPokemon[]=[0x175ADB, 0x175AE2] // Voltorb 1
+StaticPokemon[]=[0x175AF9, 0x175B00] // Voltorb 2
+StaticPokemon[]=[0x175B17, 0x175B1E] // Voltorb 3
+StaticPokemon[]=[0x18010A, 0x180111] // Electrode 1
+StaticPokemon[]=[0x180128, 0x18012F] // Electrode 2
+StaticPokemon[]=[0x14CF1E] // Wynaut Egg
+StaticPokemon[]=[0x16C023, 0x16C033] // Beldum
+StaticPokemon[]=[0x17E914] // Castform
+
+[Sapphire (J)]
+Game=AXPJ
+Version=0
+Type=Sapp
+CopyFrom=Ruby (J)
+PokemonStats=0x1D0978
+PokemonMovesets=0x1D9910
+PokemonTMHMCompat=0x1CEE3C
+PokemonEvolutions=0x1D58D4
+StarterPokemon=0x3D25AC
+TrainerData=0x1C4C24
+TrainerClassNames=0x1C49A4
+ItemData=0x39A62C
+MoveData=0x1CCE7C
+MoveNames=0x1CAC8C
+AbilityNames=0x1CBBD4
+TmMoves=0x35010C
+PokemonFrontSprites=0x1BCAF0
+PokemonNormalPalettes=0x1BED50
+TradeTableOffset=0x1E9BD8
+StaticPokemonSupport=1
+StaticPokemon[]=[0x162AB3, 0x162AE0] // Lileep
+StaticPokemon[]=[0x162B05, 0x162B32] // Anorith
+StaticPokemon[]=[0x174991, 0x18003D, 0x17498A] // Groudon
+StaticPokemon[]=[0x171CCA, 0x171CD3] // Regirock
+StaticPokemon[]=[0x17675C, 0x176765] // Regice
+StaticPokemon[]=[0x17680F, 0x176818] // Registeel
+StaticPokemon[]=[0x1793C4, 0x1793EA] // Latias (Southern Island)
+StaticPokemon[]=[0x176AD4, 0x176ADB] // Rayquaza
+StaticPokemon[]=[0x18017C, 0x180185] // Kecleons on OW (7)
+StaticPokemon[]=[0x1532CB, 0x1532D4] // Kecleon w/ Steven
+StaticPokemon[]=[0x175A6B, 0x175A72] // Voltorb 1
+StaticPokemon[]=[0x175A89, 0x175A90] // Voltorb 2
+StaticPokemon[]=[0x175AA7, 0x175AAE] // Voltorb 3
+StaticPokemon[]=[0x18009A, 0x1800A1] // Electrode 1
+StaticPokemon[]=[0x1800B8, 0x1800BF] // Electrode 2
+StaticPokemon[]=[0x14CEB2] // Wynaut Egg
+StaticPokemon[]=[0x16BFB3, 0x16BFC3] // Beldum
+StaticPokemon[]=[0x17E8A4] // Castform
+
+[Emerald (J)]
+Game=BPEJ
+Version=0
+Type=Em
+TableFile=gba_jap
+FreeSpace=0xE40000
+PokemonNameLength=6
+PokemonStats=0x2F0D70
+PokemonMovesets=0x2F9D08
+PokemonTMHMCompat=0x2EF228
+PokemonEvolutions=0x2F5CCC
+StarterPokemon=0x590C08
+StarterItems=0xB0A66
+TrainerData=0x2E383C
+TrainerEntrySize=32
+TrainerCount=0x357
+TrainerClassNames=0x2E3564
+TrainerClassCount=66
+TrainerClassNameLength=11
+TrainerNameLength=6
+ItemEntrySize=40
+ItemCount=376
+MoveNameLength=8
+AbilityNameLength=8
+TmMoves=0x5E144C
+TmMovesDuplicate=0x5E18F8
+MoveTutorData=0x5E08C4
+MoveTutorMoves=30
+ItemImages=0x5DFCC8
+TmPals=[0xDB613C, 0xDB609C, 0xDB62F4, 0xDB6164, 0xDB627C, 0xDB62CC, 0xDB61B4, 0xDB62A4, 0xDB622C, 0xDB62A4, 0xDB61DC, 0xDB60EC, 0xDB61B4, 0xDB6254, 0xDB6114, 0xDB618C, 0xDB60C4, 0xDB6204]
+IntroCryOffset=0x3084C
+IntroSpriteOffset=0x31664
+MapBankCount=0x22
+MapBankSizes=[57,5,5,6,7,8,9,7,7,14,8,17,10,23,13,15,15,2,2,2,3,1,1,1,108,61,89,2,1,13,1,1,2,1]
+ItemBallPic=59
+TradeTableOffset=0x30D114
+TradeTableSize=4
+TradesUnused=[]
+StaticPokemonSupport=1
+StaticPokemon[]=[0x2015EE, 0x201613, 0x201616, 0x201698, 0x2016A6] // Lileep
+StaticPokemon[]=[0x201600, 0x2016B6, 0x2016B9, 0x20173B, 0x201749] // Anorith
+StaticPokemon[]=[0x21D057, 0x21D065, 0x21D0BA] // Kyogre
+StaticPokemon[]=[0x21D128, 0x21D136, 0x21D18B] // Groudon
+StaticPokemon[]=[0x213E8A, 0x213E93, 0x213ED9] // Regirock
+StaticPokemon[]=[0x21B8A1, 0x21B8AA, 0x21B8F0] // Regice
+StaticPokemon[]=[0x21B9A3, 0x21B9AC, 0x21B9F2] // Registeel
+StaticPokemon[]=[0x21BF95, 0x21BF9E, 0x21BFE4] // Rayquaza
+StaticPokemon[]=[0x243407, 0x243410] // Kecleons on OW (7)
+StaticPokemon[]=[0x1EDB4E, 0x1EDB57] // Kecleon w/ Steven
+StaticPokemon[]=[0x21A80D, 0x21A814] // Voltorb 1
+StaticPokemon[]=[0x21A85A, 0x21A861] // Voltorb 2
+StaticPokemon[]=[0x21A8A7, 0x21A8AE] // Voltorb 3
+StaticPokemon[]=[0x217CF7, 0x217CFE] // Electrode 1
+StaticPokemon[]=[0x217D44, 0x217D4B] // Electrode 2
+StaticPokemon[]=[0x222AB7, 0x222AC5] // Sudowoodo in Battle Frontier
+StaticPokemon[]=[0x222944]
+StaticPokemon[]=[0x222957] // Latias/Latios on Southern Island
+StaticPokemon[]=[0x23B6A0, 0x23B6B0, 0x23B6FA, 0x23B705] // Deoxys on Birth Island
+StaticPokemon[]=[0x23B4DB, 0x23B515, 0x23B56A, 0x23B575] // Mew on Faraway Island
+StaticPokemon[]=[0x23C1AE, 0x23C1DD, 0x23C22C, 0x23C237] // Ho-Oh on Navel Rock
+StaticPokemon[]=[0x23C2F6, 0x23C301, 0x23C34B, 0x23C356] // Lugia on Navel Rock
+StaticPokemon[]=[0x1E5912] // Wynaut Egg
+StaticPokemon[]=[0x20C8FA, 0x20C8FD, 0x20C97F, 0x20C990] // Beldum
+StaticPokemon[]=[0x24161F, 0x241622] // Castform
+
+[Emerald (T-Eng)]
+Game=BPET
+Version=0
+Type=Em
+CopyStaticPokemon=1
+CopyFrom=Emerald (J)
+
+[Fire Red (J)]
+Game=BPRJ
+Version=0
+Type=FRLG
+TableFile=gba_jap
+FreeSpace=0x800000
+PokemonNameLength=6
+PokemonStats=0x2111A8
+PokemonMovesets=0x21A1C0
+PokemonTMHMCompat=0x20F5D8
+PokemonEvolutions=0x216184
+BattleTrappersBanned=[55,56,57,58,59]
+StarterPokemon=0x17D1D0
+TrainerData=0x1FDFD8
+TrainerEntrySize=32
+TrainerCount=0x2E7
+TrainerClassNames=0x1FDB3C
+TrainerClassCount=107
+TrainerClassNameLength=11
+TrainerNameLength=6
+ItemEntrySize=40
+ItemCount=374
+MoveNameLength=8
+AbilityNameLength=8
+TmMoves=0x419D34
+TmMovesDuplicate=0x419F9C
+MoveTutorData=0x4192F0
+MoveTutorMoves=15
+ItemImages=0x39C79C
+TmPals=[0xD91E8C, 0xD91DEC, 0xD92044, 0xD91EB4, 0xD91FCC, 0xD9201C, 0xD91F04, 0xD91FF4, 0xD91F7C, 0xD91FF4, 0xD91F2C, 0xD91E3C, 0xD91F04, 0xD91FA4, 0xD91E64, 0xD91EDC, 0xD91E14, 0xD91F54]
+IntroCryOffset=0x13034C
+IntroSpriteOffset=0x1317B4
+IntroOtherOffset=0x131760
+MapBankCount=0x2B
+MapBankSizes=[5,123,60,66,4,6,8,10,6,8,20,10,8,2,10,4,2,2,2,1,1,2,2,3,2,3,2,1,1,1,1,7,5,5,8,8,5,5,1,1,1,2,1]
+ItemBallPic=92
+TradeTableOffset=0x22D2F8
+TradeTableSize=9
+TradesUnused=[]
+StaticPokemonSupport=1
+StaticPokemon[]=[0x184BB8, 0x184BBB, 0x184BFB, 0x184C2F] // Eevee in Celadon Mansion
+StaticPokemon[]=[0x18A2E0, 0x18A2E7] // Hitmonlee in Fighting Dojo
+StaticPokemon[]=[0x18A326, 0x18A32D] // Hitmonchan in Fighting Dojo
+StaticPokemon[]=[0x16C18B, 0x16C192] // Electrode in The Power Plant
+StaticPokemon[]=[0x16C1E9, 0x16C1F0] // Electrode in The Power Plant
+StaticPokemon[]=[0x16C117, 0x16C11E, 0x16C172] // Zapdos in the Power Plant
+StaticPokemon[]=[0x16B2B8, 0x16B2BF, 0x16B313] // Articuno in the Seafoams
+StaticPokemon[]=[0x16C846, 0x16C84D, 0x16C8A1] // Moltres in Mt.Ember
+StaticPokemon[]=[0x1693E1, 0x1693F5, 0x16943B] // Mewtwo in Unk. Dungeon
+StaticPokemon[]=[0x1769F0, 0x1769F7] // Sleeping Snorlax (12)
+StaticPokemon[]=[0x177A5E, 0x177A65] // Sleeping Snorlax (16)
+StaticPokemon[]=[0x16C9CA, 0x16C9D0] // Hypno in Berry Forest
+StaticPokemon[]=[0x16F243, 0x16F253, 0x16F29D, 0x16F2A8] // Deoxys on Birth Island
+StaticPokemon[]=[0x16EF99, 0x16EFC8, 0x16F017, 0x16F022] // Ho-Oh on Navel Rock
+StaticPokemon[]=[0x16F0E7, 0x16F0F2, 0x16F13C, 0x16F147] // Lugia on Navel Rock
+StaticPokemon[]=[0x18959C, 0x1895A0, 0x1895AB, 0x18949D] // Old Amber
+StaticPokemon[]=[0x189512, 0x189516, 0x189521, 0x189421] // Helix Fossil
+StaticPokemon[]=[0x189557, 0x18955B, 0x189566, 0x18945F] // Dome Fossil
+StaticPokemon[]=[0x1675D8, 0x167617, 0x16764A] // Lapras in Silph. Co
+StaticPokemon[]=[0x18C668, 0x18C727] // Magikarp in Mt.Moon Center
+StaticPokemon[]=[0x185A8A, 0x185B06] // Abra
+StaticPokemon[]=[0x185A9A, 0x185B11] // Clefairy
+StaticPokemon[]=[0x185ABA, 0x185B27] // Scyther
+StaticPokemon[]=[0x185AAA, 0x185B1C] // Dratini
+StaticPokemon[]=[0x185ACA, 0x185B32] // Porygon
+
+[Fire Red (J) 1.1]
+Game=BPRJ
+Version=1
+Type=FRLG
+CopyFrom=Fire Red (J)
+PokemonStats=0x20C9C0
+PokemonMovesets=0x2159D8
+PokemonTMHMCompat=0x20ADF0
+PokemonEvolutions=0x21199C
+StarterPokemon=0x17CD8E
+TrainerData=0x1F97F0
+TrainerClassNames=0x1F9354
+TmMoves=0x415634
+TmMovesDuplicate=0x41589C
+MoveTutorData=0x414BF0
+ItemImages=0x397F5C
+IntroCryOffset=0x13029C
+IntroSpriteOffset=0x131704
+IntroOtherOffset=0x1316B0
+TradeTableOffset=0x228B10
+StaticPokemonSupport=1
+StaticPokemon[]=[0x184774, 0x184777, 0x1847B7, 0x1847EB] // Eevee in Celadon Mansion
+StaticPokemon[]=[0x189E9C, 0x189EA3] // Hitmonlee in Fighting Dojo
+StaticPokemon[]=[0x189EE2, 0x189EE9] // Hitmonchan in Fighting Dojo
+StaticPokemon[]=[0x16BD20, 0x16BD27] // Electrode in The Power Plant
+StaticPokemon[]=[0x16BD7E, 0x16BD85] // Electrode in The Power Plant
+StaticPokemon[]=[0x16BCAC, 0x16BCB3, 0x16BD07] // Zapdos in the Power Plant
+StaticPokemon[]=[0x16AE48, 0x16AE4F, 0x16AEA3] // Articuno in the Seafoams
+StaticPokemon[]=[0x16C3DB, 0x16C3E2, 0x16C436] // Moltres in Mt.Ember
+StaticPokemon[]=[0x168F71, 0x168F85, 0x168FCB] // Mewtwo in Unk. Dungeon
+StaticPokemon[]=[0x1765A4, 0x1765AB] // Sleeping Snorlax (12)
+StaticPokemon[]=[0x177612, 0x177619] // Sleeping Snorlax (16)
+StaticPokemon[]=[0x16C55F, 0x16C565] // Hypno in Berry Forest
+StaticPokemon[]=[0x16EDDB, 0x16EDEB, 0x16EE35, 0x16EE40] // Deoxys on Birth Island
+StaticPokemon[]=[0x16EB31, 0x16EB60, 0x16EBAF, 0x16EBBA] // Ho-Oh on Navel Rock
+StaticPokemon[]=[0x16EC7F, 0x16EC8A, 0x16ECD4, 0x16ECDF] // Lugia on Navel Rock
+StaticPokemon[]=[0x189158, 0x18915C, 0x189167, 0x189059] // Old Amber
+StaticPokemon[]=[0x1890CE, 0x1890D2, 0x1890DD, 0x188FDD] // Helix Fossil
+StaticPokemon[]=[0x189113, 0x189117, 0x189122, 0x18901B] // Dome Fossil
+StaticPokemon[]=[0x167163, 0x1671A2, 0x1671D5] // Lapras in Silph. Co
+StaticPokemon[]=[0x18C224, 0x18C2E3] // Magikarp in Mt.Moon Center
+StaticPokemon[]=[0x185646, 0x1856C2] // Abra
+StaticPokemon[]=[0x185656, 0x1856CD] // Clefairy
+StaticPokemon[]=[0x185676, 0x1856E3] // Scyther
+StaticPokemon[]=[0x185666, 0x1856D8] // Dratini
+StaticPokemon[]=[0x185686, 0x1856EE] // Porygon
+
+[Leaf Green (J)]
+Game=BPGJ
+Version=0
+Type=FRLG
+CopyFrom=Fire Red (J)
+PokemonStats=0x211184
+PokemonMovesets=0x21A1A0
+PokemonTMHMCompat=0x20F5B4
+PokemonEvolutions=0x216164
+StarterPokemon=0x17D1AC
+TrainerData=0x1FDFB4
+TrainerClassNames=0x1FDB18
+TmMoves=0x419CBC
+TmMovesDuplicate=0x419F24
+MoveTutorData=0x419278
+ItemImages=0x39C60C
+TmPals=[0xD91F0C, 0xD91E6C, 0xD920C4, 0xD91F34, 0xD9204C, 0xD9209C, 0xD91F84, 0xD92074, 0xD91FFC, 0xD92074, 0xD91FAC, 0xD91EBC, 0xD91F84, 0xD92024, 0xD91EE4, 0xD91F5C, 0xD91E94, 0xD91FD4]
+IntroCryOffset=0x130324
+IntroSpriteOffset=0x13178C
+IntroOtherOffset=0x131738
+TradeTableOffset=0x22D2D8
+StaticPokemonSupport=1
+StaticPokemon[]=[0x184B94, 0x184B97, 0x184BD7, 0x184C0B] // Eevee in Celadon Mansion
+StaticPokemon[]=[0x18A2BC, 0x18A2C3] // Hitmonlee in Fighting Dojo
+StaticPokemon[]=[0x18A302, 0x18A309] // Hitmonchan in Fighting Dojo
+StaticPokemon[]=[0x16C167, 0x16C16E] // Electrode in The Power Plant
+StaticPokemon[]=[0x16C1C5, 0x16C1CC] // Electrode in The Power Plant
+StaticPokemon[]=[0x16C0F3, 0x16C0FA, 0x16C14E] // Zapdos in the Power Plant
+StaticPokemon[]=[0x16B294, 0x16B29B, 0x16B2EF] // Articuno in the Seafoams
+StaticPokemon[]=[0x16C822, 0x16C829, 0x16C87D] // Moltres in Mt.Ember
+StaticPokemon[]=[0x1693BD, 0x1693D1, 0x169417] // Mewtwo in Unk. Dungeon
+StaticPokemon[]=[0x1769CC, 0x1769D3] // Sleeping Snorlax (12)
+StaticPokemon[]=[0x177A3A, 0x177A41] // Sleeping Snorlax (16)
+StaticPokemon[]=[0x16C9A6, 0x16C9AC] // Hypno in Berry Forest
+StaticPokemon[]=[0x16F21F, 0x16F22F, 0x16F279, 0x16F284] // Deoxys on Birth Island
+StaticPokemon[]=[0x16EF75, 0x16EFA4, 0x16EFF3, 0x16EFFE] // Ho-Oh on Navel Rock
+StaticPokemon[]=[0x16F0C3, 0x16F0CE, 0x16F118, 0x16F123] // Lugia on Navel Rock
+StaticPokemon[]=[0x189578, 0x18957C, 0x189587, 0x189479] // Old Amber
+StaticPokemon[]=[0x1894EE, 0x1894F2, 0x1894FD, 0x1893FD] // Helix Fossil
+StaticPokemon[]=[0x189533, 0x189537, 0x189542, 0x18943B] // Dome Fossil
+StaticPokemon[]=[0x1675B4, 0x1675F3, 0x167626] // Lapras in Silph. Co
+StaticPokemon[]=[0x18C644, 0x18C703] // Magikarp in Mt.Moon Center
+StaticPokemon[]=[0x185A66, 0x185AE2]
+StaticPokemon[]=[0x185A76, 0x185AED]
+StaticPokemon[]=[0x185A86, 0x185B19]
+StaticPokemon[]=[0x185A96, 0x185AF8]
+StaticPokemon[]=[0x185AA6, 0x185B0E]
\ No newline at end of file
diff --git a/src/com/dabomstew/pkrandom/config/gen4_offsets.ini b/src/com/dabomstew/pkrandom/config/gen4_offsets.ini
new file mode 100755
index 000000000..cc8ef5948
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/config/gen4_offsets.ini
@@ -0,0 +1,539 @@
+[Diamond (U)]
+Game=ADAE
+Type=DP
+PokemonStats=poketool/personal/personal.narc
+PokemonMovesets=poketool/personal/wotbl.narc
+PokemonEvolutions=poketool/personal/evo.narc
+BabyPokemon=poketool/personal/pms.narc
+TrainerData=poketool/trainer/trdata.narc
+TrainerPokemon=poketool/trainer/trpoke.narc
+MoveData=poketool/waza/waza_tbl.narc
+WildPokemon=fielddata/encountdata/d_enc_data.narc
+InGameTrades=fielddata/pokemon_trade/fld_trade.narc
+StarterPokemonOvlNumber=64
+StarterPokemonOffset=0x1B88
+Scripts=fielddata/script/scr_seq_release.narc
+Text=msgdata/msg.narc
+HasExtraPokemonNames=Yes
+PokemonNamesTextOffset=362
+TrainerNamesTextOffset=559
+TrainerClassesTextOffset=560
+MoveDescriptionsTextOffset=587
+MoveNamesTextOffset=588
+AbilityNamesTextOffset=552
+ItemNamesTextOffset=344
+ItemDescriptionsTextOffset=343
+StarterScreenTextOffset=320
+PokedexSpeciesTextOffset=621
+StarterLocationTextOffset=270
+IngameTradesTextOffset=326
+HiddenItemTableOffset=0xF2DB4
+HiddenItemCount=229
+Events=fielddata/eventdata/zone_event_release.narc
+ItemBallsScriptOffset=370
+ItemBallsSkip=[40, 196]
+StaticPokemonSupport=1
+StaticPokemon[]=[230:0x4AE, 230:0xE9A, 230:0xECE, 230:0x1201, 230:0x1235] // Dialga
+StaticPokemon[]=[230:0x4B4, 230:0xEA0, 230:0xED4, 230:0x1207, 230:0x123B] // Palkia
+StaticPokemon[]=[352:0x39, 352:0x48] // Uxie
+StaticPokemon[]=[348:0x81, 348:0x90] // Azelf
+StaticPokemon[]=[278:0x16F, 278:0x17E] // Heatran
+StaticPokemon[]=[309:0x88, 309:0x94] // Regigigas
+StaticPokemon[]=[283:0x50, 283:0x5F] // Giratina
+StaticPokemon[]=[354:0x40] // Darkrai
+StaticPokemon[]=[302:0x39, 302:0x48] // Shaymin
+StaticPokemon[]=[232:0x45, 232:0x53, 232:0x62] // Arceus
+StaticPokemon[]=[112:0xB5] // Eevee
+StaticPokemon[]=[90:0x568] // Happiny
+StaticPokemon[]=[321:0x332] // Riolu
+StaticPokemon[]=[210:0x1C5, 210:0x1D6] // Drifloon
+StaticPokemon[]=[329:0x74, 329:0x80] // Rotom
+StaticPokemon[]=[406:0x153, 406:0x160] // Spiritomb
+
+
+[Pearl (U)]
+Game=APAE
+Type=DP
+CopyStaticPokemon=1
+CopyFrom=ADAE
+PokemonStats=poketool/personal_pearl/personal.narc
+WildPokemon=fielddata/encountdata/p_enc_data.narc
+
+[Platinum (U)]
+Game=CPUE
+Type=Plat
+CopyFrom=ADAE
+PokemonStats=poketool/personal/pl_personal.narc
+MoveData=poketool/waza/pl_waza_tbl.narc
+WildPokemon=fielddata/encountdata/pl_enc_data.narc
+Scripts=fielddata/script/scr_seq.narc
+StarterPokemonOvlNumber=78
+StarterPokemonOffset=0x1BC0
+MoveTutorMovesOvlNumber=5
+MoveTutorMovesOffset=0x2FF64
+MoveTutorCount=38
+MoveTutorBytesCount=12
+MoveTutorCompatOvlNumber=5
+MoveTutorCompatOffset=0x3012C
+MoveTutorCompatBytes=5
+Text=msgdata/pl_msg.narc
+PokemonNamesTextOffset=412
+TrainerNamesTextOffset=618
+TrainerClassesTextOffset=619
+MoveDescriptionsTextOffset=646
+MoveNamesTextOffset=647
+AbilityNamesTextOffset=610
+ItemDescriptionsTextOffset=391
+ItemNamesTextOffset=392
+StarterScreenTextOffset=360
+PokedexSpeciesTextOffset=711
+StarterLocationTextOffset=466
+IngameTradesTextOffset=370
+HiddenItemTableOffset=0xEA378
+HiddenItemCount=257
+Events=fielddata/eventdata/zone_event.narc
+ItemBallsScriptOffset=404
+ItemBallsSkip=[25, 238, 321, 325, 326]
+StaticPokemonSupport=1
+StaticPokemon[]=[361:0x39, 361:0x48] // Uxie
+StaticPokemon[]=[357:0x81, 357:0x90] // Azelf
+StaticPokemon[]=[239:0xAB, 239:0xB8] // Dialga
+StaticPokemon[]=[240:0xAB, 240:0xB8] // Palkia
+StaticPokemon[]=[286:0x103, 286:0x112] // Heatran
+StaticPokemon[]=[317:0x88, 317:0x94] // Regigigas
+StaticPokemon[]=[392:0xB0, 392:0xBD] // Registeel
+StaticPokemon[]=[394:0xB0, 394:0xBD] // Regice
+StaticPokemon[]=[396:0xB0, 396:0xBD] // Regirock
+StaticPokemon[]=[363:0x8E] // Darkrai
+StaticPokemon[]=[310:0x87, 310:0x96] // Shaymin
+StaticPokemon[]=[238:0x6C, 238:0x7A, 238:0x89] // Arceus
+StaticPokemon[]=[71:0xE5B] // Togepi
+StaticPokemon[]=[117:0x79] // Eevee
+StaticPokemon[]=[153:0x7D] // Porygon
+StaticPokemon[]=[329:0x338] // Riolu
+StaticPokemon[]=[216:0x1C9, 216:0x1DA] // Drifloon
+StaticPokemon[]=[337:0x51, 337:0x5D] // Rotom
+StaticPokemon[]=[441:0x153, 441:0x160] // Spiritomb
+
+[HeartGold (U)]
+Game=IPKE
+Type=HGSS
+PokemonStats=a/0/0/2
+PokemonMovesets=a/0/3/3
+PokemonEvolutions=a/0/3/4
+BabyPokemon=poketool/personal/pms.narc
+TrainerData=a/0/5/5
+TrainerPokemon=a/0/5/6
+MoveData=a/0/1/1
+WildPokemon=a/0/3/7
+InGameTrades=a/1/1/2
+Scripts=a/0/1/2
+MoveTutorMovesOvlNumber=1
+MoveTutorMovesOffset=0x23AE0
+MoveTutorCount=51
+MoveTutorBytesCount=4
+MoveTutorCompat=fielddata/wazaoshie/waza_oshie.bin
+MoveTutorCompatOffset=0
+MoveTutorCompatBytesCount=8
+Text=a/0/2/7
+HasExtraPokemonNames=Yes
+PokemonNamesTextOffset=237
+TrainerNamesTextOffset=729
+TrainerClassesTextOffset=730
+MoveDescriptionsTextOffset=749
+MoveNamesTextOffset=750
+AbilityNamesTextOffset=720
+ItemDescriptionsTextOffset=221
+ItemNamesTextOffset=222
+StarterScreenTextOffset=190
+IngameTradesTextOffset=200
+HiddenItemTableOffset=0xFA558
+HiddenItemCount=231
+Events=a/0/3/2
+ItemBallsScriptOffset=141
+ItemBallsSkip=[58]
+StaticPokemonSupport=1
+StaticPokemon[]=[104:0x108] // Lugia
+StaticPokemon[]=[21:0xD1] // Ho-oh
+StaticPokemon[]=[216:0x58F, 216:0x6E8, 216:0x708, 24:0x67, 24:0xB4, 24:0x314, 24:0x320, 24:0xD4] // Suicune
+StaticPokemon[]=[14:0x2F, 14:0x3B] // Articuno
+StaticPokemon[]=[191:0x26B, 191:0x277] // Zapdos
+StaticPokemon[]=[106:0x2F, 106:0x3B] // Moltres
+StaticPokemon[]=[11:0x2F, 11:0x3B] // Mewtwo
+StaticPokemon[]=[134:0xA3, 134:0xB4] // Kyogre
+StaticPokemon[]=[133:0xA3, 133:0xB4] // Groudon
+StaticPokemon[]=[135:0xDA, 135:0xEB, 135:0x62, 135:0x98] // Rayquaza
+StaticPokemon[]=[131:0x43A, 131:0x67C, 131:0x872, 131:0x8E4] // Dialga
+StaticPokemon[]=[131:0x4A2, 131:0x695, 131:0x88D, 131:0x8FA] // Palkia
+StaticPokemon[]=[131:0x50A] // Giratina
+StaticPokemon[]=[750:0x4CC] // Latias
+StaticPokemon[]=[750:0x4B7] // Latios
+StaticPokemon[]=[243:0x2FD, 243:0x14B] // Sudowoodo
+StaticPokemon[]=[58:0x61, 58:0x6D] // Lapras
+StaticPokemon[]=[938:0x3CD, 938:0x3DE] // Red Gyarados
+StaticPokemon[]=[197:0x6C, 197:0x7D] // Snorlax
+StaticPokemon[]=[89:0xF3D, 89:0x1078, 89:0x10A5, 89:0x112C, 89:0x11B1] // Koffing @ Rocket Base
+StaticPokemon[]=[89:0xF6A, 89:0xFC4, 89:0x101E, 89:0x104B, 89:0x1159, 89:0x1186] // Voltorb @ Rocket Base
+StaticPokemon[]=[89:0xF97, 89:0xFF1, 89:0x10D2, 89:0x10FF, 89:0x11E0] // Geodude @ Rocket Base
+StaticPokemon[]=[90:0x784] // Electrode @ Rocket Base (1)
+StaticPokemon[]=[90:0x7E8] // Electrode @ Rocket Base (2)
+StaticPokemon[]=[90:0x84C] // Electrode @ Rocket Base (3)
+StaticPokemon[]=[892:0x61] // Eevee
+StaticPokemon[]=[98:0x71] // Tyrogue
+StaticPokemon[]=[112:0x4D1] // Dratini
+StaticPokemon[]=[740:0x66F, 740:0x675, 740:0x695, 740:0x818, 740:0x8BC] // Bulbasaur
+StaticPokemon[]=[740:0x71D, 740:0x723, 740:0x743, 740:0x833, 740:0x8D7] // Squirtle
+StaticPokemon[]=[740:0x7CB, 740:0x7D1, 740:0x7F1] // Charmander
+StaticPokemon[]=[837:0x28F] // Treecko
+StaticPokemon[]=[837:0x2A8] // Torchic
+StaticPokemon[]=[837:0x2B4] // Mudkipz
+StaticPokemon[]=[860:0x146, 860:0x14D] // Primo's Mareep Egg
+StaticPokemon[]=[860:0x180, 860:0x187] // Primo's Wooper Egg
+StaticPokemon[]=[860:0x1BA, 860:0x1C1] // Primo's Slugma Egg
+StaticPokemonTrades=[6,7] // Shuckie & Kenya
+MysteryEggOffset=0x1C80E // Togepi Mystery Egg
+
+[SoulSilver (U)]
+Game=IPGE
+Type=HGSS
+CopyStaticPokemon=1
+CopyFrom=IPKE
+WildPokemon=a/1/3/6
+
+[Pearl (J)]
+Game=APAJ
+Type=DP
+CopyFrom=APAE
+StarterPokemonOffset=0x30
+Scripts=fielddata/script/scr_seq.narc
+HiddenItemTableOffset=0xF4C14
+Events=fielddata/eventdata/zone_event.narc
+HasExtraPokemonNames=No
+PokemonNamesTextOffset=356
+TrainerNamesTextOffset=550
+TrainerClassesTextOffset=551
+MoveDescriptionsTextOffset=574
+MoveNamesTextOffset=575
+AbilityNamesTextOffset=544
+ItemDescriptionsTextOffset=340
+ItemNamesTextOffset=341
+StarterScreenTextOffset=318
+PokedexSpeciesTextOffset=607
+StarterLocationTextOffset=269
+IngameTradesTextOffset=324
+
+[Diamond (J)]
+Game=ADAJ
+Type=DP
+CopyFrom=ADAE
+StarterPokemonOffset=0x30
+Scripts=fielddata/script/scr_seq.narc
+HiddenItemTableOffset=0xF4C10
+Events=fielddata/eventdata/zone_event.narc
+HasExtraPokemonNames=No
+PokemonNamesTextOffset=356
+TrainerNamesTextOffset=550
+TrainerClassesTextOffset=551
+MoveDescriptionsTextOffset=574
+MoveNamesTextOffset=575
+AbilityNamesTextOffset=544
+ItemDescriptionsTextOffset=340
+ItemNamesTextOffset=341
+StarterScreenTextOffset=318
+PokedexSpeciesTextOffset=607
+StarterLocationTextOffset=269
+IngameTradesTextOffset=324
+
+[Pearl (G)]
+Game=APAD
+Type=DP
+CopyFrom=APAE
+HiddenItemTableOffset=0xF2DC4
+InGameTrades=resource/ger/pokemon_trade/fld_trade.narc
+
+[Diamond (G)]
+Game=ADAD
+Type=DP
+CopyFrom=ADAE
+HiddenItemTableOffset=0xF2DC4
+InGameTrades=resource/ger/pokemon_trade/fld_trade.narc
+
+[Pearl (S)]
+Game=APAS
+Type=DP
+CopyFrom=APAE
+HiddenItemTableOffset=0xF2E00
+InGameTrades=resource/spa/pokemon_trade/fld_trade.narc
+
+[Diamond (S)]
+Game=ADAS
+Type=DP
+CopyFrom=ADAE
+HiddenItemTableOffset=0xF2E00
+InGameTrades=resource/spa/pokemon_trade/fld_trade.narc
+
+[Pearl (I)]
+Game=APAI
+Type=DP
+CopyFrom=APAE
+HiddenItemTableOffset=0xF2D68
+InGameTrades=resource/ita/pokemon_trade/fld_trade.narc
+
+[Diamond (I)]
+Game=ADAI
+Type=DP
+CopyFrom=ADAE
+HiddenItemTableOffset=0xF2D68
+InGameTrades=resource/ita/pokemon_trade/fld_trade.narc
+
+[Pearl (F)]
+Game=APAF
+Type=DP
+CopyFrom=APAE
+HiddenItemTableOffset=0xF2DF4
+InGameTrades=resource/fra/pokemon_trade/fld_trade.narc
+
+[Diamond (F)]
+Game=ADAF
+Type=DP
+CopyFrom=ADAE
+HiddenItemTableOffset=0xF2DF4
+InGameTrades=resource/fra/pokemon_trade/fld_trade.narc
+
+[Pearl (K)]
+Game=APAK
+Type=DP
+CopyFrom=APAE
+HiddenItemTableOffset=0xEE400
+HasExtraPokemonNames=No
+PokemonNamesTextOffset=357
+TrainerNamesTextOffset=552
+TrainerClassesTextOffset=553
+MoveDescriptionsTextOffset=576
+MoveNamesTextOffset=577
+AbilityNamesTextOffset=546
+ItemDescriptionsTextOffset=341
+ItemNamesTextOffset=342
+StarterScreenTextOffset=319
+PokedexSpeciesTextOffset=609
+StarterLocationTextOffset=269
+IngameTradesTextOffset=325
+InGameTrades=resource/kor/pokemon_trade/fld_trade.narc
+
+[Diamond (K)]
+Game=ADAK
+Type=DP
+CopyFrom=ADAE
+HiddenItemTableOffset=0xEE400
+HasExtraPokemonNames=No
+PokemonNamesTextOffset=357
+TrainerNamesTextOffset=552
+TrainerClassesTextOffset=553
+MoveDescriptionsTextOffset=576
+MoveNamesTextOffset=577
+AbilityNamesTextOffset=546
+ItemDescriptionsTextOffset=341
+ItemNamesTextOffset=342
+StarterScreenTextOffset=319
+PokedexSpeciesTextOffset=609
+StarterLocationTextOffset=269
+IngameTradesTextOffset=325
+InGameTrades=resource/kor/pokemon_trade/fld_trade.narc
+
+[Platinum (J)]
+Game=CPUJ
+Type=Plat
+CopyFrom=CPUE
+HiddenItemTableOffset=0xE9A4C
+MoveTutorMovesOffset=0x2FD54
+MoveTutorCompatOffset=0x2FF1C
+StarterPokemonOffset=0x1BAC
+HasExtraPokemonNames=No
+PokemonNamesTextOffset=408
+TrainerNamesTextOffset=611
+TrainerClassesTextOffset=612
+MoveDescriptionsTextOffset=635
+MoveNamesTextOffset=636
+AbilityNamesTextOffset=604
+ItemDescriptionsTextOffset=389
+ItemNamesTextOffset=390
+StarterScreenTextOffset=359
+PokedexSpeciesTextOffset=698
+StarterLocationTextOffset=460
+IngameTradesTextOffset=369
+
+[Platinum (G)]
+Game=CPUD
+Type=Plat
+CopyFrom=CPUE
+HiddenItemTableOffset=0xEA3D0
+MoveTutorMovesOffset=0x2FF80
+MoveTutorCompatOffset=0x30148
+InGameTrades=resource/ger/pokemon_trade/fld_trade.narc
+
+[Platinum (F)]
+Game=CPUF
+Type=Plat
+CopyFrom=CPUE
+HiddenItemTableOffset=0xEA400
+MoveTutorMovesOffset=0x2FF6C
+MoveTutorCompatOffset=0x30134
+InGameTrades=resource/fra/pokemon_trade/fld_trade.narc
+
+[Platinum (S)]
+Game=CPUS
+Type=Plat
+CopyFrom=CPUE
+HiddenItemTableOffset=0xEA40C
+MoveTutorMovesOffset=0x2FF6C
+MoveTutorCompatOffset=0x30134
+InGameTrades=resource/spa/pokemon_trade/fld_trade.narc
+
+[Platinum (I)]
+Game=CPUI
+Type=Plat
+CopyFrom=CPUE
+HiddenItemTableOffset=0xEA394
+MoveTutorMovesOffset=0x2FF74
+MoveTutorCompatOffset=0x3013C
+InGameTrades=resource/ita/pokemon_trade/fld_trade.narc
+
+[Platinum (K)]
+Game=CPUK
+Type=Plat
+CopyFrom=CPUE
+HiddenItemTableOffset=0xEAE00
+MoveTutorMovesOffset=0x2FF5C
+MoveTutorCompatOffset=0x30124
+HasExtraPokemonNames=No
+PokemonNamesTextOffset=408
+TrainerNamesTextOffset=612
+TrainerClassesTextOffset=613
+MoveDescriptionsTextOffset=636
+MoveNamesTextOffset=637
+AbilityNamesTextOffset=605
+ItemDescriptionsTextOffset=389
+ItemNamesTextOffset=390
+StarterScreenTextOffset=359
+PokedexSpeciesTextOffset=701
+StarterLocationTextOffset=461
+IngameTradesTextOffset=369
+InGameTrades=resource/kor/pokemon_trade/fld_trade.narc
+
+[HeartGold (J)]
+Game=IPKJ
+Type=HGSS
+CopyFrom=IPKE
+HiddenItemTableOffset=0xF9D08
+MoveTutorMovesOffset=0x23954
+HasExtraPokemonNames=No
+PokemonNamesTextOffset=232
+TrainerNamesTextOffset=719
+TrainerClassesTextOffset=720
+MoveDescriptionsTextOffset=738
+MoveNamesTextOffset=739
+AbilityNamesTextOffset=711
+ItemDescriptionsTextOffset=218
+ItemNamesTextOffset=219
+StarterScreenTextOffset=188
+IngameTradesTextOffset=198
+
+[SoulSilver (J)]
+Game=IPGJ
+Type=HGSS
+CopyFrom=IPGE
+HiddenItemTableOffset=0xF9D08
+MoveTutorMovesOffset=0x23954
+HasExtraPokemonNames=No
+PokemonNamesTextOffset=232
+TrainerNamesTextOffset=719
+TrainerClassesTextOffset=720
+MoveDescriptionsTextOffset=738
+MoveNamesTextOffset=739
+AbilityNamesTextOffset=711
+ItemDescriptionsTextOffset=218
+ItemNamesTextOffset=219
+StarterScreenTextOffset=188
+IngameTradesTextOffset=198
+
+[HeartGold (K)]
+Game=IPKK
+Type=HGSS
+CopyFrom=IPKE
+HasExtraPokemonNames=No
+HiddenItemTableOffset=0xFAC04
+PokemonNamesTextOffset=233
+TrainerNamesTextOffset=723
+TrainerClassesTextOffset=724
+MoveDescriptionsTextOffset=742
+MoveNamesTextOffset=743
+AbilityNamesTextOffset=715
+ItemDescriptionsTextOffset=219
+ItemNamesTextOffset=220
+StarterScreenTextOffset=189
+IngameTradesTextOffset=199
+
+[SoulSilver (K)]
+Game=IPGK
+Type=HGSS
+CopyFrom=IPGE
+HasExtraPokemonNames=No
+HiddenItemTableOffset=0xFABFC
+PokemonNamesTextOffset=233
+TrainerNamesTextOffset=723
+TrainerClassesTextOffset=724
+MoveDescriptionsTextOffset=742
+MoveNamesTextOffset=743
+AbilityNamesTextOffset=715
+ItemDescriptionsTextOffset=219
+ItemNamesTextOffset=220
+StarterScreenTextOffset=189
+IngameTradesTextOffset=199
+
+[HeartGold (F)]
+Game=IPKF
+Type=HGSS
+CopyFrom=IPKE
+HiddenItemTableOffset=0xFA53C
+
+[SoulSilver (F)]
+Game=IPGF
+Type=HGSS
+CopyFrom=IPGE
+HiddenItemTableOffset=0xFA53C
+
+[HeartGold (G)]
+Game=IPKD
+Type=HGSS
+CopyFrom=IPKE
+HiddenItemTableOffset=0xFA50C
+
+[SoulSilver (G)]
+Game=IPGD
+Type=HGSS
+CopyFrom=IPGE
+HiddenItemTableOffset=0xFA50C
+
+[HeartGold (S)]
+Game=IPKS
+Type=HGSS
+CopyFrom=IPKE
+HiddenItemTableOffset=0xFA540
+
+[SoulSilver (S)]
+Game=IPGS
+Type=HGSS
+CopyFrom=IPGE
+HiddenItemTableOffset=0xFA548
+
+[HeartGold (I)]
+Game=IPKI
+Type=HGSS
+CopyFrom=IPKE
+HiddenItemTableOffset=0xFA4D0
+
+[SoulSilver (I)]
+Game=IPGI
+Type=HGSS
+CopyFrom=IPGE
+HiddenItemTableOffset=0xFA4D0
\ No newline at end of file
diff --git a/src/com/dabomstew/pkrandom/config/gen5_offsets.ini b/src/com/dabomstew/pkrandom/config/gen5_offsets.ini
new file mode 100755
index 000000000..d74f20c39
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/config/gen5_offsets.ini
@@ -0,0 +1,334 @@
+[Black (U)]
+Game=IRBO
+Type=BW1
+PokemonStats=a/0/1/6
+PokemonMovesets=a/0/1/8
+PokemonEvolutions=a/0/1/9
+BabyPokemon=a/0/2/0
+TrainerData=a/0/9/2
+TrainerPokemon=a/0/9/3
+MoveData=a/0/2/1
+WildPokemon=a/1/2/6
+Scripts=a/0/5/7
+InGameTrades=a/1/6/5
+TradesUnused=[1,3,7,8,9,10,11,12]
+StarterOffsets1=[782:639, 782:644, 782:0x361, 782:0x5FD, 304:0xF9, 304:0x19C]
+StarterOffsets2=[782:687, 782:692, 782:0x356, 782:0x5F2, 304:0x11C, 304:0x1C4]
+StarterOffsets3=[782:716, 782:721, 782:0x338, 782:0x5D4, 304:0x12C, 304:0x1D9]
+PokedexGivenFileOffset=792
+StarterGraphics=a/2/0/5
+PokemonGraphics=a/0/0/4
+TextStrings=a/0/0/2
+TextStory=a/0/0/3
+PokemonNamesTextOffset=70
+TrainerNamesTextOffset=190
+TrainerClassesTextOffset=191
+TrainerMugshotsTextOffset=176
+MoveDescriptionsTextOffset=202
+MoveNamesTextOffset=203
+AbilityNamesTextOffset=182
+ItemDescriptionsTextOffset=53
+ItemNamesTextOffset=54
+StarterLocationTextOffset=430
+IngameTradesTextOffset=35
+ItemBallsScriptOffset=864
+HiddenItemsScriptOffset=865
+ItemBallsSkip=[]
+HiddenItemsSkip=[]
+StaticPokemonSupport=1
+StaticPokemon[]=[304:0x121, 304:0x1C9, 304:0x299] // Grass Monkey
+StaticPokemon[]=[304:0x131, 304:0x1DE, 304:0x2B7] // Fire Monkey
+StaticPokemon[]=[304:0xFE, 304:0x1A1, 304:0x268] // Water Monkey
+StaticPokemon[]=[526:0x758] // Magikarp
+StaticPokemon[]=[94:0x810, 94:0x64, 94:0xB4, 94:0x44B, 94:0x7AB, 94:0x7D0, 94:0x7DC] // Zorua
+StaticPokemon[]=[776:0x85, 776:0xB2] // Larvesta
+StaticPokemon[]=[316:0x369] // Darmanitan 1
+StaticPokemon[]=[316:0x437] // Darmanitan 2
+StaticPokemon[]=[316:0x505] // Darmanitan 3
+StaticPokemon[]=[316:0x5D3] // Darmanitan 4
+StaticPokemon[]=[316:0x6A1] // Darmanitan 5
+StaticPokemon[]=[306:0x65, 306:0x8F] // Musharna
+StaticPokemon[]=[770:0x2F8, 770:0x353] // Zoroark
+StaticPokemon[]=[364:0xE, 364:0x1F] // Volcarona
+StaticPokemon[]=[474:0x1CE, 474:0x20A] // Victini
+StaticPokemon[]=[426:0x133, 426:0x15B, 556:0x1841, 556:0xCFC, 556:0x1878, 556:0x18EA] // Reshiram
+StaticPokemon[]=[426:0x127, 426:0x174, 556:0x184D, 556:0x186C, 556:0xD15, 556:0x18DE] // Zekrom
+StaticPokemon[]=[670:0x415, 670:0x426, 692:0x1E2] // Cobalion
+StaticPokemon[]=[458:0x10, 458:0x21, 692:0x203] // Terrakion
+StaticPokemon[]=[312:0x10, 312:0x21, 692:0x224] // Virizion
+StaticPokemon[]=[752:0x66D, 752:0x6CC, 752:0x6DD] // Landorus
+StaticPokemon[]=[464:0x10, 468:0x4F, 468:0x60] // Kyurem
+
+[White (U)]
+Game=IRAO
+Type=BW1
+CopyStaticPokemon=1
+CopyFrom=IRBO
+TradesUnused=[0,2,7,8,9,10,11,12]
+
+[Black 2 (U)]
+Game=IREO
+Type=BW2
+CopyFrom=IRBO
+TrainerData=a/0/9/1
+TrainerPokemon=a/0/9/2
+DriftveilPokemon=a/2/5/0
+WildPokemon=a/1/2/7
+HiddenHollows=a/2/7/3
+HabitatList=a/2/9/6
+PokemonAreaData=a/1/7/6
+Scripts=a/0/5/6
+InGameTrades=a/1/6/3
+TradesUnused=[25]
+StarterOffsets1=[854:0x58B, 854:0x590, 854:0x595]
+StarterOffsets2=[854:0x5C0, 854:0x5C5, 854:0x5CA]
+StarterOffsets3=[854:0x5E2, 854:0x5E7, 854:0x5EC]
+PokedexGivenFileOffset=854
+StarterGraphics=a/2/0/2
+PokemonGraphics=a/0/0/4
+MoveTutorOvlNumber=36
+MoveTutorDataOffset=0x51538
+PokemonNamesTextOffset=90
+TrainerNamesTextOffset=382
+TrainerClassesTextOffset=383
+TrainerMugshotsTextOffset=368
+MoveDescriptionsTextOffset=402
+MoveNamesTextOffset=403
+AbilityNamesTextOffset=374
+ItemDescriptionsTextOffset=63
+ItemNamesTextOffset=64
+StarterLocationTextOffset=169
+IngameTradesTextOffset=37
+ItemBallsScriptOffset=1240
+HiddenItemsScriptOffset=1241
+ItemBallsSkip=[]
+HiddenItemsSkip=[]
+StaticPokemonSupport=1
+StaticPokemon[]=[662:0x1DE, 662:0x240, 740:0xCD, 740:0xFC, 740:0x12C, 740:0x14C] // Cobalion
+StaticPokemon[]=[730:0x13A, 730:0x15F, 730:0x19B, 730:0x1BB] // Virizion
+StaticPokemon[]=[948:0x45D, 948:0x48D, 948:0x4AD] // Terrakion
+StaticPokemon[]=[426:0x38A, 426:0x39B, 556:0x367, 556:0x568, 556:0x5E6, 556:0x6E1, 1208:0x3A4, 1208:0xA6A, 1208:0x717] // Reshiram
+StaticPokemon[]=[426:0x36B, 426:0x37C, 556:0x350, 556:0x551, 556:0x5C7, 556:0x6C3, 1208:0x38D, 1208:0xA53, 1208:0x706] // Zekrom
+StaticPokemon[]=[1112:0x133, 1122:0x2BA, 1122:0x311, 1128:0x37A, 1128:0x3D1, 1208:0x1B7, 1208:0x1F8, 1208:0xD8B, 1208:0xD97, 1208:0xDB6, 1208:0xDC2, 1208:0x723, 1208:0xF3D, 1208:0xF4E] // Kyurem
+StaticPokemon[]=[304:0xCC, 304:0x14B, 304:0x1BC, 304:0x237, 304:0x327, 304:0x3E6, 304:0x4A1, 304:0x54A, 304:0x5BD, 304:0x5CE] // Latias
+StaticPokemon[]=[304:0xB5, 304:0x134, 304:0x1A5, 304:0x220, 304:0x310, 304:0x3CF, 304:0x48A, 304:0x533, 304:0x59E, 304:0x5AF] // Latios
+StaticPokemon[]=[32:0x247, 32:0x2B0, 32:0x2C1, 1034:0x12A] // Uxie
+StaticPokemon[]=[684:0x136, 684:0x1C2, 684:0x1D3, 1034:0x169] // Mesprit
+StaticPokemon[]=[950:0xA1, 950:0x10A, 950:0x11B, 1034:0x1BE] // Azelf
+StaticPokemon[]=[1222:0x134, 1222:0x145, 1018:0x32] // Regirock
+StaticPokemon[]=[1224:0x134, 1224:0x145, 1018:0x2C] // Regice
+StaticPokemon[]=[1226:0x134, 1226:0x145, 1018:0x38] // Registeel
+StaticPokemon[]=[1018:0x97, 1018:0xA8] // Regigigas
+StaticPokemon[]=[526:0x48D, 526:0x512, 526:0x523] // Cresselia
+StaticPokemon[]=[1068:0x193, 1068:0x1D6, 1068:0x1E7, 1080:0x193, 1080:0x1D6, 1080:0x1E7] // Heatran
+StaticPokemon[]=[652:0x5C6, 652:0x5E9] // Mandibuzz
+StaticPokemon[]=[1102:0x592, 1102:0x5B5] // Braviary
+StaticPokemon[]=[364:0xE, 364:0x32, 364:0x40] // Volcarona
+StaticPokemon[]=[1030:0x290, 1030:0x2A1] // Crustle
+StaticPokemon[]=[480:0xE1, 480:0x10A, 480:0x131, 480:0x15A] // Jellicent
+StaticPokemon[]=[1168:0x2C, 1168:0x4F] // Shiny Haxorus
+StaticPokemon[]=[988:0x382] // Eevee
+StaticPokemon[]=[664:0x3B5, 664:0x3E2, 664:0x40F, 664:0x43C] // Deerling
+StaticPokemon[]=[880:0xAB4, 880:0xAC7] // Shiny Gible
+StaticPokemon[]=[880:0xAD3, 880:0xAE6] // Shiny Dratini
+StaticPokemon[]=[54:0xDD] // Happiny Egg
+StaticPokemon[]=[526:0x27E] // Magikarp
+StaticPokemonFormValues=[1208:0xD8D, 1208:0xD9B, 1208:0xDB8, 1208:0xDC6, 664:0x3B7, 664:0x3E4, 664:0x411, 664:0x43E] // Kyurem, Deerling
+
+[White 2 (U)]
+Game=IRDO
+Type=BW2
+CopyStaticPokemon=1
+CopyFrom=IREO
+MoveTutorDataOffset=0x5152C
+TradesUnused=[24]
+
+[Black (F)]
+Game=IRBF
+Type=BW1
+CopyStaticPokemon=1
+CopyFrom=IRBO
+
+[White (F)]
+Game=IRAF
+Type=BW1
+CopyStaticPokemon=1
+CopyFrom=IRAO
+
+[Black (G)]
+Game=IRBD
+Type=BW1
+CopyStaticPokemon=1
+CopyFrom=IRBO
+
+[White (G)]
+Game=IRAD
+Type=BW1
+CopyStaticPokemon=1
+CopyFrom=IRAO
+
+[Black (S)]
+Game=IRBS
+Type=BW1
+CopyStaticPokemon=1
+CopyFrom=IRBO
+
+[White (S)]
+Game=IRAS
+Type=BW1
+CopyStaticPokemon=1
+CopyFrom=IRAO
+
+[Black (I)]
+Game=IRBI
+Type=BW1
+CopyStaticPokemon=1
+CopyFrom=IRBO
+
+[White (I)]
+Game=IRAI
+Type=BW1
+CopyStaticPokemon=1
+CopyFrom=IRAO
+
+[Black (J)]
+Game=IRBJ
+Type=BW1
+CopyStaticPokemon=1
+CopyFrom=IRBO
+MoveDescriptionsTextOffset=203
+MoveNamesTextOffset=204
+
+[White (J)]
+Game=IRAJ
+Type=BW1
+CopyStaticPokemon=1
+CopyFrom=IRAO
+MoveDescriptionsTextOffset=203
+MoveNamesTextOffset=204
+
+[Black (K)]
+Game=IRBK
+Type=BW1
+CopyStaticPokemon=1
+CopyFrom=IRBO
+
+[White (K)]
+Game=IRAK
+Type=BW1
+CopyStaticPokemon=1
+CopyFrom=IRAO
+
+[Black 2 (F)]
+Game=IREF
+Type=BW2
+CopyStaticPokemon=1
+CopyFrom=IREO
+MoveTutorDataOffset=0x5152C
+
+[White 2 (F)]
+Game=IRDF
+Type=BW2
+CopyStaticPokemon=1
+CopyFrom=IRDO
+MoveTutorDataOffset=0x51520
+
+[Black 2 (G)]
+Game=IRED
+Type=BW2
+CopyStaticPokemon=1
+CopyFrom=IREO
+MoveTutorDataOffset=0x5155C
+
+[White 2 (G)]
+Game=IRDD
+Type=BW2
+CopyStaticPokemon=1
+CopyFrom=IRDO
+MoveTutorDataOffset=0x51550
+
+[Black 2 (I)]
+Game=IREI
+Type=BW2
+CopyStaticPokemon=1
+CopyFrom=IREO
+MoveTutorDataOffset=0x51554
+
+[White 2 (I)]
+Game=IRDI
+Type=BW2
+CopyStaticPokemon=1
+CopyFrom=IRDO
+MoveTutorDataOffset=0x51548
+
+[Black 2 (S)]
+Game=IRES
+Type=BW2
+CopyStaticPokemon=1
+CopyFrom=IREO
+MoveTutorDataOffset=0x5153C
+
+[White 2 (S)]
+Game=IRDS
+Type=BW2
+CopyStaticPokemon=1
+CopyFrom=IRDO
+MoveTutorDataOffset=0x51530
+
+[Black 2 (J)]
+Game=IREJ
+Type=BW2
+CopyFrom=IREO
+MoveTutorDataOffset=0x512DC
+StaticPokemonSupport=1
+StaticPokemon[]=[662:0x1DE, 662:0x240, 740:0xCD, 740:0xFC, 740:0x12C, 740:0x14C] // Cobalion
+StaticPokemon[]=[730:0x13A, 730:0x15F, 730:0x19B, 730:0x1BB] // Virizion
+StaticPokemon[]=[948:0x45D, 948:0x48D, 948:0x4AD] // Terrakion
+StaticPokemon[]=[426:0x38A, 426:0x39B, 556:0x367, 556:0x568, 556:0x5E6, 556:0x6E1, 1208:0x3A4, 1208:0xA6A, 1208:0x717] // Reshiram
+StaticPokemon[]=[426:0x36B, 426:0x37C, 556:0x350, 556:0x551, 556:0x5C7, 556:0x6C3, 1208:0x38D, 1208:0xA53, 1208:0x706] // Zekrom
+StaticPokemon[]=[1112:0x133, 1122:0x2BA, 1122:0x311, 1128:0x37A, 1128:0x3D1, 1208:0x1B7, 1208:0x1F8, 1208:0xD8B, 1208:0xD97, 1208:0xDB6, 1208:0xDC2, 1208:0x723, 1208:0xF3D, 1208:0xF4E] // Kyurem
+StaticPokemon[]=[304:0xCC, 304:0x14B, 304:0x1B8, 304:0x22F, 304:0x31B, 304:0x3D6, 304:0x491, 304:0x536, 304:0x5A9, 304:0x5BA] // Latias
+StaticPokemon[]=[304:0xB5, 304:0x134, 304:0x1A1, 304:0x218, 304:0x304, 304:0x3BF, 304:0x47A, 304:0x51F, 304:0x58A, 304:0x59B] // Latios
+StaticPokemon[]=[32:0x247, 32:0x2B0, 32:0x2C1, 1034:0x12A] // Uxie
+StaticPokemon[]=[684:0x136, 684:0x1C2, 684:0x1D3, 1034:0x169] // Mesprit
+StaticPokemon[]=[950:0xA1, 950:0x10A, 950:0x11B, 1034:0x1BE] // Azelf
+StaticPokemon[]=[1222:0x134, 1222:0x145, 1018:0x32] // Regirock
+StaticPokemon[]=[1224:0x134, 1224:0x145, 1018:0x2C] // Regice
+StaticPokemon[]=[1226:0x134, 1226:0x145, 1018:0x38] // Registeel
+StaticPokemon[]=[1018:0x97, 1018:0xA8] // Regigigas
+StaticPokemon[]=[526:0x48D, 526:0x512, 526:0x523] // Cresselia
+StaticPokemon[]=[1068:0x171, 1068:0x1B4, 1068:0x1C5, 1080:0x171, 1080:0x1B4, 1080:0x1C5] // Heatran
+StaticPokemon[]=[652:0x5C6, 652:0x5E9] // Mandibuzz
+StaticPokemon[]=[1102:0x592, 1102:0x5B5] // Braviary
+StaticPokemon[]=[364:0xE, 364:0x32, 364:0x40] // Volcarona
+StaticPokemon[]=[1030:0x290, 1030:0x2A1] // Crustle
+StaticPokemon[]=[480:0xE1, 480:0x10A, 480:0x131, 480:0x15A] // Jellicent
+StaticPokemon[]=[1168:0x2C, 1168:0x4F] // Shiny Haxorus
+StaticPokemon[]=[988:0x382] // Eevee
+StaticPokemon[]=[664:0x3B5, 664:0x3E2, 664:0x40F, 664:0x43C] // Deerling
+StaticPokemon[]=[880:0xAB4, 880:0xAC7] // Shiny Gible
+StaticPokemon[]=[880:0xAD3, 880:0xAE6] // Shiny Dratini
+StaticPokemon[]=[54:0xDD] // Happiny Egg
+StaticPokemon[]=[526:0x27E] // Magikarp
+StaticPokemonFormValues=[1208:0xD8D, 1208:0xD9B, 1208:0xDB8, 1208:0xDC6, 664:0x3B7, 664:0x3E4, 664:0x411, 664:0x43E] // Kyurem, Deerling
+
+[White 2 (J)]
+Game=IRDJ
+Type=BW2
+CopyStaticPokemon=1
+CopyFrom=IREJ
+MoveTutorDataOffset=0x512D0
+
+[Black 2 (K)]
+Game=IREK
+Type=BW2
+CopyStaticPokemon=1
+CopyFrom=IREO
+MoveTutorDataOffset=0x5160C
+
+[White 2 (K)]
+Game=IRDK
+Type=BW2
+CopyStaticPokemon=1
+CopyFrom=IRDO
+MoveTutorDataOffset=0x51600
\ No newline at end of file
diff --git a/src/com/dabomstew/pkrandom/config/green_translation.tbl b/src/com/dabomstew/pkrandom/config/green_translation.tbl
new file mode 100755
index 000000000..e01baf04d
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/config/green_translation.tbl
@@ -0,0 +1,66 @@
+7F=
+87='
+8D=-
+90=0
+91=1
+92=2
+93=3
+94=4
+95=5
+96=6
+97=7
+98=8
+99=9
+9F=?
+A1=A
+A2=B
+A3=C
+A4=D
+A5=E
+A6=F
+A7=G
+A8=H
+A9=I
+AA=J
+AB=K
+AC=L
+AD=M
+AE=N
+AF=O
+B0=P
+B1=Q
+B2=R
+B3=S
+B4=T
+B5=U
+B6=V
+B7=W
+B8=X
+B9=Y
+BA=Z
+C1=a
+C2=b
+C3=c
+C4=d
+C5=e
+C6=f
+C7=g
+C8=h
+C9=i
+CA=j
+CB=k
+CC=l
+CD=m
+CE=n
+CF=o
+D0=p
+D1=q
+D2=r
+D3=s
+D4=t
+D5=u
+D6=v
+D7=w
+D8=x
+D9=y
+DA=z
\ No newline at end of file
diff --git a/src/com/dabomstew/pkrandom/config/gsc_english.tbl b/src/com/dabomstew/pkrandom/config/gsc_english.tbl
new file mode 100755
index 000000000..ac7cd6e9a
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/config/gsc_english.tbl
@@ -0,0 +1,96 @@
+4A=[pk]
+54=[POKé]
+58=$
+74=â„–
+75=…
+7F=
+79=┌
+7A=─
+7B=â”
+7C=│
+7D=â””
+7E=┘
+80=A
+81=B
+82=C
+83=D
+84=E
+85=F
+86=G
+87=H
+88=I
+89=J
+8A=K
+8B=L
+8C=M
+8D=N
+8E=O
+8F=P
+90=Q
+91=R
+92=S
+93=T
+94=U
+95=V
+96=W
+97=X
+98=Y
+99=Z
+9A=(
+9B=)
+9C=:
+9D=;
+9E=[
+9F=]
+A0=a
+A1=b
+A2=c
+A3=d
+A4=e
+A5=f
+A6=g
+A7=h
+A8=i
+A9=j
+AA=k
+AB=l
+AC=m
+AD=n
+AE=o
+AF=p
+B0=q
+B1=r
+B2=s
+B3=t
+B4=u
+B5=v
+B6=w
+B7=x
+B8=y
+B9=z
+C0=Ä
+C1=Ö
+C2=Ü
+C3=ä
+C4=ö
+C5=ü
+D0='d
+D1='l
+D2='m
+D3='r
+D4='s
+D5='t
+D6='v
+E0='
+E1=[PK]
+E2=[MN]
+E3=-
+E6=?
+E7=!
+E8=.
+E9=&
+EA=é
+EB=→
+F0=$
+F2=[.]
+F4=,
\ No newline at end of file
diff --git a/src/com/dabomstew/pkrandom/config/gsc_espita.tbl b/src/com/dabomstew/pkrandom/config/gsc_espita.tbl
new file mode 100755
index 000000000..adb453731
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/config/gsc_espita.tbl
@@ -0,0 +1,122 @@
+4A=[pk]
+54=[POKé]
+58=$
+74=â„–
+75=…
+7F=
+79=┌
+7A=─
+7B=â”
+7C=│
+7D=â””
+7E=┘
+80=A
+81=B
+82=C
+83=D
+84=E
+85=F
+86=G
+87=H
+88=I
+89=J
+8A=K
+8B=L
+8C=M
+8D=N
+8E=O
+8F=P
+90=Q
+91=R
+92=S
+93=T
+94=U
+95=V
+96=W
+97=X
+98=Y
+99=Z
+9A=(
+9B=)
+9C=:
+9D=;
+9E=[
+9F=]
+A0=a
+A1=b
+A2=c
+A3=d
+A4=e
+A5=f
+A6=g
+A7=h
+A8=i
+A9=j
+AA=k
+AB=l
+AC=m
+AD=n
+AE=o
+AF=p
+B0=q
+B1=r
+B2=s
+B3=t
+B4=u
+B5=v
+B6=w
+B7=x
+B8=y
+B9=z
+BA=Ã
+BB=è
+BC=é
+BD=ù
+BE=À
+BF=Ã
+C0=Ä
+C1=Ö
+C2=Ü
+C3=ä
+C4=ö
+C5=ü
+C6=È
+C7=É
+C8=Ì
+C9=Ã
+CA=Ñ
+CB=Ã’
+CC=Ó
+CD=Ù
+CE=Ú
+CF=á
+D0=ì
+D1=Ã
+D2=ñ
+D3=ò
+D4=ó
+D5=ú
+D6=°
+D7=&
+D8='d
+D9='l
+DA='m
+DB='r
+DC='s
+DD='t
+DE='v
+E0='
+E1=[PK]
+E2=[MN]
+E3=-
+E4=¿
+E5=¡
+E6=?
+E7=!
+E8=.
+E9=&
+EA=é
+EB=→
+F0=$
+F2=[.]
+F4=,
\ No newline at end of file
diff --git a/src/com/dabomstew/pkrandom/config/gsc_freger.tbl b/src/com/dabomstew/pkrandom/config/gsc_freger.tbl
new file mode 100755
index 000000000..7e481b3fa
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/config/gsc_freger.tbl
@@ -0,0 +1,115 @@
+4A=[pk]
+54=[POKé]
+58=$
+74=â„–
+75=…
+7F=
+79=┌
+7A=─
+7B=â”
+7C=│
+7D=â””
+7E=┘
+80=A
+81=B
+82=C
+83=D
+84=E
+85=F
+86=G
+87=H
+88=I
+89=J
+8A=K
+8B=L
+8C=M
+8D=N
+8E=O
+8F=P
+90=Q
+91=R
+92=S
+93=T
+94=U
+95=V
+96=W
+97=X
+98=Y
+99=Z
+9A=(
+9B=)
+9C=:
+9D=;
+9E=[
+9F=]
+A0=a
+A1=b
+A2=c
+A3=d
+A4=e
+A5=f
+A6=g
+A7=h
+A8=i
+A9=j
+AA=k
+AB=l
+AC=m
+AD=n
+AE=o
+AF=p
+B0=q
+B1=r
+B2=s
+B3=t
+B4=u
+B5=v
+B6=w
+B7=x
+B8=y
+B9=z
+BA=Ã
+BB=è
+BC=é
+BD=ù
+BE=ß
+BF=ç
+C0=Ä
+C1=Ö
+C2=Ü
+C3=ä
+C4=ö
+C5=ü
+C6=ë
+C7=ï
+C8=â
+C9=ô
+CA=û
+CB=ê
+CC=î
+D4=c'
+D5=d'
+D6=j'
+D7=l'
+D8=m'
+D9=n'
+DA=p'
+DB=s'
+DC='s
+DD=t'
+DE=u'
+DF=y'
+E0='
+E1=[PK]
+E2=[MN]
+E3=-
+E4=+
+E6=?
+E7=!
+E8=.
+E9=&
+EA=é
+EB=→
+F0=$
+F2=[.]
+F4=,
\ No newline at end of file
diff --git a/src/com/dabomstew/pkrandom/config/nicknames.txt b/src/com/dabomstew/pkrandom/config/nicknames.txt
new file mode 100755
index 000000000..e9cd587d1
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/config/nicknames.txt
@@ -0,0 +1,20 @@
+Red
+Blue
+Yellow
+Cuddles
+Angry
+Scout
+Buster
+Rusty
+Shadow
+Gizmo
+Chester
+Sylvester
+Merlin
+Smokey
+Angel
+Midnight
+Willow
+Baxter
+Cookie
+Callie
\ No newline at end of file
diff --git a/src/com/dabomstew/pkrandom/config/rby_english.tbl b/src/com/dabomstew/pkrandom/config/rby_english.tbl
new file mode 100755
index 000000000..9ec4cbe62
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/config/rby_english.tbl
@@ -0,0 +1,88 @@
+4A=[pk]
+54=[POKé]
+58=$
+74=â„–
+75=…
+7F=
+79=┌
+7A=─
+7B=â”
+7C=│
+7D=â””
+7E=┘
+80=A
+81=B
+82=C
+83=D
+84=E
+85=F
+86=G
+87=H
+88=I
+89=J
+8A=K
+8B=L
+8C=M
+8D=N
+8E=O
+8F=P
+90=Q
+91=R
+92=S
+93=T
+94=U
+95=V
+96=W
+97=X
+98=Y
+99=Z
+9A=(
+9B=)
+9C=:
+9D=;
+9E=[
+9F=]
+A0=a
+A1=b
+A2=c
+A3=d
+A4=e
+A5=f
+A6=g
+A7=h
+A8=i
+A9=j
+AA=k
+AB=l
+AC=m
+AD=n
+AE=o
+AF=p
+B0=q
+B1=r
+B2=s
+B3=t
+B4=u
+B5=v
+B6=w
+B7=x
+B8=y
+B9=z
+BA=é
+BB='d
+BC='l
+BD='s
+BE='t
+BF='v
+E0='
+E1=[PK]
+E2=[MN]
+E3=-
+E4='r
+E5='m
+E6=?
+E7=!
+E8=.
+F0=$
+F2=[.]
+F4=,
\ No newline at end of file
diff --git a/src/com/dabomstew/pkrandom/config/rby_espita.tbl b/src/com/dabomstew/pkrandom/config/rby_espita.tbl
new file mode 100755
index 000000000..405b0badd
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/config/rby_espita.tbl
@@ -0,0 +1,119 @@
+4A=[pk]
+54=[POKé]
+58=$
+74=â„–
+75=…
+7F=
+79=┌
+7A=─
+7B=â”
+7C=│
+7D=â””
+7E=┘
+80=A
+81=B
+82=C
+83=D
+84=E
+85=F
+86=G
+87=H
+88=I
+89=J
+8A=K
+8B=L
+8C=M
+8D=N
+8E=O
+8F=P
+90=Q
+91=R
+92=S
+93=T
+94=U
+95=V
+96=W
+97=X
+98=Y
+99=Z
+9A=(
+9B=)
+9C=:
+9D=;
+9E=[
+9F=]
+A0=a
+A1=b
+A2=c
+A3=d
+A4=e
+A5=f
+A6=g
+A7=h
+A8=i
+A9=j
+AA=k
+AB=l
+AC=m
+AD=n
+AE=o
+AF=p
+B0=q
+B1=r
+B2=s
+B3=t
+B4=u
+B5=v
+B6=w
+B7=x
+B8=y
+B9=z
+BA=Ã
+BB=è
+BC=é
+BD=ù
+BE=À
+BF=Ã
+C0=Ä
+C1=Ö
+C2=Ü
+C3=ä
+C4=ö
+C5=ü
+C6=È
+C7=É
+C8=Ì
+C9=Ã
+CA=Ñ
+CB=Ã’
+CC=Ó
+CD=Ù
+CE=Ú
+CF=á
+D0=ì
+D1=Ã
+D2=ñ
+D3=ò
+D4=ó
+D5=ú
+D6=°
+D7=&
+D8='d
+D9='l
+DA='m
+DB='r
+DC='s
+DD='t
+DE='v
+E0='
+E1=[PK]
+E2=[MN]
+E3=-
+E4=¿
+E5=¡
+E6=?
+E7=!
+E8=.
+F0=$
+F2=[.]
+F4=,
\ No newline at end of file
diff --git a/src/com/dabomstew/pkrandom/config/rby_freger.tbl b/src/com/dabomstew/pkrandom/config/rby_freger.tbl
new file mode 100755
index 000000000..382993127
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/config/rby_freger.tbl
@@ -0,0 +1,112 @@
+4A=[pk]
+54=[POKé]
+58=$
+74=â„–
+75=…
+7F=
+79=┌
+7A=─
+7B=â”
+7C=│
+7D=â””
+7E=┘
+80=A
+81=B
+82=C
+83=D
+84=E
+85=F
+86=G
+87=H
+88=I
+89=J
+8A=K
+8B=L
+8C=M
+8D=N
+8E=O
+8F=P
+90=Q
+91=R
+92=S
+93=T
+94=U
+95=V
+96=W
+97=X
+98=Y
+99=Z
+9A=(
+9B=)
+9C=:
+9D=;
+9E=[
+9F=]
+A0=a
+A1=b
+A2=c
+A3=d
+A4=e
+A5=f
+A6=g
+A7=h
+A8=i
+A9=j
+AA=k
+AB=l
+AC=m
+AD=n
+AE=o
+AF=p
+B0=q
+B1=r
+B2=s
+B3=t
+B4=u
+B5=v
+B6=w
+B7=x
+B8=y
+B9=z
+BA=Ã
+BB=è
+BC=é
+BD=ù
+BE=ß
+BF=ç
+C0=Ä
+C1=Ö
+C2=Ü
+C3=ä
+C4=ö
+C5=ü
+C6=ë
+C7=ï
+C8=â
+C9=ô
+CA=û
+CB=ê
+CC=î
+D4=c'
+D5=d'
+D6=j'
+D7=l'
+D8=m'
+D9=n'
+DA=p'
+DB=s'
+DC='s
+DD=t'
+DE=u'
+DF=y'
+E0='
+E1=[PK]
+E2=[MN]
+E3=-
+E4=+
+E6=?
+E7=!
+E8=.
+F0=$
+F2=[.]
+F4=,
\ No newline at end of file
diff --git a/src/com/dabomstew/pkrandom/config/trainerclasses.txt b/src/com/dabomstew/pkrandom/config/trainerclasses.txt
new file mode 100755
index 000000000..fcebb2794
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/config/trainerclasses.txt
@@ -0,0 +1,83 @@
+Cop
+Man
+God
+Fan
+Chef
+Poet
+Lazy
+Lady
+Gent
+Boss
+Biker
+Chief
+Clerk
+Nurse
+Tamer
+Doctor
+Leader
+Artist
+Rocker
+Dancer
+Writer
+Author
+Scribe
+Fisher
+Sailor
+Ranger
+Servant
+Trainer
+Cyclist
+Gymnast
+Artisan
+Analyst
+Juggler
+Breeder
+Swimmer
+Manager
+Operator
+Designer
+Director
+Botanist
+Engineer
+Champion
+Rich Kid
+Rich Boy
+Rich Girl
+Performer
+Developer
+Gentleman
+Schoolboy
+Swimmer ♂
+Swimmer ♀
+Technician
+Schoolgirl
+Elite Four
+Strong Man
+Ghostwriter
+Preschooler
+Ace Trainer
+Bug Catcher
+Entrepreneur
+Weightlifter
+Cooltrainer♂
+Cooltrainer♀
+Elitetrainer
+Twins
+Ma&Pa
+Sr&Jr
+Couple
+Ma & Pa
+Sr & Jr
+Bro&Sis
+Ma & Pop
+Mom & Pa
+Mom & Pop
+Sr. & Jr.
+Ma And Pa
+Champions
+Old Couple
+Bro And Sis
+Cute Couple
+Cool Couple
+Young Couple
+Cheerleaders
\ No newline at end of file
diff --git a/src/com/dabomstew/pkrandom/config/trainernames.txt b/src/com/dabomstew/pkrandom/config/trainernames.txt
new file mode 100755
index 000000000..a74d12724
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/config/trainernames.txt
@@ -0,0 +1,84 @@
+Pi
+Jo
+Bob
+Max
+Joe
+Leo
+Ann
+Tia
+Mia
+Kim
+Mike
+Mark
+Alex
+Joey
+Anne
+Zoey
+Jill
+Kate
+Robin
+Wayne
+Scott
+Jimmy
+Chloe
+Donna
+Sonya
+Pansy
+Dudley
+Daniel
+Landon
+Thomas
+Rachel
+Noelle
+Stacey
+Cammie
+Forrest
+Esteban
+Malcolm
+Webster
+Marilyn
+Jasmine
+Jessica
+Crystal
+Jonathan
+Marshall
+Lawrence
+Tristian
+Mallorie
+Kristine
+Veronica
+Scarlett
+Cristiano
+Marcellus
+Lillianna
+Kimberley
+Wellington
+Florentino
+Jacqueline
+Antoinette
+Christopher
+Maximillian
+Max&Joe
+Joe&Max
+Bob&Ann
+Ann&Bob
+Zoe&Kim
+Kim&Zoe
+Ally&Cam
+Cam&Ally
+Emma&May
+May&Emma
+Nick&Stu
+Stu&Nick
+Max & Joe
+Joe & Max
+Bob & Ann
+Ann & Bob
+Zoe & Kim
+Kim & Zoe
+Ally & Cam
+Cam & Ally
+Emma & May
+May & Emma
+Nick & Stu
+Stu & Nick
diff --git a/src/com/dabomstew/pkrandom/config/vietcrystal.tbl b/src/com/dabomstew/pkrandom/config/vietcrystal.tbl
new file mode 100755
index 000000000..71a06ce37
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/config/vietcrystal.tbl
@@ -0,0 +1,54 @@
+7F=
+80=!
+81="
+82=%
+83=&
+84='
+85=(
+86=)
+87=+
+88=,
+89=-
+8A=.
+8B=/
+8C=0
+8D=1
+8E=2
+8F=3
+90=4
+91=5
+92=6
+93=7
+94=8
+95=9
+96=:
+97=;
+98==
+99=>
+9A=?
+9B=A
+9C=B
+9D=C
+9E=D
+9F=E
+A0=F
+A1=G
+A2=H
+A3=I
+A4=J
+A5=K
+A6=L
+A7=M
+A8=N
+A9=O
+AA=P
+AB=Q
+AC=R
+AD=S
+AE=T
+AF=U
+B0=V
+B1=W
+B2=X
+B3=Y
+B4=Z
diff --git a/src/com/dabomstew/pkrandom/gui/AboutDialog.form b/src/com/dabomstew/pkrandom/gui/AboutDialog.form
new file mode 100755
index 000000000..4fbd4cbf8
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/gui/AboutDialog.form
@@ -0,0 +1,117 @@
+
+
+
diff --git a/src/com/dabomstew/pkrandom/gui/AboutDialog.java b/src/com/dabomstew/pkrandom/gui/AboutDialog.java
new file mode 100755
index 000000000..ed26d13e1
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/gui/AboutDialog.java
@@ -0,0 +1,154 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.dabomstew.pkrandom.gui;
+
+/*----------------------------------------------------------------------------*/
+/*-- AboutDialog.java - describes this program! --*/
+/*-- --*/
+/*-- Part of "Universal Pokemon Randomizer" by Dabomstew --*/
+/*-- Pokemon and any associated names and the like are --*/
+/*-- trademark and (C) Nintendo 1996-2012. --*/
+/*-- --*/
+/*-- The custom code written here is licensed under the terms of the GPL: --*/
+/*-- --*/
+/*-- This program is free software: you can redistribute it and/or modify --*/
+/*-- it under the terms of the GNU General Public License as published by --*/
+/*-- the Free Software Foundation, either version 3 of the License, or --*/
+/*-- (at your option) any later version. --*/
+/*-- --*/
+/*-- This program is distributed in the hope that it will be useful, --*/
+/*-- but WITHOUT ANY WARRANTY; without even the implied warranty of --*/
+/*-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --*/
+/*-- GNU General Public License for more details. --*/
+/*-- --*/
+/*-- You should have received a copy of the GNU General Public License --*/
+/*-- along with this program. If not, see . --*/
+/*----------------------------------------------------------------------------*/
+
+import java.awt.Desktop;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+/**
+ *
+ * @author Stewart
+ */
+public class AboutDialog extends javax.swing.JDialog {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -4693681699711757794L;
+ /**
+ * Creates new form AboutDialog
+ */
+ public AboutDialog(java.awt.Frame parent, boolean modal) {
+ super(parent, modal);
+ initComponents();
+ setLocationRelativeTo(parent);
+ }
+
+ /**
+ * This method is called from within the constructor to initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is always
+ * regenerated by the Form Editor.
+ */
+
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ titleLabel = new javax.swing.JLabel();
+ authorLabel = new javax.swing.JLabel();
+ ackLabel = new javax.swing.JLabel();
+ linkLabel = new javax.swing.JLabel();
+ okButton = new javax.swing.JButton();
+
+ setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
+ java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("com/dabomstew/pkrandom/gui/Bundle"); // NOI18N
+ setTitle(bundle.getString("AboutDialog.title")); // NOI18N
+
+ titleLabel.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N
+ titleLabel.setText(bundle.getString("AboutDialog.titleLabel.text")); // NOI18N
+
+ authorLabel.setText(bundle.getString("AboutDialog.authorLabel.text")); // NOI18N
+
+ ackLabel.setText(bundle.getString("AboutDialog.ackLabel.text")); // NOI18N
+
+ linkLabel.setText(bundle.getString("AboutDialog.linkLabel.text")); // NOI18N
+ linkLabel.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
+ linkLabel.addMouseListener(new java.awt.event.MouseAdapter() {
+ public void mouseClicked(java.awt.event.MouseEvent evt) {
+ siteLinkClicked(evt);
+ }
+ });
+
+ okButton.setText(bundle.getString("AboutDialog.okButton.text")); // NOI18N
+ okButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ okButtonActionPerformed(evt);
+ }
+ });
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
+ getContentPane().setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(titleLabel)
+ .addGroup(layout.createSequentialGroup()
+ .addGap(10, 10, 10)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(ackLabel)
+ .addComponent(authorLabel)
+ .addComponent(linkLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))))
+ .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
+ .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(okButton)
+ .addGap(135, 135, 135))
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(titleLabel)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(authorLabel)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(ackLabel)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(linkLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 11, Short.MAX_VALUE)
+ .addComponent(okButton)
+ .addContainerGap())
+ );
+
+ pack();
+ }// //GEN-END:initComponents
+
+ private void siteLinkClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_siteLinkClicked
+ Desktop desktop = java.awt.Desktop.getDesktop();
+ try {
+ desktop.browse(new URI("http://pokehacks.dabomstew.com/randomizer"));
+ } catch (IOException e) {
+ } catch (URISyntaxException e) {
+ }
+ }//GEN-LAST:event_siteLinkClicked
+
+ private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed
+ this.setVisible(false);
+ }//GEN-LAST:event_okButtonActionPerformed
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JLabel ackLabel;
+ private javax.swing.JLabel authorLabel;
+ private javax.swing.JLabel linkLabel;
+ private javax.swing.JButton okButton;
+ private javax.swing.JLabel titleLabel;
+ // End of variables declaration//GEN-END:variables
+}
diff --git a/src/com/dabomstew/pkrandom/gui/Bundle.properties b/src/com/dabomstew/pkrandom/gui/Bundle.properties
new file mode 100755
index 000000000..aeadedc62
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/gui/Bundle.properties
@@ -0,0 +1,280 @@
+# To change this template, choose Tools | Templates
+# and open the template in the editor.
+
+RandomizerGUI.tpPowerLevelsCB.text=Try to use Pokemon with similar strength?
+RandomizerGUI.starterPokemonPanel.border.title=Starter Pokemon
+RandomizerGUI.spCustomRB.toolTipText=Lets you pick the 3 starter pokemon you want to use.
+RandomizerGUI.spCustomRB.text=Custom
+RandomizerGUI.spUnchangedRB.toolTipText=Don't change the starter Pokemon.
+RandomizerGUI.spUnchangedRB.text=Unchanged
+RandomizerGUI.riRomCodeLabel.text=ROM Code
+RandomizerGUI.wpARCatchEmAllRB.toolTipText=If this is turned on, every random Pokemon chosen to replace an encounter will be one that hasn't been chosen before.
This should make sure that every Pokemon is catchable.
Once every Pokemon has been chosen the Pokemon choice list will start again from full.
+RandomizerGUI.wpARCatchEmAllRB.text=Catch Em All Mode
+RandomizerGUI.wpARTypeThemedRB.toolTipText=If this is chosen, every encounter area will have only Pokemon of a random type.
This may lead to a more realistic experience, or an odd one (e.g. if Fire pokemon are chosen to be in Surfing encounters).
+RandomizerGUI.wpARTypeThemedRB.text=Type Theme Areas
+RandomizerGUI.wildPokemonARulePanel.border.title=Additional Rule
+RandomizerGUI.wpARNoneRB.toolTipText=Don't apply any other rules.
+RandomizerGUI.wpARNoneRB.text=None
+RandomizerGUI.spRandom2EvosRB.toolTipText=Picks 3 random starter Pokemon to be used.
These Pokemon must have 2 evolution stages, e.g. be like the starters in the real games.
+RandomizerGUI.spRandom2EvosRB.text=Random (basic Pokemon with 2 evolutions)
+RandomizerGUI.wpUseTimeCB.toolTipText=This affects games that have either seasons or morning/day/night encounter sets.
If this is checked, each of these sets will be treated as a separate "area".
So you will have to visit each place in morning/day/night, or in each season, to collect the Pokemon.
If this isn't checked, all of morning/day/night and all seasons will use the same encounter data.
+RandomizerGUI.wpUseTimeCB.text=Use time-based encounters?
+RandomizerGUI.wpNoLegendariesCB.text=Don't use legendaries?
+RandomizerGUI.tmhmsPanel.border.title=TMs & HMs
+RandomizerGUI.stpRandomTotalRB.toolTipText=Selecting this will replace every static Pokemon encounter, gift or purchase with another random one.
In this particular mode, any Pokemon can replace any other Pokemon, so you could get a Mew in the Game Corner.
Or fight Magikarp instead of Mewtwo...
+RandomizerGUI.stpRandomTotalRB.text=Random (Completely)
+RandomizerGUI.tmmUnchangedRB.toolTipText=Leave the moves in TMs as they are.
If Metronome Only Mode is selected, all TMs are changed to Metronome and this setting has no effect.
+RandomizerGUI.tmmUnchangedRB.text=Unchanged
+RandomizerGUI.tmMovesPanel.border.title=TM Moves
+RandomizerGUI.tmHmCompatPanel.border.title=TM/HM Compatibility
+RandomizerGUI.tmmRandomRB.toolTipText=Give each TM a new move.
HM moves are not affected, nor can they be selected to be put in TMs.
Each TM will still be unique.
If Metronome Only Mode is selected, all TMs are changed to Metronome and this setting has no effect.
+RandomizerGUI.tmmRandomRB.text=Random
+RandomizerGUI.pbsChangesShuffleRB.toolTipText=Shuffle each Pokemon's stats.
For example, its base Attack may be swapped with its base Special Attack, etc.
This does not make any Pokemon stronger or weaker.
+RandomizerGUI.pbsChangesShuffleRB.text=Shuffle
+RandomizerGUI.pbsChangesRandomEvosRB.toolTipText=Randomises each Pokemon's stats, as long as they fall within the original base stat total.
Evolutions of a Pokemon will follow that Pokemon's stat distribution.
This could make Pokemon stronger or weaker if they get unlucky or lucky rolls on stats they need.
+RandomizerGUI.pbsChangesRandomEvosRB.text=Random (follow evolutions)
+RandomizerGUI.riRomSupportLabel.text=Support: XXX
+RandomizerGUI.baseStatsPanel.border.title=Pokemon Base Statistics
+RandomizerGUI.pbsChangesUnchangedRB.toolTipText=Don't change Pokemon stats from the base at all.
+RandomizerGUI.pbsChangesUnchangedRB.text=Unchanged
+RandomizerGUI.spRandomRB.toolTipText=Picks 3 random starter Pokemon to be used.
+RandomizerGUI.spRandomRB.text=Random (completely)
+RandomizerGUI.staticPokemonPanel.border.title=Static Pokemon
+RandomizerGUI.stpUnchangedRB.toolTipText=Static Pokemon remain the same.
+RandomizerGUI.stpUnchangedRB.text=Unchanged
+RandomizerGUI.stpRandomL4LRB.toolTipText=Selecting this will replace every static Pokemon encounter, gift or purchase with another random one.
In this particular mode, legendary pokemon will always be swapped for other legendaries.
Also, normal non-legendary Pokemon will only be swapped for other non-legendaries.
+RandomizerGUI.stpRandomL4LRB.text=Random (Legendary <-> Legendary & Normal <-> Normal)
+RandomizerGUI.romInfoPanel.border.title=ROM Information
+RandomizerGUI.riRomNameLabel.text=ROM Name
+RandomizerGUI.usePresetsButton.text=Premade Seed
+RandomizerGUI.saveROMButton.text=Randomize (Save)
+RandomizerGUI.trainersPokemonPanel.border.title=Trainers Pokemon
+RandomizerGUI.goUpdateMovesCheckBox.toolTipText=If this is checked, moves will be updated to their Gen 6 stats (power, accuracy, etc) where possible.
If you don't like the changes made in Gen6, try the "Legacy" checkbox...
This does NOT add the Fairy type! Moves that were changed to Fairy type will keep their Gen 5 types.
+RandomizerGUI.goUpdateMovesCheckBox.text=Update Moves
+RandomizerGUI.tpUnchangedRB.toolTipText=Don't change Trainers' Pokemon at all.
+RandomizerGUI.tpUnchangedRB.text=Unchanged
+RandomizerGUI.goRemoveTradeEvosCheckBox.toolTipText=If this is checked, every evolution that isn't possible to do without trading in the current game will be changed.
Some of the types that will be changed are:- "Normal" trade evolutions
- Trade evolutions with another condition, such as held item or Pokemon traded for
- Day/night evolutions if there isn't day/night in the game
- Contest-stat evolutions if there aren't contests in the game
- Location-based evolutions, if those locations don't exist in the game
- Move-based evolutions, only if you randomize movesets
+RandomizerGUI.goRemoveTradeEvosCheckBox.text=Change Impossible Evos
+RandomizerGUI.goLowerCaseNamesCheckBox.toolTipText=If this is selected, all Pokemon names will be made into Camel Case.
e.g. VENUSAUR becomes Venusaur.
This looks better in Gen3 games, and OK in Gen1/Gen2 games.
+RandomizerGUI.goLowerCaseNamesCheckBox.text=Lower Case Pokemon Names
+RandomizerGUI.pmsRandomTotalRB.toolTipText=Randomise Pokemon movesets, completely ignoring the type of the move and the Pokemon.
Each Pokemon will get at least one reasonably accurate damaging move to begin with.
+RandomizerGUI.pmsRandomTotalRB.text=Random (completely)
+RandomizerGUI.goNationalDexCheckBox.toolTipText=If this is checked then the National Dex will be given to the player at the start of the game with the regular Pokedex.
This is only available and necessary for Gen 3 games, where in FRLG National Dex Pokemon can't evolve if you don't have it.
+RandomizerGUI.goNationalDexCheckBox.text=Give National Dex at Start
+RandomizerGUI.title=Universal Pokemon Randomizer
+RandomizerGUI.generalOptionsPanel.border.title=General Options
+RandomizerGUI.goUpdateTypesCheckBox.toolTipText=If this is checked, the type weakness/strengths/immunities will be updated to the current set.
For RBY, this means Ghost will be Super Effective against Psychic, among other changes.
+RandomizerGUI.goUpdateTypesCheckBox.text=Update Type Effectiveness
+RandomizerGUI.pmsRandomTypeRB.toolTipText=Randomise Pokemon movesets, preferring moves that are of the type (or one of the types) of the Pokemon.
Each Pokemon will get at least one reasonably accurate damaging move to begin with.
+RandomizerGUI.pmsRandomTypeRB.text=Random (preferring same type)
+RandomizerGUI.pmsUnchangedRB.toolTipText=Don't change Pokemon movesets at all.
+RandomizerGUI.pmsUnchangedRB.text=Unchanged
+RandomizerGUI.pokemonMovesetsPanel.border.title=Pokemon Movesets
+RandomizerGUI.ptRandomTotalRB.toolTipText=Randomise Pokemon types completely.
Evolutions of a Pokemon are completely separate from that Pokemon, so the type of a Pokemon will likely completely change every evolution.
+RandomizerGUI.ptRandomTotalRB.text=Random (completely)
+RandomizerGUI.ptRandomFollowEvosRB.toolTipText=Randomise the types of each Pokemon, but make most evolutions copy the base Pokemon (except perhaps adding an extra secondary type).
Evolutions that don't copy types are the Eeveelutions, among others.
+RandomizerGUI.ptRandomFollowEvosRB.text=Random (follow evolutions)
+RandomizerGUI.ptUnchangedRB.toolTipText=Doesn't change Pokemon types at all.
+RandomizerGUI.ptUnchangedRB.text=Unchanged
+RandomizerGUI.pokemonTypesPanel.border.title=Pokemon Types
+RandomizerGUI.pbsChangesRandomTotalRB.toolTipText=Randomises each Pokemon's stats, as long as they fall within the original base stat total.
Evolutions of a Pokemon will be completely separate from that Pokemon, so evolving a Pokemon will make its stats drastically change.
This could make Pokemon stronger or weaker if they get unlucky or lucky rolls on stats they need.
+RandomizerGUI.pbsChangesRandomTotalRB.text=Random (completely)
+RandomizerGUI.thcRandomTotalRB.toolTipText=Randomise the TMs and HMs that each Pokemon can learn.
Each TM or HM will have a 50% chance of being learnable regardless of type.
+RandomizerGUI.thcRandomTotalRB.text=Random (completely)
+RandomizerGUI.openROMButton.text=Open ROM
+RandomizerGUI.thcUnchangedRB.toolTipText=Every Pokemon will be able to learn the same TMs that it could before.
Note that this applies even if you change the TM moves, which could lead to some odd combinations.
+RandomizerGUI.thcUnchangedRB.text=Unchanged
+RandomizerGUI.thcRandomTypeRB.toolTipText=Randomise the TMs and HMs that each Pokemon can learn.
Each TM or HM will have:
A 90% chance of being learnable if the Pokemon has it as (one of) its type(s).
A 50% chance of being learnable if the move is Normal and the Pokemon isn't.
A 25% chance otherwise.
+RandomizerGUI.thcRandomTypeRB.text=Random (prefer same type)
+RandomizerGUI.wpUnchangedRB.toolTipText=Don't change Wild Pokemon at all.
+RandomizerGUI.wpUnchangedRB.text=Unchanged
+RandomizerGUI.wpRandomRB.toolTipText=Completely randomise Wild Pokemon in every area.
This should mean that there are many different Pokemon in each area.
+RandomizerGUI.wpRandomRB.text=Random
+RandomizerGUI.wpArea11RB.toolTipText=Each Pokemon in a given encounter area will be replaced by another Pokemon in every slot it appears in.
This will make each area have a handful of random Pokemon.
+RandomizerGUI.wpArea11RB.text=Area 1-to-1 Mapping
+RandomizerGUI.wpGlobalRB.toolTipText=Every place a certain Pokemon appears in, it will be replaced by another set Pokemon.
This mode doesn't support any other rules except similar strength because it is too restrictive on its own.
+RandomizerGUI.wpGlobalRB.text=Global 1-to-1 Mapping
+RandomizerGUI.tpNoLegendariesCB.text=Don't use legendaries?
+RandomizerGUI.tpRivalCarriesStarterCB.toolTipText=If this is selected, the rival will have their starter in every team they battle you with, evolved if it is far enough through.
The rest of their team will be chosen in the same way as every other trainer.
+RandomizerGUI.tpRivalCarriesStarterCB.text=Rival carries starter through game?
+RandomizerGUI.wildPokemonPanel.border.title=Wild Pokemon
+RandomizerGUI.tpTypeThemedRB.toolTipText=Pick a type for each trainer and give them random Pokemon in that type.
Certain groups of trainers, such as the trainers in each gym, will all be given the same (random) type.
+RandomizerGUI.tpTypeThemedRB.text=Type Themed
+RandomizerGUI.tpRandomRB.toolTipText=Randomise Trainers' Pokemon completely.
+RandomizerGUI.tpRandomRB.text=Random
+RandomizerGUI.tpTypeWeightingCB.toolTipText=If this is checked, the number of trainers with each type will roughly match up to the number of Pokemon with that type.
This should reduce repetition of Pokemon, but may lead to a lot of trainers with the same type in a row.
+RandomizerGUI.tpTypeWeightingCB.text=Weight types by # of Pokemon with them?
+RandomizerGUI.tpPowerLevelsCB.toolTipText=If this is checked, the random Pokemon that replaces each Pokemon will be of similar power to the original.
However, preserving other rules such as type theming has precedence over this, so weaker or stronger Pokemon will be chosen if there are no other Pokemon available.
+RandomizerGUI.tnRandomizeCB.toolTipText=Check this to randomize trainers' names when you fight them.
For RBY, this only includes the Gym Leaders and Elite 4, as no-one else has names.
For every other game this will replace the names of each individual trainer.
+RandomizerGUI.tnRandomizeCB.text=Randomize Trainer Names
+RandomizerGUI.tcnRandomizeCB.text=Randomize Trainer Class Names
+RandomizerGUI.tcnRandomizeCB.toolTipText=Check this to randomize the class names to new names (e.g. "Youngster" could become "Misfit").
+RandomizerGUI.aboutButton.text=About
+RandomizerGUI.cantWriteConfigFile=WARNING: The randomizer is unable to write its config file to the directory it is in.\nThis means that it will probably be unable to save the randomized ROMs it creates.\nPlease run the randomizer from a directory where you can write files.\nYou can try to use the randomizer as-is, but it will probably not work and the auto-updater will be disabled.
+RandomizerGUI.copyNameFilesDialog.text=You appear to have customized name files in the config directory left over from an old version of the randomizer.\nWould you like these files to be copied to the main program directory so they are used in this version?
+RandomizerGUI.copyNameFilesDialog.title=Copy custom names?
+RandomizerGUI.copyNameFilesFailed=At least one file was not able to be copied.
+RandomizerGUI.configFileMissing=The file %s is missing from the configuration and so this program cannot start.\nPlease make sure you extract the program from the ZIP file before running it.
+RandomizerGUI.noRomLoaded=NO ROM LOADED
+RandomizerGUI.loadingText=Loading...
+RandomizerGUI.savingText=Saving...
+RandomizerGUI.loadFailed=There was an unhandled exception trying to load your ROM.\nA log file containing some details has been saved to %s.\nPlease include this file in any bug reports you do.
+RandomizerGUI.loadFailedNoLog=There was an unhandled exception trying to load your ROM.
+RandomizerGUI.unreadableRom=Could not read %s from disk.\nPlease ensure you have read access to the ROM you're trying to open.
+RandomizerGUI.tooShortToBeARom=%s appears to be a blank or nearly blank file.\nCheck to make sure you're opening the right file.
+RandomizerGUI.openedZIPfile=%s is a ZIP archive, not a ROM.\nYou should extract it and try to randomize the actual ROM file inside.
+RandomizerGUI.openedRARfile=%s is a RAR archive, not a ROM.\nYou should extract it and try to randomize the actual ROM file inside.
+RandomizerGUI.openedIPSfile=%s is an IPS patch, not a ROM.\nYou should apply it to a ROM first before trying to randomize the result.
+RandomizerGUI.unsupportedRom=Could not load %s - it's not a supported ROM.
+RandomizerGUI.romSupportPrefix=Support:
+RandomizerGUI.processFailed=There was an unhandled exception trying to process your ROM.\nA log file containing some details has been saved to %s.\nPlease include this file in any bug reports you do.
+RandomizerGUI.processFailedNoLog=There was an unhandled exception trying to process your ROM.
+RandomizerGUI.raceModeRequirements=You can't use Race Mode without randomizing either the wild Pokemon or the trainer Pokemon.\nReview this and try again.
+RandomizerGUI.pokeLimitNotChosen=You enabled the option to limit the Pokemon that appear, but didn't choose any to allow.\nSelect some by clicking on the "Limit Pokemon" button and try again.
+RandomizerGUI.presetFailTrainerClasses=Can't use this preset because you have a different set of random trainer class names to the creator.\nHave them make you a rndp file instead.
+RandomizerGUI.presetFailTrainerNames=Can't use this preset because you have a different set of random trainer names to the creator.\nHave them make you a rndp file instead.
+RandomizerGUI.presetFailNicknames=Can't use this preset because you have a different set of random nicknames to the creator.\nHave them make you a rndp file instead.
+RandomizerGUI.starterUnavailable=Could not set one of the custom starters from the settings file because it does not exist in this generation.
+RandomizerGUI.saveFailedIO=There was an unhandled exception trying to save your ROM to disk.\nA log file containing some details has been saved to %s.\nPlease include this file in any bug reports you do.
+RandomizerGUI.saveFailedIONoLog=There was an unhandled exception trying to save your ROM to disk.
+RandomizerGUI.raceModeCheckValuePopup=Your check value for the race is:\n%08X\nDistribute this along with the preset file, if you're the race maker!\nIf you received this in a race, compare it to the value the race maker gave.
+RandomizerGUI.saveLogDialog.text=Do you want to save a log file of the randomization performed?\nThis may allow you to gain an unfair advantage, do not do so if you are doing something like a race.
+RandomizerGUI.saveLogDialog.title=Save Log?
+RandomizerGUI.logSaveFailed=Could not save log file!
+RandomizerGUI.logSaved=Log file saved to\n%s.log
+RandomizerGUI.randomizationDone=Randomization Complete. You can now play!
+RandomizerGUI.saveFailed=There was an unhandled exception trying to save your ROM.\nA log file containing some details has been saved to %s.\nPlease include this file in any bug reports you do.
+RandomizerGUI.saveFailedNoLog=There was an unhandled exception trying to save your ROM.
+RandomizerGUI.cantOverwriteDS=You cannot overwrite the original ROM when you save a DS randomization.\nPlease choose a different filename.
+RandomizerGUI.noUpdates=No new updates found.
+RandomizerGUI.settingsFileOlder=This settings file is for an old randomizer version.\nYou should make a new file.
+RandomizerGUI.settingsFileNewer=This settings file is for a newer randomizer version.\nYou should upgrade your randomizer.
+RandomizerGUI.invalidSettingsFile=Settings file is not valid.
+RandomizerGUI.settingsLoaded=Settings loaded from %s.
+RandomizerGUI.settingsLoadFailed=Settings file load failed. Please try again.
+RandomizerGUI.settingsSaveFailed=Settings file save failed. Please try again.
+RandomizerGUI.abilitiesPanel.border.title=Pokemon Abilities
+RandomizerGUI.paUnchangedRB.text=Unchanged
+RandomizerGUI.paUnchangedRB.toolTipText=Don't change Pokemon abilities from the base at all.
+RandomizerGUI.wpCatchRateCB.text=Set minimum catch rate?
+RandomizerGUI.wpCatchRateCB.toolTipText=If this is selected, every Pokemon in the game with a catch rate below a certain level will have its catch rate increased.
This means that if you throw a Poke Ball at a Pokemon weakened to red, it should have at least a 25-30% chance of catching it.
Legendaries only get half this chance (about 15% at low health), except for legendaries that were already easier to catch like Mew.
+RandomizerGUI.paWonderGuardCB.text=Allow Wonder Guard?
+RandomizerGUI.paWonderGuardCB.toolTipText=If this is checked, Wonder Guard will be able to be chosen as any Pokemon's ability.
This can lead to some very overpowered/broken Pokemon.
USE WITH CAUTION!
+RandomizerGUI.paRandomizeRB.toolTipText=Give each Pokemon new abilities.
Each Pokemon will have a base ability, and a 50% chance of having a 2nd ability different from the first.
(50% of the species will have this ability if it is made).
In Generation 5 games, each Pokemon will also receive a new random "Dream World" ability.
Pokemon such as Shedinja which have Wonder Guard as their ability will keep it to maintain balance.
+RandomizerGUI.paRandomizeRB.text=Randomize
+RandomizerGUI.mtMovesPanel.border.title=Move Tutor Moves
+RandomizerGUI.mtmUnchangedRB.toolTipText=Leave the moves taught by tutors as they are.
If Metronome Only Mode is selected, all Move Tutors are changed to Metronome and this setting has no effect.
+RandomizerGUI.mtmUnchangedRB.text=Unchanged
+RandomizerGUI.mtmRandomRB.toolTipText=Give each move tutor slot a new move.
Each Move Tutor move will still be unique, and they will not overlap with TM/HM moves.
If Metronome Only Mode is selected, all Move Tutors are changed to Metronome and this setting has no effect.
+RandomizerGUI.mtmRandomRB.text=Random
+RandomizerGUI.mtCompatPanel.border.title=Move Tutor Compatibility
+RandomizerGUI.mtcUnchangedRB.toolTipText=Every Pokemon will be able to learn the same move tutor moves that it could before.
Note that this applies even if you randomize the moves, which could lead to some odd combinations.
+RandomizerGUI.mtcUnchangedRB.text=Unchanged
+RandomizerGUI.mtcRandomTypeRB.text=Random (prefer same type)
+RandomizerGUI.mtcRandomTypeRB.toolTipText=Randomise the Move Tutor moves that each Pokemon can learn.
Each move will have:
A 90% chance of being learnable if the Pokemon has it as (one of) its type(s).
A 50% chance of being learnable if the move is Normal and the Pokemon isn't.
A 25% chance otherwise.
+RandomizerGUI.mtcRandomTotalRB.text=Random (completely)
+RandomizerGUI.mtcRandomTotalRB.toolTipText=Randomise the Move Tutor moves that each Pokemon can learn.
Each move will have a 50% chance of being learnable regardless of type.
+RandomizerGUI.mtNoExistLabel.text=This game does not have any Move Tutors, or they are not randomizable yet.
+RandomizerGUI.moveTutorsPanel.border.title=Move Tutors
+RandomizerGUI.raceModeCB.text=Race Mode
+RandomizerGUI.raceModeCB.toolTipText=Select this to enable certain things which are useful for a speedrun race of the ROM you create.
The ability to save a log file will be disabled, and a check value will be generated.
You can send this value around with the preset file to ensure that everyone has the same ROM to race with.
+RandomizerGUI.otherOptionsPanel.border.title=Other Options
+RandomizerGUI.tpNoEarlyShedinjaCB.text=No Early Wonder Guard?
+RandomizerGUI.tpNoEarlyShedinjaCB.toolTipText=Pokemon such as Shedinja, with the ability "Wonder Guard", are a pain to run into early on when you can't damage them.
Selecting this option will make sure that no trainers are given these Pokemon under level 20.
By the time you are fighting level 20 trainers you can reasonably be expected to have a counter for each type.
+RandomizerGUI.randomizeHollowsCB.text=Randomize Hidden Hollows
+RandomizerGUI.randomizeHollowsCB.toolTipText=Checking this randomizes the Pokemon you see in Hidden Hollows.
For now, at least, the items remain the same.
Hidden Hollows, and consequently this option, are only available in Black2/White2.
+RandomizerGUI.brokenMovesCB.text=No Game-Breaking Moves
+RandomizerGUI.brokenMovesCB.toolTipText=Checking this checkbox will stop moves that can break early/late games being available in randomized movesets, TMs or Move Tutors.
In first generation games, Dragon Rage, SonicBoom, Spore, and every OHKO move are banned.
In second generation onwards, only SonicBoom and Dragon Rage are banned (because OHKO moves and sleep are a LOT less broken).
+RandomizerGUI.loadQSButton.toolTipText=Clicking this button allows you to load predefined settings from a file.
If the file was created with a game which has less randomization options
than the one you are randomizing now, those options will be set to "Unchanged"/Off.
If you load from a newer game, everything that isn't supported will be ignored.
+RandomizerGUI.loadQSButton.text=Load Settings
+RandomizerGUI.saveQSButton.text=Save Settings
+RandomizerGUI.saveQSButton.toolTipText=Clicking this will allow you to save the current randomization settings as a file.
You can then load these settings when you are randomizing any ROM.
The way in which ROMs with more or less features than the current one
are handled is described when you hover over the "Load Settings" button.
+RandomizerGUI.wpARSimilarStrengthRB.text=Similar Strength
+RandomizerGUI.wpARSimilarStrengthRB.toolTipText=If this is checked, the random Pokemon that replaces each Pokemon will be of similar power to the original.
However, preserving other rules such as 1-1 maps has precedence over this, so weaker or stronger Pokemon will be chosen if there are no other Pokemon available.
This option is not available alongside Type Themes or Catch-em-All because the Pokemon pool would be too limited in some cases.
+RandomizerGUI.pmsMetronomeOnlyRB.text=Metronome Only Mode
+RandomizerGUI.pmsMetronomeOnlyRB.toolTipText=Where possible, every Pok\u00e9mon in the entire game will have Metronome as its only move,
with the PP boosted to 40 to make it possible to complete fights without always using Struggle.
Does not currently apply to non-standard battles such as the Battle Tower/Frontier or the PWT.
+RandomizerGUI.inGameTradesPanel.border.title=In-Game Trades
+RandomizerGUI.fieldItemsPanel.border.title=Field Items
+RandomizerGUI.igtUnchangedRB.text=Unchanged
+RandomizerGUI.igtUnchangedRB.toolTipText=In-game trades remain the same.
+RandomizerGUI.igtGivenOnlyRB.text=Randomize Given Pokemon Only
+RandomizerGUI.igtGivenOnlyRB.toolTipText=Selecting this will randomize the Pokemon you receive from each in-game trade,
but the Pokemon requested by the NPC in exchange will remain the same.
+RandomizerGUI.igtBothRB.text=Randomize both Requested & Given Pokemon
+RandomizerGUI.igtBothRB.toolTipText=Selecting this will replace both the Pokemon you receive from an in-game trade and the Pokemon required to do the trade.
+RandomizerGUI.fiUnchangedRB.toolTipText=Items on the ground and hidden items remain the same.
+RandomizerGUI.fiUnchangedRB.text=Unchanged
+RandomizerGUI.fiShuffleRB.toolTipText=Selecting this will take the full set of items that can be picked up from item balls, as well as hidden items,
and randomize their order so each item appears in a new place.
Key items are left in their original location and glitch items are excluded.
This stops item balls containing seriously overpowered items, but more powerful items may be available early on.
TMs will remain in the same item balls, but the numbers of the TMs in them will be shuffled among the set.
+RandomizerGUI.fiShuffleRB.text=Shuffle
+RandomizerGUI.fiRandomRB.text=Randomize
+RandomizerGUI.fiRandomRB.toolTipText=Selecting this will place a new random item in each item ball & hidden item slot.
Key items & glitch items are automatically excluded.
This means item balls can contain seriously overpowered items such as Master Balls.
TMs will remain in the same item balls, but the numbers of the TMs in them will be randomized, including TMs not usually available from item balls.
All TMs will still be available at least once in the game.
+RandomizerGUI.igtRandomNicknameCB.toolTipText=Check this to randomize the nicknames of the Pokemon you receive.
The nicknames will be chosen from a predefined list.
If there are no more usable nicknames the original nicknames will be kept for the rest of the trades.
+RandomizerGUI.igtRandomNicknameCB.text=Randomize Nicknames
+RandomizerGUI.igtRandomItemCB.text=Randomize Items
+RandomizerGUI.igtRandomItemCB.toolTipText=Check this to give each Pokemon you receive from an ingame trade a random held item.
This includes trades that do not normally have a held item on the Pokemon.
+RandomizerGUI.igtRandomIVsCB.toolTipText=Check this to randomize the IVs of the Pokemon you receive from ingame trades.
In most games these Pokemon have set IVs, so clicking this randomizes those set IVs.
+RandomizerGUI.igtRandomIVsCB.text=Randomize IVs
+RandomizerGUI.igtRandomOTCB.text=Randomize OTs
+RandomizerGUI.igtRandomOTCB.toolTipText=Check this to randomize the Original Trainer (ID & name) of the Pokemon you receive from trades.
The names will be chosen from the same list as trainer names,
with names that are too long to be OT names excluded.
+RandomizerGUI.spHeldItemsCB.toolTipText=Checking this will randomize the items held by the starters where possible.
In Generation 2 games, each starter will get an individual random item.
In Generation 3 games, all the starters will get the same random item.
+RandomizerGUI.spHeldItemsCB.text=Randomize Starter Held Items
+RandomizerGUI.wpHeldItemsCB.toolTipText=Checking this will randomize the items held by Pokemon in the wild, including whether they can have one at all or not.
In some cases, these item definitions will also apply to static encounters with legendaries and the like.
+RandomizerGUI.wpHeldItemsCB.text=Randomize held items?
+RandomizerGUI.codeTweaksCB.text=
+RandomizerGUI.codeTweaksCB.toolTipText=Select this to enable the use of certain code tweaks that you can select by clicking the button.
If this box isn't checked no tweaks will be applied!
These are only currently available for English versions of Generation 1/2 games.
+RandomizerGUI.codeTweaksBtn.text=Code Tweaks
+RandomizerGUI.codeTweaksBtn.textWithActive=Code Tweaks (%d)
+RandomizerGUI.pokeLimitCB.text=
+RandomizerGUI.pokeLimitBtn.text=Limit Pokemon
+RandomizerGUI.pokeLimitCB.toolTipText=Select this to allow yourself to limit the Pokemon used by the randomization.
If this box isn't checked all Pokemon will be allowed!
+RandomizerGUI.updateSettingsButton.text=Update Settings
+RandomizerGUI.toggleAutoUpdatesMenuItem.text=Toggle AutoUpdate
+RandomizerGUI.manualUpdateMenuItem.text=Check for Update Now
+RandomizerGUI.disableAutoUpdate=Disable Auto Update
+RandomizerGUI.enableAutoUpdate=Enable Auto Update
+RandomizerGUI.autoUpdateDisabled=Auto update disabled.\nTo get new updates you will need to manually look for them or look on the website.
+RandomizerGUI.autoUpdateEnabled=Auto update enabled.\nThe randomizer will check for new updates each time you open it.
+RandomizerGUI.goUpdateMovesLegacyCheckBox.text=Legacy?
+RandomizerGUI.goUpdateMovesLegacyCheckBox.toolTipText=Instead of updating moves to their Gen 6 stats, update them to their Gen 5 stats instead.
This is intended for people who used the "Update Moves" function in old randomizers but don't like the new changes.
This is available for every game except Gen 5 games where it would be pointless.
+RandomizerGUI.pbsStandardEXPCurvesCB.text=Standardize EXP Curves
+RandomizerGUI.pbsStandardEXPCurvesCB.toolTipText=When this is selected, every Pokemon's EXP curve will be changed to one of the following:- Medium Fast (1,000,000 EXP to Level 100) if it isn't a legendary
- Slow (1,250,000 EXP to Level 100) if it is.
This will cause Pokemon to be better or worse based more on their stats/moves/type rather than the difficulty of leveling them.
WARNING: This will break trade compatibility with ROMs that don't have this option enabled. Use with caution.
+GenerationLimitDialog.includePokemonHeader.text=Include Pokemon from:
+GenerationLimitDialog.relatedPokemonHeader.text=... and related Pokemon from:
+GenerationLimitDialog.gen1CB.text=Generation 1
+GenerationLimitDialog.gen2CB.text=Generation 2
+GenerationLimitDialog.gen3CB.text=Generation 3
+GenerationLimitDialog.gen4CB.text=Generation 4
+GenerationLimitDialog.gen5CB.text=Generation 5
+GenerationLimitDialog.okButton.text=OK
+GenerationLimitDialog.gen2Short=Gen 2
+GenerationLimitDialog.gen4Short=Gen 4
+GenerationLimitDialog.gen1Short=Gen 1
+GenerationLimitDialog.gen3Short=Gen 3
+GenerationLimitDialog.title=Choose Pokemon to allow
+GenerationLimitDialog.cancelButton.text=Cancel
+GenerationLimitDialog.warningRomHackLabel.text=WARNING: This functionality will NOT work correctly with ROM hacks
that change the available Pokemon or add new ones!
+AboutDialog.linkLabel.text=http://pokehacks.dabomstew.com/randomizer
+AboutDialog.titleLabel.text=Universal Pokemon Randomizer 1.6.1-dev
+AboutDialog.title=About
+AboutDialog.ackLabel.text=Based on research by various sources; see Acknowledgements
+AboutDialog.authorLabel.text=Created by Dabomstew
+AboutDialog.okButton.text=OK
+CodeTweaksDialog.headerLabel.text=Choose tweaks to enable...
+CodeTweaksDialog.bwPatchCB.text=B/W Exp Patch
+CodeTweaksDialog.bwPatchCB.toolTipText=Select this to patch the game you are randomizing to use the Black/White new XP gain system.
This system gives EXP in a different way, rewarding players for beating higher level Pokemon with lower levels.
This is currently available only for English R/B/Y and G/S/C.
+CodeTweaksDialog.nerfXAccCB.text=Nerf X Accuracy
+CodeTweaksDialog.nerfXAccCB.toolTipText=X Accuracy in Generation 1 games is a pretty broken item, given that it gives 100% accuracy to any and all moves used.
Apply this code tweak to stop X Accuracy from working on sleep moves, trapping moves & one-hit KO moves.
Doing this means that the player cannot use X Accuracy and lock the opponents into infinite sleep/Wrap, nor can they just use one-hit KO moves on everything.
Applying this patch will also remove the one-hit KO moves from the "broken moves" list if you use that option, since they aren't really broken without X Accuracy.
Credit to Mountebank for this patch.
+CodeTweaksDialog.critRateFixCB.text="Fix" Crit Rate
+CodeTweaksDialog.critRateFixCB.toolTipText=Selecting this option will "fix" Generation 1's critical hit rate to be the same as the other games (1/16), instead of being based on Speed.
Focus Energy and Dire Hit will also be fixed to increase crit rate instead of decreasing it.
"High crit rate" moves such as Slash will have double the normal crit chance, like in later games.
+CodeTweaksDialog.title=Code Tweaks
+CodeTweaksDialog.okButton.text=OK
+CodeTweaksDialog.cancelButton.text=Cancel
+PresetMakeDialog.doneButton.text=Done
+PresetMakeDialog.jLabel5.text=Alternatively you can produce a file which contains this data which you can then send to people.
+PresetMakeDialog.jLabel3.text=Random Seed:
+PresetMakeDialog.jLabel2.text=Below are the settings you can give to other people to produce the same randomization as you just did.
+PresetMakeDialog.jLabel4.text=Config String:
+PresetMakeDialog.jLabel1.text=Your game has been successfully randomized!
+PresetMakeDialog.title=Randomization Completed - Seed Details
+PresetMakeDialog.produceFileButton.text=Produce File
+RandomizerGUI.pms4MovesCB.toolTipText=Check this to make sure every Pokemon gets 4 moves at level 1, instead of them keeping their original move count.
This ensures that every Pokemon you catch will have a full moveset.
This is now available for all supported games.
+RandomizerGUI.pms4MovesCB.text=Every Pokemon starts with 4 moves?
diff --git a/src/com/dabomstew/pkrandom/gui/CodeTweaksDialog.form b/src/com/dabomstew/pkrandom/gui/CodeTweaksDialog.form
new file mode 100755
index 000000000..213f6aa34
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/gui/CodeTweaksDialog.form
@@ -0,0 +1,142 @@
+
+
+
diff --git a/src/com/dabomstew/pkrandom/gui/CodeTweaksDialog.java b/src/com/dabomstew/pkrandom/gui/CodeTweaksDialog.java
new file mode 100755
index 000000000..4bfaaa62e
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/gui/CodeTweaksDialog.java
@@ -0,0 +1,180 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.dabomstew.pkrandom.gui;
+
+import java.util.ResourceBundle;
+
+import com.dabomstew.pkrandom.CodeTweaks;
+
+/**
+ *
+ * @author Stewart
+ */
+public class CodeTweaksDialog extends javax.swing.JDialog {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1771633141425200187L;
+ private static final ResourceBundle bundle = ResourceBundle
+ .getBundle("com/dabomstew/pkrandom/gui/Bundle");
+ private boolean pressedOk;
+
+ /**
+ * Creates new form CodeTweaksDialog
+ */
+ public CodeTweaksDialog(RandomizerGUI parent, int current, int available) {
+ super(parent, true);
+ initComponents();
+ initialState(available);
+ if (current != 0) {
+ current &= available;
+ restoreFrom(current);
+ }
+ pressedOk = false;
+ setLocationRelativeTo(parent);
+ setVisible(true);
+
+ }
+
+ private void initialState(int available) {
+ bwPatchCB.setVisible((available & CodeTweaks.BW_EXP_PATCH) > 0);
+ nerfXAccCB.setVisible((available & CodeTweaks.NERF_X_ACCURACY) > 0);
+ critRateFixCB.setVisible((available & CodeTweaks.FIX_CRIT_RATE) > 0);
+ }
+
+ private void restoreFrom(int current) {
+ bwPatchCB.setSelected((current & CodeTweaks.BW_EXP_PATCH) > 0);
+ nerfXAccCB.setSelected((current & CodeTweaks.NERF_X_ACCURACY) > 0);
+ critRateFixCB.setSelected((current & CodeTweaks.FIX_CRIT_RATE) > 0);
+ }
+
+ public boolean pressedOK() {
+ return pressedOk;
+ }
+
+ public int getChoice() {
+ int choice = 0;
+ if (bwPatchCB.isSelected()) {
+ choice |= CodeTweaks.BW_EXP_PATCH;
+ }
+ if (nerfXAccCB.isSelected()) {
+ choice |= CodeTweaks.NERF_X_ACCURACY;
+ }
+ if (critRateFixCB.isSelected()) {
+ choice |= CodeTweaks.FIX_CRIT_RATE;
+ }
+ return choice;
+ }
+
+ /**
+ * This method is called from within the constructor to initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is always
+ * regenerated by the Form Editor.
+ */
+ @SuppressWarnings("unchecked")
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ headerLabel = new javax.swing.JLabel();
+ bwPatchCB = new javax.swing.JCheckBox();
+ nerfXAccCB = new javax.swing.JCheckBox();
+ critRateFixCB = new javax.swing.JCheckBox();
+ okButton = new javax.swing.JButton();
+ cancelButton = new javax.swing.JButton();
+
+ setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
+ java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("com/dabomstew/pkrandom/gui/Bundle"); // NOI18N
+ setTitle(bundle.getString("CodeTweaksDialog.title")); // NOI18N
+
+ headerLabel.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N
+ headerLabel.setText(bundle.getString("CodeTweaksDialog.headerLabel.text")); // NOI18N
+
+ bwPatchCB.setText(bundle.getString("CodeTweaksDialog.bwPatchCB.text")); // NOI18N
+ bwPatchCB.setToolTipText(bundle.getString("CodeTweaksDialog.bwPatchCB.toolTipText")); // NOI18N
+
+ nerfXAccCB.setText(bundle.getString("CodeTweaksDialog.nerfXAccCB.text")); // NOI18N
+ nerfXAccCB.setToolTipText(bundle.getString("CodeTweaksDialog.nerfXAccCB.toolTipText")); // NOI18N
+
+ critRateFixCB.setText(bundle.getString("CodeTweaksDialog.critRateFixCB.text")); // NOI18N
+ critRateFixCB.setToolTipText(bundle.getString("CodeTweaksDialog.critRateFixCB.toolTipText")); // NOI18N
+
+ okButton.setText(bundle.getString("CodeTweaksDialog.okButton.text")); // NOI18N
+ okButton.setMaximumSize(new java.awt.Dimension(65, 23));
+ okButton.setMinimumSize(new java.awt.Dimension(65, 23));
+ okButton.setPreferredSize(new java.awt.Dimension(65, 23));
+ okButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ okButtonActionPerformed(evt);
+ }
+ });
+
+ cancelButton.setText(bundle.getString("CodeTweaksDialog.cancelButton.text")); // NOI18N
+ cancelButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ cancelButtonActionPerformed(evt);
+ }
+ });
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
+ getContentPane().setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(okButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(cancelButton))
+ .addGroup(layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(critRateFixCB)
+ .addComponent(nerfXAccCB)
+ .addComponent(bwPatchCB)
+ .addComponent(headerLabel))
+ .addGap(0, 0, Short.MAX_VALUE)))
+ .addContainerGap())
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(headerLabel)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(bwPatchCB)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(nerfXAccCB)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(critRateFixCB)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 31, Short.MAX_VALUE)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(okButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(cancelButton))
+ .addContainerGap())
+ );
+
+ pack();
+ }// //GEN-END:initComponents
+
+ private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_okButtonActionPerformed
+ pressedOk = true;
+ setVisible(false);
+ }// GEN-LAST:event_okButtonActionPerformed
+
+ private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_cancelButtonActionPerformed
+ pressedOk = false;
+ setVisible(false);
+ }// GEN-LAST:event_cancelButtonActionPerformed
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JCheckBox bwPatchCB;
+ private javax.swing.JButton cancelButton;
+ private javax.swing.JCheckBox critRateFixCB;
+ private javax.swing.JLabel headerLabel;
+ private javax.swing.JCheckBox nerfXAccCB;
+ private javax.swing.JButton okButton;
+ // End of variables declaration//GEN-END:variables
+}
diff --git a/src/com/dabomstew/pkrandom/gui/GenerationLimitDialog.form b/src/com/dabomstew/pkrandom/gui/GenerationLimitDialog.form
new file mode 100755
index 000000000..e116fbc99
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/gui/GenerationLimitDialog.form
@@ -0,0 +1,314 @@
+
+
+
diff --git a/src/com/dabomstew/pkrandom/gui/GenerationLimitDialog.java b/src/com/dabomstew/pkrandom/gui/GenerationLimitDialog.java
new file mode 100755
index 000000000..82bc1779a
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/gui/GenerationLimitDialog.java
@@ -0,0 +1,448 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.dabomstew.pkrandom.gui;
+
+import com.dabomstew.pkrandom.pokemon.GenRestrictions;
+
+/**
+ *
+ * @author Stewart
+ */
+public class GenerationLimitDialog extends javax.swing.JDialog {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 106783506965080925L;
+ private boolean pressedOk;
+
+ /**
+ * Creates new form GenerationLimitDialog
+ */
+ public GenerationLimitDialog(RandomizerGUI parent, GenRestrictions current,
+ int generation) {
+ super(parent, true);
+ initComponents();
+ initialState(generation);
+ if (current != null) {
+ current.limitToGen(generation);
+ restoreFrom(current);
+ }
+ enableAndDisableBoxes();
+ pressedOk = false;
+ setLocationRelativeTo(parent);
+ setVisible(true);
+
+ }
+
+ public boolean pressedOK() {
+ return pressedOk;
+ }
+
+ public GenRestrictions getChoice() {
+ GenRestrictions gr = new GenRestrictions();
+ gr.allow_gen1 = this.gen1CB.isSelected();
+ gr.allow_gen2 = this.gen2CB.isSelected();
+ gr.allow_gen3 = this.gen3CB.isSelected();
+ gr.allow_gen4 = this.gen4CB.isSelected();
+ gr.allow_gen5 = this.gen5CB.isSelected();
+
+ gr.assoc_g1_g2 = this.g1Rg2CB.isSelected();
+ gr.assoc_g1_g4 = this.g1Rg4CB.isSelected();
+
+ gr.assoc_g2_g1 = this.g2Rg1CB.isSelected();
+ gr.assoc_g2_g3 = this.g2Rg3CB.isSelected();
+ gr.assoc_g2_g4 = this.g2Rg4CB.isSelected();
+
+ gr.assoc_g3_g2 = this.g3Rg2CB.isSelected();
+ gr.assoc_g3_g4 = this.g3Rg4CB.isSelected();
+
+ gr.assoc_g4_g1 = this.g4Rg1CB.isSelected();
+ gr.assoc_g4_g2 = this.g4Rg2CB.isSelected();
+ gr.assoc_g4_g3 = this.g4Rg3CB.isSelected();
+
+ return gr;
+ }
+
+ private void initialState(int generation) {
+ if (generation < 2) {
+ gen2CB.setVisible(false);
+ g1Rg2CB.setVisible(false);
+ g2Rg1CB.setVisible(false);
+ g2Rg3CB.setVisible(false);
+ g2Rg4CB.setVisible(false);
+ }
+ if (generation < 3) {
+ gen3CB.setVisible(false);
+ g2Rg3CB.setVisible(false);
+ g3Rg2CB.setVisible(false);
+ g3Rg4CB.setVisible(false);
+ }
+ if (generation < 4) {
+ gen4CB.setVisible(false);
+ g1Rg4CB.setVisible(false);
+ g2Rg4CB.setVisible(false);
+ g3Rg4CB.setVisible(false);
+ g4Rg1CB.setVisible(false);
+ g4Rg2CB.setVisible(false);
+ g4Rg3CB.setVisible(false);
+ }
+ if (generation < 5) {
+ gen5CB.setVisible(false);
+ }
+ }
+
+ private void restoreFrom(GenRestrictions restrict) {
+ gen1CB.setSelected(restrict.allow_gen1);
+ gen2CB.setSelected(restrict.allow_gen2);
+ gen3CB.setSelected(restrict.allow_gen3);
+ gen4CB.setSelected(restrict.allow_gen4);
+ gen5CB.setSelected(restrict.allow_gen5);
+
+ g1Rg2CB.setSelected(restrict.assoc_g1_g2);
+ g1Rg4CB.setSelected(restrict.assoc_g1_g4);
+
+ g2Rg1CB.setSelected(restrict.assoc_g2_g1);
+ g2Rg3CB.setSelected(restrict.assoc_g2_g3);
+ g2Rg4CB.setSelected(restrict.assoc_g2_g4);
+
+ g3Rg2CB.setSelected(restrict.assoc_g3_g2);
+ g3Rg4CB.setSelected(restrict.assoc_g3_g4);
+
+ g4Rg1CB.setSelected(restrict.assoc_g4_g1);
+ g4Rg2CB.setSelected(restrict.assoc_g4_g2);
+ g4Rg3CB.setSelected(restrict.assoc_g4_g3);
+ }
+
+ /**
+ * This method is called from within the constructor to initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is always
+ * regenerated by the Form Editor.
+ */
+ @SuppressWarnings("unchecked")
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ includePokemonHeader = new javax.swing.JLabel();
+ gen1CB = new javax.swing.JCheckBox();
+ gen2CB = new javax.swing.JCheckBox();
+ gen3CB = new javax.swing.JCheckBox();
+ gen4CB = new javax.swing.JCheckBox();
+ gen5CB = new javax.swing.JCheckBox();
+ relatedPokemonHeader = new javax.swing.JLabel();
+ g1Rg2CB = new javax.swing.JCheckBox();
+ g1Rg4CB = new javax.swing.JCheckBox();
+ g2Rg1CB = new javax.swing.JCheckBox();
+ g2Rg3CB = new javax.swing.JCheckBox();
+ g2Rg4CB = new javax.swing.JCheckBox();
+ g3Rg2CB = new javax.swing.JCheckBox();
+ g3Rg4CB = new javax.swing.JCheckBox();
+ g4Rg1CB = new javax.swing.JCheckBox();
+ g4Rg2CB = new javax.swing.JCheckBox();
+ g4Rg3CB = new javax.swing.JCheckBox();
+ okButton = new javax.swing.JButton();
+ cancelButton = new javax.swing.JButton();
+ warningRomHackLabel = new javax.swing.JLabel();
+
+ setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
+ java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("com/dabomstew/pkrandom/gui/Bundle"); // NOI18N
+ setTitle(bundle.getString("GenerationLimitDialog.title")); // NOI18N
+
+ includePokemonHeader.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N
+ includePokemonHeader.setText(bundle.getString("GenerationLimitDialog.includePokemonHeader.text")); // NOI18N
+
+ gen1CB.setText(bundle.getString("GenerationLimitDialog.gen1CB.text")); // NOI18N
+ gen1CB.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ gen1CBActionPerformed(evt);
+ }
+ });
+
+ gen2CB.setText(bundle.getString("GenerationLimitDialog.gen2CB.text")); // NOI18N
+ gen2CB.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ gen2CBActionPerformed(evt);
+ }
+ });
+
+ gen3CB.setText(bundle.getString("GenerationLimitDialog.gen3CB.text")); // NOI18N
+ gen3CB.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ gen3CBActionPerformed(evt);
+ }
+ });
+
+ gen4CB.setText(bundle.getString("GenerationLimitDialog.gen4CB.text")); // NOI18N
+ gen4CB.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ gen4CBActionPerformed(evt);
+ }
+ });
+
+ gen5CB.setText(bundle.getString("GenerationLimitDialog.gen5CB.text")); // NOI18N
+ gen5CB.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ gen5CBActionPerformed(evt);
+ }
+ });
+
+ relatedPokemonHeader.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N
+ relatedPokemonHeader.setText(bundle.getString("GenerationLimitDialog.relatedPokemonHeader.text")); // NOI18N
+
+ g1Rg2CB.setText(bundle.getString("GenerationLimitDialog.gen2Short")); // NOI18N
+
+ g1Rg4CB.setText(bundle.getString("GenerationLimitDialog.gen4Short")); // NOI18N
+
+ g2Rg1CB.setText(bundle.getString("GenerationLimitDialog.gen1Short")); // NOI18N
+
+ g2Rg3CB.setText(bundle.getString("GenerationLimitDialog.gen3Short")); // NOI18N
+
+ g2Rg4CB.setText(bundle.getString("GenerationLimitDialog.gen4Short")); // NOI18N
+
+ g3Rg2CB.setText(bundle.getString("GenerationLimitDialog.gen2Short")); // NOI18N
+
+ g3Rg4CB.setText(bundle.getString("GenerationLimitDialog.gen4Short")); // NOI18N
+
+ g4Rg1CB.setText(bundle.getString("GenerationLimitDialog.gen1Short")); // NOI18N
+
+ g4Rg2CB.setText(bundle.getString("GenerationLimitDialog.gen2Short")); // NOI18N
+
+ g4Rg3CB.setText(bundle.getString("GenerationLimitDialog.gen3Short")); // NOI18N
+
+ okButton.setText(bundle.getString("GenerationLimitDialog.okButton.text")); // NOI18N
+ okButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ okButtonActionPerformed(evt);
+ }
+ });
+
+ cancelButton.setText(bundle.getString("GenerationLimitDialog.cancelButton.text")); // NOI18N
+ cancelButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ cancelButtonActionPerformed(evt);
+ }
+ });
+
+ warningRomHackLabel.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N
+ warningRomHackLabel.setForeground(new java.awt.Color(255, 0, 0));
+ warningRomHackLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
+ warningRomHackLabel.setText(bundle.getString("GenerationLimitDialog.warningRomHackLabel.text")); // NOI18N
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
+ getContentPane().setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
+ .addGroup(layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(gen5CB)
+ .addGroup(layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(includePokemonHeader)
+ .addComponent(gen1CB)
+ .addComponent(gen2CB)
+ .addComponent(gen3CB)
+ .addComponent(gen4CB))
+ .addGap(106, 106, 106)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(g4Rg1CB)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(g4Rg2CB)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(g4Rg3CB))
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(g3Rg2CB)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(g3Rg4CB))
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(g2Rg1CB)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(g2Rg3CB)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(g2Rg4CB))
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(g1Rg2CB)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(g1Rg4CB))
+ .addComponent(relatedPokemonHeader))))
+ .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ .addGroup(layout.createSequentialGroup()
+ .addGap(0, 0, Short.MAX_VALUE)
+ .addComponent(okButton)
+ .addGap(32, 32, 32)
+ .addComponent(cancelButton)
+ .addGap(134, 134, 134))))
+ .addGroup(layout.createSequentialGroup()
+ .addGap(20, 20, 20)
+ .addComponent(warningRomHackLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addGap(0, 0, Short.MAX_VALUE))
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(includePokemonHeader)
+ .addComponent(relatedPokemonHeader))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(gen1CB)
+ .addComponent(g1Rg2CB)
+ .addComponent(g1Rg4CB))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(gen2CB)
+ .addComponent(g2Rg1CB)
+ .addComponent(g2Rg3CB)
+ .addComponent(g2Rg4CB))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(gen3CB)
+ .addComponent(g3Rg2CB)
+ .addComponent(g3Rg4CB))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(gen4CB)
+ .addComponent(g4Rg1CB)
+ .addComponent(g4Rg2CB)
+ .addComponent(g4Rg3CB))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(gen5CB)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(okButton)
+ .addComponent(cancelButton))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(warningRomHackLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addContainerGap())
+ );
+
+ pack();
+ }// //GEN-END:initComponents
+
+ private void enableAndDisableBoxes() {
+
+ // enable sub-boxes of checked main boxes
+ g1Rg2CB.setEnabled(gen1CB.isSelected());
+ g1Rg4CB.setEnabled(gen1CB.isSelected());
+ g2Rg1CB.setEnabled(gen2CB.isSelected());
+ g2Rg3CB.setEnabled(gen2CB.isSelected());
+ g2Rg4CB.setEnabled(gen2CB.isSelected());
+ g3Rg2CB.setEnabled(gen3CB.isSelected());
+ g3Rg4CB.setEnabled(gen3CB.isSelected());
+ g4Rg1CB.setEnabled(gen4CB.isSelected());
+ g4Rg2CB.setEnabled(gen4CB.isSelected());
+ g4Rg3CB.setEnabled(gen4CB.isSelected());
+
+ // uncheck disabled subboxes
+ if (!gen1CB.isSelected()) {
+ g1Rg2CB.setSelected(false);
+ g1Rg4CB.setSelected(false);
+ }
+ if (!gen2CB.isSelected()) {
+ g2Rg1CB.setSelected(false);
+ g2Rg3CB.setSelected(false);
+ g2Rg4CB.setSelected(false);
+ }
+ if (!gen3CB.isSelected()) {
+ g3Rg2CB.setSelected(false);
+ g3Rg4CB.setSelected(false);
+ }
+ if (!gen4CB.isSelected()) {
+ g4Rg1CB.setSelected(false);
+ g4Rg2CB.setSelected(false);
+ g4Rg3CB.setSelected(false);
+ }
+
+ // check and disable implied boxes
+ if (gen1CB.isSelected()) {
+ g2Rg1CB.setEnabled(false);
+ g2Rg1CB.setSelected(true);
+ g4Rg1CB.setEnabled(false);
+ g4Rg1CB.setSelected(true);
+ }
+
+ if (gen2CB.isSelected()) {
+ g1Rg2CB.setEnabled(false);
+ g1Rg2CB.setSelected(true);
+ g3Rg2CB.setEnabled(false);
+ g3Rg2CB.setSelected(true);
+ g4Rg2CB.setEnabled(false);
+ g4Rg2CB.setSelected(true);
+ }
+
+ if (gen3CB.isSelected()) {
+ g2Rg3CB.setEnabled(false);
+ g2Rg3CB.setSelected(true);
+ g4Rg3CB.setEnabled(false);
+ g4Rg3CB.setSelected(true);
+ }
+
+ if (gen4CB.isSelected()) {
+ g1Rg4CB.setEnabled(false);
+ g1Rg4CB.setSelected(true);
+ g2Rg4CB.setEnabled(false);
+ g2Rg4CB.setSelected(true);
+ g3Rg4CB.setEnabled(false);
+ g3Rg4CB.setSelected(true);
+ }
+ }
+
+ private void gen1CBActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_gen1CBActionPerformed
+ enableAndDisableBoxes();
+ }// GEN-LAST:event_gen1CBActionPerformed
+
+ private void gen2CBActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_gen2CBActionPerformed
+ enableAndDisableBoxes();
+ }// GEN-LAST:event_gen2CBActionPerformed
+
+ private void gen3CBActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_gen3CBActionPerformed
+ enableAndDisableBoxes();
+ }// GEN-LAST:event_gen3CBActionPerformed
+
+ private void gen4CBActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_gen4CBActionPerformed
+ enableAndDisableBoxes();
+ }// GEN-LAST:event_gen4CBActionPerformed
+
+ private void gen5CBActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_gen5CBActionPerformed
+ enableAndDisableBoxes();
+ }// GEN-LAST:event_gen5CBActionPerformed
+
+ private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_okButtonActionPerformed
+ pressedOk=true;
+ setVisible(false);
+ }// GEN-LAST:event_okButtonActionPerformed
+
+ private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_cancelButtonActionPerformed
+ pressedOk=false;
+ setVisible(false);
+ }// GEN-LAST:event_cancelButtonActionPerformed
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JButton cancelButton;
+ private javax.swing.JCheckBox g1Rg2CB;
+ private javax.swing.JCheckBox g1Rg4CB;
+ private javax.swing.JCheckBox g2Rg1CB;
+ private javax.swing.JCheckBox g2Rg3CB;
+ private javax.swing.JCheckBox g2Rg4CB;
+ private javax.swing.JCheckBox g3Rg2CB;
+ private javax.swing.JCheckBox g3Rg4CB;
+ private javax.swing.JCheckBox g4Rg1CB;
+ private javax.swing.JCheckBox g4Rg2CB;
+ private javax.swing.JCheckBox g4Rg3CB;
+ private javax.swing.JCheckBox gen1CB;
+ private javax.swing.JCheckBox gen2CB;
+ private javax.swing.JCheckBox gen3CB;
+ private javax.swing.JCheckBox gen4CB;
+ private javax.swing.JCheckBox gen5CB;
+ private javax.swing.JLabel includePokemonHeader;
+ private javax.swing.JButton okButton;
+ private javax.swing.JLabel relatedPokemonHeader;
+ private javax.swing.JLabel warningRomHackLabel;
+ // End of variables declaration//GEN-END:variables
+}
diff --git a/src/com/dabomstew/pkrandom/gui/InvalidSupplementFilesException.java b/src/com/dabomstew/pkrandom/gui/InvalidSupplementFilesException.java
new file mode 100755
index 000000000..4e792678a
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/gui/InvalidSupplementFilesException.java
@@ -0,0 +1,36 @@
+package com.dabomstew.pkrandom.gui;
+
+/*----------------------------------------------------------------------------*/
+/*-- InvalidSupplementFilesException.java - thrown when the trainer class --*/
+/*-- or trainer name files found are--*/
+/*-- different from those of the --*/
+/*-- preset creator. --*/
+/*-- --*/
+/*-- Part of "Universal Pokemon Randomizer" by Dabomstew --*/
+/*-- Pokemon and any associated names and the like are --*/
+/*-- trademark and (C) Nintendo 1996-2012. --*/
+/*-- --*/
+/*-- The custom code written here is licensed under the terms of the GPL: --*/
+/*-- --*/
+/*-- This program is free software: you can redistribute it and/or modify --*/
+/*-- it under the terms of the GNU General Public License as published by --*/
+/*-- the Free Software Foundation, either version 3 of the License, or --*/
+/*-- (at your option) any later version. --*/
+/*-- --*/
+/*-- This program is distributed in the hope that it will be useful, --*/
+/*-- but WITHOUT ANY WARRANTY; without even the implied warranty of --*/
+/*-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --*/
+/*-- GNU General Public License for more details. --*/
+/*-- --*/
+/*-- You should have received a copy of the GNU General Public License --*/
+/*-- along with this program. If not, see . --*/
+/*----------------------------------------------------------------------------*/
+
+public class InvalidSupplementFilesException extends Exception {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -3778498838677886358L;
+
+}
diff --git a/src/com/dabomstew/pkrandom/gui/OperationDialog.form b/src/com/dabomstew/pkrandom/gui/OperationDialog.form
new file mode 100755
index 000000000..e4166a967
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/gui/OperationDialog.form
@@ -0,0 +1,79 @@
+
+
+
diff --git a/src/com/dabomstew/pkrandom/gui/OperationDialog.java b/src/com/dabomstew/pkrandom/gui/OperationDialog.java
new file mode 100755
index 000000000..cae3427dc
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/gui/OperationDialog.java
@@ -0,0 +1,125 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.dabomstew.pkrandom.gui;
+
+import java.awt.Dialog;
+import java.awt.Frame;
+import java.awt.Image;
+import java.awt.Toolkit;
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.swing.ImageIcon;
+
+/**
+ *
+ * @author Stewart
+ */
+public class OperationDialog extends javax.swing.JDialog {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 5965463550336235236L;
+
+ /**
+ * Creates new form OperationDialog
+ */
+ public OperationDialog(String text, Frame parent, boolean modal) {
+ super(parent, modal);
+ initComponents();
+ this.loadingLabel.setText(text);
+ setLocationRelativeTo(parent);
+ }
+
+ public OperationDialog(String text, Dialog parent, boolean modal) {
+ super(parent, modal);
+ initComponents();
+ this.loadingLabel.setText(text);
+ setLocationRelativeTo(parent);
+ }
+
+ /**
+ * This method is called from within the constructor to initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is always
+ * regenerated by the Form Editor.
+ */
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ jPanel1 = new javax.swing.JPanel();
+ loadingLabel = new javax.swing.JLabel();
+
+ setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE);
+ setResizable(false);
+ setUndecorated(true);
+
+ jPanel1.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(
+ 0, 0, 0), 2, true));
+
+ loadingLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
+ loadingLabel.setIcon(getLoadingIcon());
+ loadingLabel.setText("Loading...");
+
+ javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(
+ jPanel1);
+ jPanel1.setLayout(jPanel1Layout);
+ jPanel1Layout.setHorizontalGroup(jPanel1Layout.createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING).addGroup(
+ jPanel1Layout.createSequentialGroup().addContainerGap()
+ .addComponent(loadingLabel)
+ .addContainerGap(53, Short.MAX_VALUE)));
+ jPanel1Layout.setVerticalGroup(jPanel1Layout.createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING).addGroup(
+ jPanel1Layout
+ .createSequentialGroup()
+ .addContainerGap()
+ .addComponent(loadingLabel)
+ .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)));
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(
+ getContentPane());
+ getContentPane().setLayout(layout);
+ layout.setHorizontalGroup(layout.createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING).addComponent(
+ jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE));
+ layout.setVerticalGroup(layout.createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING).addComponent(
+ jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.PREFERRED_SIZE));
+
+ pack();
+ }// //GEN-END:initComponents
+
+ private ImageIcon getLoadingIcon() {
+ try {
+ InputStream in = OperationDialog.class
+ .getResourceAsStream("/com/dabomstew/pkrandom/gui/loading.gif");
+ byte[] buf = new byte[in.available()];
+ in.read(buf);
+ in.close();
+ Image image = Toolkit.getDefaultToolkit().createImage(buf);
+ return new ImageIcon(image);
+ } catch (IOException ex) {
+ return null;
+ }
+ }
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JPanel jPanel1;
+ private javax.swing.JLabel loadingLabel;
+
+ // End of variables declaration//GEN-END:variables
+
+ public static void main(String[] args) {
+ // testing
+ new OperationDialog("Testing...", (Frame)null, true);
+ }
+}
diff --git a/src/com/dabomstew/pkrandom/gui/PresetFileFilter.java b/src/com/dabomstew/pkrandom/gui/PresetFileFilter.java
new file mode 100755
index 000000000..fc6dae5d5
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/gui/PresetFileFilter.java
@@ -0,0 +1,57 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.dabomstew.pkrandom.gui;
+
+/*----------------------------------------------------------------------------*/
+/*-- PresetFileFilter.java - a file filter for the "randomization presets" --*/
+/*-- which allow the same random ROM to be produced--*/
+/*-- on demand. --*/
+/*-- --*/
+/*-- Part of "Universal Pokemon Randomizer" by Dabomstew --*/
+/*-- Pokemon and any associated names and the like are --*/
+/*-- trademark and (C) Nintendo 1996-2012. --*/
+/*-- --*/
+/*-- The custom code written here is licensed under the terms of the GPL: --*/
+/*-- --*/
+/*-- This program is free software: you can redistribute it and/or modify --*/
+/*-- it under the terms of the GNU General Public License as published by --*/
+/*-- the Free Software Foundation, either version 3 of the License, or --*/
+/*-- (at your option) any later version. --*/
+/*-- --*/
+/*-- This program is distributed in the hope that it will be useful, --*/
+/*-- but WITHOUT ANY WARRANTY; without even the implied warranty of --*/
+/*-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --*/
+/*-- GNU General Public License for more details. --*/
+/*-- --*/
+/*-- You should have received a copy of the GNU General Public License --*/
+/*-- along with this program. If not, see . --*/
+/*----------------------------------------------------------------------------*/
+
+import java.io.File;
+
+import javax.swing.filechooser.FileFilter;
+
+public class PresetFileFilter extends FileFilter {
+
+ @Override
+ public boolean accept(File arg0) {
+ if (arg0.isDirectory()) {
+ return true; // needed to allow directory navigation
+ }
+ String filename = arg0.getName();
+ if (filename.contains(".") == false) {
+ return false;
+ }
+ String extension = arg0.getName().substring(
+ arg0.getName().lastIndexOf('.') + 1);
+ return extension.toLowerCase().equals("rndp");
+ }
+
+ @Override
+ public String getDescription() {
+ return "Pokemon Randomizer Preset (*.rndp)";
+ }
+
+}
diff --git a/src/com/dabomstew/pkrandom/gui/PresetLoadDialog.form b/src/com/dabomstew/pkrandom/gui/PresetLoadDialog.form
new file mode 100755
index 000000000..008d3c586
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/gui/PresetLoadDialog.form
@@ -0,0 +1,197 @@
+
+
+
diff --git a/src/com/dabomstew/pkrandom/gui/PresetLoadDialog.java b/src/com/dabomstew/pkrandom/gui/PresetLoadDialog.java
new file mode 100755
index 000000000..8ca2b1ba3
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/gui/PresetLoadDialog.java
@@ -0,0 +1,564 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.dabomstew.pkrandom.gui;
+
+/*----------------------------------------------------------------------------*/
+/*-- PresetLoadDialog.java - a dialog to allow use of preset files or --*/
+/*-- random seed/config string pairs to produce --*/
+/*-- premade ROMs. --*/
+/*-- --*/
+/*-- Part of "Universal Pokemon Randomizer" by Dabomstew --*/
+/*-- Pokemon and any associated names and the like are --*/
+/*-- trademark and (C) Nintendo 1996-2012. --*/
+/*-- --*/
+/*-- The custom code written here is licensed under the terms of the GPL: --*/
+/*-- --*/
+/*-- This program is free software: you can redistribute it and/or modify --*/
+/*-- it under the terms of the GNU General Public License as published by --*/
+/*-- the Free Software Foundation, either version 3 of the License, or --*/
+/*-- (at your option) any later version. --*/
+/*-- --*/
+/*-- This program is distributed in the hope that it will be useful, --*/
+/*-- but WITHOUT ANY WARRANTY; without even the implied warranty of --*/
+/*-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --*/
+/*-- GNU General Public License for more details. --*/
+/*-- --*/
+/*-- You should have received a copy of the GNU General Public License --*/
+/*-- along with this program. If not, see . --*/
+/*----------------------------------------------------------------------------*/
+
+import java.io.DataInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+
+import javax.swing.JDialog;
+import javax.swing.JFileChooser;
+import javax.swing.JOptionPane;
+import javax.swing.JTextField;
+import javax.swing.SwingUtilities;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+
+import com.dabomstew.pkrandom.romhandlers.RomHandler;
+
+/**
+ *
+ * @author Stewart
+ */
+public class PresetLoadDialog extends javax.swing.JDialog {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -7898067118947765260L;
+ private RandomizerGUI parentGUI;
+ private RomHandler currentROM;
+ private boolean completed = false;
+ private String requiredName = null;
+ private volatile boolean changeFieldsWithoutCheck = false;
+ private byte[] trainerClasses = null, trainerNames = null, nicknames = null;
+
+ /**
+ * Creates new form PresetLoadDialog
+ */
+ public PresetLoadDialog(RandomizerGUI parent) {
+ super(parent, true);
+ initComponents();
+ this.parentGUI = parent;
+ this.presetFileChooser.setCurrentDirectory(new File("./"));
+ this.romFileChooser.setCurrentDirectory(new File("./"));
+ initialState();
+ setLocationRelativeTo(parent);
+ setVisible(true);
+ }
+
+ private void initialState() {
+ this.romFileButton.setEnabled(false);
+ this.acceptButton.setEnabled(false);
+ addChangeListener(this.randomSeedField);
+ addChangeListener(this.configStringField);
+ }
+
+ private void addChangeListener(JTextField field) {
+ field.getDocument().addDocumentListener(new DocumentListener() {
+
+ @Override
+ public void insertUpdate(DocumentEvent e) {
+ if (!changeFieldsWithoutCheck)
+ PresetLoadDialog.this.checkValues();
+
+ }
+
+ @Override
+ public void removeUpdate(DocumentEvent e) {
+ if (!changeFieldsWithoutCheck)
+ PresetLoadDialog.this.checkValues();
+
+ }
+
+ @Override
+ public void changedUpdate(DocumentEvent e) {
+ if (!changeFieldsWithoutCheck)
+ PresetLoadDialog.this.checkValues();
+
+ }
+ });
+
+ }
+
+ protected boolean checkValues() {
+ String name;
+ try {
+ Long.parseLong(this.randomSeedField.getText());
+ } catch (NumberFormatException ex) {
+ invalidValues();
+ return false;
+ }
+ try {
+ name = this.parentGUI.getValidRequiredROMName(
+ this.configStringField.getText(), trainerClasses,
+ trainerNames, nicknames);
+ } catch (InvalidSupplementFilesException ex) {
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ changeFieldsWithoutCheck = true;
+ configStringField.setText("");
+ randomSeedField.setText("");
+ changeFieldsWithoutCheck = false;
+ }
+ });
+ invalidValues();
+ return false;
+ } catch (Exception ex) {
+ // other exception
+ ex.printStackTrace();
+ invalidValues();
+ return false;
+ }
+ if (name == null) {
+ invalidValues();
+ return false;
+ }
+ requiredName = name;
+ this.romRequiredLabel.setText("ROM Required: " + name);
+ this.romFileButton.setEnabled(true);
+
+ if (currentROM != null && currentROM.getROMName().equals(name) == false) {
+ this.currentROM = null;
+ this.acceptButton.setEnabled(false);
+ this.romFileField.setText("");
+ }
+ return true;
+ }
+
+ private void invalidValues() {
+ this.currentROM = null;
+ this.romFileField.setText("");
+ this.romRequiredLabel
+ .setText("ROM Required: Enter settings above first.");
+ this.romFileButton.setEnabled(false);
+ this.acceptButton.setEnabled(false);
+ this.requiredName = null;
+
+ }
+
+ public boolean isCompleted() {
+ return completed;
+ }
+
+ public RomHandler getROM() {
+ return currentROM;
+ }
+
+ public long getSeed() {
+ return Long.parseLong(this.randomSeedField.getText());
+ }
+
+ public String getConfigString() {
+ return this.configStringField.getText();
+ }
+
+ public byte[] getTrainerClasses() {
+ return trainerClasses;
+ }
+
+ public byte[] getTrainerNames() {
+ return trainerNames;
+ }
+
+ public byte[] getNicknames() {
+ return nicknames;
+ }
+
+ /**
+ * This method is called from within the constructor to initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is always
+ * regenerated by the Form Editor.
+ */
+ private void initComponents() {
+
+ presetFileChooser = new javax.swing.JFileChooser();
+ romFileChooser = new javax.swing.JFileChooser();
+ presetFileLabel = new javax.swing.JLabel();
+ presetFileField = new javax.swing.JTextField();
+ presetFileButton = new javax.swing.JButton();
+ jLabel1 = new javax.swing.JLabel();
+ jLabel2 = new javax.swing.JLabel();
+ randomSeedField = new javax.swing.JTextField();
+ jLabel3 = new javax.swing.JLabel();
+ configStringField = new javax.swing.JTextField();
+ romRequiredLabel = new javax.swing.JLabel();
+ jLabel5 = new javax.swing.JLabel();
+ romFileField = new javax.swing.JTextField();
+ romFileButton = new javax.swing.JButton();
+ acceptButton = new javax.swing.JButton();
+ cancelButton = new javax.swing.JButton();
+
+ presetFileChooser.setFileFilter(new PresetFileFilter());
+
+ romFileChooser.setFileFilter(new ROMFilter());
+
+ setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
+ setTitle("Use Premade Seed");
+ setModal(true);
+ setResizable(false);
+
+ presetFileLabel.setText("Seed File:");
+
+ presetFileField.setEditable(false);
+
+ presetFileButton.setText("...");
+ presetFileButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ presetFileButtonActionPerformed(evt);
+ }
+ });
+
+ jLabel1.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N
+ jLabel1.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
+ jLabel1.setText("-OR-");
+
+ jLabel2.setText("Random Seed:");
+
+ jLabel3.setText("Config String:");
+
+ romRequiredLabel
+ .setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
+ romRequiredLabel.setText("ROM Required: Enter settings above first.");
+
+ jLabel5.setText("Rom File:");
+
+ romFileField.setEditable(false);
+
+ romFileButton.setText("...");
+ romFileButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ romFileButtonActionPerformed(evt);
+ }
+ });
+
+ acceptButton.setText("Apply Randomization Settings");
+ acceptButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ acceptButtonActionPerformed(evt);
+ }
+ });
+
+ cancelButton.setText("Cancel");
+ cancelButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ cancelButtonActionPerformed(evt);
+ }
+ });
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(
+ getContentPane());
+ getContentPane().setLayout(layout);
+ layout.setHorizontalGroup(layout
+ .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(
+ layout.createParallelGroup(
+ javax.swing.GroupLayout.Alignment.TRAILING,
+ false)
+ .addComponent(
+ jLabel5,
+ javax.swing.GroupLayout.Alignment.LEADING,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)
+ .addComponent(
+ presetFileLabel,
+ javax.swing.GroupLayout.Alignment.LEADING,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)
+ .addComponent(
+ jLabel2,
+ javax.swing.GroupLayout.Alignment.LEADING,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)
+ .addComponent(
+ jLabel3,
+ javax.swing.GroupLayout.Alignment.LEADING,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE))
+ .addGap(18, 18, 18)
+ .addGroup(
+ layout.createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ layout.createSequentialGroup()
+ .addComponent(
+ acceptButton)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.RELATED,
+ 169,
+ Short.MAX_VALUE)
+ .addComponent(
+ cancelButton))
+ .addComponent(randomSeedField)
+ .addComponent(configStringField)
+ .addComponent(presetFileField)
+ .addComponent(romFileField))
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(
+ layout.createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING,
+ false)
+ .addComponent(
+ presetFileButton,
+ javax.swing.GroupLayout.PREFERRED_SIZE,
+ 26,
+ javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(
+ romFileButton,
+ javax.swing.GroupLayout.PREFERRED_SIZE,
+ 1, Short.MAX_VALUE))
+ .addGap(12, 12, 12))
+ .addComponent(jLabel1, javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(romRequiredLabel,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE));
+ layout.setVerticalGroup(layout
+ .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(
+ layout.createParallelGroup(
+ javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(presetFileLabel)
+ .addComponent(
+ presetFileField,
+ javax.swing.GroupLayout.PREFERRED_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(presetFileButton))
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(jLabel1)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(
+ layout.createParallelGroup(
+ javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(jLabel2)
+ .addComponent(
+ randomSeedField,
+ javax.swing.GroupLayout.PREFERRED_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addGroup(
+ layout.createParallelGroup(
+ javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(jLabel3)
+ .addComponent(
+ configStringField,
+ javax.swing.GroupLayout.PREFERRED_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(romRequiredLabel)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addGroup(
+ layout.createParallelGroup(
+ javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(jLabel5)
+ .addComponent(
+ romFileField,
+ javax.swing.GroupLayout.PREFERRED_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(romFileButton))
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.RELATED,
+ 23, Short.MAX_VALUE)
+ .addGroup(
+ layout.createParallelGroup(
+ javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(acceptButton)
+ .addComponent(cancelButton))
+ .addContainerGap()));
+
+ pack();
+ }// //GEN-END:initComponents
+
+ private void presetFileButtonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_presetFileButtonActionPerformed
+ presetFileChooser.setSelectedFile(null);
+ int returnVal = presetFileChooser.showOpenDialog(this);
+ if (returnVal == JFileChooser.APPROVE_OPTION) {
+ File fh = presetFileChooser.getSelectedFile();
+ try {
+ DataInputStream dis = new DataInputStream(new FileInputStream(
+ fh));
+ int checkByte = dis.readByte() & 0xFF;
+ if (checkByte != RandomizerGUI.PRESET_FILE_VERSION) {
+ dis.close();
+ JOptionPane
+ .showMessageDialog(this,
+ "This seed file is not for this version of the randomizer.");
+ return;
+ }
+ long seed = dis.readLong();
+ String preset = dis.readUTF();
+ int tclen = dis.readInt();
+ trainerClasses = new byte[tclen];
+ dis.read(trainerClasses);
+ int tnlen = dis.readInt();
+ trainerNames = new byte[tnlen];
+ dis.read(trainerNames);
+ int nnlen = dis.readInt();
+ nicknames = new byte[nnlen];
+ dis.read(nicknames);
+ changeFieldsWithoutCheck = true;
+ this.randomSeedField.setText(Long.toString(seed));
+ this.configStringField.setText(preset);
+ changeFieldsWithoutCheck = false;
+ if (checkValues()) {
+ this.randomSeedField.setEnabled(false);
+ this.configStringField.setEnabled(false);
+ this.presetFileField.setText(fh.getAbsolutePath());
+ } else {
+ this.randomSeedField.setText("");
+ this.configStringField.setText("");
+ this.randomSeedField.setEnabled(true);
+ this.configStringField.setEnabled(true);
+ this.presetFileField.setText("");
+ trainerClasses = null;
+ trainerNames = null;
+ JOptionPane.showMessageDialog(this,
+ "The seed file did not contain valid settings.");
+ }
+ dis.close();
+ } catch (IOException ex) {
+ JOptionPane.showMessageDialog(this,
+ "Could not load seed file.");
+ }
+ }
+ }// GEN-LAST:event_presetFileButtonActionPerformed
+
+ private void romFileButtonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_romFileButtonActionPerformed
+ romFileChooser.setSelectedFile(null);
+ int returnVal = romFileChooser.showOpenDialog(this);
+ if (returnVal == JFileChooser.APPROVE_OPTION) {
+ final File fh = romFileChooser.getSelectedFile();
+ for (RomHandler rh : parentGUI.checkHandlers) {
+ if (rh.detectRom(fh.getAbsolutePath())) {
+ final RomHandler checkHandler = rh;
+ final JDialog opDialog = new OperationDialog("Loading...",
+ this, true);
+ Thread t = new Thread() {
+ @Override
+ public void run() {
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ opDialog.setVisible(true);
+ }
+ });
+ try {
+ checkHandler.loadRom(fh.getAbsolutePath());
+ } catch (Exception ex) {
+ JOptionPane.showMessageDialog(
+ PresetLoadDialog.this,
+ "ROM load failed.");
+ }
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ opDialog.setVisible(false);
+ if (checkHandler.getROMName().equals(
+ requiredName)) {
+ // Got it
+ romFileField.setText(fh
+ .getAbsolutePath());
+ currentROM = checkHandler;
+ acceptButton.setEnabled(true);
+ return;
+ } else {
+ JOptionPane.showMessageDialog(
+ PresetLoadDialog.this,
+ "This isn't the required ROM.\nRequired: "
+ + requiredName
+ + "\nThis ROM: "
+ + checkHandler
+ .getROMName());
+ return;
+ }
+ }
+ });
+ }
+ };
+ t.start();
+ return;
+ }
+ }
+ JOptionPane.showMessageDialog(this,
+ "The file you specified isn't a valid Pokemon ROM.");
+ }
+ }// GEN-LAST:event_romFileButtonActionPerformed
+
+ private void acceptButtonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_acceptButtonActionPerformed
+ completed = true;
+ this.setVisible(false);
+ }// GEN-LAST:event_acceptButtonActionPerformed
+
+ private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_cancelButtonActionPerformed
+ completed = false;
+ this.setVisible(false);
+ }// GEN-LAST:event_cancelButtonActionPerformed
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JButton acceptButton;
+ private javax.swing.JButton cancelButton;
+ private javax.swing.JTextField configStringField;
+ private javax.swing.JLabel jLabel1;
+ private javax.swing.JLabel jLabel2;
+ private javax.swing.JLabel jLabel3;
+ private javax.swing.JLabel jLabel5;
+ private javax.swing.JButton presetFileButton;
+ private javax.swing.JFileChooser presetFileChooser;
+ private javax.swing.JTextField presetFileField;
+ private javax.swing.JLabel presetFileLabel;
+ private javax.swing.JTextField randomSeedField;
+ private javax.swing.JButton romFileButton;
+ private javax.swing.JFileChooser romFileChooser;
+ private javax.swing.JTextField romFileField;
+ private javax.swing.JLabel romRequiredLabel;
+ // End of variables declaration//GEN-END:variables
+}
diff --git a/src/com/dabomstew/pkrandom/gui/PresetMakeDialog.form b/src/com/dabomstew/pkrandom/gui/PresetMakeDialog.form
new file mode 100755
index 000000000..0277fb5f2
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/gui/PresetMakeDialog.form
@@ -0,0 +1,162 @@
+
+
+
diff --git a/src/com/dabomstew/pkrandom/gui/PresetMakeDialog.java b/src/com/dabomstew/pkrandom/gui/PresetMakeDialog.java
new file mode 100755
index 000000000..4a367cf33
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/gui/PresetMakeDialog.java
@@ -0,0 +1,239 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.dabomstew.pkrandom.gui;
+
+/*----------------------------------------------------------------------------*/
+/*-- PresetMakeDialog.java - a dialog to allow preset pairs to either be --*/
+/*-- copied down or saved to a binary file for --*/
+/*-- later use. --*/
+/*-- --*/
+/*-- Part of "Universal Pokemon Randomizer" by Dabomstew --*/
+/*-- Pokemon and any associated names and the like are --*/
+/*-- trademark and (C) Nintendo 1996-2012. --*/
+/*-- --*/
+/*-- The custom code written here is licensed under the terms of the GPL: --*/
+/*-- --*/
+/*-- This program is free software: you can redistribute it and/or modify --*/
+/*-- it under the terms of the GNU General Public License as published by --*/
+/*-- the Free Software Foundation, either version 3 of the License, or --*/
+/*-- (at your option) any later version. --*/
+/*-- --*/
+/*-- This program is distributed in the hope that it will be useful, --*/
+/*-- but WITHOUT ANY WARRANTY; without even the implied warranty of --*/
+/*-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --*/
+/*-- GNU General Public License for more details. --*/
+/*-- --*/
+/*-- You should have received a copy of the GNU General Public License --*/
+/*-- along with this program. If not, see . --*/
+/*----------------------------------------------------------------------------*/
+
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.swing.JFileChooser;
+import javax.swing.JOptionPane;
+
+import com.dabomstew.pkrandom.FileFunctions;
+
+/**
+ *
+ * @author Stewart
+ */
+public class PresetMakeDialog extends javax.swing.JDialog {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 7663903108783731673L;
+ private long seed;
+ private String configString;
+
+ /**
+ * Creates new form PresetMakeDialog
+ */
+ public PresetMakeDialog(java.awt.Frame parent, long seed,
+ String configString) {
+ super(parent, true);
+ initComponents();
+ randomSeedField.setText(Long.toString(seed));
+ configStringField.setText(configString);
+ this.seed = seed;
+ this.configString = configString;
+ presetFileChooser.setCurrentDirectory(new File("./"));
+ setLocationRelativeTo(parent);
+ setVisible(true);
+ }
+
+ /**
+ * This method is called from within the constructor to initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is always
+ * regenerated by the Form Editor.
+ */
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ presetFileChooser = new javax.swing.JFileChooser();
+ jLabel1 = new javax.swing.JLabel();
+ jLabel2 = new javax.swing.JLabel();
+ jLabel3 = new javax.swing.JLabel();
+ randomSeedField = new javax.swing.JTextField();
+ jLabel4 = new javax.swing.JLabel();
+ configStringField = new javax.swing.JTextField();
+ jLabel5 = new javax.swing.JLabel();
+ produceFileButton = new javax.swing.JButton();
+ doneButton = new javax.swing.JButton();
+
+ presetFileChooser.setFileFilter(new PresetFileFilter());
+
+ setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
+ java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("com/dabomstew/pkrandom/gui/Bundle"); // NOI18N
+ setTitle(bundle.getString("PresetMakeDialog.title")); // NOI18N
+ setModal(true);
+ setResizable(false);
+
+ jLabel1.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
+ jLabel1.setText(bundle.getString("PresetMakeDialog.jLabel1.text")); // NOI18N
+
+ jLabel2.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
+ jLabel2.setText(bundle.getString("PresetMakeDialog.jLabel2.text")); // NOI18N
+
+ jLabel3.setText(bundle.getString("PresetMakeDialog.jLabel3.text")); // NOI18N
+
+ randomSeedField.setEditable(false);
+
+ jLabel4.setText(bundle.getString("PresetMakeDialog.jLabel4.text")); // NOI18N
+
+ configStringField.setEditable(false);
+
+ jLabel5.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
+ jLabel5.setText(bundle.getString("PresetMakeDialog.jLabel5.text")); // NOI18N
+
+ produceFileButton.setText(bundle.getString("PresetMakeDialog.produceFileButton.text")); // NOI18N
+ produceFileButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ produceFileButtonActionPerformed(evt);
+ }
+ });
+
+ doneButton.setText(bundle.getString("PresetMakeDialog.doneButton.text")); // NOI18N
+ doneButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ doneButtonActionPerformed(evt);
+ }
+ });
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
+ getContentPane().setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(jLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(jLabel2, javax.swing.GroupLayout.DEFAULT_SIZE, 599, Short.MAX_VALUE)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(jLabel3)
+ .addComponent(jLabel4))
+ .addGap(18, 18, 18)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(randomSeedField)
+ .addComponent(configStringField))
+ .addContainerGap())
+ .addComponent(jLabel5, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addGroup(layout.createSequentialGroup()
+ .addGap(67, 67, 67)
+ .addComponent(produceFileButton)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(doneButton)
+ .addGap(66, 66, 66))
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(jLabel1)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(jLabel2)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(jLabel3)
+ .addComponent(randomSeedField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(jLabel4)
+ .addComponent(configStringField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(jLabel5)
+ .addGap(18, 18, 18)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(produceFileButton)
+ .addComponent(doneButton))
+ .addGap(0, 11, Short.MAX_VALUE))
+ );
+
+ pack();
+ }// //GEN-END:initComponents
+
+ private void produceFileButtonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_produceFileButtonActionPerformed
+ presetFileChooser.setSelectedFile(null);
+ int returnVal = presetFileChooser.showSaveDialog(this);
+ if (returnVal == JFileChooser.APPROVE_OPTION) {
+ File fh = presetFileChooser.getSelectedFile();
+ // Fix extension?
+ fh = FileFunctions.fixFilename(fh, "rndp");
+ try {
+ DataOutputStream dos = new DataOutputStream(
+ new FileOutputStream(fh));
+ dos.writeByte((byte)RandomizerGUI.PRESET_FILE_VERSION);
+ dos.writeLong(seed);
+ dos.writeUTF(configString);
+ byte[] trainerclasses = readFile(FileFunctions
+ .openConfig("trainerclasses.txt"));
+ dos.writeInt(trainerclasses.length);
+ dos.write(trainerclasses);
+ byte[] trainernames = readFile(FileFunctions
+ .openConfig("trainernames.txt"));
+ dos.writeInt(trainernames.length);
+ dos.write(trainernames);
+ byte[] nicknames = readFile(FileFunctions
+ .openConfig("nicknames.txt"));
+ dos.writeInt(nicknames.length);
+ dos.write(nicknames);
+ dos.close();
+ JOptionPane.showMessageDialog(this, "Preset file saved to\n"
+ + fh.getAbsolutePath());
+ } catch (IOException ex) {
+ JOptionPane.showMessageDialog(this,
+ "Could not save the preset file.");
+ }
+ }
+ }// GEN-LAST:event_produceFileButtonActionPerformed
+
+ protected static byte[] readFile(InputStream is) throws IOException {
+ byte[] file = new byte[is.available()];
+ is.read(file);
+ is.close();
+ return file;
+ }
+
+ private void doneButtonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_doneButtonActionPerformed
+ this.setVisible(false);
+ }// GEN-LAST:event_doneButtonActionPerformed
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JTextField configStringField;
+ private javax.swing.JButton doneButton;
+ private javax.swing.JLabel jLabel1;
+ private javax.swing.JLabel jLabel2;
+ private javax.swing.JLabel jLabel3;
+ private javax.swing.JLabel jLabel4;
+ private javax.swing.JLabel jLabel5;
+ private javax.swing.JFileChooser presetFileChooser;
+ private javax.swing.JButton produceFileButton;
+ private javax.swing.JTextField randomSeedField;
+ // End of variables declaration//GEN-END:variables
+}
diff --git a/src/com/dabomstew/pkrandom/gui/QSFileFilter.java b/src/com/dabomstew/pkrandom/gui/QSFileFilter.java
new file mode 100755
index 000000000..f578de71f
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/gui/QSFileFilter.java
@@ -0,0 +1,57 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.dabomstew.pkrandom.gui;
+
+/*----------------------------------------------------------------------------*/
+/*-- PresetFileFilter.java - a file filter for the "randomization presets" --*/
+/*-- which allow the same random ROM to be produced--*/
+/*-- on demand. --*/
+/*-- --*/
+/*-- Part of "Universal Pokemon Randomizer" by Dabomstew --*/
+/*-- Pokemon and any associated names and the like are --*/
+/*-- trademark and (C) Nintendo 1996-2012. --*/
+/*-- --*/
+/*-- The custom code written here is licensed under the terms of the GPL: --*/
+/*-- --*/
+/*-- This program is free software: you can redistribute it and/or modify --*/
+/*-- it under the terms of the GNU General Public License as published by --*/
+/*-- the Free Software Foundation, either version 3 of the License, or --*/
+/*-- (at your option) any later version. --*/
+/*-- --*/
+/*-- This program is distributed in the hope that it will be useful, --*/
+/*-- but WITHOUT ANY WARRANTY; without even the implied warranty of --*/
+/*-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --*/
+/*-- GNU General Public License for more details. --*/
+/*-- --*/
+/*-- You should have received a copy of the GNU General Public License --*/
+/*-- along with this program. If not, see . --*/
+/*----------------------------------------------------------------------------*/
+
+import java.io.File;
+
+import javax.swing.filechooser.FileFilter;
+
+public class QSFileFilter extends FileFilter {
+
+ @Override
+ public boolean accept(File arg0) {
+ if (arg0.isDirectory()) {
+ return true; // needed to allow directory navigation
+ }
+ String filename = arg0.getName();
+ if (filename.contains(".") == false) {
+ return false;
+ }
+ String extension = arg0.getName().substring(
+ arg0.getName().lastIndexOf('.') + 1);
+ return extension.toLowerCase().equals("rnqs");
+ }
+
+ @Override
+ public String getDescription() {
+ return "Randomization Quick Settings (*.rnqs)";
+ }
+
+}
diff --git a/src/com/dabomstew/pkrandom/gui/ROMFilter.java b/src/com/dabomstew/pkrandom/gui/ROMFilter.java
new file mode 100755
index 000000000..cbfe411e6
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/gui/ROMFilter.java
@@ -0,0 +1,58 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.dabomstew.pkrandom.gui;
+
+/*----------------------------------------------------------------------------*/
+/*-- ROMFilter.java - a file filter for the various games which can be --*/
+/*-- randomized with this program. --*/
+/*-- --*/
+/*-- Part of "Universal Pokemon Randomizer" by Dabomstew --*/
+/*-- Pokemon and any associated names and the like are --*/
+/*-- trademark and (C) Nintendo 1996-2012. --*/
+/*-- --*/
+/*-- The custom code written here is licensed under the terms of the GPL: --*/
+/*-- --*/
+/*-- This program is free software: you can redistribute it and/or modify --*/
+/*-- it under the terms of the GNU General Public License as published by --*/
+/*-- the Free Software Foundation, either version 3 of the License, or --*/
+/*-- (at your option) any later version. --*/
+/*-- --*/
+/*-- This program is distributed in the hope that it will be useful, --*/
+/*-- but WITHOUT ANY WARRANTY; without even the implied warranty of --*/
+/*-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --*/
+/*-- GNU General Public License for more details. --*/
+/*-- --*/
+/*-- You should have received a copy of the GNU General Public License --*/
+/*-- along with this program. If not, see . --*/
+/*----------------------------------------------------------------------------*/
+
+import java.io.File;
+
+import javax.swing.filechooser.FileFilter;
+
+public class ROMFilter extends FileFilter {
+
+ @Override
+ public boolean accept(File arg0) {
+ if (arg0.isDirectory()) {
+ return true; // needed to allow directory navigation
+ }
+ String filename = arg0.getName();
+ if (filename.contains(".") == false) {
+ return false;
+ }
+ String extension = arg0.getName()
+ .substring(arg0.getName().lastIndexOf('.') + 1).toLowerCase();
+ return extension.equals("gb") || extension.equals("sgb")
+ || extension.equals("gbc") || extension.equals("gba")
+ || extension.equals("nds");
+ }
+
+ @Override
+ public String getDescription() {
+ return "Nintendo GB(C/A)/DS ROM File (*.gb,*.sgb,*.gbc,*.gba,*.nds)";
+ }
+
+}
diff --git a/src/com/dabomstew/pkrandom/gui/RandomizerGUI.form b/src/com/dabomstew/pkrandom/gui/RandomizerGUI.form
new file mode 100755
index 000000000..643300a4d
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/gui/RandomizerGUI.form
@@ -0,0 +1,2449 @@
+
+
+
diff --git a/src/com/dabomstew/pkrandom/gui/RandomizerGUI.java b/src/com/dabomstew/pkrandom/gui/RandomizerGUI.java
new file mode 100755
index 000000000..42190fdc5
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/gui/RandomizerGUI.java
@@ -0,0 +1,5307 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.dabomstew.pkrandom.gui;
+
+/*----------------------------------------------------------------------------*/
+/*-- RandomizerGUI.java - the main GUI for the randomizer, containing the --*/
+/*-- various options available and such. --*/
+/*-- --*/
+/*-- Part of "Universal Pokemon Randomizer" by Dabomstew --*/
+/*-- Pokemon and any associated names and the like are --*/
+/*-- trademark and (C) Nintendo 1996-2012. --*/
+/*-- --*/
+/*-- The custom code written here is licensed under the terms of the GPL: --*/
+/*-- --*/
+/*-- This program is free software: you can redistribute it and/or modify --*/
+/*-- it under the terms of the GNU General Public License as published by --*/
+/*-- the Free Software Foundation, either version 3 of the License, or --*/
+/*-- (at your option) any later version. --*/
+/*-- --*/
+/*-- This program is distributed in the hope that it will be useful, --*/
+/*-- but WITHOUT ANY WARRANTY; without even the implied warranty of --*/
+/*-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --*/
+/*-- GNU General Public License for more details. --*/
+/*-- --*/
+/*-- You should have received a copy of the GNU General Public License --*/
+/*-- along with this program. If not, see . --*/
+/*----------------------------------------------------------------------------*/
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintStream;
+import java.io.UnsupportedEncodingException;
+import java.net.URL;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Scanner;
+import java.util.TreeMap;
+import java.util.zip.CRC32;
+
+import javax.swing.AbstractButton;
+import javax.swing.DefaultComboBoxModel;
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JFileChooser;
+import javax.swing.JOptionPane;
+import javax.swing.SwingUtilities;
+import javax.xml.bind.DatatypeConverter;
+
+import com.dabomstew.pkrandom.CodeTweaks;
+import com.dabomstew.pkrandom.FileFunctions;
+import com.dabomstew.pkrandom.RandomSource;
+import com.dabomstew.pkrandom.pokemon.Encounter;
+import com.dabomstew.pkrandom.pokemon.EncounterSet;
+import com.dabomstew.pkrandom.pokemon.GenRestrictions;
+import com.dabomstew.pkrandom.pokemon.IngameTrade;
+import com.dabomstew.pkrandom.pokemon.Move;
+import com.dabomstew.pkrandom.pokemon.MoveLearnt;
+import com.dabomstew.pkrandom.pokemon.Pokemon;
+import com.dabomstew.pkrandom.pokemon.Trainer;
+import com.dabomstew.pkrandom.pokemon.TrainerPokemon;
+import com.dabomstew.pkrandom.romhandlers.AbstractDSRomHandler;
+import com.dabomstew.pkrandom.romhandlers.Gen1RomHandler;
+import com.dabomstew.pkrandom.romhandlers.Gen2RomHandler;
+import com.dabomstew.pkrandom.romhandlers.Gen3RomHandler;
+import com.dabomstew.pkrandom.romhandlers.Gen4RomHandler;
+import com.dabomstew.pkrandom.romhandlers.Gen5RomHandler;
+import com.dabomstew.pkrandom.romhandlers.RomHandler;
+
+/**
+ *
+ * @author Stewart
+ */
+public class RandomizerGUI extends javax.swing.JFrame {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 637989089525556154L;
+ private RomHandler romHandler;
+ protected RomHandler[] checkHandlers;
+ public static final int PRESET_FILE_VERSION = 160;
+ public static final int UPDATE_VERSION = 1602;
+
+ public static PrintStream verboseLog = System.out;
+
+ private OperationDialog opDialog;
+ private boolean presetMode;
+ private GenRestrictions currentRestrictions;
+ private int currentCodeTweaks;
+
+ private static String rootPath = "./";
+
+ // Settings
+ private boolean autoUpdateEnabled;
+ private boolean haveCheckedCustomNames;
+
+ java.util.ResourceBundle bundle;
+
+ /**
+ * @param args
+ * the command line arguments
+ */
+ public static void main(String args[]) {
+ boolean autoupdate = true;
+ for (String arg : args) {
+ if (arg.equalsIgnoreCase("--noupdate")) {
+ autoupdate = false;
+ break;
+ }
+ }
+ final boolean au = autoupdate;
+ try {
+ javax.swing.UIManager.setLookAndFeel(javax.swing.UIManager
+ .getSystemLookAndFeelClassName());
+ } catch (ClassNotFoundException ex) {
+ java.util.logging.Logger.getLogger(RandomizerGUI.class.getName())
+ .log(java.util.logging.Level.SEVERE, null, ex);
+ } catch (InstantiationException ex) {
+ java.util.logging.Logger.getLogger(RandomizerGUI.class.getName())
+ .log(java.util.logging.Level.SEVERE, null, ex);
+ } catch (IllegalAccessException ex) {
+ java.util.logging.Logger.getLogger(RandomizerGUI.class.getName())
+ .log(java.util.logging.Level.SEVERE, null, ex);
+ } catch (javax.swing.UnsupportedLookAndFeelException ex) {
+ java.util.logging.Logger.getLogger(RandomizerGUI.class.getName())
+ .log(java.util.logging.Level.SEVERE, null, ex);
+ }
+
+ /* Create and display the form */
+ java.awt.EventQueue.invokeLater(new Runnable() {
+ public void run() {
+ new RandomizerGUI(au);
+ }
+ });
+ }
+
+ // constructor
+ /**
+ * Creates new form RandomizerGUI
+ *
+ * @param autoupdate
+ */
+ public RandomizerGUI(boolean autoupdate) {
+
+ try {
+ URL location = RandomizerGUI.class.getProtectionDomain()
+ .getCodeSource().getLocation();
+ File fh = new File(java.net.URLDecoder.decode(location.getFile(),
+ "UTF-8")).getParentFile();
+ rootPath = fh.getAbsolutePath() + File.separator;
+ } catch (Exception e) {
+ rootPath = "./";
+ }
+
+ bundle = java.util.ResourceBundle
+ .getBundle("com/dabomstew/pkrandom/gui/Bundle"); // NOI18N
+ testForRequiredConfigs();
+ checkHandlers = new RomHandler[] { new Gen1RomHandler(),
+ new Gen2RomHandler(), new Gen3RomHandler(),
+ new Gen4RomHandler(), new Gen5RomHandler() };
+ initComponents();
+ initialiseState();
+ autoUpdateEnabled = true;
+ haveCheckedCustomNames = false;
+ attemptReadConfig();
+ if (!autoupdate) {
+ // override autoupdate
+ autoUpdateEnabled = false;
+ }
+ boolean canWrite = attemptWriteConfig();
+ if (!canWrite) {
+ JOptionPane.showMessageDialog(null,
+ bundle.getString("RandomizerGUI.cantWriteConfigFile"));
+ autoUpdateEnabled = false;
+ }
+ setLocationRelativeTo(null);
+ setVisible(true);
+ checkCustomNames();
+ if (autoUpdateEnabled) {
+ new UpdateCheckThread(this, false).start();
+ }
+ }
+
+ // config-related stuff
+
+ private void checkCustomNames() {
+ String[] cnamefiles = new String[] { "trainerclasses.txt",
+ "trainernames.txt", "nicknames.txt" };
+ int[] defaultcsums = new int[] { -1442281799, -1499590809, 1641673648 };
+
+ boolean foundCustom = false;
+ for (int file = 0; file < 3; file++) {
+ File oldFile = new File(rootPath + "/config/" + cnamefiles[file]);
+ File currentFile = new File(rootPath + cnamefiles[file]);
+ if (oldFile.exists() && oldFile.canRead() && !currentFile.exists()) {
+ try {
+ int crc = getFileChecksum(new FileInputStream(oldFile));
+ if (crc != defaultcsums[file]) {
+ foundCustom = true;
+ break;
+ }
+ } catch (FileNotFoundException e) {
+ }
+ }
+ }
+
+ if (foundCustom) {
+ int response = JOptionPane
+ .showConfirmDialog(
+ RandomizerGUI.this,
+ bundle.getString("RandomizerGUI.copyNameFilesDialog.text"),
+ bundle.getString("RandomizerGUI.copyNameFilesDialog.title"),
+ JOptionPane.YES_NO_OPTION);
+ boolean onefailed = false;
+ if (response == JOptionPane.YES_OPTION) {
+ for (String filename : cnamefiles) {
+ if (new File(rootPath + "/config/" + filename).canRead()) {
+ try {
+ FileInputStream fis = new FileInputStream(new File(
+ rootPath + "config/" + filename));
+ FileOutputStream fos = new FileOutputStream(
+ new File(rootPath + filename));
+ byte[] buf = new byte[1024];
+ int len;
+ while ((len = fis.read(buf)) > 0) {
+ fos.write(buf, 0, len);
+ }
+ fos.close();
+ fis.close();
+ } catch (IOException ex) {
+ onefailed = true;
+ }
+ }
+ }
+ if (onefailed) {
+ JOptionPane.showMessageDialog(this, bundle
+ .getString("RandomizerGUI.copyNameFilesFailed"));
+ }
+ }
+ }
+
+ haveCheckedCustomNames = true;
+ attemptWriteConfig();
+ }
+
+ private void attemptReadConfig() {
+ File fh = new File(rootPath + "config.ini");
+ if (!fh.exists() || !fh.canRead()) {
+ return;
+ }
+
+ try {
+ Scanner sc = new Scanner(fh, "UTF-8");
+ while (sc.hasNextLine()) {
+ String q = sc.nextLine().trim();
+ if (q.contains("//")) {
+ q = q.substring(0, q.indexOf("//")).trim();
+ }
+ if (!q.isEmpty()) {
+ String[] tokens = q.split("=", 2);
+ if (tokens.length == 2) {
+ String key = tokens[0].trim();
+ if (key.equalsIgnoreCase("autoupdate")) {
+ autoUpdateEnabled = Boolean.parseBoolean(tokens[1]
+ .trim());
+ } else if (key.equalsIgnoreCase("checkedcustomnames")) {
+ haveCheckedCustomNames = Boolean
+ .parseBoolean(tokens[1].trim());
+ }
+ }
+ }
+ }
+ sc.close();
+ } catch (IOException ex) {
+
+ }
+ }
+
+ private boolean attemptWriteConfig() {
+ File fh = new File(rootPath + "config.ini");
+ if (fh.exists() && !fh.canWrite()) {
+ return false;
+ }
+
+ try {
+ PrintStream ps = new PrintStream(new FileOutputStream(fh), true,
+ "UTF-8");
+ ps.println("autoupdate=" + autoUpdateEnabled);
+ ps.println("checkedcustomnames=" + haveCheckedCustomNames);
+ ps.close();
+ return true;
+ } catch (IOException e) {
+ return false;
+ }
+
+ }
+
+ private void testForRequiredConfigs() {
+ String[] required = new String[] { "gameboy_jap.tbl",
+ "rby_english.tbl", "rby_freger.tbl", "rby_espita.tbl",
+ "green_translation.tbl", "gsc_english.tbl", "gsc_freger.tbl",
+ "gsc_espita.tbl", "gba_english.tbl", "gba_jap.tbl",
+ "Generation4.tbl", "Generation5.tbl", "gen1_offsets.ini",
+ "gen2_offsets.ini", "gen3_offsets.ini", "gen4_offsets.ini",
+ "gen5_offsets.ini", "trainerclasses.txt", "trainernames.txt",
+ "nicknames.txt" };
+ for (String filename : required) {
+ if (!FileFunctions.configExists(filename)) {
+ JOptionPane.showMessageDialog(null, String.format(
+ bundle.getString("RandomizerGUI.configFileMissing"),
+ filename));
+ System.exit(1);
+ return;
+ }
+ }
+ }
+
+ // form initial state
+
+ private void initialiseState() {
+ this.romHandler = null;
+ this.currentRestrictions = null;
+ this.currentCodeTweaks = 0;
+ updateCodeTweaksButtonText();
+ initialFormState();
+ this.romOpenChooser.setCurrentDirectory(new File(rootPath));
+ this.romSaveChooser.setCurrentDirectory(new File(rootPath));
+ if (new File(rootPath + "settings/").exists()) {
+ this.qsOpenChooser.setCurrentDirectory(new File(rootPath
+ + "settings/"));
+ this.qsSaveChooser.setCurrentDirectory(new File(rootPath
+ + "settings/"));
+ } else {
+ this.qsOpenChooser.setCurrentDirectory(new File(rootPath));
+ this.qsSaveChooser.setCurrentDirectory(new File(rootPath));
+ }
+ }
+
+ private void initialFormState() {
+ // Disable all rom components
+ this.goRemoveTradeEvosCheckBox.setEnabled(false);
+ this.goUpdateMovesCheckBox.setEnabled(false);
+ this.goUpdateMovesLegacyCheckBox.setEnabled(false);
+ this.goUpdateTypesCheckBox.setEnabled(false);
+ this.goLowerCaseNamesCheckBox.setEnabled(false);
+ this.goNationalDexCheckBox.setEnabled(false);
+
+ this.goRemoveTradeEvosCheckBox.setSelected(false);
+ this.goUpdateMovesCheckBox.setSelected(false);
+ this.goUpdateMovesLegacyCheckBox.setSelected(false);
+ this.goUpdateTypesCheckBox.setSelected(false);
+ this.goLowerCaseNamesCheckBox.setSelected(false);
+ this.goNationalDexCheckBox.setSelected(false);
+
+ this.goUpdateMovesLegacyCheckBox.setVisible(true);
+
+ this.codeTweaksCB.setEnabled(false);
+ this.codeTweaksCB.setSelected(false);
+ this.codeTweaksBtn.setEnabled(false);
+ this.codeTweaksBtn.setVisible(true);
+ this.codeTweaksCB.setVisible(true);
+ this.pokeLimitCB.setEnabled(false);
+ this.pokeLimitCB.setSelected(false);
+ this.pokeLimitBtn.setEnabled(false);
+ this.pokeLimitBtn.setVisible(true);
+ this.pokeLimitCB.setVisible(true);
+ this.raceModeCB.setEnabled(false);
+ this.raceModeCB.setSelected(false);
+ this.randomizeHollowsCB.setEnabled(false);
+ this.randomizeHollowsCB.setSelected(false);
+ this.brokenMovesCB.setEnabled(false);
+ this.brokenMovesCB.setSelected(false);
+
+ this.riRomNameLabel.setText(bundle
+ .getString("RandomizerGUI.noRomLoaded"));
+ this.riRomCodeLabel.setText("");
+ this.riRomSupportLabel.setText("");
+
+ this.loadQSButton.setEnabled(false);
+ this.saveQSButton.setEnabled(false);
+
+ this.pbsChangesUnchangedRB.setEnabled(false);
+ this.pbsChangesRandomEvosRB.setEnabled(false);
+ this.pbsChangesRandomTotalRB.setEnabled(false);
+ this.pbsChangesShuffleRB.setEnabled(false);
+ this.pbsChangesUnchangedRB.setSelected(true);
+ this.pbsStandardEXPCurvesCB.setEnabled(false);
+ this.pbsStandardEXPCurvesCB.setSelected(false);
+
+ this.abilitiesPanel.setVisible(true);
+ this.paUnchangedRB.setEnabled(false);
+ this.paRandomizeRB.setEnabled(false);
+ this.paWonderGuardCB.setEnabled(false);
+ this.paUnchangedRB.setSelected(true);
+ this.paWonderGuardCB.setSelected(false);
+
+ this.spCustomPoke1Chooser.setEnabled(false);
+ this.spCustomPoke2Chooser.setEnabled(false);
+ this.spCustomPoke3Chooser.setEnabled(false);
+ this.spCustomPoke1Chooser.setSelectedIndex(0);
+ this.spCustomPoke1Chooser.setModel(new DefaultComboBoxModel(
+ new String[] { "--" }));
+ this.spCustomPoke2Chooser.setSelectedIndex(0);
+ this.spCustomPoke2Chooser.setModel(new DefaultComboBoxModel(
+ new String[] { "--" }));
+ this.spCustomPoke3Chooser.setSelectedIndex(0);
+ this.spCustomPoke3Chooser.setModel(new DefaultComboBoxModel(
+ new String[] { "--" }));
+ this.spCustomRB.setEnabled(false);
+ this.spRandomRB.setEnabled(false);
+ this.spRandom2EvosRB.setEnabled(false);
+ this.spUnchangedRB.setEnabled(false);
+ this.spUnchangedRB.setSelected(true);
+ this.spHeldItemsCB.setEnabled(false);
+ this.spHeldItemsCB.setSelected(false);
+ this.spHeldItemsCB.setVisible(true);
+
+ this.pmsRandomTotalRB.setEnabled(false);
+ this.pmsRandomTypeRB.setEnabled(false);
+ this.pmsUnchangedRB.setEnabled(false);
+ this.pmsUnchangedRB.setSelected(true);
+ this.pmsMetronomeOnlyRB.setEnabled(false);
+ this.pms4MovesCB.setEnabled(false);
+ this.pms4MovesCB.setSelected(false);
+ this.pms4MovesCB.setVisible(true);
+
+ this.ptRandomFollowEvosRB.setEnabled(false);
+ this.ptRandomTotalRB.setEnabled(false);
+ this.ptUnchangedRB.setEnabled(false);
+ this.ptUnchangedRB.setSelected(true);
+
+ this.tpPowerLevelsCB.setEnabled(false);
+ this.tpRandomRB.setEnabled(false);
+ this.tpRivalCarriesStarterCB.setEnabled(false);
+ this.tpTypeThemedRB.setEnabled(false);
+ this.tpTypeWeightingCB.setEnabled(false);
+ this.tpNoLegendariesCB.setEnabled(false);
+ this.tpNoEarlyShedinjaCB.setEnabled(false);
+ this.tpNoEarlyShedinjaCB.setVisible(true);
+ this.tpUnchangedRB.setEnabled(false);
+ this.tpUnchangedRB.setSelected(true);
+ this.tpPowerLevelsCB.setSelected(false);
+ this.tpRivalCarriesStarterCB.setSelected(false);
+ this.tpTypeWeightingCB.setSelected(false);
+ this.tpNoLegendariesCB.setSelected(false);
+ this.tpNoEarlyShedinjaCB.setSelected(false);
+
+ this.tnRandomizeCB.setEnabled(false);
+ this.tcnRandomizeCB.setEnabled(false);
+
+ this.tnRandomizeCB.setSelected(false);
+ this.tcnRandomizeCB.setSelected(false);
+
+ this.wpUnchangedRB.setEnabled(false);
+ this.wpRandomRB.setEnabled(false);
+ this.wpArea11RB.setEnabled(false);
+ this.wpGlobalRB.setEnabled(false);
+ this.wpUnchangedRB.setSelected(true);
+
+ this.wpARNoneRB.setEnabled(false);
+ this.wpARCatchEmAllRB.setEnabled(false);
+ this.wpARTypeThemedRB.setEnabled(false);
+ this.wpARSimilarStrengthRB.setEnabled(false);
+ this.wpARNoneRB.setSelected(true);
+
+ this.wpUseTimeCB.setEnabled(false);
+ this.wpUseTimeCB.setVisible(true);
+ this.wpUseTimeCB.setSelected(false);
+
+ this.wpNoLegendariesCB.setEnabled(false);
+ this.wpNoLegendariesCB.setSelected(false);
+
+ this.wpCatchRateCB.setEnabled(false);
+ this.wpCatchRateCB.setSelected(false);
+
+ this.wpHeldItemsCB.setEnabled(false);
+ this.wpHeldItemsCB.setSelected(false);
+ this.wpHeldItemsCB.setVisible(true);
+
+ this.stpRandomL4LRB.setEnabled(false);
+ this.stpRandomTotalRB.setEnabled(false);
+ this.stpUnchangedRB.setEnabled(false);
+ this.stpUnchangedRB.setSelected(true);
+
+ this.tmmRandomRB.setEnabled(false);
+ this.tmmUnchangedRB.setEnabled(false);
+ this.tmmUnchangedRB.setSelected(true);
+
+ this.thcRandomTotalRB.setEnabled(false);
+ this.thcRandomTypeRB.setEnabled(false);
+ this.thcUnchangedRB.setEnabled(false);
+ this.thcUnchangedRB.setSelected(true);
+
+ this.mtmRandomRB.setEnabled(false);
+ this.mtmUnchangedRB.setEnabled(false);
+ this.mtmUnchangedRB.setSelected(true);
+
+ this.mtcRandomTotalRB.setEnabled(false);
+ this.mtcRandomTypeRB.setEnabled(false);
+ this.mtcUnchangedRB.setEnabled(false);
+ this.mtcUnchangedRB.setSelected(true);
+
+ this.mtMovesPanel.setVisible(true);
+ this.mtCompatPanel.setVisible(true);
+ this.mtNoExistLabel.setVisible(false);
+
+ this.igtUnchangedRB.setEnabled(false);
+ this.igtGivenOnlyRB.setEnabled(false);
+ this.igtBothRB.setEnabled(false);
+ this.igtUnchangedRB.setSelected(true);
+
+ this.igtRandomItemCB.setEnabled(false);
+ this.igtRandomItemCB.setSelected(false);
+ this.igtRandomItemCB.setVisible(true);
+
+ this.igtRandomIVsCB.setEnabled(false);
+ this.igtRandomIVsCB.setSelected(false);
+ this.igtRandomIVsCB.setVisible(true);
+
+ this.igtRandomOTCB.setEnabled(false);
+ this.igtRandomOTCB.setSelected(false);
+ this.igtRandomOTCB.setVisible(true);
+
+ this.igtRandomNicknameCB.setEnabled(false);
+ this.igtRandomNicknameCB.setSelected(false);
+
+ this.fiUnchangedRB.setEnabled(false);
+ this.fiShuffleRB.setEnabled(false);
+ this.fiRandomRB.setEnabled(false);
+ this.fiUnchangedRB.setSelected(true);
+
+ }
+
+ // rom loading
+
+ private void loadROM() {
+ romOpenChooser.setSelectedFile(null);
+ int returnVal = romOpenChooser.showOpenDialog(this);
+ if (returnVal == JFileChooser.APPROVE_OPTION) {
+ final File fh = romOpenChooser.getSelectedFile();
+ // first, check for common filetypes that aren't ROMs
+ // read first 10 bytes of the file to do this
+ try {
+ FileInputStream fis = new FileInputStream(fh);
+ byte[] sig = new byte[10];
+ int siglen = fis.read(sig);
+ fis.close();
+ if (siglen < 10) {
+ JOptionPane.showMessageDialog(this, String.format(
+ bundle.getString("RandomizerGUI.tooShortToBeARom"),
+ fh.getName()));
+ return;
+ }
+ if (sig[0] == 0x50 && sig[1] == 0x4b && sig[2] == 0x03
+ && sig[3] == 0x04) {
+ JOptionPane.showMessageDialog(this, String.format(
+ bundle.getString("RandomizerGUI.openedZIPfile"),
+ fh.getName()));
+ return;
+ }
+ if (sig[0] == 0x52 && sig[1] == 0x61 && sig[2] == 0x72
+ && sig[3] == 0x21 && sig[4] == 0x1A && sig[5] == 0x07) {
+ JOptionPane.showMessageDialog(this, String.format(
+ bundle.getString("RandomizerGUI.openedRARfile"),
+ fh.getName()));
+ return;
+ }
+ if (sig[0] == 'P' && sig[1] == 'A' && sig[2] == 'T'
+ && sig[3] == 'C' && sig[4] == 'H') {
+ JOptionPane.showMessageDialog(this, String.format(
+ bundle.getString("RandomizerGUI.openedIPSfile"),
+ fh.getName()));
+ return;
+ }
+ // none of these? let's see if it's a valid ROM, then
+ } catch (IOException ex) {
+ JOptionPane.showMessageDialog(this, String.format(
+ bundle.getString("RandomizerGUI.unreadableRom"),
+ fh.getName()));
+ return;
+ }
+ for (RomHandler rh : checkHandlers) {
+ if (rh.detectRom(fh.getAbsolutePath())) {
+ this.romHandler = rh;
+ opDialog = new OperationDialog(
+ bundle.getString("RandomizerGUI.loadingText"),
+ this, true);
+ Thread t = new Thread() {
+ @Override
+ public void run() {
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ opDialog.setVisible(true);
+ }
+ });
+ try {
+ RandomizerGUI.this.romHandler.loadRom(fh
+ .getAbsolutePath());
+ } catch (Exception ex) {
+ long time = System.currentTimeMillis();
+ try {
+ String errlog = "error_" + time + ".txt";
+ PrintStream ps = new PrintStream(
+ new FileOutputStream(errlog));
+ PrintStream e1 = System.err;
+ System.setErr(ps);
+ ex.printStackTrace();
+ verboseLog.close();
+ System.setErr(e1);
+ ps.close();
+ JOptionPane
+ .showMessageDialog(
+ RandomizerGUI.this,
+ String.format(
+ bundle.getString("RandomizerGUI.loadFailed"),
+ errlog));
+ } catch (Exception logex) {
+ JOptionPane
+ .showMessageDialog(
+ RandomizerGUI.this,
+ bundle.getString("RandomizerGUI.loadFailedNoLog"));
+ verboseLog.close();
+ }
+ }
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ RandomizerGUI.this.opDialog
+ .setVisible(false);
+ RandomizerGUI.this.initialFormState();
+ RandomizerGUI.this.romLoaded();
+ }
+ });
+ }
+ };
+ t.start();
+
+ return;
+ }
+ }
+ JOptionPane.showMessageDialog(this, String.format(
+ bundle.getString("RandomizerGUI.unsupportedRom"),
+ fh.getName()));
+ }
+
+ }
+
+ private void romLoaded() {
+ try {
+ this.currentRestrictions = null;
+ this.currentCodeTweaks = 0;
+ updateCodeTweaksButtonText();
+ this.riRomNameLabel.setText(this.romHandler.getROMName());
+ this.riRomCodeLabel.setText(this.romHandler.getROMCode());
+ this.riRomSupportLabel.setText(bundle
+ .getString("RandomizerGUI.romSupportPrefix")
+ + " "
+ + this.romHandler.getSupportLevel());
+ this.goUpdateMovesCheckBox.setSelected(false);
+ if (romHandler instanceof Gen1RomHandler) {
+ this.goUpdateTypesCheckBox.setEnabled(true);
+ }
+ this.goUpdateMovesCheckBox.setSelected(false);
+ this.goUpdateMovesCheckBox.setEnabled(true);
+ this.goUpdateMovesLegacyCheckBox.setSelected(false);
+ this.goUpdateMovesLegacyCheckBox.setEnabled(false);
+ this.goUpdateMovesLegacyCheckBox
+ .setVisible(!(romHandler instanceof Gen5RomHandler));
+ this.goRemoveTradeEvosCheckBox.setSelected(false);
+ this.goRemoveTradeEvosCheckBox.setEnabled(true);
+ if (!(romHandler instanceof Gen5RomHandler)
+ && !(romHandler instanceof Gen4RomHandler)) {
+ this.goLowerCaseNamesCheckBox.setSelected(false);
+ this.goLowerCaseNamesCheckBox.setEnabled(true);
+ }
+ if (romHandler instanceof Gen3RomHandler) {
+ this.goNationalDexCheckBox.setSelected(false);
+ this.goNationalDexCheckBox.setEnabled(true);
+ }
+ this.raceModeCB.setSelected(false);
+ this.raceModeCB.setEnabled(true);
+
+ this.codeTweaksCB.setSelected(false);
+ this.codeTweaksCB.setEnabled(romHandler.codeTweaksAvailable() != 0);
+ this.codeTweaksBtn.setEnabled(false);
+ this.codeTweaksBtn
+ .setVisible(romHandler.codeTweaksAvailable() != 0);
+ this.codeTweaksCB.setVisible(romHandler.codeTweaksAvailable() != 0);
+
+ this.pokeLimitCB.setSelected(false);
+ this.pokeLimitBtn.setEnabled(false);
+ this.pokeLimitCB
+ .setEnabled(!(romHandler instanceof Gen1RomHandler));
+ this.pokeLimitCB
+ .setVisible(!(romHandler instanceof Gen1RomHandler));
+ this.pokeLimitBtn
+ .setVisible(!(romHandler instanceof Gen1RomHandler));
+
+ this.randomizeHollowsCB.setSelected(false);
+ this.randomizeHollowsCB.setEnabled(romHandler
+ .hasHiddenHollowPokemon());
+
+ this.brokenMovesCB.setSelected(false);
+ this.brokenMovesCB.setEnabled(true);
+
+ this.loadQSButton.setEnabled(true);
+ this.saveQSButton.setEnabled(true);
+
+ this.pbsChangesUnchangedRB.setEnabled(true);
+ this.pbsChangesUnchangedRB.setSelected(true);
+ this.pbsChangesRandomEvosRB.setEnabled(true);
+ this.pbsChangesRandomTotalRB.setEnabled(true);
+ this.pbsChangesShuffleRB.setEnabled(true);
+
+ this.pbsStandardEXPCurvesCB.setEnabled(true);
+ this.pbsStandardEXPCurvesCB.setSelected(false);
+
+ if (romHandler.abilitiesPerPokemon() > 0) {
+ this.paUnchangedRB.setEnabled(true);
+ this.paUnchangedRB.setSelected(true);
+ this.paRandomizeRB.setEnabled(true);
+ this.paWonderGuardCB.setEnabled(false);
+ } else {
+ this.abilitiesPanel.setVisible(false);
+ }
+
+ this.spUnchangedRB.setEnabled(true);
+ this.spUnchangedRB.setSelected(true);
+
+ this.spCustomPoke3Chooser.setVisible(true);
+ if (romHandler.canChangeStarters()) {
+ this.spCustomRB.setEnabled(true);
+ this.spRandomRB.setEnabled(true);
+ this.spRandom2EvosRB.setEnabled(true);
+ if (romHandler.isYellow()) {
+ this.spCustomPoke3Chooser.setVisible(false);
+ }
+ populateDropdowns();
+ }
+
+ this.spHeldItemsCB.setSelected(false);
+ boolean hasStarterHeldItems = (romHandler instanceof Gen2RomHandler || romHandler instanceof Gen3RomHandler);
+ this.spHeldItemsCB.setEnabled(hasStarterHeldItems);
+ this.spHeldItemsCB.setVisible(hasStarterHeldItems);
+
+ this.pmsRandomTotalRB.setEnabled(true);
+ this.pmsRandomTypeRB.setEnabled(true);
+ this.pmsUnchangedRB.setEnabled(true);
+ this.pmsUnchangedRB.setSelected(true);
+ this.pmsMetronomeOnlyRB.setEnabled(true);
+
+ this.pms4MovesCB.setVisible(romHandler.supportsFourStartingMoves());
+
+ this.ptRandomFollowEvosRB.setEnabled(true);
+ this.ptRandomTotalRB.setEnabled(true);
+ this.ptUnchangedRB.setEnabled(true);
+ this.ptUnchangedRB.setSelected(true);
+
+ this.tpRandomRB.setEnabled(true);
+ this.tpTypeThemedRB.setEnabled(true);
+ this.tpUnchangedRB.setEnabled(true);
+ this.tpUnchangedRB.setSelected(true);
+ this.tnRandomizeCB.setEnabled(true);
+ this.tcnRandomizeCB.setEnabled(true);
+
+ if (romHandler instanceof Gen1RomHandler
+ || romHandler instanceof Gen2RomHandler) {
+ this.tpNoEarlyShedinjaCB.setVisible(false);
+ } else {
+ this.tpNoEarlyShedinjaCB.setVisible(true);
+ }
+ this.tpNoEarlyShedinjaCB.setSelected(false);
+
+ this.wpArea11RB.setEnabled(true);
+ this.wpGlobalRB.setEnabled(true);
+ this.wpRandomRB.setEnabled(true);
+ this.wpUnchangedRB.setEnabled(true);
+ this.wpUnchangedRB.setSelected(true);
+ this.wpUseTimeCB.setEnabled(false);
+ this.wpNoLegendariesCB.setEnabled(false);
+ if (!romHandler.hasTimeBasedEncounters()) {
+ this.wpUseTimeCB.setVisible(false);
+ }
+ this.wpCatchRateCB.setEnabled(true);
+
+ this.wpHeldItemsCB.setSelected(false);
+ this.wpHeldItemsCB.setEnabled(true);
+ if (romHandler instanceof Gen1RomHandler) {
+ this.wpHeldItemsCB.setVisible(false);
+ }
+
+ this.stpUnchangedRB.setEnabled(true);
+ if (this.romHandler.canChangeStaticPokemon()) {
+ this.stpRandomL4LRB.setEnabled(true);
+ this.stpRandomTotalRB.setEnabled(true);
+
+ }
+
+ this.tmmRandomRB.setEnabled(true);
+ this.tmmUnchangedRB.setEnabled(true);
+
+ this.thcRandomTotalRB.setEnabled(true);
+ this.thcRandomTypeRB.setEnabled(true);
+ this.thcUnchangedRB.setEnabled(true);
+
+ if (this.romHandler.hasMoveTutors()) {
+ this.mtmRandomRB.setEnabled(true);
+ this.mtmUnchangedRB.setEnabled(true);
+
+ this.mtcRandomTotalRB.setEnabled(true);
+ this.mtcRandomTypeRB.setEnabled(true);
+ this.mtcUnchangedRB.setEnabled(true);
+ } else {
+ this.mtCompatPanel.setVisible(false);
+ this.mtMovesPanel.setVisible(false);
+ this.mtNoExistLabel.setVisible(true);
+ }
+
+ this.igtUnchangedRB.setEnabled(true);
+ this.igtBothRB.setEnabled(true);
+ this.igtGivenOnlyRB.setEnabled(true);
+
+ if (this.romHandler instanceof Gen1RomHandler) {
+ this.igtRandomItemCB.setVisible(false);
+ this.igtRandomIVsCB.setVisible(false);
+ this.igtRandomOTCB.setVisible(false);
+ }
+
+ this.fiUnchangedRB.setEnabled(true);
+ this.fiRandomRB.setEnabled(true);
+ this.fiShuffleRB.setEnabled(true);
+
+ if (this.romHandler instanceof AbstractDSRomHandler) {
+ ((AbstractDSRomHandler) this.romHandler).closeInnerRom();
+ }
+ } catch (Exception ex) {
+ long time = System.currentTimeMillis();
+ try {
+ String errlog = "error_" + time + ".txt";
+ PrintStream ps = new PrintStream(new FileOutputStream(errlog));
+ PrintStream e1 = System.err;
+ System.setErr(ps);
+ ex.printStackTrace();
+ System.setErr(e1);
+ ps.close();
+ JOptionPane
+ .showMessageDialog(
+ RandomizerGUI.this,
+ String.format(
+ bundle.getString("RandomizerGUI.processFailed"),
+ errlog));
+ } catch (Exception logex) {
+ JOptionPane.showMessageDialog(RandomizerGUI.this,
+ bundle.getString("RandomizerGUI.processFailedNoLog"));
+ }
+ }
+ }
+
+ private void populateDropdowns() {
+ List currentStarters = romHandler.getStarters();
+ List allPokes = romHandler.getPokemon();
+ String[] pokeNames = new String[allPokes.size() - 1];
+ for (int i = 1; i < allPokes.size(); i++) {
+ pokeNames[i - 1] = allPokes.get(i).name;
+ }
+ this.spCustomPoke1Chooser.setModel(new DefaultComboBoxModel(pokeNames));
+ this.spCustomPoke1Chooser
+ .setSelectedIndex(currentStarters.get(0).number - 1);
+ this.spCustomPoke2Chooser.setModel(new DefaultComboBoxModel(pokeNames));
+ this.spCustomPoke2Chooser
+ .setSelectedIndex(currentStarters.get(1).number - 1);
+ if (!romHandler.isYellow()) {
+ this.spCustomPoke3Chooser.setModel(new DefaultComboBoxModel(
+ pokeNames));
+ this.spCustomPoke3Chooser
+ .setSelectedIndex(currentStarters.get(2).number - 1);
+ }
+ }
+
+ private void enableOrDisableSubControls() {
+ // This isn't for a new ROM being loaded (that's romLoaded)
+ // This is just for when a radio button gets selected or state is loaded
+ // and we need to enable/disable secondary controls
+ // e.g. wild pokemon / trainer pokemon "modifier"
+ // and the 3 starter pokemon dropdowns
+
+ if (this.goUpdateMovesCheckBox.isSelected()
+ && !(romHandler instanceof Gen5RomHandler)) {
+ this.goUpdateMovesLegacyCheckBox.setEnabled(true);
+ } else {
+ this.goUpdateMovesLegacyCheckBox.setEnabled(false);
+ this.goUpdateMovesLegacyCheckBox.setSelected(false);
+ }
+
+ this.codeTweaksBtn.setEnabled(this.codeTweaksCB.isSelected());
+ updateCodeTweaksButtonText();
+ this.pokeLimitBtn.setEnabled(this.pokeLimitCB.isSelected());
+
+ if (this.spCustomRB.isSelected()) {
+ this.spCustomPoke1Chooser.setEnabled(true);
+ this.spCustomPoke2Chooser.setEnabled(true);
+ this.spCustomPoke3Chooser.setEnabled(true);
+ } else {
+ this.spCustomPoke1Chooser.setEnabled(false);
+ this.spCustomPoke2Chooser.setEnabled(false);
+ this.spCustomPoke3Chooser.setEnabled(false);
+ }
+
+ if (this.paRandomizeRB.isSelected()) {
+ this.paWonderGuardCB.setEnabled(true);
+ } else {
+ this.paWonderGuardCB.setEnabled(false);
+ this.paWonderGuardCB.setSelected(false);
+ }
+
+ if (this.tpUnchangedRB.isSelected()) {
+ this.tpPowerLevelsCB.setEnabled(false);
+ this.tpRivalCarriesStarterCB.setEnabled(false);
+ this.tpNoLegendariesCB.setEnabled(false);
+ this.tpNoEarlyShedinjaCB.setEnabled(false);
+ this.tpNoEarlyShedinjaCB.setSelected(false);
+ } else {
+ this.tpPowerLevelsCB.setEnabled(true);
+ this.tpRivalCarriesStarterCB.setEnabled(true);
+ this.tpNoLegendariesCB.setEnabled(true);
+ this.tpNoEarlyShedinjaCB.setEnabled(true);
+ }
+
+ if (this.tpTypeThemedRB.isSelected()) {
+ this.tpTypeWeightingCB.setEnabled(true);
+ } else {
+ this.tpTypeWeightingCB.setEnabled(false);
+ }
+
+ if (this.wpArea11RB.isSelected() || this.wpRandomRB.isSelected()) {
+ this.wpARNoneRB.setEnabled(true);
+ this.wpARSimilarStrengthRB.setEnabled(true);
+ this.wpARCatchEmAllRB.setEnabled(true);
+ this.wpARTypeThemedRB.setEnabled(true);
+ } else if (this.wpGlobalRB.isSelected()) {
+ if (this.wpARCatchEmAllRB.isSelected()
+ || this.wpARTypeThemedRB.isSelected()) {
+ this.wpARNoneRB.setSelected(true);
+ }
+ this.wpARNoneRB.setEnabled(true);
+ this.wpARSimilarStrengthRB.setEnabled(true);
+ this.wpARCatchEmAllRB.setEnabled(false);
+ this.wpARTypeThemedRB.setEnabled(false);
+ } else {
+ this.wpARNoneRB.setEnabled(false);
+ this.wpARSimilarStrengthRB.setEnabled(false);
+ this.wpARCatchEmAllRB.setEnabled(false);
+ this.wpARTypeThemedRB.setEnabled(false);
+ this.wpARNoneRB.setSelected(true);
+ }
+
+ if (this.wpUnchangedRB.isSelected()) {
+ this.wpUseTimeCB.setEnabled(false);
+ this.wpNoLegendariesCB.setEnabled(false);
+ } else {
+ this.wpUseTimeCB.setEnabled(true);
+ this.wpNoLegendariesCB.setEnabled(true);
+ }
+
+ if (this.igtUnchangedRB.isSelected()) {
+ this.igtRandomItemCB.setEnabled(false);
+ this.igtRandomIVsCB.setEnabled(false);
+ this.igtRandomNicknameCB.setEnabled(false);
+ this.igtRandomOTCB.setEnabled(false);
+ } else {
+ this.igtRandomItemCB.setEnabled(true);
+ this.igtRandomIVsCB.setEnabled(true);
+ this.igtRandomNicknameCB.setEnabled(true);
+ this.igtRandomOTCB.setEnabled(true);
+ }
+
+ if (this.pmsMetronomeOnlyRB.isSelected()) {
+ this.tmmUnchangedRB.setEnabled(false);
+ this.tmmRandomRB.setEnabled(false);
+ this.tmmUnchangedRB.setSelected(true);
+
+ this.mtmUnchangedRB.setEnabled(false);
+ this.mtmRandomRB.setEnabled(false);
+ this.mtmUnchangedRB.setSelected(true);
+ } else {
+ this.tmmUnchangedRB.setEnabled(true);
+ this.tmmRandomRB.setEnabled(true);
+
+ this.mtmUnchangedRB.setEnabled(true);
+ this.mtmRandomRB.setEnabled(true);
+ }
+
+ if (this.pmsMetronomeOnlyRB.isSelected()
+ || this.pmsUnchangedRB.isSelected()) {
+ this.pms4MovesCB.setEnabled(false);
+ this.pms4MovesCB.setSelected(false);
+ } else {
+ this.pms4MovesCB.setEnabled(true);
+ }
+ }
+
+ private void saveROM() {
+ if (romHandler == null) {
+ return; // none loaded
+ }
+ if (raceModeCB.isSelected() && tpUnchangedRB.isSelected()
+ && wpUnchangedRB.isSelected()) {
+ JOptionPane.showMessageDialog(this,
+ bundle.getString("RandomizerGUI.raceModeRequirements"));
+ return;
+ }
+ if (pokeLimitCB.isSelected()
+ && (this.currentRestrictions == null || this.currentRestrictions
+ .nothingSelected())) {
+ JOptionPane.showMessageDialog(this,
+ bundle.getString("RandomizerGUI.pokeLimitNotChosen"));
+ return;
+ }
+ romSaveChooser.setSelectedFile(null);
+ int returnVal = romSaveChooser.showSaveDialog(this);
+ if (returnVal == JFileChooser.APPROVE_OPTION) {
+ File fh = romSaveChooser.getSelectedFile();
+ // Fix or add extension
+ List extensions = new ArrayList(Arrays.asList(
+ "sgb", "gbc", "gba", "nds"));
+ extensions.remove(this.romHandler.getDefaultExtension());
+ fh = FileFunctions.fixFilename(fh,
+ this.romHandler.getDefaultExtension(), extensions);
+ boolean allowed = true;
+ if (this.romHandler instanceof AbstractDSRomHandler) {
+ String currentFN = this.romHandler.loadedFilename();
+ if (currentFN.equals(fh.getAbsolutePath())) {
+ JOptionPane.showMessageDialog(this,
+ bundle.getString("RandomizerGUI.cantOverwriteDS"));
+ allowed = false;
+ }
+ }
+ if (allowed) {
+ // Get a seed
+ long seed = RandomSource.pickSeed();
+ // Apply it
+ RandomSource.seed(seed);
+ presetMode = false;
+ performRandomization(fh.getAbsolutePath(), seed, null, null,
+ null);
+ }
+ }
+ }
+
+ private String getConfigString() {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ baos.write(makeByteSelected(this.goLowerCaseNamesCheckBox,
+ this.goNationalDexCheckBox, this.goRemoveTradeEvosCheckBox,
+ this.goUpdateMovesCheckBox, this.goUpdateMovesLegacyCheckBox,
+ this.goUpdateTypesCheckBox, this.tnRandomizeCB,
+ this.tcnRandomizeCB));
+
+ baos.write(makeByteSelected(this.pbsChangesRandomEvosRB,
+ this.pbsChangesRandomTotalRB, this.pbsChangesShuffleRB,
+ this.pbsChangesUnchangedRB, this.paUnchangedRB,
+ this.paRandomizeRB, this.paWonderGuardCB,
+ this.pbsStandardEXPCurvesCB));
+
+ baos.write(makeByteSelected(this.ptRandomFollowEvosRB,
+ this.ptRandomTotalRB, this.ptUnchangedRB, this.codeTweaksCB,
+ this.raceModeCB, this.randomizeHollowsCB, this.brokenMovesCB,
+ this.pokeLimitCB));
+
+ baos.write(makeByteSelected(this.spCustomRB, this.spRandomRB,
+ this.spUnchangedRB, this.spRandom2EvosRB, this.spHeldItemsCB));
+
+ // @4
+ writePokemonIndex(baos, this.spCustomPoke1Chooser);
+ writePokemonIndex(baos, this.spCustomPoke2Chooser);
+ writePokemonIndex(baos, this.spCustomPoke3Chooser);
+
+ // 10
+ baos.write(makeByteSelected(this.pmsRandomTotalRB,
+ this.pmsRandomTypeRB, this.pmsUnchangedRB,
+ this.pmsMetronomeOnlyRB, this.pms4MovesCB));
+
+ // changed 160
+ baos.write(makeByteSelected(this.tpPowerLevelsCB, this.tpRandomRB,
+ this.tpRivalCarriesStarterCB, this.tpTypeThemedRB,
+ this.tpTypeWeightingCB, this.tpUnchangedRB,
+ this.tpNoLegendariesCB, this.tpNoEarlyShedinjaCB));
+
+ baos.write(makeByteSelected(this.wpARCatchEmAllRB, this.wpArea11RB,
+ this.wpARNoneRB, this.wpARTypeThemedRB, this.wpGlobalRB,
+ this.wpRandomRB, this.wpUnchangedRB, this.wpUseTimeCB));
+
+ // bugfix 161
+ baos.write(makeByteSelected(this.wpCatchRateCB, this.wpNoLegendariesCB,
+ this.wpARSimilarStrengthRB, this.wpHeldItemsCB));
+
+ baos.write(makeByteSelected(this.stpUnchangedRB, this.stpRandomL4LRB,
+ this.stpRandomTotalRB));
+
+ baos.write(makeByteSelected(this.thcRandomTotalRB,
+ this.thcRandomTypeRB, this.thcUnchangedRB, this.tmmRandomRB,
+ this.tmmUnchangedRB));
+
+ baos.write(makeByteSelected(this.mtcRandomTotalRB,
+ this.mtcRandomTypeRB, this.mtcUnchangedRB, this.mtmRandomRB,
+ this.mtmUnchangedRB));
+
+ // new 150
+ baos.write(makeByteSelected(this.igtBothRB, this.igtGivenOnlyRB,
+ this.igtRandomItemCB, this.igtRandomIVsCB,
+ this.igtRandomNicknameCB, this.igtRandomOTCB,
+ this.igtUnchangedRB));
+
+ baos.write(makeByteSelected(this.fiRandomRB, this.fiShuffleRB,
+ this.fiUnchangedRB));
+
+ // @ 19
+ try {
+ if (currentRestrictions != null) {
+ writeFullInt(baos, currentRestrictions.toInt());
+ } else {
+ writeFullInt(baos, 0);
+ }
+ } catch (IOException e) {
+ }
+
+ // @ 23
+ try {
+ writeFullInt(baos, currentCodeTweaks);
+ } catch (IOException e) {
+
+ }
+
+ try {
+ byte[] romName = romHandler.getROMName().getBytes("US-ASCII");
+ baos.write(romName.length);
+ baos.write(romName);
+ } catch (UnsupportedEncodingException e) {
+ baos.write(0);
+ } catch (IOException e) {
+ baos.write(0);
+ }
+
+ byte[] current = baos.toByteArray();
+ CRC32 checksum = new CRC32();
+ checksum.update(current);
+
+ try {
+ writeFullInt(baos, (int) checksum.getValue());
+ writeFullInt(baos, getFileChecksum("trainerclasses.txt"));
+ writeFullInt(baos, getFileChecksum("trainernames.txt"));
+ writeFullInt(baos, getFileChecksum("nicknames.txt"));
+ } catch (IOException e) {
+ }
+
+ return DatatypeConverter.printBase64Binary(baos.toByteArray());
+ }
+
+ private static int getFileChecksum(String filename) {
+ try {
+ return getFileChecksum(FileFunctions.openConfig(filename));
+ } catch (IOException e) {
+ return 0;
+ }
+ }
+
+ private static int getFileChecksum(InputStream stream) {
+ try {
+ Scanner sc = new Scanner(stream, "UTF-8");
+ CRC32 checksum = new CRC32();
+ while (sc.hasNextLine()) {
+ String line = sc.nextLine().trim();
+ if (!line.isEmpty()) {
+ checksum.update(line.getBytes("UTF-8"));
+ }
+ }
+ sc.close();
+ return (int) checksum.getValue();
+ } catch (IOException e) {
+ return 0;
+ }
+
+ }
+
+ public String getValidRequiredROMName(String config, byte[] trainerClasses,
+ byte[] trainerNames, byte[] nicknames)
+ throws UnsupportedEncodingException,
+ InvalidSupplementFilesException {
+ byte[] data = DatatypeConverter.parseBase64Binary(config);
+
+ if (data.length < 44) {
+ return null; // too short
+ }
+
+ // Check the checksum
+ ByteBuffer buf = ByteBuffer.allocate(4).put(data, data.length - 16, 4);
+ buf.rewind();
+ int crc = buf.getInt();
+
+ CRC32 checksum = new CRC32();
+ checksum.update(data, 0, data.length - 16);
+ if ((int) checksum.getValue() != crc) {
+ return null; // checksum failure
+ }
+
+ // Check the trainerclass & trainernames crc
+ if (trainerClasses == null
+ && !checkOtherCRC(data, 0, 6, "trainerclasses.txt",
+ data.length - 12)) {
+ JOptionPane.showMessageDialog(null,
+ bundle.getString("RandomizerGUI.presetFailTrainerClasses"));
+ throw new InvalidSupplementFilesException();
+ }
+ if (trainerNames == null
+ && (!checkOtherCRC(data, 0, 5, "trainernames.txt",
+ data.length - 8) || !checkOtherCRC(data, 16, 5,
+ "trainernames.txt", data.length - 8))) {
+ JOptionPane.showMessageDialog(null,
+ bundle.getString("RandomizerGUI.presetFailTrainerNames"));
+ throw new InvalidSupplementFilesException();
+ }
+ if (nicknames == null
+ && !checkOtherCRC(data, 16, 4, "nicknames.txt", data.length - 4)) {
+ JOptionPane.showMessageDialog(null,
+ bundle.getString("RandomizerGUI.presetFailNicknames"));
+ throw new InvalidSupplementFilesException();
+ }
+
+ int nameLength = data[27] & 0xFF;
+ if (data.length != 44 + nameLength) {
+ return null; // not valid length
+ }
+ String name = new String(data, 28, nameLength, "US-ASCII");
+ return name;
+ }
+
+ private boolean restoreFrom(String config) {
+ // Need to add enables
+ byte[] data = DatatypeConverter.parseBase64Binary(config);
+
+ // Check the checksum
+ ByteBuffer buf = ByteBuffer.allocate(4).put(data, data.length - 16, 4);
+ buf.rewind();
+ int crc = buf.getInt();
+
+ CRC32 checksum = new CRC32();
+ checksum.update(data, 0, data.length - 16);
+
+ if ((int) checksum.getValue() != crc) {
+ return false; // checksum failure
+ }
+
+ // Restore the actual controls
+ restoreStates(data[0], this.goLowerCaseNamesCheckBox,
+ this.goNationalDexCheckBox, this.goRemoveTradeEvosCheckBox,
+ this.goUpdateMovesCheckBox, this.goUpdateMovesLegacyCheckBox,
+ this.goUpdateTypesCheckBox, this.tnRandomizeCB,
+ this.tcnRandomizeCB);
+
+ // sanity override
+ if (this.goUpdateMovesLegacyCheckBox.isSelected()
+ && (romHandler instanceof Gen5RomHandler)) {
+ // they probably don't want moves updated actually
+ this.goUpdateMovesLegacyCheckBox.setSelected(false);
+ this.goUpdateMovesCheckBox.setSelected(false);
+ }
+
+ restoreStates(data[1], this.pbsChangesRandomEvosRB,
+ this.pbsChangesRandomTotalRB, this.pbsChangesShuffleRB,
+ this.pbsChangesUnchangedRB, this.paUnchangedRB,
+ this.paRandomizeRB, this.paWonderGuardCB,
+ this.pbsStandardEXPCurvesCB);
+
+ restoreStates(data[2], this.ptRandomFollowEvosRB, this.ptRandomTotalRB,
+ this.ptUnchangedRB, this.codeTweaksCB, this.raceModeCB,
+ this.randomizeHollowsCB, this.brokenMovesCB, this.pokeLimitCB);
+
+ restoreStates(data[3], this.spCustomRB, this.spRandomRB,
+ this.spUnchangedRB, this.spRandom2EvosRB, this.spHeldItemsCB);
+
+ restoreSelectedIndex(data, 4, this.spCustomPoke1Chooser);
+ restoreSelectedIndex(data, 6, this.spCustomPoke2Chooser);
+ restoreSelectedIndex(data, 8, this.spCustomPoke3Chooser);
+
+ restoreStates(data[10], this.pmsRandomTotalRB, this.pmsRandomTypeRB,
+ this.pmsUnchangedRB, this.pmsMetronomeOnlyRB, this.pms4MovesCB);
+
+ // changed 160
+ restoreStates(data[11], this.tpPowerLevelsCB, this.tpRandomRB,
+ this.tpRivalCarriesStarterCB, this.tpTypeThemedRB,
+ this.tpTypeWeightingCB, this.tpUnchangedRB,
+ this.tpNoLegendariesCB, this.tpNoEarlyShedinjaCB);
+
+ restoreStates(data[12], this.wpARCatchEmAllRB, this.wpArea11RB,
+ this.wpARNoneRB, this.wpARTypeThemedRB, this.wpGlobalRB,
+ this.wpRandomRB, this.wpUnchangedRB, this.wpUseTimeCB);
+
+ restoreStates(data[13], this.wpCatchRateCB, this.wpNoLegendariesCB,
+ this.wpARSimilarStrengthRB, this.wpHeldItemsCB);
+
+ restoreStates(data[14], this.stpUnchangedRB, this.stpRandomL4LRB,
+ this.stpRandomTotalRB);
+
+ restoreStates(data[15], this.thcRandomTotalRB, this.thcRandomTypeRB,
+ this.thcUnchangedRB, this.tmmRandomRB, this.tmmUnchangedRB);
+ restoreStates(data[16], this.mtcRandomTotalRB, this.mtcRandomTypeRB,
+ this.mtcUnchangedRB, this.mtmRandomRB, this.mtmUnchangedRB);
+
+ // new 150
+ restoreStates(data[17], this.igtBothRB, this.igtGivenOnlyRB,
+ this.igtRandomItemCB, this.igtRandomIVsCB,
+ this.igtRandomNicknameCB, this.igtRandomOTCB,
+ this.igtUnchangedRB);
+ restoreStates(data[18], this.fiRandomRB, this.fiShuffleRB,
+ this.fiUnchangedRB);
+
+ // gen restrictions
+ int genlim = readFullInt(data, 19);
+ if (genlim == 0) {
+ this.currentRestrictions = null;
+ } else {
+ this.currentRestrictions = new GenRestrictions(genlim);
+ this.currentRestrictions.limitToGen(this.romHandler
+ .generationOfPokemon());
+ }
+
+ int codetweaks = readFullInt(data, 23);
+ this.currentCodeTweaks = codetweaks
+ & this.romHandler.codeTweaksAvailable();
+ updateCodeTweaksButtonText();
+ // Sanity override
+ if (this.currentCodeTweaks == 0) {
+ this.codeTweaksCB.setSelected(false);
+ }
+
+ this.enableOrDisableSubControls();
+
+ // Name data is ignored here - we should've used it earlier.
+ return true;
+ }
+
+ private void performRandomization(final String filename, final long seed,
+ byte[] trainerClasses, byte[] trainerNames, byte[] nicknames) {
+
+ final boolean raceMode = raceModeCB.isSelected();
+ int checkValue = 0;
+ final long startTime = System.currentTimeMillis();
+ // Setup verbose log
+ final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ String nl = System.getProperty("line.separator");
+ try {
+ verboseLog = new PrintStream(baos, false, "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ verboseLog = new PrintStream(baos);
+ }
+ try {
+ // limit pokemon?
+ if (this.pokeLimitCB.isSelected()) {
+ romHandler.setPokemonPool(currentRestrictions);
+ romHandler.removeEvosForPokemonPool();
+ }
+
+ // Update type effectiveness in RBY?
+ if (romHandler instanceof Gen1RomHandler
+ && this.goUpdateTypesCheckBox.isSelected()) {
+ romHandler.fixTypeEffectiveness();
+ }
+
+ // Move updates
+ if (this.goUpdateMovesCheckBox.isSelected()) {
+ romHandler.initMoveUpdates();
+ if (!(romHandler instanceof Gen5RomHandler)) {
+ romHandler.updateMovesToGen5();
+ }
+ if (!this.goUpdateMovesLegacyCheckBox.isSelected()) {
+ romHandler.updateMovesToGen6();
+ }
+ romHandler.printMoveUpdates();
+ }
+
+ List moves = romHandler.getMoves();
+
+ // Trade evolutions removal
+ if (this.goRemoveTradeEvosCheckBox.isSelected()) {
+ romHandler.removeTradeEvolutions(!this.pmsUnchangedRB
+ .isSelected());
+ }
+
+ // Camel case?
+ if (!(romHandler instanceof Gen5RomHandler)
+ && !(romHandler instanceof Gen4RomHandler)
+ && this.goLowerCaseNamesCheckBox.isSelected()) {
+ romHandler.applyCamelCaseNames();
+ }
+
+ // National dex gen3?
+ if (romHandler instanceof Gen3RomHandler
+ && this.goNationalDexCheckBox.isSelected()) {
+ romHandler.patchForNationalDex();
+ }
+
+ // Code Tweaks?
+ if (romHandler.codeTweaksAvailable() != 0) {
+ int ctavailable = romHandler.codeTweaksAvailable();
+ if ((ctavailable & CodeTweaks.BW_EXP_PATCH) > 0
+ && (currentCodeTweaks & CodeTweaks.BW_EXP_PATCH) > 0) {
+ romHandler.applyBWEXPPatch();
+ }
+
+ if ((ctavailable & CodeTweaks.FIX_CRIT_RATE) > 0
+ && (currentCodeTweaks & CodeTweaks.FIX_CRIT_RATE) > 0) {
+ romHandler.applyCritRatePatch();
+ }
+
+ if ((ctavailable & CodeTweaks.NERF_X_ACCURACY) > 0
+ && (currentCodeTweaks & CodeTweaks.NERF_X_ACCURACY) > 0) {
+ romHandler.applyXAccNerfPatch();
+ }
+ }
+
+ // Hollows?
+ if (romHandler.hasHiddenHollowPokemon()
+ && this.randomizeHollowsCB.isSelected()) {
+ romHandler.randomizeHiddenHollowPokemon();
+ }
+
+ List allPokes = romHandler.getPokemon();
+
+ // Base stats changing
+ if (this.pbsChangesShuffleRB.isSelected()) {
+ romHandler.shufflePokemonStats();
+ } else if (this.pbsChangesRandomEvosRB.isSelected()) {
+ romHandler.randomizePokemonStats(true);
+ } else if (this.pbsChangesRandomTotalRB.isSelected()) {
+ romHandler.randomizePokemonStats(false);
+ }
+
+ if (this.pbsStandardEXPCurvesCB.isSelected()) {
+ romHandler.standardizeEXPCurves();
+ }
+
+ // Abilities? (new 1.0.2)
+ if (this.romHandler.abilitiesPerPokemon() > 0
+ && this.paRandomizeRB.isSelected()) {
+ romHandler
+ .randomizeAbilities(this.paWonderGuardCB.isSelected());
+ }
+
+ // Pokemon Types
+ if (this.ptRandomFollowEvosRB.isSelected()) {
+ romHandler.randomizePokemonTypes(true);
+ } else if (this.ptRandomTotalRB.isSelected()) {
+ romHandler.randomizePokemonTypes(false);
+ }
+
+ // Wild Held Items?
+ String[] itemNames = romHandler.getItemNames();
+ if (this.wpHeldItemsCB.isSelected()) {
+ romHandler.randomizeWildHeldItems();
+ }
+
+ // Log base stats & types if changed at all
+ if (this.pbsChangesUnchangedRB.isSelected()
+ && this.ptUnchangedRB.isSelected()
+ && this.paUnchangedRB.isSelected()
+ && this.wpHeldItemsCB.isSelected() == false) {
+ verboseLog.println("Pokemon base stats & type: unchanged" + nl);
+ } else {
+ verboseLog.println("--Pokemon Base Stats & Types--");
+ if (romHandler instanceof Gen1RomHandler) {
+ verboseLog
+ .println("NUM|NAME |TYPE | HP| ATK| DEF| SPE|SPEC");
+ for (Pokemon pkmn : allPokes) {
+ if (pkmn != null) {
+ String typeString = pkmn.primaryType == null ? "NULL"
+ : pkmn.primaryType.toString();
+ if (pkmn.secondaryType != null) {
+ typeString += "/"
+ + (pkmn.secondaryType == null ? "NULL"
+ : pkmn.secondaryType.toString());
+ }
+ verboseLog.printf(
+ "%3d|%-10s|%-17s|%4d|%4d|%4d|%4d|%4d" + nl,
+ pkmn.number, pkmn.name, typeString,
+ pkmn.hp, pkmn.attack, pkmn.defense,
+ pkmn.speed, pkmn.special);
+ }
+
+ }
+ } else {
+ verboseLog
+ .print("NUM|NAME |TYPE | HP| ATK| DEF| SPE|SATK|SDEF");
+ int abils = romHandler.abilitiesPerPokemon();
+ for (int i = 0; i < abils; i++) {
+ verboseLog.print("|ABILITY" + (i + 1) + " ");
+ }
+ verboseLog.print("|ITEM");
+ verboseLog.println();
+ for (Pokemon pkmn : allPokes) {
+ if (pkmn != null) {
+ String typeString = pkmn.primaryType.toString();
+ if (pkmn.secondaryType != null) {
+ typeString += "/"
+ + pkmn.secondaryType.toString();
+ }
+ verboseLog.printf(
+ "%3d|%-10s|%-17s|%4d|%4d|%4d|%4d|%4d|%4d",
+ pkmn.number, pkmn.name, typeString,
+ pkmn.hp, pkmn.attack, pkmn.defense,
+ pkmn.speed, pkmn.spatk, pkmn.spdef);
+ if (abils > 0) {
+ verboseLog.printf("|%-12s|%-12s",
+ romHandler.abilityName(pkmn.ability1),
+ romHandler.abilityName(pkmn.ability2));
+ if (abils > 2) {
+ verboseLog.printf("|%-12s", romHandler
+ .abilityName(pkmn.ability3));
+ }
+ }
+ verboseLog.print("|");
+ if (pkmn.guaranteedHeldItem > 0) {
+ verboseLog
+ .print(itemNames[pkmn.guaranteedHeldItem]
+ + " (100%)");
+ } else {
+ int itemCount = 0;
+ if (pkmn.commonHeldItem > 0) {
+ itemCount++;
+ verboseLog
+ .print(itemNames[pkmn.commonHeldItem]
+ + " (common)");
+ }
+ if (pkmn.rareHeldItem > 0) {
+ if (itemCount > 0) {
+ verboseLog.print(", ");
+ }
+ itemCount++;
+ verboseLog
+ .print(itemNames[pkmn.rareHeldItem]
+ + " (rare)");
+ }
+ if (pkmn.darkGrassHeldItem > 0) {
+ if (itemCount > 0) {
+ verboseLog.print(", ");
+ }
+ itemCount++;
+ verboseLog
+ .print(itemNames[pkmn.darkGrassHeldItem]
+ + " (dark grass only)");
+ }
+ }
+ verboseLog.println();
+ }
+
+ }
+ }
+ if (raceMode) {
+ for (Pokemon pkmn : allPokes) {
+ if (pkmn != null) {
+ checkValue = addToCV(checkValue, pkmn.hp,
+ pkmn.attack, pkmn.defense, pkmn.speed,
+ pkmn.spatk, pkmn.spdef, pkmn.ability1,
+ pkmn.ability2, pkmn.ability3);
+ }
+ }
+ }
+ verboseLog.println();
+ }
+
+ // Starter Pokemon
+ // Applied after type to update the strings correctly based on new
+ // types
+ if (romHandler.canChangeStarters()) {
+ if (this.spCustomRB.isSelected()) {
+ verboseLog.println("--Custom Starters--");
+ Pokemon pkmn1 = allPokes.get(this.spCustomPoke1Chooser
+ .getSelectedIndex() + 1);
+ verboseLog.println("Set starter 1 to " + pkmn1.name);
+ Pokemon pkmn2 = allPokes.get(this.spCustomPoke2Chooser
+ .getSelectedIndex() + 1);
+ verboseLog.println("Set starter 2 to " + pkmn2.name);
+ if (romHandler.isYellow()) {
+ romHandler.setStarters(Arrays.asList(pkmn1, pkmn2));
+ } else {
+ Pokemon pkmn3 = allPokes.get(this.spCustomPoke3Chooser
+ .getSelectedIndex() + 1);
+ verboseLog.println("Set starter 3 to " + pkmn3.name);
+ romHandler.setStarters(Arrays.asList(pkmn1, pkmn2,
+ pkmn3));
+ }
+ verboseLog.println();
+
+ } else if (this.spRandomRB.isSelected()) {
+ // Randomise
+ verboseLog.println("--Random Starters--");
+ int starterCount = 3;
+ if (romHandler.isYellow()) {
+ starterCount = 2;
+ }
+ List starters = new ArrayList();
+ for (int i = 0; i < starterCount; i++) {
+ Pokemon pkmn = romHandler.randomPokemon();
+ while (starters.contains(pkmn)) {
+ pkmn = romHandler.randomPokemon();
+ }
+ verboseLog.println("Set starter " + (i + 1) + " to "
+ + pkmn.name);
+ starters.add(pkmn);
+ }
+ romHandler.setStarters(starters);
+ verboseLog.println();
+ } else if (this.spRandom2EvosRB.isSelected()) {
+ // Randomise
+ verboseLog.println("--Random 2-Evolution Starters--");
+ int starterCount = 3;
+ if (romHandler.isYellow()) {
+ starterCount = 2;
+ }
+ List starters = new ArrayList();
+ for (int i = 0; i < starterCount; i++) {
+ Pokemon pkmn = romHandler.random2EvosPokemon();
+ while (starters.contains(pkmn)) {
+ pkmn = romHandler.random2EvosPokemon();
+ }
+ verboseLog.println("Set starter " + (i + 1) + " to "
+ + pkmn.name);
+ starters.add(pkmn);
+ }
+ romHandler.setStarters(starters);
+ verboseLog.println();
+ }
+ if (this.spHeldItemsCB.isSelected()
+ && (romHandler instanceof Gen1RomHandler) == false) {
+ romHandler.randomizeStarterHeldItems();
+ }
+ }
+
+ // Movesets
+ boolean noBrokenMoves = this.brokenMovesCB.isSelected();
+ boolean forceFourLv1s = romHandler.supportsFourStartingMoves()
+ && this.pms4MovesCB.isSelected();
+ if (this.pmsRandomTypeRB.isSelected()) {
+ romHandler.randomizeMovesLearnt(true, noBrokenMoves,
+ forceFourLv1s);
+ } else if (this.pmsRandomTotalRB.isSelected()) {
+ romHandler.randomizeMovesLearnt(false, noBrokenMoves,
+ forceFourLv1s);
+ }
+
+ // Show the new movesets if applicable
+ if (this.pmsUnchangedRB.isSelected()) {
+ verboseLog.println("Pokemon Movesets: Unchanged." + nl);
+ } else if (this.pmsMetronomeOnlyRB.isSelected()) {
+ verboseLog.println("Pokemon Movesets: Metronome Only." + nl);
+ } else {
+ verboseLog.println("--Pokemon Movesets--");
+ List movesets = new ArrayList();
+ Map> moveData = romHandler
+ .getMovesLearnt();
+ for (Pokemon pkmn : moveData.keySet()) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(String.format("%03d %-10s : ", pkmn.number,
+ pkmn.name));
+ List data = moveData.get(pkmn);
+ boolean first = true;
+ for (MoveLearnt ml : data) {
+ if (!first) {
+ sb.append(", ");
+ }
+
+ sb.append(moves.get(ml.move).name + " at level "
+ + ml.level);
+ first = false;
+ }
+ movesets.add(sb.toString());
+ }
+ Collections.sort(movesets);
+ for (String moveset : movesets) {
+ verboseLog.println(moveset);
+ }
+ verboseLog.println();
+ }
+
+ // Trainer Pokemon
+ if (this.tpRandomRB.isSelected()) {
+ romHandler.randomizeTrainerPokes(
+ this.tpRivalCarriesStarterCB.isSelected(),
+ this.tpPowerLevelsCB.isSelected(),
+ this.tpNoLegendariesCB.isSelected(),
+ this.tpNoEarlyShedinjaCB.isSelected());
+ } else if (this.tpTypeThemedRB.isSelected()) {
+ romHandler.typeThemeTrainerPokes(
+ this.tpRivalCarriesStarterCB.isSelected(),
+ this.tpPowerLevelsCB.isSelected(),
+ this.tpTypeWeightingCB.isSelected(),
+ this.tpNoLegendariesCB.isSelected(),
+ this.tpNoEarlyShedinjaCB.isSelected());
+ }
+
+ // Trainer names & class names randomization
+ // done before trainer log to add proper names
+
+ if (this.tcnRandomizeCB.isSelected()) {
+ romHandler.randomizeTrainerClassNames(trainerClasses);
+ }
+
+ if (this.tnRandomizeCB.isSelected()) {
+ romHandler.randomizeTrainerNames(trainerNames);
+ }
+
+ if (this.tpUnchangedRB.isSelected()) {
+ verboseLog.println("Trainers: Unchanged." + nl);
+ } else {
+ verboseLog.println("--Trainers Pokemon--");
+ List trainers = romHandler.getTrainers();
+ int idx = 0;
+ for (Trainer t : trainers) {
+ idx++;
+ verboseLog.print("#" + idx + " ");
+ if (t.fullDisplayName != null) {
+ verboseLog.print("(" + t.fullDisplayName + ")");
+ } else if (t.name != null) {
+ verboseLog.print("(" + t.name + ")");
+ }
+ if (t.offset != idx && t.offset != 0) {
+ verboseLog.printf("@%X", t.offset);
+ }
+ verboseLog.print(" - ");
+ boolean first = true;
+ for (TrainerPokemon tpk : t.pokemon) {
+ if (!first) {
+ verboseLog.print(", ");
+ }
+ verboseLog.print(tpk.pokemon.name + " Lv" + tpk.level);
+ first = false;
+ }
+ verboseLog.println();
+ }
+ verboseLog.println();
+ }
+
+ // Apply metronome only mode now that trainers have been dealt with
+ if (pmsMetronomeOnlyRB.isSelected()) {
+ romHandler.metronomeOnlyMode();
+ }
+
+ if (raceMode) {
+ List trainers = romHandler.getTrainers();
+ for (Trainer t : trainers) {
+ for (TrainerPokemon tpk : t.pokemon) {
+ checkValue = addToCV(checkValue, tpk.level,
+ tpk.pokemon.number);
+ }
+ }
+ }
+
+ // Wild Pokemon
+ // actually call this code (Kappa)
+ if (this.wpCatchRateCB.isSelected()) {
+ if (romHandler instanceof Gen5RomHandler) {
+ romHandler.minimumCatchRate(50, 25);
+ } else {
+ romHandler.minimumCatchRate(75, 37);
+ }
+ }
+ if (this.wpRandomRB.isSelected()) {
+ romHandler.randomEncounters(this.wpUseTimeCB.isSelected(),
+ this.wpARCatchEmAllRB.isSelected(),
+ this.wpARTypeThemedRB.isSelected(),
+ this.wpARSimilarStrengthRB.isSelected(),
+ this.wpNoLegendariesCB.isSelected());
+ } else if (this.wpArea11RB.isSelected()) {
+ romHandler.area1to1Encounters(this.wpUseTimeCB.isSelected(),
+ this.wpARCatchEmAllRB.isSelected(),
+ this.wpARTypeThemedRB.isSelected(),
+ this.wpARSimilarStrengthRB.isSelected(),
+ this.wpNoLegendariesCB.isSelected());
+ } else if (this.wpGlobalRB.isSelected()) {
+ romHandler.game1to1Encounters(this.wpUseTimeCB.isSelected(),
+ this.wpARSimilarStrengthRB.isSelected(),
+ this.wpNoLegendariesCB.isSelected());
+ }
+
+ if (this.wpUnchangedRB.isSelected()) {
+ verboseLog.println("Wild Pokemon: Unchanged." + nl);
+ } else {
+ verboseLog.println("--Wild Pokemon--");
+ List encounters = romHandler
+ .getEncounters(this.wpUseTimeCB.isSelected());
+ int idx = 0;
+ for (EncounterSet es : encounters) {
+ idx++;
+ verboseLog.print("Set #" + idx + " ");
+ if (es.displayName != null) {
+ verboseLog.print("- " + es.displayName + " ");
+ }
+ verboseLog.print("(rate=" + es.rate + ")");
+ verboseLog.print(" - ");
+ boolean first = true;
+ for (Encounter e : es.encounters) {
+ if (!first) {
+ verboseLog.print(", ");
+ }
+ verboseLog.print(e.pokemon.name + " Lv");
+ if (e.maxLevel > 0 && e.maxLevel != e.level) {
+ verboseLog.print("s " + e.level + "-" + e.maxLevel);
+ } else {
+ verboseLog.print(e.level);
+ }
+ first = false;
+ }
+ verboseLog.println();
+ }
+ verboseLog.println();
+ }
+
+ if (raceMode) {
+ List encounters = romHandler
+ .getEncounters(this.wpUseTimeCB.isSelected());
+ for (EncounterSet es : encounters) {
+ for (Encounter e : es.encounters) {
+ checkValue = addToCV(checkValue, e.level,
+ e.pokemon.number);
+ }
+ }
+ }
+
+ // Static Pokemon
+
+ if (romHandler.canChangeStaticPokemon()) {
+ List oldStatics = romHandler.getStaticPokemon();
+ if (this.stpRandomL4LRB.isSelected()) {
+ romHandler.randomizeStaticPokemon(true);
+ } else if (this.stpRandomTotalRB.isSelected()) {
+ romHandler.randomizeStaticPokemon(false);
+ }
+ List newStatics = romHandler.getStaticPokemon();
+ if (this.stpUnchangedRB.isSelected()) {
+ verboseLog.println("Static Pokemon: Unchanged." + nl);
+ } else {
+ verboseLog.println("--Static Pokemon--");
+ Map seenPokemon = new TreeMap();
+ for (int i = 0; i < oldStatics.size(); i++) {
+ Pokemon oldP = oldStatics.get(i);
+ Pokemon newP = newStatics.get(i);
+ if (raceMode) {
+ checkValue = addToCV(checkValue, newP.number);
+ }
+ verboseLog.print(oldP.name);
+ if (seenPokemon.containsKey(oldP)) {
+ int amount = seenPokemon.get(oldP);
+ verboseLog.print("(" + (++amount) + ")");
+ seenPokemon.put(oldP, amount);
+ } else {
+ seenPokemon.put(oldP, 1);
+ }
+ verboseLog.println(" => " + newP.name);
+ }
+ verboseLog.println();
+ }
+ }
+
+ // TMs
+ if (!pmsMetronomeOnlyRB.isSelected()
+ && this.tmmRandomRB.isSelected()) {
+ romHandler.randomizeTMMoves(noBrokenMoves);
+ verboseLog.println("--TM Moves--");
+ List tmMoves = romHandler.getTMMoves();
+ for (int i = 0; i < tmMoves.size(); i++) {
+ verboseLog.printf("TM%02d %s" + nl, i + 1,
+ moves.get(tmMoves.get(i)).name);
+ if (raceMode) {
+ checkValue = addToCV(checkValue, tmMoves.get(i));
+ }
+ }
+ verboseLog.println();
+ } else if (pmsMetronomeOnlyRB.isSelected()) {
+ verboseLog.println("TM Moves: Metronome Only." + nl);
+ } else {
+ verboseLog.println("TM Moves: Unchanged." + nl);
+ }
+
+ // TM/HM compatibility
+ if (this.thcRandomTypeRB.isSelected()) {
+ romHandler.randomizeTMHMCompatibility(true);
+ } else if (this.thcRandomTotalRB.isSelected()) {
+ romHandler.randomizeTMHMCompatibility(false);
+ }
+
+ // Move Tutors (new 1.0.3)
+ if (this.romHandler.hasMoveTutors()) {
+ if (!pmsMetronomeOnlyRB.isSelected()
+ && this.mtmRandomRB.isSelected()) {
+ List oldMtMoves = romHandler.getMoveTutorMoves();
+ romHandler.randomizeMoveTutorMoves(noBrokenMoves);
+ verboseLog.println("--Move Tutor Moves--");
+ List newMtMoves = romHandler.getMoveTutorMoves();
+ for (int i = 0; i < newMtMoves.size(); i++) {
+ verboseLog.printf("%s => %s" + nl,
+ moves.get(oldMtMoves.get(i)).name,
+ moves.get(newMtMoves.get(i)).name);
+ if (raceMode) {
+ checkValue = addToCV(checkValue, newMtMoves.get(i));
+ }
+ }
+ verboseLog.println();
+ } else if (pmsMetronomeOnlyRB.isSelected()) {
+ verboseLog
+ .println("Move Tutor Moves: Metronome Only." + nl);
+ } else {
+ verboseLog.println("Move Tutor Moves: Unchanged." + nl);
+ }
+
+ // Compatibility
+ if (this.mtcRandomTypeRB.isSelected()) {
+ romHandler.randomizeMoveTutorCompatibility(true);
+ } else if (this.mtcRandomTotalRB.isSelected()) {
+ romHandler.randomizeMoveTutorCompatibility(false);
+ }
+ }
+
+ // In-game trades
+ List oldTrades = romHandler.getIngameTrades();
+ if (this.igtGivenOnlyRB.isSelected()) {
+ romHandler.randomizeIngameTrades(false, nicknames,
+ this.igtRandomNicknameCB.isSelected(), trainerNames,
+ this.igtRandomOTCB.isSelected(),
+ this.igtRandomIVsCB.isSelected(),
+ this.igtRandomItemCB.isSelected());
+ } else if (this.igtBothRB.isSelected()) {
+ romHandler.randomizeIngameTrades(true, nicknames,
+ this.igtRandomNicknameCB.isSelected(), trainerNames,
+ this.igtRandomOTCB.isSelected(),
+ this.igtRandomIVsCB.isSelected(),
+ this.igtRandomItemCB.isSelected());
+ }
+
+ if (!this.igtUnchangedRB.isSelected()) {
+ verboseLog.println("--In-Game Trades--");
+ List newTrades = romHandler.getIngameTrades();
+ int size = oldTrades.size();
+ for (int i = 0; i < size; i++) {
+ IngameTrade oldT = oldTrades.get(i);
+ IngameTrade newT = newTrades.get(i);
+ verboseLog.printf(
+ "Trading %s for %s the %s has become trading %s for %s the %s"
+ + nl, oldT.requestedPokemon.name,
+ oldT.nickname, oldT.givenPokemon.name,
+ newT.requestedPokemon.name, newT.nickname,
+ newT.givenPokemon.name);
+ }
+ verboseLog.println();
+ }
+
+ // Field Items
+ if (this.fiShuffleRB.isSelected()) {
+ romHandler.shuffleFieldItems();
+ } else if (this.fiRandomRB.isSelected()) {
+ romHandler.randomizeFieldItems();
+ }
+
+ // Signature...
+ romHandler.applySignature();
+
+ // Save
+ final int finishedCV = checkValue;
+ opDialog = new OperationDialog(
+ bundle.getString("RandomizerGUI.savingText"), this, true);
+ Thread t = new Thread() {
+ @Override
+ public void run() {
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ opDialog.setVisible(true);
+ }
+ });
+ boolean succeededSave = false;
+ try {
+ RandomizerGUI.this.romHandler.saveRom(filename);
+ succeededSave = true;
+ } catch (Exception ex) {
+ long time = System.currentTimeMillis();
+ try {
+ String errlog = "error_" + time + ".txt";
+ PrintStream ps = new PrintStream(
+ new FileOutputStream(errlog));
+ PrintStream e1 = System.err;
+ System.setErr(ps);
+ ex.printStackTrace();
+ verboseLog.close();
+ System.setErr(e1);
+ ps.close();
+ JOptionPane
+ .showMessageDialog(
+ RandomizerGUI.this,
+ String.format(
+ bundle.getString("RandomizerGUI.saveFailedIO"),
+ errlog));
+ } catch (Exception logex) {
+ JOptionPane
+ .showMessageDialog(
+ RandomizerGUI.this,
+ bundle.getString("RandomizerGUI.saveFailedIONoLog"));
+ verboseLog.close();
+ }
+ }
+ if (succeededSave) {
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ RandomizerGUI.this.opDialog.setVisible(false);
+ // Log tail
+ verboseLog
+ .println("------------------------------------------------------------------");
+ verboseLog.println("Randomization of "
+ + romHandler.getROMName()
+ + " completed.");
+ verboseLog.println("Time elapsed: "
+ + (System.currentTimeMillis() - startTime)
+ + "ms");
+ verboseLog.println("RNG Calls: "
+ + RandomSource.callsSinceSeed());
+ verboseLog
+ .println("------------------------------------------------------------------");
+
+ // Log?
+ verboseLog.close();
+ byte[] out = baos.toByteArray();
+ verboseLog = System.out;
+
+ if (raceMode) {
+ JOptionPane.showMessageDialog(
+ RandomizerGUI.this,
+ String.format(
+ bundle.getString("RandomizerGUI.raceModeCheckValuePopup"),
+ finishedCV));
+ } else {
+ int response = JOptionPane.showConfirmDialog(
+ RandomizerGUI.this,
+ bundle.getString("RandomizerGUI.saveLogDialog.text"),
+ bundle.getString("RandomizerGUI.saveLogDialog.title"),
+ JOptionPane.YES_NO_OPTION);
+ if (response == JOptionPane.YES_OPTION) {
+ try {
+ FileOutputStream fos = new FileOutputStream(
+ filename + ".log");
+ fos.write(0xEF);
+ fos.write(0xBB);
+ fos.write(0xBF);
+ fos.write(out);
+ fos.close();
+ } catch (IOException e) {
+ JOptionPane.showMessageDialog(
+ RandomizerGUI.this,
+ bundle.getString("RandomizerGUI.logSaveFailed"));
+ return;
+ }
+ JOptionPane.showMessageDialog(
+ RandomizerGUI.this,
+ String.format(
+ bundle.getString("RandomizerGUI.logSaved"),
+ filename));
+ }
+ }
+ if (presetMode) {
+ JOptionPane.showMessageDialog(
+ RandomizerGUI.this,
+ bundle.getString("RandomizerGUI.randomizationDone"));
+ // Done
+ RandomizerGUI.this.romHandler = null;
+ initialFormState();
+ } else {
+ // Compile a config string
+ String configString = getConfigString();
+ // Show the preset maker
+ new PresetMakeDialog(RandomizerGUI.this,
+ seed, configString);
+
+ // Done
+ RandomizerGUI.this.romHandler = null;
+ initialFormState();
+ }
+ }
+ });
+ } else {
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ RandomizerGUI.this.opDialog.setVisible(false);
+ verboseLog = System.out;
+ RandomizerGUI.this.romHandler = null;
+ initialFormState();
+ }
+ });
+ }
+ }
+ };
+ t.start();
+ } catch (Exception ex) {
+ long time = System.currentTimeMillis();
+ try {
+ String errlog = "error_" + time + ".txt";
+ PrintStream ps = new PrintStream(new FileOutputStream(errlog));
+ PrintStream e1 = System.err;
+ System.setErr(ps);
+ ex.printStackTrace();
+ verboseLog.close();
+ byte[] out = baos.toByteArray();
+ System.err.print(new String(out, "UTF-8"));
+ System.setErr(e1);
+ ps.close();
+ JOptionPane.showMessageDialog(this, String.format(
+ bundle.getString("RandomizerGUI.saveFailed"), errlog));
+ } catch (Exception logex) {
+ JOptionPane.showMessageDialog(this,
+ bundle.getString("RandomizerGUI.saveFailedNoLog"));
+ verboseLog.close();
+ }
+ }
+
+ }
+
+ private void presetLoader() {
+ PresetLoadDialog pld = new PresetLoadDialog(this);
+ if (pld.isCompleted()) {
+ // Apply it
+ long seed = pld.getSeed();
+ String config = pld.getConfigString();
+ this.romHandler = pld.getROM();
+ this.romLoaded();
+ this.restoreFrom(config);
+ romSaveChooser.setSelectedFile(null);
+ int returnVal = romSaveChooser.showSaveDialog(this);
+ if (returnVal == JFileChooser.APPROVE_OPTION) {
+ File fh = romSaveChooser.getSelectedFile();
+ // Fix or add extension
+ List extensions = new ArrayList(Arrays.asList(
+ "sgb", "gbc", "gba", "nds"));
+ extensions.remove(this.romHandler.getDefaultExtension());
+ fh = FileFunctions.fixFilename(fh,
+ this.romHandler.getDefaultExtension(), extensions);
+ boolean allowed = true;
+ if (this.romHandler instanceof AbstractDSRomHandler) {
+ String currentFN = this.romHandler.loadedFilename();
+ if (currentFN.equals(fh.getAbsolutePath())) {
+ JOptionPane.showMessageDialog(this, bundle
+ .getString("RandomizerGUI.cantOverwriteDS"));
+ allowed = false;
+ }
+ }
+ if (allowed) {
+ // Apply the seed we were given
+ RandomSource.seed(seed);
+ presetMode = true;
+ performRandomization(fh.getAbsolutePath(), seed,
+ pld.getTrainerClasses(), pld.getTrainerNames(),
+ pld.getNicknames());
+ } else {
+ this.romHandler = null;
+ initialFormState();
+ }
+
+ } else {
+ this.romHandler = null;
+ initialFormState();
+ }
+ }
+
+ }
+
+ // helper methods
+
+ private boolean checkOtherCRC(byte[] data, int byteIndex, int switchIndex,
+ String filename, int offsetInData) {
+ // If the switch at data[byteIndex].switchIndex is on,
+ // then check that the CRC at
+ // data[offsetInData] ... data[offsetInData+3]
+ // matches the CRC of filename.
+ // If not, return false.
+ // If any other case, return true.
+ int switches = data[byteIndex] & 0xFF;
+ if (((switches >> switchIndex) & 0x01) == 0x01) {
+ // have to check the CRC
+ int crc = readFullInt(data, offsetInData);
+
+ if (getFileChecksum(filename) != crc) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private void restoreSelectedIndex(byte[] data, int offset,
+ JComboBox comboBox) {
+ int selIndex = (data[offset] & 0xFF) | ((data[offset + 1] & 0xFF) << 8);
+ if (comboBox.getModel().getSize() > selIndex) {
+ comboBox.setSelectedIndex(selIndex);
+ } else if (this.spCustomRB.isSelected()) {
+ JOptionPane.showMessageDialog(this,
+ bundle.getString("RandomizerGUI.starterUnavailable"));
+ }
+ }
+
+ private void restoreStates(byte b, AbstractButton... switches) {
+ int value = b & 0xFF;
+ for (int i = 0; i < switches.length; i++) {
+ int realValue = (value >> i) & 0x01;
+ switches[i].setSelected(realValue == 0x01);
+ }
+ }
+
+ private int readFullInt(byte[] data, int offset) {
+ ByteBuffer buf = ByteBuffer.allocate(4).put(data, offset, 4);
+ buf.rewind();
+ return buf.getInt();
+ }
+
+ private void writeFullInt(ByteArrayOutputStream baos, int checksum)
+ throws IOException {
+ byte[] crc = ByteBuffer.allocate(4).putInt(checksum).array();
+ baos.write(crc);
+
+ }
+
+ private void writePokemonIndex(ByteArrayOutputStream baos,
+ JComboBox comboBox) {
+ baos.write(comboBox.getSelectedIndex() & 0xFF);
+ baos.write((comboBox.getSelectedIndex() >> 8) & 0xFF);
+
+ }
+
+ private int makeByteSelected(AbstractButton... switches) {
+ if (switches.length > 8) {
+ // No can do
+ return 0;
+ }
+ int initial = 0;
+ int state = 1;
+ for (AbstractButton b : switches) {
+ initial |= b.isSelected() ? state : 0;
+ state *= 2;
+ }
+ return initial;
+ }
+
+ private int addToCV(int checkValue, int... values) {
+ for (int value : values) {
+ checkValue = Integer.rotateLeft(checkValue, 3);
+ checkValue ^= value;
+ }
+ return checkValue;
+ }
+
+ private void updateCodeTweaksButtonText() {
+ if (currentCodeTweaks == 0 || !codeTweaksCB.isSelected()) {
+ codeTweaksBtn.setText(bundle
+ .getString("RandomizerGUI.codeTweaksBtn.text"));
+ } else {
+ int ctCount = 0;
+ for (int i = 0; i < 32; i++) {
+ if ((currentCodeTweaks & (1 << i)) > 0) {
+ ctCount++;
+ }
+ }
+ codeTweaksBtn.setText(String.format(bundle
+ .getString("RandomizerGUI.codeTweaksBtn.textWithActive"),
+ ctCount));
+ }
+ }
+
+ // public response methods
+
+ public void updateFound(int newVersion, String changelog) {
+ new UpdateFoundDialog(this, newVersion, changelog);
+ }
+
+ public void noUpdateFound() {
+ JOptionPane.showMessageDialog(this,
+ bundle.getString("RandomizerGUI.noUpdates"));
+ }
+
+ public static String getRootPath() {
+ return rootPath;
+ }
+
+ // actions
+
+ private void updateSettingsButtonActionPerformed(
+ java.awt.event.ActionEvent evt) {// GEN-FIRST:event_updateSettingsButtonActionPerformed
+ if (autoUpdateEnabled) {
+ toggleAutoUpdatesMenuItem.setText(bundle
+ .getString("RandomizerGUI.disableAutoUpdate"));
+ } else {
+ toggleAutoUpdatesMenuItem.setText(bundle
+ .getString("RandomizerGUI.enableAutoUpdate"));
+ }
+ updateSettingsMenu.show(updateSettingsButton, 0,
+ updateSettingsButton.getHeight());
+ }// GEN-LAST:event_updateSettingsButtonActionPerformed
+
+ private void toggleAutoUpdatesMenuItemActionPerformed(
+ java.awt.event.ActionEvent evt) {// GEN-FIRST:event_toggleAutoUpdatesMenuItemActionPerformed
+ autoUpdateEnabled = !autoUpdateEnabled;
+ if (autoUpdateEnabled) {
+ JOptionPane.showMessageDialog(this,
+ bundle.getString("RandomizerGUI.autoUpdateEnabled"));
+ } else {
+ JOptionPane.showMessageDialog(this,
+ bundle.getString("RandomizerGUI.autoUpdateDisabled"));
+ }
+ attemptWriteConfig();
+ }// GEN-LAST:event_toggleAutoUpdatesMenuItemActionPerformed
+
+ private void manualUpdateMenuItemActionPerformed(
+ java.awt.event.ActionEvent evt) {// GEN-FIRST:event_manualUpdateMenuItemActionPerformed
+ new UpdateCheckThread(this, true).start();
+ }// GEN-LAST:event_manualUpdateMenuItemActionPerformed
+
+ private void loadQSButtonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_loadQSButtonActionPerformed
+ if (this.romHandler == null) {
+ return;
+ }
+ qsOpenChooser.setSelectedFile(null);
+ int returnVal = qsOpenChooser.showOpenDialog(this);
+ if (returnVal == JFileChooser.APPROVE_OPTION) {
+ File fh = qsOpenChooser.getSelectedFile();
+ try {
+ FileInputStream fis = new FileInputStream(fh);
+ int version = fis.read();
+ if (version < PRESET_FILE_VERSION) {
+ JOptionPane
+ .showMessageDialog(
+ this,
+ bundle.getString("RandomizerGUI.settingsFileOlder"));
+ fis.close();
+ return;
+ } else if (version > PRESET_FILE_VERSION) {
+ JOptionPane
+ .showMessageDialog(
+ this,
+ bundle.getString("RandomizerGUI.settingsFileNewer"));
+ fis.close();
+ return;
+ }
+ int cslength = fis.read();
+ byte[] csBuf = new byte[cslength];
+ fis.read(csBuf);
+ fis.close();
+ String configString = new String(csBuf, "UTF-8");
+ String romName = getValidRequiredROMName(configString,
+ new byte[] {}, new byte[] {}, new byte[] {});
+ if (romName == null) {
+ JOptionPane.showMessageDialog(this, bundle
+ .getString("RandomizerGUI.invalidSettingsFile"));
+ }
+ // now we just load it
+ initialFormState();
+ romLoaded();
+ restoreFrom(configString);
+ JCheckBox[] checkboxes = new JCheckBox[] { this.brokenMovesCB,
+ this.codeTweaksCB, this.goLowerCaseNamesCheckBox,
+ this.goNationalDexCheckBox,
+ this.goRemoveTradeEvosCheckBox,
+ this.goUpdateMovesCheckBox, this.goUpdateTypesCheckBox,
+ this.spHeldItemsCB, this.paWonderGuardCB,
+ this.raceModeCB, this.randomizeHollowsCB,
+ this.tcnRandomizeCB, this.tnRandomizeCB,
+ this.tpNoEarlyShedinjaCB, this.tpNoLegendariesCB,
+ this.tpPowerLevelsCB, this.tpRivalCarriesStarterCB,
+ this.tpTypeWeightingCB, this.wpCatchRateCB,
+ this.wpNoLegendariesCB, this.wpUseTimeCB,
+ this.igtRandomItemCB, this.igtRandomIVsCB,
+ this.igtRandomNicknameCB, this.igtRandomOTCB };
+ for (JCheckBox cb : checkboxes) {
+ if (!cb.isEnabled() || !cb.isVisible()) {
+ cb.setSelected(false);
+ }
+ }
+
+ if (!this.romHandler.canChangeStaticPokemon()) {
+ this.stpUnchangedRB.setSelected(true);
+ }
+
+ JOptionPane.showMessageDialog(this, String.format(
+ bundle.getString("RandomizerGUI.settingsLoaded"),
+ fh.getName()));
+ } catch (IOException ex) {
+ JOptionPane.showMessageDialog(this,
+ bundle.getString("RandomizerGUI.settingsLoadFailed"));
+ } catch (InvalidSupplementFilesException e) {
+ // not possible
+ }
+ }
+ }// GEN-LAST:event_loadQSButtonActionPerformed
+
+ private void saveQSButtonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_saveQSButtonActionPerformed
+ if (this.romHandler == null) {
+ return;
+ }
+ qsSaveChooser.setSelectedFile(null);
+ int returnVal = qsSaveChooser.showSaveDialog(this);
+ if (returnVal == JFileChooser.APPROVE_OPTION) {
+ File fh = qsSaveChooser.getSelectedFile();
+ // Fix or add extension
+ fh = FileFunctions.fixFilename(fh, "rnqs");
+ // Save now?
+ try {
+ FileOutputStream fos = new FileOutputStream(fh);
+ fos.write(PRESET_FILE_VERSION);
+ byte[] configString = getConfigString().getBytes("UTF-8");
+ fos.write(configString.length);
+ fos.write(configString);
+ fos.close();
+ } catch (IOException ex) {
+ JOptionPane.showMessageDialog(this,
+ bundle.getString("RandomizerGUI.settingsSaveFailed"));
+ }
+ }
+ }// GEN-LAST:event_saveQSButtonActionPerformed
+
+ private void codeTweaksBtnActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_codeTweaksBtnActionPerformed
+ CodeTweaksDialog ctd = new CodeTweaksDialog(this,
+ this.currentCodeTweaks, this.romHandler.codeTweaksAvailable());
+ if (ctd.pressedOK()) {
+ this.currentCodeTweaks = ctd.getChoice();
+ updateCodeTweaksButtonText();
+ }
+ }// GEN-LAST:event_codeTweaksBtnActionPerformed
+
+ private void pokeLimitBtnActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_pokeLimitBtnActionPerformed
+ GenerationLimitDialog gld = new GenerationLimitDialog(this,
+ this.currentRestrictions, this.romHandler.generationOfPokemon());
+ if (gld.pressedOK()) {
+ this.currentRestrictions = gld.getChoice();
+ }
+ }// GEN-LAST:event_pokeLimitBtnActionPerformed
+
+ private void goUpdateMovesCheckBoxActionPerformed(
+ java.awt.event.ActionEvent evt) {// GEN-FIRST:event_goUpdateMovesCheckBoxActionPerformed
+ this.enableOrDisableSubControls();
+ }// GEN-LAST:event_goUpdateMovesCheckBoxActionPerformed
+
+ private void codeTweaksCBActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_codeTweaksCBActionPerformed
+ this.enableOrDisableSubControls();
+ }// GEN-LAST:event_codeTweaksCBActionPerformed
+
+ private void pokeLimitCBActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_pokeLimitCBActionPerformed
+ this.enableOrDisableSubControls();
+ }// GEN-LAST:event_pokeLimitCBActionPerformed
+
+ private void pmsMetronomeOnlyRBActionPerformed(
+ java.awt.event.ActionEvent evt) {// GEN-FIRST:event_pmsMetronomeOnlyRBActionPerformed
+ this.enableOrDisableSubControls();
+ }// GEN-LAST:event_pmsMetronomeOnlyRBActionPerformed
+
+ private void igtUnchangedRBActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_igtUnchangedRBActionPerformed
+ this.enableOrDisableSubControls();
+ }// GEN-LAST:event_igtUnchangedRBActionPerformed
+
+ private void igtGivenOnlyRBActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_igtGivenOnlyRBActionPerformed
+ this.enableOrDisableSubControls();
+ }// GEN-LAST:event_igtGivenOnlyRBActionPerformed
+
+ private void igtBothRBActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_igtBothRBActionPerformed
+ this.enableOrDisableSubControls();
+ }// GEN-LAST:event_igtBothRBActionPerformed
+
+ private void wpARNoneRBActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_wpARNoneRBActionPerformed
+ this.enableOrDisableSubControls();
+ }// GEN-LAST:event_wpARNoneRBActionPerformed
+
+ private void wpARSimilarStrengthRBActionPerformed(
+ java.awt.event.ActionEvent evt) {// GEN-FIRST:event_wpARSimilarStrengthRBActionPerformed
+ this.enableOrDisableSubControls();
+ }// GEN-LAST:event_wpARSimilarStrengthRBActionPerformed
+
+ private void wpARCatchEmAllRBActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_wpARCatchEmAllRBActionPerformed
+ this.enableOrDisableSubControls();
+ }// GEN-LAST:event_wpARCatchEmAllRBActionPerformed
+
+ private void wpARTypeThemedRBActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_wpARTypeThemedRBActionPerformed
+ this.enableOrDisableSubControls();
+ }// GEN-LAST:event_wpARTypeThemedRBActionPerformed
+
+ private void pmsUnchangedRBActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_pmsUnchangedRBActionPerformed
+ this.enableOrDisableSubControls();
+ }// GEN-LAST:event_pmsUnchangedRBActionPerformed
+
+ private void pmsRandomTypeRBActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_pmsRandomTypeRBActionPerformed
+ this.enableOrDisableSubControls();
+ }// GEN-LAST:event_pmsRandomTypeRBActionPerformed
+
+ private void pmsRandomTotalRBActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_pmsRandomTotalRBActionPerformed
+ this.enableOrDisableSubControls();
+ }// GEN-LAST:event_pmsRandomTotalRBActionPerformed
+
+ private void mtmUnchangedRBActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_mtmUnchangedRBActionPerformed
+ this.enableOrDisableSubControls();
+ }// GEN-LAST:event_mtmUnchangedRBActionPerformed
+
+ private void paUnchangedRBActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_paUnchangedRBActionPerformed
+ this.enableOrDisableSubControls();
+ }// GEN-LAST:event_paUnchangedRBActionPerformed
+
+ private void paRandomizeRBActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_paRandomizeRBActionPerformed
+ this.enableOrDisableSubControls();
+ }// GEN-LAST:event_paRandomizeRBActionPerformed
+
+ private void aboutButtonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_aboutButtonActionPerformed
+ new AboutDialog(this, true).setVisible(true);
+ }// GEN-LAST:event_aboutButtonActionPerformed
+
+ private void openROMButtonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_openROMButtonActionPerformed
+ loadROM();
+ }// GEN-LAST:event_openROMButtonActionPerformed
+
+ private void saveROMButtonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_saveROMButtonActionPerformed
+ saveROM();
+ }// GEN-LAST:event_saveROMButtonActionPerformed
+
+ private void usePresetsButtonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_usePresetsButtonActionPerformed
+ presetLoader();
+ }// GEN-LAST:event_usePresetsButtonActionPerformed
+
+ private void wpUnchangedRBActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_wpUnchangedRBActionPerformed
+ this.enableOrDisableSubControls();
+ }// GEN-LAST:event_wpUnchangedRBActionPerformed
+
+ private void tpUnchangedRBActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_tpUnchangedRBActionPerformed
+ this.enableOrDisableSubControls();
+ }// GEN-LAST:event_tpUnchangedRBActionPerformed
+
+ private void tpRandomRBActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_tpRandomRBActionPerformed
+ this.enableOrDisableSubControls();
+ }// GEN-LAST:event_tpRandomRBActionPerformed
+
+ private void tpTypeThemedRBActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_tpTypeThemedRBActionPerformed
+ this.enableOrDisableSubControls();
+ }// GEN-LAST:event_tpTypeThemedRBActionPerformed
+
+ private void spUnchangedRBActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_spUnchangedRBActionPerformed
+ this.enableOrDisableSubControls();
+ }// GEN-LAST:event_spUnchangedRBActionPerformed
+
+ private void spCustomRBActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_spCustomRBActionPerformed
+ this.enableOrDisableSubControls();
+ }// GEN-LAST:event_spCustomRBActionPerformed
+
+ private void spRandomRBActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_spRandomRBActionPerformed
+ this.enableOrDisableSubControls();
+ }// GEN-LAST:event_spRandomRBActionPerformed
+
+ private void wpRandomRBActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_wpRandomRBActionPerformed
+ this.enableOrDisableSubControls();
+ }// GEN-LAST:event_wpRandomRBActionPerformed
+
+ private void wpArea11RBActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_wpArea11RBActionPerformed
+ this.enableOrDisableSubControls();
+ }// GEN-LAST:event_wpArea11RBActionPerformed
+
+ private void wpGlobalRBActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_wpGlobalRBActionPerformed
+ this.enableOrDisableSubControls();
+ }// GEN-LAST:event_wpGlobalRBActionPerformed
+
+ /**
+ * This method is called from within the constructor to initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is always
+ * regenerated by the Form Editor.
+ */
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ pokeStatChangesButtonGroup = new javax.swing.ButtonGroup();
+ pokeTypesButtonGroup = new javax.swing.ButtonGroup();
+ pokeMovesetsButtonGroup = new javax.swing.ButtonGroup();
+ trainerPokesButtonGroup = new javax.swing.ButtonGroup();
+ wildPokesButtonGroup = new javax.swing.ButtonGroup();
+ wildPokesARuleButtonGroup = new javax.swing.ButtonGroup();
+ starterPokemonButtonGroup = new javax.swing.ButtonGroup();
+ romOpenChooser = new javax.swing.JFileChooser();
+ romSaveChooser = new JFileChooser() {
+
+ private static final long serialVersionUID = 3244234325234511L;
+
+ public void approveSelection() {
+ File fh = getSelectedFile();
+ // Fix or add extension
+ List extensions = new ArrayList(Arrays.asList(
+ "sgb", "gbc", "gba", "nds"));
+ extensions.remove(RandomizerGUI.this.romHandler
+ .getDefaultExtension());
+ fh = FileFunctions.fixFilename(fh,
+ RandomizerGUI.this.romHandler.getDefaultExtension(),
+ extensions);
+ if (fh.exists() && getDialogType() == SAVE_DIALOG) {
+ int result = JOptionPane.showConfirmDialog(this,
+ "The file exists, overwrite?", "Existing file",
+ JOptionPane.YES_NO_CANCEL_OPTION);
+ switch (result) {
+ case JOptionPane.YES_OPTION:
+ super.approveSelection();
+ return;
+ case JOptionPane.CANCEL_OPTION:
+ cancelSelection();
+ return;
+ default:
+ return;
+ }
+ }
+ super.approveSelection();
+ }
+ };
+ qsOpenChooser = new javax.swing.JFileChooser();
+ qsSaveChooser = new javax.swing.JFileChooser();
+ staticPokemonButtonGroup = new javax.swing.ButtonGroup();
+ tmMovesButtonGroup = new javax.swing.ButtonGroup();
+ tmHmCompatibilityButtonGroup = new javax.swing.ButtonGroup();
+ pokeAbilitiesButtonGroup = new javax.swing.ButtonGroup();
+ mtMovesButtonGroup = new javax.swing.ButtonGroup();
+ mtCompatibilityButtonGroup = new javax.swing.ButtonGroup();
+ ingameTradesButtonGroup = new javax.swing.ButtonGroup();
+ fieldItemsButtonGroup = new javax.swing.ButtonGroup();
+ updateSettingsMenu = new javax.swing.JPopupMenu();
+ toggleAutoUpdatesMenuItem = new javax.swing.JMenuItem();
+ manualUpdateMenuItem = new javax.swing.JMenuItem();
+ generalOptionsPanel = new javax.swing.JPanel();
+ goUpdateTypesCheckBox = new javax.swing.JCheckBox();
+ goUpdateMovesCheckBox = new javax.swing.JCheckBox();
+ goRemoveTradeEvosCheckBox = new javax.swing.JCheckBox();
+ goLowerCaseNamesCheckBox = new javax.swing.JCheckBox();
+ goNationalDexCheckBox = new javax.swing.JCheckBox();
+ goUpdateMovesLegacyCheckBox = new javax.swing.JCheckBox();
+ romInfoPanel = new javax.swing.JPanel();
+ riRomNameLabel = new javax.swing.JLabel();
+ riRomCodeLabel = new javax.swing.JLabel();
+ riRomSupportLabel = new javax.swing.JLabel();
+ optionsScrollPane = new javax.swing.JScrollPane();
+ optionsScrollPane.getVerticalScrollBar().setUnitIncrement(16);
+ optionsContainerPanel = new javax.swing.JPanel();
+ baseStatsPanel = new javax.swing.JPanel();
+ pbsChangesUnchangedRB = new javax.swing.JRadioButton();
+ pbsChangesShuffleRB = new javax.swing.JRadioButton();
+ pbsChangesRandomEvosRB = new javax.swing.JRadioButton();
+ pbsChangesRandomTotalRB = new javax.swing.JRadioButton();
+ pbsStandardEXPCurvesCB = new javax.swing.JCheckBox();
+ pokemonTypesPanel = new javax.swing.JPanel();
+ ptUnchangedRB = new javax.swing.JRadioButton();
+ ptRandomFollowEvosRB = new javax.swing.JRadioButton();
+ ptRandomTotalRB = new javax.swing.JRadioButton();
+ pokemonMovesetsPanel = new javax.swing.JPanel();
+ pmsUnchangedRB = new javax.swing.JRadioButton();
+ pmsRandomTypeRB = new javax.swing.JRadioButton();
+ pmsRandomTotalRB = new javax.swing.JRadioButton();
+ pmsMetronomeOnlyRB = new javax.swing.JRadioButton();
+ pms4MovesCB = new javax.swing.JCheckBox();
+ trainersPokemonPanel = new javax.swing.JPanel();
+ tpUnchangedRB = new javax.swing.JRadioButton();
+ tpRandomRB = new javax.swing.JRadioButton();
+ tpTypeThemedRB = new javax.swing.JRadioButton();
+ tpPowerLevelsCB = new javax.swing.JCheckBox();
+ tpTypeWeightingCB = new javax.swing.JCheckBox();
+ tpRivalCarriesStarterCB = new javax.swing.JCheckBox();
+ tpNoLegendariesCB = new javax.swing.JCheckBox();
+ tnRandomizeCB = new javax.swing.JCheckBox();
+ tcnRandomizeCB = new javax.swing.JCheckBox();
+ tpNoEarlyShedinjaCB = new javax.swing.JCheckBox();
+ wildPokemonPanel = new javax.swing.JPanel();
+ wpUnchangedRB = new javax.swing.JRadioButton();
+ wpRandomRB = new javax.swing.JRadioButton();
+ wpArea11RB = new javax.swing.JRadioButton();
+ wpGlobalRB = new javax.swing.JRadioButton();
+ wildPokemonARulePanel = new javax.swing.JPanel();
+ wpARNoneRB = new javax.swing.JRadioButton();
+ wpARCatchEmAllRB = new javax.swing.JRadioButton();
+ wpARTypeThemedRB = new javax.swing.JRadioButton();
+ wpARSimilarStrengthRB = new javax.swing.JRadioButton();
+ wpUseTimeCB = new javax.swing.JCheckBox();
+ wpNoLegendariesCB = new javax.swing.JCheckBox();
+ wpCatchRateCB = new javax.swing.JCheckBox();
+ wpHeldItemsCB = new javax.swing.JCheckBox();
+ starterPokemonPanel = new javax.swing.JPanel();
+ spUnchangedRB = new javax.swing.JRadioButton();
+ spCustomRB = new javax.swing.JRadioButton();
+ spCustomPoke1Chooser = new javax.swing.JComboBox();
+ spCustomPoke2Chooser = new javax.swing.JComboBox();
+ spCustomPoke3Chooser = new javax.swing.JComboBox();
+ spRandomRB = new javax.swing.JRadioButton();
+ spRandom2EvosRB = new javax.swing.JRadioButton();
+ spHeldItemsCB = new javax.swing.JCheckBox();
+ staticPokemonPanel = new javax.swing.JPanel();
+ stpUnchangedRB = new javax.swing.JRadioButton();
+ stpRandomL4LRB = new javax.swing.JRadioButton();
+ stpRandomTotalRB = new javax.swing.JRadioButton();
+ tmhmsPanel = new javax.swing.JPanel();
+ tmMovesPanel = new javax.swing.JPanel();
+ tmmUnchangedRB = new javax.swing.JRadioButton();
+ tmmRandomRB = new javax.swing.JRadioButton();
+ tmHmCompatPanel = new javax.swing.JPanel();
+ thcUnchangedRB = new javax.swing.JRadioButton();
+ thcRandomTypeRB = new javax.swing.JRadioButton();
+ thcRandomTotalRB = new javax.swing.JRadioButton();
+ abilitiesPanel = new javax.swing.JPanel();
+ paUnchangedRB = new javax.swing.JRadioButton();
+ paRandomizeRB = new javax.swing.JRadioButton();
+ paWonderGuardCB = new javax.swing.JCheckBox();
+ moveTutorsPanel = new javax.swing.JPanel();
+ mtMovesPanel = new javax.swing.JPanel();
+ mtmUnchangedRB = new javax.swing.JRadioButton();
+ mtmRandomRB = new javax.swing.JRadioButton();
+ mtCompatPanel = new javax.swing.JPanel();
+ mtcUnchangedRB = new javax.swing.JRadioButton();
+ mtcRandomTypeRB = new javax.swing.JRadioButton();
+ mtcRandomTotalRB = new javax.swing.JRadioButton();
+ mtNoExistLabel = new javax.swing.JLabel();
+ inGameTradesPanel = new javax.swing.JPanel();
+ igtUnchangedRB = new javax.swing.JRadioButton();
+ igtGivenOnlyRB = new javax.swing.JRadioButton();
+ igtBothRB = new javax.swing.JRadioButton();
+ igtRandomNicknameCB = new javax.swing.JCheckBox();
+ igtRandomOTCB = new javax.swing.JCheckBox();
+ igtRandomIVsCB = new javax.swing.JCheckBox();
+ igtRandomItemCB = new javax.swing.JCheckBox();
+ fieldItemsPanel = new javax.swing.JPanel();
+ fiUnchangedRB = new javax.swing.JRadioButton();
+ fiShuffleRB = new javax.swing.JRadioButton();
+ fiRandomRB = new javax.swing.JRadioButton();
+ openROMButton = new javax.swing.JButton();
+ saveROMButton = new javax.swing.JButton();
+ usePresetsButton = new javax.swing.JButton();
+ aboutButton = new javax.swing.JButton();
+ otherOptionsPanel = new javax.swing.JPanel();
+ codeTweaksCB = new javax.swing.JCheckBox();
+ raceModeCB = new javax.swing.JCheckBox();
+ randomizeHollowsCB = new javax.swing.JCheckBox();
+ brokenMovesCB = new javax.swing.JCheckBox();
+ codeTweaksBtn = new javax.swing.JButton();
+ pokeLimitCB = new javax.swing.JCheckBox();
+ pokeLimitBtn = new javax.swing.JButton();
+ loadQSButton = new javax.swing.JButton();
+ saveQSButton = new javax.swing.JButton();
+ updateSettingsButton = new javax.swing.JButton();
+
+ romOpenChooser.setFileFilter(new ROMFilter());
+
+ romSaveChooser.setDialogType(javax.swing.JFileChooser.SAVE_DIALOG);
+ romSaveChooser.setFileFilter(new ROMFilter());
+
+ qsOpenChooser.setFileFilter(new QSFileFilter());
+
+ qsSaveChooser.setDialogType(javax.swing.JFileChooser.SAVE_DIALOG);
+ qsSaveChooser.setFileFilter(new QSFileFilter());
+
+ java.util.ResourceBundle bundle = java.util.ResourceBundle
+ .getBundle("com/dabomstew/pkrandom/gui/Bundle"); // NOI18N
+ toggleAutoUpdatesMenuItem.setText(bundle
+ .getString("RandomizerGUI.toggleAutoUpdatesMenuItem.text")); // NOI18N
+ toggleAutoUpdatesMenuItem
+ .addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ toggleAutoUpdatesMenuItemActionPerformed(evt);
+ }
+ });
+ updateSettingsMenu.add(toggleAutoUpdatesMenuItem);
+
+ manualUpdateMenuItem.setText(bundle
+ .getString("RandomizerGUI.manualUpdateMenuItem.text")); // NOI18N
+ manualUpdateMenuItem
+ .addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ manualUpdateMenuItemActionPerformed(evt);
+ }
+ });
+ updateSettingsMenu.add(manualUpdateMenuItem);
+
+ setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
+ setTitle(bundle.getString("RandomizerGUI.title")); // NOI18N
+
+ generalOptionsPanel
+ .setBorder(javax.swing.BorderFactory.createTitledBorder(
+ null,
+ bundle.getString("RandomizerGUI.generalOptionsPanel.border.title"),
+ javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION,
+ javax.swing.border.TitledBorder.DEFAULT_POSITION,
+ new java.awt.Font("Tahoma", 1, 11))); // NOI18N
+
+ goUpdateTypesCheckBox.setText(bundle
+ .getString("RandomizerGUI.goUpdateTypesCheckBox.text")); // NOI18N
+ goUpdateTypesCheckBox.setToolTipText(bundle
+ .getString("RandomizerGUI.goUpdateTypesCheckBox.toolTipText")); // NOI18N
+
+ goUpdateMovesCheckBox.setText(bundle
+ .getString("RandomizerGUI.goUpdateMovesCheckBox.text")); // NOI18N
+ goUpdateMovesCheckBox.setToolTipText(bundle
+ .getString("RandomizerGUI.goUpdateMovesCheckBox.toolTipText")); // NOI18N
+ goUpdateMovesCheckBox
+ .addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ goUpdateMovesCheckBoxActionPerformed(evt);
+ }
+ });
+
+ goRemoveTradeEvosCheckBox.setText(bundle
+ .getString("RandomizerGUI.goRemoveTradeEvosCheckBox.text")); // NOI18N
+ goRemoveTradeEvosCheckBox
+ .setToolTipText(bundle
+ .getString("RandomizerGUI.goRemoveTradeEvosCheckBox.toolTipText")); // NOI18N
+
+ goLowerCaseNamesCheckBox.setText(bundle
+ .getString("RandomizerGUI.goLowerCaseNamesCheckBox.text")); // NOI18N
+ goLowerCaseNamesCheckBox
+ .setToolTipText(bundle
+ .getString("RandomizerGUI.goLowerCaseNamesCheckBox.toolTipText")); // NOI18N
+
+ goNationalDexCheckBox.setText(bundle
+ .getString("RandomizerGUI.goNationalDexCheckBox.text")); // NOI18N
+ goNationalDexCheckBox.setToolTipText(bundle
+ .getString("RandomizerGUI.goNationalDexCheckBox.toolTipText")); // NOI18N
+
+ goUpdateMovesLegacyCheckBox.setText(bundle
+ .getString("RandomizerGUI.goUpdateMovesLegacyCheckBox.text")); // NOI18N
+ goUpdateMovesLegacyCheckBox
+ .setToolTipText(bundle
+ .getString("RandomizerGUI.goUpdateMovesLegacyCheckBox.toolTipText")); // NOI18N
+
+ javax.swing.GroupLayout generalOptionsPanelLayout = new javax.swing.GroupLayout(
+ generalOptionsPanel);
+ generalOptionsPanel.setLayout(generalOptionsPanelLayout);
+ generalOptionsPanelLayout
+ .setHorizontalGroup(generalOptionsPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ generalOptionsPanelLayout
+ .createSequentialGroup()
+ .addContainerGap()
+ .addGroup(
+ generalOptionsPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ generalOptionsPanelLayout
+ .createSequentialGroup()
+ .addGroup(
+ generalOptionsPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(
+ goUpdateTypesCheckBox)
+ .addComponent(
+ goRemoveTradeEvosCheckBox)
+ .addComponent(
+ goNationalDexCheckBox))
+ .addContainerGap(
+ 14,
+ Short.MAX_VALUE))
+ .addGroup(
+ generalOptionsPanelLayout
+ .createSequentialGroup()
+ .addGroup(
+ generalOptionsPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ generalOptionsPanelLayout
+ .createSequentialGroup()
+ .addComponent(
+ goUpdateMovesCheckBox)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(
+ goUpdateMovesLegacyCheckBox))
+ .addComponent(
+ goLowerCaseNamesCheckBox))
+ .addGap(0,
+ 0,
+ Short.MAX_VALUE)))));
+ generalOptionsPanelLayout
+ .setVerticalGroup(generalOptionsPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ generalOptionsPanelLayout
+ .createSequentialGroup()
+ .addComponent(goUpdateTypesCheckBox)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(
+ generalOptionsPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(
+ goUpdateMovesCheckBox)
+ .addComponent(
+ goUpdateMovesLegacyCheckBox))
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(goRemoveTradeEvosCheckBox)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(goLowerCaseNamesCheckBox)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(goNationalDexCheckBox)
+ .addContainerGap(
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)));
+
+ romInfoPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(
+ null,
+ bundle.getString("RandomizerGUI.romInfoPanel.border.title"),
+ javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION,
+ javax.swing.border.TitledBorder.DEFAULT_POSITION,
+ new java.awt.Font("Tahoma", 1, 11))); // NOI18N
+
+ riRomNameLabel.setText(bundle
+ .getString("RandomizerGUI.riRomNameLabel.text")); // NOI18N
+
+ riRomCodeLabel.setText(bundle
+ .getString("RandomizerGUI.riRomCodeLabel.text")); // NOI18N
+
+ riRomSupportLabel.setText(bundle
+ .getString("RandomizerGUI.riRomSupportLabel.text")); // NOI18N
+
+ javax.swing.GroupLayout romInfoPanelLayout = new javax.swing.GroupLayout(
+ romInfoPanel);
+ romInfoPanel.setLayout(romInfoPanelLayout);
+ romInfoPanelLayout
+ .setHorizontalGroup(romInfoPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ romInfoPanelLayout
+ .createSequentialGroup()
+ .addContainerGap()
+ .addGroup(
+ romInfoPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(
+ riRomNameLabel)
+ .addComponent(
+ riRomCodeLabel)
+ .addComponent(
+ riRomSupportLabel))
+ .addContainerGap(
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)));
+ romInfoPanelLayout
+ .setVerticalGroup(romInfoPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ romInfoPanelLayout
+ .createSequentialGroup()
+ .addGap(5, 5, 5)
+ .addComponent(riRomNameLabel)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(riRomCodeLabel)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(riRomSupportLabel)
+ .addContainerGap(
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)));
+
+ baseStatsPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(
+ null,
+ bundle.getString("RandomizerGUI.baseStatsPanel.border.title"),
+ javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION,
+ javax.swing.border.TitledBorder.DEFAULT_POSITION,
+ new java.awt.Font("Tahoma", 1, 11))); // NOI18N
+
+ pokeStatChangesButtonGroup.add(pbsChangesUnchangedRB);
+ pbsChangesUnchangedRB.setSelected(true);
+ pbsChangesUnchangedRB.setText(bundle
+ .getString("RandomizerGUI.pbsChangesUnchangedRB.text")); // NOI18N
+ pbsChangesUnchangedRB.setToolTipText(bundle
+ .getString("RandomizerGUI.pbsChangesUnchangedRB.toolTipText")); // NOI18N
+
+ pokeStatChangesButtonGroup.add(pbsChangesShuffleRB);
+ pbsChangesShuffleRB.setText(bundle
+ .getString("RandomizerGUI.pbsChangesShuffleRB.text")); // NOI18N
+ pbsChangesShuffleRB.setToolTipText(bundle
+ .getString("RandomizerGUI.pbsChangesShuffleRB.toolTipText")); // NOI18N
+
+ pokeStatChangesButtonGroup.add(pbsChangesRandomEvosRB);
+ pbsChangesRandomEvosRB.setText(bundle
+ .getString("RandomizerGUI.pbsChangesRandomEvosRB.text")); // NOI18N
+ pbsChangesRandomEvosRB.setToolTipText(bundle
+ .getString("RandomizerGUI.pbsChangesRandomEvosRB.toolTipText")); // NOI18N
+
+ pokeStatChangesButtonGroup.add(pbsChangesRandomTotalRB);
+ pbsChangesRandomTotalRB.setText(bundle
+ .getString("RandomizerGUI.pbsChangesRandomTotalRB.text")); // NOI18N
+ pbsChangesRandomTotalRB
+ .setToolTipText(bundle
+ .getString("RandomizerGUI.pbsChangesRandomTotalRB.toolTipText")); // NOI18N
+
+ pbsStandardEXPCurvesCB.setText(bundle
+ .getString("RandomizerGUI.pbsStandardEXPCurvesCB.text")); // NOI18N
+ pbsStandardEXPCurvesCB.setToolTipText(bundle
+ .getString("RandomizerGUI.pbsStandardEXPCurvesCB.toolTipText")); // NOI18N
+
+ javax.swing.GroupLayout baseStatsPanelLayout = new javax.swing.GroupLayout(
+ baseStatsPanel);
+ baseStatsPanel.setLayout(baseStatsPanelLayout);
+ baseStatsPanelLayout
+ .setHorizontalGroup(baseStatsPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ baseStatsPanelLayout
+ .createSequentialGroup()
+ .addContainerGap()
+ .addGroup(
+ baseStatsPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ baseStatsPanelLayout
+ .createSequentialGroup()
+ .addGroup(
+ baseStatsPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(
+ pbsChangesUnchangedRB)
+ .addComponent(
+ pbsChangesRandomEvosRB)
+ .addComponent(
+ pbsChangesRandomTotalRB))
+ .addContainerGap(
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE))
+ .addGroup(
+ baseStatsPanelLayout
+ .createSequentialGroup()
+ .addComponent(
+ pbsChangesShuffleRB)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.RELATED,
+ 125,
+ Short.MAX_VALUE)
+ .addComponent(
+ pbsStandardEXPCurvesCB)
+ .addGap(38,
+ 38,
+ 38)))));
+ baseStatsPanelLayout
+ .setVerticalGroup(baseStatsPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ baseStatsPanelLayout
+ .createSequentialGroup()
+ .addContainerGap()
+ .addComponent(pbsChangesUnchangedRB)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addGroup(
+ baseStatsPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(
+ pbsChangesShuffleRB)
+ .addComponent(
+ pbsStandardEXPCurvesCB))
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(pbsChangesRandomEvosRB)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(pbsChangesRandomTotalRB)
+ .addContainerGap(
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)));
+
+ pokemonTypesPanel
+ .setBorder(javax.swing.BorderFactory.createTitledBorder(
+ null,
+ bundle.getString("RandomizerGUI.pokemonTypesPanel.border.title"),
+ javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION,
+ javax.swing.border.TitledBorder.DEFAULT_POSITION,
+ new java.awt.Font("Tahoma", 1, 11))); // NOI18N
+
+ pokeTypesButtonGroup.add(ptUnchangedRB);
+ ptUnchangedRB.setSelected(true);
+ ptUnchangedRB.setText(bundle
+ .getString("RandomizerGUI.ptUnchangedRB.text")); // NOI18N
+ ptUnchangedRB.setToolTipText(bundle
+ .getString("RandomizerGUI.ptUnchangedRB.toolTipText")); // NOI18N
+
+ pokeTypesButtonGroup.add(ptRandomFollowEvosRB);
+ ptRandomFollowEvosRB.setText(bundle
+ .getString("RandomizerGUI.ptRandomFollowEvosRB.text")); // NOI18N
+ ptRandomFollowEvosRB.setToolTipText(bundle
+ .getString("RandomizerGUI.ptRandomFollowEvosRB.toolTipText")); // NOI18N
+
+ pokeTypesButtonGroup.add(ptRandomTotalRB);
+ ptRandomTotalRB.setText(bundle
+ .getString("RandomizerGUI.ptRandomTotalRB.text")); // NOI18N
+ ptRandomTotalRB.setToolTipText(bundle
+ .getString("RandomizerGUI.ptRandomTotalRB.toolTipText")); // NOI18N
+
+ javax.swing.GroupLayout pokemonTypesPanelLayout = new javax.swing.GroupLayout(
+ pokemonTypesPanel);
+ pokemonTypesPanel.setLayout(pokemonTypesPanelLayout);
+ pokemonTypesPanelLayout
+ .setHorizontalGroup(pokemonTypesPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ pokemonTypesPanelLayout
+ .createSequentialGroup()
+ .addContainerGap()
+ .addGroup(
+ pokemonTypesPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(
+ ptUnchangedRB)
+ .addComponent(
+ ptRandomFollowEvosRB)
+ .addComponent(
+ ptRandomTotalRB))
+ .addContainerGap(
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)));
+ pokemonTypesPanelLayout
+ .setVerticalGroup(pokemonTypesPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ pokemonTypesPanelLayout
+ .createSequentialGroup()
+ .addContainerGap()
+ .addComponent(ptUnchangedRB)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(ptRandomFollowEvosRB)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(ptRandomTotalRB)
+ .addContainerGap(
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)));
+
+ pokemonMovesetsPanel
+ .setBorder(javax.swing.BorderFactory.createTitledBorder(
+ null,
+ bundle.getString("RandomizerGUI.pokemonMovesetsPanel.border.title"),
+ javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION,
+ javax.swing.border.TitledBorder.DEFAULT_POSITION,
+ new java.awt.Font("Tahoma", 1, 11))); // NOI18N
+
+ pokeMovesetsButtonGroup.add(pmsUnchangedRB);
+ pmsUnchangedRB.setSelected(true);
+ pmsUnchangedRB.setText(bundle
+ .getString("RandomizerGUI.pmsUnchangedRB.text")); // NOI18N
+ pmsUnchangedRB.setToolTipText(bundle
+ .getString("RandomizerGUI.pmsUnchangedRB.toolTipText")); // NOI18N
+ pmsUnchangedRB.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ pmsUnchangedRBActionPerformed(evt);
+ }
+ });
+
+ pokeMovesetsButtonGroup.add(pmsRandomTypeRB);
+ pmsRandomTypeRB.setText(bundle
+ .getString("RandomizerGUI.pmsRandomTypeRB.text")); // NOI18N
+ pmsRandomTypeRB.setToolTipText(bundle
+ .getString("RandomizerGUI.pmsRandomTypeRB.toolTipText")); // NOI18N
+ pmsRandomTypeRB.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ pmsRandomTypeRBActionPerformed(evt);
+ }
+ });
+
+ pokeMovesetsButtonGroup.add(pmsRandomTotalRB);
+ pmsRandomTotalRB.setText(bundle
+ .getString("RandomizerGUI.pmsRandomTotalRB.text")); // NOI18N
+ pmsRandomTotalRB.setToolTipText(bundle
+ .getString("RandomizerGUI.pmsRandomTotalRB.toolTipText")); // NOI18N
+ pmsRandomTotalRB.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ pmsRandomTotalRBActionPerformed(evt);
+ }
+ });
+
+ pokeMovesetsButtonGroup.add(pmsMetronomeOnlyRB);
+ pmsMetronomeOnlyRB.setText(bundle
+ .getString("RandomizerGUI.pmsMetronomeOnlyRB.text")); // NOI18N
+ pmsMetronomeOnlyRB.setToolTipText(bundle
+ .getString("RandomizerGUI.pmsMetronomeOnlyRB.toolTipText")); // NOI18N
+ pmsMetronomeOnlyRB
+ .addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ pmsMetronomeOnlyRBActionPerformed(evt);
+ }
+ });
+
+ pms4MovesCB.setText(bundle.getString("RandomizerGUI.pms4MovesCB.text")); // NOI18N
+ pms4MovesCB.setToolTipText(bundle
+ .getString("RandomizerGUI.pms4MovesCB.toolTipText")); // NOI18N
+
+ javax.swing.GroupLayout pokemonMovesetsPanelLayout = new javax.swing.GroupLayout(
+ pokemonMovesetsPanel);
+ pokemonMovesetsPanel.setLayout(pokemonMovesetsPanelLayout);
+ pokemonMovesetsPanelLayout
+ .setHorizontalGroup(pokemonMovesetsPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ pokemonMovesetsPanelLayout
+ .createSequentialGroup()
+ .addContainerGap()
+ .addGroup(
+ pokemonMovesetsPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(
+ pmsUnchangedRB)
+ .addGroup(
+ pokemonMovesetsPanelLayout
+ .createSequentialGroup()
+ .addComponent(
+ pmsRandomTypeRB)
+ .addGap(198,
+ 198,
+ 198)
+ .addComponent(
+ pms4MovesCB))
+ .addComponent(
+ pmsRandomTotalRB)
+ .addComponent(
+ pmsMetronomeOnlyRB))
+ .addContainerGap(134, Short.MAX_VALUE)));
+ pokemonMovesetsPanelLayout
+ .setVerticalGroup(pokemonMovesetsPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ pokemonMovesetsPanelLayout
+ .createSequentialGroup()
+ .addContainerGap(
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)
+ .addComponent(pmsUnchangedRB)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addGroup(
+ pokemonMovesetsPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(
+ pmsRandomTypeRB)
+ .addComponent(
+ pms4MovesCB))
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(pmsRandomTotalRB)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(pmsMetronomeOnlyRB)));
+
+ trainersPokemonPanel
+ .setBorder(javax.swing.BorderFactory.createTitledBorder(
+ null,
+ bundle.getString("RandomizerGUI.trainersPokemonPanel.border.title"),
+ javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION,
+ javax.swing.border.TitledBorder.DEFAULT_POSITION,
+ new java.awt.Font("Tahoma", 1, 11))); // NOI18N
+
+ trainerPokesButtonGroup.add(tpUnchangedRB);
+ tpUnchangedRB.setSelected(true);
+ tpUnchangedRB.setText(bundle
+ .getString("RandomizerGUI.tpUnchangedRB.text")); // NOI18N
+ tpUnchangedRB.setToolTipText(bundle
+ .getString("RandomizerGUI.tpUnchangedRB.toolTipText")); // NOI18N
+ tpUnchangedRB.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ tpUnchangedRBActionPerformed(evt);
+ }
+ });
+
+ trainerPokesButtonGroup.add(tpRandomRB);
+ tpRandomRB.setText(bundle.getString("RandomizerGUI.tpRandomRB.text")); // NOI18N
+ tpRandomRB.setToolTipText(bundle
+ .getString("RandomizerGUI.tpRandomRB.toolTipText")); // NOI18N
+ tpRandomRB.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ tpRandomRBActionPerformed(evt);
+ }
+ });
+
+ trainerPokesButtonGroup.add(tpTypeThemedRB);
+ tpTypeThemedRB.setText(bundle
+ .getString("RandomizerGUI.tpTypeThemedRB.text")); // NOI18N
+ tpTypeThemedRB.setToolTipText(bundle
+ .getString("RandomizerGUI.tpTypeThemedRB.toolTipText")); // NOI18N
+ tpTypeThemedRB.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ tpTypeThemedRBActionPerformed(evt);
+ }
+ });
+
+ tpPowerLevelsCB.setText(bundle
+ .getString("RandomizerGUI.tpPowerLevelsCB.text")); // NOI18N
+ tpPowerLevelsCB.setToolTipText(bundle
+ .getString("RandomizerGUI.tpPowerLevelsCB.toolTipText")); // NOI18N
+ tpPowerLevelsCB.setEnabled(false);
+
+ tpTypeWeightingCB.setText(bundle
+ .getString("RandomizerGUI.tpTypeWeightingCB.text")); // NOI18N
+ tpTypeWeightingCB.setToolTipText(bundle
+ .getString("RandomizerGUI.tpTypeWeightingCB.toolTipText")); // NOI18N
+ tpTypeWeightingCB.setEnabled(false);
+
+ tpRivalCarriesStarterCB.setText(bundle
+ .getString("RandomizerGUI.tpRivalCarriesStarterCB.text")); // NOI18N
+ tpRivalCarriesStarterCB
+ .setToolTipText(bundle
+ .getString("RandomizerGUI.tpRivalCarriesStarterCB.toolTipText")); // NOI18N
+ tpRivalCarriesStarterCB.setEnabled(false);
+
+ tpNoLegendariesCB.setText(bundle
+ .getString("RandomizerGUI.tpNoLegendariesCB.text")); // NOI18N
+ tpNoLegendariesCB.setEnabled(false);
+
+ tnRandomizeCB.setText(bundle
+ .getString("RandomizerGUI.tnRandomizeCB.text")); // NOI18N
+ tnRandomizeCB.setToolTipText(bundle
+ .getString("RandomizerGUI.tnRandomizeCB.toolTipText")); // NOI18N
+
+ tcnRandomizeCB.setText(bundle
+ .getString("RandomizerGUI.tcnRandomizeCB.text")); // NOI18N
+ tcnRandomizeCB.setToolTipText(bundle
+ .getString("RandomizerGUI.tcnRandomizeCB.toolTipText")); // NOI18N
+
+ tpNoEarlyShedinjaCB.setText(bundle
+ .getString("RandomizerGUI.tpNoEarlyShedinjaCB.text")); // NOI18N
+ tpNoEarlyShedinjaCB.setToolTipText(bundle
+ .getString("RandomizerGUI.tpNoEarlyShedinjaCB.toolTipText")); // NOI18N
+
+ javax.swing.GroupLayout trainersPokemonPanelLayout = new javax.swing.GroupLayout(
+ trainersPokemonPanel);
+ trainersPokemonPanel.setLayout(trainersPokemonPanelLayout);
+ trainersPokemonPanelLayout
+ .setHorizontalGroup(trainersPokemonPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ trainersPokemonPanelLayout
+ .createSequentialGroup()
+ .addContainerGap()
+ .addGroup(
+ trainersPokemonPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(
+ tpTypeThemedRB)
+ .addGroup(
+ trainersPokemonPanelLayout
+ .createSequentialGroup()
+ .addGroup(
+ trainersPokemonPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(
+ tpUnchangedRB)
+ .addComponent(
+ tpRandomRB))
+ .addGap(47,
+ 47,
+ 47)
+ .addGroup(
+ trainersPokemonPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(
+ tpNoEarlyShedinjaCB)
+ .addGroup(
+ trainersPokemonPanelLayout
+ .createSequentialGroup()
+ .addGroup(
+ trainersPokemonPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING,
+ false)
+ .addComponent(
+ tpTypeWeightingCB,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)
+ .addComponent(
+ tpRivalCarriesStarterCB,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)
+ .addComponent(
+ tpPowerLevelsCB,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)
+ .addComponent(
+ tpNoLegendariesCB,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE))
+ .addGap(18,
+ 18,
+ 18)
+ .addGroup(
+ trainersPokemonPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(
+ tnRandomizeCB)
+ .addComponent(
+ tcnRandomizeCB))))))
+ .addContainerGap(160, Short.MAX_VALUE)));
+ trainersPokemonPanelLayout
+ .setVerticalGroup(trainersPokemonPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ trainersPokemonPanelLayout
+ .createSequentialGroup()
+ .addGroup(
+ trainersPokemonPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(
+ tpUnchangedRB)
+ .addComponent(
+ tpRivalCarriesStarterCB)
+ .addComponent(
+ tnRandomizeCB))
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addGroup(
+ trainersPokemonPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(
+ tpRandomRB)
+ .addComponent(
+ tpPowerLevelsCB)
+ .addComponent(
+ tcnRandomizeCB))
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addGroup(
+ trainersPokemonPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(
+ tpTypeThemedRB)
+ .addComponent(
+ tpTypeWeightingCB))
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(tpNoLegendariesCB)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(tpNoEarlyShedinjaCB)
+ .addContainerGap(
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)));
+
+ wildPokemonPanel
+ .setBorder(javax.swing.BorderFactory.createTitledBorder(
+ null,
+ bundle.getString("RandomizerGUI.wildPokemonPanel.border.title"),
+ javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION,
+ javax.swing.border.TitledBorder.DEFAULT_POSITION,
+ new java.awt.Font("Tahoma", 1, 11))); // NOI18N
+
+ wildPokesButtonGroup.add(wpUnchangedRB);
+ wpUnchangedRB.setSelected(true);
+ wpUnchangedRB.setText(bundle
+ .getString("RandomizerGUI.wpUnchangedRB.text")); // NOI18N
+ wpUnchangedRB.setToolTipText(bundle
+ .getString("RandomizerGUI.wpUnchangedRB.toolTipText")); // NOI18N
+ wpUnchangedRB.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ wpUnchangedRBActionPerformed(evt);
+ }
+ });
+
+ wildPokesButtonGroup.add(wpRandomRB);
+ wpRandomRB.setText(bundle.getString("RandomizerGUI.wpRandomRB.text")); // NOI18N
+ wpRandomRB.setToolTipText(bundle
+ .getString("RandomizerGUI.wpRandomRB.toolTipText")); // NOI18N
+ wpRandomRB.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ wpRandomRBActionPerformed(evt);
+ }
+ });
+
+ wildPokesButtonGroup.add(wpArea11RB);
+ wpArea11RB.setText(bundle.getString("RandomizerGUI.wpArea11RB.text")); // NOI18N
+ wpArea11RB.setToolTipText(bundle
+ .getString("RandomizerGUI.wpArea11RB.toolTipText")); // NOI18N
+ wpArea11RB.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ wpArea11RBActionPerformed(evt);
+ }
+ });
+
+ wildPokesButtonGroup.add(wpGlobalRB);
+ wpGlobalRB.setText(bundle.getString("RandomizerGUI.wpGlobalRB.text")); // NOI18N
+ wpGlobalRB.setToolTipText(bundle
+ .getString("RandomizerGUI.wpGlobalRB.toolTipText")); // NOI18N
+ wpGlobalRB.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ wpGlobalRBActionPerformed(evt);
+ }
+ });
+
+ wildPokemonARulePanel
+ .setBorder(javax.swing.BorderFactory.createTitledBorder(bundle
+ .getString("RandomizerGUI.wildPokemonARulePanel.border.title"))); // NOI18N
+
+ wildPokesARuleButtonGroup.add(wpARNoneRB);
+ wpARNoneRB.setSelected(true);
+ wpARNoneRB.setText(bundle.getString("RandomizerGUI.wpARNoneRB.text")); // NOI18N
+ wpARNoneRB.setToolTipText(bundle
+ .getString("RandomizerGUI.wpARNoneRB.toolTipText")); // NOI18N
+ wpARNoneRB.setEnabled(false);
+ wpARNoneRB.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ wpARNoneRBActionPerformed(evt);
+ }
+ });
+
+ wildPokesARuleButtonGroup.add(wpARCatchEmAllRB);
+ wpARCatchEmAllRB.setText(bundle
+ .getString("RandomizerGUI.wpARCatchEmAllRB.text")); // NOI18N
+ wpARCatchEmAllRB.setToolTipText(bundle
+ .getString("RandomizerGUI.wpARCatchEmAllRB.toolTipText")); // NOI18N
+ wpARCatchEmAllRB.setEnabled(false);
+ wpARCatchEmAllRB.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ wpARCatchEmAllRBActionPerformed(evt);
+ }
+ });
+
+ wildPokesARuleButtonGroup.add(wpARTypeThemedRB);
+ wpARTypeThemedRB.setText(bundle
+ .getString("RandomizerGUI.wpARTypeThemedRB.text")); // NOI18N
+ wpARTypeThemedRB.setToolTipText(bundle
+ .getString("RandomizerGUI.wpARTypeThemedRB.toolTipText")); // NOI18N
+ wpARTypeThemedRB.setEnabled(false);
+ wpARTypeThemedRB.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ wpARTypeThemedRBActionPerformed(evt);
+ }
+ });
+
+ wildPokesARuleButtonGroup.add(wpARSimilarStrengthRB);
+ wpARSimilarStrengthRB.setText(bundle
+ .getString("RandomizerGUI.wpARSimilarStrengthRB.text")); // NOI18N
+ wpARSimilarStrengthRB.setToolTipText(bundle
+ .getString("RandomizerGUI.wpARSimilarStrengthRB.toolTipText")); // NOI18N
+ wpARSimilarStrengthRB.setEnabled(false);
+ wpARSimilarStrengthRB
+ .addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ wpARSimilarStrengthRBActionPerformed(evt);
+ }
+ });
+
+ javax.swing.GroupLayout wildPokemonARulePanelLayout = new javax.swing.GroupLayout(
+ wildPokemonARulePanel);
+ wildPokemonARulePanel.setLayout(wildPokemonARulePanelLayout);
+ wildPokemonARulePanelLayout
+ .setHorizontalGroup(wildPokemonARulePanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ wildPokemonARulePanelLayout
+ .createSequentialGroup()
+ .addContainerGap()
+ .addGroup(
+ wildPokemonARulePanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ wildPokemonARulePanelLayout
+ .createSequentialGroup()
+ .addComponent(
+ wpARTypeThemedRB)
+ .addGap(0,
+ 0,
+ Short.MAX_VALUE))
+ .addGroup(
+ wildPokemonARulePanelLayout
+ .createSequentialGroup()
+ .addGroup(
+ wildPokemonARulePanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(
+ wpARSimilarStrengthRB)
+ .addComponent(
+ wpARNoneRB)
+ .addComponent(
+ wpARCatchEmAllRB))
+ .addContainerGap(
+ 58,
+ Short.MAX_VALUE)))));
+ wildPokemonARulePanelLayout
+ .setVerticalGroup(wildPokemonARulePanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ wildPokemonARulePanelLayout
+ .createSequentialGroup()
+ .addComponent(wpARNoneRB)
+ .addGap(3, 3, 3)
+ .addComponent(wpARSimilarStrengthRB)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(wpARCatchEmAllRB)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.RELATED,
+ 3, Short.MAX_VALUE)
+ .addComponent(
+ wpARTypeThemedRB,
+ javax.swing.GroupLayout.PREFERRED_SIZE,
+ 30,
+ javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addContainerGap()));
+
+ wpUseTimeCB.setText(bundle.getString("RandomizerGUI.wpUseTimeCB.text")); // NOI18N
+ wpUseTimeCB.setToolTipText(bundle
+ .getString("RandomizerGUI.wpUseTimeCB.toolTipText")); // NOI18N
+
+ wpNoLegendariesCB.setText(bundle
+ .getString("RandomizerGUI.wpNoLegendariesCB.text")); // NOI18N
+
+ wpCatchRateCB.setText(bundle
+ .getString("RandomizerGUI.wpCatchRateCB.text")); // NOI18N
+ wpCatchRateCB.setToolTipText(bundle
+ .getString("RandomizerGUI.wpCatchRateCB.toolTipText")); // NOI18N
+
+ wpHeldItemsCB.setText(bundle
+ .getString("RandomizerGUI.wpHeldItemsCB.text")); // NOI18N
+ wpHeldItemsCB.setToolTipText(bundle
+ .getString("RandomizerGUI.wpHeldItemsCB.toolTipText")); // NOI18N
+
+ javax.swing.GroupLayout wildPokemonPanelLayout = new javax.swing.GroupLayout(
+ wildPokemonPanel);
+ wildPokemonPanel.setLayout(wildPokemonPanelLayout);
+ wildPokemonPanelLayout
+ .setHorizontalGroup(wildPokemonPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ wildPokemonPanelLayout
+ .createSequentialGroup()
+ .addContainerGap()
+ .addGroup(
+ wildPokemonPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(
+ wpUnchangedRB)
+ .addComponent(
+ wpRandomRB)
+ .addComponent(
+ wpArea11RB)
+ .addComponent(
+ wpGlobalRB))
+ .addGap(18, 18, 18)
+ .addComponent(
+ wildPokemonARulePanel,
+ javax.swing.GroupLayout.PREFERRED_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addGap(18, 18, 18)
+ .addGroup(
+ wildPokemonPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(
+ wpUseTimeCB)
+ .addComponent(
+ wpNoLegendariesCB)
+ .addComponent(
+ wpCatchRateCB)
+ .addComponent(
+ wpHeldItemsCB))
+ .addContainerGap(
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)));
+ wildPokemonPanelLayout
+ .setVerticalGroup(wildPokemonPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.TRAILING)
+ .addGroup(
+ javax.swing.GroupLayout.Alignment.LEADING,
+ wildPokemonPanelLayout
+ .createSequentialGroup()
+ .addContainerGap()
+ .addComponent(wpUnchangedRB)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(wpRandomRB)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(wpArea11RB)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(wpGlobalRB))
+ .addGroup(
+ javax.swing.GroupLayout.Alignment.LEADING,
+ wildPokemonPanelLayout
+ .createSequentialGroup()
+ .addGap(28, 28, 28)
+ .addComponent(wpUseTimeCB)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(wpNoLegendariesCB)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(wpCatchRateCB)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(wpHeldItemsCB))
+ .addGroup(
+ javax.swing.GroupLayout.Alignment.LEADING,
+ wildPokemonPanelLayout
+ .createSequentialGroup()
+ .addContainerGap()
+ .addComponent(
+ wildPokemonARulePanel,
+ javax.swing.GroupLayout.PREFERRED_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.PREFERRED_SIZE)));
+
+ starterPokemonPanel
+ .setBorder(javax.swing.BorderFactory.createTitledBorder(
+ null,
+ bundle.getString("RandomizerGUI.starterPokemonPanel.border.title"),
+ javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION,
+ javax.swing.border.TitledBorder.DEFAULT_POSITION,
+ new java.awt.Font("Tahoma", 1, 11))); // NOI18N
+
+ starterPokemonButtonGroup.add(spUnchangedRB);
+ spUnchangedRB.setSelected(true);
+ spUnchangedRB.setText(bundle
+ .getString("RandomizerGUI.spUnchangedRB.text")); // NOI18N
+ spUnchangedRB.setToolTipText(bundle
+ .getString("RandomizerGUI.spUnchangedRB.toolTipText")); // NOI18N
+ spUnchangedRB.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ spUnchangedRBActionPerformed(evt);
+ }
+ });
+
+ starterPokemonButtonGroup.add(spCustomRB);
+ spCustomRB.setText(bundle.getString("RandomizerGUI.spCustomRB.text")); // NOI18N
+ spCustomRB.setToolTipText(bundle
+ .getString("RandomizerGUI.spCustomRB.toolTipText")); // NOI18N
+ spCustomRB.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ spCustomRBActionPerformed(evt);
+ }
+ });
+
+ spCustomPoke1Chooser.setModel(new javax.swing.DefaultComboBoxModel(
+ new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
+ spCustomPoke1Chooser.setEnabled(false);
+
+ spCustomPoke2Chooser.setModel(new javax.swing.DefaultComboBoxModel(
+ new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
+ spCustomPoke2Chooser.setEnabled(false);
+
+ spCustomPoke3Chooser.setModel(new javax.swing.DefaultComboBoxModel(
+ new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
+ spCustomPoke3Chooser.setEnabled(false);
+
+ starterPokemonButtonGroup.add(spRandomRB);
+ spRandomRB.setText(bundle.getString("RandomizerGUI.spRandomRB.text")); // NOI18N
+ spRandomRB.setToolTipText(bundle
+ .getString("RandomizerGUI.spRandomRB.toolTipText")); // NOI18N
+ spRandomRB.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ spRandomRBActionPerformed(evt);
+ }
+ });
+
+ starterPokemonButtonGroup.add(spRandom2EvosRB);
+ spRandom2EvosRB.setText(bundle
+ .getString("RandomizerGUI.spRandom2EvosRB.text")); // NOI18N
+ spRandom2EvosRB.setToolTipText(bundle
+ .getString("RandomizerGUI.spRandom2EvosRB.toolTipText")); // NOI18N
+
+ spHeldItemsCB.setText(bundle
+ .getString("RandomizerGUI.spHeldItemsCB.text")); // NOI18N
+ spHeldItemsCB.setToolTipText(bundle
+ .getString("RandomizerGUI.spHeldItemsCB.toolTipText")); // NOI18N
+
+ javax.swing.GroupLayout starterPokemonPanelLayout = new javax.swing.GroupLayout(
+ starterPokemonPanel);
+ starterPokemonPanel.setLayout(starterPokemonPanelLayout);
+ starterPokemonPanelLayout
+ .setHorizontalGroup(starterPokemonPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ starterPokemonPanelLayout
+ .createSequentialGroup()
+ .addContainerGap()
+ .addGroup(
+ starterPokemonPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(
+ spUnchangedRB)
+ .addGroup(
+ starterPokemonPanelLayout
+ .createSequentialGroup()
+ .addComponent(
+ spCustomRB)
+ .addGap(18,
+ 18,
+ 18)
+ .addComponent(
+ spCustomPoke1Chooser,
+ javax.swing.GroupLayout.PREFERRED_SIZE,
+ 90,
+ javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(
+ spCustomPoke2Chooser,
+ javax.swing.GroupLayout.PREFERRED_SIZE,
+ 90,
+ javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(
+ spCustomPoke3Chooser,
+ javax.swing.GroupLayout.PREFERRED_SIZE,
+ 90,
+ javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addGap(18,
+ 18,
+ 18)
+ .addComponent(
+ spHeldItemsCB))
+ .addComponent(
+ spRandomRB)
+ .addComponent(
+ spRandom2EvosRB))
+ .addContainerGap(162, Short.MAX_VALUE)));
+ starterPokemonPanelLayout
+ .setVerticalGroup(starterPokemonPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ starterPokemonPanelLayout
+ .createSequentialGroup()
+ .addContainerGap()
+ .addComponent(spUnchangedRB)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addGroup(
+ starterPokemonPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(
+ spCustomRB)
+ .addComponent(
+ spCustomPoke1Chooser,
+ javax.swing.GroupLayout.PREFERRED_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(
+ spCustomPoke2Chooser,
+ javax.swing.GroupLayout.PREFERRED_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(
+ spCustomPoke3Chooser,
+ javax.swing.GroupLayout.PREFERRED_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(
+ spHeldItemsCB))
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(spRandomRB)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(spRandom2EvosRB)
+ .addContainerGap(11, Short.MAX_VALUE)));
+
+ staticPokemonPanel
+ .setBorder(javax.swing.BorderFactory.createTitledBorder(
+ null,
+ bundle.getString("RandomizerGUI.staticPokemonPanel.border.title"),
+ javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION,
+ javax.swing.border.TitledBorder.DEFAULT_POSITION,
+ new java.awt.Font("Tahoma", 1, 11))); // NOI18N
+
+ staticPokemonButtonGroup.add(stpUnchangedRB);
+ stpUnchangedRB.setSelected(true);
+ stpUnchangedRB.setText(bundle
+ .getString("RandomizerGUI.stpUnchangedRB.text")); // NOI18N
+ stpUnchangedRB.setToolTipText(bundle
+ .getString("RandomizerGUI.stpUnchangedRB.toolTipText")); // NOI18N
+
+ staticPokemonButtonGroup.add(stpRandomL4LRB);
+ stpRandomL4LRB.setText(bundle
+ .getString("RandomizerGUI.stpRandomL4LRB.text")); // NOI18N
+ stpRandomL4LRB.setToolTipText(bundle
+ .getString("RandomizerGUI.stpRandomL4LRB.toolTipText")); // NOI18N
+
+ staticPokemonButtonGroup.add(stpRandomTotalRB);
+ stpRandomTotalRB.setText(bundle
+ .getString("RandomizerGUI.stpRandomTotalRB.text")); // NOI18N
+ stpRandomTotalRB.setToolTipText(bundle
+ .getString("RandomizerGUI.stpRandomTotalRB.toolTipText")); // NOI18N
+
+ javax.swing.GroupLayout staticPokemonPanelLayout = new javax.swing.GroupLayout(
+ staticPokemonPanel);
+ staticPokemonPanel.setLayout(staticPokemonPanelLayout);
+ staticPokemonPanelLayout
+ .setHorizontalGroup(staticPokemonPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ staticPokemonPanelLayout
+ .createSequentialGroup()
+ .addContainerGap()
+ .addGroup(
+ staticPokemonPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(
+ stpUnchangedRB)
+ .addComponent(
+ stpRandomL4LRB)
+ .addComponent(
+ stpRandomTotalRB))
+ .addContainerGap(401, Short.MAX_VALUE)));
+ staticPokemonPanelLayout
+ .setVerticalGroup(staticPokemonPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ staticPokemonPanelLayout
+ .createSequentialGroup()
+ .addComponent(stpUnchangedRB)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(stpRandomL4LRB)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(stpRandomTotalRB)));
+
+ tmhmsPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(null,
+ bundle.getString("RandomizerGUI.tmhmsPanel.border.title"),
+ javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION,
+ javax.swing.border.TitledBorder.DEFAULT_POSITION,
+ new java.awt.Font("Tahoma", 1, 11))); // NOI18N
+
+ tmMovesPanel.setBorder(javax.swing.BorderFactory
+ .createTitledBorder(bundle
+ .getString("RandomizerGUI.tmMovesPanel.border.title"))); // NOI18N
+
+ tmMovesButtonGroup.add(tmmUnchangedRB);
+ tmmUnchangedRB.setSelected(true);
+ tmmUnchangedRB.setText(bundle
+ .getString("RandomizerGUI.tmmUnchangedRB.text")); // NOI18N
+ tmmUnchangedRB.setToolTipText(bundle
+ .getString("RandomizerGUI.tmmUnchangedRB.toolTipText")); // NOI18N
+
+ tmMovesButtonGroup.add(tmmRandomRB);
+ tmmRandomRB.setText(bundle.getString("RandomizerGUI.tmmRandomRB.text")); // NOI18N
+ tmmRandomRB.setToolTipText(bundle
+ .getString("RandomizerGUI.tmmRandomRB.toolTipText")); // NOI18N
+
+ javax.swing.GroupLayout tmMovesPanelLayout = new javax.swing.GroupLayout(
+ tmMovesPanel);
+ tmMovesPanel.setLayout(tmMovesPanelLayout);
+ tmMovesPanelLayout
+ .setHorizontalGroup(tmMovesPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ tmMovesPanelLayout
+ .createSequentialGroup()
+ .addContainerGap()
+ .addGroup(
+ tmMovesPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(
+ tmmUnchangedRB)
+ .addComponent(
+ tmmRandomRB))
+ .addContainerGap(118, Short.MAX_VALUE)));
+ tmMovesPanelLayout
+ .setVerticalGroup(tmMovesPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ tmMovesPanelLayout
+ .createSequentialGroup()
+ .addContainerGap()
+ .addComponent(tmmUnchangedRB)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(tmmRandomRB)
+ .addContainerGap(
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)));
+
+ tmHmCompatPanel
+ .setBorder(javax.swing.BorderFactory.createTitledBorder(bundle
+ .getString("RandomizerGUI.tmHmCompatPanel.border.title"))); // NOI18N
+
+ tmHmCompatibilityButtonGroup.add(thcUnchangedRB);
+ thcUnchangedRB.setSelected(true);
+ thcUnchangedRB.setText(bundle
+ .getString("RandomizerGUI.thcUnchangedRB.text")); // NOI18N
+ thcUnchangedRB.setToolTipText(bundle
+ .getString("RandomizerGUI.thcUnchangedRB.toolTipText")); // NOI18N
+
+ tmHmCompatibilityButtonGroup.add(thcRandomTypeRB);
+ thcRandomTypeRB.setText(bundle
+ .getString("RandomizerGUI.thcRandomTypeRB.text")); // NOI18N
+ thcRandomTypeRB.setToolTipText(bundle
+ .getString("RandomizerGUI.thcRandomTypeRB.toolTipText")); // NOI18N
+
+ tmHmCompatibilityButtonGroup.add(thcRandomTotalRB);
+ thcRandomTotalRB.setText(bundle
+ .getString("RandomizerGUI.thcRandomTotalRB.text")); // NOI18N
+ thcRandomTotalRB.setToolTipText(bundle
+ .getString("RandomizerGUI.thcRandomTotalRB.toolTipText")); // NOI18N
+
+ javax.swing.GroupLayout tmHmCompatPanelLayout = new javax.swing.GroupLayout(
+ tmHmCompatPanel);
+ tmHmCompatPanel.setLayout(tmHmCompatPanelLayout);
+ tmHmCompatPanelLayout
+ .setHorizontalGroup(tmHmCompatPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ tmHmCompatPanelLayout
+ .createSequentialGroup()
+ .addContainerGap()
+ .addGroup(
+ tmHmCompatPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(
+ thcUnchangedRB)
+ .addComponent(
+ thcRandomTypeRB)
+ .addComponent(
+ thcRandomTotalRB))
+ .addContainerGap(79, Short.MAX_VALUE)));
+ tmHmCompatPanelLayout
+ .setVerticalGroup(tmHmCompatPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ tmHmCompatPanelLayout
+ .createSequentialGroup()
+ .addContainerGap()
+ .addComponent(thcUnchangedRB)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(thcRandomTypeRB)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(thcRandomTotalRB)
+ .addContainerGap(
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)));
+
+ javax.swing.GroupLayout tmhmsPanelLayout = new javax.swing.GroupLayout(
+ tmhmsPanel);
+ tmhmsPanel.setLayout(tmhmsPanelLayout);
+ tmhmsPanelLayout
+ .setHorizontalGroup(tmhmsPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ tmhmsPanelLayout
+ .createSequentialGroup()
+ .addContainerGap()
+ .addComponent(
+ tmMovesPanel,
+ javax.swing.GroupLayout.PREFERRED_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.RELATED,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)
+ .addComponent(
+ tmHmCompatPanel,
+ javax.swing.GroupLayout.PREFERRED_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addContainerGap()));
+ tmhmsPanelLayout
+ .setVerticalGroup(tmhmsPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ tmhmsPanelLayout
+ .createSequentialGroup()
+ .addContainerGap(
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)
+ .addGroup(
+ tmhmsPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING,
+ false)
+ .addComponent(
+ tmHmCompatPanel,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)
+ .addComponent(
+ tmMovesPanel,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE))));
+
+ abilitiesPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(
+ null,
+ bundle.getString("RandomizerGUI.abilitiesPanel.border.title"),
+ javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION,
+ javax.swing.border.TitledBorder.DEFAULT_POSITION,
+ new java.awt.Font("Tahoma", 1, 11))); // NOI18N
+
+ pokeAbilitiesButtonGroup.add(paUnchangedRB);
+ paUnchangedRB.setSelected(true);
+ paUnchangedRB.setText(bundle
+ .getString("RandomizerGUI.paUnchangedRB.text")); // NOI18N
+ paUnchangedRB.setToolTipText(bundle
+ .getString("RandomizerGUI.paUnchangedRB.toolTipText")); // NOI18N
+ paUnchangedRB.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ paUnchangedRBActionPerformed(evt);
+ }
+ });
+
+ pokeAbilitiesButtonGroup.add(paRandomizeRB);
+ paRandomizeRB.setText(bundle
+ .getString("RandomizerGUI.paRandomizeRB.text")); // NOI18N
+ paRandomizeRB.setToolTipText(bundle
+ .getString("RandomizerGUI.paRandomizeRB.toolTipText")); // NOI18N
+ paRandomizeRB.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ paRandomizeRBActionPerformed(evt);
+ }
+ });
+
+ paWonderGuardCB.setText(bundle
+ .getString("RandomizerGUI.paWonderGuardCB.text")); // NOI18N
+ paWonderGuardCB.setToolTipText(bundle
+ .getString("RandomizerGUI.paWonderGuardCB.toolTipText")); // NOI18N
+
+ javax.swing.GroupLayout abilitiesPanelLayout = new javax.swing.GroupLayout(
+ abilitiesPanel);
+ abilitiesPanel.setLayout(abilitiesPanelLayout);
+ abilitiesPanelLayout
+ .setHorizontalGroup(abilitiesPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ abilitiesPanelLayout
+ .createSequentialGroup()
+ .addContainerGap()
+ .addGroup(
+ abilitiesPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(
+ paUnchangedRB)
+ .addComponent(
+ paRandomizeRB)
+ .addComponent(
+ paWonderGuardCB))
+ .addContainerGap(190, Short.MAX_VALUE)));
+ abilitiesPanelLayout
+ .setVerticalGroup(abilitiesPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ abilitiesPanelLayout
+ .createSequentialGroup()
+ .addContainerGap()
+ .addComponent(paUnchangedRB)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(paRandomizeRB)
+ .addGap(18, 18, 18)
+ .addComponent(paWonderGuardCB)
+ .addContainerGap(
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)));
+
+ moveTutorsPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(
+ null,
+ bundle.getString("RandomizerGUI.moveTutorsPanel.border.title"),
+ javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION,
+ javax.swing.border.TitledBorder.DEFAULT_POSITION,
+ new java.awt.Font("Tahoma", 1, 11))); // NOI18N
+
+ mtMovesPanel.setBorder(javax.swing.BorderFactory
+ .createTitledBorder(bundle
+ .getString("RandomizerGUI.mtMovesPanel.border.title"))); // NOI18N
+
+ mtMovesButtonGroup.add(mtmUnchangedRB);
+ mtmUnchangedRB.setSelected(true);
+ mtmUnchangedRB.setText(bundle
+ .getString("RandomizerGUI.mtmUnchangedRB.text")); // NOI18N
+ mtmUnchangedRB.setToolTipText(bundle
+ .getString("RandomizerGUI.mtmUnchangedRB.toolTipText")); // NOI18N
+ mtmUnchangedRB.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ mtmUnchangedRBActionPerformed(evt);
+ }
+ });
+
+ mtMovesButtonGroup.add(mtmRandomRB);
+ mtmRandomRB.setText(bundle.getString("RandomizerGUI.mtmRandomRB.text")); // NOI18N
+ mtmRandomRB.setToolTipText(bundle
+ .getString("RandomizerGUI.mtmRandomRB.toolTipText")); // NOI18N
+
+ javax.swing.GroupLayout mtMovesPanelLayout = new javax.swing.GroupLayout(
+ mtMovesPanel);
+ mtMovesPanel.setLayout(mtMovesPanelLayout);
+ mtMovesPanelLayout
+ .setHorizontalGroup(mtMovesPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ mtMovesPanelLayout
+ .createSequentialGroup()
+ .addContainerGap()
+ .addGroup(
+ mtMovesPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(
+ mtmUnchangedRB)
+ .addComponent(
+ mtmRandomRB))
+ .addContainerGap(118, Short.MAX_VALUE)));
+ mtMovesPanelLayout
+ .setVerticalGroup(mtMovesPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ mtMovesPanelLayout
+ .createSequentialGroup()
+ .addContainerGap()
+ .addComponent(mtmUnchangedRB)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(mtmRandomRB)
+ .addContainerGap(
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)));
+
+ mtCompatPanel
+ .setBorder(javax.swing.BorderFactory.createTitledBorder(bundle
+ .getString("RandomizerGUI.mtCompatPanel.border.title"))); // NOI18N
+
+ mtCompatibilityButtonGroup.add(mtcUnchangedRB);
+ mtcUnchangedRB.setSelected(true);
+ mtcUnchangedRB.setText(bundle
+ .getString("RandomizerGUI.mtcUnchangedRB.text")); // NOI18N
+ mtcUnchangedRB.setToolTipText(bundle
+ .getString("RandomizerGUI.mtcUnchangedRB.toolTipText")); // NOI18N
+
+ mtCompatibilityButtonGroup.add(mtcRandomTypeRB);
+ mtcRandomTypeRB.setText(bundle
+ .getString("RandomizerGUI.mtcRandomTypeRB.text")); // NOI18N
+ mtcRandomTypeRB.setToolTipText(bundle
+ .getString("RandomizerGUI.mtcRandomTypeRB.toolTipText")); // NOI18N
+
+ mtCompatibilityButtonGroup.add(mtcRandomTotalRB);
+ mtcRandomTotalRB.setText(bundle
+ .getString("RandomizerGUI.mtcRandomTotalRB.text")); // NOI18N
+ mtcRandomTotalRB.setToolTipText(bundle
+ .getString("RandomizerGUI.mtcRandomTotalRB.toolTipText")); // NOI18N
+
+ javax.swing.GroupLayout mtCompatPanelLayout = new javax.swing.GroupLayout(
+ mtCompatPanel);
+ mtCompatPanel.setLayout(mtCompatPanelLayout);
+ mtCompatPanelLayout
+ .setHorizontalGroup(mtCompatPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ mtCompatPanelLayout
+ .createSequentialGroup()
+ .addContainerGap()
+ .addGroup(
+ mtCompatPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(
+ mtcUnchangedRB)
+ .addComponent(
+ mtcRandomTypeRB)
+ .addComponent(
+ mtcRandomTotalRB))
+ .addContainerGap(79, Short.MAX_VALUE)));
+ mtCompatPanelLayout
+ .setVerticalGroup(mtCompatPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ mtCompatPanelLayout
+ .createSequentialGroup()
+ .addContainerGap()
+ .addComponent(mtcUnchangedRB)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(mtcRandomTypeRB)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(mtcRandomTotalRB)
+ .addContainerGap(
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)));
+
+ mtNoExistLabel.setText(bundle
+ .getString("RandomizerGUI.mtNoExistLabel.text")); // NOI18N
+
+ javax.swing.GroupLayout moveTutorsPanelLayout = new javax.swing.GroupLayout(
+ moveTutorsPanel);
+ moveTutorsPanel.setLayout(moveTutorsPanelLayout);
+ moveTutorsPanelLayout
+ .setHorizontalGroup(moveTutorsPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ moveTutorsPanelLayout
+ .createSequentialGroup()
+ .addContainerGap()
+ .addGroup(
+ moveTutorsPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ moveTutorsPanelLayout
+ .createSequentialGroup()
+ .addComponent(
+ mtMovesPanel,
+ javax.swing.GroupLayout.PREFERRED_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.RELATED,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)
+ .addComponent(
+ mtCompatPanel,
+ javax.swing.GroupLayout.PREFERRED_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addGroup(
+ moveTutorsPanelLayout
+ .createSequentialGroup()
+ .addComponent(
+ mtNoExistLabel)
+ .addGap(0,
+ 0,
+ Short.MAX_VALUE)))
+ .addContainerGap()));
+ moveTutorsPanelLayout
+ .setVerticalGroup(moveTutorsPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ moveTutorsPanelLayout
+ .createSequentialGroup()
+ .addComponent(mtNoExistLabel)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.RELATED,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)
+ .addGroup(
+ moveTutorsPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING,
+ false)
+ .addComponent(
+ mtCompatPanel,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)
+ .addComponent(
+ mtMovesPanel,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE))));
+
+ inGameTradesPanel
+ .setBorder(javax.swing.BorderFactory.createTitledBorder(
+ null,
+ bundle.getString("RandomizerGUI.inGameTradesPanel.border.title"),
+ javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION,
+ javax.swing.border.TitledBorder.DEFAULT_POSITION,
+ new java.awt.Font("Tahoma", 1, 11))); // NOI18N
+
+ ingameTradesButtonGroup.add(igtUnchangedRB);
+ igtUnchangedRB.setSelected(true);
+ igtUnchangedRB.setText(bundle
+ .getString("RandomizerGUI.igtUnchangedRB.text")); // NOI18N
+ igtUnchangedRB.setToolTipText(bundle
+ .getString("RandomizerGUI.igtUnchangedRB.toolTipText")); // NOI18N
+ igtUnchangedRB.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ igtUnchangedRBActionPerformed(evt);
+ }
+ });
+
+ ingameTradesButtonGroup.add(igtGivenOnlyRB);
+ igtGivenOnlyRB.setText(bundle
+ .getString("RandomizerGUI.igtGivenOnlyRB.text")); // NOI18N
+ igtGivenOnlyRB.setToolTipText(bundle
+ .getString("RandomizerGUI.igtGivenOnlyRB.toolTipText")); // NOI18N
+ igtGivenOnlyRB.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ igtGivenOnlyRBActionPerformed(evt);
+ }
+ });
+
+ ingameTradesButtonGroup.add(igtBothRB);
+ igtBothRB.setText(bundle.getString("RandomizerGUI.igtBothRB.text")); // NOI18N
+ igtBothRB.setToolTipText(bundle
+ .getString("RandomizerGUI.igtBothRB.toolTipText")); // NOI18N
+ igtBothRB.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ igtBothRBActionPerformed(evt);
+ }
+ });
+
+ igtRandomNicknameCB.setText(bundle
+ .getString("RandomizerGUI.igtRandomNicknameCB.text")); // NOI18N
+ igtRandomNicknameCB.setToolTipText(bundle
+ .getString("RandomizerGUI.igtRandomNicknameCB.toolTipText")); // NOI18N
+
+ igtRandomOTCB.setText(bundle
+ .getString("RandomizerGUI.igtRandomOTCB.text")); // NOI18N
+ igtRandomOTCB.setToolTipText(bundle
+ .getString("RandomizerGUI.igtRandomOTCB.toolTipText")); // NOI18N
+
+ igtRandomIVsCB.setText(bundle
+ .getString("RandomizerGUI.igtRandomIVsCB.text")); // NOI18N
+ igtRandomIVsCB.setToolTipText(bundle
+ .getString("RandomizerGUI.igtRandomIVsCB.toolTipText")); // NOI18N
+
+ igtRandomItemCB.setText(bundle
+ .getString("RandomizerGUI.igtRandomItemCB.text")); // NOI18N
+ igtRandomItemCB.setToolTipText(bundle
+ .getString("RandomizerGUI.igtRandomItemCB.toolTipText")); // NOI18N
+
+ javax.swing.GroupLayout inGameTradesPanelLayout = new javax.swing.GroupLayout(
+ inGameTradesPanel);
+ inGameTradesPanel.setLayout(inGameTradesPanelLayout);
+ inGameTradesPanelLayout
+ .setHorizontalGroup(inGameTradesPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ javax.swing.GroupLayout.Alignment.TRAILING,
+ inGameTradesPanelLayout
+ .createSequentialGroup()
+ .addContainerGap()
+ .addGroup(
+ inGameTradesPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(
+ igtUnchangedRB)
+ .addComponent(
+ igtGivenOnlyRB)
+ .addComponent(igtBothRB))
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.RELATED,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)
+ .addGroup(
+ inGameTradesPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(
+ igtRandomItemCB)
+ .addComponent(
+ igtRandomNicknameCB)
+ .addComponent(
+ igtRandomOTCB)
+ .addComponent(
+ igtRandomIVsCB))
+ .addGap(113, 113, 113)));
+ inGameTradesPanelLayout
+ .setVerticalGroup(inGameTradesPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ inGameTradesPanelLayout
+ .createSequentialGroup()
+ .addGroup(
+ inGameTradesPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(
+ igtUnchangedRB)
+ .addComponent(
+ igtRandomNicknameCB))
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addGroup(
+ inGameTradesPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(
+ igtGivenOnlyRB)
+ .addComponent(
+ igtRandomOTCB))
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addGroup(
+ inGameTradesPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(igtBothRB)
+ .addComponent(
+ igtRandomIVsCB))
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(igtRandomItemCB)
+ .addContainerGap(
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)));
+
+ fieldItemsPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(
+ null,
+ bundle.getString("RandomizerGUI.fieldItemsPanel.border.title"),
+ javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION,
+ javax.swing.border.TitledBorder.DEFAULT_POSITION,
+ new java.awt.Font("Tahoma", 1, 11))); // NOI18N
+
+ fieldItemsButtonGroup.add(fiUnchangedRB);
+ fiUnchangedRB.setSelected(true);
+ fiUnchangedRB.setText(bundle
+ .getString("RandomizerGUI.fiUnchangedRB.text")); // NOI18N
+ fiUnchangedRB.setToolTipText(bundle
+ .getString("RandomizerGUI.fiUnchangedRB.toolTipText")); // NOI18N
+
+ fieldItemsButtonGroup.add(fiShuffleRB);
+ fiShuffleRB.setText(bundle.getString("RandomizerGUI.fiShuffleRB.text")); // NOI18N
+ fiShuffleRB.setToolTipText(bundle
+ .getString("RandomizerGUI.fiShuffleRB.toolTipText")); // NOI18N
+
+ fieldItemsButtonGroup.add(fiRandomRB);
+ fiRandomRB.setText(bundle.getString("RandomizerGUI.fiRandomRB.text")); // NOI18N
+ fiRandomRB.setToolTipText(bundle
+ .getString("RandomizerGUI.fiRandomRB.toolTipText")); // NOI18N
+
+ javax.swing.GroupLayout fieldItemsPanelLayout = new javax.swing.GroupLayout(
+ fieldItemsPanel);
+ fieldItemsPanel.setLayout(fieldItemsPanelLayout);
+ fieldItemsPanelLayout
+ .setHorizontalGroup(fieldItemsPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ fieldItemsPanelLayout
+ .createSequentialGroup()
+ .addContainerGap()
+ .addGroup(
+ fieldItemsPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(
+ fiUnchangedRB)
+ .addComponent(
+ fiShuffleRB)
+ .addComponent(
+ fiRandomRB))
+ .addContainerGap(
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)));
+ fieldItemsPanelLayout
+ .setVerticalGroup(fieldItemsPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ fieldItemsPanelLayout
+ .createSequentialGroup()
+ .addComponent(fiUnchangedRB)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(fiShuffleRB)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(fiRandomRB)));
+
+ javax.swing.GroupLayout optionsContainerPanelLayout = new javax.swing.GroupLayout(
+ optionsContainerPanel);
+ optionsContainerPanel.setLayout(optionsContainerPanelLayout);
+ optionsContainerPanelLayout
+ .setHorizontalGroup(optionsContainerPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(pokemonTypesPanel,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)
+ .addComponent(pokemonMovesetsPanel,
+ javax.swing.GroupLayout.Alignment.TRAILING,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)
+ .addComponent(trainersPokemonPanel,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)
+ .addComponent(wildPokemonPanel,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)
+ .addComponent(starterPokemonPanel,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)
+ .addComponent(staticPokemonPanel,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)
+ .addComponent(tmhmsPanel,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)
+ .addGroup(
+ optionsContainerPanelLayout
+ .createSequentialGroup()
+ .addComponent(
+ baseStatsPanel,
+ javax.swing.GroupLayout.PREFERRED_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(
+ abilitiesPanel,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE))
+ .addComponent(moveTutorsPanel,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)
+ .addComponent(inGameTradesPanel,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)
+ .addComponent(fieldItemsPanel,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE));
+ optionsContainerPanelLayout
+ .setVerticalGroup(optionsContainerPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ optionsContainerPanelLayout
+ .createSequentialGroup()
+ .addGroup(
+ optionsContainerPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING,
+ false)
+ .addComponent(
+ baseStatsPanel,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)
+ .addComponent(
+ abilitiesPanel,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE))
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(
+ starterPokemonPanel,
+ javax.swing.GroupLayout.PREFERRED_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(
+ pokemonTypesPanel,
+ javax.swing.GroupLayout.PREFERRED_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(
+ pokemonMovesetsPanel,
+ javax.swing.GroupLayout.PREFERRED_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(
+ trainersPokemonPanel,
+ javax.swing.GroupLayout.PREFERRED_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(
+ wildPokemonPanel,
+ javax.swing.GroupLayout.PREFERRED_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(
+ staticPokemonPanel,
+ javax.swing.GroupLayout.PREFERRED_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(
+ tmhmsPanel,
+ javax.swing.GroupLayout.PREFERRED_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(
+ moveTutorsPanel,
+ javax.swing.GroupLayout.PREFERRED_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(
+ inGameTradesPanel,
+ javax.swing.GroupLayout.PREFERRED_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(
+ fieldItemsPanel,
+ javax.swing.GroupLayout.PREFERRED_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addContainerGap(
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)));
+
+ optionsScrollPane.setViewportView(optionsContainerPanel);
+
+ openROMButton.setText(bundle
+ .getString("RandomizerGUI.openROMButton.text")); // NOI18N
+ openROMButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ openROMButtonActionPerformed(evt);
+ }
+ });
+
+ saveROMButton.setText(bundle
+ .getString("RandomizerGUI.saveROMButton.text")); // NOI18N
+ saveROMButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ saveROMButtonActionPerformed(evt);
+ }
+ });
+
+ usePresetsButton.setText(bundle
+ .getString("RandomizerGUI.usePresetsButton.text")); // NOI18N
+ usePresetsButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ usePresetsButtonActionPerformed(evt);
+ }
+ });
+
+ aboutButton.setText(bundle.getString("RandomizerGUI.aboutButton.text")); // NOI18N
+ aboutButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ aboutButtonActionPerformed(evt);
+ }
+ });
+
+ otherOptionsPanel
+ .setBorder(javax.swing.BorderFactory.createTitledBorder(
+ null,
+ bundle.getString("RandomizerGUI.otherOptionsPanel.border.title"),
+ javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION,
+ javax.swing.border.TitledBorder.DEFAULT_POSITION,
+ new java.awt.Font("Tahoma", 1, 11))); // NOI18N
+
+ codeTweaksCB.setText(bundle
+ .getString("RandomizerGUI.codeTweaksCB.text")); // NOI18N
+ codeTweaksCB.setToolTipText(bundle
+ .getString("RandomizerGUI.codeTweaksCB.toolTipText")); // NOI18N
+ codeTweaksCB.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ codeTweaksCBActionPerformed(evt);
+ }
+ });
+
+ raceModeCB.setText(bundle.getString("RandomizerGUI.raceModeCB.text")); // NOI18N
+ raceModeCB.setToolTipText(bundle
+ .getString("RandomizerGUI.raceModeCB.toolTipText")); // NOI18N
+
+ randomizeHollowsCB.setText(bundle
+ .getString("RandomizerGUI.randomizeHollowsCB.text")); // NOI18N
+ randomizeHollowsCB.setToolTipText(bundle
+ .getString("RandomizerGUI.randomizeHollowsCB.toolTipText")); // NOI18N
+
+ brokenMovesCB.setText(bundle
+ .getString("RandomizerGUI.brokenMovesCB.text")); // NOI18N
+ brokenMovesCB.setToolTipText(bundle
+ .getString("RandomizerGUI.brokenMovesCB.toolTipText")); // NOI18N
+
+ codeTweaksBtn.setText(bundle
+ .getString("RandomizerGUI.codeTweaksBtn.text")); // NOI18N
+ codeTweaksBtn.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ codeTweaksBtnActionPerformed(evt);
+ }
+ });
+
+ pokeLimitCB.setText(bundle.getString("RandomizerGUI.pokeLimitCB.text")); // NOI18N
+ pokeLimitCB.setToolTipText(bundle
+ .getString("RandomizerGUI.pokeLimitCB.toolTipText")); // NOI18N
+ pokeLimitCB.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ pokeLimitCBActionPerformed(evt);
+ }
+ });
+
+ pokeLimitBtn.setText(bundle
+ .getString("RandomizerGUI.pokeLimitBtn.text")); // NOI18N
+ pokeLimitBtn.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ pokeLimitBtnActionPerformed(evt);
+ }
+ });
+
+ javax.swing.GroupLayout otherOptionsPanelLayout = new javax.swing.GroupLayout(
+ otherOptionsPanel);
+ otherOptionsPanel.setLayout(otherOptionsPanelLayout);
+ otherOptionsPanelLayout
+ .setHorizontalGroup(otherOptionsPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ otherOptionsPanelLayout
+ .createSequentialGroup()
+ .addContainerGap()
+ .addGroup(
+ otherOptionsPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(
+ raceModeCB)
+ .addComponent(
+ brokenMovesCB)
+ .addGroup(
+ otherOptionsPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.TRAILING,
+ false)
+ .addGroup(
+ javax.swing.GroupLayout.Alignment.LEADING,
+ otherOptionsPanelLayout
+ .createSequentialGroup()
+ .addComponent(
+ codeTweaksCB)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(
+ codeTweaksBtn,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE))
+ .addGroup(
+ javax.swing.GroupLayout.Alignment.LEADING,
+ otherOptionsPanelLayout
+ .createSequentialGroup()
+ .addComponent(
+ pokeLimitCB)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(
+ pokeLimitBtn))))
+ .addContainerGap(
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE))
+ .addGroup(
+ javax.swing.GroupLayout.Alignment.TRAILING,
+ otherOptionsPanelLayout
+ .createSequentialGroup()
+ .addContainerGap(
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)
+ .addComponent(randomizeHollowsCB)
+ .addContainerGap()));
+ otherOptionsPanelLayout
+ .setVerticalGroup(otherOptionsPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ otherOptionsPanelLayout
+ .createSequentialGroup()
+ .addGroup(
+ otherOptionsPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(
+ codeTweaksCB)
+ .addComponent(
+ codeTweaksBtn))
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(
+ otherOptionsPanelLayout
+ .createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(
+ pokeLimitBtn)
+ .addComponent(
+ pokeLimitCB))
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(raceModeCB)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(randomizeHollowsCB)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(brokenMovesCB)
+ .addContainerGap(
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)));
+
+ loadQSButton.setText(bundle
+ .getString("RandomizerGUI.loadQSButton.text")); // NOI18N
+ loadQSButton.setToolTipText(bundle
+ .getString("RandomizerGUI.loadQSButton.toolTipText")); // NOI18N
+ loadQSButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ loadQSButtonActionPerformed(evt);
+ }
+ });
+
+ saveQSButton.setText(bundle
+ .getString("RandomizerGUI.saveQSButton.text")); // NOI18N
+ saveQSButton.setToolTipText(bundle
+ .getString("RandomizerGUI.saveQSButton.toolTipText")); // NOI18N
+ saveQSButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ saveQSButtonActionPerformed(evt);
+ }
+ });
+
+ updateSettingsButton.setText(bundle
+ .getString("RandomizerGUI.updateSettingsButton.text")); // NOI18N
+ updateSettingsButton
+ .addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ updateSettingsButtonActionPerformed(evt);
+ }
+ });
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(
+ getContentPane());
+ getContentPane().setLayout(layout);
+ layout.setHorizontalGroup(layout
+ .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(
+ layout.createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(
+ optionsScrollPane,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ 747, Short.MAX_VALUE)
+ .addGroup(
+ layout.createSequentialGroup()
+ .addComponent(
+ generalOptionsPanel,
+ javax.swing.GroupLayout.PREFERRED_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(
+ otherOptionsPanel,
+ javax.swing.GroupLayout.PREFERRED_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(
+ layout.createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING,
+ false)
+ .addGroup(
+ layout.createSequentialGroup()
+ .addComponent(
+ loadQSButton)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(
+ saveQSButton))
+ .addComponent(
+ romInfoPanel,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE))
+ .addGap(18, 18,
+ 18)
+ .addGroup(
+ layout.createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(
+ saveROMButton,
+ javax.swing.GroupLayout.Alignment.TRAILING,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ 147,
+ Short.MAX_VALUE)
+ .addComponent(
+ usePresetsButton,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)
+ .addComponent(
+ openROMButton,
+ javax.swing.GroupLayout.Alignment.TRAILING,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)
+ .addComponent(
+ updateSettingsButton,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)
+ .addComponent(
+ aboutButton,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE))))
+ .addContainerGap()));
+ layout.setVerticalGroup(layout
+ .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(
+ layout.createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ layout.createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING,
+ false)
+ .addComponent(
+ generalOptionsPanel,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)
+ .addComponent(
+ otherOptionsPanel,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ 0,
+ Short.MAX_VALUE))
+ .addGroup(
+ layout.createSequentialGroup()
+ .addComponent(
+ romInfoPanel,
+ javax.swing.GroupLayout.PREFERRED_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addGroup(
+ layout.createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(
+ loadQSButton)
+ .addComponent(
+ saveQSButton)))
+ .addGroup(
+ layout.createSequentialGroup()
+ .addComponent(
+ openROMButton)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(
+ saveROMButton)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(
+ usePresetsButton)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(
+ updateSettingsButton)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(
+ aboutButton)))
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(optionsScrollPane,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ 380, Short.MAX_VALUE).addContainerGap()));
+
+ pack();
+ }// //GEN-END:initComponents
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JPanel abilitiesPanel;
+ private javax.swing.JButton aboutButton;
+ private javax.swing.JPanel baseStatsPanel;
+ private javax.swing.JCheckBox brokenMovesCB;
+ private javax.swing.JButton codeTweaksBtn;
+ private javax.swing.JCheckBox codeTweaksCB;
+ private javax.swing.JRadioButton fiRandomRB;
+ private javax.swing.JRadioButton fiShuffleRB;
+ private javax.swing.JRadioButton fiUnchangedRB;
+ private javax.swing.ButtonGroup fieldItemsButtonGroup;
+ private javax.swing.JPanel fieldItemsPanel;
+ private javax.swing.JPanel generalOptionsPanel;
+ private javax.swing.JCheckBox goLowerCaseNamesCheckBox;
+ private javax.swing.JCheckBox goNationalDexCheckBox;
+ private javax.swing.JCheckBox goRemoveTradeEvosCheckBox;
+ private javax.swing.JCheckBox goUpdateMovesCheckBox;
+ private javax.swing.JCheckBox goUpdateMovesLegacyCheckBox;
+ private javax.swing.JCheckBox goUpdateTypesCheckBox;
+ private javax.swing.JRadioButton igtBothRB;
+ private javax.swing.JRadioButton igtGivenOnlyRB;
+ private javax.swing.JCheckBox igtRandomIVsCB;
+ private javax.swing.JCheckBox igtRandomItemCB;
+ private javax.swing.JCheckBox igtRandomNicknameCB;
+ private javax.swing.JCheckBox igtRandomOTCB;
+ private javax.swing.JRadioButton igtUnchangedRB;
+ private javax.swing.JPanel inGameTradesPanel;
+ private javax.swing.ButtonGroup ingameTradesButtonGroup;
+ private javax.swing.JButton loadQSButton;
+ private javax.swing.JMenuItem manualUpdateMenuItem;
+ private javax.swing.JPanel moveTutorsPanel;
+ private javax.swing.JPanel mtCompatPanel;
+ private javax.swing.ButtonGroup mtCompatibilityButtonGroup;
+ private javax.swing.ButtonGroup mtMovesButtonGroup;
+ private javax.swing.JPanel mtMovesPanel;
+ private javax.swing.JLabel mtNoExistLabel;
+ private javax.swing.JRadioButton mtcRandomTotalRB;
+ private javax.swing.JRadioButton mtcRandomTypeRB;
+ private javax.swing.JRadioButton mtcUnchangedRB;
+ private javax.swing.JRadioButton mtmRandomRB;
+ private javax.swing.JRadioButton mtmUnchangedRB;
+ private javax.swing.JButton openROMButton;
+ private javax.swing.JPanel optionsContainerPanel;
+ private javax.swing.JScrollPane optionsScrollPane;
+ private javax.swing.JPanel otherOptionsPanel;
+ private javax.swing.JRadioButton paRandomizeRB;
+ private javax.swing.JRadioButton paUnchangedRB;
+ private javax.swing.JCheckBox paWonderGuardCB;
+ private javax.swing.JRadioButton pbsChangesRandomEvosRB;
+ private javax.swing.JRadioButton pbsChangesRandomTotalRB;
+ private javax.swing.JRadioButton pbsChangesShuffleRB;
+ private javax.swing.JRadioButton pbsChangesUnchangedRB;
+ private javax.swing.JCheckBox pbsStandardEXPCurvesCB;
+ private javax.swing.JCheckBox pms4MovesCB;
+ private javax.swing.JRadioButton pmsMetronomeOnlyRB;
+ private javax.swing.JRadioButton pmsRandomTotalRB;
+ private javax.swing.JRadioButton pmsRandomTypeRB;
+ private javax.swing.JRadioButton pmsUnchangedRB;
+ private javax.swing.ButtonGroup pokeAbilitiesButtonGroup;
+ private javax.swing.JButton pokeLimitBtn;
+ private javax.swing.JCheckBox pokeLimitCB;
+ private javax.swing.ButtonGroup pokeMovesetsButtonGroup;
+ private javax.swing.ButtonGroup pokeStatChangesButtonGroup;
+ private javax.swing.ButtonGroup pokeTypesButtonGroup;
+ private javax.swing.JPanel pokemonMovesetsPanel;
+ private javax.swing.JPanel pokemonTypesPanel;
+ private javax.swing.JRadioButton ptRandomFollowEvosRB;
+ private javax.swing.JRadioButton ptRandomTotalRB;
+ private javax.swing.JRadioButton ptUnchangedRB;
+ private javax.swing.JFileChooser qsOpenChooser;
+ private javax.swing.JFileChooser qsSaveChooser;
+ private javax.swing.JCheckBox raceModeCB;
+ private javax.swing.JCheckBox randomizeHollowsCB;
+ private javax.swing.JLabel riRomCodeLabel;
+ private javax.swing.JLabel riRomNameLabel;
+ private javax.swing.JLabel riRomSupportLabel;
+ private javax.swing.JPanel romInfoPanel;
+ private javax.swing.JFileChooser romOpenChooser;
+ private javax.swing.JFileChooser romSaveChooser;
+ private javax.swing.JButton saveQSButton;
+ private javax.swing.JButton saveROMButton;
+ private javax.swing.JComboBox spCustomPoke1Chooser;
+ private javax.swing.JComboBox spCustomPoke2Chooser;
+ private javax.swing.JComboBox spCustomPoke3Chooser;
+ private javax.swing.JRadioButton spCustomRB;
+ private javax.swing.JCheckBox spHeldItemsCB;
+ private javax.swing.JRadioButton spRandom2EvosRB;
+ private javax.swing.JRadioButton spRandomRB;
+ private javax.swing.JRadioButton spUnchangedRB;
+ private javax.swing.ButtonGroup starterPokemonButtonGroup;
+ private javax.swing.JPanel starterPokemonPanel;
+ private javax.swing.ButtonGroup staticPokemonButtonGroup;
+ private javax.swing.JPanel staticPokemonPanel;
+ private javax.swing.JRadioButton stpRandomL4LRB;
+ private javax.swing.JRadioButton stpRandomTotalRB;
+ private javax.swing.JRadioButton stpUnchangedRB;
+ private javax.swing.JCheckBox tcnRandomizeCB;
+ private javax.swing.JRadioButton thcRandomTotalRB;
+ private javax.swing.JRadioButton thcRandomTypeRB;
+ private javax.swing.JRadioButton thcUnchangedRB;
+ private javax.swing.JPanel tmHmCompatPanel;
+ private javax.swing.ButtonGroup tmHmCompatibilityButtonGroup;
+ private javax.swing.ButtonGroup tmMovesButtonGroup;
+ private javax.swing.JPanel tmMovesPanel;
+ private javax.swing.JPanel tmhmsPanel;
+ private javax.swing.JRadioButton tmmRandomRB;
+ private javax.swing.JRadioButton tmmUnchangedRB;
+ private javax.swing.JCheckBox tnRandomizeCB;
+ private javax.swing.JMenuItem toggleAutoUpdatesMenuItem;
+ private javax.swing.JCheckBox tpNoEarlyShedinjaCB;
+ private javax.swing.JCheckBox tpNoLegendariesCB;
+ private javax.swing.JCheckBox tpPowerLevelsCB;
+ private javax.swing.JRadioButton tpRandomRB;
+ private javax.swing.JCheckBox tpRivalCarriesStarterCB;
+ private javax.swing.JRadioButton tpTypeThemedRB;
+ private javax.swing.JCheckBox tpTypeWeightingCB;
+ private javax.swing.JRadioButton tpUnchangedRB;
+ private javax.swing.ButtonGroup trainerPokesButtonGroup;
+ private javax.swing.JPanel trainersPokemonPanel;
+ private javax.swing.JButton updateSettingsButton;
+ private javax.swing.JPopupMenu updateSettingsMenu;
+ private javax.swing.JButton usePresetsButton;
+ private javax.swing.JPanel wildPokemonARulePanel;
+ private javax.swing.JPanel wildPokemonPanel;
+ private javax.swing.ButtonGroup wildPokesARuleButtonGroup;
+ private javax.swing.ButtonGroup wildPokesButtonGroup;
+ private javax.swing.JRadioButton wpARCatchEmAllRB;
+ private javax.swing.JRadioButton wpARNoneRB;
+ private javax.swing.JRadioButton wpARSimilarStrengthRB;
+ private javax.swing.JRadioButton wpARTypeThemedRB;
+ private javax.swing.JRadioButton wpArea11RB;
+ private javax.swing.JCheckBox wpCatchRateCB;
+ private javax.swing.JRadioButton wpGlobalRB;
+ private javax.swing.JCheckBox wpHeldItemsCB;
+ private javax.swing.JCheckBox wpNoLegendariesCB;
+ private javax.swing.JRadioButton wpRandomRB;
+ private javax.swing.JRadioButton wpUnchangedRB;
+ private javax.swing.JCheckBox wpUseTimeCB;
+ // End of variables declaration//GEN-END:variables
+}
diff --git a/src/com/dabomstew/pkrandom/gui/UpdateCheckThread.java b/src/com/dabomstew/pkrandom/gui/UpdateCheckThread.java
new file mode 100755
index 000000000..c108fabf2
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/gui/UpdateCheckThread.java
@@ -0,0 +1,75 @@
+package com.dabomstew.pkrandom.gui;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.Scanner;
+
+import javax.swing.SwingUtilities;
+
+import com.dabomstew.pkrandom.FileFunctions;
+
+public class UpdateCheckThread extends Thread {
+ private RandomizerGUI mainWindow;
+ private boolean doNotifyNone;
+
+ public UpdateCheckThread(RandomizerGUI mainWindow, boolean doNotifyNone) {
+ this.mainWindow = mainWindow;
+ this.doNotifyNone = doNotifyNone;
+ }
+
+ @Override
+ public void run() {
+ boolean found = false;
+ try {
+ byte[] versionCheck = FileFunctions
+ .downloadFile("http://pokehacks.dabomstew.com/randomizer/autoupdate/latest.txt");
+ int version = Integer.parseInt(new String(versionCheck));
+ if (version > RandomizerGUI.UPDATE_VERSION) {
+ byte[] output = FileFunctions
+ .downloadFile("http://pokehacks.dabomstew.com/randomizer/autoupdate/version.txt");
+ Scanner sc = new Scanner(new ByteArrayInputStream(output));
+ final int newVersion = Integer.parseInt(sc.nextLine());
+ if (newVersion > RandomizerGUI.UPDATE_VERSION) {
+ // Update found, parse changelog
+ StringBuilder changelog = new StringBuilder();
+ int clid = Integer.parseInt(sc.nextLine());
+ String nl = System.getProperty("line.separator");
+ boolean first = true;
+ while (clid > RandomizerGUI.UPDATE_VERSION && sc.hasNext()) {
+ if (!first) {
+ changelog.append(nl);
+ }
+ first = false;
+ String line = sc.nextLine();
+ while (line.equals("EOV") == false && sc.hasNext()) {
+ changelog.append(line + nl);
+ line = sc.nextLine();
+ }
+ clid = Integer.parseInt(sc.nextLine());
+ }
+ final String doneCL = changelog.toString();
+ found = true;
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ mainWindow.updateFound(newVersion, doneCL);
+ }
+ });
+ }
+ }
+ } catch (IOException ex) {
+ ex.printStackTrace();
+ } catch (NumberFormatException ex) {
+ ex.printStackTrace();
+ }
+ if (!found && this.doNotifyNone) {
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ mainWindow.noUpdateFound();
+ }
+ });
+ }
+ }
+
+}
diff --git a/src/com/dabomstew/pkrandom/gui/UpdateFoundDialog.form b/src/com/dabomstew/pkrandom/gui/UpdateFoundDialog.form
new file mode 100755
index 000000000..bee7442c0
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/gui/UpdateFoundDialog.form
@@ -0,0 +1,105 @@
+
+
+
diff --git a/src/com/dabomstew/pkrandom/gui/UpdateFoundDialog.java b/src/com/dabomstew/pkrandom/gui/UpdateFoundDialog.java
new file mode 100755
index 000000000..305acfa11
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/gui/UpdateFoundDialog.java
@@ -0,0 +1,281 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.dabomstew.pkrandom.gui;
+
+import java.awt.Desktop;
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URI;
+import java.util.Scanner;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+import javax.swing.JOptionPane;
+
+import com.dabomstew.pkrandom.FileFunctions;
+
+/**
+ *
+ * @author Stewart
+ */
+public class UpdateFoundDialog extends javax.swing.JDialog {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -1641494584047215623L;
+ private int targetVersion;
+
+ /**
+ * Creates new form UpdateFoundDialog
+ */
+ public UpdateFoundDialog(RandomizerGUI parent, int newVersion,
+ String changelog) {
+ super(parent, true);
+ initComponents();
+ targetVersion = newVersion;
+ Scanner sc = new Scanner(changelog);
+ String firstLine = htmlspecialchars(sc.nextLine());
+ sc.close();
+ updateFoundLabel
+ .setText("An update to the Randomizer has been found: "
+ + firstLine
+ + ".
You can see the changes made since your last update below.");
+ while (changelog.trim().toLowerCase().startsWith("")) {
+ changelog = changelog.trim().substring(6);
+ }
+ updateChangelogArea.setText(changelog);
+ updateChangelogArea.setCaretPosition(0);
+ this.setLocationRelativeTo(parent);
+ this.setVisible(true);
+
+ }
+
+ /**
+ * This method is called from within the constructor to initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is always
+ * regenerated by the Form Editor.
+ */
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ updateFoundLabel = new javax.swing.JLabel();
+ clScroller = new javax.swing.JScrollPane();
+ updateChangelogArea = new javax.swing.JTextArea();
+ downloadUpdateBtn = new javax.swing.JButton();
+ closeBtn = new javax.swing.JButton();
+
+ setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
+
+ updateFoundLabel
+ .setText("An update to the Randomizer has been found: x.x.x, released blah.
You can see the changes made below.");
+
+ clScroller
+ .setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
+
+ updateChangelogArea.setEditable(false);
+ updateChangelogArea.setColumns(40);
+ updateChangelogArea.setLineWrap(true);
+ updateChangelogArea.setRows(5);
+ updateChangelogArea.setWrapStyleWord(true);
+ updateChangelogArea.setEnabled(false);
+ clScroller.setViewportView(updateChangelogArea);
+
+ downloadUpdateBtn.setText("Download Update Now");
+ downloadUpdateBtn
+ .addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ downloadUpdateBtnActionPerformed(evt);
+ }
+ });
+
+ closeBtn.setText("Close Without Updating");
+ closeBtn.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ closeBtnActionPerformed(evt);
+ }
+ });
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(
+ getContentPane());
+ getContentPane().setLayout(layout);
+ layout.setHorizontalGroup(layout
+ .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(
+ layout.createParallelGroup(
+ javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(clScroller)
+ .addGroup(
+ layout.createSequentialGroup()
+ .addComponent(
+ updateFoundLabel,
+ javax.swing.GroupLayout.PREFERRED_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addGap(0,
+ 161,
+ Short.MAX_VALUE))
+ .addGroup(
+ layout.createSequentialGroup()
+ .addComponent(
+ downloadUpdateBtn)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.RELATED,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)
+ .addComponent(
+ closeBtn)))
+ .addContainerGap()));
+ layout.setVerticalGroup(layout
+ .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(
+ layout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(updateFoundLabel,
+ javax.swing.GroupLayout.PREFERRED_SIZE,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(clScroller,
+ javax.swing.GroupLayout.PREFERRED_SIZE,
+ 209,
+ javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(
+ javax.swing.LayoutStyle.ComponentPlacement.RELATED,
+ javax.swing.GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)
+ .addGroup(
+ layout.createParallelGroup(
+ javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(downloadUpdateBtn)
+ .addComponent(closeBtn))
+ .addContainerGap()));
+
+ pack();
+ }// //GEN-END:initComponents
+
+ private void downloadUpdateBtnActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_downloadUpdateBtnActionPerformed
+ // External: download delta file
+ String deltaFile = "delta_" + RandomizerGUI.UPDATE_VERSION + "_"
+ + targetVersion + ".zip";
+ try {
+ byte[] zip = FileFunctions
+ .downloadFile("http://pokehacks.dabomstew.com/randomizer/autoupdate/"
+ + deltaFile);
+ extract(zip, new File("./"));
+ JOptionPane
+ .showMessageDialog(
+ this,
+ "Update complete - the randomizer will now close.\n"
+ + "You should now re-open the program and begin using the new version.");
+ System.exit(0);
+ } catch (IOException ex) {
+ JOptionPane
+ .showMessageDialog(
+ this,
+ "Automatic update not available.\n"
+ + "You will now be taken to the website to download it manually.");
+ attemptOpenBrowser();
+ }
+ }// GEN-LAST:event_downloadUpdateBtnActionPerformed
+
+ private void attemptOpenBrowser() {
+ String targetURL = "http://pokehacks.dabomstew.com/randomizer/downloads.php";
+ Desktop desktop = Desktop.isDesktopSupported() ? Desktop.getDesktop()
+ : null;
+
+ if (desktop == null || !desktop.isSupported(Desktop.Action.BROWSE)) {
+ JOptionPane
+ .showMessageDialog(
+ this,
+ "The downloads page could not be opened automatically.\n"
+ + "Open a browser and navigate to the below link to download the update:\n"
+ + targetURL);
+ } else {
+ try {
+ desktop.browse(new URI(targetURL));
+ } catch (Exception e) {
+ JOptionPane
+ .showMessageDialog(
+ this,
+ "The downloads page could not be opened automatically.\n"
+ + "Open a browser and navigate to the below link to download the update:\n"
+ + targetURL);
+ }
+ }
+ this.setVisible(false);
+ }
+
+ private void extractFile(ZipInputStream in, File outdir, String name)
+ throws IOException {
+ byte[] buffer = new byte[4096];
+ BufferedOutputStream out = new BufferedOutputStream(
+ new FileOutputStream(new File(outdir, name)));
+ int count = -1;
+ while ((count = in.read(buffer)) != -1)
+ out.write(buffer, 0, count);
+ out.close();
+ }
+
+ private void mkdirs(File outdir, String path) {
+ File d = new File(outdir, path);
+ if (!d.exists())
+ d.mkdirs();
+ }
+
+ private String dirpart(String name) {
+ int s = name.lastIndexOf(File.separatorChar);
+ return s == -1 ? null : name.substring(0, s);
+ }
+
+ private String htmlspecialchars(String original) {
+ return original.replace("&", "&").replace("<", "<")
+ .replace(">", ">");
+ }
+
+ public void extract(byte[] zipfile, File outdir) throws IOException {
+ ZipInputStream zin = new ZipInputStream(new ByteArrayInputStream(
+ zipfile));
+ ZipEntry entry;
+ String name, dir;
+ while ((entry = zin.getNextEntry()) != null) {
+ name = entry.getName();
+ if (entry.isDirectory()) {
+ mkdirs(outdir, name);
+ continue;
+ }
+ /*
+ * this part is necessary because file entry can come before
+ * directory entry where is file located i.e.: /foo/foo.txt /foo/
+ */
+ dir = dirpart(name);
+ if (dir != null)
+ mkdirs(outdir, dir);
+
+ extractFile(zin, outdir, name);
+ }
+ zin.close();
+ }
+
+ private void closeBtnActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_closeBtnActionPerformed
+ this.setVisible(false);
+ }// GEN-LAST:event_closeBtnActionPerformed
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JScrollPane clScroller;
+ private javax.swing.JButton closeBtn;
+ private javax.swing.JButton downloadUpdateBtn;
+ private javax.swing.JTextArea updateChangelogArea;
+ private javax.swing.JLabel updateFoundLabel;
+ // End of variables declaration//GEN-END:variables
+}
diff --git a/src/com/dabomstew/pkrandom/gui/loading.gif b/src/com/dabomstew/pkrandom/gui/loading.gif
new file mode 100755
index 000000000..3288d1035
Binary files /dev/null and b/src/com/dabomstew/pkrandom/gui/loading.gif differ
diff --git a/src/com/dabomstew/pkrandom/newnds/CRC16.java b/src/com/dabomstew/pkrandom/newnds/CRC16.java
new file mode 100755
index 000000000..43f9bd2e6
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/newnds/CRC16.java
@@ -0,0 +1,66 @@
+package com.dabomstew.pkrandom.newnds;
+
+/*----------------------------------------------------------------------------*/
+/*-- CRC16.java - crc16 calculator for NDS checksums --*/
+/*-- Code derived from "Nintendo DS rom tool", copyright (C) DevkitPro --*/
+/*-- Original Code by Rafael Vuijk, Dave Murphy, Alexei Karpenko --*/
+/*-- --*/
+/*-- Ported to Java by Dabomstew under the terms of the GPL: --*/
+/*-- --*/
+/*-- This program is free software: you can redistribute it and/or modify --*/
+/*-- it under the terms of the GNU General Public License as published by --*/
+/*-- the Free Software Foundation, either version 3 of the License, or --*/
+/*-- (at your option) any later version. --*/
+/*-- --*/
+/*-- This program is distributed in the hope that it will be useful, --*/
+/*-- but WITHOUT ANY WARRANTY; without even the implied warranty of --*/
+/*-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --*/
+/*-- GNU General Public License for more details. --*/
+/*-- --*/
+/*-- You should have received a copy of the GNU General Public License --*/
+/*-- along with this program. If not, see . --*/
+/*----------------------------------------------------------------------------*/
+
+public class CRC16 {
+ private static final int[] table = { 0x0000, 0xC0C1, 0xC181, 0x0140,
+ 0xC301, 0x03C0, 0x0280, 0xC241, 0xC601, 0x06C0, 0x0780, 0xC741,
+ 0x0500, 0xC5C1, 0xC481, 0x0440, 0xCC01, 0x0CC0, 0x0D80, 0xCD41,
+ 0x0F00, 0xCFC1, 0xCE81, 0x0E40, 0x0A00, 0xCAC1, 0xCB81, 0x0B40,
+ 0xC901, 0x09C0, 0x0880, 0xC841, 0xD801, 0x18C0, 0x1980, 0xD941,
+ 0x1B00, 0xDBC1, 0xDA81, 0x1A40, 0x1E00, 0xDEC1, 0xDF81, 0x1F40,
+ 0xDD01, 0x1DC0, 0x1C80, 0xDC41, 0x1400, 0xD4C1, 0xD581, 0x1540,
+ 0xD701, 0x17C0, 0x1680, 0xD641, 0xD201, 0x12C0, 0x1380, 0xD341,
+ 0x1100, 0xD1C1, 0xD081, 0x1040, 0xF001, 0x30C0, 0x3180, 0xF141,
+ 0x3300, 0xF3C1, 0xF281, 0x3240, 0x3600, 0xF6C1, 0xF781, 0x3740,
+ 0xF501, 0x35C0, 0x3480, 0xF441, 0x3C00, 0xFCC1, 0xFD81, 0x3D40,
+ 0xFF01, 0x3FC0, 0x3E80, 0xFE41, 0xFA01, 0x3AC0, 0x3B80, 0xFB41,
+ 0x3900, 0xF9C1, 0xF881, 0x3840, 0x2800, 0xE8C1, 0xE981, 0x2940,
+ 0xEB01, 0x2BC0, 0x2A80, 0xEA41, 0xEE01, 0x2EC0, 0x2F80, 0xEF41,
+ 0x2D00, 0xEDC1, 0xEC81, 0x2C40, 0xE401, 0x24C0, 0x2580, 0xE541,
+ 0x2700, 0xE7C1, 0xE681, 0x2640, 0x2200, 0xE2C1, 0xE381, 0x2340,
+ 0xE101, 0x21C0, 0x2080, 0xE041, 0xA001, 0x60C0, 0x6180, 0xA141,
+ 0x6300, 0xA3C1, 0xA281, 0x6240, 0x6600, 0xA6C1, 0xA781, 0x6740,
+ 0xA501, 0x65C0, 0x6480, 0xA441, 0x6C00, 0xACC1, 0xAD81, 0x6D40,
+ 0xAF01, 0x6FC0, 0x6E80, 0xAE41, 0xAA01, 0x6AC0, 0x6B80, 0xAB41,
+ 0x6900, 0xA9C1, 0xA881, 0x6840, 0x7800, 0xB8C1, 0xB981, 0x7940,
+ 0xBB01, 0x7BC0, 0x7A80, 0xBA41, 0xBE01, 0x7EC0, 0x7F80, 0xBF41,
+ 0x7D00, 0xBDC1, 0xBC81, 0x7C40, 0xB401, 0x74C0, 0x7580, 0xB541,
+ 0x7700, 0xB7C1, 0xB681, 0x7640, 0x7200, 0xB2C1, 0xB381, 0x7340,
+ 0xB101, 0x71C0, 0x7080, 0xB041, 0x5000, 0x90C1, 0x9181, 0x5140,
+ 0x9301, 0x53C0, 0x5280, 0x9241, 0x9601, 0x56C0, 0x5780, 0x9741,
+ 0x5500, 0x95C1, 0x9481, 0x5440, 0x9C01, 0x5CC0, 0x5D80, 0x9D41,
+ 0x5F00, 0x9FC1, 0x9E81, 0x5E40, 0x5A00, 0x9AC1, 0x9B81, 0x5B40,
+ 0x9901, 0x59C0, 0x5880, 0x9841, 0x8801, 0x48C0, 0x4980, 0x8941,
+ 0x4B00, 0x8BC1, 0x8A81, 0x4A40, 0x4E00, 0x8EC1, 0x8F81, 0x4F40,
+ 0x8D01, 0x4DC0, 0x4C80, 0x8C41, 0x4400, 0x84C1, 0x8581, 0x4540,
+ 0x8701, 0x47C0, 0x4680, 0x8641, 0x8201, 0x42C0, 0x4380, 0x8341,
+ 0x4100, 0x81C1, 0x8081, 0x4040 };
+
+ public static short calculate(byte[] data, int offset, int length) {
+ int crc = 0xFFFF;
+ for (int i = 0; i < length; i++) {
+ crc = ((crc >>> 8) ^ table[(crc ^ data[i + offset]) & 0xff]);
+ }
+ return (short) crc;
+ }
+}
\ No newline at end of file
diff --git a/src/com/dabomstew/pkrandom/newnds/NDSFile.java b/src/com/dabomstew/pkrandom/newnds/NDSFile.java
new file mode 100755
index 000000000..074c1affc
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/newnds/NDSFile.java
@@ -0,0 +1,122 @@
+package com.dabomstew.pkrandom.newnds;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+
+/*----------------------------------------------------------------------------*/
+/*-- NDSFile.java - an entry in the FAT/FNT filesystem --*/
+/*-- Code based on "Nintendo DS rom tool", copyright (C) DevkitPro --*/
+/*-- Original Code by Rafael Vuijk, Dave Murphy, Alexei Karpenko --*/
+/*-- --*/
+/*-- Ported to Java by Dabomstew under the terms of the GPL: --*/
+/*-- --*/
+/*-- This program is free software: you can redistribute it and/or modify --*/
+/*-- it under the terms of the GNU General Public License as published by --*/
+/*-- the Free Software Foundation, either version 3 of the License, or --*/
+/*-- (at your option) any later version. --*/
+/*-- --*/
+/*-- This program is distributed in the hope that it will be useful, --*/
+/*-- but WITHOUT ANY WARRANTY; without even the implied warranty of --*/
+/*-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --*/
+/*-- GNU General Public License for more details. --*/
+/*-- --*/
+/*-- You should have received a copy of the GNU General Public License --*/
+/*-- along with this program. If not, see . --*/
+/*----------------------------------------------------------------------------*/
+
+public class NDSFile {
+
+ private NDSRom parent;
+ public int offset, size;
+ public int fileID;
+ public String fullPath;
+ public Extracted status = Extracted.NOT;
+ public String extFilename;
+ public byte[] data;
+
+ public NDSFile(NDSRom parent) {
+ this.parent = parent;
+ }
+
+ public byte[] getContents() throws IOException {
+ if (this.status == Extracted.NOT) {
+ // extract file
+ parent.reopenROM();
+ RandomAccessFile rom = parent.getBaseRom();
+ byte[] buf = new byte[this.size];
+ rom.seek(this.offset);
+ rom.readFully(buf);
+ if (parent.isWritingEnabled()) {
+ // make a file
+ String tmpDir = parent.getTmpFolder();
+ String tmpFilename = fullPath.replaceAll("[^A-Za-z0-9_]+", "");
+ this.extFilename = tmpFilename;
+ File tmpFile = new File(tmpDir + extFilename);
+ FileOutputStream fos = new FileOutputStream(tmpFile);
+ fos.write(buf);
+ fos.close();
+ tmpFile.deleteOnExit();
+ this.status = Extracted.TO_FILE;
+ this.data = null;
+ return buf;
+ } else {
+ this.status = Extracted.TO_RAM;
+ this.data = buf;
+ byte[] newcopy = new byte[buf.length];
+ System.arraycopy(buf, 0, newcopy, 0, buf.length);
+ return newcopy;
+ }
+ } else if (this.status == Extracted.TO_RAM) {
+ byte[] newcopy = new byte[this.data.length];
+ System.arraycopy(this.data, 0, newcopy, 0, this.data.length);
+ return newcopy;
+ } else {
+ String tmpDir = parent.getTmpFolder();
+ FileInputStream fis = new FileInputStream(tmpDir + this.extFilename);
+ byte[] file = new byte[fis.available()];
+ fis.read(file);
+ fis.close();
+ return file;
+ }
+ }
+
+ public void writeOverride(byte[] data) throws IOException {
+ if (status == Extracted.NOT) {
+ // temp extract
+ getContents();
+ }
+ if (status == Extracted.TO_FILE) {
+ String tmpDir = parent.getTmpFolder();
+ FileOutputStream fos = new FileOutputStream(new File(tmpDir
+ + this.extFilename));
+ fos.write(data);
+ fos.close();
+ } else {
+ if (this.data.length == data.length) {
+ // copy new in
+ System.arraycopy(data, 0, this.data, 0, data.length);
+ } else {
+ // make new array
+ this.data = null;
+ this.data = new byte[data.length];
+ System.arraycopy(data, 0, this.data, 0, data.length);
+ }
+ }
+ }
+
+ // returns null if no override
+ public byte[] getOverrideContents() throws IOException {
+ if (status == Extracted.NOT) {
+ return null;
+ }
+ return getContents();
+ }
+
+ private enum Extracted {
+ NOT, TO_FILE, TO_RAM;
+ }
+
+}
diff --git a/src/com/dabomstew/pkrandom/newnds/NDSRom.java b/src/com/dabomstew/pkrandom/newnds/NDSRom.java
new file mode 100755
index 000000000..db8cd36ba
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/newnds/NDSRom.java
@@ -0,0 +1,699 @@
+package com.dabomstew.pkrandom.newnds;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import com.dabomstew.pkrandom.RomFunctions;
+import com.dabomstew.pkrandom.gui.RandomizerGUI;
+
+import cuecompressors.BLZCoder;
+
+/*----------------------------------------------------------------------------*/
+/*-- NDSRom.java - base class for opening/saving ROMs --*/
+/*-- Code based on "Nintendo DS rom tool", copyright (C) DevkitPro --*/
+/*-- Original Code by Rafael Vuijk, Dave Murphy, Alexei Karpenko --*/
+/*-- --*/
+/*-- Ported to Java by Dabomstew under the terms of the GPL: --*/
+/*-- --*/
+/*-- This program is free software: you can redistribute it and/or modify --*/
+/*-- it under the terms of the GNU General Public License as published by --*/
+/*-- the Free Software Foundation, either version 3 of the License, or --*/
+/*-- (at your option) any later version. --*/
+/*-- --*/
+/*-- This program is distributed in the hope that it will be useful, --*/
+/*-- but WITHOUT ANY WARRANTY; without even the implied warranty of --*/
+/*-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --*/
+/*-- GNU General Public License for more details. --*/
+/*-- --*/
+/*-- You should have received a copy of the GNU General Public License --*/
+/*-- along with this program. If not, see . --*/
+/*----------------------------------------------------------------------------*/
+
+public class NDSRom {
+
+ private String romFilename;
+ private RandomAccessFile baseRom;
+ private boolean romOpen;
+ private Map files;
+ private Map filesByID;
+ private Map arm9overlaysByFileID;
+ private NDSY9Entry[] arm9overlays;
+ private byte[] fat;
+ private String tmpFolder;
+ private boolean writingEnabled;
+ private boolean arm9_open, arm9_changed, arm9_has_footer;
+ private boolean arm9_compressed;
+ private int arm9_szmode, arm9_szoffset;
+ private byte[] arm9_footer;
+ private byte[] arm9_ramstored;
+
+ private static final int arm9_align = 0x1FF, arm7_align = 0x1FF;
+ private static final int fnt_align = 0x1FF, fat_align = 0x1FF;
+ private static final int banner_align = 0x1FF, file_align = 0x1FF;
+
+ public NDSRom(String filename) throws IOException {
+ this.romFilename = filename;
+ this.baseRom = new RandomAccessFile(filename, "r");
+ this.romOpen = true;
+ // TMP folder?
+ String rawFilename = new File(filename).getName();
+ String dataFolder = "tmp_"
+ + rawFilename.substring(0, rawFilename.lastIndexOf('.'));
+ // remove nonsensical chars
+ dataFolder = dataFolder.replaceAll("[^A-Za-z0-9_]+", "");
+ File tmpFolder = new File(RandomizerGUI.getRootPath() + dataFolder);
+ tmpFolder.mkdir();
+ if (tmpFolder.canWrite()) {
+ writingEnabled = true;
+ this.tmpFolder = RandomizerGUI.getRootPath() + dataFolder
+ + File.separator;
+ tmpFolder.deleteOnExit();
+ } else {
+ writingEnabled = false;
+ }
+ readFileSystem();
+ arm9_open = false;
+ arm9_changed = false;
+ arm9_ramstored = null;
+ }
+
+ public void reopenROM() throws IOException {
+ if (!this.romOpen) {
+ this.baseRom = new RandomAccessFile(this.romFilename, "r");
+ this.romOpen = true;
+ }
+ }
+
+ public void closeROM() throws IOException {
+ if (this.romOpen && this.baseRom != null) {
+ this.baseRom.close();
+ this.baseRom = null;
+ this.romOpen = false;
+ }
+ }
+
+ private void readFileSystem() throws IOException {
+ baseRom.seek(0x40);
+ int fntOffset = readFromFile(baseRom, 4);
+ readFromFile(baseRom, 4); // fntSize not needed
+ int fatOffset = readFromFile(baseRom, 4);
+ int fatSize = readFromFile(baseRom, 4);
+
+ // Read full FAT table
+ baseRom.seek(fatOffset);
+ fat = new byte[fatSize];
+ baseRom.readFully(fat);
+
+ Map directoryPaths = new HashMap();
+ directoryPaths.put(0xF000, "");
+ int dircount = readFromFile(baseRom, fntOffset + 0x6, 2);
+ files = new HashMap();
+ filesByID = new HashMap();
+
+ // read fnt table
+ baseRom.seek(fntOffset);
+ int[] subTableOffsets = new int[dircount];
+ int[] firstFileIDs = new int[dircount];
+ int[] parentDirIDs = new int[dircount];
+ for (int i = 0; i < dircount && i < 0x1000; i++) {
+ subTableOffsets[i] = readFromFile(baseRom, 4) + fntOffset;
+ firstFileIDs[i] = readFromFile(baseRom, 2);
+ parentDirIDs[i] = readFromFile(baseRom, 2);
+ }
+
+ // get dirnames
+ String[] directoryNames = new String[dircount];
+ Map filenames = new TreeMap();
+ Map fileDirectories = new HashMap();
+ for (int i = 0; i < dircount && i < 0x1000; i++) {
+ firstPassDirectory(i, subTableOffsets[i], firstFileIDs[i],
+ directoryNames, filenames, fileDirectories);
+ }
+
+ // get full dirnames
+ for (int i = 1; i < dircount && i < 0x1000; i++) {
+ String dirname = directoryNames[i];
+ if (dirname != null) {
+ String fullDirName = "";
+ int curDir = i;
+ while (dirname != null && !dirname.isEmpty()) {
+ if (!fullDirName.isEmpty()) {
+ fullDirName = "/" + fullDirName;
+ }
+ fullDirName = dirname + fullDirName;
+ int parentDir = parentDirIDs[curDir];
+ if (parentDir >= 0xF001 && parentDir <= 0xFFFF) {
+ curDir = parentDir - 0xF000;
+ dirname = directoryNames[curDir];
+ } else {
+ break;
+ }
+ }
+ directoryPaths.put(i + 0xF000, fullDirName);
+ } else {
+ directoryPaths.put(i + 0xF000, "");
+ }
+ }
+
+ // parse files
+ for (int fileID : filenames.keySet()) {
+ String filename = filenames.get(fileID);
+ int directory = fileDirectories.get(fileID);
+ String dirPath = directoryPaths.get(directory + 0xF000);
+ String fullFilename = filename;
+ if (!dirPath.isEmpty()) {
+ fullFilename = dirPath + "/" + filename;
+ }
+ NDSFile nf = new NDSFile(this);
+ int start = readFromByteArr(fat, fileID * 8, 4);
+ int end = readFromByteArr(fat, fileID * 8 + 4, 4);
+ nf.offset = start;
+ nf.size = end - start;
+ nf.fullPath = fullFilename;
+ nf.fileID = fileID;
+ files.put(fullFilename, nf);
+ filesByID.put(fileID, nf);
+ }
+
+ // arm9 overlays
+ int arm9_ovl_table_offset = readFromFile(baseRom, 0x50, 4);
+ int arm9_ovl_table_size = readFromFile(baseRom, 0x54, 4);
+ int arm9_ovl_count = arm9_ovl_table_size / 32;
+ byte[] y9table = new byte[arm9_ovl_table_size];
+ arm9overlays = new NDSY9Entry[arm9_ovl_count];
+ arm9overlaysByFileID = new HashMap();
+ baseRom.seek(arm9_ovl_table_offset);
+ baseRom.readFully(y9table);
+
+ // parse overlays
+ for (int i = 0; i < arm9_ovl_count; i++) {
+ NDSY9Entry overlay = new NDSY9Entry(this);
+ int fileID = readFromByteArr(y9table, i * 32 + 24, 4);
+ int start = readFromByteArr(fat, fileID * 8, 4);
+ int end = readFromByteArr(fat, fileID * 8 + 4, 4);
+ overlay.offset = start;
+ overlay.size = end - start;
+ overlay.original_size = end - start;
+ overlay.fileID = fileID;
+ overlay.overlay_id = i;
+ overlay.ram_address = readFromByteArr(y9table, i * 32 + 4, 4);
+ overlay.ram_size = readFromByteArr(y9table, i * 32 + 8, 4);
+ overlay.bss_size = readFromByteArr(y9table, i * 32 + 12, 4);
+ overlay.static_start = readFromByteArr(y9table, i * 32 + 16, 4);
+ overlay.static_end = readFromByteArr(y9table, i * 32 + 20, 4);
+ overlay.compressed_size = readFromByteArr(y9table, i * 32 + 28, 3);
+ overlay.compress_flag = y9table[i * 32 + 31] & 0xFF;
+ arm9overlays[i] = overlay;
+ arm9overlaysByFileID.put(fileID, overlay);
+ }
+ }
+
+ public void saveTo(String filename) throws IOException {
+ this.reopenROM();
+
+ // Initialise new ROM
+ RandomAccessFile fNew = new RandomAccessFile(filename, "rw");
+
+ int headersize = readFromFile(this.baseRom, 0x84, 4);
+ this.baseRom.seek(0);
+ copy(this.baseRom, fNew, headersize);
+
+ // arm9
+ int arm9_offset = ((int) (fNew.getFilePointer() + arm9_align))
+ & (~arm9_align);
+ int old_arm9_offset = readFromFile(this.baseRom, 0x20, 4);
+ int arm9_size = readFromFile(this.baseRom, 0x2C, 4);
+ if (arm9_open && arm9_changed) {
+ // custom arm9
+ byte[] newARM9 = getARM9();
+ if (arm9_compressed) {
+ newARM9 = new BLZCoder(null).BLZ_EncodePub(newARM9, true,
+ false, "arm9.bin");
+ if (arm9_szoffset > 0) {
+ int newValue = arm9_szmode == 1 ? newARM9.length
+ : newARM9.length + 0x4000;
+ writeToByteArr(newARM9, arm9_szoffset, 3, newValue);
+ }
+ }
+ arm9_size = newARM9.length;
+ // copy new arm9
+ fNew.seek(arm9_offset);
+ fNew.write(newARM9);
+ // footer?
+ if (arm9_has_footer) {
+ fNew.write(arm9_footer);
+ }
+
+ } else {
+ // copy arm9+footer
+ this.baseRom.seek(old_arm9_offset);
+ fNew.seek(arm9_offset);
+ copy(this.baseRom, fNew, arm9_size + 12);
+ }
+
+ // arm9 ovl
+ int arm9_ovl_offset = (int) fNew.getFilePointer();
+ int arm9_ovl_size = arm9overlays.length * 32;
+
+ // don't actually write arm9 ovl yet
+
+ // arm7
+ int arm7_offset = ((int) (arm9_ovl_offset + arm9_ovl_size + arm7_align))
+ & (~arm7_align);
+ int old_arm7_offset = readFromFile(this.baseRom, 0x30, 4);
+ int arm7_size = readFromFile(this.baseRom, 0x3C, 4);
+ // copy arm7
+ this.baseRom.seek(old_arm7_offset);
+ fNew.seek(arm7_offset);
+ copy(this.baseRom, fNew, arm7_size);
+
+ // arm7 ovl
+ int arm7_ovl_offset = (int) fNew.getFilePointer();
+ int old_arm7_ovl_offset = readFromFile(this.baseRom, 0x58, 4);
+ int arm7_ovl_size = readFromFile(this.baseRom, 0x5C, 4);
+
+ // copy arm7 ovl
+ this.baseRom.seek(old_arm7_ovl_offset);
+ fNew.seek(arm7_ovl_offset);
+ copy(this.baseRom, fNew, arm7_ovl_size);
+
+ // banner
+ int banner_offset = ((int) (fNew.getFilePointer() + banner_align))
+ & (~banner_align);
+ int old_banner_offset = readFromFile(this.baseRom, 0x68, 4);
+ int banner_size = 0x840;
+ // copy banner
+ this.baseRom.seek(old_banner_offset);
+ fNew.seek(banner_offset);
+ copy(this.baseRom, fNew, banner_size);
+
+ // filename table (doesn't change)
+ int fnt_offset = ((int) (fNew.getFilePointer() + fnt_align))
+ & (~fnt_align);
+ int old_fnt_offset = readFromFile(this.baseRom, 0x40, 4);
+ int fnt_size = readFromFile(this.baseRom, 0x44, 4);
+ // copy fnt
+ this.baseRom.seek(old_fnt_offset);
+ fNew.seek(fnt_offset);
+ copy(this.baseRom, fNew, fnt_size);
+
+ // make space for the FAT table
+ int fat_offset = ((int) (fNew.getFilePointer() + fat_align))
+ & (~fat_align);
+ int fat_size = fat.length;
+
+ // Now for actual files
+ // Make a new FAT as needed
+ // also make a new y9 table
+ byte[] newfat = new byte[fat.length];
+ byte[] y9table = new byte[arm9overlays.length * 32];
+ int base_offset = fat_offset + fat_size;
+ int filecount = fat.length / 8;
+ for (int fid = 0; fid < filecount; fid++) {
+ int offset_of_file = (base_offset + file_align) & (~file_align);
+ int file_len = 0;
+ boolean copiedCustom = false;
+ if (filesByID.containsKey(fid)) {
+ byte[] customContents = filesByID.get(fid)
+ .getOverrideContents();
+ if (customContents != null) {
+ // copy custom
+ fNew.seek(offset_of_file);
+ fNew.write(customContents);
+ copiedCustom = true;
+ file_len = customContents.length;
+ }
+ }
+ if (arm9overlaysByFileID.containsKey(fid)) {
+ NDSY9Entry entry = arm9overlaysByFileID.get(fid);
+ int overlay_id = entry.overlay_id;
+ byte[] customContents = entry.getOverrideContents();
+ if (customContents != null) {
+ // copy custom
+ fNew.seek(offset_of_file);
+ fNew.write(customContents);
+ copiedCustom = true;
+ file_len = customContents.length;
+ }
+ // regardless, fill in y9 table
+ writeToByteArr(y9table, overlay_id * 32, 4, overlay_id);
+ writeToByteArr(y9table, overlay_id * 32 + 4, 4,
+ entry.ram_address);
+ writeToByteArr(y9table, overlay_id * 32 + 8, 4, entry.ram_size);
+ writeToByteArr(y9table, overlay_id * 32 + 12, 4, entry.bss_size);
+ writeToByteArr(y9table, overlay_id * 32 + 16, 4,
+ entry.static_start);
+ writeToByteArr(y9table, overlay_id * 32 + 20, 4,
+ entry.static_end);
+ writeToByteArr(y9table, overlay_id * 32 + 24, 4, fid);
+ writeToByteArr(y9table, overlay_id * 32 + 28, 3,
+ entry.compressed_size);
+ writeToByteArr(y9table, overlay_id * 32 + 31, 1,
+ entry.compress_flag);
+ }
+ if (!copiedCustom) {
+ // copy from original ROM
+ int file_starts = readFromByteArr(fat, fid * 8, 4);
+ int file_ends = readFromByteArr(fat, fid * 8 + 4, 4);
+ file_len = file_ends - file_starts;
+ this.baseRom.seek(file_starts);
+ fNew.seek(offset_of_file);
+ copy(this.baseRom, fNew, file_len);
+ }
+ // write to new FAT
+ writeToByteArr(newfat, fid * 8, 4, offset_of_file);
+ writeToByteArr(newfat, fid * 8 + 4, 4, offset_of_file + file_len);
+ // update base_offset
+ base_offset = offset_of_file + file_len;
+ }
+
+ // write new FAT table
+ fNew.seek(fat_offset);
+ fNew.write(newfat);
+
+ // write y9 table
+ fNew.seek(arm9_ovl_offset);
+ fNew.write(y9table);
+
+ // tidy up ending
+ // base_offset is the end of the last file
+ int newfilesize = base_offset;
+ newfilesize = (newfilesize + 3) & ~3;
+ int application_end_offset = newfilesize;
+ if (newfilesize != base_offset) {
+ fNew.seek(newfilesize - 1);
+ fNew.write(0);
+ }
+
+ // calculate device capacity;
+ newfilesize |= newfilesize >> 16;
+ newfilesize |= newfilesize >> 8;
+ newfilesize |= newfilesize >> 4;
+ newfilesize |= newfilesize >> 2;
+ newfilesize |= newfilesize >> 1;
+ newfilesize++;
+ if (newfilesize <= 128 * 1024) {
+ newfilesize = 128 * 1024;
+ }
+ int devcap = -18;
+ int x = newfilesize;
+ while (x != 0) {
+ x >>= 1;
+ devcap++;
+ }
+ int devicecap = ((devcap < 0) ? 0 : devcap);
+
+ // Update offsets in ROM header
+ writeToFile(fNew, 0x20, 4, arm9_offset);
+ writeToFile(fNew, 0x2C, 4, arm9_size);
+ writeToFile(fNew, 0x30, 4, arm7_offset);
+ writeToFile(fNew, 0x3C, 4, arm7_size);
+ writeToFile(fNew, 0x40, 4, fnt_offset);
+ writeToFile(fNew, 0x48, 4, fat_offset);
+ writeToFile(fNew, 0x50, 4, arm9_ovl_offset);
+ writeToFile(fNew, 0x58, 4, arm7_ovl_offset);
+ writeToFile(fNew, 0x68, 4, banner_offset);
+ writeToFile(fNew, 0x80, 4, application_end_offset);
+ writeToFile(fNew, 0x14, 1, devicecap);
+
+ // Update header CRC
+ fNew.seek(0);
+ byte[] headerForCRC = new byte[0x15E];
+ fNew.readFully(headerForCRC);
+ short crc = CRC16.calculate(headerForCRC, 0, 0x15E);
+ writeToFile(fNew, 0x15E, 2, (crc & 0xFFFF));
+
+ // done
+ fNew.close();
+ closeROM();
+ }
+
+ private void copy(RandomAccessFile from, RandomAccessFile to, int bytes)
+ throws IOException {
+ int sizeof_copybuf = Math.min(256 * 1024, bytes);
+ byte[] copybuf = new byte[sizeof_copybuf];
+ while (bytes > 0) {
+ int size2 = (bytes >= sizeof_copybuf) ? sizeof_copybuf : bytes;
+ int read = from.read(copybuf, 0, size2);
+ to.write(copybuf, 0, read);
+ bytes -= read;
+ }
+ copybuf = null;
+ }
+
+ // returns null if file doesn't exist
+ public byte[] getFile(String filename) throws IOException {
+ if (files.containsKey(filename)) {
+ return files.get(filename).getContents();
+ } else {
+ return null;
+ }
+ }
+
+ public byte[] getOverlay(int number) throws IOException {
+ if (number >= 0 && number <= arm9overlays.length) {
+ return arm9overlays[number].getContents();
+ } else {
+ return null;
+ }
+ }
+
+ public byte[] getARM9() throws IOException {
+ if (!arm9_open) {
+ arm9_open = true;
+ this.reopenROM();
+ int arm9_offset = readFromFile(this.baseRom, 0x20, 4);
+ int arm9_size = readFromFile(this.baseRom, 0x2C, 4);
+ byte[] arm9 = new byte[arm9_size];
+ this.baseRom.seek(arm9_offset);
+ this.baseRom.readFully(arm9);
+ // footer check
+ int nitrocode = readFromFile(this.baseRom, 4);
+ if (nitrocode == 0xDEC00621) {
+ // found a footer
+ arm9_footer = new byte[12];
+ writeToByteArr(arm9_footer, 0, 4, 0xDEC00621);
+ this.baseRom.read(arm9_footer, 4, 8);
+ arm9_has_footer = true;
+ } else {
+ arm9_has_footer = false;
+ }
+ // Any extras?
+ while ((readFromByteArr(arm9, arm9.length - 12, 4) == 0xDEC00621)
+ || ((readFromByteArr(arm9, arm9.length - 12, 4) == 0
+ && readFromByteArr(arm9, arm9.length - 8, 4) == 0 && readFromByteArr(
+ arm9, arm9.length - 4, 4) == 0))) {
+ if (!arm9_has_footer) {
+ arm9_has_footer = true;
+ arm9_footer = new byte[0];
+ }
+ byte[] newfooter = new byte[arm9_footer.length + 12];
+ System.arraycopy(arm9, arm9.length - 12, newfooter, 0, 12);
+ System.arraycopy(arm9_footer, 0, newfooter, 12,
+ arm9_footer.length);
+ arm9_footer = newfooter;
+ byte[] newarm9 = new byte[arm9.length - 12];
+ System.arraycopy(arm9, 0, newarm9, 0, arm9.length - 12);
+ arm9 = newarm9;
+ }
+ // Compression?
+ arm9_compressed = false;
+ arm9_szoffset = 0;
+ if (((int) arm9[arm9.length - 5]) >= 0x08
+ && ((int) arm9[arm9.length - 5]) <= 0x0B) {
+ int compSize = readFromByteArr(arm9, arm9.length - 8, 3);
+ if (compSize > (arm9.length * 9 / 10)
+ && compSize < (arm9.length * 11 / 10)) {
+ arm9_compressed = true;
+ byte[] compLength = new byte[3];
+ writeToByteArr(compLength, 0, 3, arm9.length);
+ List foundOffsets = RomFunctions.search(arm9,
+ compLength);
+ if (foundOffsets.size() == 1) {
+ arm9_szmode = 1;
+ arm9_szoffset = foundOffsets.get(0);
+ } else {
+ byte[] compLength2 = new byte[3];
+ writeToByteArr(compLength2, 0, 3, arm9.length + 0x4000);
+ List foundOffsets2 = RomFunctions.search(arm9,
+ compLength2);
+ if (foundOffsets2.size() == 1) {
+ arm9_szmode = 2;
+ arm9_szoffset = foundOffsets2.get(0);
+ } else {
+ }
+ }
+ }
+ }
+
+ if (arm9_compressed) {
+ arm9 = new BLZCoder(null).BLZ_DecodePub(arm9, "arm9.bin");
+ }
+
+ // Now actually make the copy or w/e
+ if (writingEnabled) {
+ File arm9file = new File(tmpFolder + "arm9.bin");
+ FileOutputStream fos = new FileOutputStream(arm9file);
+ fos.write(arm9);
+ fos.close();
+ arm9file.deleteOnExit();
+ this.arm9_ramstored = null;
+ return arm9;
+ } else {
+ this.arm9_ramstored = arm9;
+ byte[] newcopy = new byte[arm9.length];
+ System.arraycopy(arm9, 0, newcopy, 0, arm9.length);
+ return newcopy;
+ }
+ } else {
+ if (writingEnabled) {
+ FileInputStream fis = new FileInputStream(tmpFolder
+ + "arm9.bin");
+ byte[] file = new byte[fis.available()];
+ fis.read(file);
+ fis.close();
+ return file;
+ } else {
+ byte[] newcopy = new byte[this.arm9_ramstored.length];
+ System.arraycopy(this.arm9_ramstored, 0, newcopy, 0,
+ this.arm9_ramstored.length);
+ return newcopy;
+ }
+ }
+ }
+
+ // returns null if file doesn't exist
+ public void writeFile(String filename, byte[] data) throws IOException {
+ if (files.containsKey(filename)) {
+ files.get(filename).writeOverride(data);
+ }
+ }
+
+ public void writeOverlay(int number, byte[] data) throws IOException {
+ if (number >= 0 && number <= arm9overlays.length) {
+ arm9overlays[number].writeOverride(data);
+ }
+ }
+
+ public void writeARM9(byte[] arm9) throws IOException {
+ if (!arm9_open) {
+ getARM9();
+ }
+ arm9_changed = true;
+ if (writingEnabled) {
+ FileOutputStream fos = new FileOutputStream(new File(tmpFolder
+ + "arm9.bin"));
+ fos.write(arm9);
+ fos.close();
+ } else {
+ if (this.arm9_ramstored.length == arm9.length) {
+ // copy new in
+ System.arraycopy(arm9, 0, this.arm9_ramstored, 0, arm9.length);
+ } else {
+ // make new array
+ this.arm9_ramstored = null;
+ this.arm9_ramstored = new byte[arm9.length];
+ System.arraycopy(arm9, 0, this.arm9_ramstored, 0, arm9.length);
+ }
+ }
+ }
+
+ private void firstPassDirectory(int dir, int subTableOffset,
+ int firstFileID, String[] directoryNames,
+ Map filenames,
+ Map fileDirectories) throws IOException {
+ // read subtable
+ baseRom.seek(subTableOffset);
+ while (true) {
+ int control = baseRom.read();
+ if (control == 0x00) {
+ // done
+ break;
+ }
+ int namelen = control & 0x7F;
+ byte[] rawname = new byte[namelen];
+ baseRom.readFully(rawname);
+ String name = new String(rawname, "US-ASCII");
+ if ((control & 0x80) > 0x00) {
+ // sub-directory
+ int subDirectoryID = readFromFile(baseRom, 2);
+ directoryNames[subDirectoryID - 0xF000] = name;
+ } else {
+ int fileID = firstFileID++;
+ filenames.put(fileID, name);
+ fileDirectories.put(fileID, dir);
+ }
+ }
+ }
+
+ // Helper methods to get variable-size ints out of files
+
+ public String getTmpFolder() {
+ return tmpFolder;
+ }
+
+ public RandomAccessFile getBaseRom() {
+ return baseRom;
+ }
+
+ public boolean isWritingEnabled() {
+ return writingEnabled;
+ }
+
+ public int readFromByteArr(byte[] data, int offset, int size) {
+ int result = 0;
+ for (int i = 0; i < size; i++) {
+ result |= (data[i + offset] & 0xFF) << (i * 8);
+ }
+ return result;
+ }
+
+ public void writeToByteArr(byte[] data, int offset, int size, int value) {
+ for (int i = 0; i < size; i++) {
+ data[offset + i] = (byte) ((value >> (i * 8)) & 0xFF);
+ }
+ }
+
+ public int readFromFile(RandomAccessFile file, int size) throws IOException {
+ return readFromFile(file, -1, size);
+ }
+
+ // use -1 offset to read from current position
+ // useful if you want to read blocks
+ public int readFromFile(RandomAccessFile file, int offset, int size)
+ throws IOException {
+ byte[] buf = new byte[size];
+ if (offset >= 0)
+ file.seek(offset);
+ file.readFully(buf);
+ int result = 0;
+ for (int i = 0; i < size; i++) {
+ result |= (buf[i] & 0xFF) << (i * 8);
+ }
+ return result;
+ }
+
+ public void writeToFile(RandomAccessFile file, int size, int value)
+ throws IOException {
+ writeToFile(file, -1, size, value);
+ }
+
+ public void writeToFile(RandomAccessFile file, int offset, int size,
+ int value) throws IOException {
+ byte[] buf = new byte[size];
+ for (int i = 0; i < size; i++) {
+ buf[i] = (byte) ((value >> (i * 8)) & 0xFF);
+ }
+ if (offset >= 0)
+ file.seek(offset);
+ file.write(buf);
+ }
+
+}
diff --git a/src/com/dabomstew/pkrandom/newnds/NDSY9Entry.java b/src/com/dabomstew/pkrandom/newnds/NDSY9Entry.java
new file mode 100755
index 000000000..8791167f7
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/newnds/NDSY9Entry.java
@@ -0,0 +1,147 @@
+package com.dabomstew.pkrandom.newnds;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+
+import cuecompressors.BLZCoder;
+
+/*----------------------------------------------------------------------------*/
+/*-- NDSY9Entry.java - an entry in the arm9 overlay system --*/
+/*-- Code based on "Nintendo DS rom tool", copyright (C) DevkitPro --*/
+/*-- Original Code by Rafael Vuijk, Dave Murphy, Alexei Karpenko --*/
+/*-- --*/
+/*-- Ported to Java by Dabomstew under the terms of the GPL: --*/
+/*-- --*/
+/*-- This program is free software: you can redistribute it and/or modify --*/
+/*-- it under the terms of the GNU General Public License as published by --*/
+/*-- the Free Software Foundation, either version 3 of the License, or --*/
+/*-- (at your option) any later version. --*/
+/*-- --*/
+/*-- This program is distributed in the hope that it will be useful, --*/
+/*-- but WITHOUT ANY WARRANTY; without even the implied warranty of --*/
+/*-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --*/
+/*-- GNU General Public License for more details. --*/
+/*-- --*/
+/*-- You should have received a copy of the GNU General Public License --*/
+/*-- along with this program. If not, see . --*/
+/*----------------------------------------------------------------------------*/
+
+public class NDSY9Entry {
+
+ private NDSRom parent;
+ public int offset, size, original_size;
+ public int fileID;
+ public int overlay_id;
+ public int ram_address, ram_size;
+ public int bss_size;
+ public int static_start, static_end;
+ public int compressed_size;
+ public int compress_flag;
+ public Extracted status = Extracted.NOT;
+ public String extFilename;
+ public byte[] data;
+ private boolean decompressed_data = false;
+
+ public NDSY9Entry(NDSRom parent) {
+ this.parent = parent;
+ }
+
+ public byte[] getContents() throws IOException {
+ if (this.status == Extracted.NOT) {
+ // extract file
+ parent.reopenROM();
+ RandomAccessFile rom = parent.getBaseRom();
+ byte[] buf = new byte[this.original_size];
+ rom.seek(this.offset);
+ rom.readFully(buf);
+ // Compression?
+ if (compress_flag != 0
+ && this.original_size == this.compressed_size
+ && this.compressed_size != 0) {
+ buf = new BLZCoder(null).BLZ_DecodePub(buf, "overlay "
+ + overlay_id);
+ decompressed_data = true;
+ }
+ if (parent.isWritingEnabled()) {
+ // make a file
+ String tmpDir = parent.getTmpFolder();
+ String fullPath = String.format("overlay_%04d", overlay_id);
+ String tmpFilename = fullPath.replaceAll("[^A-Za-z0-9_]+", "");
+ this.extFilename = tmpFilename;
+ File tmpFile = new File(tmpDir + extFilename);
+ FileOutputStream fos = new FileOutputStream(tmpFile);
+ fos.write(buf);
+ fos.close();
+ tmpFile.deleteOnExit();
+ this.status = Extracted.TO_FILE;
+ this.data = null;
+ return buf;
+ } else {
+ this.status = Extracted.TO_RAM;
+ this.data = buf;
+ byte[] newcopy = new byte[buf.length];
+ System.arraycopy(buf, 0, newcopy, 0, buf.length);
+ return newcopy;
+ }
+ } else if (this.status == Extracted.TO_RAM) {
+ byte[] newcopy = new byte[this.data.length];
+ System.arraycopy(this.data, 0, newcopy, 0, this.data.length);
+ return newcopy;
+ } else {
+ String tmpDir = parent.getTmpFolder();
+ FileInputStream fis = new FileInputStream(tmpDir + this.extFilename);
+ byte[] file = new byte[fis.available()];
+ fis.read(file);
+ fis.close();
+ return file;
+ }
+ }
+
+ public void writeOverride(byte[] data) throws IOException {
+ if (status == Extracted.NOT) {
+ // temp extract
+ getContents();
+ }
+ size = data.length;
+ if (status == Extracted.TO_FILE) {
+ String tmpDir = parent.getTmpFolder();
+ FileOutputStream fos = new FileOutputStream(new File(tmpDir
+ + this.extFilename));
+ fos.write(data);
+ fos.close();
+ } else {
+ if (this.data.length == data.length) {
+ // copy new in
+ System.arraycopy(data, 0, this.data, 0, data.length);
+ } else {
+ // make new array
+ this.data = null;
+ this.data = new byte[data.length];
+ System.arraycopy(data, 0, this.data, 0, data.length);
+ }
+ }
+ }
+
+ // returns null if no override
+ public byte[] getOverrideContents() throws IOException {
+ if (status == Extracted.NOT) {
+ return null;
+ }
+ byte[] buf = getContents();
+ if (this.decompressed_data) {
+ buf = new BLZCoder(null).BLZ_EncodePub(buf, false, false,
+ "overlay " + overlay_id);
+ // update our compressed size
+ this.compressed_size = buf.length;
+ }
+ return buf;
+ }
+
+ private enum Extracted {
+ NOT, TO_FILE, TO_RAM;
+ }
+
+}
diff --git a/src/com/dabomstew/pkrandom/patches/crystal_en_bwxp.ips b/src/com/dabomstew/pkrandom/patches/crystal_en_bwxp.ips
new file mode 100755
index 000000000..5c47f28b3
Binary files /dev/null and b/src/com/dabomstew/pkrandom/patches/crystal_en_bwxp.ips differ
diff --git a/src/com/dabomstew/pkrandom/patches/gs_en_bwxp.ips b/src/com/dabomstew/pkrandom/patches/gs_en_bwxp.ips
new file mode 100755
index 000000000..db8f16cca
Binary files /dev/null and b/src/com/dabomstew/pkrandom/patches/gs_en_bwxp.ips differ
diff --git a/src/com/dabomstew/pkrandom/patches/rb_en_bwxp.ips b/src/com/dabomstew/pkrandom/patches/rb_en_bwxp.ips
new file mode 100755
index 000000000..e8ba4b70b
Binary files /dev/null and b/src/com/dabomstew/pkrandom/patches/rb_en_bwxp.ips differ
diff --git a/src/com/dabomstew/pkrandom/patches/rb_en_critrate.ips b/src/com/dabomstew/pkrandom/patches/rb_en_critrate.ips
new file mode 100755
index 000000000..f08ef39a4
Binary files /dev/null and b/src/com/dabomstew/pkrandom/patches/rb_en_critrate.ips differ
diff --git a/src/com/dabomstew/pkrandom/patches/rb_en_xaccnerf.ips b/src/com/dabomstew/pkrandom/patches/rb_en_xaccnerf.ips
new file mode 100755
index 000000000..426753a4b
Binary files /dev/null and b/src/com/dabomstew/pkrandom/patches/rb_en_xaccnerf.ips differ
diff --git a/src/com/dabomstew/pkrandom/patches/yellow_en_bwxp.ips b/src/com/dabomstew/pkrandom/patches/yellow_en_bwxp.ips
new file mode 100755
index 000000000..96be65567
Binary files /dev/null and b/src/com/dabomstew/pkrandom/patches/yellow_en_bwxp.ips differ
diff --git a/src/com/dabomstew/pkrandom/patches/yellow_en_critrate.ips b/src/com/dabomstew/pkrandom/patches/yellow_en_critrate.ips
new file mode 100755
index 000000000..a691f04f9
Binary files /dev/null and b/src/com/dabomstew/pkrandom/patches/yellow_en_critrate.ips differ
diff --git a/src/com/dabomstew/pkrandom/patches/yellow_en_xaccnerf.ips b/src/com/dabomstew/pkrandom/patches/yellow_en_xaccnerf.ips
new file mode 100755
index 000000000..e968abe1f
Binary files /dev/null and b/src/com/dabomstew/pkrandom/patches/yellow_en_xaccnerf.ips differ
diff --git a/src/com/dabomstew/pkrandom/pokemon/Encounter.java b/src/com/dabomstew/pkrandom/pokemon/Encounter.java
new file mode 100755
index 000000000..d6af69cc9
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/pokemon/Encounter.java
@@ -0,0 +1,43 @@
+package com.dabomstew.pkrandom.pokemon;
+
+/*----------------------------------------------------------------------------*/
+/*-- Encounter.java - contains one wild Pokemon slot --*/
+/*-- --*/
+/*-- Part of "Universal Pokemon Randomizer" by Dabomstew --*/
+/*-- Pokemon and any associated names and the like are --*/
+/*-- trademark and (C) Nintendo 1996-2012. --*/
+/*-- --*/
+/*-- The custom code written here is licensed under the terms of the GPL: --*/
+/*-- --*/
+/*-- This program is free software: you can redistribute it and/or modify --*/
+/*-- it under the terms of the GNU General Public License as published by --*/
+/*-- the Free Software Foundation, either version 3 of the License, or --*/
+/*-- (at your option) any later version. --*/
+/*-- --*/
+/*-- This program is distributed in the hope that it will be useful, --*/
+/*-- but WITHOUT ANY WARRANTY; without even the implied warranty of --*/
+/*-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --*/
+/*-- GNU General Public License for more details. --*/
+/*-- --*/
+/*-- You should have received a copy of the GNU General Public License --*/
+/*-- along with this program. If not, see . --*/
+/*----------------------------------------------------------------------------*/
+
+public class Encounter {
+
+ public int level;
+ public int maxLevel;
+ public Pokemon pokemon;
+
+ public String toString() {
+ if (pokemon == null) {
+ return "ERROR";
+ }
+ if (maxLevel == 0) {
+ return pokemon.name + " Lv" + level;
+ } else {
+ return pokemon.name + " Lvs " + level + "-" + maxLevel;
+ }
+ }
+
+}
diff --git a/src/com/dabomstew/pkrandom/pokemon/EncounterSet.java b/src/com/dabomstew/pkrandom/pokemon/EncounterSet.java
new file mode 100755
index 000000000..33c264dbb
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/pokemon/EncounterSet.java
@@ -0,0 +1,42 @@
+package com.dabomstew.pkrandom.pokemon;
+
+/*----------------------------------------------------------------------------*/
+/*-- EncounterSet.java - contains a group of wild Pokemon --*/
+/*-- --*/
+/*-- Part of "Universal Pokemon Randomizer" by Dabomstew --*/
+/*-- Pokemon and any associated names and the like are --*/
+/*-- trademark and (C) Nintendo 1996-2012. --*/
+/*-- --*/
+/*-- The custom code written here is licensed under the terms of the GPL: --*/
+/*-- --*/
+/*-- This program is free software: you can redistribute it and/or modify --*/
+/*-- it under the terms of the GNU General Public License as published by --*/
+/*-- the Free Software Foundation, either version 3 of the License, or --*/
+/*-- (at your option) any later version. --*/
+/*-- --*/
+/*-- This program is distributed in the hope that it will be useful, --*/
+/*-- but WITHOUT ANY WARRANTY; without even the implied warranty of --*/
+/*-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --*/
+/*-- GNU General Public License for more details. --*/
+/*-- --*/
+/*-- You should have received a copy of the GNU General Public License --*/
+/*-- along with this program. If not, see . --*/
+/*----------------------------------------------------------------------------*/
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class EncounterSet {
+
+ public int rate;
+ public List encounters = new ArrayList();
+ public boolean battleTrappersBanned = false;
+ public String displayName;
+ public int offset;
+
+ public String toString() {
+ return "Encounter [Rate = " + rate + ", Encounters = " + encounters
+ + "]";
+ }
+
+}
diff --git a/src/com/dabomstew/pkrandom/pokemon/Evolution.java b/src/com/dabomstew/pkrandom/pokemon/Evolution.java
new file mode 100755
index 000000000..503daec07
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/pokemon/Evolution.java
@@ -0,0 +1,82 @@
+package com.dabomstew.pkrandom.pokemon;
+
+/*----------------------------------------------------------------------------*/
+/*-- Evolution.java - represents an evolution between 2 Pokemon. --*/
+/*-- --*/
+/*-- Part of "Universal Pokemon Randomizer" by Dabomstew --*/
+/*-- Pokemon and any associated names and the like are --*/
+/*-- trademark and (C) Nintendo 1996-2012. --*/
+/*-- --*/
+/*-- The custom code written here is licensed under the terms of the GPL: --*/
+/*-- --*/
+/*-- This program is free software: you can redistribute it and/or modify --*/
+/*-- it under the terms of the GNU General Public License as published by --*/
+/*-- the Free Software Foundation, either version 3 of the License, or --*/
+/*-- (at your option) any later version. --*/
+/*-- --*/
+/*-- This program is distributed in the hope that it will be useful, --*/
+/*-- but WITHOUT ANY WARRANTY; without even the implied warranty of --*/
+/*-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --*/
+/*-- GNU General Public License for more details. --*/
+/*-- --*/
+/*-- You should have received a copy of the GNU General Public License --*/
+/*-- along with this program. If not, see . --*/
+/*----------------------------------------------------------------------------*/
+
+public class Evolution implements Comparable {
+
+ public int from;
+ public int to;
+ public boolean carryStats;
+ public EvolutionType type;
+ public int extraInfo;
+
+ public Evolution(int from, int to, boolean carryStats, EvolutionType type, int extra) {
+ this.from = from;
+ this.to = to;
+ this.carryStats = carryStats;
+ this.type = type;
+ this.extraInfo = extra;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + from;
+ result = prime * result + to;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ Evolution other = (Evolution) obj;
+ if (from != other.from)
+ return false;
+ if (to != other.to)
+ return false;
+ return true;
+ }
+
+ @Override
+ public int compareTo(Evolution o) {
+ if (this.from < o.from) {
+ return -1;
+ } else if (this.from > o.from) {
+ return 1;
+ } else if (this.to < o.to) {
+ return -1;
+ } else if (this.to > o.to) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+
+}
diff --git a/src/com/dabomstew/pkrandom/pokemon/EvolutionType.java b/src/com/dabomstew/pkrandom/pokemon/EvolutionType.java
new file mode 100755
index 000000000..ea362f8db
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/pokemon/EvolutionType.java
@@ -0,0 +1,42 @@
+package com.dabomstew.pkrandom.pokemon;
+
+public enum EvolutionType {
+ LEVEL(1, 1, 4, 4, 4), STONE(2, 2, 7, 7, 8), TRADE(3, 3, 5, 5, 5), TRADE_ITEM(
+ -1, 3, 6, 6, 6), HAPPINESS(-1, 4, 1, 1, 1), HAPPINESS_DAY(-1, 4, 2,
+ 2, 2), HAPPINESS_NIGHT(-1, 4, 3, 3, 3), LEVEL_ATTACK_HIGHER(-1, 5,
+ 8, 8, 9), LEVEL_DEFENSE_HIGHER(-1, 5, 10, 10, 11), LEVEL_ATK_DEF_SAME(
+ -1, 5, 9, 9, 10), LEVEL_LOW_PV(-1, -1, 11, 11, 12), LEVEL_HIGH_PV(
+ -1, -1, 12, 12, 13), LEVEL_CREATE_EXTRA(-1, -1, 13, 13, 14), LEVEL_IS_EXTRA(
+ -1, -1, 14, 14, 15), LEVEL_HIGH_BEAUTY(-1, -1, 15, 15, 16), STONE_MALE_ONLY(
+ -1, -1, -1, 16, 17), STONE_FEMALE_ONLY(-1, -1, -1, 17, 18), LEVEL_ITEM_DAY(
+ -1, -1, -1, 18, 19), LEVEL_ITEM_NIGHT(-1, -1, -1, 19, 20), LEVEL_WITH_MOVE(
+ -1, -1, -1, 20, 21), LEVEL_WITH_OTHER(-1, -1, -1, 21, 22), LEVEL_MALE_ONLY(
+ -1, -1, -1, 22, 23), LEVEL_FEMALE_ONLY(-1, -1, -1, 23, 24), LEVEL_ELECTRIFIED_AREA(
+ -1, -1, -1, 24, 25), LEVEL_MOSS_ROCK(-1, -1, -1, 25, 26), LEVEL_ICY_ROCK(
+ -1, -1, -1, 26, 27), TRADE_SPECIAL(-1, -1, -1, -1, 7);
+ private int[] indexNumbers;
+ private static EvolutionType[][] reverseIndexes = new EvolutionType[5][30];
+
+ static {
+ for (EvolutionType et : EvolutionType.values()) {
+ for (int i = 0; i < et.indexNumbers.length; i++) {
+ if (et.indexNumbers[i] > 0
+ && reverseIndexes[i][et.indexNumbers[i]] == null) {
+ reverseIndexes[i][et.indexNumbers[i]] = et;
+ }
+ }
+ }
+ }
+
+ private EvolutionType(int... indexes) {
+ this.indexNumbers = indexes;
+ }
+
+ public int toIndex(int generation) {
+ return indexNumbers[generation - 1];
+ }
+
+ public static EvolutionType fromIndex(int generation, int index) {
+ return reverseIndexes[generation - 1][index];
+ }
+}
diff --git a/src/com/dabomstew/pkrandom/pokemon/ExpCurve.java b/src/com/dabomstew/pkrandom/pokemon/ExpCurve.java
new file mode 100755
index 000000000..399867044
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/pokemon/ExpCurve.java
@@ -0,0 +1,43 @@
+package com.dabomstew.pkrandom.pokemon;
+
+public enum ExpCurve {
+
+ SLOW, MEDIUM_SLOW, MEDIUM_FAST, FAST, ERRATIC, FLUCTUATING;
+
+ public static ExpCurve fromByte(byte curve) {
+ switch (curve) {
+ case 0:
+ return MEDIUM_FAST;
+ case 1:
+ return ERRATIC;
+ case 2:
+ return FLUCTUATING;
+ case 3:
+ return MEDIUM_SLOW;
+ case 4:
+ return FAST;
+ case 5:
+ return SLOW;
+ }
+ return null;
+ }
+
+ public byte toByte() {
+ switch (this) {
+ case SLOW:
+ return 5;
+ case MEDIUM_SLOW:
+ return 3;
+ case MEDIUM_FAST:
+ return 0;
+ case FAST:
+ return 4;
+ case ERRATIC:
+ return 1;
+ case FLUCTUATING:
+ return 2;
+ }
+ return 0; // default
+ }
+
+}
diff --git a/src/com/dabomstew/pkrandom/pokemon/GenRestrictions.java b/src/com/dabomstew/pkrandom/pokemon/GenRestrictions.java
new file mode 100755
index 000000000..1d6ca97b1
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/pokemon/GenRestrictions.java
@@ -0,0 +1,88 @@
+package com.dabomstew.pkrandom.pokemon;
+
+public class GenRestrictions {
+
+ public boolean allow_gen1, allow_gen2, allow_gen3, allow_gen4, allow_gen5;
+
+ public boolean assoc_g1_g2, assoc_g1_g4;
+ public boolean assoc_g2_g1, assoc_g2_g3, assoc_g2_g4;
+ public boolean assoc_g3_g2, assoc_g3_g4;
+ public boolean assoc_g4_g1, assoc_g4_g2, assoc_g4_g3;
+
+ public GenRestrictions() {
+ }
+
+ public GenRestrictions(int state) {
+ allow_gen1 = (state & 1) > 0;
+ allow_gen2 = (state & 2) > 0;
+ allow_gen3 = (state & 4) > 0;
+ allow_gen4 = (state & 8) > 0;
+ allow_gen5 = (state & 16) > 0;
+
+ assoc_g1_g2 = (state & 32) > 0;
+ assoc_g1_g4 = (state & 64) > 0;
+
+ assoc_g2_g1 = (state & 128) > 0;
+ assoc_g2_g3 = (state & 256) > 0;
+ assoc_g2_g4 = (state & 512) > 0;
+
+ assoc_g3_g2 = (state & 1024) > 0;
+ assoc_g3_g4 = (state & 2048) > 0;
+
+ assoc_g4_g1 = (state & 4096) > 0;
+ assoc_g4_g2 = (state & 8192) > 0;
+ assoc_g4_g3 = (state & 16384) > 0;
+ }
+
+ public boolean nothingSelected() {
+ return !allow_gen1 && !allow_gen2 && !allow_gen3 && !allow_gen4
+ && !allow_gen5;
+ }
+
+ public int toInt() {
+ return makeIntSelected(allow_gen1, allow_gen2, allow_gen3, allow_gen4,
+ allow_gen5, assoc_g1_g2, assoc_g1_g4, assoc_g2_g1, assoc_g2_g3,
+ assoc_g2_g4, assoc_g3_g2, assoc_g3_g4, assoc_g4_g1,
+ assoc_g4_g2, assoc_g4_g3);
+ }
+
+ public void limitToGen(int generation) {
+ if (generation < 2) {
+ allow_gen2 = false;
+ assoc_g1_g2 = false;
+ assoc_g2_g1 = false;
+ }
+ if (generation < 3) {
+ allow_gen3 = false;
+ assoc_g2_g3 = false;
+ assoc_g3_g2 = false;
+ }
+ if (generation < 4) {
+ allow_gen4 = false;
+ assoc_g1_g4 = false;
+ assoc_g2_g4 = false;
+ assoc_g3_g4 = false;
+ assoc_g4_g1 = false;
+ assoc_g4_g2 = false;
+ assoc_g4_g3 = false;
+ }
+ if (generation < 5) {
+ allow_gen5 = false;
+ }
+ }
+
+ private int makeIntSelected(boolean... switches) {
+ if (switches.length > 32) {
+ // No can do
+ return 0;
+ }
+ int initial = 0;
+ int state = 1;
+ for (boolean b : switches) {
+ initial |= b ? state : 0;
+ state *= 2;
+ }
+ return initial;
+ }
+
+}
diff --git a/src/com/dabomstew/pkrandom/pokemon/IngameTrade.java b/src/com/dabomstew/pkrandom/pokemon/IngameTrade.java
new file mode 100755
index 000000000..c37f6cb92
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/pokemon/IngameTrade.java
@@ -0,0 +1,17 @@
+package com.dabomstew.pkrandom.pokemon;
+
+public class IngameTrade {
+
+ public int id;
+
+ public Pokemon requestedPokemon, givenPokemon;
+
+ public String nickname, otName;
+
+ public int otId;
+
+ public int[] ivs = new int[0];
+
+ public int item = 0;
+
+}
diff --git a/src/com/dabomstew/pkrandom/pokemon/ItemList.java b/src/com/dabomstew/pkrandom/pokemon/ItemList.java
new file mode 100755
index 000000000..04f65c2cb
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/pokemon/ItemList.java
@@ -0,0 +1,74 @@
+package com.dabomstew.pkrandom.pokemon;
+
+import com.dabomstew.pkrandom.RandomSource;
+
+public class ItemList {
+
+ private boolean[] items;
+ private boolean[] tms;
+
+ public ItemList(int highestIndex) {
+ items = new boolean[highestIndex + 1];
+ tms = new boolean[highestIndex + 1];
+ for (int i = 1; i <= highestIndex; i++) {
+ items[i] = true;
+ }
+ }
+
+ public boolean isTM(int index) {
+ if (index < 0 || index >= tms.length) {
+ return false;
+ }
+ return tms[index];
+ }
+
+ public boolean isAllowed(int index) {
+ if (index < 0 || index >= tms.length) {
+ return false;
+ }
+ return items[index];
+ }
+
+ public void banSingles(int... indexes) {
+ for (int index : indexes) {
+ items[index] = false;
+ }
+ }
+
+ public void banRange(int startIndex, int length) {
+ for (int i = 0; i < length; i++) {
+ items[i + startIndex] = false;
+ }
+ }
+
+ public void tmRange(int startIndex, int length) {
+ for (int i = 0; i < length; i++) {
+ tms[i + startIndex] = true;
+ }
+ }
+
+ public int randomItem() {
+ int chosen = 0;
+ while (!items[chosen]) {
+ chosen = RandomSource.nextInt(items.length);
+ }
+ return chosen;
+ }
+
+ public int randomNonTM() {
+ int chosen = 0;
+ while (!items[chosen] || tms[chosen]) {
+ chosen = RandomSource.nextInt(items.length);
+ }
+ return chosen;
+ }
+
+ public int randomTM() {
+ int chosen = 0;
+ while (!tms[chosen]) {
+ chosen = RandomSource.nextInt(items.length);
+ }
+ return chosen;
+ }
+
+}
diff --git a/src/com/dabomstew/pkrandom/pokemon/Move.java b/src/com/dabomstew/pkrandom/pokemon/Move.java
new file mode 100755
index 000000000..eb253b832
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/pokemon/Move.java
@@ -0,0 +1,47 @@
+package com.dabomstew.pkrandom.pokemon;
+
+/*----------------------------------------------------------------------------*/
+/*-- Move.java - represents a move usable by Pokemon. --*/
+/*-- --*/
+/*-- Part of "Universal Pokemon Randomizer" by Dabomstew --*/
+/*-- Pokemon and any associated names and the like are --*/
+/*-- trademark and (C) Nintendo 1996-2012. --*/
+/*-- --*/
+/*-- The custom code written here is licensed under the terms of the GPL: --*/
+/*-- --*/
+/*-- This program is free software: you can redistribute it and/or modify --*/
+/*-- it under the terms of the GNU General Public License as published by --*/
+/*-- the Free Software Foundation, either version 3 of the License, or --*/
+/*-- (at your option) any later version. --*/
+/*-- --*/
+/*-- This program is distributed in the hope that it will be useful, --*/
+/*-- but WITHOUT ANY WARRANTY; without even the implied warranty of --*/
+/*-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --*/
+/*-- GNU General Public License for more details. --*/
+/*-- --*/
+/*-- You should have received a copy of the GNU General Public License --*/
+/*-- along with this program. If not, see . --*/
+/*----------------------------------------------------------------------------*/
+
+public class Move {
+
+ public String name;
+ public int number;
+ public int internalId;
+ public int power;
+ public int pp;
+ public double hitratio;
+ public Type type;
+ public int effectIndex;
+
+ public String toString() {
+ return "#" + number + " " + name + " - Power: " + power + ", Base PP: "
+ + pp + ", Type: " + type + ", Hit%: " + (hitratio)
+ + ", Effect: " + effectIndex;
+ }
+
+ public void setAccuracy(double percent) {
+ hitratio = percent;
+ }
+
+}
diff --git a/src/com/dabomstew/pkrandom/pokemon/MoveLearnt.java b/src/com/dabomstew/pkrandom/pokemon/MoveLearnt.java
new file mode 100755
index 000000000..c9b87a562
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/pokemon/MoveLearnt.java
@@ -0,0 +1,35 @@
+package com.dabomstew.pkrandom.pokemon;
+
+/*----------------------------------------------------------------------------*/
+/*-- MoveLearnt.java - represents a move learnt by a Pokemon at a level. --*/
+/*-- --*/
+/*-- Part of "Universal Pokemon Randomizer" by Dabomstew --*/
+/*-- Pokemon and any associated names and the like are --*/
+/*-- trademark and (C) Nintendo 1996-2012. --*/
+/*-- --*/
+/*-- The custom code written here is licensed under the terms of the GPL: --*/
+/*-- --*/
+/*-- This program is free software: you can redistribute it and/or modify --*/
+/*-- it under the terms of the GNU General Public License as published by --*/
+/*-- the Free Software Foundation, either version 3 of the License, or --*/
+/*-- (at your option) any later version. --*/
+/*-- --*/
+/*-- This program is distributed in the hope that it will be useful, --*/
+/*-- but WITHOUT ANY WARRANTY; without even the implied warranty of --*/
+/*-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --*/
+/*-- GNU General Public License for more details. --*/
+/*-- --*/
+/*-- You should have received a copy of the GNU General Public License --*/
+/*-- along with this program. If not, see . --*/
+/*----------------------------------------------------------------------------*/
+
+public class MoveLearnt {
+
+ public int move;
+ public int level;
+
+ public String toString() {
+ return "move "+move+" at level "+level;
+ }
+
+}
diff --git a/src/com/dabomstew/pkrandom/pokemon/Pokemon.java b/src/com/dabomstew/pkrandom/pokemon/Pokemon.java
new file mode 100755
index 000000000..b3ef526d9
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/pokemon/Pokemon.java
@@ -0,0 +1,221 @@
+package com.dabomstew.pkrandom.pokemon;
+
+/*----------------------------------------------------------------------------*/
+/*-- Pokemon.java - represents an individual Pokemon, and contains --*/
+/*-- common Pokemon-related functions. --*/
+/*-- --*/
+/*-- Part of "Universal Pokemon Randomizer" by Dabomstew --*/
+/*-- Pokemon and any associated names and the like are --*/
+/*-- trademark and (C) Nintendo 1996-2012. --*/
+/*-- --*/
+/*-- The custom code written here is licensed under the terms of the GPL: --*/
+/*-- --*/
+/*-- This program is free software: you can redistribute it and/or modify --*/
+/*-- it under the terms of the GNU General Public License as published by --*/
+/*-- the Free Software Foundation, either version 3 of the License, or --*/
+/*-- (at your option) any later version. --*/
+/*-- --*/
+/*-- This program is distributed in the hope that it will be useful, --*/
+/*-- but WITHOUT ANY WARRANTY; without even the implied warranty of --*/
+/*-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --*/
+/*-- GNU General Public License for more details. --*/
+/*-- --*/
+/*-- You should have received a copy of the GNU General Public License --*/
+/*-- along with this program. If not, see . --*/
+/*----------------------------------------------------------------------------*/
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import com.dabomstew.pkrandom.RandomSource;
+
+public class Pokemon implements Comparable {
+
+ public String name;
+ public int number;
+
+ public Type primaryType, secondaryType;
+
+ public int hp, attack, defense, spatk, spdef, speed, special;
+
+ public int ability1, ability2, ability3;
+
+ public int catchRate;
+
+ public int guaranteedHeldItem, commonHeldItem, rareHeldItem,
+ darkGrassHeldItem;
+
+ public ExpCurve growthCurve;
+
+ public Pokemon() {
+ }
+
+ public void shuffleStats() {
+ List stats = Arrays.asList(hp, attack, defense, spatk, spdef,
+ speed);
+ Collections.shuffle(stats, RandomSource.instance());
+
+ // Copy in new stats
+ hp = stats.get(0);
+ attack = stats.get(1);
+ defense = stats.get(2);
+ spatk = stats.get(3);
+ spdef = stats.get(4);
+ speed = stats.get(5);
+
+ // make special the average of spatk and spdef
+ special = (int) Math.ceil((spatk + spdef) / 2.0f);
+
+ // Copy special from a random one of spatk or spdef
+// if (RandomSource.random() < 0.5) {
+// special = spatk;
+// } else {
+// special = spdef;
+// }
+ }
+
+ public void randomizeStatsWithinBST() {
+ if (number == 292) {
+ // Shedinja is horribly broken unless we restrict him to 1HP.
+ int bst = bst() - 51;
+
+ // Make weightings
+ double atkW = RandomSource.random(), defW = RandomSource.random();
+ double spaW = RandomSource.random(), spdW = RandomSource.random(), speW = RandomSource
+ .random();
+
+ double totW = atkW + defW + spaW + spdW + speW;
+
+ hp = 1;
+ attack = (int) Math.max(1, Math.round(atkW / totW * bst)) + 10;
+ defense = (int) Math.max(1, Math.round(defW / totW * bst)) + 10;
+ spatk = (int) Math.max(1, Math.round(spaW / totW * bst)) + 10;
+ spdef = (int) Math.max(1, Math.round(spdW / totW * bst)) + 10;
+ speed = (int) Math.max(1, Math.round(speW / totW * bst)) + 10;
+
+ // Fix up special too
+ special = (int) Math.ceil((spatk + spdef) / 2.0f);
+
+ } else {
+ // Minimum 20 HP, 10 everything else
+ int bst = bst() - 70;
+
+ // Make weightings
+ double hpW = RandomSource.random(), atkW = RandomSource.random(), defW = RandomSource
+ .random();
+ double spaW = RandomSource.random(), spdW = RandomSource.random(), speW = RandomSource
+ .random();
+
+ double totW = hpW + atkW + defW + spaW + spdW + speW;
+
+ hp = (int) Math.max(1, Math.round(hpW / totW * bst)) + 20;
+ attack = (int) Math.max(1, Math.round(atkW / totW * bst)) + 10;
+ defense = (int) Math.max(1, Math.round(defW / totW * bst)) + 10;
+ spatk = (int) Math.max(1, Math.round(spaW / totW * bst)) + 10;
+ spdef = (int) Math.max(1, Math.round(spdW / totW * bst)) + 10;
+ speed = (int) Math.max(1, Math.round(speW / totW * bst)) + 10;
+
+ // Fix up special too
+ special = (int) Math.ceil((spatk + spdef) / 2.0f);
+ }
+
+ // Check for something we can't store
+ if (hp > 255 || attack > 255 || defense > 255 || spatk > 255
+ || spdef > 255 || speed > 255) {
+ // re roll
+ randomizeStatsWithinBST();
+ }
+
+ }
+
+ public void copyRandomizedStatsUpEvolution(Pokemon evolvesFrom) {
+ double ourBST = bst();
+ double theirBST = evolvesFrom.bst();
+
+ double bstRatio = ourBST / theirBST;
+
+ hp = (int) Math.min(255,
+ Math.max(1, Math.round(evolvesFrom.hp * bstRatio)));
+ attack = (int) Math.min(255,
+ Math.max(1, Math.round(evolvesFrom.attack * bstRatio)));
+ defense = (int) Math.min(255,
+ Math.max(1, Math.round(evolvesFrom.defense * bstRatio)));
+ speed = (int) Math.min(255,
+ Math.max(1, Math.round(evolvesFrom.speed * bstRatio)));
+ spatk = (int) Math.min(255,
+ Math.max(1, Math.round(evolvesFrom.spatk * bstRatio)));
+ spdef = (int) Math.min(255,
+ Math.max(1, Math.round(evolvesFrom.spdef * bstRatio)));
+
+ special = (int) Math.ceil((spatk + spdef) / 2.0f);
+ }
+
+ public int bst() {
+ return hp + attack + defense + spatk + spdef + speed;
+ }
+
+ public int bstForPowerLevels() {
+ // Take into account Shedinja's purposefully nerfed HP
+ if (number == 292) {
+ return (attack + defense + spatk + spdef + speed) * 6 / 5;
+ } else {
+ return hp + attack + defense + spatk + spdef + speed;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "Pokemon [name=" + name + ", number=" + number
+ + ", primaryType=" + primaryType + ", secondaryType="
+ + secondaryType + ", hp=" + hp + ", attack=" + attack
+ + ", defense=" + defense + ", spatk=" + spatk + ", spdef="
+ + spdef + ", speed=" + speed + "]";
+ }
+
+ public String toStringRBY() {
+ return "Pokemon [name=" + name + ", number=" + number
+ + ", primaryType=" + primaryType + ", secondaryType="
+ + secondaryType + ", hp=" + hp + ", attack=" + attack
+ + ", defense=" + defense + ", special=" + special + ", speed="
+ + speed + "]";
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + number;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ Pokemon other = (Pokemon) obj;
+ if (number != other.number)
+ return false;
+ return true;
+ }
+
+ @Override
+ public int compareTo(Pokemon o) {
+ return number - o.number;
+ }
+
+ private static final List legendaries = Arrays.asList(144, 145,
+ 146, 150, 151, 243, 244, 245, 249, 250, 251, 377, 378, 379, 380,
+ 381, 382, 383, 384, 385, 386, 479, 480, 481, 482, 483, 484, 485,
+ 486, 487, 488, 489, 490, 491, 492, 493, 494, 638, 639, 640, 641,
+ 642, 643, 644, 645, 646, 647, 648, 649);
+
+ public boolean isLegendary() {
+ return legendaries.contains(this.number);
+ }
+
+}
diff --git a/src/com/dabomstew/pkrandom/pokemon/Trainer.java b/src/com/dabomstew/pkrandom/pokemon/Trainer.java
new file mode 100755
index 000000000..31d5b0228
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/pokemon/Trainer.java
@@ -0,0 +1,92 @@
+package com.dabomstew.pkrandom.pokemon;
+
+/*----------------------------------------------------------------------------*/
+/*-- Trainer.java - represents a Trainer's pokemon set/other details. --*/
+/*-- --*/
+/*-- Part of "Universal Pokemon Randomizer" by Dabomstew --*/
+/*-- Pokemon and any associated names and the like are --*/
+/*-- trademark and (C) Nintendo 1996-2012. --*/
+/*-- --*/
+/*-- The custom code written here is licensed under the terms of the GPL: --*/
+/*-- --*/
+/*-- This program is free software: you can redistribute it and/or modify --*/
+/*-- it under the terms of the GNU General Public License as published by --*/
+/*-- the Free Software Foundation, either version 3 of the License, or --*/
+/*-- (at your option) any later version. --*/
+/*-- --*/
+/*-- This program is distributed in the hope that it will be useful, --*/
+/*-- but WITHOUT ANY WARRANTY; without even the implied warranty of --*/
+/*-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --*/
+/*-- GNU General Public License for more details. --*/
+/*-- --*/
+/*-- You should have received a copy of the GNU General Public License --*/
+/*-- along with this program. If not, see . --*/
+/*----------------------------------------------------------------------------*/
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class Trainer implements Comparable {
+ public int offset;
+ public List pokemon = new ArrayList();
+ public String tag;
+ public boolean importantTrainer;
+ public int poketype;
+ public String name;
+ public int trainerclass;
+ public String fullDisplayName;
+
+ public String toString() {
+ StringBuilder sb = new StringBuilder("[");
+ if (fullDisplayName != null) {
+ sb.append(fullDisplayName + " ");
+ } else if (name != null) {
+ sb.append(name + " ");
+ }
+ if (trainerclass != 0) {
+ sb.append("(" + trainerclass + ") - ");
+ }
+ sb.append(String.format("%x", offset));
+ sb.append(" => ");
+ boolean first = true;
+ for (TrainerPokemon p : pokemon) {
+ if (!first) {
+ sb.append(',');
+ }
+ sb.append(p.pokemon.name + " Lv" + p.level);
+ first = false;
+ }
+ sb.append(']');
+ if (tag != null) {
+ sb.append(" (" + tag + ")");
+ }
+ return sb.toString();
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + offset;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ Trainer other = (Trainer) obj;
+ if (offset != other.offset)
+ return false;
+ return true;
+ }
+
+ @Override
+ public int compareTo(Trainer o) {
+ return offset - o.offset;
+ }
+}
diff --git a/src/com/dabomstew/pkrandom/pokemon/TrainerPokemon.java b/src/com/dabomstew/pkrandom/pokemon/TrainerPokemon.java
new file mode 100755
index 000000000..5fca5ac37
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/pokemon/TrainerPokemon.java
@@ -0,0 +1,44 @@
+package com.dabomstew.pkrandom.pokemon;
+
+/*----------------------------------------------------------------------------*/
+/*-- TrainerPokemon.java - represents a Pokemon owned by a trainer. --*/
+/*-- --*/
+/*-- Part of "Universal Pokemon Randomizer" by Dabomstew --*/
+/*-- Pokemon and any associated names and the like are --*/
+/*-- trademark and (C) Nintendo 1996-2012. --*/
+/*-- --*/
+/*-- The custom code written here is licensed under the terms of the GPL: --*/
+/*-- --*/
+/*-- This program is free software: you can redistribute it and/or modify --*/
+/*-- it under the terms of the GNU General Public License as published by --*/
+/*-- the Free Software Foundation, either version 3 of the License, or --*/
+/*-- (at your option) any later version. --*/
+/*-- --*/
+/*-- This program is distributed in the hope that it will be useful, --*/
+/*-- but WITHOUT ANY WARRANTY; without even the implied warranty of --*/
+/*-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --*/
+/*-- GNU General Public License for more details. --*/
+/*-- --*/
+/*-- You should have received a copy of the GNU General Public License --*/
+/*-- along with this program. If not, see . --*/
+/*----------------------------------------------------------------------------*/
+
+public class TrainerPokemon {
+
+ public Pokemon pokemon;
+ public int level;
+
+ public int move1;
+ public int move2;
+ public int move3;
+ public int move4;
+
+ public int AILevel;
+ public int heldItem;
+ public int ability;
+
+ public String toString() {
+ return pokemon.name + " Lv" + level;
+ }
+
+}
diff --git a/src/com/dabomstew/pkrandom/pokemon/Type.java b/src/com/dabomstew/pkrandom/pokemon/Type.java
new file mode 100755
index 000000000..bf6f2a752
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/pokemon/Type.java
@@ -0,0 +1,60 @@
+package com.dabomstew.pkrandom.pokemon;
+
+/*----------------------------------------------------------------------------*/
+/*-- Type.java - represents a Pokemon or move type. --*/
+/*-- --*/
+/*-- Part of "Universal Pokemon Randomizer" by Dabomstew --*/
+/*-- Pokemon and any associated names and the like are --*/
+/*-- trademark and (C) Nintendo 1996-2012. --*/
+/*-- --*/
+/*-- The custom code written here is licensed under the terms of the GPL: --*/
+/*-- --*/
+/*-- This program is free software: you can redistribute it and/or modify --*/
+/*-- it under the terms of the GNU General Public License as published by --*/
+/*-- the Free Software Foundation, either version 3 of the License, or --*/
+/*-- (at your option) any later version. --*/
+/*-- --*/
+/*-- This program is distributed in the hope that it will be useful, --*/
+/*-- but WITHOUT ANY WARRANTY; without even the implied warranty of --*/
+/*-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --*/
+/*-- GNU General Public License for more details. --*/
+/*-- --*/
+/*-- You should have received a copy of the GNU General Public License --*/
+/*-- along with this program. If not, see . --*/
+/*----------------------------------------------------------------------------*/
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import com.dabomstew.pkrandom.RandomSource;
+import com.dabomstew.pkrandom.RomFunctions;
+
+public enum Type {
+
+ NORMAL, FIGHTING, FLYING, GRASS, WATER, FIRE, ROCK, GROUND, PSYCHIC, BUG, DRAGON, ELECTRIC, GHOST, POISON, ICE, STEEL, DARK,
+ GAS(true), FAIRY(true), WOOD(true), ABNORMAL(true), WIND(true), SOUND(true), LIGHT(true);
+
+ public boolean isHackOnly;
+
+ private Type() {
+ this.isHackOnly = false;
+ }
+
+ private Type(boolean isHackOnly) {
+ this.isHackOnly = isHackOnly;
+ }
+
+ private static final List VALUES = Collections
+ .unmodifiableList(Arrays.asList(values()));
+ private static final int SIZE = VALUES.size();
+
+ public static Type randomType() {
+ return VALUES.get(RandomSource.nextInt(SIZE));
+ }
+
+ public String camelCase() {
+ return RomFunctions.camelCase(this.toString());
+ }
+
+}
diff --git a/src/com/dabomstew/pkrandom/romhandlers/AbstractDSRomHandler.java b/src/com/dabomstew/pkrandom/romhandlers/AbstractDSRomHandler.java
new file mode 100755
index 000000000..c36dae75f
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/romhandlers/AbstractDSRomHandler.java
@@ -0,0 +1,406 @@
+package com.dabomstew.pkrandom.romhandlers;
+
+/*----------------------------------------------------------------------------*/
+/*-- AbstractDSRomHandler.java - a base class for DS rom handlers --*/
+/*-- which standardises common DS functions. --*/
+/*-- --*/
+/*-- Part of "Universal Pokemon Randomizer" by Dabomstew --*/
+/*-- Pokemon and any associated names and the like are --*/
+/*-- trademark and (C) Nintendo 1996-2012. --*/
+/*-- --*/
+/*-- The custom code written here is licensed under the terms of the GPL: --*/
+/*-- --*/
+/*-- This program is free software: you can redistribute it and/or modify --*/
+/*-- it under the terms of the GNU General Public License as published by --*/
+/*-- the Free Software Foundation, either version 3 of the License, or --*/
+/*-- (at your option) any later version. --*/
+/*-- --*/
+/*-- This program is distributed in the hope that it will be useful, --*/
+/*-- but WITHOUT ANY WARRANTY; without even the implied warranty of --*/
+/*-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --*/
+/*-- GNU General Public License for more details. --*/
+/*-- --*/
+/*-- You should have received a copy of the GNU General Public License --*/
+/*-- along with this program. If not, see . --*/
+/*----------------------------------------------------------------------------*/
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Map;
+import java.util.TreeMap;
+
+import com.dabomstew.pkrandom.newnds.NDSRom;
+import com.dabomstew.pkrandom.pokemon.Type;
+
+public abstract class AbstractDSRomHandler extends AbstractRomHandler {
+
+ protected String dataFolder;
+ private NDSRom baseRom;
+ private String loadedFN;
+
+ @Override
+ public boolean detectRom(String filename) {
+ try {
+ FileInputStream fis = new FileInputStream(filename);
+ fis.skip(0x0C);
+ byte[] sig = new byte[4];
+ fis.read(sig);
+ fis.close();
+ String ndsCode = new String(sig, "US-ASCII");
+ return detectNDSRom(ndsCode);
+ } catch (Exception e) {
+ return false;
+ }
+ }
+
+ protected abstract boolean detectNDSRom(String ndsCode);
+
+ @Override
+ public boolean loadRom(String filename) {
+ if (!detectRom(filename)) {
+ return false;
+ }
+ // Load inner rom
+ try {
+ baseRom = new NDSRom(filename);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ loadedFN = filename;
+ loadedROM();
+ return true;
+ }
+
+ @Override
+ public String loadedFilename() {
+ return loadedFN;
+ }
+
+ protected byte[] get3byte(int amount) {
+ byte[] ret = new byte[3];
+ ret[0] = (byte) (amount & 0xFF);
+ ret[1] = (byte) ((amount >> 8) & 0xFF);
+ ret[2] = (byte) ((amount >> 16) & 0xFF);
+ return ret;
+ }
+
+ protected abstract void loadedROM();
+
+ protected abstract void savingROM();
+
+ @Override
+ public boolean saveRom(String filename) {
+ savingROM();
+ try {
+ baseRom.saveTo(filename);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ return true;
+ }
+
+ public void closeInnerRom() throws IOException {
+ baseRom.closeROM();
+ }
+
+ @Override
+ public boolean canChangeStaticPokemon() {
+ return false;
+ }
+
+ public NARCContents readNARC(String subpath) throws IOException {
+ Map frames = readNitroFrames(subpath);
+ if (!frames.containsKey("FATB") || !frames.containsKey("FNTB")
+ || !frames.containsKey("FIMG")) {
+ System.err.println("Not a valid narc file");
+ return null;
+ }
+ // File contents
+ NARCContents narc = new NARCContents();
+ byte[] fatbframe = frames.get("FATB");
+ byte[] fimgframe = frames.get("FIMG");
+ int fileCount = readLong(fatbframe, 0);
+ for (int i = 0; i < fileCount; i++) {
+ int startOffset = readLong(fatbframe, 4 + i * 8);
+ int endOffset = readLong(fatbframe, 8 + i * 8);
+ int length = (endOffset - startOffset);
+ byte[] thisFile = new byte[length];
+ try {
+ System.arraycopy(fimgframe, startOffset, thisFile, 0, length);
+ } catch (ArrayIndexOutOfBoundsException ex) {
+ System.out.printf(
+ "AIOBEX: start %d length %d size of frame %d\n",
+ startOffset, length, fimgframe.length);
+ }
+ narc.files.add(thisFile);
+ }
+ // Filenames?
+ byte[] fntbframe = frames.get("FNTB");
+ int unk1 = readLong(fntbframe, 0);
+ if (unk1 == 8) {
+ // Filenames exist
+ narc.hasFilenames = true;
+ int offset = 8;
+ for (int i = 0; i < fileCount; i++) {
+ int fnLength = (fntbframe[offset] & 0xFF);
+ offset++;
+ byte[] filenameBA = new byte[fnLength];
+ System.arraycopy(fntbframe, offset, filenameBA, 0, fnLength);
+ String filename = new String(filenameBA, "US-ASCII");
+ narc.filenames.add(filename);
+ }
+ } else {
+ narc.hasFilenames = false;
+ for (int i = 0; i < fileCount; i++) {
+ narc.filenames.add(null);
+ }
+ }
+ return narc;
+ }
+
+ public void writeNARC(String subpath, NARCContents narc) throws IOException {
+ // Get bytes required for FIMG frame
+ int bytesRequired = 0;
+ for (byte[] file : narc.files) {
+ bytesRequired += Math.ceil(file.length / 4.0) * 4;
+ }
+ // FIMG frame & FATB frame build
+
+ // 4 for numentries, 8*size for entries, 8 for nitro header
+ byte[] fatbFrame = new byte[4 + narc.files.size() * 8 + 8];
+ // bytesRequired + 8 for nitro header
+ byte[] fimgFrame = new byte[bytesRequired + 8];
+
+ // Nitro headers
+ fatbFrame[0] = 'B';
+ fatbFrame[1] = 'T';
+ fatbFrame[2] = 'A';
+ fatbFrame[3] = 'F';
+ writeLong(fatbFrame, 4, fatbFrame.length);
+
+ fimgFrame[0] = 'G';
+ fimgFrame[1] = 'M';
+ fimgFrame[2] = 'I';
+ fimgFrame[3] = 'F';
+ writeLong(fimgFrame, 4, fimgFrame.length);
+ int offset = 0;
+
+ writeLong(fatbFrame, 8, narc.files.size());
+ for (int i = 0; i < narc.files.size(); i++) {
+ byte[] file = narc.files.get(i);
+ int bytesRequiredForFile = (int) (Math.ceil(file.length / 4.0) * 4);
+ System.arraycopy(file, 0, fimgFrame, offset + 8, file.length);
+ for (int filler = file.length; filler < bytesRequiredForFile; filler++) {
+ fimgFrame[offset + 8 + filler] = (byte) 0xFF;
+ }
+ writeLong(fatbFrame, 12 + i * 8, offset);
+ writeLong(fatbFrame, 16 + i * 8, offset + file.length);
+ offset += bytesRequiredForFile;
+ }
+
+ // FNTB Frame
+ int bytesForFNTBFrame = 16;
+ if (narc.hasFilenames) {
+ for (String filename : narc.filenames) {
+ bytesForFNTBFrame += filename.getBytes("US-ASCII").length + 1;
+ }
+ }
+ byte[] fntbFrame = new byte[bytesForFNTBFrame];
+
+ fntbFrame[0] = 'B';
+ fntbFrame[1] = 'T';
+ fntbFrame[2] = 'N';
+ fntbFrame[3] = 'F';
+ writeLong(fntbFrame, 4, fntbFrame.length);
+
+ if (narc.hasFilenames) {
+ writeLong(fntbFrame, 8, 8);
+ writeLong(fntbFrame, 12, 0x10000);
+ int fntbOffset = 16;
+ for (String filename : narc.filenames) {
+ byte[] fntbfilename = filename.getBytes("US-ASCII");
+ fntbFrame[fntbOffset] = (byte) fntbfilename.length;
+ System.arraycopy(fntbfilename, 0, fntbFrame, fntbOffset + 1,
+ fntbfilename.length);
+ fntbOffset += 1 + fntbfilename.length;
+ }
+ } else {
+ writeLong(fntbFrame, 8, 4);
+ writeLong(fntbFrame, 12, 0x10000);
+ }
+
+ // Now for the actual Nitro file
+ int nitrolength = 16 + fatbFrame.length + fntbFrame.length
+ + fimgFrame.length;
+ byte[] nitroFile = new byte[nitrolength];
+ nitroFile[0] = 'N';
+ nitroFile[1] = 'A';
+ nitroFile[2] = 'R';
+ nitroFile[3] = 'C';
+ writeWord(nitroFile, 4, 0xFFFE);
+ writeWord(nitroFile, 6, 0x0100);
+ writeLong(nitroFile, 8, nitrolength);
+ writeWord(nitroFile, 12, 0x10);
+ writeWord(nitroFile, 14, 3);
+ System.arraycopy(fatbFrame, 0, nitroFile, 16, fatbFrame.length);
+ System.arraycopy(fntbFrame, 0, nitroFile, 16 + fatbFrame.length,
+ fntbFrame.length);
+ System.arraycopy(fimgFrame, 0, nitroFile, 16 + fatbFrame.length
+ + fntbFrame.length, fimgFrame.length);
+ this.writeFile(subpath, nitroFile);
+ }
+
+ private Map readNitroFrames(String filename)
+ throws IOException {
+ byte[] wholeFile = this.readFile(filename);
+
+ // Read the number of frames
+ int frameCount = readWord(wholeFile, 0x0E);
+
+ // each frame
+ int offset = 0x10;
+ Map frames = new TreeMap();
+ for (int i = 0; i < frameCount; i++) {
+ byte[] magic = new byte[] { wholeFile[offset + 3],
+ wholeFile[offset + 2], wholeFile[offset + 1],
+ wholeFile[offset] };
+ String magicS = new String(magic, "US-ASCII");
+
+ int frame_size = readLong(wholeFile, offset + 4);
+ // Patch for BB/VW and other DS hacks which don't update
+ // the size of their expanded NARCs correctly
+ if (i == frameCount - 1 && offset + frame_size < wholeFile.length) {
+ frame_size = wholeFile.length - offset;
+ }
+ byte[] frame = new byte[frame_size - 8];
+ System.arraycopy(wholeFile, offset + 8, frame, 0, frame_size - 8);
+ frames.put(magicS, frame);
+ offset += frame_size;
+ }
+ return frames;
+ }
+
+ protected int readWord(byte[] data, int offset) {
+ return (data[offset] & 0xFF) | ((data[offset + 1] & 0xFF) << 8);
+ }
+
+ protected int readLong(byte[] data, int offset) {
+ return (data[offset] & 0xFF) | ((data[offset + 1] & 0xFF) << 8)
+ | ((data[offset + 2] & 0xFF) << 16)
+ | ((data[offset + 3] & 0xFF) << 24);
+ }
+
+ protected int readRelativePointer(byte[] data, int offset) {
+ return readLong(data, offset) + offset + 4;
+ }
+
+ protected void writeWord(byte[] data, int offset, int value) {
+ data[offset] = (byte) (value & 0xFF);
+ data[offset + 1] = (byte) ((value >> 8) & 0xFF);
+ }
+
+ protected void writeLong(byte[] data, int offset, int value) {
+ data[offset] = (byte) (value & 0xFF);
+ data[offset + 1] = (byte) ((value >> 8) & 0xFF);
+ data[offset + 2] = (byte) ((value >> 16) & 0xFF);
+ data[offset + 3] = (byte) ((value >> 24) & 0xFF);
+ }
+
+ protected void writeRelativePointer(byte[] data, int offset, int pointer) {
+ int relPointer = pointer - (offset + 4);
+ writeLong(data, offset, relPointer);
+ }
+
+ protected byte[] readFile(String location) throws IOException {
+ return baseRom.getFile(location);
+ }
+
+ protected void writeFile(String location, byte[] data) throws IOException {
+ writeFile(location, data, 0, data.length);
+ }
+
+ protected void writeFile(String location, byte[] data, int offset,
+ int length) throws IOException {
+ if (offset != 0 || length != data.length) {
+ byte[] newData = new byte[length];
+ System.arraycopy(data, offset, newData, 0, length);
+ data = newData;
+ }
+ baseRom.writeFile(location, data);
+ }
+
+ protected byte[] readARM9() throws IOException {
+ return baseRom.getARM9();
+ }
+
+ protected void writeARM9(byte[] data) throws IOException {
+ baseRom.writeARM9(data);
+ }
+
+ protected byte[] readOverlay(int number) throws IOException {
+ return baseRom.getOverlay(number);
+ }
+
+ protected void writeOverlay(int number, byte[] data) throws IOException {
+ baseRom.writeOverlay(number, data);
+ }
+
+ protected void readByteIntoFlags(byte[] data, boolean[] flags,
+ int offsetIntoFlags, int offsetIntoData) {
+ int thisByte = data[offsetIntoData] & 0xFF;
+ for (int i = 0; i < 8 && (i + offsetIntoFlags) < flags.length; i++) {
+ flags[offsetIntoFlags + i] = ((thisByte >> i) & 0x01) == 0x01;
+ }
+ }
+
+ protected byte getByteFromFlags(boolean[] flags, int offsetIntoFlags) {
+ int thisByte = 0;
+ for (int i = 0; i < 8 && (i + offsetIntoFlags) < flags.length; i++) {
+ thisByte |= (flags[offsetIntoFlags + i] ? 1 : 0) << i;
+ }
+ return (byte) thisByte;
+ }
+
+ protected int typeTMPaletteNumber(Type t) {
+ if (t == null) {
+ return 411; // CURSE
+ }
+ switch (t) {
+ case FIGHTING:
+ return 398;
+ case DRAGON:
+ return 399;
+ case WATER:
+ return 400;
+ case PSYCHIC:
+ return 401;
+ case NORMAL:
+ return 402;
+ case POISON:
+ return 403;
+ case ICE:
+ return 404;
+ case GRASS:
+ return 405;
+ case FIRE:
+ return 406;
+ case DARK:
+ return 407;
+ case STEEL:
+ return 408;
+ case ELECTRIC:
+ return 409;
+ case GROUND:
+ return 410;
+ case GHOST:
+ default:
+ return 411; // for CURSE
+ case ROCK:
+ return 412;
+ case FLYING:
+ return 413;
+ case BUG:
+ return 610;
+ }
+ }
+
+}
diff --git a/src/com/dabomstew/pkrandom/romhandlers/AbstractGBRomHandler.java b/src/com/dabomstew/pkrandom/romhandlers/AbstractGBRomHandler.java
new file mode 100755
index 000000000..63e507bb0
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/romhandlers/AbstractGBRomHandler.java
@@ -0,0 +1,135 @@
+package com.dabomstew.pkrandom.romhandlers;
+
+/*----------------------------------------------------------------------------*/
+/*-- AbstractGBRomHandler.java - a base class for GB/GBA rom handlers --*/
+/*-- which standardises common GB(A) functions.--*/
+/*-- --*/
+/*-- Part of "Universal Pokemon Randomizer" by Dabomstew --*/
+/*-- Pokemon and any associated names and the like are --*/
+/*-- trademark and (C) Nintendo 1996-2012. --*/
+/*-- --*/
+/*-- The custom code written here is licensed under the terms of the GPL: --*/
+/*-- --*/
+/*-- This program is free software: you can redistribute it and/or modify --*/
+/*-- it under the terms of the GNU General Public License as published by --*/
+/*-- the Free Software Foundation, either version 3 of the License, or --*/
+/*-- (at your option) any later version. --*/
+/*-- --*/
+/*-- This program is distributed in the hope that it will be useful, --*/
+/*-- but WITHOUT ANY WARRANTY; without even the implied warranty of --*/
+/*-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --*/
+/*-- GNU General Public License for more details. --*/
+/*-- --*/
+/*-- You should have received a copy of the GNU General Public License --*/
+/*-- along with this program. If not, see . --*/
+/*----------------------------------------------------------------------------*/
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+public abstract class AbstractGBRomHandler extends AbstractRomHandler {
+
+ protected byte[] rom;
+ private String loadedFN;
+
+ public boolean detectRom(String filename) {
+ if (new File(filename).length() > 32 * 1024 * 1024) {
+ return false;
+ }
+ byte[] loaded = loadFile(filename);
+ if (loaded.length == 0) {
+ // nope
+ return false;
+ }
+ return detectRom(loaded);
+ }
+
+ @Override
+ public boolean loadRom(String filename) {
+ byte[] loaded = loadFile(filename);
+ if (!detectRom(loaded)) {
+ return false;
+ }
+ this.rom = loaded;
+ loadedFN = filename;
+ loadedRom();
+ return true;
+ }
+
+ @Override
+ public String loadedFilename() {
+ return loadedFN;
+ }
+
+ @Override
+ public boolean saveRom(String filename) {
+ savingRom();
+ try {
+ FileOutputStream fos = new FileOutputStream(filename);
+ fos.write(rom);
+ fos.close();
+ return true;
+ } catch (IOException ex) {
+ return false;
+ }
+ }
+
+ @Override
+ public boolean canChangeStaticPokemon() {
+ return true;
+ }
+
+ public abstract boolean detectRom(byte[] rom);
+
+ public abstract void loadedRom();
+
+ public abstract void savingRom();
+
+ private byte[] loadFile(String filename) {
+ try {
+ FileInputStream fis = new FileInputStream(filename);
+ byte[] file = new byte[fis.available()];
+ fis.read(file);
+ fis.close();
+ return file;
+ } catch (IOException ex) {
+ return new byte[0];
+ }
+ }
+
+ protected void readByteIntoFlags(boolean[] flags, int offsetIntoFlags,
+ int offsetIntoROM) {
+ int thisByte = rom[offsetIntoROM] & 0xFF;
+ for (int i = 0; i < 8 && (i + offsetIntoFlags) < flags.length; i++) {
+ flags[offsetIntoFlags + i] = ((thisByte >> i) & 0x01) == 0x01;
+ }
+ }
+
+ protected byte getByteFromFlags(boolean[] flags, int offsetIntoFlags) {
+ int thisByte = 0;
+ for (int i = 0; i < 8 && (i + offsetIntoFlags) < flags.length; i++) {
+ thisByte |= (flags[offsetIntoFlags + i] ? 1 : 0) << i;
+ }
+ return (byte) thisByte;
+ }
+
+ protected int readWord(int offset) {
+ return readWord(rom, offset);
+ }
+
+ protected int readWord(byte[] data, int offset) {
+ return (data[offset] & 0xFF) + ((data[offset + 1] & 0xFF) << 8);
+ }
+
+ protected void writeWord(int offset, int value) {
+ writeWord(rom, offset, value);
+ }
+
+ protected void writeWord(byte[] data, int offset, int value) {
+ data[offset] = (byte) (value % 0x100);
+ data[offset + 1] = (byte) ((value / 0x100) % 0x100);
+ }
+
+}
diff --git a/src/com/dabomstew/pkrandom/romhandlers/AbstractRomHandler.java b/src/com/dabomstew/pkrandom/romhandlers/AbstractRomHandler.java
new file mode 100755
index 000000000..7e1d4d7bd
--- /dev/null
+++ b/src/com/dabomstew/pkrandom/romhandlers/AbstractRomHandler.java
@@ -0,0 +1,2841 @@
+package com.dabomstew.pkrandom.romhandlers;
+
+/*----------------------------------------------------------------------------*/
+/*-- AbstractRomHandler.java - a base class for all rom handlers which --*/
+/*-- implements the majority of the actual --*/
+/*-- randomizer logic by building on the base --*/
+/*-- getters & setters provided by each concrete --*/
+/*-- handler. --*/
+/*-- --*/
+/*-- Part of "Universal Pokemon Randomizer" by Dabomstew --*/
+/*-- Pokemon and any associated names and the like are --*/
+/*-- trademark and (C) Nintendo 1996-2012. --*/
+/*-- --*/
+/*-- The custom code written here is licensed under the terms of the GPL: --*/
+/*-- --*/
+/*-- This program is free software: you can redistribute it and/or modify --*/
+/*-- it under the terms of the GNU General Public License as published by --*/
+/*-- the Free Software Foundation, either version 3 of the License, or --*/
+/*-- (at your option) any later version. --*/
+/*-- --*/
+/*-- This program is distributed in the hope that it will be useful, --*/
+/*-- but WITHOUT ANY WARRANTY; without even the implied warranty of --*/
+/*-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --*/
+/*-- GNU General Public License for more details. --*/
+/*-- --*/
+/*-- You should have received a copy of the GNU General Public License --*/
+/*-- along with this program. If not, see . --*/
+/*----------------------------------------------------------------------------*/
+
+import java.io.ByteArrayInputStream;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Scanner;
+import java.util.Set;
+import java.util.Stack;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+import javax.swing.JOptionPane;
+
+import com.dabomstew.pkrandom.FileFunctions;
+import com.dabomstew.pkrandom.RandomSource;
+import com.dabomstew.pkrandom.RomFunctions;
+import com.dabomstew.pkrandom.gui.RandomizerGUI;
+import com.dabomstew.pkrandom.pokemon.Encounter;
+import com.dabomstew.pkrandom.pokemon.EncounterSet;
+import com.dabomstew.pkrandom.pokemon.Evolution;
+import com.dabomstew.pkrandom.pokemon.ExpCurve;
+import com.dabomstew.pkrandom.pokemon.GenRestrictions;
+import com.dabomstew.pkrandom.pokemon.IngameTrade;
+import com.dabomstew.pkrandom.pokemon.ItemList;
+import com.dabomstew.pkrandom.pokemon.Move;
+import com.dabomstew.pkrandom.pokemon.MoveLearnt;
+import com.dabomstew.pkrandom.pokemon.Pokemon;
+import com.dabomstew.pkrandom.pokemon.Trainer;
+import com.dabomstew.pkrandom.pokemon.TrainerPokemon;
+import com.dabomstew.pkrandom.pokemon.Type;
+
+public abstract class AbstractRomHandler implements RomHandler {
+
+ private static final String tnamesFile = "trainernames.txt";
+ private static final String tclassesFile = "trainerclasses.txt";
+ private static final String nnamesFile = "nicknames.txt";
+
+ private boolean restrictionsSet;
+ protected List mainPokemonList;
+ protected List noLegendaryList, onlyLegendaryList;
+
+ /* Constructor */
+
+ public AbstractRomHandler() {
+ }
+
+ /* Public Methods, implemented here for all gens */
+
+ protected void checkPokemonRestrictions() {
+ if (!restrictionsSet) {
+ setPokemonPool(null);
+ }
+ }
+
+ public void setPokemonPool(GenRestrictions restrictions) {
+ restrictionsSet = true;
+ mainPokemonList = this.allPokemonWithoutNull();
+ if (restrictions != null) {
+ mainPokemonList = new ArrayList();
+ List allPokemon = this.getPokemon();
+ List evos = this.getEvolutions();
+
+ if (restrictions.allow_gen1) {
+ addPokesFromRange(mainPokemonList, allPokemon, 1, 151);
+ if (restrictions.assoc_g1_g2 && allPokemon.size() > 251) {
+ addEvosFromRange(mainPokemonList, allPokemon, evos, 1, 151,
+ 152, 251);
+ }
+ if (restrictions.assoc_g1_g4 && allPokemon.size() > 493) {
+ addEvosFromRange(mainPokemonList, allPokemon, evos, 1, 151,
+ 387, 493);
+ }
+ }
+
+ if (restrictions.allow_gen2 && allPokemon.size() > 251) {
+ addPokesFromRange(mainPokemonList, allPokemon, 152, 251);
+ if (restrictions.assoc_g2_g1) {
+ addEvosFromRange(mainPokemonList, allPokemon, evos, 152,
+ 251, 1, 151);
+ }
+ if (restrictions.assoc_g2_g3 && allPokemon.size() > 386) {
+ addEvosFromRange(mainPokemonList, allPokemon, evos, 152,
+ 251, 252, 386);
+ }
+ if (restrictions.assoc_g2_g4 && allPokemon.size() > 493) {
+ addEvosFromRange(mainPokemonList, allPokemon, evos, 152,
+ 251, 387, 493);
+ }
+ }
+
+ if (restrictions.allow_gen3 && allPokemon.size() > 386) {
+ addPokesFromRange(mainPokemonList, allPokemon, 252, 386);
+ if (restrictions.assoc_g3_g2) {
+ addEvosFromRange(mainPokemonList, allPokemon, evos, 252,
+ 386, 152, 251);
+ }
+ if (restrictions.assoc_g3_g4 && allPokemon.size() > 493) {
+ addEvosFromRange(mainPokemonList, allPokemon, evos, 252,
+ 386, 387, 493);
+ }
+ }
+
+ if (restrictions.allow_gen4 && allPokemon.size() > 493) {
+ addPokesFromRange(mainPokemonList, allPokemon, 387, 493);
+ if (restrictions.assoc_g4_g1) {
+ addEvosFromRange(mainPokemonList, allPokemon, evos, 387,
+ 493, 1, 151);
+ }
+ if (restrictions.assoc_g4_g2) {
+ addEvosFromRange(mainPokemonList, allPokemon, evos, 387,
+ 493, 152, 251);
+ }
+ if (restrictions.assoc_g4_g3) {
+ addEvosFromRange(mainPokemonList, allPokemon, evos, 387,
+ 493, 252, 386);
+ }
+ }
+
+ if (restrictions.allow_gen5 && allPokemon.size() > 649) {
+ addPokesFromRange(mainPokemonList, allPokemon, 494, 649);
+ }
+ }
+
+ noLegendaryList = new ArrayList();
+ onlyLegendaryList = new ArrayList();
+
+ for (Pokemon p : mainPokemonList) {
+ if (p.isLegendary()) {
+ onlyLegendaryList.add(p);
+ } else {
+ noLegendaryList.add(p);
+ }
+ }
+ }
+
+ private void addPokesFromRange(List pokemonPool,
+ List allPokemon, int range_min, int range_max) {
+ for (int i = range_min; i <= range_max; i++) {
+ if (!pokemonPool.contains(allPokemon.get(i))) {
+ pokemonPool.add(allPokemon.get(i));
+ }
+ }
+ }
+
+ private void addEvosFromRange(List pokemonPool,
+ List allPokemon, List evos, int first_min,
+ int first_max, int second_min, int second_max) {
+ for (Evolution e : evos) {
+ Pokemon potential = null;
+ if ((e.from >= first_min && e.from <= first_max
+ && e.to >= second_min && e.to <= second_max)) {
+ potential = allPokemon.get(e.to);
+ } else if ((e.from >= second_min && e.from <= second_max
+ && e.to >= first_min && e.to <= first_max)) {
+ potential = allPokemon.get(e.from);
+ }
+ if (potential != null && !pokemonPool.contains(potential)) {
+ pokemonPool.add(potential);
+ }
+ }
+ }
+
+ @Override
+ public void randomizePokemonStats(boolean evolutionSanity) {
+ List allPokes = this.getPokemon();
+ List evolutions = this.getEvolutions();
+ if (evolutionSanity) {
+ // Spread stats up MOST evolutions.
+ Set dontCopyPokes = RomFunctions
+ .getBasicOrNoCopyPokemon(this);
+
+ for (Pokemon pk : dontCopyPokes) {
+ pk.randomizeStatsWithinBST();
+ }
+ // go "up" evolutions looking for pre-evos to do first
+ for (Evolution evo : evolutions) {
+ if (evo.carryStats) {
+ Stack currentStack = new Stack();
+ Evolution current = evo;
+ while (current != null) {
+ Evolution last = current;
+ currentStack.push(last);
+ current = null;
+ for (Evolution evo2 : evolutions) {
+ if (last.from == evo2.to && evo2.carryStats) {
+ current = evo2;
+ break;
+ }
+ }
+ }
+ // now we have a stack of evolutions
+ while (!currentStack.isEmpty()) {
+ Evolution useEvo = currentStack.pop();
+ useEvo.carryStats = false; // so we don't waste time
+ // later
+ Pokemon to = allPokes.get(useEvo.to);
+ Pokemon from = allPokes.get(useEvo.from);
+ to.copyRandomizedStatsUpEvolution(from);
+ }
+ }
+ }
+ } else {
+ for (Pokemon pk : allPokes) {
+ if (pk != null) {
+ pk.randomizeStatsWithinBST();
+ }
+ }
+ }
+
+ }
+
+ @Override
+ public void applyCamelCaseNames() {
+ List pokes = getPokemon();
+ for (Pokemon pkmn : pokes) {
+ if (pkmn == null) {
+ continue;
+ }
+ pkmn.name = RomFunctions.camelCase(pkmn.name);
+ }
+
+ }
+
+ @Override
+ public void minimumCatchRate(int rateNonLegendary, int rateLegendary) {
+ List pokes = getPokemon();
+ for (Pokemon pkmn : pokes) {
+ if (pkmn == null) {
+ continue;
+ }
+ int minCatchRate = pkmn.isLegendary() ? rateLegendary
+ : rateNonLegendary;
+ pkmn.catchRate = Math.max(pkmn.catchRate, minCatchRate);
+ }
+
+ }
+
+ @Override
+ public void standardizeEXPCurves() {
+ List pokes = getPokemon();
+ for (Pokemon pkmn : pokes) {
+ if (pkmn == null) {
+ continue;
+ }
+ pkmn.growthCurve = pkmn.isLegendary() ? ExpCurve.SLOW
+ : ExpCurve.MEDIUM_FAST;
+ }
+ }
+
+ @Override
+ public void randomizePokemonTypes(boolean evolutionSanity) {
+ if (evolutionSanity) {
+ Set dontCopyPokes = RomFunctions
+ .getBasicOrNoCopyPokemon(this);
+ // Type randomization
+ // Step 1: Basic or Excluded From Copying Pokemon
+ // A Basic/EFC pokemon has a 35% chance of a second type if it has
+ // an evolution, a 50% chance otherwise
+ for (Pokemon pk : dontCopyPokes) {
+ pk.primaryType = randomType();
+ pk.secondaryType = null;
+ if (RomFunctions.pokemonHasEvo(this, pk)) {
+ if (RandomSource.random() < 0.35) {
+ pk.secondaryType = randomType();
+ while (pk.secondaryType == pk.primaryType) {
+ pk.secondaryType = randomType();
+ }
+ }
+ } else {
+ if (RandomSource.random() < 0.5) {
+ pk.secondaryType = randomType();
+ while (pk.secondaryType == pk.primaryType) {
+ pk.secondaryType = randomType();
+ }
+ }
+ }
+ }
+ // Step 2: First Evolutions
+ // A first evolution has a 15% chance of adding a type if there's a
+ // 3rd stage, Or a 25% chance if there's not
+ Set firstEvos = RomFunctions.getFirstEvolutions(this);
+ for (Pokemon pk : firstEvos) {
+ Pokemon evolvedFrom = RomFunctions.evolvesFrom(this, pk);
+ pk.primaryType = evolvedFrom.primaryType;
+ pk.secondaryType = evolvedFrom.secondaryType;
+ if (pk.secondaryType == null) {
+ if (RomFunctions.pokemonHasEvo(this, pk)) {
+ if (RandomSource.random() < 0.15) {
+ pk.secondaryType = randomType();
+ while (pk.secondaryType == pk.primaryType) {
+ pk.secondaryType = randomType();
+ }
+ }
+ } else {
+ if (RandomSource.random() < 0.25) {
+ pk.secondaryType = randomType();
+ while (pk.secondaryType == pk.primaryType) {
+ pk.secondaryType = randomType();
+ }
+ }
+ }
+ }
+ }
+
+ // Step 3: Second Evolutions
+ // A second evolution has a 25% chance of adding a type
+ Set secondEvos = RomFunctions.getSecondEvolutions(this);
+ for (Pokemon pk : secondEvos) {
+ Pokemon evolvedFrom = RomFunctions.evolvesFrom(this, pk);
+ pk.primaryType = evolvedFrom.primaryType;
+ pk.secondaryType = evolvedFrom.secondaryType;
+ if (pk.secondaryType == null) {
+ if (RandomSource.random() < 0.25) {
+ pk.secondaryType = randomType();
+ while (pk.secondaryType == pk.primaryType) {
+ pk.secondaryType = randomType();
+ }
+ }
+ }
+ }
+ } else {
+ // Entirely random types
+ List allPokes = this.getPokemon();
+ for (Pokemon pkmn : allPokes) {
+ if (pkmn != null) {
+ pkmn.primaryType = randomType();
+ pkmn.secondaryType = null;
+ if (RandomSource.random() < 0.5) {
+ pkmn.secondaryType = randomType();
+ while (pkmn.secondaryType == pkmn.primaryType) {
+ pkmn.secondaryType = randomType();
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private static final int WONDER_GUARD_INDEX = 25;
+
+ @Override
+ public void randomizeAbilities(boolean allowWonderGuard) {
+ // Abilities don't exist in some games...
+ if (this.abilitiesPerPokemon() == 0) {
+ return;
+ }
+
+ // Deal with "natural" abilities first regardless
+ List allPokes = this.getPokemon();
+ int maxAbility = this.highestAbilityIndex();
+ for (Pokemon pk : allPokes) {
+ if (pk == null) {
+ continue;
+ }
+
+ // Wonder Guard?
+ if (pk.ability1 != WONDER_GUARD_INDEX
+ && pk.ability2 != WONDER_GUARD_INDEX
+ && pk.ability3 != WONDER_GUARD_INDEX) {
+ // Pick first ability
+ pk.ability1 = RandomSource.nextInt(maxAbility) + 1;
+ // Wonder guard block
+ if (!allowWonderGuard) {
+ while (pk.ability1 == WONDER_GUARD_INDEX) {
+ pk.ability1 = RandomSource.nextInt(maxAbility) + 1;
+ }
+ }
+
+ // Second ability?
+ if (RandomSource.nextDouble() < 0.5) {
+ // Yes, second ability
+ pk.ability2 = RandomSource.nextInt(maxAbility) + 1;
+ // Wonder guard? Also block first ability from reappearing
+ if (allowWonderGuard) {
+ while (pk.ability2 == pk.ability1) {
+ pk.ability2 = RandomSource.nextInt(maxAbility) + 1;
+ }
+ } else {
+ while (pk.ability2 == WONDER_GUARD_INDEX
+ || pk.ability2 == pk.ability1) {
+ pk.ability2 = RandomSource.nextInt(maxAbility) + 1;
+ }
+ }
+ } else {
+ // Nope
+ pk.ability2 = 0;
+ }
+ }
+ }
+
+ // DW Abilities?
+ if (this.abilitiesPerPokemon() == 3) {
+ // Give a random DW ability to every Pokemon
+ for (Pokemon pk : allPokes) {
+ if (pk == null) {
+ continue;
+ }
+ if (pk.ability1 != WONDER_GUARD_INDEX
+ && pk.ability2 != WONDER_GUARD_INDEX
+ && pk.ability3 != WONDER_GUARD_INDEX) {
+ pk.ability3 = RandomSource.nextInt(maxAbility) + 1;
+ // Wonder guard? Also block other abilities from reappearing
+ if (allowWonderGuard) {
+ while (pk.ability3 == pk.ability1
+ || pk.ability3 == pk.ability2) {
+ pk.ability3 = RandomSource.nextInt(maxAbility) + 1;
+ }
+ } else {
+ while (pk.ability3 == WONDER_GUARD_INDEX
+ || pk.ability3 == pk.ability1
+ || pk.ability3 == pk.ability2) {
+ pk.ability3 = RandomSource.nextInt(maxAbility) + 1;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public Pokemon randomPokemon() {
+ checkPokemonRestrictions();
+ return mainPokemonList
+ .get(RandomSource.nextInt(mainPokemonList.size()));
+ }
+
+ @Override
+ public Pokemon randomNonLegendaryPokemon() {
+ checkPokemonRestrictions();
+ return noLegendaryList
+ .get(RandomSource.nextInt(noLegendaryList.size()));
+ }
+
+ @Override
+ public Pokemon randomLegendaryPokemon() {
+ checkPokemonRestrictions();
+ return onlyLegendaryList.get(RandomSource.nextInt(onlyLegendaryList
+ .size()));
+ }
+
+ private List twoEvoPokes;
+
+ @Override
+ public Pokemon random2EvosPokemon() {
+ if (twoEvoPokes == null) {
+ // Prepare the list
+ List allPokes = this.getPokemon();
+ List remainingPokes = allPokemonWithoutNull();
+ List allEvos = this.getEvolutions();
+ Map reverseKeepPokemon = new TreeMap();
+ for (Evolution e : allEvos) {
+ reverseKeepPokemon
+ .put(allPokes.get(e.to), allPokes.get(e.from));
+ }
+ remainingPokes.retainAll(reverseKeepPokemon.values());
+ // All pokemon with evolutions are left
+ // Look for the evolutions themselves again in the evo-list
+ Set keepFor2Evos = new TreeSet();
+ for (Evolution e : allEvos) {
+ Pokemon from = allPokes.get(e.from);
+ if (reverseKeepPokemon.containsKey(from)) {
+ keepFor2Evos.add(reverseKeepPokemon.get(from));
+ }
+ }
+ remainingPokes.retainAll(keepFor2Evos);
+ twoEvoPokes = remainingPokes;
+ }
+ return twoEvoPokes.get(RandomSource.nextInt(twoEvoPokes.size()));
+ }
+
+ @Override
+ public void randomEncounters(boolean useTimeOfDay, boolean catchEmAll,
+ boolean typeThemed, boolean usePowerLevels, boolean noLegendaries) {
+ checkPokemonRestrictions();
+ List currentEncounters = this.getEncounters(useTimeOfDay);
+ List banned = this.bannedForWildEncounters();
+ // Assume EITHER catch em all OR type themed OR match strength for now
+ if (catchEmAll) {
+
+ List allPokes = noLegendaries ? new ArrayList(
+ noLegendaryList) : new ArrayList(mainPokemonList);
+ allPokes.removeAll(banned);
+ for (EncounterSet area : currentEncounters) {
+ for (Encounter enc : area.encounters) {
+ // Pick a random pokemon
+ int picked = RandomSource.nextInt(allPokes.size());
+ enc.pokemon = allPokes.get(picked);
+ if (area.battleTrappersBanned
+ && hasBattleTrappingAbility(enc.pokemon)) {
+ // Skip past this Pokemon for now and just pick a random
+ // one
+ List pickable = noLegendaries ? new ArrayList(
+ noLegendaryList) : new ArrayList(
+ mainPokemonList);
+ pickable.removeAll(banned);
+ if (pickable.size() == 0) {
+ JOptionPane.showMessageDialog(null,
+ "ERROR: Couldn't replace a Pokemon!");
+ return;
+ }
+ while (hasBattleTrappingAbility(enc.pokemon)) {
+ picked = RandomSource.nextInt(pickable.size());
+ enc.pokemon = pickable.get(picked);
+ }
+ } else {
+ // Picked this Pokemon, remove it
+ allPokes.remove(picked);
+ if (allPokes.size() == 0) {
+ // Start again
+ allPokes.addAll(noLegendaries ? noLegendaryList
+ : mainPokemonList);
+ allPokes.removeAll(banned);
+ }
+ }
+ }
+ }
+ } else if (typeThemed) {
+ Map> cachedPokeLists = new TreeMap>();
+ for (EncounterSet area : currentEncounters) {
+ Type areaTheme = randomType();
+ if (!cachedPokeLists.containsKey(areaTheme)) {
+ cachedPokeLists.put(areaTheme,
+ pokemonOfType(areaTheme, noLegendaries));
+ }
+ List possiblePokemon = cachedPokeLists.get(areaTheme);
+ for (Encounter enc : area.encounters) {
+ // Pick a random themed pokemon
+ enc.pokemon = possiblePokemon.get(RandomSource
+ .nextInt(possiblePokemon.size()));
+ while (banned.contains(enc.pokemon)
+ || (area.battleTrappersBanned && hasBattleTrappingAbility(enc.pokemon))) {
+ enc.pokemon = possiblePokemon.get(RandomSource
+ .nextInt(possiblePokemon.size()));
+ }
+ }
+ }
+ } else if (usePowerLevels) {
+ List allowedPokes = noLegendaries ? new ArrayList(
+ noLegendaryList) : new ArrayList(mainPokemonList);
+ allowedPokes.removeAll(banned);
+ for (EncounterSet area : currentEncounters) {
+ for (Encounter enc : area.encounters) {
+ enc.pokemon = pickWildPowerLvlReplacement(allowedPokes,
+ enc.pokemon, area.battleTrappersBanned, false, null);
+ }
+ }
+ } else {
+ // Entirely random
+ for (EncounterSet area : currentEncounters) {
+ for (Encounter enc : area.encounters) {
+ enc.pokemon = noLegendaries ? randomNonLegendaryPokemon()
+ : randomPokemon();
+ while (banned.contains(enc.pokemon)
+ || (area.battleTrappersBanned && hasBattleTrappingAbility(enc.pokemon))) {
+ enc.pokemon = noLegendaries ? randomNonLegendaryPokemon()
+ : randomPokemon();
+ }
+ }
+ }
+ }
+
+ setEncounters(useTimeOfDay, currentEncounters);
+ }
+
+ @Override
+ public void area1to1Encounters(boolean useTimeOfDay, boolean catchEmAll,
+ boolean typeThemed, boolean usePowerLevels, boolean noLegendaries) {
+ checkPokemonRestrictions();
+ List currentEncounters = this.getEncounters(useTimeOfDay);
+ List banned = this.bannedForWildEncounters();
+ // Assume EITHER catch em all OR type themed for now
+ if (catchEmAll) {
+ List allPokes = noLegendaries ? new ArrayList(
+ noLegendaryList) : new ArrayList(mainPokemonList);
+ allPokes.removeAll(banned);
+ for (EncounterSet area : currentEncounters) {
+ // Poke-set
+ Set inArea = pokemonInArea(area);
+ // Build area map using catch em all
+ Map areaMap = new TreeMap();
+ for (Pokemon areaPk : inArea) {
+ int picked = RandomSource.nextInt(allPokes.size());
+ Pokemon pickedMN = allPokes.get(picked);
+ if (area.battleTrappersBanned
+ && hasBattleTrappingAbility(pickedMN)) {
+ // Skip past this Pokemon for now and just pick a random
+ // one
+ List pickable = noLegendaries ? new ArrayList(
+ noLegendaryList) : new ArrayList(
+ mainPokemonList);
+ pickable.removeAll(banned);
+ if (pickable.size() == 0) {
+ JOptionPane.showMessageDialog(null,
+ "ERROR: Couldn't replace a Pokemon!");
+ return;
+ }
+ while (hasBattleTrappingAbility(pickedMN)) {
+ picked = RandomSource.nextInt(pickable.size());
+ pickedMN = pickable.get(picked);
+ }
+ areaMap.put(areaPk, pickedMN);
+ } else {
+ areaMap.put(areaPk, pickedMN);
+ allPokes.remove(picked);
+ if (allPokes.size() == 0) {
+ // Start again
+ allPokes.addAll(noLegendaries ? noLegendaryList
+ : mainPokemonList);
+ allPokes.removeAll(banned);
+ }
+ }
+ }
+ for (Encounter enc : area.encounters) {
+ // Apply the map
+ enc.pokemon = areaMap.get(enc.pokemon);
+ }
+ }
+ } else if (typeThemed) {
+ Map> cachedPokeLists = new TreeMap>();
+ for (EncounterSet area : currentEncounters) {
+ Type areaTheme = randomType();
+ if (!cachedPokeLists.containsKey(areaTheme)) {
+ cachedPokeLists.put(areaTheme,
+ pokemonOfType(areaTheme, noLegendaries));
+ }
+ List possiblePokemon = new ArrayList(
+ cachedPokeLists.get(areaTheme));
+ possiblePokemon.removeAll(banned);
+ // Poke-set
+ Set inArea = pokemonInArea(area);
+ // Build area map using type theme, reset the list if needed
+ Map areaMap = new TreeMap();
+ for (Pokemon areaPk : inArea) {
+ int picked = RandomSource.nextInt(possiblePokemon.size());
+ Pokemon pickedMN = possiblePokemon.get(picked);
+ if (area.battleTrappersBanned
+ && hasBattleTrappingAbility(pickedMN)) {
+ // Skip past this Pokemon for now and just pick a random
+ // one
+ List pickable = new ArrayList(
+ cachedPokeLists.get(areaTheme));
+ pickable.removeAll(banned);
+ if (pickable.size() == 0) {
+ // Try all Pokemon instead
+ pickable = noLegendaries ? new ArrayList(
+ noLegendaryList) : new ArrayList(
+ mainPokemonList);
+ pickable.removeAll(banned);
+ }
+ if (pickable.size() == 0) {
+ JOptionPane.showMessageDialog(null,
+ "ERROR: Couldn't replace a Pokemon!");
+ return;
+ }
+ while (hasBattleTrappingAbility(pickedMN)) {
+ picked = RandomSource.nextInt(pickable.size());
+ pickedMN = pickable.get(picked);
+ }
+ areaMap.put(areaPk, pickedMN);
+ } else {
+ areaMap.put(areaPk, pickedMN);
+ possiblePokemon.remove(picked);
+ if (possiblePokemon.size() == 0) {
+ // Start again
+ possiblePokemon.addAll(cachedPokeLists
+ .get(areaTheme));
+ possiblePokemon.removeAll(banned);
+ }
+ }
+ }
+ for (Encounter enc : area.encounters) {
+ // Apply the map
+ enc.pokemon = areaMap.get(enc.pokemon);
+ }
+ }
+ } else if (usePowerLevels) {
+ List allowedPokes = noLegendaries ? new ArrayList(
+ noLegendaryList) : new ArrayList(mainPokemonList);
+ allowedPokes.removeAll(banned);
+ for (EncounterSet area : currentEncounters) {
+ // Poke-set
+ Set inArea = pokemonInArea(area);
+ // Build area map using randoms
+ Map areaMap = new TreeMap();
+ List usedPks = new ArrayList();
+ for (Pokemon areaPk : inArea) {
+ Pokemon picked = pickWildPowerLvlReplacement(allowedPokes,
+ areaPk, area.battleTrappersBanned, false, usedPks);
+ areaMap.put(areaPk, picked);
+ usedPks.add(picked);
+ }
+ for (Encounter enc : area.encounters) {
+ // Apply the map
+ enc.pokemon = areaMap.get(enc.pokemon);
+ }
+ }
+ } else {
+ // Entirely random
+ for (EncounterSet area : currentEncounters) {
+ // Poke-set
+ Set inArea = pokemonInArea(area);
+ // Build area map using randoms
+ Map areaMap = new TreeMap();
+ for (Pokemon areaPk : inArea) {
+ Pokemon picked = noLegendaries ? randomNonLegendaryPokemon()
+ : randomPokemon();
+ while (areaMap.containsValue(picked)
+ || banned.contains(picked)
+ || (area.battleTrappersBanned && hasBattleTrappingAbility(picked))) {
+ picked = noLegendaries ? randomNonLegendaryPokemon()
+ : randomPokemon();
+ }
+ areaMap.put(areaPk, picked);
+ }
+ for (Encounter enc : area.encounters) {
+ // Apply the map
+ enc.pokemon = areaMap.get(enc.pokemon);
+ }
+ }
+ }
+
+ setEncounters(useTimeOfDay, currentEncounters);
+
+ }
+
+ @Override
+ public void game1to1Encounters(boolean useTimeOfDay,
+ boolean usePowerLevels, boolean noLegendaries) {
+ checkPokemonRestrictions();
+ // Build the full 1-to-1 map
+ Map translateMap = new TreeMap();
+ List remainingLeft = allPokemonWithoutNull();
+ List remainingRight = noLegendaries ? new ArrayList(
+ noLegendaryList) : new ArrayList(mainPokemonList);
+ List banned = this.bannedForWildEncounters();
+ // Banned pokemon should be mapped to themselves
+ for (Pokemon bannedPK : banned) {
+ translateMap.put(bannedPK, bannedPK);
+ remainingLeft.remove(bannedPK);
+ remainingRight.remove(bannedPK);
+ }
+ while (remainingLeft.isEmpty() == false) {
+ if (usePowerLevels) {
+ int pickedLeft = RandomSource.nextInt(remainingLeft.size());
+ Pokemon pickedLeftP = remainingLeft.remove(pickedLeft);
+ Pokemon pickedRightP = null;
+ if (remainingRight.size() == 1) {
+ // pick this (it may or may not be the same poke)
+ pickedRightP = remainingRight.get(0);
+ } else {
+ // pick on power level with the current one blocked
+ pickedRightP = pickWildPowerLvlReplacement(remainingRight,
+ pickedLeftP, false, true, null);
+ }
+ remainingRight.remove(pickedRightP);
+ translateMap.put(pickedLeftP, pickedRightP);
+ } else {
+ int pickedLeft = RandomSource.nextInt(remainingLeft.size());
+ int pickedRight = RandomSource.nextInt(remainingRight.size());
+ Pokemon pickedLeftP = remainingLeft.remove(pickedLeft);
+ Pokemon pickedRightP = remainingRight.get(pickedRight);
+ while (pickedLeftP.number == pickedRightP.number
+ && remainingRight.size() != 1) {
+ // Reroll for a different pokemon if at all possible
+ pickedRight = RandomSource.nextInt(remainingRight.size());
+ pickedRightP = remainingRight.get(pickedRight);
+ }
+ remainingRight.remove(pickedRight);
+ translateMap.put(pickedLeftP, pickedRightP);
+ }
+ if (remainingRight.size() == 0) {
+ // restart
+ remainingRight.addAll(noLegendaries ? noLegendaryList
+ : mainPokemonList);
+ remainingRight.removeAll(banned);
+ }
+ }
+
+ // Map remaining to themselves just in case
+ List allPokes = allPokemonWithoutNull();
+ for (Pokemon poke : allPokes) {
+ if (!translateMap.containsKey(poke)) {
+ translateMap.put(poke, poke);
+ }
+ }
+
+ List currentEncounters = this.getEncounters(useTimeOfDay);
+
+ for (EncounterSet area : currentEncounters) {
+ for (Encounter enc : area.encounters) {
+ // Apply the map
+ enc.pokemon = translateMap.get(enc.pokemon);
+ if (area.battleTrappersBanned
+ && hasBattleTrappingAbility(enc.pokemon)) {
+ // Ignore the map and put a random non-trapping Poke
+ List pickable = noLegendaries ? new ArrayList(
+ noLegendaryList) : new ArrayList(
+ mainPokemonList);
+ pickable.removeAll(banned);
+ if (pickable.size() == 0) {
+ JOptionPane.showMessageDialog(null,
+ "ERROR: Couldn't replace a Pokemon!");
+ return;
+ }
+ if (usePowerLevels) {
+ enc.pokemon = pickWildPowerLvlReplacement(pickable,
+ enc.pokemon, true, false, null);
+ } else {
+ while (hasBattleTrappingAbility(enc.pokemon)) {
+ int picked = RandomSource.nextInt(pickable.size());
+ enc.pokemon = pickable.get(picked);
+ }
+ }
+ }
+ }
+ }
+
+ setEncounters(useTimeOfDay, currentEncounters);
+
+ }
+
+ @Override
+ public void randomizeTrainerPokes(boolean rivalCarriesStarter,
+ boolean usePowerLevels, boolean noLegendaries,
+ boolean noEarlyWonderGuard) {
+ checkPokemonRestrictions();
+ List currentTrainers = this.getTrainers();
+ cachedReplacementLists = new TreeMap>();
+ cachedAllList = noLegendaries ? new ArrayList(noLegendaryList)
+ : new ArrayList(mainPokemonList);
+
+ // Fully random is easy enough - randomize then worry about rival
+ // carrying starter at the end
+ for (Trainer t : currentTrainers) {
+ if (t.tag != null && t.tag.equals("IRIVAL")) {
+ continue; // skip
+ }
+ for (TrainerPokemon tp : t.pokemon) {
+ boolean wgAllowed = (!noEarlyWonderGuard) || tp.level >= 20;
+ tp.pokemon = pickReplacement(tp.pokemon, usePowerLevels, null,
+ noLegendaries, wgAllowed);
+ }
+ }
+
+ // Rival carries starter?
+ if (rivalCarriesStarter) {
+ rivalCarriesStarterUpdate(currentTrainers, "RIVAL", 1);
+ rivalCarriesStarterUpdate(currentTrainers, "FRIEND", 2);
+ }
+
+ // Save it all up
+ this.setTrainers(currentTrainers);
+ }
+
+ @Override
+ public void typeThemeTrainerPokes(boolean rivalCarriesStarter,
+ boolean usePowerLevels, boolean weightByFrequency,
+ boolean noLegendaries, boolean noEarlyWonderGuard) {
+ checkPokemonRestrictions();
+ List currentTrainers = this.getTrainers();
+ cachedReplacementLists = new TreeMap>();
+ cachedAllList = noLegendaries ? new ArrayList(noLegendaryList)
+ : new ArrayList(mainPokemonList);
+ typeWeightings = new TreeMap();
+ totalTypeWeighting = 0;
+
+ // Construct groupings for types
+ // Anything starting with GYM or ELITE or CHAMPION is a group
+ Set assignedTrainers = new TreeSet();
+ Map> groups = new TreeMap>();
+ for (Trainer t : currentTrainers) {
+ if (t.tag != null && t.tag.equals("IRIVAL")) {
+ continue; // skip
+ }
+ String group = t.tag == null ? "" : t.tag;
+ if (group.contains("-")) {
+ group = group.substring(0, group.indexOf('-'));
+ }
+ if (group.startsWith("GYM") || group.startsWith("ELITE")
+ || group.startsWith("CHAMPION")
+ || group.startsWith("THEMED")) {
+ // Yep this is a group
+ if (!groups.containsKey(group)) {
+ groups.put(group, new ArrayList());
+ }
+ groups.get(group).add(t);
+ assignedTrainers.add(t);
+ } else if (group.startsWith("GIO")) {
+ // Giovanni has same grouping as his gym, gym 8
+ if (!groups.containsKey("GYM8")) {
+ groups.put("GYM8", new ArrayList());
+ }
+ groups.get("GYM8").add(t);
+ assignedTrainers.add(t);
+ }
+ }
+
+ // Give a type to each group
+ // Gym & elite types have to be unique
+ // So do uber types, including the type we pick for champion
+ Set usedGymTypes = new TreeSet();
+ Set usedEliteTypes = new TreeSet();
+ Set usedUberTypes = new TreeSet();
+ for (String group : groups.keySet()) {
+ List trainersInGroup = groups.get(group);
+ Type typeForGroup = pickType(weightByFrequency, noLegendaries);
+ if (group.startsWith("GYM")) {
+ while (usedGymTypes.contains(typeForGroup)) {
+ typeForGroup = pickType(weightByFrequency, noLegendaries);
+ }
+ usedGymTypes.add(typeForGroup);
+ }
+ if (group.startsWith("ELITE")) {
+ while (usedEliteTypes.contains(typeForGroup)) {
+ typeForGroup = pickType(weightByFrequency, noLegendaries);
+ }
+ usedEliteTypes.add(typeForGroup);
+ }
+ if (group.equals("CHAMPION")) {
+ usedUberTypes.add(typeForGroup);
+ }
+ // Themed groups just have a theme, no special criteria
+ for (Trainer t : trainersInGroup) {
+ for (TrainerPokemon tp : t.pokemon) {
+ boolean wgAllowed = (!noEarlyWonderGuard) || tp.level >= 20;
+ tp.pokemon = pickReplacement(tp.pokemon, usePowerLevels,
+ typeForGroup, noLegendaries, wgAllowed);
+ }
+ }
+ }
+
+ // Give a type to each unassigned trainer
+ for (Trainer t : currentTrainers) {
+ if (t.tag != null && t.tag.equals("IRIVAL")) {
+ continue; // skip
+ }
+
+ if (!assignedTrainers.contains(t)) {
+ Type typeForTrainer = pickType(weightByFrequency, noLegendaries);
+ // Ubers: can't have the same type as each other
+ if (t.tag != null && t.tag.equals("UBER")) {
+ while (usedUberTypes.contains(typeForTrainer)) {
+ typeForTrainer = pickType(weightByFrequency,
+ noLegendaries);
+ }
+ usedUberTypes.add(typeForTrainer);
+ }
+ for (TrainerPokemon tp : t.pokemon) {
+ boolean shedAllowed = (!noEarlyWonderGuard)
+ || tp.level >= 20;
+ tp.pokemon = pickReplacement(tp.pokemon, usePowerLevels,
+ typeForTrainer, noLegendaries, shedAllowed);
+ }
+ }
+ }
+
+ // Rival carries starter?
+ if (rivalCarriesStarter) {
+ rivalCarriesStarterUpdate(currentTrainers, "RIVAL", 1);
+ rivalCarriesStarterUpdate(currentTrainers, "FRIEND", 2);
+ }
+
+ // Save it all up
+ this.setTrainers(currentTrainers);
+ }
+
+ @Override
+ public void randomizeMovesLearnt(boolean typeThemed, boolean noBroken,
+ boolean forceFourStartingMoves) {
+ // Get current sets
+ Map> movesets = this.getMovesLearnt();
+ List hms = this.getHMMoves();
+ @SuppressWarnings("unchecked")
+ List banned = noBroken ? this.getGameBreakingMoves()
+ : Collections.EMPTY_LIST;
+ for (Pokemon pkmn : movesets.keySet()) {
+ Set learnt = new TreeSet();
+ List moves = movesets.get(pkmn);
+ // 4 starting moves?
+ if (forceFourStartingMoves) {
+ int lv1count = 0;
+ for (MoveLearnt ml : moves) {
+ if (ml.level == 1) {
+ lv1count++;
+ }
+ }
+ if (lv1count < 4) {
+ for (int i = 0; i < 4 - lv1count; i++) {
+ MoveLearnt fakeLv1 = new MoveLearnt();
+ fakeLv1.level = 1;
+ fakeLv1.move = 0;
+ moves.add(0, fakeLv1);
+ }
+ }
+ }
+ // Last level 1 move should be replaced with a damaging one
+ int damagingMove = pickMove(pkmn, typeThemed, true, hms);
+ // Find last lv1 move
+ // lv1index ends up as the index of the first non-lv1 move
+ int lv1index = 0;
+ while (lv1index < moves.size() && moves.get(lv1index).level == 1) {
+ lv1index++;
+ }
+ // last lv1 move is 1 before lv1index
+ if (lv1index == 0) {
+ lv1index++;
+ }
+ moves.get(lv1index - 1).move = damagingMove;
+ moves.get(lv1index - 1).level = 1; // just in case
+ learnt.add(damagingMove);
+ // Rest replace with randoms
+ for (int i = 0; i < moves.size(); i++) {
+ if (i == (lv1index - 1)) {
+ continue;
+ }
+ int picked = pickMove(pkmn, typeThemed, false, hms);
+ while (learnt.contains(picked) || banned.contains(picked)) {
+ picked = pickMove(pkmn, typeThemed, false, hms);
+ }
+ moves.get(i).move = picked;
+ learnt.add(picked);
+ }
+ }
+ // Done, save
+ this.setMovesLearnt(movesets);
+
+ }
+
+ private static final int METRONOME_MOVE = 118;
+
+ @Override
+ public void metronomeOnlyMode() {
+ // TODO fix static pokemon with set movesets
+
+ // movesets
+ Map> movesets = this.getMovesLearnt();
+
+ MoveLearnt metronomeML = new MoveLearnt();
+ metronomeML.level = 1;
+ metronomeML.move = METRONOME_MOVE;
+
+ for (List ms : movesets.values()) {
+ if (ms != null && ms.size() > 0) {
+ ms.clear();
+ ms.add(metronomeML);
+ }
+ }
+
+ this.setMovesLearnt(movesets);
+
+ // trainers
+ // run this to remove all custom non-Metronome moves
+ this.setTrainers(this.getTrainers());
+
+ // tms
+ List tmMoves = this.getTMMoves();
+
+ for (int i = 0; i < tmMoves.size(); i++) {
+ tmMoves.set(i, METRONOME_MOVE);
+ }
+
+ this.setTMMoves(tmMoves);
+
+ // movetutors
+ if (this.hasMoveTutors()) {
+ List mtMoves = this.getMoveTutorMoves();
+
+ for (int i = 0; i < mtMoves.size(); i++) {
+ mtMoves.set(i, METRONOME_MOVE);
+ }
+
+ this.setMoveTutorMoves(mtMoves);
+ }
+
+ // move tweaks
+ List moveData = this.getMoves();
+
+ Move metronome = moveData.get(METRONOME_MOVE);
+
+ metronome.pp = 40;
+
+ List hms = this.getHMMoves();
+
+ for (int hm : hms) {
+ Move thisHM = moveData.get(hm);
+ thisHM.pp = 0;
+ }
+ }
+
+ @Override
+ public void randomizeStaticPokemon(boolean legendForLegend) {
+ // Load
+ checkPokemonRestrictions();
+ List currentStaticPokemon = this.getStaticPokemon();
+ List replacements = new ArrayList();
+ List banned = this.bannedForStaticPokemon();
+
+ if (legendForLegend) {
+ List legendariesLeft = new ArrayList(
+ onlyLegendaryList);
+ List nonlegsLeft = new ArrayList(noLegendaryList);
+ legendariesLeft.removeAll(banned);
+ nonlegsLeft.removeAll(banned);
+ for (int i = 0; i < currentStaticPokemon.size(); i++) {
+ Pokemon old = currentStaticPokemon.get(i);
+ Pokemon newPK;
+ if (old.isLegendary()) {
+ newPK = legendariesLeft.remove(RandomSource
+ .nextInt(legendariesLeft.size()));
+ if (legendariesLeft.size() == 0) {
+ legendariesLeft.addAll(onlyLegendaryList);
+ legendariesLeft.removeAll(banned);
+ }
+ } else {
+ newPK = nonlegsLeft.remove(RandomSource.nextInt(nonlegsLeft
+ .size()));
+ if (nonlegsLeft.size() == 0) {
+ nonlegsLeft.addAll(onlyLegendaryList);
+ nonlegsLeft.removeAll(banned);
+ }
+ }
+ replacements.add(newPK);
+ }
+ } else {
+ List pokemonLeft = new ArrayList(mainPokemonList);
+ pokemonLeft.removeAll(banned);
+ for (int i = 0; i < currentStaticPokemon.size(); i++) {
+ Pokemon newPK = pokemonLeft.remove(RandomSource
+ .nextInt(pokemonLeft.size()));
+ if (pokemonLeft.size() == 0) {
+ pokemonLeft.addAll(mainPokemonList);
+ pokemonLeft.removeAll(banned);
+ }
+ replacements.add(newPK);
+ }
+ }
+
+ // Save
+ this.setStaticPokemon(replacements);
+ }
+
+ @Override
+ public void randomizeTMMoves(boolean noBroken) {
+ // Pick some random TM moves.
+ int tmCount = this.getTMCount();
+ List allMoves = this.getMoves();
+ List newTMs = new ArrayList();
+ List hms = this.getHMMoves();
+ @SuppressWarnings("unchecked")
+ List banned = noBroken ? this.getGameBreakingMoves()
+ : Collections.EMPTY_LIST;
+ for (int i = 0; i < tmCount; i++) {
+ int chosenMove = RandomSource.nextInt(allMoves.size() - 1) + 1;
+ while (newTMs.contains(chosenMove)
+ || RomFunctions.bannedRandomMoves[chosenMove]
+ || hms.contains(chosenMove) || banned.contains(chosenMove)) {
+ chosenMove = RandomSource.nextInt(allMoves.size() - 1) + 1;
+ }
+ newTMs.add(chosenMove);
+ }
+ this.setTMMoves(newTMs);
+ }
+
+ @Override
+ public void randomizeTMHMCompatibility(boolean preferSameType) {
+ // Get current compatibility
+ Map compat = this.getTMHMCompatibility();
+ List tmHMs = new ArrayList(this.getTMMoves());
+ tmHMs.addAll(this.getHMMoves());
+ List moveData = this.getMoves();
+ for (Map.Entry compatEntry : compat.entrySet()) {
+ Pokemon pkmn = compatEntry.getKey();
+ boolean[] flags = compatEntry.getValue();
+ for (int i = 1; i <= tmHMs.size(); i++) {
+ int move = tmHMs.get(i - 1);
+ Move mv = moveData.get(move);
+ double probability = 0.5;
+ if (preferSameType) {
+ if (pkmn.primaryType.equals(mv.type)
+ || (pkmn.secondaryType != null && pkmn.secondaryType
+ .equals(mv.type))) {
+ probability = 0.9;
+ } else if (mv.type != null && mv.type.equals(Type.NORMAL)) {
+ probability = 0.5;
+ } else {
+ probability = 0.25;
+ }
+ }
+ flags[i] = (RandomSource.random() < probability);
+ }
+ }
+
+ // Set the new compatibility
+ this.setTMHMCompatibility(compat);
+ }
+
+ @Override
+ public void randomizeMoveTutorMoves(boolean noBroken) {
+ if (!this.hasMoveTutors()) {
+ return;
+ }
+ // Pick some random Move Tutor moves, excluding TMs.
+ int mtCount = this.getMoveTutorMoves().size();
+ List allMoves = this.getMoves();
+ List tms = this.getTMMoves();
+ List newMTs = new ArrayList();
+ List hms = this.getHMMoves();
+ @SuppressWarnings("unchecked")
+ List banned = noBroken ? this.getGameBreakingMoves()
+ : Collections.EMPTY_LIST;
+ for (int i = 0; i < mtCount; i++) {
+ int chosenMove = RandomSource.nextInt(allMoves.size() - 1) + 1;
+ while (newMTs.contains(chosenMove) || tms.contains(chosenMove)
+ || RomFunctions.bannedRandomMoves[chosenMove]
+ || hms.contains(chosenMove) || banned.contains(chosenMove)) {
+ chosenMove = RandomSource.nextInt(allMoves.size() - 1) + 1;
+ }
+ newMTs.add(chosenMove);
+ }
+ this.setMoveTutorMoves(newMTs);
+ }
+
+ @Override
+ public void randomizeMoveTutorCompatibility(boolean preferSameType) {
+ if (!this.hasMoveTutors()) {
+ return;
+ }
+ // Get current compatibility
+ Map compat = this.getMoveTutorCompatibility();
+ List mts = this.getMoveTutorMoves();
+ List moveData = this.getMoves();
+ for (Map.Entry compatEntry : compat.entrySet()) {
+ Pokemon pkmn = compatEntry.getKey();
+ boolean[] flags = compatEntry.getValue();
+ for (int i = 1; i <= mts.size(); i++) {
+ int move = mts.get(i - 1);
+ Move mv = moveData.get(move);
+ double probability = 0.5;
+ if (preferSameType) {
+ if (pkmn.primaryType.equals(mv.type)
+ || (pkmn.secondaryType != null && pkmn.secondaryType
+ .equals(mv.type))) {
+ probability = 0.9;
+ } else if (mv.type != null && mv.type.equals(Type.NORMAL)) {
+ probability = 0.5;
+ } else {
+ probability = 0.25;
+ }
+ }
+ flags[i] = (RandomSource.random() < probability);
+ }
+ }
+
+ // Set the new compatibility
+ this.setMoveTutorCompatibility(compat);
+
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void randomizeTrainerNames(byte[] presetNames) {
+ List[] allTrainerNames = new List[] { new ArrayList(),
+ new ArrayList() };
+ Map> trainerNamesByLength[] = new Map[] {
+ new TreeMap>(),
+ new TreeMap>() };
+ // Check for the file
+ if (FileFunctions.configExists(tnamesFile)) {
+ try {
+ Scanner sc = null;
+ if (presetNames == null) {
+ sc = new Scanner(FileFunctions.openConfig(tnamesFile),
+ "UTF-8");
+ } else {
+ sc = new Scanner(new ByteArrayInputStream(presetNames),
+ "UTF-8");
+ }
+ while (sc.hasNextLine()) {
+ String trainername = sc.nextLine().trim();
+ if (trainername.isEmpty()) {
+ continue;
+ }
+ if (trainername.startsWith("\uFEFF")) {
+ trainername = trainername.substring(1);
+ }
+ int idx = trainername.contains("&") ? 1 : 0;
+ int len = this.internalStringLength(trainername);
+ if (len <= 10) {
+ allTrainerNames[idx].add(trainername);
+ if (trainerNamesByLength[idx].containsKey(len)) {
+ trainerNamesByLength[idx].get(len).add(trainername);
+ } else {
+ List namesOfThisLength = new ArrayList();
+ namesOfThisLength.add(trainername);
+ trainerNamesByLength[idx].put(len,
+ namesOfThisLength);
+ }
+ }
+ }
+ sc.close();
+ } catch (FileNotFoundException e) {
+ // Can't read, just don't load anything
+ }
+ }
+
+ // Get the current trainer names data
+ List currentTrainerNames = this.getTrainerNames();
+ if (currentTrainerNames.size() == 0) {
+ // RBY have no trainer names
+ return;
+ }
+ TrainerNameMode mode = this.trainerNameMode();
+ int maxLength = this.maxTrainerNameLength();
+
+ // Init the translation map and new list
+ Map translation = new HashMap();
+ List