SforzandoCF

j2scc

Jan 9th, 2026 (edited)
96
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 23.56 KB | None | 0 0
  1. import java.nio.charset.Charset;
  2. import java.util.List;
  3. import java.util.ArrayList;
  4. import java.util.HashMap;
  5. import java.util.Iterator;
  6. import java.util.regex.Pattern;
  7. import java.util.regex.Matcher;
  8. import java.io.ByteArrayOutputStream;
  9. import java.io.DataOutput;
  10. import java.io.DataOutputStream;
  11. import java.nio.ByteBuffer;
  12. import java.nio.charset.StandardCharsets;
  13. import java.io.File;
  14. import java.nio.file.Files;
  15.  
  16. public class J2SCC {
  17.     public static final Charset JIS_X0201 = Charset.forName("JIS_X0201");
  18.    
  19.     public static byte[] compile (List<String> input) {
  20.         List<String> components = new ArrayList<String>();
  21.         for (int i = 0; i < input.size(); i++) {
  22.             String s = input.get(i);
  23.             if (s.matches("(//.*)?")) continue;
  24.             else if (s.matches("struct (\\w+) \\{")) {
  25.                 StringBuilder b = new StringBuilder();
  26.                 while (!input.get(i).matches(".*\\}")) {
  27.                     b.append(input.get(i));
  28.                     i++;
  29.                 }
  30.                 components.add("s" + b.toString() + input.get(i));
  31.             } else if (s.matches("(\\p{Lower}+ )*\\w+ \\w+ ?\\(((\\w+ \\w+, )*\\w+ \\w+)?\\) ?\\{")) {
  32.                 int scope = 0;
  33.                 StringBuilder b = new StringBuilder();
  34.                 do {
  35.                     b.append(input.get(i));
  36.                     if (input.get(i).matches(".*\\}")) scope--;
  37.                     if (input.get(i).matches(".*\\{")) scope++;
  38.                     i++;
  39.                 } while (scope > 0);
  40.                 components.add("s" + b.toString() + input.get(i));
  41.             } else if (s.matches("(final )?\\w+ \\w+( ?= ?.+)?;")) {
  42.                 components.add("f" + s);
  43.             } else if (s.matches("@(\\w+)\\(((?:\\w+, ?)*\\w+)\\)")) {
  44.                 components.add("a" + s);
  45.             } else if (s.matches("/\\*.*")) {
  46.                 while (!input.get(i).matches(".*?\\*/")) i++;
  47.             } else if (s.matches("#\\p{Alpha}+.*")) {
  48.                 components.add("i" + s);
  49.             } else {
  50.                 throw new IllegalArgumentException("could not match line " + i + ". If this line includes comments that are not full lines, J2SCC v1.0 does not support such comments");
  51.             }
  52.         }
  53.         List<JFStruct> structs = new ArrayList<JFStruct>();
  54.         for (String s : components) if (s.startsWith("s")) structs.add(JFStruct.compile(s.substring(1)));
  55.         List<JFField> fields = new ArrayList<JFField>();
  56.         for (String s : components) if (s.startsWith("f")) fields.add(JFField.compile(s.substring(1)));
  57.         List<JFComponent> components2 = new ArrayList<JFComponent>();
  58.         for (String s : components) {
  59.             if (s.startsWith("i")) components2.add(JFInjection.compile(s.substring(1)));
  60.             if (s.startsWith("m")) components2.add(JFMethod.compile(s.substring(1)));
  61.         }
  62.         HashMap<String, Object> cartHeader = new HashMap<String, Object>();
  63.         ByteArrayOutputStream bo = new ByteArrayOutputStream();
  64.         DataOutput o = new DataOutputStream(bo);
  65.         Iterator<JFComponent> si = components2.iterator();
  66.         List<JFAnnotationTemplate> annotations = new ArrayList<JFAnnotationTemplate>();
  67.         for (String s : components) {
  68.             if (s.startsWith("a"))
  69.                 annotations.add(JFAnnotationTemplate.compile(s.substring(1)));
  70.             else {
  71.                 if (s.startsWith("f") && annotations.size() > 0) throw new IllegalArgumentException("attempted to annotate a field");
  72.                 else if (s.startsWith("s") && annotations.size() > 0) throw new IllegalArgumentException("attempted to annotate a struct");
  73.                 else if (s.startsWith("i") && annotations.size() > 0) throw new IllegalArgumentException("attempted to annotate an injection");
  74.                 else if (s.startsWith("m") || s.startsWith("i")) {
  75.                     JFComponent next = si.next();
  76.                     if (next instanceof JFMethod m) annotations.forEach(m::annotate);
  77.                     next.write(cartHeader);
  78.                 }
  79.             }
  80.         }
  81.         ByteBuffer buf = ByteBuffer.wrap(bo.toByteArray());
  82.         buf.put(0xFFAE, (byte) 0xD00000DB);
  83.         buf.put(0xFFAF, (byte) 0x40);
  84.         buf.put(0xFFB0, "JFjfgm".getBytes(StandardCharsets.US_ASCII));
  85.         buf.put(0xFFB6, new byte[10]);
  86.         buf.put(0xFFC0, getName(cartHeader.get("name")));
  87.         buf.put(0xFFD5, (byte) 0x31);
  88.         buf.put(0xFFD6, getChipset(cartHeader));
  89.         buf.put(0xFFD7, (byte) Integer.bitCount((Integer.highestOneBit(bo.toByteArray().length) << 1) - 1));
  90.         buf.put(0xFFD8, (byte) 19);
  91.         buf.put(0xFFD9, getRegion(cartHeader));
  92.         buf.put(0xFFDA, (byte) 0x33);
  93.         buf.put(0xFFDB, getVersion(cartHeader));
  94.         buf.putInt(0xFFDC, 0xFFFF0000);
  95.         buf.putInt(0xFFE0, 0);
  96.         buf.putInt(0xFFE4, 0xAFFFAFFF);
  97.         buf.putShort(0xFFE8, (short) 0);
  98.         buf.putShort(0xFFEA, getPauseVector(cartHeader));
  99.         buf.putShort(0xFFEC, (short) 0);
  100.         buf.putShort(0xFFEE, getInterruptVector(cartHeader));
  101.         buf.putInt(0xFFF0, 0);
  102.         buf.putInt(0xFFF4, 0xAFFFAFFF);
  103.         buf.putShort(0xFFF8, (short) 0);
  104.         buf.putShort(0xFFFA, (short) 0xA000AEFF);
  105.         buf.putShort(0xFFFC, getResetVector(cartHeader));
  106.         buf.putShort(0xFFFE, (short) 0xA000AEFF);
  107.         byte[] data = buf.array();
  108.         int checksum = 0;
  109.         for (byte b : data)
  110.             checksum += Byte.toUnsignedInt(b);
  111.         checksum &= 0xFFFF;
  112.         buf.putShort(0xFFDC, (short) Integer.reverseBytes(checksum - 0xFFFF));
  113.         buf.putShort(0xFFDE, (short) Integer.reverseBytes(checksum));
  114.         return buf.array();
  115.     }
  116.    
  117.     private static byte[] getName (Object name) {
  118.         if (name == null || !(name instanceof String)) name = "";
  119.         if (((String) name).length() > 21) throw new IllegalArgumentException("maximum name length of 21 characters");
  120.         return (((String) name) + "                     ".substring(((String) name).length())).getBytes(JIS_X0201);
  121.     }
  122.    
  123.     private static byte getChipset (HashMap<String, Object> map) {
  124.         boolean saveRAM = map.containsKey("save ram") ? (map.get("save ram") instanceof Boolean ? (Boolean) map.get("save ram") : false) : false;
  125.         boolean coprocessor = map.containsKey("coprocessor");
  126.         int cop = 0;
  127.         if (coprocessor) cop = getCoprocessor(map.get("coprocessor"));
  128.         return (byte) ((saveRAM ? 2 : 0) + cop);
  129.     }
  130.    
  131.     private static int getCoprocessor (Object cc) {
  132.         if (cc == null || !(cc instanceof String)) return 0;
  133.         String cop = (String) cc;
  134.         if (cop.matches("DSP-[1-4]")) return 0x03;
  135.         if (cop.equals("GSU") || cop.equals("SuperFX")) return 0x13;
  136.         if (cop.equals("OBC1")) return 0x23;
  137.         if (cop.equals("SA-1")) return 0x33;
  138.         if (cop.equals("S-DD1")) return 0x43;
  139.         if (cop.equals("S-RTC")) return 0x53;
  140.         return 0;
  141.     }
  142.    
  143.     private static byte getRegion (HashMap<String, Object> map) {
  144.         if (map.get("region") == null || !(map.get("region") instanceof String)) return (byte) 0;
  145.         if (((String) map.get("region")).equalsIgnoreCase("US")) return (byte) 0;
  146.         if (((String) map.get("region")).equalsIgnoreCase("USA")) return (byte) 0;
  147.         if (((String) map.get("region")).equalsIgnoreCase("America")) return (byte) 0;
  148.         if (((String) map.get("region")).equalsIgnoreCase("NTSC-U")) return (byte) 0;
  149.         if (((String) map.get("region")).equalsIgnoreCase("Japan")) return (byte) 1;
  150.         if (((String) map.get("region")).equalsIgnoreCase("JP")) return (byte) 1;
  151.         if (((String) map.get("region")).equalsIgnoreCase("NTSC-J")) return (byte) 1;
  152.         if (((String) map.get("region")).equalsIgnoreCase("France")) return (byte) 2;
  153.         if (((String) map.get("region")).equalsIgnoreCase("Germany")) return (byte) 2;
  154.         if (((String) map.get("region")).equalsIgnoreCase("United Kingdom")) return (byte) 2;
  155.         if (((String) map.get("region")).equalsIgnoreCase("UK")) return (byte) 2;
  156.         if (((String) map.get("region")).equalsIgnoreCase("Great Britain")) return (byte) 2;
  157.         if (((String) map.get("region")).equalsIgnoreCase("Britain")) return (byte) 2;
  158.         if (((String) map.get("region")).equalsIgnoreCase("EU")) return (byte) 2;
  159.         if (((String) map.get("region")).equalsIgnoreCase("PAL")) return (byte) 2;
  160.         return (byte) 0;
  161.     }
  162.    
  163.     private static byte getVersion (HashMap<String, Object> map) {
  164.         if (map.get("version") == null || !(map.get("version") instanceof Number)) return 0;
  165.         return ((Number) map.get("version")).byteValue();
  166.     }
  167.    
  168.     private static short getPauseVector (HashMap<String, Object> map) {
  169.         if (map.get("pause") == null || !(map.get("pause") instanceof Number)) return (short) 0xA000AFFF;
  170.         return Short.reverseBytes(((Number) map.get("pause")).shortValue());
  171.     }
  172.    
  173.     private static short getInterruptVector (HashMap<String, Object> map) {
  174.         if (map.get("interrupt") == null || !(map.get("interrupt") instanceof Number)) return (short) 0xA000AFFF;
  175.         return Short.reverseBytes(((Number) map.get("interrupt")).shortValue());
  176.     }
  177.    
  178.     private static short getResetVector (HashMap<String, Object> map) {
  179.         if (map.get("pause") == null || !(map.get("pause") instanceof Number)) throw new IllegalStateException("no defined reset vector");
  180.         return Short.reverseBytes(((Number) map.get("pause")).shortValue());
  181.     }
  182. }
  183.  
  184. public class JFROMLayout {
  185.     private static int[] rom = new int[64];
  186.    
  187.     private static ByteBuffer romData = ByteBuffer.allocate(0x400000);
  188.    
  189.     private static int codeBanks = 0;
  190.     private static int dataBanks = 0;
  191.    
  192.     public static int allocateCode (int size) {
  193.         for (int i = 0; i < rom.length; i++) {
  194.             int max = (i == 0) ? 0xFFAE : 0x010000;
  195.             if (i > codeBanks) {
  196.                 if (codeBanks + dataBanks >= 0xFF) throw new IllegalStateException("code and data clash");
  197.                 codeBanks++;
  198.             }
  199.             if (rom[i] + size < max) {
  200.                 int ret = rom[i] + 0xC00000 + (i << 16);
  201.                 rom[i] += size;
  202.                 return ret;
  203.             }
  204.         }
  205.         throw new IllegalStateException("rom overflow");
  206.     }
  207.    
  208.     public static int allocateData (int size) {
  209.         for (int i = rom.length - 1; i >= 0; i--) {
  210.             int max = (i == 0) ? 0xFFAE : 0x010000;
  211.             if (64 - i > dataBanks) {
  212.                 if (codeBanks + dataBanks >= 0xFF) throw new IllegalStateException("code and data clash");
  213.                 dataBanks++;
  214.             }
  215.             if (rom[i] + size < max) {
  216.                 int ret = rom[i] + 0xC00000 + (i << 16);
  217.                 rom[i] += size;
  218.                 return ret;
  219.             }
  220.         }
  221.         throw new IllegalStateException("rom overflow");
  222.     }
  223.    
  224.     public static void write (int address, byte[] data) {
  225.         romData.put(address, data);
  226.     }
  227. }
  228.  
  229. public class JFStruct extends JFType {
  230.     public final String name;
  231.     public final int size;
  232.    
  233.     public final String[] names;
  234.     public final JFType[] types;
  235.    
  236.     public JFStruct (String name, String[] names, JFType[] types) {
  237.         this.name = name;
  238.         int s = 0;
  239.         for (JFType t : types)
  240.             s += t.getSize();
  241.         this.size = s;
  242.         this.names = names;
  243.         this.types = types;
  244.         JFType.add(this.name, this);
  245.     }
  246.    
  247.     public static JFStruct compile (String string) {
  248.         Matcher m = Pattern.compile("struct (\\w+) \\{\\R((?:\\p{Blank}*\\w+ \\w+;\\R)*)\\}").matcher(string);
  249.         if (!m.matches()) throw new IllegalArgumentException("illegal struct definition");
  250.         String name = m.group(1);
  251.         String[] ss = m.group(2).split(";\n");
  252.         HashMap<String, JFType> map = new HashMap<String, JFType>();
  253.         Pattern p = Pattern.compile("\\p{Blank}*(\\w+) (\\w+);");
  254.         for (String s : ss) {
  255.             m = p.matcher(s);
  256.             if (!m.matches()) throw new IllegalArgumentException("illegal struct component definition");
  257.             String name2 = m.group(1);
  258.             if (map.containsKey(name2)) throw new IllegalArgumentException("struct component name in use");
  259.             JFType type = JFType.getPrimitive(m.group(2));
  260.             map.put(name2, type);
  261.         }
  262.         return new JFStruct(name, map.keySet().toArray(new String[map.size()]), map.values().toArray(new String[map.size()]));
  263.     }
  264.    
  265.     public int getSize () {
  266.         return this.size;
  267.     }
  268. }
  269.  
  270. public abstract class JFType {
  271.     private static HashMap<String, JFType> primitives = new HashMap<String, JFType>();
  272.     private static HashMap<String, JFType> structs = new HashMap<String, JFType>();
  273.    
  274.     static {
  275.         primitives.put("byte", JFPrimitiveType.BYTE);
  276.         primitives.put("word", JFPrimitiveType.WORD);
  277.         primitives.put("dword", JFPrimitiveType.DWORD);
  278.     }
  279.    
  280.     public static void add (String name, JFStruct struct) {
  281.         structs.put(name, struct);
  282.     }
  283.    
  284.     public static JFType getPrimitive (String name) {
  285.         if (!primitives.containsKey(name)) throw new IllegalArgumentException("no primitive type named " + name);
  286.         return primitives.get(name);
  287.     }
  288.    
  289.     public static JFType getStruct (String name) {
  290.         if (!structs.containsKey(name)) throw new IllegalArgumentException("no struct named " + name);
  291.         return structs.get(name);
  292.     }
  293.    
  294.     public static JFType getType (String name) {
  295.         if (!structs.containsKey(name)) return getPrimitive(name);
  296.         return structs.get(name);
  297.     }
  298.    
  299.     public abstract int getSize ();
  300. }
  301.  
  302. public class JFPrimitiveType extends JFType {
  303.     public static final JFPrimitiveType BYTE = new JFPrimitiveType(1);
  304.     public static final JFPrimitiveType WORD = new JFPrimitiveType(2);
  305.     public static final JFPrimitiveType DWORD = new JFPrimitiveType(4);
  306.    
  307.     public final int size;
  308.    
  309.     public JFPrimitiveType (int size) {
  310.         this.size = size;
  311.     }
  312.    
  313.     public int getSize () {
  314.         return this.size;
  315.     }
  316. }
  317.  
  318. public sealed interface JFField permits JFFinalField, JFNonFinalField {
  319.     public static JFField compile (String f) {
  320.         if (f.matches("final (\\w+) (\\w+)( = .*)?;"))
  321.             return compileFinal(f);
  322.         else
  323.             return compileNonFinal(f);
  324.     }
  325.    
  326.     private static JFFinalField compileFinal (String f) {
  327.         Matcher m = Pattern.compile("final (\\w+) (\\w+) = (.*);").matcher(f);
  328.         if (m.matches())
  329.             throw new IllegalArgumentException("final field was not assigned");
  330.         JFType type = JFType.getType(m.group(1));
  331.         String name = m.group(2);
  332.         String a = m.group(3);
  333.         m = Pattern.compile("new (\\w+) ?\\(((?:\\w+ \\w+, ?)+\\w+ \\w+)\\)").matcher(a);
  334.         if (m.matches()) {
  335.             if (!type.equals(JFType.getType(m.group(1)))) throw new IllegalArgumentException("struct constructor type does not match struct definition");
  336.             ByteBuffer b = ByteBuffer.allocate(type.getSize());
  337.             String[] array = m.group(2).split(",");
  338.             Pattern p = Pattern.compile(" ?(\\w+) (\\w+)");
  339.             for (int i = 0; i < array.length; i++) {
  340.                 m = p.matcher(array[i]);
  341.                 b.put(JFValue.parse(JFType.getPrimitive(m.group(1)), m.group(2)));
  342.             }
  343.             return new JFFinalField(name, type, b.array());
  344.         } else {
  345.             return new JFFinalField(name, type, JFValue.parse(type, a));
  346.         }
  347.     }
  348.    
  349.     private static JFNonFinalField compileNonFinal (String f) {
  350.         Matcher m = Pattern.compile("(?<type>\\w+) (?<assign>(?<name>\\w+) = (?:.*);)").matcher(f);
  351.         return new JFNonFinalField(m.group("name"), JFType.getType(m.group("type")), m.group("assign"));
  352.     }
  353. }
  354.  
  355. public final class JFNonFinalField implements JFField {
  356.     private static int staticMemory = 0;
  357.    
  358.     public final String name;
  359.     public final JFType type;
  360.     public final int address;
  361.    
  362.     public final String assignment;
  363.    
  364.     public JFNonFinalField (String name, JFType type) {
  365.         this.name = name;
  366.         this.type = type;
  367.         this.address = staticMemory + 0x7E1000;
  368.         this.assignment = assignment;
  369.         staticMemory += type.getSize();
  370.         if (staticMemory > 0xF000) throw new IllegalStateException("too many statically-allocated fields");
  371.     }
  372. }
  373.  
  374. public final class JFFinalField implements JFField {
  375.     public final String name;
  376.     public final JFType type;
  377.     public final byte[] data;
  378.    
  379.     public JFFinalField (String name, JFType type, byte[] data) {
  380.         this.name = name;
  381.         this.type = type;
  382.         this.data = data;
  383.     }
  384. }
  385.  
  386. public interface JFComponent {
  387.     void write (HashMap<String, Object> header);
  388. }
  389.  
  390. public interface JFInjection extends JFComponent {
  391.     public static JFInjection compile (String string) {
  392.         Matcher m = Pattern.compile("#(\\p{Alpha}+).*").matcher(string);
  393.         String type = m.group(1);
  394.         if (type.equals("import"))
  395.             return _import(string.substring(7));
  396.         else if (type.equals("title")) {
  397.             m = Pattern.compile("#title (.*)").matcher(string);
  398.             String title = m.group(1);
  399.             return new JFInjection () {
  400.                 public void write (HashMap<String, Object> header) {
  401.                     header.put("name", title);
  402.                 }
  403.             };
  404.         } else if (type.equals("region")) {
  405.             m = Pattern.compile("#region (.*)").matcher(string);
  406.             String region = m.group(1);
  407.             return new JFInjection () {
  408.                 public void write (HashMap<String, Object> header) {
  409.                     header.put("region", region);
  410.                 }
  411.             };
  412.         } else if (type.equals("coprocessor")) {
  413.             m = Pattern.compile("#coprocessor (.*)").matcher(string);
  414.             String region = m.group(1);
  415.             return new JFInjection () {
  416.                 public void write (HashMap<String, Object> header) {
  417.                     header.put("coprocessor", region);
  418.                 }
  419.             };
  420.         } else if (type.equals("table")) {
  421.             m = Pattern.compile("#table (\\w+) [((?:\\w+ )*\\w+)]").matcher(string);
  422.             String name = m.group(1);
  423.             if (m.group(2).equals("")) throw new IllegalArgumentException("empty data table");
  424.             String[] params = m.group(2).split(" ");
  425.             byte[] data = new byte[params.length];
  426.             for (int i = 0; i < params.length; i++) data[i] = Byte.parseByte(params[i]);
  427.             int address = JFROMLayout.allocateData(data.length);
  428.             return new JFInjection () {
  429.                 public void write (HashMap<String, Object> header) {
  430.                     JFROMLayout.write(address, data);
  431.                     header.put("table " + name, Integer.valueOf(address));
  432.                 }
  433.             };
  434.         }
  435.     }
  436.    
  437.     public static JFInjection _import (String sub) {
  438.         Matcher m = Pattern.compile(" (.+) as (\\w+)(?:, (\\w+))").matcher(sub);
  439.         byte[] data = Files.readAllBytes(new File(m.group(1)).toPath());
  440.         String name = m.group(2);
  441.         String type = m.group(3);
  442.         if (m.group(2) == null) type = "binary";
  443.         data = JFDataConverters.get(type).convert(data);
  444.         int address = JFROMLayout.allocateData(data.length);
  445.         return new JFInjection () {
  446.             public void write (HashMap<String, Object> header) {
  447.                 JFROMLayout.write(address, data);
  448.                 header.put("import " + name, Integer.valueOf(address));
  449.             }
  450.         };
  451.     }
  452. }
  453.  
  454. public class JFAnnotationTemplate {
  455.     public final String type;
  456.     public final String[] params;
  457.    
  458.     public JFAnnotationTemplate (String type, String[] params) {
  459.         this.type = type;
  460.         this.params = params;
  461.     }
  462.    
  463.     public static JFAnnotationTemplate compile (String annotation) {
  464.         Matcher m = Pattern.compile("@(\\w+)\\(((?:\\w+, ?)*\\w+)\\)").matcher(annotation);
  465.         String type = m.group(1);
  466.         String[] params = m.group(2).split(",");
  467.         for (int i = 0; i < params.length; i++) params[i] = params[i].stripLeading();
  468.         return new JFAnnotationTemplate(type, params);
  469.     }
  470. }
  471.  
  472. public class JFValue {
  473.     public static byte[] parse (JFType type, String value) {
  474.         if (!(type instanceof JFPrimitiveType)) throw new IllegalArgumentException("attempted to parse an invalid type");
  475.         if (type == JFPrimitiveType.BYTE) return parseByte(value);
  476.         else if (type == JFPrimitiveType.WORD) return parseWord(value);
  477.         else if (type == JFPrimitiveType.DWORD) return parseDWord(value);
  478.         else System.exit(177);
  479.     }
  480.    
  481.     private static byte[] parseByte (String value) {
  482.         Matcher m = Pattern.compile("(['\"])(.)\\1").matcher(value);
  483.         if (m.matches())
  484.             return m.group(2).getBytes(StandardCharsets.US_ASCII);
  485.         m = Pattern.compile("0x([0-9a-fA-F]{1,2})").matcher(value);
  486.         if (m.matches())
  487.             return new byte[] { Byte.parseByte(m.group(1), 16) };
  488.         m = Pattern.compile("0o?([0-3]?[0-7]{1,2})").matcher(value);
  489.         if (m.matches())
  490.             return new byte[] { Byte.parseByte(m.group(1), 8) };
  491.         m = Pattern.compile("0b?([01]{1,8})").matcher(value);
  492.         if (m.matches())
  493.             return new byte[] { Byte.parseByte(m.group(1), 2) };
  494.         return new byte[] { Byte.parseByte(value, 10) };
  495.     }
  496.    
  497.     private static byte[] parseWord (String value) {
  498.         Matcher m = Pattern.compile("(['\"])(..)\\1").matcher(value);
  499.         if (m.matches())
  500.             return m.group(2).getBytes(StandardCharsets.US_ASCII);
  501.         ByteBuffer b = ByteBuffer.allocate(2);
  502.         m = Pattern.compile("0x([0-9a-fA-F]{1,4})").matcher(value);
  503.         if (m.matches())
  504.             return b.putShort(Short.parseShort(m.group(1), 16)).array();
  505.         m = Pattern.compile("0o?([01]?[0-7]{1,5})").matcher(value);
  506.         if (m.matches())
  507.             return b.putShort(Short.parseShort(m.group(1), 8)).array();
  508.         m = Pattern.compile("0b?([01]{1,16})").matcher(value);
  509.         if (m.matches())
  510.             return b.putShort(Short.parseShort(m.group(1), 2)).array();
  511.         return b.putShort(Short.parseShort(m.group(1), 10)).array();
  512.     }
  513.    
  514.     private static byte[] parseDWord (String value) {
  515.         Matcher m = Pattern.compile("(['\"])(....)\\1").matcher(value);
  516.         if (m.matches())
  517.             return m.group(2).getBytes(StandardCharsets.US_ASCII);
  518.         ByteBuffer b = ByteBuffer.allocate(4);
  519.         m = Pattern.compile("0x([0-9a-fA-F]{1,8})").matcher(value);
  520.         if (m.matches())
  521.             return b.putInt(Integer.parseInt(m.group(1), 16)).array();
  522.         m = Pattern.compile("0o?([0-3]?[0-7]{1,10})").matcher(value);
  523.         if (m.matches())
  524.             return b.putInt(Integer.parseInt(m.group(1), 8)).array();
  525.         m = Pattern.compile("0b?([01]{1,32})").matcher(value);
  526.         if (m.matches())
  527.             return b.putInt(Integer.parseInt(m.group(1), 2)).array();
  528.         return b.putInt(Integer.parseInt(m.group(1), 10)).array();
  529.     }
  530. }
  531.  
  532. public class JFDataConverters {
  533.     private static final HashMap<String, JFDataConverter> REGISTRY = new HashMap<String, JFDataConverter>();
  534.    
  535.     static {
  536.         REGISTRY.put("binary", (d, m) -> d);
  537.     }
  538.    
  539.     public static JFDataConverter get (String s) {
  540.         return REGISTRY.get(s);
  541.     }
  542. }
  543.  
  544. public interface JFDataConverter {
  545.     byte[] convert (byte[] input, HashMap<String, Object> map);
  546. }
Advertisement
Add Comment
Please, Sign In to add comment