package com.sneed.pkrandom.romhandlers;
/*----------------------------------------------------------------------------*/
/*-- AbstractGBCRomHandler.java - an extension of AbstractGBRomHandler --*/
/*-- used for Gen 1 and Gen 2. --*/
/*-- --*/
/*-- Part of "Universal Pokemon Randomizer ZX" by the UPR-ZX team --*/
/*-- Originally part of "Universal Pokemon Randomizer" by sneed --*/
/*-- Pokemon and any associated names and the like are --*/
/*-- trademark and (C) Nintendo 1996-2020. --*/
/*-- --*/
/*-- 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.FileNotFoundException;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.Scanner;
import com.sneed.pkrandom.FileFunctions;
import com.sneed.pkrandom.constants.GBConstants;
public abstract class AbstractGBCRomHandler extends AbstractGBRomHandler {
private String[] tb;
private Map d;
private int longestTableToken;
public AbstractGBCRomHandler(Random random, PrintStream logStream) {
super(random, logStream);
}
protected void clearTextTables() {
tb = new String[256];
if (d != null) {
d.clear();
} else {
d = new HashMap();
}
longestTableToken = 0;
}
protected void readTextTable(String name) {
try {
Scanner sc = new Scanner(FileFunctions.openConfig(name + ".tbl"), "UTF-8");
while (sc.hasNextLine()) {
String q = sc.nextLine();
if (!q.trim().isEmpty()) {
String[] r = q.split("=", 2);
if (r[1].endsWith("\r\n")) {
r[1] = r[1].substring(0, r[1].length() - 2);
}
int hexcode = Integer.parseInt(r[0], 16);
if (tb[hexcode] != null) {
String oldMatch = tb[hexcode];
tb[hexcode] = null;
if (d.get(oldMatch) == hexcode) {
d.remove(oldMatch);
}
}
tb[hexcode] = r[1];
longestTableToken = Math.max(longestTableToken, r[1].length());
d.put(r[1], (byte) hexcode);
}
}
sc.close();
} catch (FileNotFoundException e) {
}
}
protected String readString(int offset, int maxLength, boolean textEngineMode) {
StringBuilder string = new StringBuilder();
for (int c = 0; c < maxLength; c++) {
int currChar = rom[offset + c] & 0xFF;
if (tb[currChar] != null) {
string.append(tb[currChar]);
if (textEngineMode && (tb[currChar].equals("\\r") || tb[currChar].equals("\\e"))) {
break;
}
} else {
if (currChar == GBConstants.stringTerminator) {
break;
} else {
string.append("\\x" + String.format("%02X", currChar));
}
}
}
return string.toString();
}
protected int lengthOfStringAt(int offset, boolean textEngineMode) {
int len = 0;
while (rom[offset + len] != GBConstants.stringTerminator
&& (!textEngineMode || (rom[offset + len] != GBConstants.stringPrintedTextEnd && rom[offset + len] != GBConstants.stringPrintedTextPromptEnd))) {
len++;
}
if (textEngineMode
&& (rom[offset + len] == GBConstants.stringPrintedTextEnd || rom[offset + len] == GBConstants.stringPrintedTextPromptEnd)) {
len++;
}
return len;
}
protected byte[] translateString(String text) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while (text.length() != 0) {
int i = Math.max(0, longestTableToken - text.length());
if (text.charAt(0) == '\\' && text.charAt(1) == 'x') {
baos.write(Integer.parseInt(text.substring(2, 4), 16));
text = text.substring(4);
} else {
while (!(d.containsKey(text.substring(0, longestTableToken - i)) || (i == longestTableToken))) {
i++;
}
if (i == longestTableToken) {
text = text.substring(1);
} else {
baos.write(d.get(text.substring(0, longestTableToken - i)) & 0xFF);
text = text.substring(longestTableToken - i);
}
}
}
return baos.toByteArray();
}
protected String readFixedLengthString(int offset, int length) {
return readString(offset, length, false);
}
// pads the length with terminators, so length should be at least str's len
// + 1
protected void writeFixedLengthString(String str, int offset, int length) {
byte[] translated = translateString(str);
int len = Math.min(translated.length, length);
System.arraycopy(translated, 0, rom, offset, len);
while (len < length) {
rom[offset + len] = GBConstants.stringTerminator;
len++;
}
}
protected void writeVariableLengthString(String str, int offset, boolean alreadyTerminated) {
byte[] translated = translateString(str);
System.arraycopy(translated, 0, rom, offset, translated.length);
if (!alreadyTerminated) {
rom[offset + translated.length] = GBConstants.stringTerminator;
}
}
protected int makeGBPointer(int offset) {
if (offset < GBConstants.bankSize) {
return offset;
} else {
return (offset % GBConstants.bankSize) + GBConstants.bankSize;
}
}
protected int bankOf(int offset) {
return (offset / GBConstants.bankSize);
}
protected int calculateOffset(int bank, int pointer) {
if (pointer < GBConstants.bankSize) {
return pointer;
} else {
return (pointer % GBConstants.bankSize) + bank * GBConstants.bankSize;
}
}
protected String readVariableLengthString(int offset, boolean textEngineMode) {
return readString(offset, Integer.MAX_VALUE, textEngineMode);
}
protected static boolean romSig(byte[] rom, String sig) {
try {
int sigOffset = GBConstants.romSigOffset;
byte[] sigBytes = sig.getBytes("US-ASCII");
for (int i = 0; i < sigBytes.length; i++) {
if (rom[sigOffset + i] != sigBytes[i]) {
return false;
}
}
return true;
} catch (UnsupportedEncodingException ex) {
return false;
}
}
protected static boolean romCode(byte[] rom, String code) {
try {
int sigOffset = GBConstants.romCodeOffset;
byte[] sigBytes = code.getBytes("US-ASCII");
for (int i = 0; i < sigBytes.length; i++) {
if (rom[sigOffset + i] != sigBytes[i]) {
return false;
}
}
return true;
} catch (UnsupportedEncodingException ex) {
return false;
}
}
}