Skip to content

Commit

Permalink
Added negative offsets variables propagator.
Browse files Browse the repository at this point in the history
  • Loading branch information
Vladimir Kononovich committed Apr 29, 2019
1 parent c2722e4 commit 2477d24
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 3 deletions.
2 changes: 1 addition & 1 deletion extension.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name=@extname@
description=Loader for Sega Mega Drive / Genesis ROMs
author=Dr. MefistO
createdOn=07.04.2019
createdOn=
version=@extversion@
7 changes: 7 additions & 0 deletions src/main/java/sega/NegVariableBaseReg.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package sega;

public enum NegVariableBaseReg {
A4,
A5,
A6
}
114 changes: 114 additions & 0 deletions src/main/java/sega/SegaAnalyzer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package sega;

import java.math.BigInteger;
import java.util.List;

import ghidra.app.services.AbstractAnalyzer;
import ghidra.app.services.AnalyzerType;
import ghidra.app.util.importer.MessageLog;
import ghidra.framework.options.OptionType;
import ghidra.framework.options.Options;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSetView;
import ghidra.program.model.lang.Register;
import ghidra.program.model.lang.RegisterValue;
import ghidra.program.model.listing.ContextChangeException;
import ghidra.program.model.listing.Function;
import ghidra.program.model.listing.FunctionIterator;
import ghidra.program.model.listing.FunctionManager;
import ghidra.program.model.listing.Program;
import ghidra.program.model.listing.ProgramContext;
import ghidra.program.model.symbol.Symbol;
import ghidra.program.model.symbol.SymbolTable;
import ghidra.program.model.symbol.SymbolType;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;

public class SegaAnalyzer extends AbstractAnalyzer {

private static final long DEF_BASE_ADDR = 0xFF8000;
private static final String OPTION_BASE_REG = "Base Register";
private static final String OPTION_BASE_VAL = "Base Address";
private NegVariableBaseReg baseReg = NegVariableBaseReg.A6;
private String baseAddr = String.format("0x%06X", DEF_BASE_ADDR);

private static boolean isSegaLoader(Program program) {
return program.getExecutableFormat().equalsIgnoreCase(SegaLoader.LOADER_NAME) ||
program.getExecutableFormat().equalsIgnoreCase("Sega Genesis/MegaDrive ROM file v.2");
}

public SegaAnalyzer() {
super("Negative Offset Variables", "Finds variables like -$XXXX(Ax) and sets specified base address", AnalyzerType.FUNCTION_ANALYZER);
}

@Override
public boolean getDefaultEnablement(Program program) {
return isSegaLoader(program);
}

@Override
public boolean canAnalyze(Program program) {
return isSegaLoader(program);
}

@Override
public void registerOptions(Options options, Program program) {
options.registerOption(OPTION_BASE_REG, OptionType.ENUM_TYPE, baseReg, null, "Register which is used in -$XXXX(Ax) expressions");

options.registerOption(OPTION_BASE_VAL, OptionType.STRING_TYPE, baseAddr, null, "Hexadecimal Base address for negative variables. 0xFF8000, for ex.");
}

@Override
public void optionsChanged(Options options, Program program) {
super.optionsChanged(options, program);

baseReg = options.getEnum(OPTION_BASE_REG, NegVariableBaseReg.A6);
baseAddr = options.getString(OPTION_BASE_VAL, baseAddr);
}

@Override
public boolean added(Program program, AddressSetView set, TaskMonitor monitor, MessageLog log)
throws CancelledException {

Address resetAddr = null;

SymbolTable symTable = program.getSymbolTable();
List<Symbol> resets = symTable.getLabelOrFunctionSymbols(VectorsTable.VECTOR_NAMES[1], program.getGlobalNamespace());
FunctionManager funcMgr = program.getFunctionManager();
ProgramContext ctx = program.getProgramContext();
Register reg = program.getRegister(baseReg.name());

for (Symbol sym: resets) {
if (sym.getSymbolType() == SymbolType.FUNCTION) {
resetAddr = sym.getAddress();
break;
}
}

if (resetAddr == null) {
return false;
}

FunctionIterator it = funcMgr.getFunctions(set, true);

while (it.hasNext()) {
Function func = it.next();

AddressSetView as = func.getBody();

if (as.getMinAddress().equals(resetAddr) || ctx.getRegisterValue(reg, as.getMinAddress()) != null) {
continue;
}

RegisterValue regVal = new RegisterValue(reg, BigInteger.valueOf(Long.decode(baseAddr)));
try {
ctx.setRegisterValue(as.getMinAddress(), as.getMaxAddress(), regVal);
} catch (ContextChangeException e) {
return false;
}
}

return true;
}

}
4 changes: 3 additions & 1 deletion src/main/java/sega/SegaLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,14 @@
*/
public class SegaLoader extends AbstractLibrarySupportLoader {

public static final String LOADER_NAME = "Sega Mega Drive / Genesis Loader";

private VectorsTable vectors;
private GameHeader header;

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

@Override
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/sega/VectorsTable.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class VectorsTable implements StructConverter {
private static final int VECTORS_SIZE = 0x100;
private static final int VECTORS_COUNT = VECTORS_SIZE / 4;

private static final String[] VECTOR_NAMES = {
public 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",
Expand Down

0 comments on commit 2477d24

Please sign in to comment.