/* * Copyright (C) 2011. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 or * version 2 as published by the Free Software Foundation. * * 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. */ package uk.me.parabola.imgfmt.app.mdr; import java.util.ArrayList; import java.util.List; import uk.me.parabola.imgfmt.app.ImgFileWriter; import uk.me.parabola.imgfmt.app.srt.Sort; import uk.me.parabola.imgfmt.app.srt.SortKey; /** * An index of countries sorted by name with pointers to the other country related sections. * There is only one per name, not per name and map. * * @author Steve Ratcliffe */ public class Mdr29 extends MdrSection implements HasHeaderFlags { private final List<Mdr29Record> index = new ArrayList<>(); private int max17; public Mdr29(MdrConfig config) { setConfig(config); } public void buildFromCountries(List<Mdr14Record> countries) { Sort sort = getConfig().getSort(); List<SortKey<Mdr14Record>> keys = MdrUtils.sortList(sort, countries); // Sorted by name, for every new name we allocate a new 29 record and set the same one in every // country with the same name. String lastName = null; Mdr29Record mdr29 = null; for (SortKey<Mdr14Record> key : keys) { Mdr14Record country = key.getObject(); String name = country.getName(); if (!name.equals(lastName)) { mdr29 = new Mdr29Record(); mdr29.setName(name); mdr29.setStrOffset(country.getStrOff()); index.add(mdr29); lastName = name; } assert mdr29 != null; country.setMdr29(mdr29); } } protected void preWriteImpl() { if (!index.isEmpty()) { Mdr29Record r = index.get(index.size() - 1); this.max17 = r.getMdr17(); } } /** * Write out the contents of this section. * * @param writer Where to write it. */ public void writeSectData(ImgFileWriter writer) { int magic = getExtraValue(); boolean hasString = (magic & 1) != 0; boolean has26 = (magic & 0x8) != 0; boolean has17 = (magic & 0x30) != 0; PointerSizes sizes = getSizes(); int size24 = sizes.getSize(24); int size22 = sizes.getSize(22); int size25 = sizes.getSize(5); // NB appears to be size of 5 (cities), not 25 (cities with country). int size26 = has26? sizes.getSize(26): 0; int size17 = numberToPointerSize(max17); for (Mdr29Record record : index) { putN(writer, size24, record.getMdr24()); if (hasString) putStringOffset(writer, record.getStrOffset()); putN(writer, size22, record.getMdr22()); putN(writer, size25, record.getMdr25()); if (has26) putN(writer, size26, record.getMdr26()); if (has17) putN(writer, size17, record.getMdr17()); } } /** * The size of a record in the section. This is not a constant and might vary * on various factors, such as the file version, if we are preparing for a * device, the number of maps etc. * * @return The size of a record in this section. */ public int getItemSize() { PointerSizes sizes = getSizes(); int size = sizes.getSize(24) + sizes.getSize(22) + sizes.getSize(5) // NB: not 25 ; if (isForDevice()) { size += numberToPointerSize(max17); } else { size += sizes.getStrOffSize(); size += sizes.getSize(26); } return size; } /** * The number of records in this section. * * @return The number of items in the section. */ protected int numberOfItems() { return index.size(); } /** * Unknown flags. * * As there are 4 bits set and 4 extra fields, that might be it. Compare * to mdr28 where there are 3 extra fields and 3 bits set. Just a guess... */ public int getExtraValue() { if (isForDevice()) { int magic = 0x6; // 22 and 25 magic |= numberToPointerSize(max17) << 4; return magic; // +17, -26, -strings } else return 0xf; // strings, 22, 25 and 26 } }