<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Archivos de Programming - Nobody comes after the last</title>
	<atom:link href="https://blog.krusher.net/en/category/computing/programming/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.krusher.net/en/category/computing/programming/</link>
	<description>Because someone had to think of the fishes</description>
	<lastBuildDate>Tue, 06 May 2025 14:57:19 +0000</lastBuildDate>
	<language>en-GB</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://blog.krusher.net/wp-content/uploads/2016/02/cropped-detras-del-ultimo-no-va-nadie-icon-32x32.jpg</url>
	<title>Archivos de Programming - Nobody comes after the last</title>
	<link>https://blog.krusher.net/en/category/computing/programming/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>About how to clone a Prestashop instance</title>
		<link>https://blog.krusher.net/en/2025/05/about-how-to-clone-a-prestashop-instance/</link>
					<comments>https://blog.krusher.net/en/2025/05/about-how-to-clone-a-prestashop-instance/#respond</comments>
		
		<dc:creator><![CDATA[Krusher]]></dc:creator>
		<pubDate>Tue, 06 May 2025 14:57:19 +0000</pubDate>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[clone]]></category>
		<category><![CDATA[prestashop]]></category>
		<guid isPermaLink="false">https://blog.krusher.net/?p=2814</guid>

					<description><![CDATA[<p>Lately, I&#8217;ve been helping my neighbor with his Prestashop website. I&#8217;ve learned a few tricks, like editing the overall appearance of the site, making and restoring backups in a limited environment, but my best invention has been cloning the Prestashop instance to have a test version where I can try things out without fear of &#8230; <a href="https://blog.krusher.net/en/2025/05/about-how-to-clone-a-prestashop-instance/" class="more-link">Continue reading<span class="screen-reader-text"> "About how to clone a Prestashop instance"</span></a></p>
<p>La entrada <a href="https://blog.krusher.net/en/2025/05/about-how-to-clone-a-prestashop-instance/">About how to clone a Prestashop instance</a> se publicó primero en <a href="https://blog.krusher.net/en">Nobody comes after the last</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Lately, I&#8217;ve been helping my neighbor with his Prestashop website. I&#8217;ve learned a few tricks, like editing the overall appearance of the site, making and restoring backups in a limited environment, but my best invention has been cloning the Prestashop instance to have a test version where I can try things out without fear of breaking anything. Here&#8217;s the code for anyone who might find it useful, <a href="https://www.gnu.org/licenses/gpl-3.0.html#license-text" target="_blank" rel="noopener">licensed under GPL 3</a>.</p>
<p>You can see the code here, too: <a href="https://gist.github.com/axelei/dafd305213ed1b2655545f06edfbc905" target="_blank" rel="noopener">https://gist.github.com/axelei/dafd305213ed1b2655545f06edfbc905</a></p>
<pre class="brush: bash; title: ; notranslate">
# Programa para clonar prestashop
# Copyright Krusher 2015 - Licenciado bajo GPL3

paramfile=&quot;httpdocs/app/config/parameters.php&quot;
extractDatabaseName=&quot;s/.*&#039;database_name&#039; =&amp;gt; &#039;\(.*\)&#039;.*/\1/p&quot;
extractDatabaseUser=&quot;s/.*&#039;database_user&#039; =&amp;gt; &#039;\(.*\)&#039;.*/\1/p&quot;
extractDatabasePassword=&quot;s/.*&#039;database_password&#039; =&amp;gt; &#039;\(.*\)&#039;.*/\1/p&quot;

if &#x5B; &quot;$#&quot; -lt 4 ]; then
  echo &quot;Error: Se requieren 3 argumentos.&quot;
  echo &quot;Uso: $0 dir_web_original dir_web_destino url_original url_destino&quot;
  exit 1
fi

echo Traspasando de $1 a $2 \(urls: $3 -- $4 \)

databaseName=$(sed -n &quot;$extractDatabaseName&quot; $1/app/config/parameters.php)
databaseUser=$(sed -n &quot;$extractDatabaseUser&quot; $1/app/config/parameters.php)
databasePassword=$(sed -n &quot;$extractDatabasePassword&quot; $1/app/config/parameters.php)

echo Datos de la base de datos de origen: $databaseName / $databaseUser / $databasePassword

targetName=$(sed -n &quot;$extractDatabaseName&quot; $2/app/config/parameters.php)
targetUser=$(sed -n &quot;$extractDatabaseUser&quot; $2/app/config/parameters.php)
targetPassword=$(sed -n &quot;$extractDatabasePassword&quot; $2/app/config/parameters.php)

echo Datos de la base de datos de destino: $targetName / $targetUser / $targetPassword

if &#x5B;&#x5B; -z &quot;$databaseName&quot; ]] || &#x5B;&#x5B; -z &quot;$databaseUser&quot; ]] || &#x5B;&#x5B; -z &quot;$databasePassword&quot; ]] || &#x5B;&#x5B; -z &quot;$targetName&quot; ]] || &#x5B;&#x5B; -z &quot;$targetUser&quot; ]] || &#x5B;&#x5B; -z &quot;$targetPassword&quot; ]]; then
  echo &quot;Error: Algunas de las variables no han sido extraídas, comprueba los errores y los directorios.&quot;
  exit 1
fi

echo URL de la instancia origen: $3
echo URL de la instancia destino: $4

read -p &quot;Pulsa enter para continuar o CTRL+C para cancelar&quot;
echo  &quot;Procediendo con el traspaso.&quot;

echo Extrayendo base de datos
rm -f temp.sql
mysqldump -u $databaseUser $databaseName -p$databasePassword &amp;gt; temp.sql
echo Borrando base de datos objetivo
mysql -u $targetUser $targetName -p$targetPassword -e &quot;drop database $targetName; create database $targetName&quot;
echo Insertando la base de datos origen en la objetivo
mysql -u $targetUser -D $targetName -p$targetPassword &amp;lt; temp.sql
rm -f temp.sql

echo borra ficheros contenido antiguo
rm -Rf $2/*
echo copia ficheros
cp -r $1/* $2/

echo Configurando base de datos objetivo con los datos originales

sed -i &quot;s/&#039;database_name&#039; =&amp;gt; &#039;\(.*\)&#039;/&#039;database_name&#039; =&amp;gt; &#039;$targetName&#039;/g&quot; $2/app/config/parameters.php
sed -i &quot;s/&#039;database_user&#039; =&amp;gt; &#039;\(.*\)&#039;/&#039;database_user&#039; =&amp;gt; &#039;$targetUser&#039;/g&quot; $2/app/config/parameters.php
sed -i &quot;s/&#039;database_password&#039; =&amp;gt; &#039;\(.*\)&#039;/&#039;database_password&#039; =&amp;gt; &#039;$targetPassword&#039;/g&quot; $2/app/config/parameters.php

echo Configurando la nueva URL en la instancia destino

mysql -u $targetUser $targetName -p$targetPassword -e &quot;update prstshp_configuration set value = &#039;$4&#039; where NAME IN (&#039;PS_SHOP_DOMAIN&#039;, &#039;PS_SHOP_DOMAIN_SSL&#039;)&quot;
mysql -u $targetUser $targetName -p$targetPassword -e &quot;UPDATE prstshp_shop_url SET domain = &#039;$4&#039;, domain_ssl = &#039;$4&#039; WHERE id_shop_url = 1;&quot;
sed -i s/\\^$3\\$/^$4$/g $2/.htaccess

echo Terminado.
</pre>
<p>The implementation could undoubtedly be improved—using a more suitable language or more advanced tools—but this is the solution I came up with given the constraints of an environment lacking many essential utilities and commands. If you found it helpful, feel free to share your experience in the comments.</p>
<p>La entrada <a href="https://blog.krusher.net/en/2025/05/about-how-to-clone-a-prestashop-instance/">About how to clone a Prestashop instance</a> se publicó primero en <a href="https://blog.krusher.net/en">Nobody comes after the last</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.krusher.net/en/2025/05/about-how-to-clone-a-prestashop-instance/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Taking Sim City 2000 into pieces</title>
		<link>https://blog.krusher.net/en/2017/12/taking-sim-city-2000-into-pieces/</link>
					<comments>https://blog.krusher.net/en/2017/12/taking-sim-city-2000-into-pieces/#comments</comments>
		
		<dc:creator><![CDATA[Krusher]]></dc:creator>
		<pubDate>Sat, 09 Dec 2017 23:15:00 +0000</pubDate>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Videogames]]></category>
		<category><![CDATA[maxis]]></category>
		<category><![CDATA[sim city 2000]]></category>
		<guid isPermaLink="false">https://blog.krusher.net/?p=1766</guid>

					<description><![CDATA[<p>SimCity 2000 (Maxis, 1993) is one of my superfavourite games, ever. I&#8217;ve been playing it for 20 years and it&#8217;s partially responsible of my terrible grades at high school. I have always liked modifying games, but so far I haven&#8217;t been serious about decoding the data files of this city simulator. And I have found &#8230; <a href="https://blog.krusher.net/en/2017/12/taking-sim-city-2000-into-pieces/" class="more-link">Continue reading<span class="screen-reader-text"> "Taking Sim City 2000 into pieces"</span></a></p>
<p>La entrada <a href="https://blog.krusher.net/en/2017/12/taking-sim-city-2000-into-pieces/">Taking Sim City 2000 into pieces</a> se publicó primero en <a href="https://blog.krusher.net/en">Nobody comes after the last</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><strong>SimCity 2000</strong> (<strong>Maxis</strong>, 1993) is one of my superfavourite games, ever. I&#8217;ve been playing it for 20 years and it&#8217;s partially responsible of my terrible grades at high school. I have always liked modifying games, but so far I haven&#8217;t been serious about decoding the data files of this city simulator. And I have found some quite interesting things!</p>
<p>There were ports in a great number of platforms, from the <strong>Macintosh</strong> (the original) to <strong>GameBoy Advance</strong>, but my favourite is <strong>MS-DOS</strong>, and it&#8217;s what this article is about. There are two interesting files: the executable (SC2000.EXE) and the data file (SC2000.DAT). Unfortunately, <strong>Windows</strong> version didn&#8217;t came out in Spanish (my mother language), and <em>Network Edition</em> version works awfully bad (and it is available only in English).<span id="more-1766"></span></p>
<h2>SC2000.EXE</h2>
<p>The game executable does not seem to have many resources, but it does have some interface texts. In the hexadecimal editor we can see some fixed-width labels.</p>
<p><a href="https://blog.krusher.net/wp-content/uploads/2017/06/Sc2000-cadenasexe.png" data-rel="lightbox-gallery-xktDizQn" data-rl_title="" data-rl_caption="" title=""><img fetchpriority="high" decoding="async" class="aligncenter size-large wp-image-1526" src="https://blog.krusher.net/wp-content/uploads/2017/06/Sc2000-cadenasexe-1024x435.png" alt="" width="840" height="357" srcset="https://blog.krusher.net/wp-content/uploads/2017/06/Sc2000-cadenasexe-1024x435.png 1024w, https://blog.krusher.net/wp-content/uploads/2017/06/Sc2000-cadenasexe-300x127.png 300w, https://blog.krusher.net/wp-content/uploads/2017/06/Sc2000-cadenasexe-768x326.png 768w, https://blog.krusher.net/wp-content/uploads/2017/06/Sc2000-cadenasexe.png 1090w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></a></p>
<p>There are some texts representing variable-width labels, too. There are also some embedded files, in which for example game scenarios are described.</p>
<p><a href="https://blog.krusher.net/wp-content/uploads/2017/06/Sc2000-cadenasexe2.png" data-rel="lightbox-gallery-xktDizQn" data-rl_title="" data-rl_caption="" title=""><img decoding="async" class="aligncenter size-large wp-image-1527" src="https://blog.krusher.net/wp-content/uploads/2017/06/Sc2000-cadenasexe2-1024x435.png" alt="" width="840" height="357" srcset="https://blog.krusher.net/wp-content/uploads/2017/06/Sc2000-cadenasexe2-1024x435.png 1024w, https://blog.krusher.net/wp-content/uploads/2017/06/Sc2000-cadenasexe2-300x127.png 300w, https://blog.krusher.net/wp-content/uploads/2017/06/Sc2000-cadenasexe2-768x326.png 768w, https://blog.krusher.net/wp-content/uploads/2017/06/Sc2000-cadenasexe2.png 1090w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></a></p>
<p>At the moment disassembling an executable from the early 90s is not one of my specialities, and thus I have not find out much. Pointers are not evident in the executable, so I left it alone. But the most interesting is the data files we are describing down below.</p>
<h2>SC2000.DAT</h2>
<p>This is the main data file. It does not have a header, but a short look in the hexadecimal editor throw some hints about its structure.</p>
<p><a href="https://blog.krusher.net/wp-content/uploads/2017/06/sc2000.dat_.png" data-rel="lightbox-gallery-xktDizQn" data-rl_title="" data-rl_caption="" title=""><img decoding="async" class="aligncenter size-large wp-image-1528" src="https://blog.krusher.net/wp-content/uploads/2017/06/sc2000.dat_-1024x435.png" alt="" width="840" height="357" srcset="https://blog.krusher.net/wp-content/uploads/2017/06/sc2000.dat_-1024x435.png 1024w, https://blog.krusher.net/wp-content/uploads/2017/06/sc2000.dat_-300x127.png 300w, https://blog.krusher.net/wp-content/uploads/2017/06/sc2000.dat_-768x326.png 768w, https://blog.krusher.net/wp-content/uploads/2017/06/sc2000.dat_.png 1090w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></a></p>
<p>It turns out that from byte 0 the first we can find is 16-byte blocks that describe files contained in the pack. The first field is evident: 12 bytes with the file name (8 + 3 characters of the <strong>MS-DOS</strong> file with the period). If there is leftover space, the rest of the bytes are 00h.</p>
<p>The other two bytes are not so evident, but it turns out that the game is originary from <strong>Macintosh</strong>, which at that time used <strong>Motorola</strong> processors. These processors, unlike <strong>Intel</strong>&#8216;s, are <em>Little-Endian</em> (being <strong>Intel</strong> <em>Big-Indian</em>). This means that numbers with more than one byte are stored ordered from the least significant byte to the most significant, instead of the &#8220;natural&#8221; ordering. This is thus a 32 bit unsigned integer in <em>little-endian</em> format, which codifies the offset of the file just before.</p>
<p>I owe the happy idea about the offset to <a href="http://www.brettlajzer.com/36" target="_blank" rel="noopener noreferrer">Brett Lajzer</a>, an Albany software engineer that began researching this file before me. I wrote him to swap information and advised me about this point, which he didn&#8217;t finally describe in his article.</p>
<p>Unpacking and packing, knowing this, is relatively simple. I&#8217;ve written a small Java program that makes this operation easy:</p>
<pre class="brush: java; title: ; notranslate">
package sce2000;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.io.FileUtils;

public class Sce2000 {
	
	public static final String SC2000DAT = &quot;G:\\dos\\sce2000\\sc2000.dat&quot;;
	public static final int NUMFILES = 399;
	
	public static class Filestrut implements Serializable {
		private static final long serialVersionUID = 1L;
		public String filename;
		public int offset;
		public int targetOffset;
	}

	public static void main(String&#x5B;] args) throws IOException, ClassNotFoundException {
		
		if (args.length == 0) {
			info();
		} else if (&quot;x&quot;.equals(args&#x5B;0])) {
			extract();
		} else if (&quot;c&quot;.equals(args&#x5B;0])) {
			create();
		} else {
			info();
		}

	}
	
	public static void info() {
		System.out.println(&quot;Usage: x to eXtract or c to Create (after eXtract) + sc2000.dat file&quot;);
	}

	public static void create() throws IOException, ClassNotFoundException {
		
		File sc2000dat = new File(SC2000DAT);
		File metafile = new File(SC2000DAT + &quot;!/meta&quot;);
		ObjectInputStream ois = new ObjectInputStream(new FileInputStream(metafile));
		List&lt;Filestrut&gt; files = (List&lt;Filestrut&gt;) ois.readObject();
		
		List&lt;Byte&gt; targetFile = new ArrayList&lt;Byte&gt;();

		for (Filestrut file : files) {
			byte&#x5B;] fileNameBytes = file.filename.getBytes(StandardCharsets.US_ASCII);
			for (Byte myByte : fileNameBytes) {
				targetFile.add(myByte);
			}
			for (int i = 0; i &lt; 16 - fileNameBytes.length; i++) {
				targetFile.add((byte) 0);
			}
			//sourceFile.length();
		}
		
		int i = 0;
		for (Filestrut file : files) {
			byte&#x5B;] binary = Files.readAllBytes(Paths.get(SC2000DAT + &quot;!/&quot; + file.filename));
			int fileOffset = targetFile.size();
			for (Byte myByte : binary) {
				targetFile.add(myByte);
			}
			int filePointer = 12 + (16 * i);
			
			byte&#x5B;] offsetBytes = fromInt(fileOffset);
			targetFile.set(filePointer, offsetBytes&#x5B;0]);
			targetFile.set(filePointer + 1, offsetBytes&#x5B;1]);
			targetFile.set(filePointer + 2, offsetBytes&#x5B;2]);
			targetFile.set(filePointer + 3, offsetBytes&#x5B;3]);
			
			i++;
		}
		
		byte&#x5B;] binaryFile = new byte&#x5B;targetFile.size()];
		for (i = 0; i &lt; targetFile.size(); i++) {
			binaryFile&#x5B;i] = targetFile.get(i);
		}
		
		FileUtils.writeByteArrayToFile(sc2000dat, binaryFile);

		
		System.out.println();
		
	}
		

	public static void extract() throws IOException {
		
		Path sc2000dat = Paths.get(SC2000DAT);
		byte&#x5B;] data = Files.readAllBytes(sc2000dat);
		
		int vector = 0;
		List&lt;Filestrut&gt; files = new ArrayList&lt;Filestrut&gt;();
		for (int i = 0; i &lt; NUMFILES; i++) {
			
			Filestrut currfile = new Filestrut();
			
			currfile.filename =  convertFilename(Arrays.copyOfRange(data, vector, vector + 12));
			vector += 12;
			
			currfile.offset = fromByteArray(Arrays.copyOfRange(data, vector, vector + 4));
			vector += 4;
			
			System.out.println(&quot;Found file &quot; + currfile.filename + &quot; at &quot; + currfile.offset);
			
			files.add(currfile);
			
		}
		
		File dir = new File(SC2000DAT + &quot;!&quot;);
		if (dir.exists()) {
			FileUtils.deleteDirectory(dir);
		}
		
		dir.mkdir();
		
		Iterator&lt;Filestrut&gt; fileIt = files.iterator();
		
		Filestrut file = fileIt.next();
		Filestrut fileNext = null;
		
		boolean stop = false;
		while (!stop) {
			
			File extracted = new File(SC2000DAT + &quot;!/&quot; + file.filename);
			
			int init = file.offset;
			int end = -1;
			if (fileIt.hasNext()) {
				fileNext = fileIt.next();
				end = fileNext.offset;
			} else {
				end = data.length;
				stop = true;
			}

			System.out.println(&quot;Writing: &quot; + extracted.getAbsolutePath());
			FileUtils.writeByteArrayToFile(extracted, Arrays.copyOfRange(data, init, end));
			
			file = fileNext;
			
		}
		
		File metafile = new File(SC2000DAT + &quot;!/meta&quot;);
		
		ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(metafile));
		oos.writeObject(files);
		oos.close();
		
		System.out.println(&quot;OK!&quot;);
	}
	
	public static byte&#x5B;] fromInt(int number) {
		byte&#x5B;] bytes = ByteBuffer.allocate(4).putInt(number).array();
		swapEndianess(bytes);
		return bytes;
	}
	
	public static void swapEndianess(byte &#x5B;] bytes) {
		byte temp1 = bytes&#x5B;0];
		byte temp2 = bytes&#x5B;1];
		bytes&#x5B;0] = bytes&#x5B;3];
		bytes&#x5B;1] = bytes&#x5B;2];
		bytes&#x5B;2] = temp2;
		bytes&#x5B;3] = temp1;
	}
	
	public static int fromByteArray(byte&#x5B;] bytes) {
		// Change endianness
		swapEndianess(bytes);
		return ByteBuffer.wrap(bytes).getInt();
	}
	
	public static String convertFilename(byte&#x5B;] data) {
	    StringBuilder sb = new StringBuilder(data.length);
	    for (int i = 0; i &lt; data.length; ++ i) {
	        if (data&#x5B;i] &lt; 0) { 
	        	throw new IllegalArgumentException();
	        }
	        if (data&#x5B;i] == 0) {
	        	break;
	        }
	        sb.append((char) data&#x5B;i]);
	    }
	    return sb.toString();
	}


}
</pre>
<p>This program has been done quick and dirty and it&#8217;s not what we would say optimized. I indulged myself loading the whole files in memory as the complete DAT file is few megabytes big. Also it has the file count and DAT path hardcoded in the code. Making it better and more efficient is left as an exercise to the reader.</p>
<p>Why in Java? It&#8217;s not the most appropriate for handling binaries, and not having unsigned types support doesn&#8217;t precisely help. I simply did it in Java and not in C because it&#8217;s the language I use for a living, and the one I&#8217;m the most fluent with. Also I&#8217;ve not programmed anything in C for 10 years. 🙂</p>
<p>Using the above code (or any other the intrepid reader can code) we can see the following file types:</p>
<ul>
<li>RAW, as the header-less image files.</li>
<li>PAL, as the colour palette used in the game.</li>
<li>Text files, some as TXT* without an extension and others with RAW extension.</li>
<li>XMI, with the music.</li>
<li>VOC, with the sound effect files.</li>
<li>FNT, with the typography files.</li>
<li>Etc, etc&#8230;</li>
</ul>
<p>Let&#8217;s talk about them a bit one by one.</p>
<h2>VOC files</h2>
<p>The game sound files are stored in VOC files. Well, that&#8217;s one is easy, as it&#8217;s not a common file format but broadly supported on many sound edition programs. It&#8217;s a format by Creative Labs that chiefly stores PCM and ADPCM coded audio, although sometimes has been used for other encodings.</p>
<p><a href="https://blog.krusher.net/wp-content/uploads/2017/06/sc2000-vocs.jpg" data-rel="lightbox-gallery-xktDizQn" data-rl_title="" data-rl_caption="" title=""><img loading="lazy" decoding="async" class="aligncenter size-large wp-image-1531" src="https://blog.krusher.net/wp-content/uploads/2017/06/sc2000-vocs-1024x560.jpg" alt="" width="840" height="459" srcset="https://blog.krusher.net/wp-content/uploads/2017/06/sc2000-vocs-1024x560.jpg 1024w, https://blog.krusher.net/wp-content/uploads/2017/06/sc2000-vocs-300x164.jpg 300w, https://blog.krusher.net/wp-content/uploads/2017/06/sc2000-vocs-768x420.jpg 768w, https://blog.krusher.net/wp-content/uploads/2017/06/sc2000-vocs-1200x656.jpg 1200w, https://blog.krusher.net/wp-content/uploads/2017/06/sc2000-vocs.jpg 1920w" sizes="auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></a></p>
<p>It can be perfectly open and saved with Adobe Audition. The sampling frequency varies from one file to another, but is recognized without many problems.</p>
<h2>Text files</h2>
<p>There are three kinds of text file types. The most simple are TXT* files without an extension, being * a number. They can be directly opened with <strong>Notepad++</strong> and be edited without problems.</p>
<p><a href="https://blog.krusher.net/wp-content/uploads/2017/06/sc2000-txt.jpg" data-rel="lightbox-gallery-xktDizQn" data-rl_title="" data-rl_caption="" title=""><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-1532" src="https://blog.krusher.net/wp-content/uploads/2017/06/sc2000-txt.jpg" alt="" width="787" height="496" srcset="https://blog.krusher.net/wp-content/uploads/2017/06/sc2000-txt.jpg 787w, https://blog.krusher.net/wp-content/uploads/2017/06/sc2000-txt-300x189.jpg 300w, https://blog.krusher.net/wp-content/uploads/2017/06/sc2000-txt-768x484.jpg 768w" sizes="auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 984px) 61vw, (max-width: 1362px) 45vw, 600px" /></a></p>
<p>Well, not quite. Encoding is not ASCII, nor UNICODE because it wasn&#8217;t common at the time. Which one, then? Well, being the game was programmed for Macintosh, encoding is <a href="https://en.wikipedia.org/wiki/Mac_OS_Roman" target="_blank" rel="noopener">Macintosh Roman</a>. This is a problem because <strong>Notepad++</strong> does not support it. <a href="https://notepad-plus-plus.org/community/topic/11052/mac-encoding" target="_blank" rel="noopener">It&#8217;s been asked for</a>, but seems not the priority, so you might want to convert it somehow to edit it more comfortably.</p>
<p><strong>Addendum</strong>: It supports it after all! The option was buried in the menus: <strong>Encoding</strong> &gt; <strong>Character Sets</strong> &gt; <strong>Cyrillic</strong> &gt; <strong>Macintosh.</strong></p>
<p>Other text files are STR*.RAW and *.RAW, being * a number. Their format is not so nice.</p>
<p><a href="https://blog.krusher.net/wp-content/uploads/2017/06/sc2000-str.jpg" data-rel="lightbox-gallery-xktDizQn" data-rl_title="" data-rl_caption="" title=""><img loading="lazy" decoding="async" class="aligncenter size-large wp-image-1533" src="https://blog.krusher.net/wp-content/uploads/2017/06/sc2000-str-1024x435.jpg" alt="" width="840" height="357" srcset="https://blog.krusher.net/wp-content/uploads/2017/06/sc2000-str-1024x435.jpg 1024w, https://blog.krusher.net/wp-content/uploads/2017/06/sc2000-str-300x127.jpg 300w, https://blog.krusher.net/wp-content/uploads/2017/06/sc2000-str-768x326.jpg 768w, https://blog.krusher.net/wp-content/uploads/2017/06/sc2000-str.jpg 1090w" sizes="auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></a></p>
<p>So the first byte is always 00h, and the second seems to store the string count in the text. Strings, unlike in C, aren&#8217;t coded terminated in 00h. They are stored preceeded by its length, coded in 1 byte. Ideally we could use an utility software for this, which could easily be coded. (but I don&#8217;t feel like to)</p>
<p>The third text file kind correspond only to PPDT1003.RAW file, which has one of the funniest characteristics in all <strong>SimCity 2000</strong>: the newspapers.</p>
<p><a href="https://blog.krusher.net/wp-content/uploads/2017/06/sc2000-periodicos.png" data-rel="lightbox-gallery-xktDizQn" data-rl_title="" data-rl_caption="" title=""><img loading="lazy" decoding="async" class="aligncenter size-large wp-image-1534" src="https://blog.krusher.net/wp-content/uploads/2017/06/sc2000-periodicos-1024x435.png" alt="" width="840" height="357" srcset="https://blog.krusher.net/wp-content/uploads/2017/06/sc2000-periodicos-1024x435.png 1024w, https://blog.krusher.net/wp-content/uploads/2017/06/sc2000-periodicos-300x127.png 300w, https://blog.krusher.net/wp-content/uploads/2017/06/sc2000-periodicos-768x326.png 768w, https://blog.krusher.net/wp-content/uploads/2017/06/sc2000-periodicos.png 1090w" sizes="auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></a></p>
<p>Unfortunately this format is a nightmare. It begins with a term dictionary separated by 00h, and then a clump of texts used to generate the articles. This custom encoding is variable-width (for an example, 5C96h represent the ñ character) and uses the previously defined terms, and of course placeholders for article subjects. These articles are procedurally generated, and an article denouncing the disappearance of an animal had as the main protagonist a cat or a rhinoceros, owned by mrs. Dwight or mr. Martínez.</p>
<p>Back in the day we had editors like <a href="https://www.romhacking.net/utilities/217/" target="_blank" rel="noopener noreferrer">Thingy</a>, which supported TBL files. You could specify a term dictionary there and easily edit files like this. Anyway, it would only be of use if we could keep the string length, and even then we would need to decipher the preceding number (and its encoding) so we could properly edit it.</p>
<p><strong>Addendum</strong>: It seems the pointers for the newspaper texts are in the PPDT1004.RAW file. They consist in blocks of 4 bytes in big-endian. What a mess.</p>
<h2>Image files</h2>
<p>Excluding some text files (described in above), RAW files store the images used in the game interface. Buildings and other elements are in some DAT files that would be out of the scope of this article, because they can be edited much more easily with the <strong>SimCity Urban Renewal Kit</strong> (SCURK), a tool included in some later versions which could edit cities &#8220;by hand&#8221; and modify the graphical aspect of the buildings.</p>
<p>Now about the files in question, these RAW files are 8 bit (256 colours) bitmaps with a 4 byte header. It doesn&#8217;t seem to be relevant information about resolution or colours, but for that matter we have another file, MINE.PAL, which specifies the colour palette used throughout the game. It&#8217;s not a Microsoft Palette file as the extension suggest, but a raw palette ACT type. Interestingly, it&#8217;s the preferred format used in <strong>Adobe Photoshop</strong>.</p>
<p><a href="https://blog.krusher.net/wp-content/uploads/2017/06/sc2000-efecto2000.png" data-rel="lightbox-gallery-xktDizQn" data-rl_title="" data-rl_caption="" title=""><img loading="lazy" decoding="async" class="aligncenter size-large wp-image-1539" src="https://blog.krusher.net/wp-content/uploads/2017/06/sc2000-efecto2000-1024x462.png" alt="" width="840" height="379" srcset="https://blog.krusher.net/wp-content/uploads/2017/06/sc2000-efecto2000-1024x462.png 1024w, https://blog.krusher.net/wp-content/uploads/2017/06/sc2000-efecto2000-300x135.png 300w, https://blog.krusher.net/wp-content/uploads/2017/06/sc2000-efecto2000-768x347.png 768w, https://blog.krusher.net/wp-content/uploads/2017/06/sc2000-efecto2000.png 1170w" sizes="auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></a></p>
<p>So for the resolution, there seems not to be an easy way to find it out simply looking at the file. The most easy method is factorizing the number (minus 4 bytes) in two factors, something <strong>Photoshop</strong> could help us with when opening the file, at least in the most modern version. By the file name we can more or less tell what&#8217;s the file for, and in case we have played (you really should!) the game, you could more or less recognize its width/height ratio. Some are easy: the title screen (TITLE.RAW) is a 640&#215;480 image. All the images use the same palette, as the game only uses the same 256 colours all of the time.</p>
<p><a href="https://blog.krusher.net/wp-content/uploads/2017/06/sc2000-rwa.png" data-rel="lightbox-gallery-xktDizQn" data-rl_title="" data-rl_caption="" title=""><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-1538" src="https://blog.krusher.net/wp-content/uploads/2017/06/sc2000-rwa.png" alt="" width="369" height="477" srcset="https://blog.krusher.net/wp-content/uploads/2017/06/sc2000-rwa.png 369w, https://blog.krusher.net/wp-content/uploads/2017/06/sc2000-rwa-232x300.png 232w" sizes="auto, (max-width: 369px) 85vw, 369px" /></a></p>
<p>I always use the same technique editing 8 bit indexed colour images: I convert them to 24 bit colour (plus 8 bit alpha channel) and I edit them comfortably. After that, before saving them, I change them to indexed color loading again the game palette. Surprisingly enough, saving the files in <em>Adobe RAW</em> format, the game loads it right, because <strong>Photoshop</strong> would allow us to preserve the 4 byte header. What a relief!</p>
<p><a href="https://blog.krusher.net/wp-content/uploads/2017/06/sc2000-guardarraw.png" data-rel="lightbox-gallery-xktDizQn" data-rl_title="" data-rl_caption="" title=""><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-1540" src="https://blog.krusher.net/wp-content/uploads/2017/06/sc2000-guardarraw.png" alt="" width="946" height="653" srcset="https://blog.krusher.net/wp-content/uploads/2017/06/sc2000-guardarraw.png 946w, https://blog.krusher.net/wp-content/uploads/2017/06/sc2000-guardarraw-300x207.png 300w, https://blog.krusher.net/wp-content/uploads/2017/06/sc2000-guardarraw-768x530.png 768w" sizes="auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></a></p>
<p>Please note: needless to say this RAW format has anything to do with raw image formats the nowadays digital cameras uses.</p>
<h2>XMI files</h2>
<p>Game music tracks are stored in the <a href="http://www.vgmpf.com/Wiki/index.php/XMI" target="_blank" rel="noopener">XMI</a> files. Tis format supports many tracks per file, but this seems not the case. The structure is very different from MIDI files, but they do about the same: store musical notes and events. It can be played in Windows easily with <a href="http://www.foobar2000.org/components/view/foo_midi" target="_blank" rel="noopener">Foobar2000</a>, and it is possible to <a href="http://www.vgmpf.com/Wiki/index.php/XMI#Converters" target="_blank" rel="noopener">convert MIDI to XML</a> (and vice versa). <a href="https://github.com/stascorp/MIDIPLEX" target="_blank" rel="noopener">MIDIPLEX</a> seems to be able to do it from <strong>Windows</strong>, but no compiled binaries are offered so I did it with older tools with <strong>MS-DOS</strong>, using <strong>DOSBox</strong>. Anyway, the very SimCity 2000 will need <strong>DOSBox</strong> to work in modern systems.</p>
<p><a href="https://blog.krusher.net/wp-content/uploads/2017/06/sc2000-xmi.png" data-rel="lightbox-gallery-xktDizQn" data-rl_title="" data-rl_caption="" title=""><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-1542" src="https://blog.krusher.net/wp-content/uploads/2017/06/sc2000-xmi.png" alt="" width="642" height="427" srcset="https://blog.krusher.net/wp-content/uploads/2017/06/sc2000-xmi.png 642w, https://blog.krusher.net/wp-content/uploads/2017/06/sc2000-xmi-300x200.png 300w" sizes="auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 984px) 61vw, (max-width: 1362px) 45vw, 600px" /></a></p>
<h2>FNT files</h2>
<p>They are presumed to be the game typographies, to judge from the numbers and the extension they come with. It seems not the same format that Windows uses (bitmap FNT), so I&#8217;ve been unable to open the files with any editor.</p>
<h2>Others</h2>
<p>Other files present in the package are General MIDI sources for OPL chipsets, some indexes and headers for the building graphic sets&#8230; anything very interesting when modifying the game. Everything else seems to be embedded in the executable file, something it&#8217;s out of my reach at the moment.</p>
<h2>In Windows</h2>
<p>On a point of information, the <strong>Windows</strong> version can be modified much more easily. The image and sound resources are present in WAV and BMP format, which are much less obscure as the previously described. The rest of the resources are embedded in the game executable, but with a resource editor they can be extracted and modified with ease, and in more accessible format than their <strong>MS-DOS</strong> counterparts. (I use <a href="http://www.angusj.com/resourcehacker/" target="_blank" rel="noopener">Resource Hacker</a>, which is free and works quite well)</p>
<p><a href="https://blog.krusher.net/wp-content/uploads/2017/06/sc2000-reshack.png" data-rel="lightbox-gallery-xktDizQn" data-rl_title="" data-rl_caption="" title=""><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-1541" src="https://blog.krusher.net/wp-content/uploads/2017/06/sc2000-reshack.png" alt="" width="846" height="631" srcset="https://blog.krusher.net/wp-content/uploads/2017/06/sc2000-reshack.png 846w, https://blog.krusher.net/wp-content/uploads/2017/06/sc2000-reshack-300x224.png 300w, https://blog.krusher.net/wp-content/uploads/2017/06/sc2000-reshack-768x573.png 768w" sizes="auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></a></p>
<p>Newspapers, however, seems to have the same calamitous format than the <strong>MS-DOS</strong> version. It&#8217;s a pity, because it would be very interesting to translate this version to Spanish.</p>
<p>So this is where I leave it. I hope it&#8217;s been educative, although after all this time there seems to be little interest modifying this game. I&#8217;ve always wanted to meddle with this game and create my own mod, <em>Sim City 2000 effect</em>, a bit mischievous, but maybe that&#8217;ll be in another time.</p>
<p>La entrada <a href="https://blog.krusher.net/en/2017/12/taking-sim-city-2000-into-pieces/">Taking Sim City 2000 into pieces</a> se publicó primero en <a href="https://blog.krusher.net/en">Nobody comes after the last</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.krusher.net/en/2017/12/taking-sim-city-2000-into-pieces/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
		<item>
		<title>JSF converter for SelectOneMenu</title>
		<link>https://blog.krusher.net/en/2017/12/jsf-converter-for-selectonemenu/</link>
					<comments>https://blog.krusher.net/en/2017/12/jsf-converter-for-selectonemenu/#comments</comments>
		
		<dc:creator><![CDATA[Krusher]]></dc:creator>
		<pubDate>Wed, 06 Dec 2017 21:19:54 +0000</pubDate>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[converter]]></category>
		<category><![CDATA[j2ee]]></category>
		<category><![CDATA[JSF]]></category>
		<category><![CDATA[primefaces]]></category>
		<guid isPermaLink="false">https://blog.krusher.net/?p=1760</guid>

					<description><![CDATA[<p>The main JSF feature (or, at least, the one I like the most) is the ease to link controller bean attributes to xhtml view. However there&#8217;s an inherent important limitation: in the HTTP standard keys and values always will be strings, because they are sent that way. Of course you could serialize an object to &#8230; <a href="https://blog.krusher.net/en/2017/12/jsf-converter-for-selectonemenu/" class="more-link">Continue reading<span class="screen-reader-text"> "JSF converter for SelectOneMenu"</span></a></p>
<p>La entrada <a href="https://blog.krusher.net/en/2017/12/jsf-converter-for-selectonemenu/">JSF converter for SelectOneMenu</a> se publicó primero en <a href="https://blog.krusher.net/en">Nobody comes after the last</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>The main <strong>JSF</strong> feature (or, at least, the one I like the most) is the ease to link controller bean attributes to xhtml view. However there&#8217;s an inherent important limitation: in the HTTP standard keys and values always will be strings, because they are sent that way. Of course you could serialize an object to base64, but a barbaric thing like that should be avoided in almost any circumstance.</p>
<p>Then how can we link a HTTP control to an object? For that, JSF provides <strong>converters</strong>. Well, it will allow you to program them, of course. Neither <a href="http://www.primefaces.org/" target="_blank" rel="noopener">PrimeFaces</a>, my library of choice, includes these converters. Thus, I&#8217;ve programmed a simple one for <a href="http://www.primefaces.org/showcase/ui/input/oneMenu.xhtml" target="_blank" rel="noopener">SelectOneMenu</a>, the dropdown menus in the like of a combobox. I&#8217;ll leave it here for my own reference, and for anyone that could use it.</p>
<p><span id="more-1760"></span></p>
<pre class="brush: java; title: ; notranslate">
/**
 * The Class SelectOneMenuConverter.
 */
@FacesConverter(&quot;selectOneMenuConverter&quot;)
public class SelectOneMenuConverter implements Converter {

	@Override
	public Object getAsObject(final FacesContext arg0, final UIComponent arg1, final String objectString) {
		if (objectString == null) {
			return null;
		}

		return fromSelect(arg1, objectString);
	}

	/**
	 * Serialize.
	 *
	 * @param object
	 *            the object
	 * @return the string
	 */
	private String serialize(final Object object) {
		if (object == null) {
			return null;
		}
		return object.getClass() + &quot;@&quot; + object.hashCode();
	}

	/**
	 * From select.
	 *
	 * @param currentcomponent
	 *            the currentcomponent
	 * @param objectString
	 *            the object string
	 * @return the object
	 */
	private Object fromSelect(final UIComponent currentcomponent, final String objectString) {

		if (currentcomponent.getClass() == UISelectItem.class) {
			final UISelectItem item = (UISelectItem) currentcomponent;
			final Object value = item.getValue();
			if (objectString.equals(serialize(value))) {
				return value;
			}
		}

		if (currentcomponent.getClass() == UISelectItems.class) {
			final UISelectItems items = (UISelectItems) currentcomponent;
			final List&lt;Object&gt; elements = (List&lt;Object&gt;) items.getValue();
			for (final Object element : elements) {
				if (objectString.equals(serialize(element))) {
					return element;
				}
			}
		}


		if (!currentcomponent.getChildren().isEmpty()) {
			for (final UIComponent component : currentcomponent.getChildren()) {
				final Object result = fromSelect(component, objectString);
				if (result != null) {
					return result;
				}
			}
		}
		return null;
	}

	@Override
	public String getAsString(final FacesContext arg0, final UIComponent arg1, final Object object) {
		return serialize(object);
	}

}
</pre>
<p>Basically, it converts any objects in a coded string with the class name and its hash. When you want to recover it, it access the collection linked to our dropdown menu value to look up the object so it can return it. It relies on the proper implementation of the hashCode method, and it requires it to return different values for different objects, but it&#8217;s a nice and quick way to do it, and will work in almost all circumstances. Using it is as easy as:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;p:selectOneMenu id=&quot;utiSelector&quot; converter=&quot;selectOneMenuConverter&quot; value=&quot;#{myBean.myObject}&quot;&gt;	
        &lt;f:selectItem itemValue=&quot;#{null}&quot; noSelectionOption=&quot;true&quot; /&gt;
	&lt;f:selectItems value=&quot;#{myBean.objectList}&quot; var=&quot;object&quot; itemValue=&quot;#{object}&quot; itemLabel=&quot;#{objeto.label}&quot;&gt;
&lt;/p:selectOneMenu&gt;
</pre>
<p>Something I usually do in the DTOs or entities is to make the hashcode to be the key, or the key&#8217;s hashcode if it&#8217;s compound or non numeric. But that&#8217;s another story.</p>
<p>La entrada <a href="https://blog.krusher.net/en/2017/12/jsf-converter-for-selectonemenu/">JSF converter for SelectOneMenu</a> se publicó primero en <a href="https://blog.krusher.net/en">Nobody comes after the last</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.krusher.net/en/2017/12/jsf-converter-for-selectonemenu/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
	</channel>
</rss>
