GHIDRA рдХрд╛ рдЖрдзреБрдирд┐рдХреАрдХрд░рдгред рд░рдо рд╕реЗрдЧрд╛ рдореЗрдЧрд╛ рдбреНрд░рд╛рдЗрд╡ рдХреЗ рд▓рд┐рдП рд▓реЛрдбрд░


рдЕрднрд┐рд╡рд╛рджрди, рд╕рд╛рдерд┐рдпреЛрдВред рдореИрдВрдиреЗ рдЕрднреА рддрдХ рдЦреБрд▓реЗ-рд╕реНрд░реЛрдд-рд╕реНрд░реЛрдд GHIDRA рдмрд╛рд░реЗ рдореЗрдВ рдирд╣реАрдВ рд╕реБрдирд╛ рд╣реИ, рд╢рд╛рдпрдж рдХреЗрд╡рд▓ рдПрдХ рдмрд╣рд░рд╛ / рдЕрдВрдзрд╛ / рдЧреВрдВрдЧрд╛ / рдХреЛрдИ рдЗрдВрдЯрд░рдиреЗрдЯ рд░рд┐рд╡рд░реНрд╕ рдЗрдВрдЬреАрдирд┐рдпрд░ рдирд╣реАрдВ рд╣реИред рдмреЙрдХреНрд╕ рдХреЗ рдмрд╛рд╣рд░ рдЗрд╕рдХреА рдХреНрд╖рдорддрд╛рдПрдВ рдЕрджреНрднреБрдд рд╣реИрдВ: рд╕рднреА рд╕рдорд░реНрдерд┐рдд рдкреНрд░реЛрд╕реЗрд╕рд░ рдХреЗ рд▓рд┐рдП рдбреАрдХреЙрдореНрдкреЛрд▓рд░, рдирдП рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ рдХрд╛ рд╕рд░рд▓ рдЬреЛрдбрд╝ (рдЖрдИрдЖрд░ рдореЗрдВ рд╕рдХреНрд╖рдо рд░реВрдкрд╛рдВрддрд░рдг рдХреЗ рдХрд╛рд░рдг рддрддреНрдХрд╛рд▓ рд╕рдХреНрд░рд┐рдп рд╡рд┐рдШрдЯрди рдХреЗ рд╕рд╛рде), рд▓рд┐рдкрд┐рдпреЛрдВ рдХрд╛ рдПрдХ рдЧреБрдЪреНрдЫрд╛ рдЬреЛ рдЬреАрд╡рди рдХреЛ рд╕рд░рд▓ рдмрдирд╛рддрд╛ рд╣реИ, Undo / Redo рдХрд░рдиреЗ рдХреА рд╕рдВрднрд╛рд╡рдирд╛ / рдФрд░ рдпрд╣ рдкреНрд░рджрд╛рди рдХреА рдЧрдИ рд╕рднреА рд╕реБрд╡рд┐рдзрд╛рдУрдВ рдХрд╛ рдХреЗрд╡рд▓ рдПрдХ рдмрд╣реБрдд рдЫреЛрдЯрд╛ рд╣рд┐рд╕реНрд╕рд╛ рд╣реИред рдпрд╣ рдХрд╣рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рдореИрдВ рдкреНрд░рднрд╛рд╡рд┐рдд рдерд╛, рд▓рдЧрднрдЧ рдХреБрдЫ рднреА рдирд╣реАрдВ рдХрд╣рдирд╛ рд╣реИред


рдЗрд╕рд▓рд┐рдП, рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рдореИрдВ рдЖрдкрдХреЛ рдмрддрд╛рдирд╛ рдЪрд╛рд╣реВрдВрдЧрд╛ рдХрд┐ рдореИрдВрдиреЗ GHIDRA рд▓рд┐рдП рдЕрдкрдирд╛ рдкрд╣рд▓рд╛ рдореЙрдбреНрдпреВрд▓ рдХреИрд╕реЗ рд▓рд┐рдЦрд╛ - Sega Mega Drive / Genesis рд▓рд┐рдП рдЧреЗрдо рдХреЗ рд▓рд┐рдП рдПрдХ рд░рдо рд▓реЛрдбрд░ред рдЗрд╕реЗ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдореБрдЭреЗ рдЬрд╝рд░реВрд░рдд рдереА ... рдмрд╕ рдХреБрдЫ рдШрдВрдЯреЗ! рдЪрд▓реЛ рдЪрд▓рддреЗ рд╣реИрдВред


рд▓реЗрдХрд┐рди рдЖрдИрдбреАрдП рдХрд╛ рдХреНрдпрд╛?

рдореИрдВрдиреЗ IDA рд▓рд┐рдП рдбрд╛рдЙрдирд▓реЛрдбрд░ рд▓рд┐рдЦрдиреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рд╕рдордЭрдиреЗ рдореЗрдВ рдХреБрдЫ рджрд┐рди рдмрд┐рддрд╛рдПред рддрдм рдпрд╣ рд╕рдВрд╕реНрдХрд░рдг 6.5 рдерд╛, рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЙрди рджрд┐рдиреЛрдВ рдореЗрдВ рдПрд╕рдбреАрдХреЗ рдкреНрд░рд▓реЗрдЦрди рдХреЗ рд╕рд╛рде рдмрд╣реБрдд рд╕рд╛рд░реА рд╕рдорд╕реНрдпрд╛рдПрдВ рдереАрдВред


рд╣рдо рд╡рд┐рдХрд╛рд╕ рдХрд╛ рдорд╛рд╣реМрд▓ рддреИрдпрд╛рд░ рдХрд░рддреЗ рд╣реИрдВ


GHIDRA рдбреЗрд╡рд▓рдкрд░реНрд╕ рдиреЗ рд▓рдЧрднрдЧ рд╣рд░ рдЪреАрдЬ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╕реЛрдЪрд╛ ( рдЗрд▓рдлрд╛рдХ , рдЖрдк рдкрд╣рд▓реЗ рдХрд╣рд╛рдВ рдереЗ?)ред рдФрд░, рдирдИ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рдЖрд╕рд╛рди рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдЙрдиреНрд╣реЛрдВрдиреЗ Eclipse - GhidraDev рд▓рд┐рдП рдПрдХ рдкреНрд▓рдЧ-рдЗрди рд╡рд┐рдХрд╕рд┐рдд рдХрд┐рдпрд╛, рдЬреЛ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ "рд░рд╛рдЗрдЯ" рдХреЛрдб рд▓рд┐рдЦрдиреЗ рдореЗрдВ рдорджрдж рдХрд░рддрд╛ рд╣реИ ред рдкреНрд▓рдЧрдЗрди рд╡рд┐рдХрд╛рд╕ рдХреЗ рдорд╛рд╣реМрд▓ рдореЗрдВ рдПрдХреАрдХреГрдд рд╣реИ, рдФрд░ рдЖрдкрдХреЛ рд╕реНрдХреНрд░рд┐рдкреНрдЯ, рд▓реЛрдбрд░, рдкреНрд░реЛрд╕реЗрд╕рд░ рдореЙрдбреНрдпреВрд▓ рдФрд░ рдЙрдирдХреЗ рд▓рд┐рдП рдПрдХреНрд╕рдЯреЗрдВрд╢рди рдХреЗ рд╕рд╛рде-рд╕рд╛рде рдирд┐рд░реНрдпрд╛рдд рдореЙрдбреНрдпреВрд▓ рдмрдирд╛рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рд╕рд╛рде рд╣реА рдирд┐рд░реНрдпрд╛рдд рдореЙрдбреНрдпреВрд▓ (рдЬреИрд╕рд╛ рдХрд┐ рдореИрдВ рд╕рдордЭрддрд╛ рд╣реВрдВ, рдпрд╣ рдПрдХ рдкрд░рд┐рдпреЛрдЬрдирд╛ рд╕реЗ рдбреЗрдЯрд╛ рдХрд╛ рдХреБрдЫ рдкреНрд░рдХрд╛рд░ рд╣реИ) рдХреБрдЫ рд╣реА рдХреНрд▓рд┐рдХ рдХреЗ рд╕рд╛рдеред


рдкреНрд▓рдЧрдЗрди рдХреЛ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, Java рд▓рд┐рдП Eclipse рдбрд╛рдЙрдирд▓реЛрдб рдХрд░реЗрдВ, Help рдХреНрд▓рд┐рдХ рдХрд░реЗрдВ -> Install New Software... , рдлрд┐рд░ Add рдмрдЯрди рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░реЗрдВ, рдФрд░ Archive... рдмрдЯрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдкреНрд▓рдЧрдЗрди рдХреЗ рд╕рд╛рде рд╕рдВрдЧреНрд░рд╣ рдЪрдпрди рд╕рдВрд╡рд╛рдж рдЦреЛрд▓реЗрдВред GhidraDev рд╕рд╛рде рд╕рдВрдЧреНрд░рд╣ $(GHIDRA)/Extensions/Eclipse/GhidraDev ред рдЗрд╕реЗ рдЪреБрдиреЗрдВ, Add рдмрдЯрди рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░реЗрдВред



рджрд┐рдЦрд╛рдИ рджреЗрдиреЗ рд╡рд╛рд▓реА рд╕реВрдЪреА рдореЗрдВ, Ghidra рдкрд░ рдПрдХ daw Ghidra , Next > рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░реЗрдВ Next > , рд╕рдордЭреМрддреЛрдВ рд╕реЗ рд╕рд╣рдордд рд╣реЛрдВ, Install Anyway рдХреНрд▓рд┐рдХ Install Anyway (рдХреНрдпреЛрдВрдХрд┐ рдкреНрд▓рдЧрдЗрди рдХрд╛ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдирд╣реАрдВ рд╣реИ), рдФрд░ Eclipse рдкреБрдирдГ рдЖрд░рдВрдн рдХрд░реЗрдВред



рдХреБрд▓ рдорд┐рд▓рд╛рдХрд░, рдПрдХ рдирдпрд╛ GhidraDev рдЖрдЗрдЯрдо рдЖрдкрдХреА рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдХреЗ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдирд┐рд░реНрдорд╛рдг рдФрд░ рд╡рд┐рддрд░рдг рдХреЗ рд▓рд┐рдП IDE GhidraDev рдореЗрдВ рджрд┐рдЦрд╛рдИ рджреЗрдЧрд╛ (рдмреЗрд╢рдХ, рдЖрдк рдирдП Eclipse рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдХреЗ рд▓рд┐рдП рд╕рд╛рдорд╛рдиреНрдп рд╡рд┐рдЬрд╝рд╛рд░реНрдб рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рднреА рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ)ред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рд╡рд┐рдХрд╕рд┐рдд рдкреНрд▓рдЧ-рдЗрди рдпрд╛ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЛ рдбреАрдмрдЧ рдХрд░рдиреЗ рдХрд╛ рдЕрд╡рд╕рд░ рд╣реИред



рдФрд░ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдбрд┐рдмрдЧрд░ рдХрд╣рд╛рдВ рд╣реИ?

рдХреНрдпрд╛ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ GHIDRA рд╕рд╛рде рд╕реНрдерд┐рддрд┐ рдХреЛ GHIDRA рд╣реИ рдХрдордмрдЦреНрдд рдХрд░реНрдХрд╢ рдкреНрд░рдЪрд╛рд░ рд▓реЗрдЦ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рд▓рдЧрднрдЧ рдПрдХ рд╣реА рд╕рд╛рдордЧреНрд░реА рд╣реЛрддреА рд╣реИ, рдЬреЛ, рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╕рдЪ рдирд╣реАрдВ рд╣реИред рдПрдХ рдЙрджрд╛рд╣рд░рдг? рд╣рд╛рдБ, рдХреГрдкрдпрд╛:


рдЙрдкрдХрд░рдг рдХрд╛ рд╡рд░реНрддрдорд╛рди рд╕рдВрд╕реНрдХрд░рдг 9.0 рд╣реИред рдФрд░ рдЯреВрд▓ рдореЗрдВ рдХреНрд░рд┐рдкреНрдЯреИрдирд╛рд▓рд┐рд╕рд┐рд╕ рдЬреИрд╕реЗ рдЕрддрд┐рд░рд┐рдХреНрдд рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЛ рд╢рд╛рдорд┐рд▓ рдХрд░рдиреЗ рдХреЗ рд╡рд┐рдХрд▓реНрдк рд╣реИрдВ, рдУрд▓реАрдбрдмрдЧ рдХреЗ рд╕рд╛рде рдмрд╛рддрдЪреАрдд, рдШрд┐рджреНрд░рд╛ рдбреАрдмрдЧрд░ред

рдФрд░ рдпрд╣ рд╕рдм рдХрд╣рд╛рдБ рд╣реИ? рдирд╣реАрдВ!


рджреВрд╕рд░рд╛ рдмрд┐рдВрджреБ: рдЦреБрд▓рд╛рдкрдиред рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдпрд╣ рд▓рдЧрднрдЧ рд╡рд╣рд╛рдБ рд╣реИ, рд▓реЗрдХрд┐рди рд▓рдЧрднрдЧ рдХреЛрдИ рднреА рдирд╣реАрдВ рд╣реИред GHIDRA рдореЗрдВ Java рдореЗрдВ рд▓рд┐рдЦреЗ рдЧрдП рдШрдЯрдХреЛрдВ рдХреЗ рд╕реНрд░реЛрдд рд╕реНрд░реЛрдд рд╣реЛрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдпрджрд┐ рдЖрдк Gradle рд▓рд┐рдкрд┐рдпреЛрдВ рдХреЛ рджреЗрдЦрддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдЧреБрдкреНрдд рд╕реЗ рдмрд╛рд╣рд░реА рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдХреЗ рдПрдХ рд╕рдореВрд╣ рдкрд░ рдирд┐рд░реНрднрд░рддрд╛рдПрдВ рд╣реИрдВ рдкреНрд░рдпреЛрдЧрд╢рд╛рд▓рд╛ NSA рд░рд┐рдкреЙрдЬрд┐рдЯрд░реАред
рд▓реЗрдЦрди рдХреЗ рд╕рдордп, рдХреЛрдИ рдбрд┐рдХрдВрдкрд╛рдЗрд▓рд░ рдФрд░ SLEIGH (рдпрд╣ рдЖрдИрдЖрд░ рдХреЗ рд▓рд┐рдП рдкреНрд░реЛрд╕реЗрд╕рд░ рдореЙрдбреНрдпреВрд▓ рдФрд░ рд░реВрдкрд╛рдВрддрд░рдг рдХреЗ рд╡рд┐рд╡рд░рдгреЛрдВ рдХреЛ рд╕рдВрдХрд▓рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЙрдкрдпреЛрдЧрд┐рддрд╛ рд╣реИ)ред


рдЦреИрд░ рдУрд╣ рдареАрдХ рд╣реИ, рдореИрдВ рдХреБрдЫ рд╕реЗ рд╡рд┐рдЪрд▓рд┐рдд рд╣реВрдБред


рддреЛ, рдЖрдЗрдП Eclipse рдореЗрдВ рдПрдХ рдирдИ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдмрдирд╛рдПрдВред


рд▓реЛрдбрд░ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдмрдирд╛рдПрдВ


GhidraDev -> New -> Ghidra Module Project...


рд╣рдо рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рдирд╛рдо рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░рддреЗ рд╣реИрдВ (рд╣рдо рдЗрд╕ рдмрд╛рдд рдХрд╛ рдзреНрдпрд╛рди рд░рдЦрддреЗ рд╣реИрдВ рдХрд┐ Loader рдкреНрд░рдХрд╛рд░ рдХреЗ рд╢рдмреНрджреЛрдВ рдХреЛ рдлрд╝рд╛рдЗрд▓ рдирд╛рдореЛрдВ рд╕реЗ рдЪрд┐рдкрдХрд╛рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдФрд░ рдХреНрд░рдо рдореЗрдВ sega_loaderLoader.java рдЬреИрд╕реА рдХреБрдЫ рднреА рдкреНрд░рд╛рдкреНрдд рдирд╣реАрдВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдЙрдиреНрд╣реЗрдВ рддрджрдиреБрд╕рд╛рд░ рдирд╛рдо рджреЗрддреЗ рд╣реИрдВ)ред



Next > рдХреНрд▓рд┐рдХ рдХрд░реЗрдВред рдпрд╣рд╛рдВ рд╣рдо рдЙрди рд╢реНрд░реЗрдгрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рдордиреЗ рдбреМрд╕ рд░рдЦрддреЗ рд╣реИрдВ рдЬрд┐рдирдХреА рд╣рдореЗрдВ рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рдореЗрд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдпрд╣ рдХреЗрд╡рд▓ рдПрдХ Loader ред Next > рдХреНрд▓рд┐рдХ рдХрд░реЗрдВред



рдпрд╣рд╛рдВ рд╣рдо рд╕рд╛рде рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдХреЗ рд▓рд┐рдП рдкрде рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░рддреЗ рд╣реИрдВред Next > рдХреНрд▓рд┐рдХ рдХрд░реЗрдВред



GHIDRA рдкрд╛рдЗрдерди ( GHIDRA рдорд╛рдзреНрдпрдо рд╕реЗ) рдореЗрдВ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рд▓рд┐рдЦрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдореИрдВ Java рдореЗрдВ рд▓рд┐рдЦреВрдВрдЧрд╛, рдЗрд╕рд▓рд┐рдП рдореИрдВ рдПрдХ рджрд╛рд╡ рдирд╣реАрдВ рд▓рдЧрд╛рддрд╛ рд╣реВрдВред рдореИрдВ Finish рджрдмрд╛рддрд╛ рд╣реВрдВред



рдПрдХ рдХреЛрдб рд▓рд┐рдЦрдирд╛


рдЦрд╛рд▓реА рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдЯреНрд░реА рдкреНрд░рднрд╛рд╡рд╢рд╛рд▓реА рд▓рдЧрддрд╛ рд╣реИ:



java рдХреЛрдб рд╡рд╛рд▓реА рд╕рднреА рдлрд╛рдЗрд▓реЗрдВ /src/main/java рд╢рд╛рдЦрд╛ рдореЗрдВ рд╣реИрдВ:



getName ()


рдЖрд░рдВрдн рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЪрд▓рд┐рдП рдмреВрдЯрд▓реЛрдбрд░ рдХреЗ рд▓рд┐рдП рдПрдХ рдирд╛рдо рдЪреБрдиреЗрдВред getName() рд╡рд┐рдзрд┐ рдЗрд╕реЗ рд▓реМрдЯрд╛рддреА рд╣реИ:


 @Override public String getName() { return "Sega Mega Drive / Genesis Loader"; } 

findSupportedLoadSpecs ()


findSupportedLoadSpecs() рд╡рд┐рдзрд┐ рддрдп рдХрд░рддреА рд╣реИ (рдмрд╛рдЗрдирд░реА рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдирд┐рд╣рд┐рдд рдбреЗрдЯрд╛ рдХреЗ рдЖрдзрд╛рд░ рдкрд░) рдЬреЛ рдкреНрд░реЛрд╕реЗрд╕рд░ рдореЙрдбреНрдпреВрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ findSupportedLoadSpecs() рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП (рд╕рд╛рде рд╣реА IDA )ред GHIDRA рд╢рдмреНрджрд╛рд╡рд▓реА рдореЗрдВ GHIDRA рдЗрд╕реЗ Compiler Language рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИред рдЗрд╕рдореЗрдВ рд╢рд╛рдорд┐рд▓ рд╣реИрдВ: рдкреНрд░реЛрд╕реЗрд╕рд░, рдПрдВрдбрд┐рдпрдирдиреЗрд╕, рдмрд┐рдЯрдиреЗрд╕ рдФрд░ рдХрдВрдкрд╛рдЗрд▓рд░ (рдпрджрд┐ рдЬреНрдЮрд╛рдд рд╣реЛ)ред


рдпрд╣ рд╡рд┐рдзрд┐ рд╕рдорд░реНрдерд┐рдд рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ рдФрд░ рднрд╛рд╖рд╛рдУрдВ рдХреА рд╕реВрдЪреА рд▓реМрдЯрд╛рддреА рд╣реИред рдпрджрд┐ рдбреЗрдЯрд╛ рдЧрд▓рдд рдкреНрд░рд╛рд░реВрдк рдореЗрдВ рд╣реИ, рддреЛ рд╣рдо рдмрд╕ рдПрдХ рдЦрд╛рд▓реА рд╕реВрдЪреА рд▓реМрдЯрд╛рддреЗ рд╣реИрдВред


рддреЛ, Sega Mega Drive рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рд╢рдмреНрдж " SEGA " рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рдмрд╛рд░ рд╣реЗрдбрд░ рдХреЗ рдСрдлрд╕реЗрдЯ 0x100 рдкрд░ рдореМрдЬреВрдж рд╣реЛрддрд╛ рд╣реИ (рдпрд╣ рдПрдХ рд╢рд░реНрдд рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди 99% рдорд╛рдорд▓реЛрдВ рдореЗрдВ рдкреВрд░рд╛ рд╣реЛрддрд╛ рд╣реИ)ред рдЖрдкрдХреЛ рдпрд╣ рдЬрд╛рдВрдЪрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рдпрд╣ рд▓рд╛рдЗрди рдЖрдпрд╛рддрд┐рдд рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рд╣реИред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, ByteProvider provider рдХреЛ findSupportedLoadSpecs() ByteProvider provider , рдЬрд┐рд╕рдХреЗ рд╕рд╛рде рд╣рдо рдлрд╝рд╛рдЗрд▓ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░реЗрдВрдЧреЗред


рдХрд┐рд╕реА рдлрд╝рд╛рдЗрд▓ рд╕реЗ рдбреЗрдЯрд╛ рдкрдврд╝рдиреЗ рдХреА рд╕реБрд╡рд┐рдзрд╛ рдХреЗ рд▓рд┐рдП рд╣рдо рдПрдХ BinaryReader рдСрдмреНрдЬреЗрдХреНрдЯ рдмрдирд╛рддреЗ рд╣реИрдВ:


 BinaryReader reader = new BinaryReader(provider, false); 

рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ false рддрд░реНрдХ Big Endian рдХрд╛ рдЙрдкрдпреЛрдЧ рдкрдврд╝рддреЗ рд╕рдордп рдЗрдВрдЧрд┐рдд рдХрд░рддрд╛ рд╣реИред рдЕрдм рд░реЗрдЦрд╛ рдкрдврд╝рддреЗ рд╣реИрдВред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, reader рдСрдмреНрдЬреЗрдХреНрдЯ рдХреА readAsciiString(offset, size) рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ:


 reader.readAsciiString(0x100, 4).equals(new String("SEGA")) 

рдпрджрд┐ equals() true , рддреЛ рд╣рдо Segov рд░рдо рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рдФрд░ рд╕реВрдЪреА рдореЗрдВ List<LoadSpec> loadSpecs = new ArrayList<>(); рдореЛрдЯреЛрд░реЛрд▓рд╛ m68k рдЬреЛрдбрд╝рдирд╛ рд╕рдВрднрд╡ рд╣реЛрдЧрд╛ред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдкреНрд░рдХрд╛рд░ рдХреА рдПрдХ рдирдИ рдСрдмреНрдЬреЗрдХреНрдЯ рдмрдирд╛рдПрдВ LoadSpec , рдЬрд┐рд╕рдХрд╛ рдирд┐рд░реНрдорд╛рддрд╛ рд▓реЛрдбрд░ рдСрдмреНрдЬреЗрдХреНрдЯ (рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, this ) рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддрд╛ рд╣реИ, рдПрдХ ImageBase рдЬрд┐рд╕рдореЗрдВ ROM рд▓реЛрдб рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдкреНрд░рдХрд╛рд░ рдХрд╛ рдПрдХ рдСрдмреНрдЬреЗрдХреНрдЯ LanguageCompilerSpecPair рдФрд░ рдПрдХ рдЭрдВрдбрд╛ - рдХреНрдпрд╛ рдпрд╣ LoadSpec рд╕реВрдЪреА рдореЗрдВ рджреВрд╕рд░реЛрдВ рдХреЗ рдмреАрдЪ LoadSpec рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ (рд╣рд╛рдВ, рд╕реВрдЪреА рдореЗрдВ рд╣рд╛рдВ) рдПрдХ рд╕реЗ рдЕрдзрд┐рдХ LoadSpec рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ)ред


LanguageCompilerSpecPair рд▓рд┐рдП рдирд┐рд░реНрдорд╛рддрд╛ рдкреНрд░рд╛рд░реВрдк рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рд╣реИ:


  1. рдкрд╣рд▓рд╛ рддрд░реНрдХ languageID , " ProcessorName: Endianness: рдмрд┐рдЯреНрд╕: ExactCpu " рд░реВрдк рдХреА рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧред рдореЗрд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдпрд╣ " 68000: BE: 32: MC68020 " рд▓рд╛рдЗрди рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП (рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ, рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ MC68000 рдбрд┐рд▓реАрд╡рд░реА рдореЗрдВ рд╢рд╛рдорд┐рд▓ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рдРрд╕реА рд╕рдорд╕реНрдпрд╛ рдирд╣реАрдВ рд╣реИ)ред ExactCpu default рд╣реЛ рд╕рдХрддрд╛ default
  2. рджреВрд╕рд░рд╛ рддрд░реНрдХ, compilerSpecID , рдЬрд┐рд╕реЗ рдЖрдкрдХреЛ рдпрд╣рд╛рдВ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдХреЛ рдЦреЛрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдореЗрдВ рдкреНрд░реЛрд╕реЗрд╕рд░ рд╡рд┐рд╡рд░рдг ( $(GHIDRA)/Ghidra/Processors/68000/data/languages ) рдХреЗ рд╕рд╛рде 68000.opinion рдлрд╝рд╛рдЗрд▓ рдореЗрдВ 68000.opinion ред рд╣рдо рджреЗрдЦрддреЗ рд╣реИрдВ рдХрд┐ рдХреЗрд╡рд▓ default рдпрд╣рд╛рдБ рдЗрдВрдЧрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рджрд░рдЕрд╕рд▓, рд╣рдо рдЗрд╕рдХрд╛ рд╕рдВрдХреЗрдд рджреЗрддреЗ рд╣реИрдВ

рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреЛрдб рд╣реИрдВ (рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдЕрдм рддрдХ рдХреБрдЫ рднреА рдЬрдЯрд┐рд▓ рдирд╣реАрдВ рд╣реИ):


 @Override public Collection<LoadSpec> findSupportedLoadSpecs(ByteProvider provider) throws IOException { List<LoadSpec> loadSpecs = new ArrayList<>(); BinaryReader reader = new BinaryReader(provider, false); if (reader.readAsciiString(0x100, 4).equals(new String("SEGA"))) { loadSpecs.add(new LoadSpec(this, 0, new LanguageCompilerSpecPair("68000:BE:32:MC68020", "default"), true)); } return loadSpecs; } 

рдореЙрдбреНрдпреВрд▓ рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ рдЖрдИрдбреАрдП рдФрд░ GHIDRA рдХреЗ рдмреАрдЪ рдХрд╛ рдЕрдВрддрд░

рдПрдХ рдЕрдВрддрд░ рд╣реИ, рдФрд░ рдпрд╣ рдЕрднреА рднреА рдмрд╣реБрдд рдордЬрдмреВрдд рд╣реИред GHIDRA рдЖрдк рдПрдХ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВ рдЬреЛ рд╡рд┐рднрд┐рдиреНрди рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░, рдЕрд▓рдЧ-рдЕрд▓рдЧ рдбреЗрдЯрд╛ рд╕реНрд╡рд░реВрдкреЛрдВ рдХреЛ рд╕рдордЭреЗрдЧрд╛, рдПрдХ рд▓реЛрдбрд░, рдПрдХ рдкреНрд░реЛрд╕реЗрд╕рд░ рдореЙрдбреНрдпреВрд▓, рдбрд┐рдХрдореНрдкрд╛рдЗрд▓рд░ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдФрд░ рдЕрдиреНрдп рдЕрдЪреНрдЫрд╛рдИрдпрд╛рдВ рд╣реЛрдЧреАред


IDA , рдпрд╣ рдкреНрд░рддреНрдпреЗрдХ рдкреНрд░рдХрд╛рд░ рдХреЗ рдРрдб-рдСрди рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрд▓рдЧ рдкрд░рд┐рдпреЛрдЬрдирд╛ рд╣реИред


рдХрд┐рддрдирд╛ рдЕрдзрд┐рдХ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ? рдореЗрд░реА рд░рд╛рдп рдореЗрдВ, GHIDRA - рдХрдИ рдмрд╛рд░!


рд▓реЛрдб ()


рдЗрд╕ рдкрджреНрдзрддрд┐ рдореЗрдВ, рд╣рдо рд╕реЗрдЧрдореЗрдВрдЯ рдмрдирд╛рдПрдВрдЧреЗ, рдЗрдирдкреБрдЯ рдбреЗрдЯрд╛ рдкреНрд░реЛрд╕реЗрд╕ рдХрд░реЗрдВрдЧреЗ, рдХреЛрдб рдФрд░ рдкрд╣рд▓реЗ рд╕реЗ рдЬреНрдЮрд╛рдд рд▓реЗрдмрд▓ рдмрдирд╛рдПрдВрдЧреЗред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╡рд╕реНрддреБрдУрдВ рдХреЛ рдкреНрд░рд╡реЗрд╢ рджреНрд╡рд╛рд░ рдкрд░ рд╣рдорд╛рд░реА рдорджрдж рдХреЗ рд▓рд┐рдП рдкреНрд░рд╕реНрддреБрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ:


  1. ByteProvider provider : рд╣рдо рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЙрд╕реЗ рдЬрд╛рдирддреЗ рд╣реИрдВред рдмрд╛рдЗрдирд░реА рдлрд╝рд╛рдЗрд▓ рдбреЗрдЯрд╛ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдирд╛
  2. LoadSpec loadSpec : рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ рдХрд╛ рд╡рд┐рдирд┐рд░реНрджреЗрд╢ LoadSpec loadSpec рдХреЗ рдЖрдпрд╛рдд рдЪрд░рдг рдХреЗ рджреМрд░рд╛рди findSupportedLoadSpecs рдЧрдпрд╛ рд╣реИ findSupportedLoadSpecs рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЧрдпрд╛ findSupportedLoadSpecs ред рдпрд╣ рдЖрд╡рд╢реНрдпрдХ рд╣реИ рдпрджрд┐, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╣рдо рдПрдХ рдореЙрдбреНрдпреВрд▓ рдореЗрдВ рдХрдИ рдбреЗрдЯрд╛ рдкреНрд░рд╛рд░реВрдкреЛрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реИрдВред рдЖрд░рд╛рдо рд╕реЗ
  3. List<Option> options : List<Option> options рд╕реВрдЪреА (рдХрд╕реНрдЯрдо рд╕рд╣рд┐рдд)ред рдореИрдВрдиреЗ рдЕрднреА рддрдХ рдЙрдирдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдирд╛ рдирд╣реАрдВ рд╕реАрдЦрд╛ рд╣реИ
  4. Program program : рдореБрдЦреНрдп рд╡рд╕реНрддреБ рдЬреЛ рд╕рднреА рдЖрд╡рд╢реНрдпрдХ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рддрдХ рдкрд╣реБрдВрдЪ рдкреНрд░рджрд╛рди рдХрд░рддреА рд╣реИ: рд▓рд┐рд╕реНрдЯрд┐рдВрдЧ, рдкрддрд╛ рд╕реНрдерд╛рди, рдЦрдВрдб, рд▓реЗрдмрд▓, рд╕рд░рдгрд┐рдпрд╛рдВ рдмрдирд╛рдирд╛, рдЖрджрд┐ред
  5. MemoryConflictHandler handler рдФрд░ TaskMonitor monitor : рд╣рдореЗрдВ рд╢рд╛рдпрдж рд╣реА рдХрднреА рдЙрдирдХреЗ рд╕рд╛рде рд╕реАрдзреЗ рдХрд╛рдо рдХрд░рдирд╛ рдкрдбрд╝рддрд╛ рд╣реИ (рдЖрдорддреМрд░ рдкрд░, рдЗрди рд╡рд╕реНрддреБрдУрдВ рдХреЛ рддреИрдпрд╛рд░ рддрд░реАрдХреЛрдВ рд╕реЗ рдЧреБрдЬрд░рдирд╛)
  6. MessageLog log : рд▓рдХрдбрд╝рд╣рд╛рд░рд╛

рддреЛ, рд╢реБрд░реБрдЖрдд рдХреЗ рд▓рд┐рдП, рдЖрдЗрдП рдХреБрдЫ рдСрдмреНрдЬреЗрдХреНрдЯ рдмрдирд╛рдПрдВ рдЬреЛ GHIDRA рд╕рдВрд╕реНрдерд╛рдУрдВ рдФрд░ рдореМрдЬреВрджрд╛ рдбреЗрдЯрд╛ рдХреЗ рд╕рд╛рде рд╣рдорд╛рд░реЗ рдХрд╛рдо рдХреЛ рд╕рд░рд▓ GHIDRA ред рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ, рд╣рдореЗрдВ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ BinaryReader рдЖрд╡рд╢реНрдпрдХрддрд╛ BinaryReader :


 BinaryReader reader = new BinaryReader(provider, false); 

рдЕрдЧрд▓рд╛ред рдпрд╣ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдмрд╣реБрдд рдЙрдкрдпреЛрдЧреА рд╣реЛрдЧрд╛ рдФрд░ FlatProgramAPI рд╡рд░реНрдЧ рдХреЗ рд▓рдЧрднрдЧ рдкреВрд░реЗ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рд╕рд░рд▓ рдХрд░реЗрдЧрд╛ (рдЖрдк рдмрд╛рдж рдореЗрдВ рджреЗрдЦреЗрдВрдЧреЗ рдХрд┐ рдЖрдк рдЗрд╕рдХреЗ рд╕рд╛рде рдХреНрдпрд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ):


 FlatProgramAPI fpa = new FlatProgramAPI(program, monitor); 

рд░рдо рд╣реЗрдбрд┐рдВрдЧ


рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдпрд╣ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░реЗрдВрдЧреЗ рдХрд┐ рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рд╕реЗрдЧрд╛ рд░рдо рдХреА рд╣реЗрдбрд┐рдВрдЧ рдХреНрдпрд╛ рд╣реИред рдкрд╣рд▓реЗ 0x100 рдмрд╛рдЗрдЯреНрд╕ рдореЗрдВ рд╡реИрдХреНрдЯрд░реЛрдВ рдХреЗ рд▓рд┐рдП 64 DivideByZero рдкреЙрдЗрдВрдЯрд░реНрд╕ рдХреА рдПрдХ рддрд╛рд▓рд┐рдХрд╛ рд╣реЛрддреА рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП: Reset , Trap , DivideByZero , VBLANK рдФрд░ рдЕрдиреНрдпред


рдЗрд╕рдХреЗ рдмрд╛рдж рд░реЛрдорд╛, рдХреНрд╖реЗрддреНрд░реЛрдВ, ROM рдФрд░ RAM рдмреНрд▓реЙрдХреЛрдВ рдХреА рд╢реБрд░реБрдЖрдд рдФрд░ рдЕрдВрдд рдХреЗ рдкрддреЗ рдХреЗ рд╕рд╛рде рд╕рдВрд░рдЪрдирд╛ рдЖрддреА рд╣реИ, рдЪреЗрдХрдмреЙрдХреНрд╕ (рдХреНрд╖реЗрддреНрд░ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреЗ рдЕрдиреБрд░реЛрдз рдкрд░ рдЪреЗрдХ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рди рдХрд┐ рдЙрдкрд╕рд░реНрдЧ) рдФрд░ рдЕрдиреНрдп рдЬрд╛рдирдХрд╛рд░реАред


рдЖрдЗрдП рдЗрди рд╕рдВрд░рдЪрдирд╛рдУрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП java рдХрдХреНрд╖рд╛рдПрдВ рдмрдирд╛рдПрдВ, рд╕рд╛рде рд╣реА рдЙрди рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд┐рдиреНрд╣реЗрдВ рд╕рдВрд░рдЪрдирд╛рдУрдВ рдХреА рд╕реВрдЪреА рдореЗрдВ рдЬреЛрдбрд╝рд╛ рдЬрд╛рдПрдЧрд╛ред


VectorsTable


рд╣рдо рдПрдХ рдирдпрд╛ рд╡рд░реНрдЧ VectorsTable , рдФрд░, рдзреНрдпрд╛рди рджреЗрддреЗ рд╣реИрдВ, рд╣рдо рд╕рдВрдХреЗрдд рджреЗрддреЗ рд╣реИрдВ рдХрд┐ рдпрд╣ StructConverter рдЗрдВрдЯрд░рдлреЗрд╕ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИред рдЗрд╕ рд╡рд░реНрдЧ рдореЗрдВ рд╣рдо рд╡реИрдХреНрдЯрд░ рдХреЗ рдкрддреЗ (рднрд╡рд┐рд╖реНрдп рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХреЗ рд▓рд┐рдП) рдФрд░ рдЙрдирдХреЗ рдирд╛рдо рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░реЗрдВрдЧреЗред



рд╣рдо рд╡реЗрдХреНрдЯрд░ рдирд╛рдореЛрдВ рдФрд░ рдЙрдирдХреА рд╕рдВрдЦреНрдпрд╛ рдХреА рдПрдХ рд╕реВрдЪреА рдШреЛрд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВ:


 private static final int VECTORS_SIZE = 0x100; private static final int VECTORS_COUNT = VECTORS_SIZE / 4; private static final String[] VECTOR_NAMES = { "SSP", "Reset", "BusErr", "AdrErr", "InvOpCode", "DivBy0", "Check", "TrapV", "GPF", "Trace", "Reserv0", "Reserv1", "Reserv2", "Reserv3", "Reserv4", "BadInt", "Reserv10", "Reserv11", "Reserv12", "Reserv13", "Reserv14", "Reserv15", "Reserv16", "Reserv17", "BadIRQ", "IRQ1", "EXT", "IRQ3", "HBLANK", "IRQ5", "VBLANK", "IRQ7", "Trap0", "Trap1", "Trap2", "Trap3", "Trap4", "Trap5", "Trap6", "Trap7", "Trap8", "Trap9", "Trap10", "Trap11", "Trap12", "Trap13","Trap14", "Trap15", "Reserv30", "Reserv31", "Reserv32", "Reserv33", "Reserv34", "Reserv35", "Reserv36", "Reserv37", "Reserv38", "Reserv39", "Reserv3A", "Reserv3B", "Reserv3C", "Reserv3D", "Reserv3E", "Reserv3F" }; 

рд╣рдо рдкрддреЗ рдФрд░ рд╡реЗрдХреНрдЯрд░ рдирд╛рдо рдХреЗ рднрдВрдбрд╛рд░рдг рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрд▓рдЧ рд╡рд░реНрдЧ рдмрдирд╛рддреЗ рд╣реИрдВ:


 package sega; import ghidra.program.model.address.Address; public class VectorFunc { private Address address; private String name; public VectorFunc(Address address, String name) { this.address = address; this.name = name; } public Address getAddress() { return address; } public String getName() { return name; } } 

рд╡реИрдХреНрдЯрд░ рдХреА рд╕реВрдЪреА vectors рд╕рд░рдгреА рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХреА рдЬрд╛рдПрдЧреА:


 private VectorFunc[] vectors; 

рдирд┐рд░реНрдорд╛рддрд╛ рдХреЗ рд▓рд┐рдП VectorsTable рд╣реЛрдЧрд╛:


  1. FlatProgramAPI fpa рд╣рд╛рдЗрдбреНрд░рд╛ рдХреЗ Address рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░ рдХреЗ рд▓рд┐рдП long рдкрддреЗ рдХреЛ рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП FlatProgramAPI fpa (рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдпрд╣ рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░ рдкрддреЗ рдХреЗ рд╕рд░рд▓ рд╕рдВрдЦреНрдпрд╛рддреНрдордХ рдорд╛рди рдХреЛ рдХрд┐рд╕реА рдЕрдиреНрдп рдЪрд┐рдк рд╕реЗ FlatProgramAPI fpa рдкреВрд░рдХ рдХрд░рддрд╛ рд╣реИ - рдкрддрд╛ рд╕реНрдерд╛рди)
  2. BinaryReader reader - рд░реАрдбрд┐рдВрдЧ рдпрд╛рд░реНрдб

toAddr() рдСрдмреНрдЬреЗрдХреНрдЯ рдореЗрдВ рдПрдХ toAddr() рд╡рд┐рдзрд┐ рд╣реИ, рдФрд░ reader рдиреЗ setPointerIndex() рдФрд░ readNextUnsignedInt() ред рд╕рд┐рджреНрдзрд╛рдВрдд рд░реВрдк рдореЗрдВ, рдЕрдзрд┐рдХ рдХреБрдЫ рднреА рдЖрд╡рд╢реНрдпрдХ рдирд╣реАрдВ рд╣реИред рд╣рдореЗрдВ рдХреЛрдб рдорд┐рд▓рддрд╛ рд╣реИ:


 public VectorsTable(FlatProgramAPI fpa, BinaryReader reader) throws IOException { if (reader.length() < VECTORS_COUNT) { return; } reader.setPointerIndex(0); vectors = new VectorFunc[VECTORS_COUNT]; for (int i = 0; i < VECTORS_COUNT; ++i) { vectors[i] = new VectorFunc(fpa.toAddr(reader.readNextUnsignedInt()), VECTOR_NAMES[i]); } } 

toDataType() рд╡рд┐рдзрд┐, рдЬрд┐рд╕реЗ рд╣рдореЗрдВ рд╕рдВрд░рдЪрдирд╛ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдУрд╡рд░рд░рд╛рдЗрдб рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдХреЛ рдПрдХ Structure рдСрдмреНрдЬреЗрдХреНрдЯ рд╡рд╛рдкрд╕ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП рдЬрд┐рд╕рдореЗрдВ рд╕рдВрд░рдЪрдирд╛ рдлрд╝реАрд▓реНрдб рдХреЗ рдирд╛рдо, рдЙрдирдХреЗ рдЖрдХрд╛рд░, рдФрд░ рдкреНрд░рддреНрдпреЗрдХ рдлрд╝реАрд▓реНрдб рдкрд░ рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдХреЛ рдШреЛрд╖рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП (рдЖрдк null рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ):


 @Override public DataType toDataType() { Structure s = new StructureDataType("VectorsTable", 0); for (int i = 0; i < VECTORS_COUNT; ++i) { s.add(POINTER, 4, VECTOR_NAMES[i], null); } return s; } 

рдареАрдХ рд╣реИ, рдЪрд▓реЛ рдкреНрд░рддреНрдпреЗрдХ рд╡реИрдХреНрдЯрд░, рдпрд╛ рдкреВрд░реА рд╕реВрдЪреА (рдмреЙрдпрд▓рд░рдкреНрд▓реЗрдЯ рдХреЛрдб рдХрд╛ рдПрдХ рдЧреБрдЪреНрдЫрд╛) рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рддрд░реАрдХреЛрдВ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВ:


рдЕрдиреНрдп рд╡рд┐рдзрд┐рдпрд╛рдБ
  public VectorFunc[] getVectors() { return vectors; } public VectorFunc getSSP() { if (vectors.length < 1) { return null; } return vectors[0]; } public VectorFunc getReset() { if (vectors.length < 2) { return null; } return vectors[1]; } public VectorFunc getBusErr() { if (vectors.length < 3) { return null; } return vectors[2]; } public VectorFunc getAdrErr() { if (vectors.length < 4) { return null; } return vectors[3]; } public VectorFunc getInvOpCode() { if (vectors.length < 5) { return null; } return vectors[4]; } public VectorFunc getDivBy0() { if (vectors.length < 6) { return null; } return vectors[5]; } public VectorFunc getCheck() { if (vectors.length < 7) { return null; } return vectors[6]; } public VectorFunc getTrapV() { if (vectors.length < 8) { return null; } return vectors[7]; } public VectorFunc getGPF() { if (vectors.length < 9) { return null; } return vectors[8]; } public VectorFunc getTrace() { if (vectors.length < 10) { return null; } return vectors[9]; } public VectorFunc getReserv0() { if (vectors.length < 11) { return null; } return vectors[10]; } public VectorFunc getReserv1() { if (vectors.length < 12) { return null; } return vectors[11]; } public VectorFunc getReserv2() { if (vectors.length < 13) { return null; } return vectors[12]; } public VectorFunc getReserv3() { if (vectors.length < 14) { return null; } return vectors[13]; } public VectorFunc getReserv4() { if (vectors.length < 15) { return null; } return vectors[14]; } public VectorFunc getBadInt() { if (vectors.length < 16) { return null; } return vectors[15]; } public VectorFunc getReserv10() { if (vectors.length < 17) { return null; } return vectors[16]; } public VectorFunc getReserv11() { if (vectors.length < 18) { return null; } return vectors[17]; } public VectorFunc getReserv12() { if (vectors.length < 19) { return null; } return vectors[18]; } public VectorFunc getReserv13() { if (vectors.length < 20) { return null; } return vectors[19]; } public VectorFunc getReserv14() { if (vectors.length < 21) { return null; } return vectors[20]; } public VectorFunc getReserv15() { if (vectors.length < 22) { return null; } return vectors[21]; } public VectorFunc getReserv16() { if (vectors.length < 23) { return null; } return vectors[22]; } public VectorFunc getReserv17() { if (vectors.length < 24) { return null; } return vectors[23]; } public VectorFunc getBadIRQ() { if (vectors.length < 25) { return null; } return vectors[24]; } public VectorFunc getIRQ1() { if (vectors.length < 26) { return null; } return vectors[25]; } public VectorFunc getEXT() { if (vectors.length < 27) { return null; } return vectors[26]; } public VectorFunc getIRQ3() { if (vectors.length < 28) { return null; } return vectors[27]; } public VectorFunc getHBLANK() { if (vectors.length < 29) { return null; } return vectors[28]; } public VectorFunc getIRQ5() { if (vectors.length < 30) { return null; } return vectors[29]; } public VectorFunc getVBLANK() { if (vectors.length < 31) { return null; } return vectors[30]; } public VectorFunc getIRQ7() { if (vectors.length < 32) { return null; } return vectors[31]; } public VectorFunc getTrap0() { if (vectors.length < 33) { return null; } return vectors[32]; } public VectorFunc getTrap1() { if (vectors.length < 34) { return null; } return vectors[33]; } public VectorFunc getTrap2() { if (vectors.length < 35) { return null; } return vectors[34]; } public VectorFunc getTrap3() { if (vectors.length < 36) { return null; } return vectors[35]; } public VectorFunc getTrap4() { if (vectors.length < 37) { return null; } return vectors[36]; } public VectorFunc getTrap5() { if (vectors.length < 38) { return null; } return vectors[37]; } public VectorFunc getTrap6() { if (vectors.length < 39) { return null; } return vectors[38]; } public VectorFunc getTrap7() { if (vectors.length < 40) { return null; } return vectors[39]; } public VectorFunc getTrap8() { if (vectors.length < 41) { return null; } return vectors[40]; } public VectorFunc getTrap9() { if (vectors.length < 42) { return null; } return vectors[41]; } public VectorFunc getTrap10() { if (vectors.length < 43) { return null; } return vectors[42]; } public VectorFunc getTrap11() { if (vectors.length < 44) { return null; } return vectors[43]; } public VectorFunc getTrap12() { if (vectors.length < 45) { return null; } return vectors[44]; } public VectorFunc getTrap13() { if (vectors.length < 46) { return null; } return vectors[45]; } public VectorFunc getTrap14() { if (vectors.length < 47) { return null; } return vectors[46]; } public VectorFunc getTrap15() { if (vectors.length < 48) { return null; } return vectors[47]; } public VectorFunc getReserv30() { if (vectors.length < 49) { return null; } return vectors[48]; } public VectorFunc getReserv31() { if (vectors.length < 50) { return null; } return vectors[49]; } public VectorFunc getReserv32() { if (vectors.length < 51) { return null; } return vectors[50]; } public VectorFunc getReserv33() { if (vectors.length < 52) { return null; } return vectors[51]; } public VectorFunc getReserv34() { if (vectors.length < 53) { return null; } return vectors[52]; } public VectorFunc getReserv35() { if (vectors.length < 54) { return null; } return vectors[53]; } public VectorFunc getReserv36() { if (vectors.length < 55) { return null; } return vectors[54]; } public VectorFunc getReserv37() { if (vectors.length < 56) { return null; } return vectors[55]; } public VectorFunc getReserv38() { if (vectors.length < 57) { return null; } return vectors[56]; } public VectorFunc getReserv39() { if (vectors.length < 58) { return null; } return vectors[57]; } public VectorFunc getReserv3A() { if (vectors.length < 59) { return null; } return vectors[58]; } public VectorFunc getReserv3B() { if (vectors.length < 60) { return null; } return vectors[59]; } public VectorFunc getReserv3C() { if (vectors.length < 61) { return null; } return vectors[60]; } public VectorFunc getReserv3D() { if (vectors.length < 62) { return null; } return vectors[61]; } public VectorFunc getReserv3E() { if (vectors.length < 63) { return null; } return vectors[62]; } public VectorFunc getReserv3F() { if (vectors.length < 64) { return null; } return vectors[63]; } 

GameHeader


рд╣рдо рдРрд╕рд╛ рд╣реА рдХрд░реЗрдВрдЧреЗ рдФрд░ рдПрдХ GameHeader рдХреНрд▓рд╛рд╕ GameHeader рдЬреЛ рдХрд┐ StructConverter рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИред


рдЦреЗрд▓ рд░рдо рд╣реЗрдбрд░ рд╕рдВрд░рдЪрдирд╛
рдСрдлрд╝рд╕реЗрдЯ рдкреНрд░рд╛рд░рдВрдн рдХрд░реЗрдВрд╕рдорд╛рдкреНрддрд┐ рдСрдлрд╕реЗрдЯрд╡рд┐рд╡рд░рдг
$ 100$ 10FрдХрдВрд╕реЛрд▓ рдирд╛рдо (рдЖрдорддреМрд░ рдкрд░ 'SEGA рдореЗрдЧрд╛ рдбреНрд░рд╛рдЗрд╡' рдпрд╛ 'SEGA рдЙрддреНрдкрддреНрддрд┐')
$ 110$ 11Fрд░рд┐рд▓реАрдЬ рдХреА рддрд╛рд░реАрдЦ (рдЖрдорддреМрд░ рдкрд░ '┬й XXXX YYYY.MMM' рдЬрд╣рд╛рдВ XXXX рдХрдВрдкрдиреА рдХреЛрдб рд╣реИ, YYYY рд╡рд░реНрд╖ рдФрд░ MMM - рдорд╣реАрдирд╛ рд╣реИ)
$ 120$ 14FрдШрд░реЗрд▓реВ рдирд╛рдо
$ 150$ 17FрдЕрдВрддрд░реНрд░рд╛рд╖реНрдЯреНрд░реАрдп рдирд╛рдо
$ 180$ 18 рдбреАрд╕рдВрд╕реНрдХрд░рдг ('XX YYYYYYYYYYYY' рдЬрд╣рд╛рдВ XX рдЧреЗрдо рдХрд╛ рдкреНрд░рдХрд╛рд░ рд╣реИ рдФрд░ YY рдЧреЗрдо рдХреЛрдб рд╣реИ)
$ 18 рдИ$ 18Fchecksum
$ 190$ 19FрдореИрдВ / рдУ рд╕рдорд░реНрдерди
$ 1 рдП 0$ 1 рдП 3рд░реЛрдо рдкреНрд░рд╛рд░рдВрдн
$ 1 рдП 4$ 1 рдП 7рд░реЛрдо рдЕрдВрдд
$ 1 рдП 8$ 1ABRAM рдкреНрд░рд╛рд░рдВрдн (рдЖрдорддреМрд░ рдкрд░ $ 00FF0000)
$ 1AC$ 1AFRAM рдЕрдВрдд (рдЖрдорддреМрд░ рдкрд░ $ 00FFFFFF)
$ 1B0$ 1 рдмреА 2'RA' рдФрд░ $ F8 SRAM рдХреЛ рд╕рдХреНрд╖рдо рдмрдирд╛рддрд╛ рд╣реИ
$ 1 рдмреА 3----рдЕрдкреНрд░рдпреБрдХреНрдд ($ 20)
$ 1B4$ 1 рдмреА 7SRAM рдкреНрд░рд╛рд░рдВрдн (рдбрд┐рдлрд╝реЙрд▓реНрдЯ $ 00200000)
$ 1 рдмреА 8$ 1BBSRAM рдЕрдВрдд (рдбрд┐рдлрд╝реЙрд▓реНрдЯ $ 0020FFFF)
$ 1BC$ 1FFрдиреЛрдЯреНрд╕ (рдЕрдкреНрд░рдпреБрдХреНрдд)

рд╣рдо рдлрд╝реАрд▓реНрдб рд╕реЗрдЯ рдХрд░рддреЗ рд╣реИрдВ, рдЗрдирдкреБрдЯ рдбреЗрдЯрд╛ рдХреА рдкрд░реНрдпрд╛рдкреНрдд рд▓рдВрдмрд╛рдИ рдХреА рдЬрд╛рдБрдЪ рдХрд░рддреЗ рд╣реИрдВ, рд╣рдорд╛рд░реЗ рд▓рд┐рдП рджреЛ рдирдП рддрд░реАрдХреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ readNextByteArray() , readNextUnsignedShort() reader рдСрдмреНрдЬреЗрдХреНрдЯ рдХрд╛ рдбреЗрдЯрд╛ рдкрдврд╝рдиреЗ рдХреЗ рд▓рд┐рдП, рдФрд░ рдПрдХ рд╕рдВрд░рдЪрдирд╛ рдмрдирд╛рдПрдБред рдкрд░рд┐рдгрд╛рдореА рдХреЛрдб рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд╣реИ:


GameHeader
 package sega; import java.io.IOException; import ghidra.app.util.bin.BinaryReader; import ghidra.app.util.bin.StructConverter; import ghidra.program.flatapi.FlatProgramAPI; import ghidra.program.model.address.Address; import ghidra.program.model.data.DataType; import ghidra.program.model.data.Structure; import ghidra.program.model.data.StructureDataType; public class GameHeader implements StructConverter { private byte[] consoleName = null; private byte[] releaseDate = null; private byte[] domesticName = null; private byte[] internationalName = null; private byte[] version = null; private short checksum = 0; private byte[] ioSupport = null; private Address romStart = null, romEnd = null; private Address ramStart = null, ramEnd = null; private byte[] sramCode = null; private byte unused = 0; private Address sramStart = null, sramEnd = null; private byte[] notes = null; FlatProgramAPI fpa; public GameHeader(FlatProgramAPI fpa, BinaryReader reader) throws IOException { this.fpa = fpa; if (reader.length() < 0x200) { return; } reader.setPointerIndex(0x100); consoleName = reader.readNextByteArray(0x10); releaseDate = reader.readNextByteArray(0x10); domesticName = reader.readNextByteArray(0x30); internationalName = reader.readNextByteArray(0x30); version = reader.readNextByteArray(0x0E); checksum = (short) reader.readNextUnsignedShort(); ioSupport = reader.readNextByteArray(0x10); romStart = fpa.toAddr(reader.readNextUnsignedInt()); romEnd = fpa.toAddr(reader.readNextUnsignedInt()); ramStart = fpa.toAddr(reader.readNextUnsignedInt()); ramEnd = fpa.toAddr(reader.readNextUnsignedInt()); sramCode = reader.readNextByteArray(0x03); unused = reader.readNextByte(); sramStart = fpa.toAddr(reader.readNextUnsignedInt()); sramEnd = fpa.toAddr(reader.readNextUnsignedInt()); notes = reader.readNextByteArray(0x44); } @Override public DataType toDataType() { Structure s = new StructureDataType("GameHeader", 0); s.add(STRING, 0x10, "ConsoleName", null); s.add(STRING, 0x10, "ReleaseDate", null); s.add(STRING, 0x30, "DomesticName", null); s.add(STRING, 0x30, "InternationalName", null); s.add(STRING, 0x0E, "Version", null); s.add(WORD, 0x02, "Checksum", null); s.add(STRING, 0x10, "IoSupport", null); s.add(POINTER, 0x04, "RomStart", null); s.add(POINTER, 0x04, "RomEnd", null); s.add(POINTER, 0x04, "RamStart", null); s.add(POINTER, 0x04, "RamEnd", null); s.add(STRING, 0x03, "SramCode", null); s.add(BYTE, 0x01, "Unused", null); s.add(POINTER, 0x04, "SramStart", null); s.add(POINTER, 0x04, "SramEnd", null); s.add(STRING, 0x44, "Notes", null); return s; } public byte[] getConsoleName() { return consoleName; } public byte[] getReleaseDate() { return releaseDate; } public byte[] getDomesticName() { return domesticName; } public byte[] getInternationalName() { return internationalName; } public byte[] getVersion() { return version; } public short getChecksum() { return checksum; } public byte[] getIoSupport() { return ioSupport; } public Address getRomStart() { return romStart; } public Address getRomEnd() { return romEnd; } public Address getRamStart() { return ramStart; } public Address getRamEnd() { return ramEnd; } public byte[] getSramCode() { return sramCode; } public byte getUnused() { return unused; } public Address getSramStart() { return sramStart; } public Address getSramEnd() { return sramEnd; } public boolean hasSRAM() { if (sramCode == null) { return false; } return sramCode[0] == 'R' && sramCode[1] == 'A' && sramCode[2] == 0xF8; } public byte[] getNotes() { return notes; } } 

рд╣реЗрдбрд░ рдХреЗ рд▓рд┐рдП рдСрдмреНрдЬреЗрдХреНрдЯ рдмрдирд╛рдПрдБ:


 vectors = new VectorsTable(fpa, reader); header = new GameHeader(fpa, reader); 

рдЦрдВрдбреЛрдВ


рд╕реЗрдЧрд╛ рдХреЗ рдкрд╛рд╕ рд╕реНрдореГрддрд┐ рдХреНрд╖реЗрддреНрд░реЛрдВ рдХрд╛ рдПрдХ рдкреНрд░рд╕рд┐рджреНрдз рдорд╛рдирдЪрд┐рддреНрд░ рд╣реИ, рдЬрд┐рд╕реЗ рдореИрдВ, рд╢рд╛рдпрдж, рдпрд╣рд╛рдВ рддрд╛рд▓рд┐рдХрд╛ рдХреЗ рд░реВрдк рдореЗрдВ рдирд╣реАрдВ рджреВрдВрдЧрд╛, рд▓реЗрдХрд┐рди рдореИрдВ рдХреЗрд╡рд▓ рд╡рд╣ рдХреЛрдб рджреВрдВрдЧрд╛ рдЬреЛ рдХрд┐ рд╕реЗрдЧрдореЗрдВрдЯ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред


рддреЛ, FlatProgramAPI рд╡рд░реНрдЧ рдХреЗ рдСрдмреНрдЬреЗрдХреНрдЯ рдореЗрдВ рдПрдХ createMemoryBlock() рд╡рд┐рдзрд┐ рд╣реИ, рдЬрд┐рд╕рдХреЗ рд╕рд╛рде рдореЗрдореЛрд░реА рдХреНрд╖реЗрддреНрд░ рдмрдирд╛рдирд╛ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИред рдЗрдирдкреБрдЯ рдкрд░, рдпрд╣ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рддрд░реНрдХ рд▓реЗрддрд╛ рд╣реИ:


  1. name : рдХреНрд╖реЗрддреНрд░ рдХрд╛ рдирд╛рдо
  2. address : рдХреНрд╖реЗрддреНрд░ рдХрд╛ рдкрддрд╛ рд╢реБрд░реВ рдХрд░реЗрдВ
  3. stream : рдЯрд╛рдЗрдк InputStream рдХрд╛ рдПрдХ рдСрдмреНрдЬреЗрдХреНрдЯ, рдЬреЛ рдореЗрдореЛрд░реА рдХреЗ рдХреНрд╖реЗрддреНрд░ рдореЗрдВ рдбреЗрдЯрд╛ рдХреЗ рд▓рд┐рдП рдЖрдзрд╛рд░ рд╣реЛрдЧрд╛ред рдпрджрд┐ рдЖрдк null рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдПрдХ рдЕрд╕рд┐рдВрдЪрд┐рдд рдХреНрд╖реЗрддреНрд░ рдмрдирд╛рдпрд╛ рдЬрд╛рдПрдЧрд╛ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, 68K RAM рдпрд╛ Z80 RAM рд╣рдореЗрдВ рдмрд╕ рдЙрд╕реА рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА
  4. size : рдирд┐рд░реНрдорд┐рдд рдХреНрд╖реЗрддреНрд░ рдХрд╛ рдЖрдХрд╛рд░
  5. isOverlay : true рдпрд╛ false рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддрд╛ true , рдФрд░ рдЗрдВрдЧрд┐рдд рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдореЗрдореЛрд░реА рдХреНрд╖реЗрддреНрд░ рдУрд╡рд░рд▓реЗ рд╣реИред рдореБрдЭреЗ рдкрддрд╛ рдирд╣реАрдВ рд╣реИ рдХрд┐ рдирд┐рд╖реНрдкрд╛рджрди рдпреЛрдЧреНрдп рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рдЫреЛрдбрд╝рдХрд░ рдЗрд╕рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХрд╣рд╛рдВ рд╣реИ

рдЖрдЙрдЯрдкреБрдЯ рдкрд░, createMemoryBlock() рдПрдХ MemoryBlock рдкреНрд░рдХрд╛рд░ рдХрд╛ рдСрдмреНрдЬреЗрдХреНрдЯ MemoryBlock , рдЬрд┐рд╕рдореЗрдВ рдЖрдк рд╡реИрдХрд▓реНрдкрд┐рдХ рд░реВрдк рд╕реЗ рдПрдХреНрд╕реЗрд╕ рд░рд╛рдЗрдЯреНрд╕ рдлреНрд▓реИрдЧ ( Read , Write , createMemoryBlock() рд╕реЗрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред


рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк, рд╣рдореЗрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдлрд╝реЙрд░реНрдо рдХрд╛ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдорд┐рд▓рддрд╛ рд╣реИ:


 private void createSegment(FlatProgramAPI fpa, InputStream stream, String name, Address address, long size, boolean read, boolean write, boolean execute) { MemoryBlock block = null; try { block = fpa.createMemoryBlock(name, address, stream, size, false); block.setRead(read); block.setWrite(read); block.setExecute(execute); } catch (Exception e) { Msg.error(this, String.format("Error creating %s segment", name)); } } 

рдпрд╣рд╛рдБ рд╣рдордиреЗ рдЕрддрд┐рд░рд┐рдХреНрдд рд░реВрдк рд╕реЗ рдПрдХ рддреНрд░реБрдЯрд┐ рд╕рдВрджреЗрд╢ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП Msg рд╡рд░реНрдЧ рдХреА рд╕реНрдереИрддрд┐рдХ error рд╡рд┐рдзрд┐ рдХреЛ рдХрд╣рд╛ рд╣реИред


рдЧреЗрдо рд░рдо рд╡рд╛рд▓реЗ рд╕реЗрдЧрдореЗрдВрдЯ рдореЗрдВ рдЕрдзрд┐рдХрддрдо рдЖрдХрд╛рд░ 0x3FFFFF (рдмрд╛рдХреА рд╕рдм рдХреБрдЫ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЕрдиреНрдп рдХреНрд╖реЗрддреНрд░реЛрдВ рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рд╣реЛрдЧрд╛)ред рдЖрдЗрдП рдЗрд╕реЗ рдмрдирд╛рдПрдВ:


 InputStream romStream = provider.getInputStream(0); createSegment(fpa, romStream, "ROM", fpa.toAddr(0x000000), Math.min(romStream.available(), 0x3FFFFF), true, false, true); 

InputStream , 0.


, ( SegaCD Sega32X ). OptionDialog . , showYesNoDialogWithNoAsDefaultButton() YES NO - NO .


:


 if (OptionDialog.YES_OPTION == OptionDialog.showYesNoDialogWithNoAsDefaultButton(null, "Question", "Create Sega CD segment?")) { if (romStream.available() > 0x3FFFFF) { InputStream epaStream = provider.getInputStream(0x400000); createSegment(fpa, epaStream, "EPA", fpa.toAddr(0x400000), 0x400000, true, true, false); } else { createSegment(fpa, null, "EPA", fpa.toAddr(0x400000), 0x400000, true, true, false); } } if (OptionDialog.YES_OPTION == OptionDialog.showYesNoDialogWithNoAsDefaultButton(null, "Question", "Create Sega 32X segment?")) { createSegment(fpa, null, "32X", fpa.toAddr(0x800000), 0x200000, true, true, false); } 

:


 createSegment(fpa, null, "Z80", fpa.toAddr(0xA00000), 0x10000, true, true, false); createSegment(fpa, null, "SYS1", fpa.toAddr(0xA10000), 16 * 2, true, true, false); createSegment(fpa, null, "SYS2", fpa.toAddr(0xA11000), 2, true, true, false); createSegment(fpa, null, "Z802", fpa.toAddr(0xA11100), 2, true, true, false); createSegment(fpa, null, "Z803", fpa.toAddr(0xA11200), 2, true, true, false); createSegment(fpa, null, "FDC", fpa.toAddr(0xA12000), 0x100, true, true, false); createSegment(fpa, null, "TIME", fpa.toAddr(0xA13000), 0x100, true, true, false); createSegment(fpa, null, "TMSS", fpa.toAddr(0xA14000), 4, true, true, false); createSegment(fpa, null, "VDP", fpa.toAddr(0xC00000), 2 * 9, true, true, false); createSegment(fpa, null, "RAM", fpa.toAddr(0xFF0000), 0x10000, true, true, true); if (header.hasSRAM()) { Address sramStart = header.getSramStart(); Address sramEnd = header.getSramEnd(); if (sramStart.getOffset() >= 0x200000 && sramEnd.getOffset() <= 0x20FFFF && sramStart.getOffset() < sramEnd.getOffset()) { createSegment(fpa, null, "SRAM", sramStart, sramEnd.getOffset() - sramStart.getOffset() + 1, true, true, false); } } 

,


CreateArrayCmd . , :


  1. address : ,
  2. numElements :
  3. dataType :
  4. elementSize :

applyTo(program) , .


, , BYTE , WORD , DWORD . , FlatProgramAPI createByte() , createWord() , createDword() ..


, , (, VDP ). , :


  1. Program getSymbolTable() , , ..
  2. createLabel() , , . , , SourceType.IMPORTED

, :


 private void createNamedByteArray(FlatProgramAPI fpa, Program program, Address address, String name, int numElements) { if (numElements > 1) { CreateArrayCmd arrayCmd = new CreateArrayCmd(address, numElements, ByteDataType.dataType, ByteDataType.dataType.getLength()); arrayCmd.applyTo(program); } else { try { fpa.createByte(address); } catch (Exception e) { Msg.error(this, "Cannot create byte. " + e.getMessage()); } } try { program.getSymbolTable().createLabel(address, name, SourceType.IMPORTED); } catch (InvalidInputException e) { Msg.error(this, String.format("%s : Error creating array %s", getName(), name)); } } private void createNamedWordArray(FlatProgramAPI fpa, Program program, Address address, String name, int numElements) { if (numElements > 1) { CreateArrayCmd arrayCmd = new CreateArrayCmd(address, numElements, WordDataType.dataType, WordDataType.dataType.getLength()); arrayCmd.applyTo(program); } else { try { fpa.createWord(address); } catch (Exception e) { Msg.error(this, "Cannot create word. " + e.getMessage()); } } try { program.getSymbolTable().createLabel(address, name, SourceType.IMPORTED); } catch (InvalidInputException e) { Msg.error(this, String.format("%s : Error creating array %s", getName(), name)); } } private void createNamedDwordArray(FlatProgramAPI fpa, Program program, Address address, String name, int numElements) { if (numElements > 1) { CreateArrayCmd arrayCmd = new CreateArrayCmd(address, numElements, DWordDataType.dataType, DWordDataType.dataType.getLength()); arrayCmd.applyTo(program); } else { try { fpa.createDWord(address); } catch (Exception e) { Msg.error(this, "Cannot create dword. " + e.getMessage()); } } try { program.getSymbolTable().createLabel(address, name, SourceType.IMPORTED); } catch (InvalidInputException e) { Msg.error(this, String.format("%s : Error creating array %s", getName(), name)); } } 

 createNamedDwordArray(fpa, program, fpa.toAddr(0xA04000), "Z80_YM2612", 1); createNamedWordArray(fpa, program, fpa.toAddr(0xA10000), "IO_PCBVER", 1); createNamedWordArray(fpa, program, fpa.toAddr(0xA10002), "IO_CT1_DATA", 1); createNamedWordArray(fpa, program, fpa.toAddr(0xA10004), "IO_CT2_DATA", 1); createNamedWordArray(fpa, program, fpa.toAddr(0xA10006), "IO_EXT_DATA", 1); createNamedWordArray(fpa, program, fpa.toAddr(0xA10008), "IO_CT1_CTRL", 1); createNamedWordArray(fpa, program, fpa.toAddr(0xA1000A), "IO_CT2_CTRL", 1); createNamedWordArray(fpa, program, fpa.toAddr(0xA1000C), "IO_EXT_CTRL", 1); createNamedWordArray(fpa, program, fpa.toAddr(0xA1000E), "IO_CT1_RX", 1); createNamedWordArray(fpa, program, fpa.toAddr(0xA10010), "IO_CT1_TX", 1); createNamedWordArray(fpa, program, fpa.toAddr(0xA10012), "IO_CT1_SMODE", 1); createNamedWordArray(fpa, program, fpa.toAddr(0xA10014), "IO_CT2_RX", 1); createNamedWordArray(fpa, program, fpa.toAddr(0xA10016), "IO_CT2_TX", 1); createNamedWordArray(fpa, program, fpa.toAddr(0xA10018), "IO_CT2_SMODE", 1); createNamedWordArray(fpa, program, fpa.toAddr(0xA1001A), "IO_EXT_RX", 1); createNamedWordArray(fpa, program, fpa.toAddr(0xA1001C), "IO_EXT_TX", 1); createNamedWordArray(fpa, program, fpa.toAddr(0xA1001E), "IO_EXT_SMODE", 1); createNamedWordArray(fpa, program, fpa.toAddr(0xA11000), "IO_RAMMODE", 1); createNamedWordArray(fpa, program, fpa.toAddr(0xA11100), "IO_Z80BUS", 1); createNamedWordArray(fpa, program, fpa.toAddr(0xA11200), "IO_Z80RES", 1); createNamedByteArray(fpa, program, fpa.toAddr(0xA12000), "IO_FDC", 0x100); createNamedByteArray(fpa, program, fpa.toAddr(0xA13000), "IO_TIME", 0x100); createNamedDwordArray(fpa, program, fpa.toAddr(0xA14000), "IO_TMSS", 1); createNamedWordArray(fpa, program, fpa.toAddr(0xC00000), "VDP_DATA", 1); createNamedWordArray(fpa, program, fpa.toAddr(0xC00002), "VDP__DATA", 1); createNamedWordArray(fpa, program, fpa.toAddr(0xC00004), "VDP_CTRL", 1); createNamedWordArray(fpa, program, fpa.toAddr(0xC00006), "VDP__CTRL", 1); createNamedWordArray(fpa, program, fpa.toAddr(0xC00008), "VDP_CNTR", 1); createNamedWordArray(fpa, program, fpa.toAddr(0xC0000A), "VDP__CNTR", 1); createNamedWordArray(fpa, program, fpa.toAddr(0xC0000C), "VDP___CNTR", 1); createNamedWordArray(fpa, program, fpa.toAddr(0xC0000E), "VDP____CNTR", 1); createNamedByteArray(fpa, program, fpa.toAddr(0xC00011), "VDP_PSG", 1); 


createData() DataUtilities . :


  1. program : Program
  2. address : ,
  3. dataType :
  4. dataLength : . -1
  5. stackPointers : true , - . false
  6. clearDataMode : , (, )

: .. (, ), . FlatProgramAPI createFunction() , .


:


 private void markVectorsTable(Program program, FlatProgramAPI fpa) { try { DataUtilities.createData(program, fpa.toAddr(0), vectors.toDataType(), -1, false, ClearDataMode.CLEAR_ALL_UNDEFINED_CONFLICT_DATA); for (VectorFunc func : vectors.getVectors()) { fpa.createFunction(func.getAddress(), func.getName()); } } catch (CodeUnitInsertionException e) { Msg.error(this, "Vectors mark conflict at 0x000000"); } } private void markHeader(Program program, FlatProgramAPI fpa) { try { DataUtilities.createData(program, fpa.toAddr(0x100), header.toDataType(), -1, false, ClearDataMode.CLEAR_ALL_UNDEFINED_CONFLICT_DATA); } catch (CodeUnitInsertionException e) { Msg.error(this, "Vectors mark conflict at 0x000100"); } } 

load()


load() setMessage() TaskMonitor , .


 monitor.setMessage(String.format("%s : Start loading", getName())); 

, :


 @Override protected void load(ByteProvider provider, LoadSpec loadSpec, List<Option> options, Program program, MemoryConflictHandler handler, TaskMonitor monitor, MessageLog log) throws CancelledException, IOException { monitor.setMessage(String.format("%s : Start loading", getName())); BinaryReader reader = new BinaryReader(provider, false); FlatProgramAPI fpa = new FlatProgramAPI(program, monitor); vectors = new VectorsTable(fpa, reader); header = new GameHeader(fpa, reader); createSegments(fpa, provider, program, monitor); markVectorsTable(program, fpa); markHeader(program, fpa); monitor.setMessage(String.format("%s : Loading done", getName())); } 

getDefaultOptions validateOptions


,



Run -> Debug As -> 1 Ghidra . .



GHIDRA


, - . Eclipse extension.properties , :


 description=Loader for Sega Mega Drive / Genesis ROMs author=Dr. MefistO createdOn=20.03.2019 

GhidraDev -> Export -> Ghidra Module Extension... :





dist zip- (- ghidra_9.0_PUBLIC_20190320_Sega.zip ) GHIDRA .


. , File -> Install Extensions... , , . ...





github- , .


: IDA GHIDRA . .

Source: https://habr.com/ru/post/hi444562/


All Articles