<?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>pagetable.com</title>
	<atom:link href="http://www.pagetable.com/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://www.pagetable.com</link>
	<description>Some Assembly Required</description>
	<lastBuildDate>Fri, 29 Mar 2013 02:50:53 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Why is my TI-99/4A in Black and White?</title>
		<link>http://www.pagetable.com/?p=672</link>
		<comments>http://www.pagetable.com/?p=672#comments</comments>
		<pubDate>Fri, 29 Mar 2013 02:50:53 +0000</pubDate>
		<dc:creator>James Abbatiello</dc:creator>
				<category><![CDATA[archeology]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=672</guid>
		<description><![CDATA[by James Abbatiello My first computer was a Texas Instruments TI-99/4A. Longtime readers may remember a previous article where we implemented TI-99/4A BASIC as a Scripting Language for modern computers. Recently I got nostalgic for the actual hardware so I got my 99 out of the closet where it had been for a decade or [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: left;" dir="ltr"><em>by James Abbatiello</em></p>
<p style="text-align: left;" dir="ltr">My first computer was a Texas Instruments <a href="http://en.wikipedia.org/wiki/Texas_Instruments_TI-99/4A">TI-99/4A</a>.  Longtime readers may remember a previous article where we implemented <a href="http://www.pagetable.com/?p=288">TI-99/4A BASIC as a Scripting Language</a> for modern computers.  Recently I got nostalgic for the actual hardware so I got my 99 out of the closet where it had been for a decade or more.  I hooked it up to the TV and turned it on.  I was expecting to see something like this:<img class="aligncenter" src="http://www.pagetable.com/docs/ti99_bw/ti994a_original_unmodified_title_screen.gif" alt="TI-99/4a title screen" width="272" height="208" /></p>
<p style="text-align: left;" dir="ltr">Instead I was greeted by this:<a href="http://www.pagetable.com/docs/ti99_bw/title_lcd_before.jpg"><img class="aligncenter" src="http://www.pagetable.com/docs/ti99_bw/title_lcd_before_s.jpg" alt="" width="440" height="253" /></a></p>
<p dir="ltr">Well, that&#8217;s not right!  It is in black and white.  And what&#8217;s with all these vertical black lines?  Clearly something&#8217;s wrong but what could it be?</p>
<h2 dir="ltr">New Meets Old</h2>
<p style="text-align: left;" dir="ltr">At first I suspected that it was my TV, which is a fairly new LCD.  Old computers or game consoles sometimes played a bit fast and loose with the NTSC standard and it seemed unlikely that a new TV would ever have been tested with something as old as a TI-99/4A.  Perhaps the TV just couldn&#8217;t interpret output from the 99.  So I tried with a CRT TV:<a href="http://www.pagetable.com/docs/ti99_bw/title_crt_before.jpg"><img class="aligncenter" src="http://www.pagetable.com/docs/ti99_bw/title_crt_before_s.jpg" alt="" width="440" height="330" /></a></p>
<p dir="ltr">Well the black bars are gone (or at least not as apparent) but it is still in black and white.  Something must be wrong with the computer itself.</p>
<h2 dir="ltr">All About Video Signals</h2>
<p dir="ltr">The output from the back of the computer is a <a href="http://en.wikipedia.org/wiki/Composite_video">composite video</a> signal but using a 5-pin <a href="http://en.wikipedia.org/wiki/DIN_connector">DIN</a> connector (that also carries audio and power) instead of the usual <a href="http://en.wikipedia.org/wiki/RCA_connector">RCA</a> jack.  Back when this computer was new that signal would usually to go an <a href="http://en.wikipedia.org/wiki/RF_modulator">RF modulator</a> which was then connected to a TV via a <a href="http://en.wikipedia.org/wiki/Twin-lead">300-ohm</a> connector.  Nowadays you can still do the same thing but since most TVs don&#8217;t have screw terminals on the back anymore it can be more convenient to take the composite video signal and hook it directly into the composite input on the TV.  All that is required is a simple adapter cable that can be <a href="http://www.stageselect.com/N174-make-a-composite-video-cable-genesis-ti994a.aspx">created yourself</a> or <a href="http://www.ebay.com/sch/i.html?_nkw=ti-99%2F4a+composite">purchased</a> <a href="http://www.iec-usa.com/cgi-bin/iec/fullpic?rhQ4ZpLU;L1133;40">online</a>.</p>
<p dir="ltr">I thought that perhaps the video circuitry was generating separate <a href="http://en.wikipedia.org/wiki/Luminance">Luminance</a> (Y) and <a href="http://en.wikipedia.org/wiki/Chromanince">Chrominance</a> (C) signals and then combining them into the final composite output.  If this were the case then it would suggest something was wrong in the C amplifier or the final combining stage.  It turns out that this is not the case.  The video chip in the TI-99/4A is referred to as the Video Display Processor (VDP) and is a <a href="http://en.wikipedia.org/wiki/Texas_Instruments_TMS9918">TMS9918A</a>, TMS9928A or TMS9929A depending on the region the computer was originally intended for and the television standard in use there (e.g. <a href="http://en.wikipedia.org/wiki/NTSC">NTSC</a> or <a href="http://en.wikipedia.org/wiki/PAL">PAL</a>).  My computer was made for the US market and outputs NTSC signals using the TMS9918A.  This chip has a single video output pin that supplies composite video directly with the Y and C already mixed.  So if something was wrong with just the C generation circuitry then it was something broken inside the VDP and my only recourse would be to try to find a replacement chip.</p>
<h2 dir="ltr">Mad Scientist Equipment</h2>
<p style="text-align: left;" dir="ltr">The VDP still seemed to work correctly in all other respects so I was hopeful that the true problem lay elsewhere.  I thought I&#8217;d take a look at the signal on an oscilloscope.  We&#8217;d expect to the see the NTSC <a href="http://en.wikipedia.org/wiki/Colorburst">colorburst</a> and if it was missing that would explain why no color was showing up on the TVs.  Here&#8217;s what it looked like:<a href="http://www.pagetable.com/docs/ti99_bw/oscope_before_1.jpg"><img class="aligncenter" src="http://www.pagetable.com/docs/ti99_bw/oscope_before_1s.jpg" alt="" width="440" height="330" /></a></p>
<p style="text-align: left;" dir="ltr">And here&#8217;s a closeup of the interesting portion:<a href="http://www.pagetable.com/docs/ti99_bw/oscope_before_2.jpg"><img class="aligncenter" src="http://www.pagetable.com/docs/ti99_bw/oscope_before_2s.jpg" alt="" width="440" height="330" /></a></p>
<p dir="ltr">I&#8217;m no expert but that looks like a <a href="http://en.wikipedia.org/wiki/Analog_television#Structure_of_a_video_signal">horizontal sync pulse</a> followed by a colorburst to me.  But there was still no color on the TV.</p>
<p dir="ltr">The composite video signal that the VDP generates is sent to a simple 2-transistor amplifier and then to the output jack.  I didn&#8217;t think it was likely but perhaps something in the amplifier had given out and Y was still strong enough to get picked up by the TV but C wasn&#8217;t.  To test this I took the computer apart and tapped the signal right as it came out of the chip and before it went through the amplifier.  It was still black-and-white.  This suggested that the problem was not in the amplifier.</p>
<h2 dir="ltr">The Healing Power of Crystals</h2>
<p style="text-align: left;" dir="ltr">At this point I knew that the VDP was mostly working correctly.  It generated the right pattern on the screen so it must be able to communicate with both the video RAM and the CPU.  That accounts for most of the pins on the VDP, the ones handling digital signals.  The remaining pins are mostly for power and the connection to the <a href="http://en.wikipedia.org/wiki/Crystal_oscillator">quartz crystal</a> that provides the timing.  I checked the power and that seemed fine.  So let&#8217;s take a closer look at the crystal:<a href="http://www.pagetable.com/docs/ti99_bw/crystal_before.jpg"><img class="aligncenter" src="http://www.pagetable.com/docs/ti99_bw/crystal_before_s.jpg" alt="" width="440" height="330" /></a></p>
<p dir="ltr">The crystal is the gray-colored component in the middle.  To the right is the VDP, covered in thermal paste.  Just behind the crystal is a variable inductor.</p>
<p dir="ltr">A variable inductor: now that&#8217;s interesting!  It is connected to the crystal and apparently used for fine tuning the frequency.  Could the fix be as simple as turning an adjustment screw?</p>
<p dir="ltr">Alas, no.  I turned it as far as it would go in both directions with no improvement to the video output.  If the frequency was off it was beyond the ability of this adjustment to correct.  I don&#8217;t have any equipment to allow precision measuring of the actual frequency this crystal was producing, but I do have the internet.  A little Googling brought me to <a href="http://tech.groups.yahoo.com/group/ti99-4a/message/67337">this post</a> on the <a href="http://tech.groups.yahoo.com/group/ti99-4a/">TI-99/4A mailing list</a>.  Yes, there&#8217;s still an active mailing list for a computer that hasn&#8217;t been manufactured in almost 30 years!</p>
<p dir="ltr">That post describes the symptoms that I was experiencing and indicated that the solution was to replace the crystal.  This was somewhat surprising to me.  I&#8217;d heard of electrolytic capacitors going bad in old equipment but a quartz crystal?  They&#8217;re usually quite reliable.  But you can&#8217;t argue with real-world experience.</p>
<p dir="ltr">The VDP takes the frequency of this crystal (10.738635 MHz) and divides it by 3 to produce the NTSC colorburst frequency (3.579545 MHz).  If the frequency of the crystal was off then the generated colorburst would also be off and the TV wouldn&#8217;t be able to sync to it.  Without seeing a valid colorburst the TV isn&#8217;t going to produce any color.  That would certainly explain our symptoms!</p>
<p dir="ltr">So after deciding to replace this crystal we have to actually find a replacement part.  We want a crystal that runs at exactly 10.738635 MHz.  We also need it rated for the proper &#8220;load capacitance&#8221;.  Running a crystal with the wrong capacitance will shift the frequency from the rated frequency.  That would be bad since our entire goal is to get the frequency back to the ideal.  The original crystal was rated for a load capacitance of 32pF (you can just make out the 32 in the above picture although it is partially obscured by the blue wire).  So we want a replacement crystal that&#8217;s also rated for 32pF.</p>
<p style="text-align: left;" dir="ltr">Let&#8217;s go internet shopping for 10.738635 MHz crystals.  <a href="http://www.jameco.com/">Jameco</a> doesn&#8217;t carry any.  <a href="http://www.digikey.com/product-search/en?x=0&amp;y=0&amp;lang=en&amp;site=us&amp;KeyWords=10.738635">Digikey has some</a> but didn&#8217;t have any in stock with a 32pF load capacitance.  Luckily <a href="http://www.mouser.com/Search/Refine.aspx?Keyword=10.738635">Mouser</a> came through for me!  A few days later and I had a replacement crystal:<a href="http://www.pagetable.com/docs/ti99_bw/new_crystal.jpg"><img class="aligncenter" src="http://www.pagetable.com/docs/ti99_bw/new_crystal_s.jpg" alt="" width="440" height="330" /></a></p>
<p style="text-align: left;" dir="ltr">And after a little surgery on the motherboard:<a href="http://www.pagetable.com/docs/ti99_bw/crystal_after.jpg"><img class="aligncenter" src="http://www.pagetable.com/docs/ti99_bw/crystal_after_s.jpg" alt="" width="440" height="330" /></a></p>
<p style="text-align: left;" dir="ltr">Now for the moment of truth:<a href="http://www.pagetable.com/docs/ti99_bw/title_lcd_after.jpg"><img class="aligncenter" src="http://www.pagetable.com/docs/ti99_bw/title_lcd_after_s.jpg" alt="" width="440" height="250" /></a></p>
<p dir="ltr">Success!  Now to play some <a href="http://en.wikipedia.org/wiki/Parsec_%28video_game%29">Parsec</a>!</p>
<h2 dir="ltr">Bonus Oscilloscope Image</h2>
<p style="text-align: left;" dir="ltr">If you&#8217;re wondering what the colorburst looks like with the new crystal then wonder no longer.<a href="http://www.pagetable.com/docs/ti99_bw/oscope_after_2.jpg"><img class="aligncenter" src="http://www.pagetable.com/docs/ti99_bw/oscope_after_2s.jpg" alt="" width="440" height="330" /></a></p>
<p dir="ltr">Looks pretty similar to my eyes but apparently it makes a world of difference to a TV.</p>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=672&amp;ts=1369319073" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=672</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Clockslide: How to waste an exact number of clock cycles on the 6502</title>
		<link>http://www.pagetable.com/?p=669</link>
		<comments>http://www.pagetable.com/?p=669#comments</comments>
		<pubDate>Tue, 07 Feb 2012 01:29:08 +0000</pubDate>
		<dc:creator>Michael Steil</dc:creator>
				<category><![CDATA[6502]]></category>
		<category><![CDATA[tricks]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=669</guid>
		<description><![CDATA[by Sven Oliver &#8216;SvOlli&#8217; Moll; the original German language version has been simultaneously posted on his blog. This is an article about the 6502 processor about the topic: how to &#8220;waste&#8221; a number of clock cycles stated in a register, in this case the X register. The principle is simple: you have a number of [...]]]></description>
			<content:encoded><![CDATA[<p><i>by Sven Oliver &#8216;SvOlli&#8217; Moll; the original German language version has been simultaneously posted on <a href='http://blog.h8u.de/index.php?/archives/1468-Clockslide-von-der-exakten-Verschwendung-von-Taktzyklen-auf-dem-6502.html'>his blog</a></i>.</p>
<p>This is an article about the 6502 processor about the topic: how to &#8220;waste&#8221; a number of clock cycles stated in a register, in this case the X register. The principle is simple: you have a number of operations that do close to nothing. The more the code is jumped to at the &#8220;front&#8221;, the more clock cycles are needed to get to the actual code. If the code is jumped to more at the &#8220;end&#8221;, the CPU gets to the code in question more quickly.</p>
<p>This nice theory won&#8217;t work directly on the 6502, because every instruction takes at least two clock cycles to execute. If you want to get it down to the precision of one cycle, this is getting more difficult. The first half of this trick I found in code of <a href="http://www.biglist.com/lists/stella/archives/199803/msg00201.html">Eckhard Stollberg</a>, who is one of the guys that pionieered homebrew on the Atari 2600 VCS. There, I found some strange bytes:</p>
<pre class='boxed'>C9 C9 C9 C9 C9 C9 C9 C9 C9 C9 C9 C9 C5 EA</pre>
<p>The disassembly looks like this:</p>
<pre class='boxed'>
; CODE1
CMP #$C9 ; 2
CMP #$C9 ; 2
CMP #$C9 ; 2
CMP #$C9 ; 2
CMP #$C9 ; 2
CMP #$C9 ; 2
CMP $EA  ; 3
</pre>
<p>To run through the code, you&#8217;ll need 15 clock cycles, and nothing changes except for some state registers. If the code is called with an offset of one byte, this code will be processed:</p>
<pre class='boxed'>
; CODE2
CMP #$C9 ; 2
CMP #$C9 ; 2
CMP #$C9 ; 2
CMP #$C9 ; 2
CMP #$C9 ; 2
CMP #$C5 ; 2
NOP      ; 2
</pre>
<p>This makes 14 clock cycles, and only the status register will be changed. If the code is called with an offset of two bytes, it is started at the CODE1 segment at the second instruction. Add another one, you&#8217;ll get to the second instruction of the CODE2 segment, and so on. This way it is possible to specify the exact number of clock cycles to be &#8220;wasted&#8221;. With on exception: to be more specific there are 2 + X clock cycles that are wasted. There is no way to waste exactly one clock cycle.</p>
<p>Now we need a way to specify the &#8220;entry&#8221; of our &#8220;slide&#8221;. On a C=64 this would be done using self-modifying code. The operand of a JMP $XXXX instruction will be replaced with the calculated address. This is not possible on systems like the Atari 2600, since the code is run in ROM. One option for example would be to use JMP ($0080) after writing the entry point to $0080 and $0081.</p>
<p>My approach differs a bit from the usual way. RAM is scarce on the Atari, and I don&#8217;t want to &#8220;waste&#8221; up two of the 128 bytes available, when there is another way. When the CPU executes a JSR $XXXX (jump to subroutine) command, it writes the current address to the stack. To be more specific, it is the address of the JSR command + 2 which is the return address &#8211; 1. And this is what I do: I write my entry point &#8211; 1 to the stack and use the command RTS (return from subroutine) to jump into the clock slide. So, I&#8217;m still using two bytes of RAM, but only for a short time, without the need to evaluate which two bytes are available at this point.</p>
<pre class='boxed'>
; the X register specifies how many of the
; 15 clock cycles possible should be skipped
LDA #&gt;clockslide
PHA
TXA
CLC
ADC #&lt;clockslide
PHA
STA WSYNC ; &lt;= this syncs to start of next scanline
clockslide:
RTS
CMP #$C9
CMP #$C9
CMP #$C9
CMP #$C9
CMP #$C9
CMP #$C9
CMP $EA
realcode:
; and here the real code continues
</pre>
<p>This approach still has one problem: between &#8220;clockslide&#8221; and &#8220;realcode&#8221;, no page crossing may occur. If this were the case, I&#8217;d have to increase the high byte on the stack by one. But since the position of the code segments is under my control, I left this out as an exercise for the reader. ;-)</p>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=669&amp;ts=1369319073" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=669</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Assembly Evolution Part 1: Accessing Memory and the strange case of the Intel 4004</title>
		<link>http://www.pagetable.com/?p=663</link>
		<comments>http://www.pagetable.com/?p=663#comments</comments>
		<pubDate>Thu, 13 Oct 2011 21:58:45 +0000</pubDate>
		<dc:creator>Michael Steil</dc:creator>
				<category><![CDATA[archeology]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=663</guid>
		<description><![CDATA[by Julien Oster, reprinted with permission. While it has become far less relevant for non-system developers to write assembly than it was a few decades ago, by now CPUs have nevertheless made it much more comfortable to do so. Today we are used to a lot of things: fancy indirect addressing modes with scale, a [...]]]></description>
			<content:encoded><![CDATA[<p><i>by Julien Oster</i>, <a href="http://blog.julien-oster.de/2011/10/assembly-evolution-part-1-accessing.html">reprinted</a> with permission.</p>
<p>While it has become far less relevant for non-system developers to write assembly than it was a few decades ago, by now CPUs have nevertheless made it much more comfortable to do so. Today we are used to a lot of things: fancy indirect addressing modes with scale, a galore of general purpose registers instead of an accumulator and maybe one or two crippled index registers, condition codes for nearly every instruction (on ARM)&#8230;</p>
<p>
But also the basics themselves have evolved. Let&#8217;s take a look at what past programmers had to put up with in entirely simple, everyday things. We&#8217;ll start with the most trivial: writing to memory.</p>
<p>
Our goal is to write a single immediate value of 3 into the memory location 5. In light of paging, segmenting and bank switching, we&#8217;ll use whatever is convenient as a definition for &#8220;memory location&#8221;. Also, we&#8217;ll let the CPU decide what the word size should be. Since you only need 2 bits to represent a 3, it should fit with every CPUs word size (<i>except</i> for 1 bit CPUs, which actually existed, but that&#8217;s a story for another posting). If we have the choice, we&#8217;ll just take the smallest.</p>
<p>
We&#8217;ll work backwards, from the present to the past, to explore the wonders of direct addressing in Intel CPUs. <i>(One precautionary warning though: I only really tested the 4004 code in an emulator, and my habits are highly tainted by current Intel CPUs. So if I made some mistake somewhere, kindly point it out and I&#8217;ll fix it!)</i></p>
<p><h3>x86</h3>
</p>
<p>
On a modern x86 CPU, it is of course fairly easy to write the value 3 to memory cell 5. You just do it:</p>
<p>
<code>mov byte [5], 3</code></p>
<p>
A single instruction, simple and obvious. I cheated a bit by not using a segment prefix, nor did I set up any segment registers/selectors beforehand. But assuming a nowadays common OS environment in protected mode, you probably don&#8217;t want to fiddle with those selectors anyway.</p>
<p><h3>8085</h3>
</p>
<p>
The Intel 8085 is somewhat of a direct predecessor to the 8086, the first in the line of the excessively successful x86 processors. While the 8086 has a 16 bit data bus, the 8085 only has 8 bit. The address bus is already full 16 bit, but its 16 bit capabilities are limited. Specifically, there is no immediate 16 bit addressing (except for branches), leaving us no way to specify our memory location in the instruction that actually performs the move.</p>
<p>
Memory is instead addressed with a pseudo register called M. This pseudo register is in reality just backed by the registers H and L paired together, each 8 bit wide, and accessing it accesses the memory location they point at (you may take a guess which register receives the High byte, and which the Low byte of the address).</p>
<p>
Luckily, there are a few simple 16bit instructions for moving immediate values, so all in all we can write our byte with:</p>
<p>
<code>LXI H, 0005h    ; </code><i>unlucky syntax, as this actually means HL instead of just H</i></p>
<p>
<code>MOV M, 3</code></p>
<p>
By the way, bonus points if you are somehow able to find out just when the address in HL is available on the address bus. The same applies to the 8080 and 8008. Does the CPU copy the register pair&#8217;s content to the address bus pins only when actual memory operations take place, or are the address bus pins somehow directly connected to H and L itself? Is that even feasible? I&#8217;d really like to find out&#8230;</p>
<p><h3>8008</h3>
</p>
<p>
We continue going further back, skipping the 8080 because it was identical in that regard, and arrive at its direct predecessor instead, the Intel 8008. The 8080 and 8085 were source compatible to the 8008 (which, mind you, is not the same as binary compatible&#8230; also it may or may not have required some light automated translation), but in the downward direction we have something vital taking from us: While already using 16bit addresses (with only a 14bit address bus, resulting in 16k memory, though), the only instructions that were allowed to contain 16bit immediate values at all are jumps and branches. Consequently, we are left with no way to completely specify our destination address in one instruction!</p>
<p>
Instead, we have to access H and L, together forming pseudo register M&#8217;s address, one at a time:</p>
<p>
<code>LHI 00h</code></p>
<p>
<code>LLI 05h</code></p>
<p>
<code>LMI 3</code></p>
<p><h3>4004</h3>
<p>It&#8217;s hardly possible to go back further than the Intel 4004, at least if you are only considering single chip CPUs (at the time of its conception in the early 70s, there were already famous multi-chip CPUs with comfortable orthogonal instruction sets, notably the PDPs). Indeed, it was the <i>first</i>&nbsp;widely available single chip CPU. This little thing was a 4-bit CPU with some strange quirks, which we will explore further.&nbsp;Overall, it bears little to no resemblance to its successor in name, the Intel 8008 (except for the internal stack, which both had&#8211;I will cover that in another posting).</p>
<p>
But let&#8217;s just look at the code for writing a value of 3 into the memory location at 5 first:</p>
<p>
<code>FIM P0, 5; load address 05h into pair R0,R1</code></p>
<p>
<code>SRC P0 &nbsp; ; set address bus to contents of R0,R1</code></p>
<p>
<code>LDM 3 &nbsp; &nbsp;; load 3 into accumulator</code></p>
<p>
<code>WRM &nbsp; &nbsp; &nbsp;; write accumulator content to memory</code></p>
<p><div>
</div>
<p>That looks a bit strange.</p>
<p>
As&nbsp;a 4 bit CPU, the 4004 has 4 bit wide registers and addresses 4 bit nibbles as words in memory. It has only one accumulator on which the majority of operations is performed, but <i>sixteen</i>&nbsp;index registers (R0-R15).</p>
<p>
Those index registers are handy for accessing memory: Besides loading values directly from ROM, an instruction exists to load data indirectly, which sets the address bus to the ROM cell&#8217;s content. Another instruction performs an indirect<i>&nbsp;jump</i>&nbsp;instead. Other than that, you can just increment index registers, albeit there is the interesting &#8220;ISZ&#8221; instruction that not only increments, but also branches if the result is not 0.</p>
<p>
Because the 4004 uses 8 bits to address the 4 bit nibbles, every two consecutive index registers form a pair, which is then used for memory references.</p>
<p>
Note that I explicitly said ROM above. This is because in the 4004 architecture, ROM and RAM are actually vastly different beasts, at least from the assembly programmer&#8217;s perspective. You can <i>not</i>&nbsp;directly access RAM. It always involves index register pairs, manually sending their content to the address bus (with a strangely named instruction &#8220;SRC&#8221;, which for some reason spells out <i>send register control</i>) and then issuing another instruction which transfers from or to the accumulator.</p>
<p>
Interestingly, accessing regular RAM nibbles is not your only choice among the transfer instructions. You can also fetch from and to I/O ports. But the CPU does not have any direct I/O port, instead they are available on both RAM and ROM! You can also read and write &#8220;RAM status characters&#8221;, which to me look like plain regular RAM cells within another namespace. If someone knows, I&#8217;d love to hear what they were used for (and if they maybe did behave differently to normal RAM).</p>
<p>
Take a look at the <a href="http://www.intel.com/Assets/PDF/DataSheet/4004_datasheet.pdf">data sheet</a>. Within its only 9 pages, the instruction set is depicted on page 4 and 5. Especially in the light that fairly reasonable orthogonal instruction sets appear to have been available in multi-chip CPUs, this first single-chip CPU is clearly a strange specialization towards the desk calculator it was meant for (the <a href="http://en.wikipedia.org/wiki/Busicom">Busicom 141-PF</a>). It has the aforementioned index register-centered RAM access, separate ROM (although there is a transfer instruction which strangely refers to some optional &#8220;read/write program memory&#8221;), a <i>three</i> level internal stack which is almost useless for general purpose programming and a lone special purpose instruction for &#8220;<i>keyboard process&#8221;</i> (KBP).</p>
<p>
Original 4004 CPUs go from anything from a few to a few thousand dollars on eBay, depending on their packaging and revision. If you&#8217;d like to, you can instead play around with a virtual one in this <a href="http://e4004.szyc.org/">java-script based, fully fledged assembler, disassembler and emulator</a>, or read the rescued <a href="http://www.4004.com/2009/Busicom-141PF-Calculator_asm_rel-1-0-1.txt">source code of the Busicom 141-PF calculator</a>. There&#8217;s lots more of schematics, data sheets and other resources on the <a href="http://www.4004.com/">Intel&#8217;s anniversary project page</a>.</p>
<p>
That is, if you are brave enough.</p>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=663&amp;ts=1369319073" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=663</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>The story of 15 Second Copy for the C-64</title>
		<link>http://www.pagetable.com/?p=656</link>
		<comments>http://www.pagetable.com/?p=656#comments</comments>
		<pubDate>Mon, 18 Jul 2011 09:00:15 +0000</pubDate>
		<dc:creator>Michael Steil</dc:creator>
				<category><![CDATA[6502]]></category>
		<category><![CDATA[archeology]]></category>
		<category><![CDATA[trivia]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=656</guid>
		<description><![CDATA[by Mike Pall, published with permission. [This is a follow-up to Thomas Tempelmann's Story of FCopy for the C-64.] Ok, I have to make a confession &#8230; more than 25 years late: I&#8217;ve reverse-engineered Thomas Tempelmann&#8217;s code, added various improvements and spread them around. I guess I&#8217;m at least partially responsible for the slew of [...]]]></description>
			<content:encoded><![CDATA[<p><i>by Mike Pall</i>, published with permission.</p>
<p>[This is a follow-up to Thomas Tempelmann's <a href="http://www.pagetable.com/?p=647">Story of FCopy for the C-64</a>.]</p>
<p>Ok, I have to make a confession &#8230; more than 25 years late:</p>
<p>I&#8217;ve reverse-engineered Thomas Tempelmann&#8217;s code, added various improvements and spread them around. I guess I&#8217;m at least partially responsible for the slew of fast-loaders, fast-copys etc. that circulated in the German C64 scene and beyond. Uh, oh &#8230;</p>
<p>I&#8217;ve only published AFLG (auto-fast-loader-generator) under my real name in the German &#8220;RUN&#8221; magazine. It owes quite a bit to TT&#8217;s original ideas. I guess I have to apologize to Thomas for not giving proper credit. But back then in the 80&#8242;s, intellectual property matters wasn&#8217;t exactly something a kid like me was overly concerned with.</p>
<p>Later on, everyone was soldering parallel-transfer cables to the VIA #1 of the 1541 and plugging them into the C64 userport. This provided extra bandwidth compared to the standard serial cable. It allowed much faster loading of programs with a tiny parallel loader (a file named &#8220;!&#8221;, that was prepended on all disks). Note that the commercial kits with cables, custom EPROMs and silly dongles followed only much later.</p>
<p>So I wrote &#8220;15 second copy&#8221;, which worked with a plain parallel cable. Yes, it copied a full 35 track disk in 15 seconds! There was only one down-side: this was only the time for reading/writing from and to disk &mdash; you had to swap the floppies <em>seven times</em> (!) and that usually took quite a bit more extra time! ;-)</p>
<div><img src="docs/15second_copy.png" width="384" height="272"></div>
<p>It worked by transferring the &#8220;live&#8221; GCR-encoded data from the 1541&#8242;s disk head to the C64 and simultaneously doing a fast checksum. Part of the checksumming was done on the 1541, part was done on the C64. There simply weren&#8217;t enough cycles left on either side! Most of the transfer happened asynchronously by adjusting for the slightly different CPU frequencies and with only a minimum number of handshakes. This meant meticulous cycle counting and use of some odd tricks.</p>
<p>The raw GCR took up more space (684*324 bytes) in the C64 RAM, so that&#8217;s why it required 4 passes. Other copy programs fully decoded the GCR and required only 3 passes. But GCR decoding was rather time-consuming, so they had to skip some sectors and read every track multiple times. OTOH my program was able to read/write at the full 300rpm, i.e. 5 tracks per second plus stepper time, which boils down to 2x ~7.5 seconds for read and write. Yep, you had to swap the floppies every 2 seconds &#8230;</p>
<p>Ok, so I spread the program. For free. I even made a 40 track version, which took 17 seconds. Only to see these coming back in various mutations, with the original credits ripped out, decorated with multiple intros, different groups pretending they wrote it or cracked it (it was free, there was <em>nothing</em> to crack!). The only thing they left alone were the copy routines, probably because they were extremely fragile and hard to understand. So it was really easy to recognize my own code. Some of the commercial parallel-cable + ROM kits even bragged with &#8220;Backups in 15 seconds!&#8221;. These were blatant rip-offs: they basically changed the screen colors and added a check for their dongles. Duh.</p>
<p>Let&#8217;s just say this rather frustrating experience taught me a lot and that&#8217;s why <a href="http://luajit.org/">I&#8217;m doing open source today</a>.</p>
<p>So I shelved my plans to write an enhanced version which would try to compress the memory to reduce the number of passes. Ah, yes &#8230; I wrote quite a few packers, too &#8230; but I&#8217;ll save that story for another time.</p>
<p>I still have the disks with the source code somewhere in my basement. But I&#8217;m not so sure I&#8217;ll be able to read them anymore. They weren&#8217;t of high quality to begin with &#8230; and I&#8217;d have to find my homegrown toolchain, too. ;-)</p>
<p>But I took the time to reverse-engineer my own code from one of the copies that are floating around on the net. For better understanding on the C64/1541 handshake issues, refer to <a href="http://www.pagetable.com/?p=568">this article</a>. If you&#8217;re wondering about the weird <code>bvc *</code> loops: the 6502 CPU of the 1541 has an SO pin, which is triggered by a full shift register for the data from the disk head. This directly sets the overflow flag in the CPU and allows reading the contents from the shift register with very low latency.</p>
<p>Yes, there&#8217;s a lot more weird code in there. For the sake of brevity, here are only the inner loops of the I/O routines for the read, write and verify pass for the C64 and the 1541 side. Enjoy!</p>
<pre>
  ;--- 1541: Read ---
  ldy #$20
f_read:
  bvc *        ; Wait for disk shift register to fill
  clv
  lda $1c01    ; Load data from disk
  sta $1801    ; Send byte to C64 via parallel cable
  inc $1800    ; Toggle serial pin
  eor $80      ; Compute checksum for 1st GCR byte in $80
  sta $80
  bvc *
  clv
  lda $1c01    ; Load data from disk
  sta $1801    ; Send byte to C64 via parallel cable
  dec $1800    ; Toggle serial pin
  eor $81      ; Compute checksum for 2nd GCR byte in $81
  sta $81
  ; ...
  ; Copy and checksum to $82 $83 $84
  ; And another time for $80 $81 $82 $83 $84 with inverted toggles
  ; ...
  dey
  beq f_read_end
  jmp f_read
f_read_end:
  ; Copy the remaining 4 bytes and checksum to $80 $81 $82
  ; Lots of bit-shifting and xoring to indirectly verify
  ; the sector checksum from the 5 byte xor of the raw GCR data

  ;--- C64: Read ---
  ; Setup ($5d) and ($5f) to point to GCR buffer
  ldy #$00
c_read:
  bit $dd00    ; Wait for serial pin to toggle
  bpl *-3
  lda $dd01    ; Read incoming data (from 1541)
  sta ($5d),y  ; Store to buffer
  iny
  bit $dd00    ; Wait for serial pin to toggle
  bmi *-3
  lda $dd01    ; Read incoming data (from 1541)
  sta ($5d),y  ; Store to buffer
  iny
  bne c_read
c_read2:
  bit $dd00    ; Wait for serial pin to toggle
  bpl *-3
  lda $dd01    ; Read incoming data (from 1541)
  sta ($5d),y  ; Store to buffer
  iny
  bit $dd00    ; Wait for serial pin to toggle
  bmi *-3
  lda $dd01    ; Read incoming data (from 1541)
  sta ($5d),y  ; Store to buffer
  iny
  cpy #$44
  bne c_read2

  ;--- C64: Write ---
  ; Setup ($5d) and ($5f) to point to GCR buffer
  ldy #$00
  tya
c_write:
  eor ($5d),y  ; Load from buffer and compute checksum
  bit $dd00    ; Wait for serial pin to toggle
  bpl *-3
  sta $dd01    ; Store xor'ed outgoing data (to 1541)
  iny
  eor ($5d),y  ; Load from buffer and compute checksum
  bit $dd00    ; Wait for serial pin to toggle
  bmi *-3
  sta $dd01    ; Store xor'ed outgoing data (to 1541)
  iny
  bne c_write
c_write2:
  eor ($5f),y  ; Load from buffer and compute checksum
  bit $dd00    ; Wait for serial pin to toggle
  bpl *-3
  sta $dd01    ; Store xor'ed outgoing data (to 1541)
  iny
  eor ($5f),y  ; Load from buffer and compute checksum
  bit $dd00    ; Wait for serial pin to toggle
  bmi *-3
  sta $dd01    ; Store xor'ed outgoing data (to 1541)
  iny
  cpy #$44
  bne c_write2
  ldx $5b
  sta $0200,x  ; Store checksum for verify pass
  inx
  stx $5b

  ;--- 1541: Write ---
  ldy #$a2
  lda #$00
f_write:
  bvc *        ; Wait for disk shift register to clear
  clv
  eor $1801    ; Xor with incoming data (from C64)
  sta $1c01    ; Write data to disk shift register
  dec $1800    ; Toggle serial pin
  lda $1801    ; Reload data to undo xor for next byte
  bvc *        ; Wait for disk shift register to clear
  clv
  eor $1801    ; Xor with incoming data (from C64)
  sta $1c01    ; Write data to disk shift register
  inc $1800    ; Toggle serial pin
  lda $1801    ; Reload data to undo xor for next byte
  dey
  bne f_write

  ;--- 1541: Verify ---
  ; Get checksum computed by c_write on the C64 side
  ldy #$a2
f_verify:
  bvc *        ; Wait for disk shift register to fill
  clv
  eor $1c01    ; Xor with data from disk
  bvc *        ; Wait for disk shift register to fill
  clv
  eor $1c01    ; Xor with data from disk
  dey
  bne f_verify
  ; Verify is ok if checksum is zero
</pre>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=656&amp;ts=1369319073" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=656</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>The story of FCopy for the C-64</title>
		<link>http://www.pagetable.com/?p=647</link>
		<comments>http://www.pagetable.com/?p=647#comments</comments>
		<pubDate>Fri, 15 Jul 2011 23:13:04 +0000</pubDate>
		<dc:creator>Michael Steil</dc:creator>
				<category><![CDATA[6502]]></category>
		<category><![CDATA[archeology]]></category>
		<category><![CDATA[trivia]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=647</guid>
		<description><![CDATA[by Thomas Tempelmann, reprinted with permission. Back in the 80s, the Commodore C-64 had an intelligent floppy drive, the 1541, i.e. an external unit that had its own CPU and everything. The C-64 would send commands to the drive which in turn would then execute them on its own, reading files, and such, then send [...]]]></description>
			<content:encoded><![CDATA[<p><i>by Thomas Tempelmann</i>, <a href="http://stackoverflow.com/revisions/0c20bf24-41cd-4b12-8f5d-569a0eaae186/view-source">reprinted</a> with permission.</p>
<p>Back in the 80s, the Commodore C-64 had an intelligent floppy drive, the 1541, i.e. an external unit that had its own CPU and everything.</p>
<p>The C-64 would send commands to the drive which in turn would then execute them on its own, reading files, and such, then send the data to the C-64, all over a propriatory serial cable.</p>
<p>The manual for the 1541 mentioned, besides the commands for reading and writing files, that one would read and write to its internal memory space. Even more exciting was that one could download 6502 code into the drive&#8217;s memory and have it executed there.</p>
<p>This got me hooked and I wanted to play with that &#8211; execute code on the drive. Of course, there was no documention on what code could be executed there, and which functions it could use.</p>
<p>A friend of mine had written a disassembler in BASIC, and so I read out all its ROM contents, which was 16KB of 6502 CPU code, and tried to understand what it does. The OS on the drive was quite amazing and advanced IMO &#8211; it had a kind of task management, with commands being sent from the communication unit to the disk I/O task handler.</p>
<p>I learned enough to understand how to use the disk I/O commands to read/write sectors of the disk. Actually, having read the Apple ]['s DOS 3.3 book which explained all of the workings of its disk format and algos in much detail, was a big help in understanding it all.</p>
<p>(I later learned that I could have also found reverse-eng'd info on the more 4032/4016 disk drives for the "business" Commodore models which worked quite much the same as the 1541, but that was not available to me as a rather disconnected hobby programmer at that time.)</p>
<p>Most importantly, I also learnt how the serial comms worked. I realized that the serial comms, using 4 lines, two for data, two for handshake, was programmed very inefficiently, all in software (though done properly, using classic serial handshaking).</p>
<p>Thus I managed to write a much faster comms routine, where I made fixed timing assumptions, using both the data and the handshake line for data transmission.</p>
<p>Now I was able to read and write sectors, and also transmit data faster than ever before.</p>
<p>Of course, it would have been great if one could simply load some code into the drive which speeds up the comms, and then use the normal commands to read a file, which in turn would use the faster comms. This was not possible, though, as the OS on the drive did not provide any hooks for that (mind that all of the OS was in ROM, unmodifiable).</p>
<p>Hence I was wondering how I could turn my exciting findings into a useful application.</p>
<p>Having been a programmer for a while already, dealing with data loss all the time (music tapes and floppy disks were not very realiable back then), I thought: Backup!</p>
<p>So I wrote a backup program which could duplicate a floppy disk in never-before seen speed: The first version did copy an entire 170 KB disk in only 8 minutes (yes, minutes), the second version did it even in about 4.5 minutes. Whereas the apps before mine took over 25 minutes. (Mind you, the Apple ][, which had its disk OS running on the Apple directly, with fast parallel data access, did this all in a minute or so).</p>
<p>And so FCopy for the C-64 was born.</p>
<p>It became soon extremely popular. Not as a backup program as I had intended it, but as the primary choice for anyone wanting to copy games and other software for their friends.</p>
<p>Turned out that a simplification in my code, which would simply skip unreadable sectors, writing a sector with a bad CRC to the copy, did circumvent most of the then-used copy protection schemes, making it possible to copy most formerly uncopyable disks.</p>
<p>I had tried to sell my app and sold it actually 70 times. When it got advertised in the magazines, claiming it would copy a disk in less than 5 minutes, customers would call and not believe it, &#8220;knowing better&#8221; that it can&#8217;t be done, yet giving it a try.</p>
<p>Not much later, others started to reverse engineer my app, and optimize it, making the comms even faster, leading to copy apps that did it even in 1.5 minutes. Faster was hardly possible, because, due to the limited amount of memory available on the 1541 and the C-64, you had to swap disks several times in the single disk drive to copy all 170 KB of its contents.</p>
<p>In the end, FCopy and its optimized successors were probably the most-popular software ever on the C-64 in the 80s. And even though it didn&#8217;t pay off financially for me, it still made me proud, and I learned a lot about reverse-engineering, futility of copy protection and how stardom feels. (Actually, Jim Butterfield, an editor for a C-64 magazine in Canada, told its readers my story, and soon he had a cheque for about 1000 CA$ for me &#8211; collected by the magazine from many grateful users sending 5$-cheques, which was a big bunch of money back then for me.)</p>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=647&amp;ts=1369319073" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=647</wfw:commentRss>
		<slash:comments>32</slash:comments>
		</item>
		<item>
		<title>Chaosradio Express #177: Commodore 64</title>
		<link>http://www.pagetable.com/?p=624</link>
		<comments>http://www.pagetable.com/?p=624#comments</comments>
		<pubDate>Tue, 05 Jul 2011 09:00:23 +0000</pubDate>
		<dc:creator>Michael Steil</dc:creator>
				<category><![CDATA[6502]]></category>
		<category><![CDATA[archeology]]></category>
		<category><![CDATA[hacks]]></category>
		<category><![CDATA[tricks]]></category>
		<category><![CDATA[trivia]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=624</guid>
		<description><![CDATA[(This article is about a German-language podcast episode on the C64.) Im Februar hat mich Tim Pritlove auf der Durchreise in Frankfurt abgefangen, wo ich mit einem Koffer voll mit zwölf Commodore 64 Motherboards in einem Hotelzimmer saß, und mit mir eine 2 Stunden und 42 Minuten lange Episode für Chaosradio Express aufgenommen. Chaosradio Express [...]]]></description>
			<content:encoded><![CDATA[<p><i>(This article is about a German-language podcast episode on the C64.)</i></p>
<p>Im Februar hat mich Tim Pritlove auf der Durchreise in Frankfurt abgefangen, wo ich mit einem Koffer voll mit zwölf Commodore 64 Motherboards in einem Hotelzimmer saß, und mit mir eine 2 Stunden und 42 Minuten lange Episode für Chaosradio Express aufgenommen.</p>
<p><a href="http://chaosradio.ccc.de/cre177.html">Chaosradio Express #177: Commodore 64</a></p>
<p><a href="docs/cre177.jpg"><img src="docs/cre177.jpg" width="440"></a></p>
<p>Hier also nochmal der Hinweis auf die Folge, die jetzt schon ein paar Monate zurückliegt, für all diejenigen, die sie nicht schon anderweitig entdeckt haben. :-)</p>
<p><a href="http://www.google.com/search?q=chaosradio+express+c64"><img src="docs/cre177.png"></a></p>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=624&amp;ts=1369319073" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=624</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Inside Commodore DOS [PDF]</title>
		<link>http://www.pagetable.com/?p=630</link>
		<comments>http://www.pagetable.com/?p=630#comments</comments>
		<pubDate>Tue, 28 Jun 2011 09:00:50 +0000</pubDate>
		<dc:creator>Michael Steil</dc:creator>
				<category><![CDATA[6502]]></category>
		<category><![CDATA[archeology]]></category>
		<category><![CDATA[literature]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=630</guid>
		<description><![CDATA[Richard Immers and Gerald G. Neufeld:Inside Commodore DOS : the complete guide to the 1541 disk operating system.Northridge, Calif. : Datamost, 1985.ISBN 0-8359-3091-2(512 pages, 7.4 MB PDF) In my quest to preserve retrocomputing documents, here is the invaluable book &#8220;Inside Commodore DOS&#8221;, which describes most of the internals of the Commodore 1541 disk drive. The [...]]]></description>
			<content:encoded><![CDATA[<p><a href="docs/Inside Commodore DOS.pdf"><img src="docs/Inside Commodore DOS.png" width="440" height="581.5"><br />
Richard Immers and Gerald G. Neufeld:<br />Inside Commodore DOS : the complete guide to the 1541 disk operating system.<br />Northridge, Calif. : Datamost, 1985.<br />ISBN 0-8359-3091-2</a><br />(512 pages, 7.4 MB PDF)</p>
<p>In my <a href="http://www.pagetable.com/?cat=9">quest to preserve retrocomputing documents</a>, here is the invaluable book &#8220;Inside Commodore DOS&#8221;, which describes most of the internals of the Commodore 1541 disk drive. The scanning was done in 2002 by <a href="http://groups.yahoo.com/group/incdos/files/">Kenneth S. Moore</a>, who in 2005 released an OCRed version, which unfortunately replaced the original page images. My version here comes with the original page images and a table of contents, and is nevertheless fully searchable.</p>
<p>Here is a fun quote from the book by the way:</p>
<p><cite>Over the years numerous writers have advised Commodore owners not to use the save and replace command because it contained a bug. Our study of the ROM routines and a lot of testing has convinced us that the bug in the replace command is a myth.</cite></p>
<p>Of course, this is <a href="http://en.wikipedia.org/wiki/Commodore_DOS#The_save-with-replace_bug">wrong</a>. Don&#8217;t use &#8220;SAVE@&#8221; on a 1541.</p>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=630&amp;ts=1369319073" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=630</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Racism in Monstropolis</title>
		<link>http://www.pagetable.com/?p=638</link>
		<comments>http://www.pagetable.com/?p=638#comments</comments>
		<pubDate>Tue, 21 Jun 2011 09:00:31 +0000</pubDate>
		<dc:creator>Michael Steil</dc:creator>
				<category><![CDATA[trivia]]></category>
		<category><![CDATA[whines]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=638</guid>
		<description><![CDATA[Sometimes, freezeframe fun does not provide fun, but sadness. In the Pixar movie Monsters Inc., you can see the following file of a child at 12 min 40 sec: Monsters scare children at night, and this is how they keep track of them. The file comes with a blueprint of the room, a list of [...]]]></description>
			<content:encoded><![CDATA[<p>Sometimes, freezeframe fun does not provide fun, but sadness.</p>
<p>In the Pixar movie Monsters Inc., you can see the following file of a child at 12 min 40 sec:</p>
<p><a href="docs/racism/file.jpg"><img src="docs/racism/file.jpg" width="440"></a></p>
<p>Monsters scare children at night, and this is how they keep track of them. The file comes with a blueprint of the room, a list of date stamps, business-critical notes like &#8220;scared of snakes&#8221;, and the standard data like name, gender, age, and&#8230; uh, race??</p>
<p><a href="docs/racism/file_detail.jpg"><img src="docs/racism/file_detail.jpg" width="440"></a></p>
<p>Albert Lozano, age 8, seems to be &#8220;hispanic&#8221;, and for monsters, this is apparently a feature that is important to them.</p>
<p>Oh well, that&#8217;s Monstropolis, a world inhabited by monsters that scare little children. Modern societies, on the other hand, have understood that &#8220;race&#8221; is a detail that is just as useful to track as shoe size. Oh wait.</p>
<p><a href="docs/racism/census_title.png"><img src="docs/racism/census_title.png" width="440"></a><br /><a href="docs/racism/census.jpg"><img src="docs/racism/census.jpg" width="440"></a></p>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=638&amp;ts=1369319073" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=638</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
		<item>
		<title>Gate A20</title>
		<link>http://www.pagetable.com/?p=600</link>
		<comments>http://www.pagetable.com/?p=600#comments</comments>
		<pubDate>Tue, 14 Jun 2011 09:00:46 +0000</pubDate>
		<dc:creator>Michael Steil</dc:creator>
				<category><![CDATA[archeology]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=600</guid>
		<description><![CDATA[]]></description>
			<content:encoded><![CDATA[<p><a href="docs/gate_a20.jpg"><img src="docs/gate_a20.jpg"></a></p>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=600&amp;ts=1369319073" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=600</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Commodore 128 Programmer&#8217;s Reference Guide (PDF)</title>
		<link>http://www.pagetable.com/?p=620</link>
		<comments>http://www.pagetable.com/?p=620#comments</comments>
		<pubDate>Tue, 07 Jun 2011 09:00:41 +0000</pubDate>
		<dc:creator>Michael Steil</dc:creator>
				<category><![CDATA[6502]]></category>
		<category><![CDATA[archeology]]></category>
		<category><![CDATA[literature]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=620</guid>
		<description><![CDATA[Commodore Business Machines.Commodore 128 Programmer&#8217;s Reference Guide.New York, NY: Bantam Books, 1986.ISBN 0-553-34378-5(756 pages, 24.6 MB PDF) This book is an indispensable reference guide and sourcebook for anyone using the new and powerful Commodore 128 computer. This machine has many new and exciting built-in features, such as the advanced BASIC programming language Version 7.0, superior [...]]]></description>
			<content:encoded><![CDATA[<p><a href="docs/Commodore 128 Programmer's Reference Guide.pdf"><img src="docs/Commodore 128 Programmer's Reference Guide.png" width="440" height="581.5"><br />
Commodore Business Machines.<br />Commodore 128 Programmer&#8217;s Reference Guide.<br />New York, NY: Bantam Books, 1986.<br />ISBN 0-553-34378-5</a><br />(756 pages, 24.6 MB PDF)</p>
<table border="1">
<tr>
<td>
<p>This book is an indispensable reference guide and sourcebook for anyone using the new and	powerful Commodore 128	computer. This machine has many new and exciting built-in features, such as the advanced BASIC programming language Version 7.0, superior graphics, and excellent sound and music capabilities. All information on these and other technical details, such as machine language programming, memory maps, input/output guide, pinout diagrams of primary chips, and schematics of the computer, are here in this, the only <b>official Commodore 128 Programmer&#8217;s Reference Guide</b>.</p>
<p>Whether you	are a new user or an advanced programmer, you&#8217;ll benefit from all of the material in this book. Find out more about:</p>
<ul>
<li>The New BASIC 7.0 &#8211; Explaining new BASIC with advanced features</li>
<li>Graphics &#8211; Utilizing the Commodore 128&#8242;s graphics programming</li>
<li>Sound and Music &#8211; Getting the notes out of the C128</li>
<li>Machine Language &#8211; Programming in machine language and combining it with BASIC</li>
<li>Operating System &#8211; Understanding the C128 operating system, the kernal, and memory management</li>
<li>Screen Editor and	Memory Maps &#8211; Deciphering the C128,	C64, and CP/M modes</li>
<li>Input/Output Guide ? Controlling peripherals through software</li>
<li>Chips &#8211; Specifications and pinouts of all important chips</li>
<li>All this and much, much more</li>
</ul>
</td>
</tr>
</table>
<p>In my <a href="http://www.pagetable.com/?cat=9">quest to preserve retrocomputing documents</a>, here is the official Commodore 128 Programmer&#8217;s Reference Guide. As always, my scanned books come with a table of contents and are fully searchable.</p>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=620&amp;ts=1369319073" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=620</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>SCUMM Script</title>
		<link>http://www.pagetable.com/?p=614</link>
		<comments>http://www.pagetable.com/?p=614#comments</comments>
		<pubDate>Mon, 30 May 2011 11:41:16 +0000</pubDate>
		<dc:creator>Michael Steil</dc:creator>
				<category><![CDATA[6502]]></category>
		<category><![CDATA[SCUMM]]></category>
		<category><![CDATA[archeology]]></category>
		<category><![CDATA[trivia]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=614</guid>
		<description><![CDATA[Ron Gilbert posted this as a comment on The Mansion &#8211; Technical Aspects, I am re-posting it here as an article. SCUMM script was a little odd. When I first started designing the language, I was going to base it on Lisp. I was use to using it to customize emacs that we used to [...]]]></description>
			<content:encoded><![CDATA[<p><i><a href="http://grumpygamer.com/">Ron Gilbert</a> posted this as a comment on <a href="http://www.pagetable.com/?p=603">The Mansion &#8211; Technical Aspects</a>, I am re-posting it here as an article.</i></p>
<p>SCUMM script was a little odd.  When I first started designing the language, I was going to base it on Lisp.  I was use to using it to customize emacs that we used to do all our coding.  This was not on PCs, but on large multiuser UNIX machines.  The Lucasfilm games group was part of the Lucasfilm computer division (which later became Pixar) and we had some very smart people that connected the C64 to the UNIX machine.  From my UNIX terminal, I had complete control over the C64 and wrote a source level debugger for SCUMM.  The 6502 assembler was custom written by Chip Morningstar and ran on the UNIX machine.</p>
<p>But I digress.  So, SCUMM started out as Lisp based, but I quickly abandon that approach in favor of something that looked a little more C-like, but some aspects of Lisp remained, mostly in the naming conventions.  Commands and variables used &#8211; (dashes) as separators.</p>
<pre>sandy-rescued = 1</pre>
<p>This was a single variable, not sandy minus rescued.  So how did SCUMM do subtraction?  You didn&#8217;t.  Until Monkey Island, there was no way to do complex expressions.  if you wanted to subtract a value you used:</p>
<pre>count -= 5</pre>
<p>If you had a complex expression, you had to chain them using +=, -=, /= and *= using temp variables.  Ugly, but it made the interpreter much simpler.  </p>
<p>(Side note, the C64 interpreter was not named SPUTM, that name didn&#8217;t come about until the PC version).</p>
<p>One of the goals I had for the SCUMM system was that non-programers could use it.  I wanted SCUMM scripts to look more like movies scripts, so the language got a little too wordy.  This goal was never really reached, you always needed to be a programmer.  :-(</p>
<p>Some examples:</p>
<pre>actor sandy walk-to 67,8</pre>
<p>This is the command that walked an actor to a spot.</p>
<pre>actor sandy face-right
actor sandy do-animation reach
walk-actor razor to-object microwave-oven
start-script watch-edna
stop-script
stop-script watch-edna
say-line dave "Don't be a tuna head."
say-line selected-kid "I don't want to use that right now."</pre>
<pre>if (melt-down) {
  say-line selected-kid "I don't think this game is very fun."
}</pre>
<p>There were no functions, everything was a &#8216;script&#8217;, a small piece of code that looked a lot like a function, but it ran in it&#8217;s own virtual process.  </p>
<pre>script watch-clock {
  do {
    object clock state ON
    break-time 60
    object clock state OFF
    break-time 60
  }
}</pre>
<p>Note the lack of a until/while on the do loop.  The script would just continue until someone killed it.</p>
<p>Time was always measured in jiffies (1/60 second).  Later on I added the ability to say &#8216;break-time 1 minute&#8217; and the compiler just multiplied by 60 before emitting the opcode.</p>
<p>If you did&#8230;</p>
<pre>start-script watch-edna
start-script clock-tick</pre>
<p>&#8230;you now had 2 additional scripts running and they all ran at the same time using preemptive multitasking.  It was a heck of a lot better than doing state engines.  If you wanted to keep an eye on something, you&#8217;d just say&#8230;</p>
<pre>start-script watch-edna</pre>
<p>&#8230;and then forget about it.  That one script could do whatever it needed and start a cut-scene if the need arose.</p>
<p>This may seem pretty tame today, but back then, it was like magic.</p>
<p>Bonus information:  The SCUMM compiler was written in Yacc and Lex.</p>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=614&amp;ts=1369319073" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=614</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>The Mansion &#8211; Technical Aspects</title>
		<link>http://www.pagetable.com/?p=603</link>
		<comments>http://www.pagetable.com/?p=603#comments</comments>
		<pubDate>Tue, 24 May 2011 03:00:06 +0000</pubDate>
		<dc:creator>Michael Steil</dc:creator>
				<category><![CDATA[6502]]></category>
		<category><![CDATA[SCUMM]]></category>
		<category><![CDATA[archeology]]></category>
		<category><![CDATA[trivia]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=603</guid>
		<description><![CDATA[by enthusi (This is a reprint from &#8220;Vandalism News&#8221; issue 52) Maniac Mansion is a true classic &#8211; in many ways. It&#8217;s a classic example of smart game play versus photorealistic graphics that is lacking in so many modern productions and it&#8217;s the first LucasArts Adventure that made use of the point and click verb [...]]]></description>
			<content:encoded><![CDATA[<p><i>by <a href="http://www.enthusi.de/">enthusi</a></i></p>
<p>(This is a reprint from <a href="http://noname.c64.org/csdb/release/?id=84122">&#8220;Vandalism News&#8221; issue 52</a>)</p>
<p><img src="docs/the_mansion/the_mansion_1.png"></p>
<p>Maniac Mansion is a true classic &#8211; in many ways.</p>
</p>
<p>It&#8217;s a classic example of smart game play versus photorealistic graphics that is lacking in so many modern productions and it&#8217;s the first LucasArts Adventure that made use of the point and click verb parser. And it&#8217;s of course eponymous for the famous SCUMM &#8211; the scripting utility for Maniac Mansion. This is reason enough to talk about it in some more detail and as a side effect advertise the NEOram version for C64 released just now.   :)</p>
</p>
<p>MM has a nice Wikipedia page (especially in Finnish &#8211; check it out  :)  so I think I shall concentrate on some technical specialties:</p>
</p>
<p>The original <i>Scumm (version 0)</i> was designed for C64 in &#8217;87 and its idea was to be able to develop a game independently of the target machine and only port the SPUTM (script presentation utility TM (seriously)) to several architectures. However it started with C64 and for several reasons the C64 version was kind of special in comparison to all later ports. Hence Scumm version 0 is only used here. Even <b>Zak McKracken</b> already had important changes and fixes. The original version came on disk with some copy protection (not too bad, not many cracks are around) and hence there is no in-game copy protection unlike all other versions (except for the Apple). You may have seen that code door at 2nd floor on other computers and guess what: the door code is made of PETSCII graphics chars! Officially the protection was left out due to disk space. In fact the 2 disk sides are pretty crammed in the original. So the game design was done on PC (UNIX system) and assembled there. This explains the spaghetti like distribution of the data and some of the code. In general the data is split into rooms. A room contains all the data for a specific area in the game. I.e. the beginning with the beautiful moon in the background or the kitchen is one &#8216;room&#8217; each. The data consists of one graphics charset in multicolour mode and its screen map (from 40&#215;17 up to 160&#215;17 chars big), one full charset for the clipping mask with its map (same size as screen map of course), a colourmap for the fourth colour per char (ranging only from 0-7) and then the scripts themselves. There is one room data set for each location and numerous scripts, one for each room and several additional ones. </p>
</p>
<p>The scripts are more or less freely distributed among the rooms by the original SCUMM. They differ a <b>LOT</b> between English and German versions, for example to have minimal waste of space at the end of a sector on disk. Beside the room graphics and script data there is also data for sound effects, the characters in the game and the objects. The people in the game are drawn as sprites, but not constructed from ordinary sprites but plotted into a semi static multiplexed sprite matrix in real time each frame (17 raster-splits per frame). The data for the characters is also attached to several rooms. Often the one they appear in first. The text charset is not the ROM font btw. Since usually $01 is set to $14, hence RAM, RAM, RAM&#8230; </p>
<p><img src="docs/the_mansion/the_mansion_2.png"></p>
<p>Each actor has a vertical stripe of sprites covering the whole height and this allows for quite some actors on screen simultaneously. The sprite priorities are set according to the actors positions, so you can actually walk in front or behind other kids and even orbit them for hours&#8230; MM is so much fun. :)</p>
</p>
<p>The graphics are stored in sprite like format (3 bytes per line) but with a successive height of 16 pixels normally. To save space each person is only stored from front, back and its right side. Whenever someone is facing left, the graphics data is mirrored via table and then plotted. Oh, and all the facial expressions, well the mouth and the chin (being one pixel) are not part of the data but added during plotting. Btw, the explosion in the intro, chucky the plant and the mummy are stored and handled as actors as well. You can see that when you leave the bathroom: the mummy disappears just before the rest does. To prevent the secret phone number from being revealed the background graphics is distorted of course. :) The graphics replacements are stored among the objects. So an open radio is a replacement of the object graphics radio. Stored as x, y position in char steps inside the room area and its width. Each object has an owner attribute and a position x, y in chars where to walk to (which is not necessarily identical to its position). Also there is a byte containing the height of the object in pixels (using 6 bits) while the upper 2 bits give the direction the actor is facing when reaching the object. So when Dave opens the fridge we see his back but when reaching a door, he&#8217;s facing right for example. The object&#8217;s name is also given along with a pointer to the script dealing with it. Those pointers are 24bit wide. 1 byte for the room it is attached to (again, these data change between different language versions) and another 16bit offset inside that data chunk.</p>
</p>
<p>The scripting for MM is rather complex. The memory resident interpreter understands 82 opcodes and handles 256 global variables! There is lots of things are stored and swapped around. Like whose friend with Ed or the Tentacle or whether the highscore at the arcade is already set&#8230; It even has fancy stuff like a random number generator (yes, the numbers in the game like phone numbers, codes) are not always the same! (Look for the cheat in the NEOram version that displays Edna&#8217;s phone number, the safe combination, the radio frequency and the highscore once it&#8217;s played).</p>
</p>
<p>A typical script contains commands like these:</p>
<pre>(0035) (42)   startScript(103)
(0037) (02)   startMusic(185)
(0039) (CE)   putActorAtObject(Var(225),162)
(003C) (82)   stopCurrentScript()
(003D) (04)   unless (Var(61) <= 73) goto 5A96
(0042) (66)   Var(66) = getClosestObjActor25(113)
(0045) (02)   startMusic(186)
(0047) (CF)   setState02()
(0048) (E2)   stopScript(Var(162))
(004A) (82)   stopCurrentScript()
(004B) (03)   doSentence(62,74,55)
(004F) (5B)   Var(69) = getActorBitVar(103,Var(64))
</pre>
<p>Unlike in later Scumm revisions, version 0 for C64 has quite some C64 specific hard coded stuff inside the data. A nice example: ALL actor graphics are stored the same way (you can simply try a PC based multicolour sprite ripper on the disk images) except for the breasts of Sandy =D They are stored completely separate. Maybe to prevent early nude-hacks? Back to the data formats. There is quite some graphics in this game - there is a total of 52 rooms, including the initial kid selection screen, save game screen or cut scenes which are all handled by the same interpreter and format. To make all this fit onto two disk sides, there is a specific RLE encoding. The four most common bytes of the data to follow are given for each data chunk. These were derived by the SCUMM on the PC during compilation already. The encoding is arranged as following:</p>
</p>
<ul>
<li>A data byte of &lt; $40 gives the number of different single unpacked bytes to follow.</li>
<li>$3f to &lt; $80 represents the length of the run of the byte to follow (+$3f of course).</li>
<li>$7f to &lt; $a0 is the number of runs of most common byte 1,</li>
<li>$9f to &lt; $c0 and $bf to &lt;$e0 and $df-$ff for common byte 2, 3 and 4 respectively.</li>
</ul>
<p>This encoding is rather effective for the MM graphics. Walkable areas for a room are composed of a list of multiple boxes with varying size and positions and stored after the graphics data. You probably noticed the slowdown during scroll in the game. This is due to the double buffered scroll which waits for all the clipping and room data to be moved into the correct RAM areas. The colour scroll of $d800 is done with some sort of line based speed code. Rastertime and memory are both used almost to the max. At start-up some own drive code is loaded into the floppy (not in my NEOram version of course). Later on a room is loaded by checking which room we want to see next, then getting its corresponding disk side from a table, checking for correct disk, getting the track and sector at which the room data starts from another table, calling a function to set this t/s offset, then calling another function with the target address in memory and another one with the length to be transferred. Only then will the room data be actually loaded. Even worse, usually only the first few bytes are read since they contain the offset to the table of other offsets (actors, objects, and scripts) which are then loaded to the corresponding memory areas. As soon as the drive code is initialised that RAM area on C64 side is overwritten by data AND code again. So the only memory available for extra code in this version was the drive interface and some other routines handling disk sides etc. A major gain was for example the now obsolete "wrong disk" message. This game really uses all the RAM there is. Most of the stack is occupied by code as well. Some of the JMPs instead of JSRs in the interpreter I didn't get at first were due to that fact - to keep the stack pointer high (that was kind of sucky to debug).</p>
</p>
<p>I was able to rewrite some interpreter routines as well to gain more space for the mouse driver and save game selection.</p>
<p>And, err... I removed the checksum check for each room data. That was also quite some speedup btw and it probably prevented lots of people from making trivial changes to the game. Yet it is hardly possible to apply big changes in the game logic. All offsets are hard-coded to the data. Even changing the length of the name for i.e. the 'fridge' by 1 char, causes dozens of offsets to change (for costumes, scripts, sounds, other rooms and so on). Even the interpreter looks rather different from language to language. And the RLE nature of the data, makes it pretty hard to change graphics as well since they have to keep the same size.</p>
<p><img src="docs/the_mansion/the_mansion_3.png"></p>
<p>For the <i>NEOram</i> version I only redistributed the room data and completely replaced its track/sector/disk side structure.</p>
</p>
<p>So unlike all other patches before this one no longer 'emulates' disk access anymore. MM handles the pointer on screen very arborescent and there is no such thing like an "open" function call. Instead pointer positions are stored as x, y chars on screen, x, y relative to room origin in chars, x, y as pixels on screen, x, y as pixel coordinates (half the x resolution 0-159) and as a delta to last frame. All of these are set by different functions. So when a verb is highlighted and you press fire, multiple addresses are set already in the background. The call itself is a self modified JMP in the end. To allow the OPEN and PICKUP command on the right mouse button I rewrote the button routine instead. The input from the mouse is faked as if it would point to the OPEN verb, the pointer is hidden (more or less), the old position stored and the mouse driver is skipped for the next 3 frames while the joystick readout is rerouted to an own routine that returns button pressed for the next frame, then 1 frame of button release and still no mouse action, one frame to return old pointer coordinates and run the routine to convert the mouse coordinates to all those mentioned before and finally enable pointer sprite and toggle mouse control back in. Sounds a bit weird but otherwise there isnt enough rastertime left. This is also why you shouldn't use the mouse on an NTSC system. The mouse is read every 2nd frame only for the very same reason. The evaluation of the new coordinates for the game engine (x, y in absolute and relative chars and check for verb activation) are only carried out when the mouse driver itself is skipped. This was the only way to get things done before the next rastersplit is due. Also the mouse is disabled as long as a button is pressed or actions with objects or scrolling the inventory would take too much rastertime. And sometimes you see a little jerky screen during loading when the I/O area has to be switched in to set NEOram registers and the rasterline hits the IRQ to switch back to text mode. I chose this part of the screen since its the least disturbing and usually works quite ok. MM is and was great fun - as soon as I've had some rest I will look into Zak McKracken deeper. Almost can't wait to do so (imagine both games on one cart). Have a lot of fun and try all the different solutions to the game. </p>
</p>
<p>Yes, Jeff HAS some more or less special ability and you can use the integrated room viewer to check for things yet unseen ;-)</p>
<p>Did you every finish the game without shooting that poor meteor (why is no one calling it accurately 'meteorite'?) into space? Go ahead and enjoy another game of Maniac Mansion. The NEOram image will work well under vice by the way but if you consider assembling your own NEOram card just look for schematics and part-lists on the web or contact maniac`enthusi.de - Quite likely there are some PCB boards still around.</p>
</p>
<p><img src="docs/the_mansion/the_mansion_4.png" align="right"></p>
<p><b>Ok, let's go rescue Sandy!</b></p>
<p><i>/enthusi</i></p>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=603&amp;ts=1369319073" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=603</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Oops! I don&#8217;t have my CashCard here.</title>
		<link>http://www.pagetable.com/?p=597</link>
		<comments>http://www.pagetable.com/?p=597#comments</comments>
		<pubDate>Wed, 18 May 2011 09:07:28 +0000</pubDate>
		<dc:creator>Michael Steil</dc:creator>
				<category><![CDATA[SCUMM]]></category>
		<category><![CDATA[archeology]]></category>
		<category><![CDATA[hacks]]></category>
		<category><![CDATA[puzzle]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=597</guid>
		<description><![CDATA[It seems that a lot of readers of pagetable.com are fans of SCUMM games like Maniac Mansion (and at least one is their creator). Here is a puzzle for you (credits go to Bernhard Bauer): In Zak McKracken, how can you get into the situation pictured below? Note that you need the CashCard in order [...]]]></description>
			<content:encoded><![CDATA[<p>It seems that a lot of readers of pagetable.com are fans of SCUMM games like <a href="http://www.pagetable.com/?p=591">Maniac Mansion</a> (and at least <a href="http://www.pagetable.com/?p=591&#038;cpage=1#comment-104717">one</a> is their creator). Here is a puzzle for you (credits go to <a href="http://black-sheep-software.de/">Bernhard Bauer</a>):</p>
<p>In Zak McKracken, how can you get into the situation pictured below? Note that you need the CashCard in order to leave San Francisco, and Zak cannot give away his CashCard.</p>
<p>C64:</p>
<p><a href="docs/cashcard/cashcard_c64.png"><img src="docs/cashcard/cashcard_c64.png" width="440"></a>
</p>
<p>FM Towns:</p>
<p><a href="docs/cashcard/cashcard_256.png"><img src="docs/cashcard/cashcard_256.png" width="440"></a>
</p>
<p>Bonus points if you solve it by converting the SCUMM script into a graph and programmatically finding the shortest path to this state.</p>
<p>(Read the solution in the comments.)</p>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=597&amp;ts=1369319073" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=597</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>Limitations in Maniac Mansion</title>
		<link>http://www.pagetable.com/?p=591</link>
		<comments>http://www.pagetable.com/?p=591#comments</comments>
		<pubDate>Wed, 11 May 2011 05:21:53 +0000</pubDate>
		<dc:creator>Michael Steil</dc:creator>
				<category><![CDATA[SCUMM]]></category>
		<category><![CDATA[archeology]]></category>
		<category><![CDATA[puzzle]]></category>
		<category><![CDATA[trivia]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=591</guid>
		<description><![CDATA[In (any version of) Maniac Mansion, if one kid is in the hallway with Green Tentacle, any other kid (even Syd and Razor) will refuse to go up the stairs to that hallway: &#8220;I&#8217;m not going up there&#8230; that monster&#8217;s got my friend!&#8221; Why is that? C64: Nintendo Entertainment System: MS-DOS Enhanced: (Read Maniac Mansion [...]]]></description>
			<content:encoded><![CDATA[<p>In (any version of) Maniac Mansion, if one kid is in the hallway with Green Tentacle, any other kid (even Syd and Razor) will refuse to go up the stairs to that hallway: &#8220;I&#8217;m not going up there&#8230; that monster&#8217;s got my friend!&#8221;</p>
<p>Why is that?</p>
<p>C64:</p>
<p>
<a href="docs/maniac_mansion/maniac_mansion_1.png"><img src="docs/maniac_mansion/maniac_mansion_1.png" width="440"></a><br />
<a href="docs/maniac_mansion/maniac_mansion_2.png"><img src="docs/maniac_mansion/maniac_mansion_2.png" width="440"></a><br />
<a href="docs/maniac_mansion/maniac_mansion_3.png"><img src="docs/maniac_mansion/maniac_mansion_3.png" width="440"></a>
</p>
<p>Nintendo Entertainment System:</p>
<p>
<a href="docs/maniac_mansion/maniac_mansion_4.png"><img src="docs/maniac_mansion/maniac_mansion_4.png" width="440"></a>
</p>
<p>MS-DOS Enhanced:</p>
<p>
<a href="docs/maniac_mansion/maniac_mansion_5.png"><img src="docs/maniac_mansion/maniac_mansion_5.png" width="440"></a>
</p>
<p>(Read Maniac Mansion creator Ron Gilbert&#8217;s authoritative answer in the comments.)</p>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=591&amp;ts=1369319073" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=591</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>What Operating System Has Crashed Here?</title>
		<link>http://www.pagetable.com/?p=588</link>
		<comments>http://www.pagetable.com/?p=588#comments</comments>
		<pubDate>Fri, 15 Apr 2011 19:07:15 +0000</pubDate>
		<dc:creator>Michael Steil</dc:creator>
				<category><![CDATA[archeology]]></category>
		<category><![CDATA[puzzle]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=588</guid>
		<description><![CDATA[(Read comments for solution.)]]></description>
			<content:encoded><![CDATA[<p><a href="docs/crash.png"><img src="docs/crash.png" width="440"></a></p>
<p>(Read comments for solution.)</p>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=588&amp;ts=1369319073" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=588</wfw:commentRss>
		<slash:comments>29</slash:comments>
		</item>
		<item>
		<title>The Double Inverted Inconsistency Principle</title>
		<link>http://www.pagetable.com/?p=580</link>
		<comments>http://www.pagetable.com/?p=580#comments</comments>
		<pubDate>Tue, 15 Mar 2011 16:20:45 +0000</pubDate>
		<dc:creator>Michael Steil</dc:creator>
				<category><![CDATA[default]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=580</guid>
		<description><![CDATA[In a discussion, when pointing out inconsistencies in your opponent&#8217;s opinion by giving two examples that you disagree with, remember that it can be made into a point against you, just by inverting the two examples &#8211; plus/minus some rhetorical decoration. Here is an easy one, taken from a discussion on Facebook: &#8220;Liberals make no [...]]]></description>
			<content:encoded><![CDATA[<p>In a discussion, when pointing out inconsistencies in your opponent&#8217;s opinion by giving two examples that you disagree with, remember that it can be made into a point against you, just by inverting the two examples &#8211; plus/minus some rhetorical decoration.</p>
<p>Here is an easy one, taken from a discussion on Facebook:</p>
<p><cite>&#8220;Liberals make no sense at all. On the one hand, they complain about the war killing innocent people, and on the other hand, they are okay with killing innocent unborn children.&#8221;</cite></p>
<p>This is the plain inverted version:</p>
<p><cite>&#8220;Conservatives make no sense at all. On the one hand, they complain about killing innocent unborn children, and on the other hand, they are okay with the war killing innocent people.&#8221;</cite></p>
<p>Of course, this requires some adjusted rhetorical decoration:</p>
<p><cite>&#8220;Conservatives make no sense at all. On the one hand, they complain about abortion, and on the other hand, they are okay with the war killing innocent women and children.&#8221;</cite></p>
<p>Here is another one, from Twitter (source not given to protect the individual):</p>
<p><cite>&#8220;Don&#8217;t critisize German nuclear power plants, because Japan is far away&#8221;, say people who demand total surveillance in Germany whenever Bin Laden farts.</cite></p>
<p>This one is full of rhetorical devices that need to swap sides. You could say something like:</p>
<p><cite>&#8220;Ignore terrorist threats in Germany, because <a href="http://en.wikipedia.org/wiki/September_11_attacks">New York</a>, <a href="http://en.wikipedia.org/wiki/7_July_2005_London_bombings">London</a> and <a href="http://en.wikipedia.org/wiki/2004_Madrid_train_bombings">Madrid</a> are far away&#8221;, say people who want to immediately turn off <a href="http://de.wikipedia.org/wiki/Kernenergie">22%</a> of Germany&#8217;s electricity because <a href="http://en.wikipedia.org/wiki/Earthquakes_in_Germany#1756_D.C3.BCren_earthquake">8.9 earthquakes</a> and tsunamis happen there, too!</p>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=580&amp;ts=1369319073" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=580</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Leave security to security code. Or: Stop fixing bugs to make your software secure!</title>
		<link>http://www.pagetable.com/?p=577</link>
		<comments>http://www.pagetable.com/?p=577#comments</comments>
		<pubDate>Tue, 08 Mar 2011 06:01:27 +0000</pubDate>
		<dc:creator>Michael Steil</dc:creator>
				<category><![CDATA[security]]></category>
		<category><![CDATA[whines]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=577</guid>
		<description><![CDATA[If you read about operating system security, it seems to be all about how many holes are discovered and how quickly they are fixed. If you look inside an OS vendor, you see lots of code auditing taking place. This assumes all security holes can be found and fixed, and that they can be eliminated [...]]]></description>
			<content:encoded><![CDATA[<p>If you read about operating system security, it seems to be all about how many holes are discovered and how quickly they are fixed. If you look inside an OS vendor, you see lots of code auditing taking place. This assumes all security holes can be found and fixed, and that they can be eliminated more quickly that new ones are added. Stop fixing bugs already, and take security seriously!</p>
<p>Recently, German publisher heise.de <a href="http://www.heise.de/mac-and-i/artikel/Schwere-der-Luecken-ist-besorgniserregend-1194782.html">interviewed Felix &#8220;fefe&#8221; von Leitner</a>, a security expert and <!-- I like the CCC, so I did not link to it in this context ;-) -->CCC spokesperson, on Mac OS X security:</p>
<p><b>heise.de</b>: Apple has put protection mechanisms like Data Execution Prevention, Address Space Layout Randomization and Sandboxing into OS X. Shouldn&#8217;t that be enough?</p>
<p><b>Felix von Leitner</b>: All these are mitigations that make exploiting the holes harder but not impossible. And: The underlying holes are still there! They have to close these holes, and not just make exploiting them harder. <i>(Das sind alles Mitigations, die das Ausnutzen von Lücken schwerer, aber nicht unmöglich machen. Und: Die unterliegenden Lücken sind noch da! Genau die muss man schließen und nicht bloß das Ausnutzen schwieriger machen.)</i></p>
<h3>Security mechanisms make certain bugs <i>impossible</i> to exploit</h3>
<p>A lot is wrong about this statement. First of all, the term &#8220;harder&#8221; is used incorrectly in this context. Making &#8220;exploiting holes harder but not impossible&#8221; would mean that an attacker has to put more effort into writing exploit code for a certain security-relevant bug, but achieve the same at the end. While this is true for some special cases (with DEP on, certain code execution exploits can be converted into ROP exploits), but the whole point of mechanisms like DEP, ASLR and sandboxing is to make certain bugs <b>impossible</b> to exploit (e.g. directory traversal bugs can be made impossible with proper sandboxing) &#8211; while other bugs are unaffected (DEP can&#8217;t help against trashing of globals though an integer exploit). So mechanisms like DEP, ASLR and sandboxing make it harder to <b>find</b> exploitable bugs, not harder to exploit existing bugs. In other words: Every one of these mechanisms makes certain bugs non-exploitable, effectively decreasing the number of exploitable bugs in the system.</p>
<p>As a consequence, it does not matter whether the underlying bug is still there. It cannot be exploited. Imagine you have an application in a sandbox that restricts all file system accesses to /tmp &#8211; is it a bug if the application doesn&#8217;t check all user filenames redundantly? Does the US President have to lock the bedroom door in the White House or can he trust the building to be secure? Of course, a point can be made for diverse levels of barriers in systems of high security where a single breach can be desastrous and fixing a hole can be expensive (think: Xbox), but if you have to set priorities, it is smarter for the President to have security around the White House than locking every door behind himself.</p>
<h3>Symmetric and asymmetric security work</h3>
<p>When an operating systems company has to decide on how to allocate its resources, it needs to be aware of symmetric and asymmetric work. Finding and fixing bugs is symmetric work. You are as efficient finding and fixing bugs as attackers are finding and exploiting them. For every hour you spend fixing bugs, attackers have to spend one more hour searching for them, roughly speaking. Adding mechanisms like ASLR is asymmetric work. It may take you 1000 hours to get it implemented, but over time, it will waste more than 1000 hours of your attackers&#8217; time &#8211; or make the attacker realize that it&#8217;s too much work and not worth attacking the system.</p>
<h3>Leave security to security code</h3>
<p>Divide your code into security code and non-security code. Security code needs to be written by people who have a security background, they keep the design and implementation simple and maintainable, and they are aware of common security pitfalls. Non-security is code that never deals with security. It can be written by anyone. If a non-security project requires a small module that deals with security (e.g. verifies a login), push it into a different process &#8211; which is then security code.</p>
<p>Imagine for example a small server application that just serves some data from your disk publicly. Attackers have exploited it to serve anything from disk or spread malware. Should you fix your application? Mind you, your application by itself has nothing to do with security. Why spend time on adding a security infrastructure to it, fixing some of the holes, ignoring others, and adding more, instead of properly partitioning responsibilities and having everyone do what they can do best: The kernel can sandbox the server so it can only access a single subdirectory, and it can&#8217;t write to the filesystem. And the server can stay simple as opposed to being bloated with security checks.</p>
<h3>How many bugs in 1000 lines of code?</h3>
<p>A lot of people seem to assume they can find and fix all bugs. <a href="http://www.murphys-laws.com/murphy/murphy-computer.html">Every non-trivial program contains at least one bug.</a> The highly security-critical first-stage bootloader of the original Xbox was only 512 bytes in size. It consisted of about 200 hand-written assembly instructions. There was one bug in the design of the crypto system in the code, as well as two code execution bugs, one of which could be exploited in two different ways. In the revised version, one of the code execution bugs was fixed, and the crypto system had been replaced with one that had a different exploitable bug. Now extrapolate this to a 10+ MB binary like an HTML5 runtime (a.k.a web browser) and think about whether looking for holes and fixing them makes a lot of sense. And keep in mind that a web browser is not all security-critical assembly carefully handwritten by security professionals.</p>
<h3>Conclusion</h3>
<p>So stop looking for and fixing holes, this won&#8217;t make an impact. If the hackers find one, instead of researching &#8220;how this could happen&#8221; and educating the programmers responsible for it, construct a system that mitigates these attacks without the worker code having to be security aware. Leave security to security code.</p>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=577&amp;ts=1369319073" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=577</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
		<item>
		<title>A 256 Byte Autostart Fast Loader for the Commodore 64</title>
		<link>http://www.pagetable.com/?p=568</link>
		<comments>http://www.pagetable.com/?p=568#comments</comments>
		<pubDate>Tue, 08 Feb 2011 07:58:22 +0000</pubDate>
		<dc:creator>Michael Steil</dc:creator>
				<category><![CDATA[default]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=568</guid>
		<description><![CDATA[Platforms like the Commodore 64 are still a lot of fun to work with, not only because the limitations make certain tasks a real challenge, but also because it is possible to use many interesting tricks on a bit- and cycle-level &#8211; after all, the system is well-understood and practically all setups were identical. This [...]]]></description>
			<content:encoded><![CDATA[<p>Platforms like the Commodore 64 are still a lot of fun to work with, not only because the limitations make certain tasks a real challenge, but also because it is possible to use many interesting tricks on a bit- and cycle-level &#8211; after all, the system is well-understood and practically all setups were identical.</p>
<p>This article presents a C64 &#8220;fast bootloader&#8221;: A small program that auto-starts when loaded into memory and chain-loads e.g. a game, but replacing the slow disk transfer routines in ROM with much faster ones &#8211; and all this fits into a single 256 bytes sector.</p>
<h2>The C64 and the Drive 1541</h2>
<p>The C64 is an 8-bit computer released in 1982 that is powered by a 1 MHz 6502-based CPU and has 64 KB of RAM. A typical C64 setup also consists of a Commodore 1541 disk drive (5.25&#8243; SS/DD media, 170 KB per side) which is a 1 MHz 6502 computer with 2 KB of RAM itself.</p>
<h2>The IEC Bus</h2>
<p>The computer and the drive are connected through a serial cable that carries three lines from the computer to the drive (ATN, CLK, DATA) and two from the drive to the computer (CLK, DATA). This IEC bus supports several daisy-chained disk drives (and printers), and the computer uses the ATN line to arbitrate the bus.</p>
<p>IEC was introduced in the C64&#8242;s predecessor VIC-20 and its floppy drive 1540, as a cheaper version for the parallel IEE-488 bus. Each device had a 6522 &#8220;VIA&#8221; I/O controller that could do a simple serial protocol in hardware &#8211; in theory. The serial port in the VIAs never worked, so Commodore decided to work around the issue by just implementing the protocol in software, after all, both devices had programmable CPUs. The C64, running basically the same system software as the VIC-20, and the 1541, a slightly updated disk drive for the C64, inherited this design.</p>
<p>As a result of every single bit having to go through a software handshake, the ROM code in the C64 and the drive could only transfer about 400 bytes per second. A game that fills all of RAM would take more than two minutes to load. Another issue of the IEC code in the C64 ROM is that it turns off interrupts every once in a while, making it impossible to properly play music in the background while loading data from disk.</p>
<h2>Fast Loaders</h2>
<p>Practically every game and every demo therefore only had a small boot program that was loaded by the original ROM code, typically less than a kilobyte in size, which contained more efficient serial code for the computer side, as well as corresponding code for the drive, which was uploaded into the drive&#8217;s RAM using the original serial protocol.</p>
<h2>The Protocol</h2>
<p>The original IEC protocol uses one clock and one data line in each direction. The sender alternates the clock line on every bit of data, and the receiver has to acknowledge the receipt by alternating its clock line. The idea of a faster protocol is to send a whole byte, bit by bit without a clock signal: Whenever both devices are undisturbed by interrupts and device DMA, we can assume the clocks of both devices to be enough in sync for the duration of transmitting a byte. (In fact, the 1541 is clocked a little bit faster than a PAL C64, so there is one extra 1541 cycle for every 67 C64 cycles.) Since the clock line is now not necessary for the handshake, it can be used for data, so we can transmit two bits at a time, and transfer a byte in four steps.</p>
<h2>Receiving a Byte</h2>
<p>The IEC bus is controlled through port A of the C64&#8242;s second 6526 &#8220;CIA&#8221; I/O chip, which is accessible through the MMIO address $DD00:</p>
<table border="1">
<tr>
<td>7</td>
<td>IEC DATA IN</td>
</tr>
<tr>
<td>6</td>
<td>IEC CLK IN</td>
</tr>
<tr>
<td>5</td>
<td>IEC DATA OUT</td>
</tr>
<tr>
<td>4</td>
<td>IEC CLK OUT</td>
</tr>
<tr>
<td>3</td>
<td>IEC ATN Signal OUT</td>
</tr>
<tr>
<td>2</td>
<td>RS-232</td>
</tr>
<tr>
<td>1-0</td>
<td>VIC Select</td>
</tr>
</table>
<p>We can signal the drive when we are ready to receive a byte through bits 4 and 5, and the drive can send data through bits 7 and 6. We need to be careful not to change bits 0 and 1, since these select the 16 KB memory bank that the video chip fetches its data from &#8211; typically, these bits are both 1.</p>
<p>The fastest way to receive a byte from the serial bus (given the sender is fast enough) is to repeatedly read two bits from $DD00, shift them down, then read the next two bits, and repeat all this four times:</p>
<pre>
    lda $DD00 ; get 2 bits into bits 6-7
    lsr
    lsr       ; move down into bits 4-5
    eor $DD00 ; get 2 more bits
    lsr
    lsr       ; move everything down to bits 2-5
    eor $DD00 ; get 2 more bits
    lsr
    lsr       ; move everything down to bits 0-5
    eor $DD00 ; get last 2 bits
</pre>
<p>The trick here is to XOR the new bits onto the already received and shifted bits, this way we avoid shifting, ANDing and ORing. An absolute load taking four cycles and a shift instruction two, receiving a byte takes 28 cycles total. We need to make sure the sending side has the same timing.</p>
<h2>Sending a Byte</h2>
<p>The 1541 disk drive has the IEC bus exposed through port A of its first &#8220;VIA&#8221; I/O chip, which is mapped at $1800:</p>
<table border="1">
<tr>
<td>7</td>
<td>IEC ATN IN</td>
</tr>
<tr>
<td>6-5</td>
<td>Device number jumper</td>
</tr>
<tr>
<td>4</td>
<td>IEC ATN ACK OUT</td>
</tr>
<tr>
<td>3</td>
<td>IEC CLOCK OUT</td>
</tr>
<tr>
<td>2</td>
<td>IEC CLOCK IN</td>
</tr>
<tr>
<td>1</td>
<td>IEC DATA OUT</td>
</tr>
<tr>
<td>0</td>
<td>IEC DATA IN</td>
</tr>
</table>
<p>The bits to write the data into are number 1 and number 3, which are not next to each other, so sending is a little more complicated than receiving. The following code assumes that the low 4 bits of the data byte are in register A, and the high 4 bits are in register Y:</p>
<pre>
    sta $1800 ; send bits 1 and 3 of A
    asl       ; bits 0 and 2 become bits 1 and 3
    and #$0F  ; mask off bit #4
    sta $1800 ; send bits 0 and 1 in A
    tya
    nop
    sta $1800 ; send bits 1 and 3 in Y
    asl       ; bits 0 and 2 become bits 1 and 3
    and #$0F  ; mask off bit #4
    sta $1800 ; send bits 0 and 1 in Y
</pre>
<p>The idea is to first just write the low 4 bits into the output port, therefore sending bits 1 and 3. Shifting the value left by one will put bits 0 and 2 into positions 1 and 3 and we can send them by writing them into the output port. Then we repeat this with the upper four bits.</p>
<p>The absolute stores are taking 4 cycles each, and &#8220;asl&#8221;, &#8220;and&#8221;, &#8220;tya&#8221; and &#8220;nop&#8221; all take 2 cycles each, so this code has exactly the same timing as the receiver side.</p>
<p>But unfortunately, this code sends the bits in the wrong order, so we need to correct it, either on the sending or on the receiving side. A simple lookup in a 256 byte table (on either side) would do the job, but storing the table in the fast loader would increase its size significantly &#8211; and therefore the time to load the fast loader with the original Commodore serial code. It would be possible to generate this table at runtime, but a good tradeoff between size and performance is this code (34 bytes; with a few bytes more, it could be converted into a generator for the table):</p>
<pre>
    eor #3        ; fix up bits 0-1 (VIC bank)
    pha           ; save original
    lsr
    lsr
    lsr
    lsr           ; get high nybble
    tax           ; to X
    ldy enc_tab,x ; super-encoded high nybble in Y
    pla
    and #$0F      ; lower nybble
    tax
    lda enc_tab,x ; super-encoded low nybble in A

enc_tab:
    .byte %1111, %0111, %1101, %0101, %1011, %0011, %1001, %0001
    .byte %1110, %0110, %1100, %0100, %1010, %0010, %1000, %0000
</pre>
<p>First, we invert the lowest two bits of the value to send, because the receiving side always reads back &#8220;11&#8243; in the lowest bits of $DD00. Then we encode both the high and the low 4 bits using a 16 byte table, putting the results in the A (low) and Y (high) registers. This table interleaves the four bits so that 0123 becomes 3120 and inverts every bit: An interesting property of the lines from the drive to the computer is that all lines arrive inverted at the computer side. This is not the case for the lines from the computer to the drive. So after this conversion, the send code above can blindly send the bits, which will show up as the original value on the receiver side.</p>
<h2>Handshake</h2>
<p>But it is not enough to just bang the bits on the bus &#8211; after every byte, we need to do a handshake. In a perfect world, we could just send a complete sector (256 bytes on a 1541) in a go, maybe even in an unrolled loop for extra speed, but there are several reasons against it. One reason is that the floppy is clocked about 2% faster, so we&#8217;re off by one cycle every 67 cycles. The fastest possible send loop is about 50 cycles per byte (including the byte encoding), and the time between two pieces of data on the bus (i.e. $1800 writes/$DD00 reads) is 8 cycles, so after 8*67 = 536 cycles = 10 transfered bytes we have missed two bits. Getting the timing correct across such a long time becomes very tricky then.</p>
<p>Another problem is the fact that the video chip in the C64 (&#8220;VIC-II&#8221;) requires 40 cycles for DMA on every 8th line of the visible screen that it sends to the display, completely stopping the CPU, which would mess up all timing. One raster line on the C64 is exactly 63 cycles long, so these CPU stalls (&#8220;badlines&#8221;) happen every 504 cycles. If we start a transfer of several bytes just after one of these badlines, we have time for a maximum of about 9 bytes ((504-40)/50). Or we could only transfer data while the VIC is outside the visible area, but this is only in 112 of the 312 lines, so we would be wasting about 64% of the processing power. Most fast loaders just turn off the screen, so the VIC doesn&#8217;t do these fetches any more, but we don&#8217;t want to take this shortcut!</p>
<p>Badlines happen every time the vertical raster location (readable in register $D012 of the VIC) is between 50 and 249 and the the lowest 3 bits reach the value of 3. (Actually, this value is variable and corresponds to the lowest 3 bits in register $D011.) So the first thing to check is whether we are below 50 or above 249 (i.e. between 250 and 311). $D012 only holds the lowest 8 bits of the raster register (the MSB is stored in the MSB of $D011), but just checking for $D012 being below 50 already means that the raster register is between 0-49 or 256-305 &#8211; this easier check with some false positives is preferrable to a more compicated but slower check. So if we are in the visible area, we must watch out whenever we are are in a line that ends in &#8220;2&#8243;, because a badline will happen some time within the next 63 cycles. In every other case, a badline won&#8217;t happen within at least 63 cycles, so we are safe to spend our 28 cycles in the receiver code. The following code does this:</p>
<pre>
wait_raster:
    lda $D012           ; vertical raster position (bits 0-7)
    cmp #50             ; between 0-49 or 256-305?
    bcc wait_raster_end ; yes, so it's safe
    and #$07            ; lowest 3 bits
    cmp #$02            ; are we in the line before a badline?
    beq wait_raster     ; yes, then wait until we are not
wait_raster_end:
</pre>
<p>If sprites are visible on the screen, this also requires extra DMAs from the VIC, but we assume that there no sprites active. If in doubt, writing 0 into VIC register $D015 makes sure they are all turned off.</p>
<p>Now the actual handshake is rather easy. The protocol is this: At the beginning, both the computer and the drive set their handshake flags to &#8220;not ready&#8221;. When the drive has data in its buffer and is ready to send a byte, it sends its flag to &#8220;ready&#8221;. Then the C64 makes sure it is not in danger of a badline and sets its &#8220;ready&#8221; flag. Just after the transfer of the byte, both devices set their flags to &#8220;not ready&#8221; again. The drive signals readyness with CLK=0, and the computer does so with both CLK=0 and DATA=0, so the code looks like this:</p>
<pre>
;-----
; C64 at initialization time
    lda #VIC_OUT | DATA_OUT ; CLK=0 DATA=1
    sta $DD00               ; we're not ready to receive

;-----
; drive at initialization time
    lda #F_CLK_OUT          ; CLK=1 DATA=0
    sta $1800               ; drive code running, we're not ready to send

;-----
; C64 waiting for drive code running
wait_fast:
    bit $DD00
    bvs wait_fast           ; wait for CLK=1, i.e. drive code running

;-----
; drive when it is ready to send (i.e. byte in buffer and converted)
    lda #0                  ; CLK=0 DATA=0
    sta $1800               ; we're ready to send

;-----
; C64 waiting for drive ready to send
wait_byte:
    bit $DD00
    bvc wait_byte           ; wait for CLK=0, i.e. drive ready to send

;-----
; C64 when it is ready to receive (i.e. not in danger of badline)
    lda #VIC_OUT            ; CLK=0 DATA=0
    sta $DD00               ; we're ready, start sending!

;-----
; drive waiting for C64 ready to receive
wait_c64:
    ldx $1800
    bne wait_c64            ; needs all 0

;-----
; C64 after receiving a byte
    lda #VIC_OUT | DATA_OUT ; CLK=0 DATA=1
    sta $DD00               ; not ready any more, don't start sending

;-----
; drive after sending a byte
    jsr $E9AE               ; CLK=1 (use ROM code to opimize for size)
</pre>
<p>Please note that logic on all $DD00 reads on the computer side looks backwards, because the bits get inverted.</p>
<h2>Timing after the Handshake</h2>
<p>The send and the receive code have exactly the same timing, but we need to make sure that they also start at the same time. The C64 code cannot start reading data from the bus directly after telling the drive that it is ready to receive, because the drive is testing for the C64&#8242;s readiness in this loop:</p>
<pre>
;-----
; drive waiting for C64 ready to receive
wait_c64:
    ldx $1800
    bne wait_c64            ; needs all 0
</pre>
<p>The load takes 4 cycles, and the branch 2 or 3, depending on whether it is taken. The actual bus access for the read from $1800 takes place in the third cycle, so in the worst case, the computer signals that its ready exactly the fourth cycle: In this case, the LDX has read the old value and the branch is taken, the LDX reads the value again, gets the right value now, and doesn&#8217;t take the branch. So the maximum time until the 1541 reacts is 10 cycles: 1 for the last cycle in the LDX, 3 for the taken branch, 4 for another LDX, and 2 for the final non-taken branch. This is the code that delays for 10 cycles between the ready signalling and the reading of the first 2 bits:</p>
<pre>
    lda #VIC_OUT ; CLK=0 DATA=0
    sta $DD00    ; we're ready, start sending!
    pha          ; 3 cycles
    pla          ; 4 cycles
    bit $00      ; 3 cycles
    lda $DD00    ; get 2 bits into bits 6&#038;7
</pre>
<h2>Reading Sectors</h2>
<p>Now that we have the transfer code for one byte in place, we can easily construct a loop on both sides that repeats the transfer 256 times for a full sector. But we also need code running inside the drive that reads sectors from disk in the first place. The easiest way to do this is use the ROM code. It will happily position the read head for us, wait for the sector to come by, read it, decode the on-disk bit encoding (6-to-4 Group-Code-Recording, GCR) and put it into a buffer:</p>
<pre>
    lda #TRACK
    sta $06
    lda #SECTOR
    sta $07
    lda #0
    sta $f9     ; buffer at $0300
    cli
    jsr $D586   ; read sector
    sei
</pre>
<p>The 1541 has 5 buffers, numbered 0 through 4, from $0300-$03FF to $0600-$06FF. The track and sector for buffer 0 are stored in zero page addresses 6 and 7, the ones for buffer one in addresses 8 and 9 and so on. Note that during the whole process of loading data into the C64, we have interrupts disabled (&#8220;SEI&#8221;), so we need to reenable them while reading from disk for the timers to work properly.</p>
<p>More advanced fastloaders don&#8217;t use the ROM code for reading, but implement a more optimized version, achieving another minor speedup. Bigger speedups can be achieved by changing the algorithm of reading completely: Tracks on a 1541 disk are up to 21 sectors, 256 bytes each, but the 1541 RAM is only 2 KB, so it cannot read a whole track into memory. Therefore it reads one sector, transfers it, reads another one and so on. After reading a sector, it needs to be decoded and sent, during which time the disk continues spinning, causing the drive to miss a few sectors. So it would be a bad idea to store files on consecutive sectors, since this would mean it has to wait for a whole turn of the disk (one fifth of a second) for that sector to arrive under the head again.</p>
<p>Instead files are stored in an interleaved fashion, typically with an interleave factor of 4, meaning a file is for example stored on sectors 0, 4, 8, 12 etc. When a fast loader is used, it would typically require a different interleave factor for optimal performance, but unfortunately the interleave factor is a property of the already written disk. A very advanced method of fast loading is therefore to always read the sector that comes by next and transfer it, unless it has been transfered before, until the complete track is in the C64. The C64 then sorts the sectors in the correct order. For smaller files, this does not work too well, since this method always reads and transfers complete tracks.</p>
<p>Even different fast loaders (like Heureka Sprint, used by Turrican and some other Rainbow Arts titles) require the data on disk to be encoded differently, making decoding more efficient. Some copy programs, like &#8220;Master Copy&#8221; don&#8217;t decode the sector data at all &#8211; but they can only do this because they write the same encoding, and the actual payload data is never required.</p>
<p>But in order to keep the implementation really small (custom read code is in the order of 600 bytes) let&#8217;s stay with the code in ROM.</p>
<h2>Uploading the Code into the Drive</h2>
<p>Let&#8217;s consider both pieces of code on the C64 and the 1541 side finished now, but what&#8217;s still missing is code to upload the drive code into the RAM of the 1541 and run it. There are several ways of doing this: The 1541 operating system over the original IEC protocol has a &#8220;memory-write&#8221; (&#8220;M-W&#8221;) command, allowing us to upload up to 36 bytes at a time, and a &#8220;memory-execute&#8221; (&#8220;M-E&#8221;) command that makes the CPU jump to the address we specify. Our 1541 code is about 100 bytes, which would take about a quarter of a second to upload with the original protocol.</p>
<p>But there is a way to avoid this cost: All code and data in the C64 came originally from disk, so why would we download it to the C64 and upload it to the 1541 again? We can just instruct the 1541 to read a sector and execute it. This can be done with block-read (&#8220;B-R&#8221;) and &#8220;memory-execute&#8221;, or with the specialized instruction &#8220;block-execute&#8221; (&#8220;B-E&#8221;). Unfortunately, &#8220;block-execute&#8221; does not work on the concept of buffers, but on the concept of channels which abstract buffers, making this more complex than it would have to be.</p>
<p>A common trick is to upload minimal 6502 code to the drive that reads a sector and jumps to it and execute that. And it&#8217;s even possible to avoid the &#8220;memory-write&#8221; command: When sending the &#8220;memory-execute&#8221;, we can send trailing bytes, for a command that is up to 42 bytes long. The code would just travel with the &#8220;memory-execute&#8221; command, and the execution address would point to this very code in the temporary command buffer:</p>
<pre>
    lda #$0f
    sta $b9   ; secondary address
    sta $b8   ; logical file number
    ldx #<cmd
    ldy #>cmd
    lda #cmd_end - cmd
    jsr $fdf9 ; filnam
    jsr $f34a ; open
    brk

cmd:
    .byte "M-E"
    .word $0200 + cmd_code - cmd
cmd_code:
    lda #18   ; track 18, sector 18
    sta $08
    sta $09
    lda #1    ; buffer at $0400
    sta $f9
    jsr $d586 ; read sector
    jmp $0400 ; jump to the code we loaded
cmd_end:
</pre>
<p>The command buffer in the 1541 is located at $0200, so the &#8220;memory-execute&#8221; jumps to the first byte just after the command itself, at $0205. We choose to store the floppy code on track 18, sector 18: Track 18 is decidated to directory entries, so unless the disk has 144 files on it, it is unlikely all sectors of track 18 are in use. Reading the code from track 18 also means the head does not have to move if we store the C64 loader there, too.</p>
<h2>Fitting C64 and Drive Code Into a Single Sector</h2>
<p>But there is an even simpler and faster solution: If we manage to fit both the C64 code and the floppy code into a single sector, we don&#8217;t have to read another sector, but we can just send a &#8220;memory-execute&#8221; into the buffer that the block was loaded into:</p>
<pre>
cmd:
    .byte "M-E"
    .word $0482
cmd_end:
</pre>
<p>The default buffer is #1 at $0400 in the drive&#8217;s memory, so after the start program got loaded into the C64, the sector can still be found at $0400.</p>
<p>The default 1541 file system does not support random file access, therefore there is no central data structure that allows a lookup of the sector number following the current one. Instead, the link to the next track and sector is stored in the first two bytes of every sector, reducing the usable space in a sector to 254 bytes (and making seeks in a file very expensive). So the first byte in a sector is the track (1-35) and the second byte is the sector (0-20) of the following block. If it is the last block of a file, the track number is zero and the sector field contains the number of valid bytes in the block; all bytes afterwards will be ignored and not transfered. This allows files that are not a multiple of 254 bytes in size.</p>
<p>So the trick is to create a file that is about half a sector in size and contains the C64 code, and we store the drive code in the unused half of the sector. So the reason why we always optimized for code size when choosing algorithms before was because we really need to fit everything in 256 bytes!</p>
<h2>Header</h2>
<p>Now what is the executable file format, you may ask? What are the headers, how are they structured? How much data is used for headers? It is complicated.</p>
<p>The shell of the C64 was Commodore BASIC, a derivative of <a href="http://www.pagetable.com/?p=43">Microsoft</a> <a href="http://www.pagetable.com/?p=46">BASIC</a> <a href="http://www.pagetable.com/?p=45">for 6502</a>. So you would load BASIC programs from disk with the &#8220;LOAD&#8221; command, you could have them printed on the screen with &#8220;LIST&#8221; and edit them; and if you wanted to run them, you would type &#8220;RUN&#8221;. This concept wasn&#8217;t really meant for programs not written in BASIC, but it was enough to have a small BASIC header in front of your assembly program, like this:</p>
<pre>
10 SYS2061
</pre>
<p>BASIC programs get loaded to $0801, so the machine code is stored directly after this small BASIC header which tells the interpreter to run machine code at 2061 = $080D. But this wastes 12 bytes and requires the user to type &#8220;RUN&#8221; after the program is loaded.</p>
<h2>Autostart</h2>
<p>It is much nicer to have the program autostart directly after the &#8220;LOAD&#8221; command. The trick here is to have the program load not into BASIC RAM, but into a region where it overwrites vectors &#8211; it&#8217;s basically a buffer exploit! Here is a rough memory map of the C64:</p>
<table border="1">
<tr>
<td>$0000-$00FF</td>
<td>BASIC and KERNAL variables</td>
</tr>
<tr>
<td>$0100-$01FF</td>
<td>Stack</td>
</tr>
<tr>
<td>$0200-$0258</td>
<td>BASIC input buffer</td>
</tr>
<tr>
<td>$0259-$02FF</td>
<td>BASIC and KERNAL variables</td>
</tr>
<tr>
<td>$0300-$033B</td>
<td>System vectors</td>
</tr>
<tr>
<td>$033C-$03FF</td>
<td>I/O buffer</td>
</tr>
<tr>
<td>$0400-$07FF</td>
<td>Screen RAM</td>
</tr>
<tr>
<td>$0800-$9FFF</td>
<td>BASIC RAM</td>
</tr>
<tr>
<td>$A000-$BFFF</td>
<td>BASIC ROM</td>
</tr>
<tr>
<td>$C000-$CFFF</td>
<td>RAM</td>
</tr>
<tr>
<td>$D000-$DFFF</td>
<td>Device MMIO</td>
</tr>
<tr>
<td>$E000-$FFFF</td>
<td>KERNAL ROM</td>
</tr>
</table>
<p>Commonly, autostart programs would overwrite the system vectors at $0300:</p>
<table border="1">
<tr>
<td>$0314-$0315</td>
<td>IRQ vector</td>
</tr>
<tr>
<td>$0316-$0317</td>
<td>BRK vector</td>
</tr>
<tr>
<td>$0318-$0319</td>
<td>NMI vector</td>
</tr>
<tr>
<td>$031A-$031B</td>
<td>OPEN vector</td>
</tr>
<tr>
<td>$031C-$031D</td>
<td>CLOSE vector</td>
</tr>
<tr>
<td>$031E-$031F</td>
<td>CHKIN vector</td>
</tr>
<tr>
<td>$0320-$0321</td>
<td>CHKOUT vector</td>
</tr>
<tr>
<td>$0322-$0323</td>
<td>CLRCHN vector</td>
</tr>
<tr>
<td>$0324-$0325</td>
<td>CHRIN vector</td>
</tr>
<tr>
<td>$0326-$0327</td>
<td>CHROUT vector</td>
</tr>
<tr>
<td>$0328-$0329</td>
<td>STOP vector</td>
</tr>
<tr>
<td>$032A-$032B</td>
<td>GETIN vector</td>
</tr>
<tr>
<td>$032C-$032D</td>
<td>CLALL vector</td>
</tr>
<tr>
<td>$032E-$032F</td>
<td>unused</td>
</tr>
<tr>
<td>$0330-$0331</td>
<td>LOAD vector</td>
</tr>
<tr>
<td>$0332-$0333</td>
<td>SAVE vector</td>
</tr>
<tr>
<td>0334-033B</td>
<td>unused</td>
</tr>
<tr>
<td>033C-03FB</td>
<td>Tape buffer</td>
</tr>
</table>
<p>Your program would load to $0326, for example, overwriting the CHROUT vector as well as the 5 following vectors, and your code would be loaded into the tape buffer starting at $033C. When loading is finished, the BASIC interpreter wants to print &#8220;READY.&#8221;, jumping over the CHROUT vector at $0326 and therefore into your code.</p>
<p>The problem with this solution is that we have to preserve the values of some of the vectors between $0328 and $033B, because the original LOAD code in ROM calls the STOP vector to test whether the user pressed the STOP key. So our file would have to contain the original values, not only wasting 12 bytes, but also introducing potential incompatibilities if the user has a cartridge like the Final Cartridge III or the Action Replay VI attached &#8211; these devices were practically ROM extensions and hooked some of these vectors to provide improved functionality.</p>
<p>(Actually, overwriting the STOP vector is useful in a different scenario: This way, we can catch execution during the load operation as opposed to after it and continue loading the same file with a replacement bus protocol.)</p>
<p>A different way to gain control after loading is to load into the stack and overwriting the address returned to after the LOAD is finished. The stack on the 6502 is always located between $0100 and $01FF, so if we overwrite this complete area with a value of 2, we would put all &#8220;$0202&#8243; vectors on the stack, catching execution as soon as the inner ROM LOAD code returns to its caller. Since the 6502 increments the return address after it fetches it from the stack, our payload would live at $0203, which is still pretty much directly after the stack area. But of course overwriting the complete stack is a waste: Experimentation shows that the one vector on the stack that actually counts is located at $01F8/$01F9.</p>
<h2>Laying Out the Code</h2>
<p>The problem with the payload starting at $0203 is that we can only use the memory up to $0258 (55 bytes) &#8211; this is the buffer for a BASIC input line. Unfortunately, this is not enough, since our code is more like 110 bytes. We can put the payload before the vector we overwrite, i.e. onto the stack. But we must be careful, because the LOAD code in ROM uses some stack, overwriting the area between $01ED to $01F7. So let&#8217;s have our code start somewhere in the stack area, going up to $01EC, and put a JMP to the code at $0203 to catch the stack return.</p>
<p>The 11 bytes at $01ED-$01F7 (stack that gets overwritten while loading) and the 9 bytes at $01FA-$0202 (area between the vector on the stack we overwrite and our first instruction at $0203) seems wasted &#8211; but not quite. We can use $01FE-$0202 to store our 5 byte &#8220;M-E&#8221; string, and we just fill all bytes from $01ED to $01FD with &#8220;2&#8243;. This gives us extra safety that our code will work machines with replacement ROMs or extended ROM routines that use a slightly different stack layout &#8211; as long as they don&#8217;t use more stack and overwrite our code.</p>
<h2>Final Words</h2>
<p>Fast loaders and autostart bootloaders have been around for almost as long as the C64. Fast loaders have used the stack trick before, and 26 cycle drive transfer code with the screen turned on has been in use before as well. So what&#8217;s really novel about the bootloader described in this article is the combination of the most optimized tricks into a single-block (256 byte) program. That&#8217;s the beauty of programming for the C64: Practically everything is implicitly open source, since the best algorithms fit in a few hundred bytes of code, and an experienced C64 hacker can reverse-engineer existing code and incorporate it into his own. That&#8217;s how it has always been done.</p>
<h2>The Code</h2>
<p>Here is the complete code, which can be assembled with the ca65 assembler of the <a href="http://www.cc65.org/">cc65 compiler suite</a>.</p>
<pre>

TARGET := $0400
TRACK := 18

DATA_OUT := $20 ; bit 5
CLK_OUT  := $10 ; bit 4
VIC_OUT  := $03 ; bits need to be on to keep VIC happy

seccnt = 2

;----------------------------------------------------------------------
; Hack to generate .PRG file with load address as first word
;----------------------------------------------------------------------
.segment "LOADADDR"
.addr *

;----------------------------------------------------------------------
; Send an "M-E" to the 1541 that jumps to floppy code.
; Then receive one block and run it.
; This code lives around $0190.
;----------------------------------------------------------------------
.segment "PART2"
main:
    lda #$0f
    sta $b9
    sta $b8
    ldx #&lt;memory_execute
    ldy #&gt;memory_execute
    lda #memory_execute_end - memory_execute
    jsr $fdf9 ; filnam
    jsr $f34a ; open

    sei
    lda #VIC_OUT | DATA_OUT ; CLK=0 DATA=1
    sta $DD00 ; we're not ready to receive

; wait until floppy code is active
wait_fast:
    bit $DD00
    bvs wait_fast ; wait for CLK=1 (inverted read!)

    lda #sector_table_end - sector_table ; number of sectors
    sta seccnt
    ldy #0
get_rest_loop:
    bit $DD00
    bvc get_rest_loop ; wait for CLK=0 (inverted read!)

; wait for raster
wait_raster:
    lda $D012
    cmp #50
    bcc wait_raster_end
    and #$07
    cmp #$02
    beq wait_raster
wait_raster_end:

    lda #VIC_OUT ; CLK=0 DATA=0
    sta $DD00 ; we're ready, start sending!
    pha ; 3 cycles
    pla ; 4 cycles
    bit $00 ; 3 cycles
    lda $DD00 ; get 2 bits into bits 6&#038;7
    lsr
    lsr ; move down by 2 (bits 4&#038;5)
    eor $DD00 ; get 2 more bits
    lsr
    lsr ; move everything down (bits 2-5)
    eor $DD00; get 2 more bits
    lsr
    lsr ; move everything down (bits 0-5)
    eor $DD00 ; get last 2 bits, now 0-7 are populated

    ldx #VIC_OUT | DATA_OUT ; CLK=0 DATA=1
    stx $DD00 ; not ready any more, don't start sending

selfmod1:
    sta TARGET,y
    iny
    bne get_rest_loop

    inc selfmod1+2
    dec seccnt
    bne get_rest_loop

inf:
    jmp inf

.segment "VECTOR"
; these bytes will be overwritten by the KERNAL stack while loading
; let's set them all to "2" so we have a chance that this will work
; on a modified KERNAL
    .byte 2,2,2,2,2,2,2,2,2,2,2
; This is the vector to the start of the code; RTS will jump to $0203
    .byte 2,2
; These bytes are on top of the return value on the stack. We could use
; them for data; or, fill them with "2" so different versions of KERNAL
; might work
    .byte 2,2,2,2

.segment "CMD"
memory_execute:
     .byte "M-E"
     .word $0480 + 2
memory_execute_end:

;----------------------------------------------------------------------
; Jump to code that receives data.
;----------------------------------------------------------------------
.segment "START"
    jmp main

;----------------------------------------------------------------------
;----------------------------------------------------------------------
; C64 -> Floppy: direct
; Floppy -> C64: inverted
;----------------------------------------------------------------------
;----------------------------------------------------------------------

.segment "FCODE"

F_DATA_OUT := $02
F_CLK_OUT  := $08

sec_index := $05

start1541:
    lda #F_CLK_OUT
    sta $1800 ; fast code is running!

    lda #0 ; sector
    sta sec_index
    sta $f9 ; buffer $0300 for the read
    lda #TRACK
    sta $06
read_loop:
    ldx sec_index
    lda sector_table,x
    inc sec_index
    bmi end
    sta $07
    cli
    jsr $D586       ; read sector
    sei

send_loop:
; we can use $f9 as the byte counter, since we'll return it to 0
; so it holds the correct buffer number "0" when we read the next sector
    ldx $f9
    lda $0300,x

; first encode
    eor #3 ; fix up for receiver side (VIC bank!)
    pha ; save original
    lsr
    lsr
    lsr
    lsr ; get high nybble
    tax ; to X
    ldy enc_tab,x ; super-encoded high nybble in Y
    ldx #0
    stx $1800 ; DATA=0, CLK=0 -> we're ready to send!
    pla
    and #$0F ; lower nybble
    tax
    lda enc_tab,x ; super-encoded low nybble in A
; then wait for C64 to be ready
wait_c64:
    ldx $1800
    bne wait_c64; needs all 0

; then send
    sta $1800
    asl
    and #$0F
    sta $1800
    tya
    nop
    sta $1800
    asl
    and #$0F
    sta $1800

    jsr $E9AE ; CLK=1 10 cycles later

    inc $f9
    bne send_loop
    beq read_loop

end:
    jmp *

enc_tab:
    .byte %1111, %0111, %1101, %0101, %1011, %0011, %1001, %0001
    .byte %1110, %0110, %1100, %0100, %1010, %0010, %1000, %0000

sector_table:
    .byte 0,1,2,3,$FF
sector_table_end:
</pre>
<p>This is the linker script:</p>
<pre>
MEMORY {
    # hack to get the load address as the first 2 bytes into the .PRG
    LOADADDR: start = $0188, size = 2;

    # the receive code, filled with $02s that overwrite the top few bytes of
    # the stack and make the KERNAL loader return to $0203
    PART2:    start = $0188, size = $0065, fill = yes, fillval = $FF, file = %O;

    VECTOR:   start = $01ED, size = $0011, fill = yes, fillval = $FF, file = %O;

    CMD:      start = $01FE, size = $0005, fill = yes, fillval = $FF, file = %O;

    # entry point $0203 due to stack overwritten with $02s
    # code that transfers M-E
    START:    start = $0203, size = $0003, fill = yes, fillval = $ff, file = %O;

    FCODE:    start = $482, size = $007E, fill = yes, fillval = $ff, file = %O;
}

SEGMENTS {
    LOADADDR:   load = LOADADDR,    type = ro;
    START:      load = START,       type = ro;
    PART2:      load = PART2,       type = ro;
    CMD:        load = CMD,         type = ro;
    VECTOR:     load = VECTOR,      type = ro;
    FCODE:      load = FCODE,       type = ro;
}
</pre>
<p>This script for the c1541 tool, which puts the code into a disk image:</p>
<pre>
format autostart,01
write "start.prg"
</pre>
<p>And this is the shell script that builds the whole thing:</p>
<pre>
ca65 start.s &#038;&#038;
ld65 -C start.cfg start.o -o start.prg &#038;&#038;
dd if=/dev/zero of=autostart.d64 bs=256 count=683 &#038;&#038;
c1541 autostart.d64 < c1541script.txt
</pre>
<p>Note that the c1541 tool creates a file with the whole block on disk, so in practice, the 1541 code will be loaded into the C64 as well, but never used. So the two link bytes of the block would have to be manually changed to decrease its size to achieve maximum speed.</p>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=568&amp;ts=1369319073" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=568</wfw:commentRss>
		<slash:comments>23</slash:comments>
		</item>
		<item>
		<title>How many Commodore 64 computers were really sold?</title>
		<link>http://www.pagetable.com/?p=547</link>
		<comments>http://www.pagetable.com/?p=547#comments</comments>
		<pubDate>Tue, 01 Feb 2011 09:00:34 +0000</pubDate>
		<dc:creator>Michael Steil</dc:creator>
				<category><![CDATA[6502]]></category>
		<category><![CDATA[archeology]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=547</guid>
		<description><![CDATA[Nobody doubts that the C64 was the greatest selling single computer model of all time, it even made it into the Guinness Book of World Records, but nobody quite knows how many it really was: Most sources say 17 million, others say 22 or even 30 million. With a high degree of confidence, I can [...]]]></description>
			<content:encoded><![CDATA[<p>Nobody doubts that the <a href="http://www.pagetable.com/?p=54">C64</a> was the greatest selling single computer model of all time, it even made it into the Guinness Book of World Records, but nobody quite knows how many it really was: Most sources say 17 million, others say 22 or even 30 million. With a high degree of confidence, I can now say that Commodore only sold 12.5 million units &#8211; how I would know that, you ask, and how do I dare to contradict well-known facts? By analyzing serial numbers!</p>
<p>But let us first examine the existing claims of 17, 22 and 30 million.</p>
<h3>Jack Tramiel&#8217;s numbers</h3>
<p>The numbers 22 and 30 million actually come from Commodore founder Jack Tramiel himself. At the <a href="http://www.computerhistory.org/events/index.php?id=1193702785">&#8220;Impact of the Commodore 64: A 25th Anniversary Celebration&#8221;</a> in December 2007 at the <a href="http://www.computerhistory.org/">Computer History Museum</a>, Tramiel claimed that Commodore sold nearly half a million C64s a month until he left the company in 1984, and he extrapolated this to &#8220;between 22 and 30 million units&#8221; during the lifetime of the C64. Tramiel&#8217;s assistant Michael Tomczyk, who left the company around the same time, uses the same 22 million figure in his 1984 book &#8220;Home Computer Wars &#8211; An Insider&#8217;s Account of Commodore and Jack Tramiel&#8221;.</p>
<h3>Commodore&#8217;s Numbers</h3>
<p>But these numbers contradict Commodore&#8217;s official sales numbers as <a href="http://groups.google.com/group/alt.c64/msg/d5b890f317d972fd">researched by Marc Walters</a>: The 1993 Annual Report supposedly states that 17 million units had been sold (production was stopped in April 1994, so this should be very close to the final number). Commodore employee Dr. Peter Kittel <a href="http://www.c64-wiki.com/index.php/Commodore">confirms</a> the 17 million.</p>
<p>Walters quotes <a href="<a href="http://groups.google.com/group/comp.sys.amiga.advocacy/msg/9133fa7a79b3420a">Commodore&#8217;s 1993 financial details</a> for the sales numbers between 1990 and 1993:</p>
<pre>
The following figures are from Commodore annual reports:
Fiscal 1990: 700K - 800K (decline begins),
fiscal 1991: 800K (non official 1M)
fiscal 1992: 650K
fiscal 1993: 150K - 200K
1993 Annual Report: 17M total C64, 4.5M C128
</pre>
<h3>Marc Walters&#8217; estimates</h3>
<p>Walters also gives his own estimates for 1982 through 1989:</p>
<pre>
1982: 150K - 300K
1983: 2M
1984: 2M-3M
1985: 2M -3M
1986: 2M -3M
1987: 1M - 2M
1988: 1M - 1.5M
1989: 1M - 1.5M
</pre>
<p>This data was later picked up by <a href="http://jeremyreimer.com/postman/node/329">Jeremy Reimer</a> for his Ars Technica article &#8220;<a href="http://arstechnica.com/old/content/2005/12/total-share.ars">Total share: 30 years of personal computer market share figures</a>&#8220;.</p>
<p>With these numbers, Commodore would have sold between 13.5 and 19 million units. The following graph shows this, with the 17 million figure added as a scaled version of the ranges given:</p>
<p><img src="docs/c64_sales/13-17-19.png" width="440"></p>
<h3>Putting all reliable data together</h3>
<p>This data is quite consistent, but generic sources contradict these steep numbers in the first years:</p>
<ul>
<li>At CES 1984: 1 million (<a href="http://www.floodgap.com/retrobits/ckb/secret/remix.html">floodgab retrobits</a>)</li>
<li>end of 1984: 3 million (<a href="http://www.c64-wiki.com/index.php/Commodore">c64-wiki.com</a>)
<li>end of 1984: 3.5 million (<a href="http://pctimeline.info/c64/">pctimeline.info</a>)
<li>end of 1986: 6 million (<a href="http://www.c64-wiki.com/index.php/Commodore">c64-wiki.com</a>)
<li>end of 1987: 7 million (<a href="http://pctimeline.info/c64/">pctimeline.info</a>)</li>
<li>end of 1990: 11 million (<a href="http://www.webs4u.co.nz/museum/c64-info.html">Commodore Home Computer Museum (NZ)</a>)</li>
</ul>
<p>This data, with Commodore&#8217;s own 1990-1993 data added and some of the missing numbers extrapolated, shows a rather flat and consistent sales curve with a single spike in 1984, totalling about 12.5 million units:</p>
<p><img src="docs/c64_sales/12.png" width="440"></p>
<p>In 1984, about 2 to 2.5 million units were sold, which is about 200,000 units per month. There is no way Tramiel&#8217;s statement holds true, given the many sources of the early numbers and their consistency. This also falsifies claims of Tramiel&#8217;s 22 million and 30 million sold units, which could be approximated by extrapolating the 2.5 million units across a decade &#8211; but the existing data shows that the C64 clearly didn&#8217;t perform equally well afterwards.</p>
<h3>Examining serial numbers</h3>
<p>There are two projects that collect C64 serial numbers:</p>
<ul>
<li>The <a href="http://c64preservation.com/dp.php?pg=registry">C64 Serial Registry</a> by the C64 Preservation Project</li>
<li>The <a href="http://www.telefonica.net/web2/c64-inventory/english/thelist.htm">C64 Inventory</a>
</ul>
<p>While the former collects lots of details including case badges and board types, the latter contains information like the video standard as well as photos of all serial number stickers. For the following statistics, we only need the C64 Serial Registry.</p>
<p>Commodore 64 computers were produced in at least 11 different factories worldwide with different and not immediately obvious conventions for serial numbers. But all PCBs, of which there were <a href="http://www.c-64.org/de/hardware2.html">16 versions</a>, were manufactured in Hong Kong, and most versions were numbered sequentially, starting at 0 for each new version. The serial number could be found on a sticker on the shield of the cartridge port.</p>
<p>The fact that serial numbers are indeed per board version and are reset to zero for every new board can be seen in the following graph, which was created by sorting the serial numbers by board first and then by number:</p>
<p><a href="docs/c64_sales/allboards.png"><img src="docs/c64_sales/allboards.png" width="440"></a></p>
<p>If the assumption is correct, serial numbers have to increase linearly until they approach the highest serial number of the board version. All boards should have about the same slope. This is true for all board versions except &#8220;250425/A&#8221; and &#8220;250425/B&#8221;, as well as the last two, &#8220;250469/A&#8221; and &#8220;250469/A&#8221;.</p>
<p>This can be explained by the bias towards machines from North America in the C64 Serial Registry: About one third of the entries in the database are from the US and Canadian market, but a much smaller percentage of units has actually been sold there &#8211; the C64 was very strong in Europe. The first, second and fourth of these board types with a much higher slope were all sold exclusively, and the third one predominantly to PAL markets, i.e. outside North America.</p>
<p>(If the slope there is roughly twice as steep, we can estimate NTSC units are overrepresented in the database by a factor of two, meaning that about 1/6 of all C64 were sold in North America.)</p>
<p>These are the 16 different versions and revisions, the year they first appeared in, the number of boards of this kind in the C64 Serial Registry (that have the board serial number field filled), and the maximum serial number observed:</p>
<table border="1">
<tr>
<td align="center"><b>year</b></td>
<td align="center"><b>board</b></td>
<td align="center"><b>num_seem</b></td>
<td align="center"><b>max_seen</b></td>
</tr>
<tr>
<td align="center"><b>1982</b></td>
<td>326298</td>
<td align="center">4</td>
<td align="right"></td>
</tr>
<tr>
<td align="center"><b>1982</b></td>
<td>326298/A</td>
<td align="center">21</td>
<td align="right">325,512</td>
</tr>
<tr>
<td align="center"><b>1982</b></td>
<td>326298/B</td>
<td align="center">6</td>
<td align="right"></td>
</tr>
<tr>
<td align="center"><b>1982</b></td>
<td>326298/C</td>
<td align="center">6</td>
<td align="right"></td>
</tr>
<tr>
<td align="center"><b>1982</b></td>
<td>KU-14194HB</td>
<td align="center">16</td>
<td align="right"></td>
</tr>
<tr>
<td align="center"><b>1983</b></td>
<td>250407/A</td>
<td align="center">7</td>
<td align="right">208,282</td>
</tr>
<tr>
<td align="center"><b>1983</b></td>
<td>250407/B</td>
<td align="center">50</td>
<td align="right">1,152,644</td>
</tr>
<tr>
<td align="center"><b>1983</b></td>
<td>250407/C</td>
<td align="center">18</td>
<td align="right">1,218,502</td>
</tr>
<tr>
<td align="center"><b>1984</b></td>
<td>250425/-</td>
<td align="center">48</td>
<td align="right">1,273,699</td>
</tr>
<tr>
<td align="center"><b>1984</b></td>
<td>250425/A</td>
<td align="center">9</td>
<td align="right">500,165</td>
</tr>
<tr>
<td align="center"><b>1984</b></td>
<td>250425/B</td>
<td align="center">4</td>
<td align="right">536,345</td>
</tr>
<tr>
<td align="center"><b>1986</b></td>
<td>250466</td>
<td align="center">18</td>
<td align="right">438,001</td>
</tr>
<tr>
<td align="center"><b>1987</b></td>
<td>250469/3</td>
<td align="center">14</td>
<td align="right">444,384</td>
</tr>
<tr>
<td align="center"><b>1988</b></td>
<td>250469/4</td>
<td align="center">29</td>
<td align="right">1,124,586</td>
</tr>
<tr>
<td align="center"><b>1989</b></td>
<td>250469/A</td>
<td align="center">16</td>
<td align="right">1,994,012</td>
</tr>
<tr>
<td align="center"><b>1990</b></td>
<td>250469/B</td>
<td align="center">17</td>
<td align="right">2,242,493</td>
</tr>
</table>
<p>(Note that four of the early versions do not have any easily discoverable serial numbers on them. Also note that the PET 64 and Educator 64 devices, which were basically &#8220;326298/A&#8221; C64 boards in an all-in-one computer, are also counted, but they sold in very small numbers. The same is true for the ill-fated &#8220;250469/B&#8221;-based C64GS game console. The portable SX-64 has a different board and is not counted.)</p>
<p>Now we can use the formula for the <a href="http://www.pagetable.com/?p=465">German Tank Problem</a> to estimate the total number produced for each type of board for which we have the maximum observed serial number:</a></p>
<p><img src="docs/c64_sales/formula.png"></p>
<p><i>k</i> is the sample size and <i>m</i> is the highest serial number observed.</p>
<table border="1">
<tr>
<td align="center"><b>year</b></td>
<td align="center"><b>board</b></td>
<td align="center"><b>num_seem</b></td>
<td align="center"><b>max_seen</b></td>
<td align="center"><b>total</b></td>
</tr>
<tr>
<td align="center"><b>1982</b></td>
<td>326298</td>
<td align="center">4</td>
<td align="right"></td>
<td align="right"></td>
</tr>
<tr>
<td align="center"><b>1982</b></td>
<td>326298/A</td>
<td align="center">21</td>
<td align="right">325,512</td>
<td align="right">341,012</td>
</tr>
<tr>
<td align="center"><b>1982</b></td>
<td>326298/B</td>
<td align="center">6</td>
<td align="right"></td>
<td align="right"></td>
</tr>
<tr>
<td align="center"><b>1982</b></td>
<td>326298/C</td>
<td align="center">6</td>
<td align="right"></td>
<td align="right"></td>
</tr>
<tr>
<td align="center"><b>1982</b></td>
<td>KU-14194HB</td>
<td align="center">16</td>
<td align="right"></td>
<td align="right"></td>
</tr>
<tr>
<td align="center"><b>1983</b></td>
<td>250407/A</td>
<td align="center">7</td>
<td align="right">208,282</td>
<td align="right">238,036</td>
</tr>
<tr>
<td align="center"><b>1983</b></td>
<td>250407/B</td>
<td align="center">50</td>
<td align="right">1,152,644</td>
<td align="right">1,175,696</td>
</tr>
<tr>
<td align="center"><b>1983</b></td>
<td>250407/C</td>
<td align="center">18</td>
<td align="right">1,218,502</td>
<td align="right">1,286,196</td>
</tr>
<tr>
<td align="center"><b>1984</b></td>
<td>250425/-</td>
<td align="center">48</td>
<td align="right">1,273,699</td>
<td align="right">1,300,233</td>
</tr>
<tr>
<td align="center"><b>1984</b></td>
<td>250425/A</td>
<td align="center">9</td>
<td align="right">500,165</td>
<td align="right">555,738</td>
</tr>
<tr>
<td align="center"><b>1984</b></td>
<td>250425/B</td>
<td align="center">4</td>
<td align="right">536,345</td>
<td align="right">670,430</td>
</tr>
<tr>
<td align="center"><b>1986</b></td>
<td>250466</td>
<td align="center">18</td>
<td align="right">438,001</td>
<td align="right">462,333</td>
</tr>
<tr>
<td align="center"><b>1987</b></td>
<td>250469/3</td>
<td align="center">14</td>
<td align="right">444,384</td>
<td align="right">476,125</td>
</tr>
<tr>
<td align="center"><b>1988</b></td>
<td>250469/4</td>
<td align="center">29</td>
<td align="right">1,124,586</td>
<td align="right">1,163,364</td>
</tr>
<tr>
<td align="center"><b>1989</b></td>
<td>250469/A</td>
<td align="center">16</td>
<td align="right">1,994,012</td>
<td align="right">2,118,637</td>
</tr>
<tr>
<td align="center"><b>1990</b></td>
<td>250469/B</td>
<td align="center">17</td>
<td align="right">2,242,493</td>
<td align="right">2,374,403</td>
</tr>
</table>
<p>For the board types without serial numbers, we can approximate the number of boards produced by scaling the result of board &#8220;326298/A&#8221; to the number of observed units of the missing ones. Since all boards without serials are from 1982 just like &#8220;326298/A&#8221;, it is probably not a very bad estimate.</p>
<p>(On the other hand, board &#8220;KU-14194HB&#8221; has only ever been put into machines produced in Germany and sold in Europe, so because of the bias of the database towards North America, this board type might be underrepresented.)</p>
<table border="1">
<tr>
<td align="center"><b>year</b></td>
<td align="center"><b>board</b></td>
<td align="center"><b>num_seem</b></td>
<td align="center"><b>max_seen</b></td>
<td align="center"><b>total</b></td>
</tr>
<tr>
<td align="center"><b>1982</b></td>
<td>326298</td>
<td align="center">4</td>
<td align="right"></td>
<td align="right">64,955</td>
</tr>
<tr>
<td align="center"><b>1982</b></td>
<td>326298/A</td>
<td align="center">21</td>
<td align="right">325,512</td>
<td align="right">341,012</td>
</tr>
<tr>
<td align="center"><b>1982</b></td>
<td>326298/B</td>
<td align="center">6</td>
<td align="right"></td>
<td align="right">97,432</td>
</tr>
<tr>
<td align="center"><b>1982</b></td>
<td>326298/C</td>
<td align="center">6</td>
<td align="right"></td>
<td align="right">97,432</td>
</tr>
<tr>
<td align="center"><b>1982</b></td>
<td>KU-14194HB</td>
<td align="center">16</td>
<td align="right"></td>
<td align="right">259,818</td>
</tr>
<tr>
<td align="center"><b>1983</b></td>
<td>250407/A</td>
<td align="center">7</td>
<td align="right">208,282</td>
<td align="right">238,036</td>
</tr>
<tr>
<td align="center"><b>1983</b></td>
<td>250407/B</td>
<td align="center">50</td>
<td align="right">1,152,644</td>
<td align="right">1,175,696</td>
</tr>
<tr>
<td align="center"><b>1983</b></td>
<td>250407/C</td>
<td align="center">18</td>
<td align="right">1,218,502</td>
<td align="right">1,286,196</td>
</tr>
<tr>
<td align="center"><b>1984</b></td>
<td>250425/-</td>
<td align="center">48</td>
<td align="right">1,273,699</td>
<td align="right">1,300,233</td>
</tr>
<tr>
<td align="center"><b>1984</b></td>
<td>250425/A</td>
<td align="center">9</td>
<td align="right">500,165</td>
<td align="right">555,738</td>
</tr>
<tr>
<td align="center"><b>1984</b></td>
<td>250425/B</td>
<td align="center">4</td>
<td align="right">536,345</td>
<td align="right">670,430</td>
</tr>
<tr>
<td align="center"><b>1986</b></td>
<td>250466</td>
<td align="center">18</td>
<td align="right">438,001</td>
<td align="right">462,333</td>
</tr>
<tr>
<td align="center"><b>1987</b></td>
<td>250469/3</td>
<td align="center">14</td>
<td align="right">444,384</td>
<td align="right">476,125</td>
</tr>
<tr>
<td align="center"><b>1988</b></td>
<td>250469/4</td>
<td align="center">29</td>
<td align="right">1,124,586</td>
<td align="right">1,163,364</td>
</tr>
<tr>
<td align="center"><b>1989</b></td>
<td>250469/A</td>
<td align="center">16</td>
<td align="right">1,994,012</td>
<td align="right">2,118,637</td>
</tr>
<tr>
<td align="center"><b>1990</b></td>
<td>250469/B</td>
<td align="center">17</td>
<td align="right">2,242,493</td>
<td align="right">2,374,403</td>
</tr>
<tr>
<td align="center"></td>
<td></td>
<td align="center"></td>
<td align="right"></td>
<td align="right"><b>12,681,839</b></td>
</tr>
</table>
<p>So according to this estimate, <b>about 12.5 million Commodore 64 computers were produced</b>, which matches the number above.</p>
<p>(By the way, about 6 million of these had the new smaller board &#8220;250469/X&#8221; with the HMOS chipset, and almost all machines since 1989, which is about 4.5 million, were sold in Europe.)</p>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=547&amp;ts=1369319073" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=547</wfw:commentRss>
		<slash:comments>45</slash:comments>
		</item>
		<item>
		<title>Commodore Plus/4, C116, C16 (TED) Technical Documents</title>
		<link>http://www.pagetable.com/?p=541</link>
		<comments>http://www.pagetable.com/?p=541#comments</comments>
		<pubDate>Tue, 25 Jan 2011 08:00:08 +0000</pubDate>
		<dc:creator>Michael Steil</dc:creator>
				<category><![CDATA[6502]]></category>
		<category><![CDATA[archeology]]></category>
		<category><![CDATA[literature]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=541</guid>
		<description><![CDATA[The Commodore Plus/4, the C16 and the C116 from 1984 were members of the 6502-based &#8220;TED&#8221; series, named after the 7360 TED (&#8220;Text Editing Device&#8221;) video controller. The TED systems were basically the low-cost cousins of the C64: The overall system architecture and the video chip are very similar to the C64&#8242;s, but they lack [...]]]></description>
			<content:encoded><![CDATA[<p>The Commodore Plus/4, the C16 and the C116 from 1984 were members of the 6502-based &#8220;TED&#8221; series, named after the 7360 TED (&#8220;Text Editing Device&#8221;) video controller. The TED systems were basically the low-cost cousins of the C64: The overall system architecture and the video chip are very similar to the C64&#8242;s, but they lack certain features like hardware sprites. On the other hand, there are some added features like extra colors and more control over the internal timing of the video chip.</p>
<p>In the <a href="http://zimmers.net/anonftp/pub/cbm/">Commodore archive at zimmers.net</a>, there is a <a href="http://www.zimmers.net/anonftp/pub/cbm/plus4/programming/manual/">collection of GIF images</a> that are scans of the some very interesting technical documents on the TED series, originally provided by Tibor Biczo and published by William Levak and Marko Mäkelä. I sorted the pages and converted them into searchable PDFs that are much nicer to look at:</p>
<p><center><a href="docs/ted/TED System Hardware Manual.pdf"><img src="docs/pdf.png" width="32" height="32"><br />&#8220;TED System Hardware Manual&#8221</a><br />(PDF, 48 pages, 7.6 MB)</center></p>
<p><center><a href="docs/ted/TED 7360R0 Preliminary Data Sheet.pdf"><img src="docs/pdf.png" width="32" height="32"><br />&#8220;TED 7360R0 Preliminary Data Sheet&#8221 (Apr 1983)</a><br />(PDF, 23 pages, 5.8 MB)</center></p>
<p><center><a href="docs/ted/TED Extra Pages.pdf"><img src="docs/pdf.png" width="32" height="32"><br />&#8220;TED Extra Pages&#8221</a><br />(PDF, 5 pages, 1.4 MB)</center></p>
<p>The &#8220;Extra Pages&#8221; contain a map of the circuit board, a Plus/4 memory map in German, a TED register map, and a German version of section 4.5.2 of the TED System Hardware Manual.</p>
<p><center><a href="docs/ted/Service Manual Model Plus 4 Computer.pdf"><img src="docs/pdf.png" width="32" height="32"><br />&#8220;Service Manual Model Plus 4 Computer.pdf&#8221 (Oct 1984, PN-314001-04)</a><br />(PDF, 25 pages, 4.9 MB)</center></p>
<p>The service manual is also taken from <a href="http://www.zimmers.net/anonftp/pub/cbm/schematics/computers/plus4/manual/index.html">zimmers.net</a>.</p>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=541&amp;ts=1369319073" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=541</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>How to not get sued by Sony</title>
		<link>http://www.pagetable.com/?p=537</link>
		<comments>http://www.pagetable.com/?p=537#comments</comments>
		<pubDate>Tue, 18 Jan 2011 03:27:04 +0000</pubDate>
		<dc:creator>Michael Steil</dc:creator>
				<category><![CDATA[hacks]]></category>
		<category><![CDATA[security]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=537</guid>
		<description><![CDATA[Hint: White t-shirt: get sued. Black t-shirt: do not get sued. Oh, and Sony also fails, among other things, at the Spanish naming system. In case you haven&#8217;t watched the video yet, you should do so now: Console Hacking 2010. I have a short cameo, repeating my age-old point that systems should be open, otherwise [...]]]></description>
			<content:encoded><![CDATA[<p><a href="docs/fail0verflow/fail0verflow.jpg"><img src="docs/fail0verflow/fail0verflow.jpg" width="440"></a></p>
<p>Hint:</p>
<ul>
<li>White t-shirt: get sued.</li>
<li>Black t-shirt: do not get sued.</li>
</ul>
<p><a href="http://www.scribd.com/doc/46739945/Motion-for-TRO"><img src="docs/fail0verflow/tro.png" width="440" border="1"></a></p>
<p>Oh, and Sony also <a href="http://marcansoft.com/blog/contact-information/">fails</a>, among other things, at the <a href="http://en.wikipedia.org/wiki/Spanish_naming_customs">Spanish naming system</a>.</p>
<p>In case you haven&#8217;t watched the video yet, you should do so now: <a href="http://media.ccc.de/browse/congress/2010/27c3-4087-en-console_hacking_2010.html">Console Hacking 2010</a>. I have a short cameo, repeating my age-old point that <a href="http://www.pagetable.com/?p=376">systems should be open, otherwise hackers will open them.</a></p>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=537&amp;ts=1369319073" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=537</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Final Cartridge III Undocumented Functions</title>
		<link>http://www.pagetable.com/?p=534</link>
		<comments>http://www.pagetable.com/?p=534#comments</comments>
		<pubDate>Fri, 14 Jan 2011 16:56:16 +0000</pubDate>
		<dc:creator>Michael Steil</dc:creator>
				<category><![CDATA[6502]]></category>
		<category><![CDATA[archeology]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=534</guid>
		<description><![CDATA[The &#8220;Final Cartridge III&#8221; has been among the most popular Commodore 64 extensions, providing a floppy speeder, BASIC extensions, a machine language monior, a freezer and even a (rarely used) graphical desktop. The major advantage compared to other C64 cartridges is the consistent way in which the Final Cartridge III extends the C64 experience. As [...]]]></description>
			<content:encoded><![CDATA[<p>The &#8220;<a href="http://ar.c64.org/wiki/Final_Cartridge">Final Cartridge III</a>&#8221; has been among the most popular Commodore 64 extensions, providing a floppy speeder, BASIC extensions, a machine language monior, a freezer and even a (rarely used) graphical desktop. The major advantage compared to other C64 cartridges is the consistent way in which the Final Cartridge III extends the C64 experience.</p>
<p>As it turns out, there are several undocumented instructions implemented in the Final Cartridge III.</p>
<h3>Filtered Directory</h3>
<pre>DOS"$&lt;filter&gt;"</pre>
<p>The DOS&#8221;$&#8221; command passes all characters following the &#8220;$&#8221; to the disk drive, allowing the user to specify filters, like this:</p>
<pre>DOS"$A*" :REM SHOW ALL FILES THAT START WITH "A"</pre>
<p>This feature is not available for the &#8220;@&#8221; command in the monitor.</p>
<h3>Fast Format</h3>
<pre>DOS"F:NAME,ID"</pre>
<p>The 26 second fast format known from the &#8220;DESKTOP&#8221; GUI is also available from the command line. Note that this also works with the &#8220;@&#8221; command in the monitor. If the ID is omitted, this only overwrites BAM and directory, just like the &#8220;N&#8221; command.<br />
<h3>Disk Rename</h3>
<pre>DOS"D:NAME,ID</pre>
<p>This commands renames the disk without erasing it. The ID can be up to 5 characters, so the default &#8220;2A&#8221; can be overwritten.</p>
<h3>FC III ROM Banking</h3>
<pre>B&lt;0..3&gt;
B</pre>
<p>B, followed by a digit between 0 to 3, in the monitor enables the view of the ROMs of the Final Cartridge III. The specified ROM bank will be visible between $8000 and $BFFF. B without a parameter switches the ROM back off.</p>
<p>The following commands in the machine language monitor can be used to dump the complete ROM of an FC3 to disk:</p>
<pre>
B 0
T 8000 BFFF 8000
S "B0",08,8000,C000
B 1
T 8000 BFFF 8000
S "B1",08,8000,C000
B 2
T 8000 BFFF 8000
S "B2",08,8000,C000
B 3
T 8000 BFFF 8000
S "B3",08,8000,C000
</pre>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=534&amp;ts=1369319073" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=534</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Reverse Engineering the MOS 6502 CPU [video]</title>
		<link>http://www.pagetable.com/?p=517</link>
		<comments>http://www.pagetable.com/?p=517#comments</comments>
		<pubDate>Tue, 04 Jan 2011 17:57:12 +0000</pubDate>
		<dc:creator>Michael Steil</dc:creator>
				<category><![CDATA[6502]]></category>
		<category><![CDATA[archeology]]></category>
		<category><![CDATA[hacks]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=517</guid>
		<description><![CDATA[Here is the video recording of my presentation &#8220;Reverse Engineering the MOS 6502 CPU&#8221; given at 27C3, on the low cost CPU that arguably launched the home computer revolution. A high-quality MP4/H.264 video file of the presentation can be downloaded here. P.S.: If you enjoyed this, you might also like my &#8220;Ultimate Commodore 64 Talk&#8221;]]></description>
			<content:encoded><![CDATA[<p>Here is the video recording of my presentation &#8220;<a href="http://events.ccc.de/congress/2010/Fahrplan/events/4159.en.html">Reverse Engineering the MOS 6502 CPU</a>&#8221; given at <a href="http://events.ccc.de/congress/2010">27C3</a>, on the low cost CPU that arguably launched the home computer revolution.</p>
<p><object width="480" height="385"><param name="movie" value="http://www.youtube.com/v/HW9AWBFH1sA?fs=1&amp;hl=en_US"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/HW9AWBFH1sA?fs=1&amp;hl=en_US" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"></embed></object></p>
<p><object width="480" height="385"><param name="movie" value="http://www.youtube.com/v/bBE4KHKzhKc?fs=1&amp;hl=en_US"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/bBE4KHKzhKc?fs=1&amp;hl=en_US" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"></embed></object></p>
<p><object width="480" height="385"><param name="movie" value="http://www.youtube.com/v/tRBo7O_blVo?fs=1&amp;hl=en_US"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/tRBo7O_blVo?fs=1&amp;hl=en_US" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"></embed></object></p>
<p><object width="480" height="385"><param name="movie" value="http://www.youtube.com/v/H_15RtVbqGU?fs=1&amp;hl=en_US"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/H_15RtVbqGU?fs=1&amp;hl=en_US" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"></embed></object></p>
<p><object width="480" height="385"><param name="movie" value="http://www.youtube.com/v/N9DYmlprCKA?fs=1&amp;hl=en_US"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/N9DYmlprCKA?fs=1&amp;hl=en_US" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"></embed></object></p>
<p><object width="480" height="385"><param name="movie" value="http://www.youtube.com/v/eZOUuqc4pk8?fs=1&amp;hl=en_US"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/eZOUuqc4pk8?fs=1&amp;hl=en_US" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"></embed></object></p>
<p>A high-quality MP4/H.264 video file of the presentation can be downloaded <a href="http://media.ccc.de/browse/congress/2010/27c3-4159-en-reverse_engineering_mos_6502.html">here</a>.</p>
<p>P.S.: If you enjoyed this, you might also like my <a href="http://www.pagetable.com/?p=54">&#8220;Ultimate Commodore 64 Talk&#8221;</a></p>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=517&amp;ts=1369319073" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=517</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>Reverse Engineering the MOS 6502 CPU  [announcement]</title>
		<link>http://www.pagetable.com/?p=512</link>
		<comments>http://www.pagetable.com/?p=512#comments</comments>
		<pubDate>Sun, 26 Dec 2010 18:58:02 +0000</pubDate>
		<dc:creator>Michael Steil</dc:creator>
				<category><![CDATA[6502]]></category>
		<category><![CDATA[archeology]]></category>
		<category><![CDATA[hacks]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=512</guid>
		<description><![CDATA[3510 transistors in 60 minutes Update: The video recording is now available.]]></description>
			<content:encoded><![CDATA[<p><i>3510 transistors in 60 minutes</i></p>
<p><a href="http://events.ccc.de/congress/2010/Fahrplan/events/4159.en.html"><img src="docs/Reverse_Engineering_the_MOS_6502_CPU.png"></a></p>
<p><b><i>Update</i></b>: The <a href="http://www.pagetable.com/?p=517">video recording</a> is now available.</p>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=512&amp;ts=1369319073" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=512</wfw:commentRss>
		<slash:comments>26</slash:comments>
		</item>
		<item>
		<title>Comparing BitTorrent Downloads of Interlaced TV Shows</title>
		<link>http://www.pagetable.com/?p=499</link>
		<comments>http://www.pagetable.com/?p=499#comments</comments>
		<pubDate>Fri, 03 Dec 2010 06:40:58 +0000</pubDate>
		<dc:creator>Michael Steil</dc:creator>
				<category><![CDATA[digital video]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=499</guid>
		<description><![CDATA[In my previous blog post, I was comparing how internet video providers like Hulu, Netflix, iTunes, Amazon and Zune handle interlaced material by comparing an episode of Futurama. This time, let&#8217;s see how rips from the BitTorrent network compare to these. I managed to acquire nine different files (I own several licenses for this episode, [...]]]></description>
			<content:encoded><![CDATA[<p>In my previous blog post, I was comparing how internet video providers like <a href="http://www.pagetable.com/?p=484">Hulu, Netflix, iTunes, Amazon and Zune handle interlaced material</a> by comparing an episode of Futurama. This time, let&#8217;s see how rips from the BitTorrent network compare to these.</p>
<p>I managed to acquire nine different files (I own several licenses for this episode, and I downloaded without uploading). Some of these have non-english audio tracks and some have hard subtitles, but let&#8217;s concentrate on the quality of the deinterlacing. The following list is already sorted by overall quality, first by interlacing quality, then by resolution, then by data rate:</p>
<table border="1">
<tr>
<td align="center">#</td>
<td>Filename</td>
<td align="center">Mbit/sec</td>
<td align="center">Encoder</td>
<td align="center">Cropping</td>
<td align="center">Resolution</td>
<td align="center">fps</td>
<td align="center">Deinterlacing</td>
</tr>
<tr>
<td align="center">1</td>
<td>Futurama &#8211; 09 &#8211; Hell Is Other Robots.avi (184287232 bytes)</td>
<td align="center">1.1</td>
<td align="center">MPEG-4</td>
<td align="center">yes</td>
<td align="center">384&#215;288</td>
<td align="center">25</td>
<td align="center">lots of blending</td>
</tr>
<tr>
<td align="center">2</td>
<td>Futurama &#8211; S01E09 &#8211; Hell Is Other Robots.avi (175728640 bytes)</td>
<td align="center">1.1</td>
<td align="center">MSMPEG4</td>
<td align="center">yes</td>
<td align="center">576&#215;432</td>
<td align="center">24.03</td>
<td align="center">lots of blending</td>
</tr>
<tr>
<td align="center">3</td>
<td>Futurama &#8211; 1&#215;09 &#8211; El infierno est&aacute; en los dem&aacute;s robots.avi (181534720 bytes)</td>
<td align="center">1.1</td>
<td align="center">MPEG-4</td>
<td align="center">yes</td>
<td align="center">640&#215;480</td>
<td align="center">25</td>
<td align="center">lots of blending</td>
</tr>
<tr>
<td align="center">4</td>
<td>Futurama 1.09 &#8211; el infierno robot &#8211; xvid -espa&ntilde;ol latino.avi (183535616 bytes)</td>
<td align="center">1.1</td>
<td align="center">MPEG-4</td>
<td align="center">yes</td>
<td align="center">640&#215;480</td>
<td align="center">23.98</td>
<td align="center">detelecine, blend</td>
</tr>
<tr>
<td align="center">5</td>
<td>Futurama &#8211; 1&#215;09 &#8211; Hell Is Other Robots.mp4 (83770003 bytes)</td>
<td align="center">0.5</td>
<td align="center">MPEG-4</td>
<td align="center">yes</td>
<td align="center">320&#215;480</td>
<td align="center">29.97</td>
<td align="center">detelecine with 30fps dups</td>
</tr>
<tr>
<td align="center">6</td>
<td>Futurama &#8211; S01E09 &#8211; Hell Is Other Robots.m4v (77853226 bytes)</td>
<td align="center">0.5</td>
<td align="center">H.264</td>
<td align="center">yes</td>
<td align="center">480&#215;368</td>
<td align="center">24.97</td>
<td align="center">detelecine</td>
</tr>
<tr>
<td align="center">7</td>
<td>Futurama.S01E09. SWESUB.DVDRip.XviD-Enectrixx.avi (183445504 bytes)</td>
<td align="center">1.1</td>
<td align="center">MPEG-4</td>
<td align="center">no</td>
<td align="center">544&#215;384</td>
<td align="center">25</td>
<td align="center">detelecine</td>
</tr>
<tr>
<td align="center">8</td>
<td>S01E09 &#8211; Hell Is Other Robots.avi (183490560 bytes)</td>
<td align="center">1.1</td>
<td align="center">MPEG-4</td>
<td align="center">yes</td>
<td align="center">640&#215;480</td>
<td align="center">25</td>
<td align="center">detelecine</td>
</tr>
<tr>
<td align="center">9</td>
<td>Futurama &#8211; S01E09 &#8211; Hell Is Other Robots [dd].avi (183492608 bytes)</td>
<td align="center">1.1</td>
<td align="center">MPEG-4</td>
<td align="center">yes</td>
<td align="center">640&#215;480</td>
<td align="center">25</td>
<td align="center">detelecine</td>
</tr>
</table>
<p>Files #1, #2 and #3 show heavy blending that goes beyond just blending the two interlaced frames per five frames. It is likely these files were encoded form a PAL source that was improperly converted from NTSC.</p>
<p>File #4 is detelecined (24 fps), but whenever the telecine pattern was not consistently PPPII (&#8220;Robot Hell&#8221; pan, end credits), the algorithm reverted to blending the two fields. It is likely this source was encoded from the NTSC DVD.</p>
<p>Files #6, #7, #8 and #9 all seem to be encoded from the same PAL source that was already deinterlaced properly, i.e. a detelecine was done to recover the 24 fps video, and then it was sped up by ~4% to get a 25 fps video. The detelecine is almost perfect: In the end credits, the algorithm properly reconstructed all frames without ever having to blend, but the &#8220;Robot Hell&#8221; pan is missing the six frames that that only existed as one field.</p>
<p>File #5 is interesting: It is 30 fps, so it has a duplicate frame after every fifth frame, but other than that, it was converted by the same high-quality detelecine as #6 through #9. Since I suspect that the #6-#9 detelecine was done professionally for the PAL DVD, it is weird to see the practically the same result (6 missing frames in &#8220;Robot Hell&#8221;, but perfect end credits etc.) with the NTSC frame rate here. It almost looks like someone took a PAL DVD (or one of the files #6-#9) and duplicated frames to get an NTSC-compatible signal.</p>
<h2>Bittorent Summary</h2>
<p>A rule of thumb is that an encoding found on BitTorrent is as good as its source. For those that had a blended source (#1-#3), nothing could fix it. For those that had an excellent progressive source (#6-#9), there was little to be done wrong. The one that had the original interlaced US master as a source did an okay job of deinterlacing.</p>
<p>Also: The PAL DVDs seem to be very high quality.</p>
<h2>Comparison to properly licensed sources</h2>
<p>Now how do these scene rips compare to legit internet video providers? Well, as <a href="http://www.pagetable.com/?p=484">my previous article</a> stated, the files on Hulu, Netflix and iTunes have the deinterlacing done wrong, leading to visible and unnecessary degradations of the vertical resolution in some (Netflix, iTunes) or all (Hulu) of the video &#8211; but this is arguably still better than the blending of BitTorrent files #1-3. Amazon Video on Demand did an okay detelecine job, although inferior to BitTorrent file #4: On complicated scenes, Amazon halved the resolution, while file #4 did blending. The Microsoft Zune store did a perfect detelecine, which is even better than the one in BitTorrent files #4-9, since it did not miss the 6 frames in the &#8220;Robot Hell&#8221; pan, but otherwise performs as well as the PAL DVD.</p>
<p>So here are the final rankings of the different sources/files/enodings for the episode &#8220;Hell Is Other Robots&#8221; of Futurama:</p>
<p>
0. <i>NTSC DVD</i>: original broadcast master, 720&#215;480, interlaced, but with the full potential to be perfectly deinterlaced! ;-)</br><br />
1. <b>Microsoft Zune</b>: perfect detelecine<br />
2. <i>PAL DVD</i>: almost perfect detelecine<br />
3. BitTorrent files #6-#9: almost perfect detelecine, like PAL DVD<br />
4. BitTorrent file #4: okay detelecine<br />
5. <b>Amazon Video on Demand</b>: okay detelecine, judder<br />
6. <b>iTunes, Netflix</b>: buggy deinterlacing, judder<br />
7. BitTorrent files #1-3: horrible blending<br />
8. <b>Hulu</b>: Consistenly halved vertical resolution
</p>
<p>So unless you want to do the deinterlacing yourself, the Zune version is the best choice. Which is, unless you actually want to play the video on the devices you care about, in which case you should get the effectively not copy-protected PAL DVDs.</p>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=499&amp;ts=1369319073" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=499</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Comparing Digital Video Downloads of Interlaced TV Shows</title>
		<link>http://www.pagetable.com/?p=484</link>
		<comments>http://www.pagetable.com/?p=484#comments</comments>
		<pubDate>Tue, 30 Nov 2010 05:00:40 +0000</pubDate>
		<dc:creator>Michael Steil</dc:creator>
				<category><![CDATA[digital video]]></category>
		<category><![CDATA[whines]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=484</guid>
		<description><![CDATA[In the days of CRT monitors, TV shows used to be broadcast in interlaced mode, which is unsupported by modern flat-panel displays. All online streaming services and video stores provide progressive video, so they must deinterlace the data first. This article compares the deinterlacing strategies of Apple iTunes, Netflix, Microsoft Zune, Amazon VoD and Hulu [...]]]></description>
			<content:encoded><![CDATA[<p>In the days of CRT monitors, TV shows used to be broadcast in interlaced mode, which is unsupported by modern flat-panel displays. All online streaming services and video stores provide progressive video, so they must deinterlace the data first. This article compares the deinterlacing strategies of Apple iTunes, Netflix, Microsoft Zune, Amazon VoD and Hulu by comparing their respective encodings of a Futurama episode.</p>
<p>If you have dealt with video formats before, you probably know about <a href="http://en.wikipedia.org/wiki/Interlaced_video">interlacing</a>, a 1930s trick to achieve both high spatial and temporal resolution at half the (analog) data rate: In NTSC countries, there are 60 fields per second (PAL: 50), and every field is half the vertical resolution of a full frame. When film footage at 24 frames per second has to be played at 30 fps (NTSC), every frame has to be shown 1.25 times &#8211; in other words, every fourth frame has to be shown twice. This introduces jerky motion (judder), but it can be improved by using the 60 Hz temporal resolution: Frame A gets shown for 2 fields, frame B for 3 fields, frame C for 2 fields, and so on. This way, every source frame gets shown for 2.5 fields, i.e. 1.25 frames &#8211; this method is called a <a href="http://en.wikipedia.org/wiki/Telecine">telecine 2:3 pulldown</a>.</p>
<p>A lot of TV material is produced at 24 fps and telecined, for several reasons: Standard movie cameras can be used instead of TV cameras, 24 fps can be converted to 25 fps PAL more easily than 30 fps NTSC, and  for cartoons, this means that only 24 (or 12) frames have to be drawn for every second.</p>
<p>Unfortunately, interlacing only works with ancient CRT TVs &#8211; modern LCD screens can only show progressive video. And while DVDs are specified to encode interlaced video, more modern formats like MPEG-4/H.264 and VC-1 usually carry progressive data. So when playing DVDs, the DVD player or the TV have to deal with the interlacing problem, and in case of modern file formats, it&#8217;s the job of the converter/encoder.</p>
<p>The naive way of converting an interlaced source to progressive is to combine every two fields into a frame. This works great if the original source material was 30 fps progressive (which is rare for NTSC but common for PAL), but for telecined video, since two out of every six frames are combined from two different fields, this leads to ugly <a href="http://www.100fps.com/">combing</a> effects.</p>
<p>If the source material was 24 fps, an inverse telecine can be done, recovering the original 24 frames per second. Unfortunately, it is not always this easy, since interlaced video may switch between methods, and sometimes use different methods at the same time, e.g. overlaying 30 fps interlaced captions on top of a 24 fps telecined picture, or compositing two telecined streams with a different phase. &#8220;<a href="http://memory-alpha.org/wiki/Star_Trek:_The_Next_Generation">Star Trek: The Next Generation</a>&#8221; is a famous offender in this category &#8211; just single-step through the title&#8230;</p>
<p>In the following paragraphs, let us look at <a href="http://theinfosphere.org/Hell_Is_Other_Robots">an episode of Futurama</a> and how the deinterlacing was done by the different providers of the show. Futurama was produced in 24 fps and telecined. Some of the editing seems to have been done on the resulting interlaced video, so the telecine pattern is not 100% consistent.</p>
<h2>NTSC DVD</h2>
<p>The NTSC DVD is basically just an MPEG-2-compressed version of the US <a href="http://en.wikipedia.org/wiki/CCIR_601">CCIR 601</a> broadcast master. It encodes 720&#215;480 anamorphic pixels (which can be displayed as 640&#215;480 or 720&#215;540) and has all the original interlacing intact. This is a frame at 640&#215;480 and properly inverse telecined:</p>
<p><a href="docs/futurama_interlacing/dvd480.png"><img src="docs/futurama_interlacing/dvd480.png" alt="DVD"></a></p>
<h2>Hulu</h2>
<p><a href="docs/futurama_interlacing/hulu480.png"><img src="docs/futurama_interlacing/hulu480.png" alt="Hulu"></a></p>
<p>Hulu (480p version) took the original image without doing any cropping on the sides. You can clearly see this picture is only half the vertical resolution, meaning one of the fields got discarded. It seems this was Hulu&#8217;s deinterlacing strategy, since throughout the complete video, everything is half the vertical resolution, whether there is motion or not. This also keeps the video at 30 fps, and effectively shows every fourth frame twice, introducing stronger judder.</p>
<h2>iTunes</h2>
<p><a href="docs/futurama_interlacing/itunes480.png"><img src="docs/futurama_interlacing/itunes480.png" alt="iTunes"></a></p>
<p>iTunes crops the picture to get rid of the black pixels in the overscan area and scales it to 640&#215;480. They run a full-blown 60 Hz deinterlace filter on the video. Such a filter is meant to take a live television signal as an input, with a temporal resolution of 60 Hz. While this looks fine on frames with no or little motion, vertical resolution is halved as soon as there is motion. Basically, it is the wrong filter. Like Hulu, iTunes preserves the 30 fps, introducing a stronger judder. (The video encoding is H.264 at 1500 kbit/sec.)</p>
<h2>Netflix</h2>
<p><a href="docs/futurama_interlacing/netflix480.png"><img src="docs/futurama_interlacing/netflix480.png" alt="Netflix"></a></p>
<p>Netflix seems to do the same as iTunes &#8211; maybe they even got the data from iTunes? The image is cropped and scaled to 640&#215;480, they run a deinterlace-filter and retain the 30 fps, leading to halved resolution when there is motion, and stronger judder.</p>
<h2>Amazon Video on Demand</h2>
<p><a href="docs/futurama_interlacing/unbox480.png"><img src="docs/futurama_interlacing/unbox480.png" alt="Amazon Video on Demand"></a></p>
<p>Amazon Video on Demand with its horribly inconvenient Unbox Player (Windows only, requires 1 GB of extra downloads and two reboots) did a better job. Like Netflix and iTunes, they cropped the picture and scaled it to 640&#215;480, but they actually did a real inverse telecine. In some segments (like the end credits), the algorithm failed because of inconsistencies of the original telecine, so it reverted to half the vertical resolution. And like the others, Amazon also encodes at 30 fps, i.e. judder. (The video encoding is VC-1 at 2600 kbit/sec.)</p>
<h2>Zune</h2>
<p><a href="docs/futurama_interlacing/zune480.png"><img src="docs/futurama_interlacing/zune480.png" alt="Zune"></a></p>
<p>Microsoft&#8217;s Zune Store provides a cropped video at 640&#215;480 at the original 24 fps and with a bitrate of 1500 kbit/sec (VC-1). Looking through it frame by frame reveals that they used a brilliant detelecine/deinterlace algorithm. On the DVD, the panning at the beginning of the &#8220;Robot Hell&#8221; song is very tricky: It breaks the standard telecine pattern (PPPIIPPPII becomes PPPIPPPI), it seems every fifth frame was removed.</p>
<p>
<img src="docs/futurama_interlacing/robothell_16.png"><img src="docs/futurama_interlacing/robothell_15.png"><img src="docs/futurama_interlacing/robothell_14.png"><img src="docs/futurama_interlacing/robothell_13.png"><br />
<img src="docs/futurama_interlacing/robothell_12.png"><img src="docs/futurama_interlacing/robothell_11.png"><img src="docs/futurama_interlacing/robothell_10.png"><img src="docs/futurama_interlacing/robothell_9.png"><br />
<img src="docs/futurama_interlacing/robothell_8.png"><img src="docs/futurama_interlacing/robothell_7.png"><img src="docs/futurama_interlacing/robothell_6.png"><img src="docs/futurama_interlacing/robothell_5.png"><br />
<img src="docs/futurama_interlacing/robothell_4.png"><img src="docs/futurama_interlacing/robothell_3.png"><img src="docs/futurama_interlacing/robothell_2.png"><img src="docs/futurama_interlacing/robothell_1.png">
</p>
<p>The pan consists of a pattern of three progressive frames, and then one interlaced frame, which is composed of the previous frame and the current frame. Consequently, every fourth frame has half its resolution wasted by the repeated lines of the previous frame, i.e. every fourth frame only exists at half resolution in the DVD master material.</p>
<p>Hulu discards half the vertical resolution for every frame anyway, and the deinterlacing algorithms of iTunes and Netflix discard half the resolution whenever there is motion. The Amazon algorithm does a good job when the telecine pattern is correct, but in this case, it gets confused and encodes all frames of the pan in half resolution. The Zune algorithm does a brilliant job here: The progressive frames stay at full resolution, and it extracts the half-resolution picture out of every fourth frame:</p>
<p>
<img src="docs/futurama_interlacing/robothell_zune_16.png"><img src="docs/futurama_interlacing/robothell_zune_15.png"><img src="docs/futurama_interlacing/robothell_zune_14.png"><img src="docs/futurama_interlacing/robothell_zune_13.png"><br />
<img src="docs/futurama_interlacing/robothell_zune_12.png"><img src="docs/futurama_interlacing/robothell_zune_11.png"><img src="docs/futurama_interlacing/robothell_zune_10.png"><img src="docs/futurama_interlacing/robothell_zune_9.png"><br />
<img src="docs/futurama_interlacing/robothell_zune_8.png"><img src="docs/futurama_interlacing/robothell_zune_7.png"><img src="docs/futurama_interlacing/robothell_zune_6.png"><img src="docs/futurama_interlacing/robothell_zune_5.png"><br />
<img src="docs/futurama_interlacing/robothell_zune_4.png"><img src="docs/futurama_interlacing/robothell_zune_3.png"><img src="docs/futurama_interlacing/robothell_zune_2.png"><img src="docs/futurama_interlacing/robothell_zune_1.png">
</p>
<p>This is the fourth picture at full size &#8211; you can see half the vertical resolution is missing (it was never there in the first place!), but the algorithm did a very good interpolation job:</p>
<p><a href="docs/futurama_interlacing/robothell_zune_big.png"><img src="docs/futurama_interlacing/robothell_zune_big.png" alt="Robot Hell (Zune)"></a></p>
<p>The Zune video is almost perfect. It recombines all fields correctly and recovers all single fields, scaling them up so that it&#8217;s hardly visible there is information missing. If you ignore the 720 vs. 640 horizontal pixels, the resulting 24 fps video contains all information of the DVD version, but with all interlacing removed, and with zero judder. Too bad it&#8217;s not <a href="http://www.pagetable.com/?p=327">H.264</a>, but <a href="http://xkcd.com/488/">DRMed</a> and only plays on Windows (XP+), Zune and <a href="http://www.pagetable.com/?p=476">Windows Phone 7</a>.</p>
<h2>Summary</h2>
<table border="1">
<tr>
<td align="center"><b>Provider</b></td>
<td align="center"><b>Cropping</b></td>
<td align="center"><b>Resolution</b></td>
<td align="center"><b>Deinterlacing</b></td>
<td align="center"><b>fps</b></td>
<td align="center"><b>Encoder</b></td>
<td align="center"><b>Bitrate (kbits/sec)</b></td>
</tr>
<tr>
<td>NTSC DVD</td>
<td align="center">no</td>
<td align="center">720&#215;480</td>
<td align="center">none</td>
<td align="center">30</td>
<td align="center">MPEG-2</td>
<td align="center">6500</td>
</tr>
<tr>
<td>Hulu</td>
<td align="center">no</td>
<td align="center">640&#215;480</td>
<td align="center">discard</td>
<td align="center">30</td>
<td align="center">H.264?</td>
<td align="center">?</td>
</tr>
<tr>
<td>iTunes</td>
<td align="center">yes</td>
<td align="center">640&#215;480</td>
<td align="center">30 Hz deinterlace</td>
<td align="center">30</td>
<td align="center">H.264</td>
<td align="center">1500</td>
</tr>
<tr>
<td>Netflix</td>
<td align="center">yes</td>
<td align="center">640&#215;480</td>
<td align="center">30 Hz deinterlace</td>
<td align="center">30</td>
<td align="center">H.264/VC-1</td>
<td align="center">?</td>
</tr>
<tr>
<td>Amazon VoD</td>
<td align="center">yes</td>
<td align="center">640&#215;480</td>
<td align="center">detelecine+decomb</td>
<td align="center">30</td>
<td align="center">VC-1</td>
<td align="center">2600</td>
</tr>
<tr>
<td>Zune</td>
<td align="center">yes</td>
<td align="center">640&#215;480</td>
<td align="center">fuzzy detelecine</td>
<td align="center">24</td>
<td align="center">VC-1</td>
<td align="center">1500</td>
</tr>
</table>
<p>Note: H.264 and VC-1 compress significantly better than MPEG-2; a rule of thumb is to divide the MPEG-2 bitrate by 2.3 to get a comparable H.264/VC-1 bitrate. So the Amazon bitrate is fine and the video is about the same quality (sharp picture, no compression artefacts) as the DVD, but the iTunes and Zune versions are not (artifacts can be seen on single frames).</p>
<p>It is scary how little effort seems to be going into video conversion/encoding at major players like iTunes, Netflix and Hulu. Amazon did a kind of okay job converting the source material properly, and only Microsoft did an excellent job. The NTSC DVDs still give you the maximum quality &#8211; but of course, if you watch them on an LCD, the burden of deinterlacing is on your side. <a href="http://handbrake.fr/">Handbrake</a> with &#8220;detelecine&#8221; (for the bulk of it) and &#8220;decomb&#8221; (for exceptions) turned on, and with a target framerate of &#8220;same as source&#8221; will generate a rather good MP4 video similar to Amazon&#8217;s, but without the judder.</p>
<p><i>Are there any stores I missed? Can someone check the PAL DVD as well as digital PAL and NTSC broadcasts? What is the magical detelecine/deinterlace program Microsoft uses?</i></p>
<p><b>See also: <a href="http://www.pagetable.com/?p=499">Comparing Bittorrent Files of Interlaced TV Shows</a></b></p>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=484&amp;ts=1369319073" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=484</wfw:commentRss>
		<slash:comments>34</slash:comments>
		</item>
		<item>
		<title>Xbox Serial Number Statistics</title>
		<link>http://www.pagetable.com/?p=465</link>
		<comments>http://www.pagetable.com/?p=465#comments</comments>
		<pubDate>Tue, 23 Nov 2010 09:00:33 +0000</pubDate>
		<dc:creator>Michael Steil</dc:creator>
				<category><![CDATA[hacks]]></category>
		<category><![CDATA[puzzle]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=465</guid>
		<description><![CDATA[Slashdot had a story recently on how in 1942, the allies were able to estimate the number of German taks produced based on the serial numbers of the tanks. In 2010, a German hacker is doing the exact same thing with Xboxes. This article describes the generic approach, shows some results, and provides previously unreleased [...]]]></description>
			<content:encoded><![CDATA[<p>Slashdot had a story recently on how in 1942, the allies were able to <a href="http://www.wired.com/autopia/2010/10/how-the-allies-used-math-against-german-tanks/">estimate the number of German taks produced based on the serial numbers of the tanks</a>. In 2010, a German hacker is doing the exact same thing with Xboxes. This article describes the generic approach, shows some results, and provides previously unreleased raw data of 14,000 Xbox serials so you can do your own statistics!</p>
<p>Between October 2003 and January 2005, the <a href="http://www.xbox-linux.org/">Xbox Linux Project</a> asked all visitors to their website to enter their Xbox serial numbers, date and country of manufacture, ROM version, hard disk and DVD drive brand and other properties, and gathered more than 14,000 entries. The original idea was to find a rule to deduce the hard disk and DVD drive types in an Xbox by only looking at the serial number, which was visible through the unopened packaging.</p>
<p>The serial sticker on an Xbox looks like this:</p>
<pre>
MFG. DATE  2002-03-03
SERIAL NO. 1166356 20903
</pre>
<p>After looking at several serial numbers, it was already clear that the last two digits (&#8220;03&#8243; in my example) are the location of manufacture: 02 is Mexico, 03 is Hungary, 05 is China and 06 is Taiwan. The three digits before (&#8220;209&#8243; in my example) are the one-digit year (&#8220;2&#8243; for &#8220;2002&#8243;) and the two-digit calender week (&#8220;09&#8243; for around the first week of March).</p>
<p>Now we want to find out how many devices were manufactured. A first approximation is to look at the manufacturing dates of all Xboxes in our database.</p>
<p><img src="http://www.pagetable.com/docs/xbox_serials/chart1.png"></p>
<p>This gives us an idea when production was ramped up (in 2001 and 2002 in November, and in 2003 in August, September and October), but the statistics don&#8217;t give us absolute numbers, and they are biased towards older devices (newer devices are not entered yet, and visitors of our site tend to be early adopters).</p>
<p>But what about these first seven digits of the serial number? Shouldn&#8217;t these be actual &#8220;serial&#8221; numbers? Let&#8217;s look at all devices from August 2003 and sort the first seven digits by manufacturing date:</p>
<p><img src="http://www.pagetable.com/docs/xbox_serials/chart2.png"></p>
<p>This does not look like a serial number. But all numbers are > 1,000,000, which implies that the first digit has a special meaning and is not part of the number. Let&#8217;s look at distribution of the first digit:</p>
<p><img src="http://www.pagetable.com/docs/xbox_serials/chart3.png"></p>
<p>The first digit seems to be the number of the assembly line in the factory! So let&#8217;s look at the remaining 6 digits again:</p>
<p><img src="http://www.pagetable.com/docs/xbox_serials/chart4.png"></p>
<p>This looks a lot better! But there are several things interleaved in this chart &#8211; because the serial numbers are of course counted independently in every factory. If we filter just all numbers form the Chinese factory, we get this:</p>
<p><img src="http://www.pagetable.com/docs/xbox_serials/chart5.png"></p>
<p>We can see serial numbers are counted up every week, but we still see all assembly lines interleaved here, and the different lines don&#8217;t reset at the same time. Here is line 6 all by itself:</p>
<p><img src="http://www.pagetable.com/docs/xbox_serials/chart6.png"></p>
<p>Looks almost perfect, if we assume the wild shots are caused by typos. Here is a manually fixed version of it:</p>
<p><img src="http://www.pagetable.com/docs/xbox_serials/chart7.png"></p>
<p>Voil&agrave;! Serial numbers that count up monotonically and get reset on every Sunday.</p>
<p>By inspection of the graph, we can estimate that assembly line 6 of the factory in China produced about 275,000 devices per week in week 33 (mid August) of 2003. This works well, because we have so many samples; but for other weeks, we have as few as five. This is the formula for the <a href="http://en.wikipedia.org/wiki/German_tank_problem">German Tank Problem</a>:</p>
<p><img src="http://www.pagetable.com/docs/xbox_serials/formula.png"></p>
<p><i>k</i> is the sample size and <i>m</i> s the highest serial number observed.</p>
<p>The estimate of Xboxes produced by assembly line 6 in China in week 33 of 2003 is therefore 285,269. Applying this to every assembly line of every factory and every week, it should be easy to get great statistics on the productivity of the different lines and factories, as well as a very good estimate of the total number of devices produced. &#8230;and this is where <i>you</i> come in!</p>
<h2>The Data</h2>
<p>You want to do your own statistics? Here is the raw data:</p>
<p><a href="http://www.pagetable.com/docs/xbox_serials/xbox_serials.csv">xbox_serials.csv</a> (2.5 MB)</p>
<p>It is a comma-separated-value file with the following columns:</p>
<table border="1">
<tr>
<td><b>Column</b></td>
<td><b>Example</b></td>
<td><b>Description</b></td>
<td><b>Comment</b></td>
</tr>
<tr>
<td>1</td>
<td>2002-03-03</td>
<td>Manufacture Date</td>
<td>YYYY-MM-DD</td>
</tr>
<tr>
<td>2</td>
<td>2002-04-30</td>
<td>Date of Purchace</td>
<td>YYYY-MM-DD</td>
</tr>
<tr>
<td>3</td>
<td>de</td>
<td>Country of Purchase</td>
<td>two-digit code</td>
</tr>
<tr>
<td>4</td>
<td>1166356&nbsp;20903</td>
<td>Serial Number</td>
<td>nnnnnnn nnnnn</td>
</tr>
<tr>
<td>5</td>
<td>v1.0</td>
<td>Xbox Version</td>
<td>motherboard revision</td>
</tr>
<tr>
<td>6</td>
<td>3944</td>
<td>Kernel Version</td>
<td>ROM version as shown in &#8220;About&#8221; dialog</td>
</tr>
<tr>
<td>7</td>
<td>4034</td>
<td>Dashboard Version</td>
<td>HD software version as shown in &#8220;About&#8221; dialog</td>
</tr>
<tr>
<td>8</td>
<td>Unknown/Other</td>
<td>Flash</td>
<td>what&#8217;s printed on flash ROM chip</td>
</tr>
<tr>
<td>9</td>
<td>PAL</td>
<td>Video Standard</td>
<td>PAL or NTSC</td>
</tr>
<tr>
<td>10</td>
<td>Black</td>
<td>Case Color</td>
<td>Xboxes are black, but there are some special editions</td>
</tr>
<tr>
<td>11</td>
<td>Thomson</td>
<td>DVD Drive</td>
<td>Philips, Samsung, Thomson</td>
</tr>
<tr>
<td>12</td>
<td>Seagate 10 GB</td>
<td>Hard Disk</td>
<td>Seagate or Western Digital</td>
</tr>
<tr>
<td>13</td>
<td>Conexant</td>
<td>Video&nbsp;Encoder&nbsp;Brand</td>
<td>Conexant, Focus, Xcalibur</td>
</tr>
<tr>
<td>14</td>
<td>Golden Xbox</td>
<td>comments</td>
<td>free-form field</td>
</tr>
</table>
<p>Please note that people were able to fill some fields with arbitraty data, so they might not necessarily be in exactly the specified form. There are also lots of typos in the serial numbers and the month and day fields in the data fields have been mixed up sometimes. You probably want to run a script over the data first that sanitizes some of the input, e.g. removes dashes and spaces from serial numbers etc.</p>
<p>Here are some ideas on what you might want to find out:</p>
<ol>
<li>Is there a better formula to estimate the number of Xboxes produced per week on a certain assembly line?</li>
<li>What day does a week start with? Does the factory produce Xboxes on Sundays? Do they produce just as many? Is it different in the respective countries?</li>
<li>How many Xboxes were produced per assembly line, per week and per factory?</li>
<li>Are all assembly lines in a certain factory just as productive?</li>
<li>Are all factories just as productive (per assembly line)?</li>
<li>Did productivity go up over time? Did it hit a maximum?</li>
<li>How many Xboxes were produced total?</li>
<li>Does an assembly line in a certain factory use all the same flash chips, hard drives and DVD drives in a certain week?</li>
<li>When did an assembly line in a certan factory switch between board revisions?</li>
<li>How long does it take an assembly line to be reconfigured for a different board revision?</li>
<li>When did factories open/close? When did assembly lines get created and torn down in certain factories? Is there a correlation? Did assembly lines get migrated between factories? How long does this take?</li>
<li>How long does it take on average for an Xbox from manufacuring to when it&#8217;s bought, per country? Does it change over the years?</li>
<li>Which factories serve which countries? Did it change?</li>
<li>How do ROM version, HD software version, motherboard version and video encoder brand correlate to each other?</li>
<li>Which countries have PAL, which have NTSC?</li>
<li>Where were the non-black Xboxes made?</li>
<li>What percentage of Xboxes has a Philips, a Samsung or a Thomson DVD drive?</li>
<li>What is the distribution of hard drive types?</li>
<li>Some people claim they have a 20 GB hard drive. How credible is this?</li>
<li>When and at which factories were certain DVD and HD types introduced?</li>
<li>Over time, how did the distribution of DVD and HD types change?</li>
<li>What is the distribution of flash chips, how did it change, and how does it correlate to factories?</li>
<li>Is there enough data to make statements about the refurbishment process (search for &#8220;refurb&#8221; in comments)?</li>
<li>What percentage of people misses a digit when trying to type in 12 digits?</li>
<li>What percentage of people replaced digits of the serial number with an &#8216;X&#8217; or a &#8216;*&#8217;? What percentage of these chose the right digits to properly anonymize their serial numbers?
<li>Any more interesting observations you can come up with?</li>
</ol>
<p>Please share your ideas as well as your results (plus source code of your scripts, please)! If you know any statistics teachers looking for a large real-world data set and an interesting set of problems, feel free to refer them to this site! :-)</p>
<p><a href="http://www.xbox-linux.org/wiki/Xbox_Manufacturing_Process_Pictures"><img src="http://www.pagetable.com/docs/xbox_serials/2.jpg" width="440" height="289"></a></p>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=465&amp;ts=1369319073" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=465</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Windows Phone 7 &amp; the Floppy Disk</title>
		<link>http://www.pagetable.com/?p=476</link>
		<comments>http://www.pagetable.com/?p=476#comments</comments>
		<pubDate>Thu, 18 Nov 2010 20:00:40 +0000</pubDate>
		<dc:creator>Michael Steil</dc:creator>
				<category><![CDATA[default]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=476</guid>
		<description><![CDATA[I&#8217;m sure all users will immediately associate a Sony 3.5&#8243; Floppy Disk with &#8220;save&#8221;. It&#8217;s not like the stock icon library also had an OK button.]]></description>
			<content:encoded><![CDATA[<p><img src="docs/wp7_floppy.jpg"></p>
<p>I&#8217;m sure all users will immediately associate a <a href="http://www.nydailynews.com/tech_guide/2010/04/27/2010-04-27_sony_to_end_sales_of_35_floppy_disk_marks_death_of_30yearold_format.html">Sony 3.5&#8243; Floppy Disk</a> with &#8220;save&#8221;. It&#8217;s not like the stock icon library also had an OK button.</p>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=476&amp;ts=1369319073" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=476</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>The Intel 80376 &#8211; a Legacy-Free i386 (with a Twist!)</title>
		<link>http://www.pagetable.com/?p=460</link>
		<comments>http://www.pagetable.com/?p=460#comments</comments>
		<pubDate>Tue, 16 Nov 2010 09:00:57 +0000</pubDate>
		<dc:creator>Michael Steil</dc:creator>
				<category><![CDATA[archeology]]></category>
		<category><![CDATA[whines]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=460</guid>
		<description><![CDATA[25 years after the introduction of the 32 bit Intel i386 CPU, all Intel compatibles still start up (and wake up!) in 16 bit stone-age mode, and they have to be switched into 32/64 bit mode to be usable. Wouldn&#8217;t it be nice if a modern i386/x86_64 CPU started at least in 32 bit protected [...]]]></description>
			<content:encoded><![CDATA[<p>25 years after the introduction of the 32 bit Intel i386 CPU, all Intel compatibles still start up (and wake up!) in 16 bit stone-age mode, and they have to be <a href="http://www.pagetable.com/?p=276">switched into 32/64 bit mode</a> to be usable.</p>
<p>Wouldn&#8217;t it be nice if a modern i386/x86_64 CPU started at least in 32 bit protected mode? Can&#8217;t they make a legacy-free CPU that does not support 16 bit mode at all? Such a CPU exists, well, existed. It&#8217;s the 1989-2001 <a href="http://en.wikipedia.org/wiki/Intel_80376">Intel 80376</a>, an embedded version of the Intel i386.</p>
<p>The <a href="http://datasheets.chipdb.org/Intel/x86/376/datashts/24018204.PDF">datasheet</a> describes all the interesting differences. The 80376 does not support any 16 bit mode, so the &#8220;D&#8221; bit in segment descriptors must be set to 1 (page 25), forcing 32 bit code and data segments. 286-style descriptors are not supported either (page 27). (The 0&#215;66 and 0&#215;67 opcode prefixes still exists, so code can work on 16 bit registers and generate 16 bit addresses (page 14), just like an i386 in 32 bit mode.)</p>
<p>Since the CPU does not support 16 bit modes, it cannot do real mode, so CR0.PE is always 1. Consequently, a 80376 starts up in 32 bit protected mode, but otherwise, startup is just like on the i386 (page 19): EIP is 0x0000FFF0, CS is 0xF000, CS.BASE is 0xFFFF0000, CS.LIMIT is 0xFFFF, and the other segment registers are 0&#215;0000, with a base of 0&#215;00000000 and a limit of 0xFFFF. No GDT is set up, and in order to get the system into a sane state, loading a GDT and reloading the segment registers is still necessary. Too bad they didn&#8217;t set all bases to 0, all limits to 0xFFFFFFFF and EIP to 0xFFFFFFF0.</p>
<p>The 80376 is designed to be forward-compatible with the i386, so unsupported features are documented as &#8220;reserved&#8221; or &#8220;must be 0/1&#8243;, and legacy properties like the garbled segment descriptors are unchanged. All (properly written) 80376 software should also run on an i386 (page 1) &#8211; except for the first few startup instructions of course. Intel provides the following code sequence (page 20) that is to be executed directly after RESET to distinguish between the 80376 and the i386:</p>
<pre>
smsw bx
test bl, 1
jnz is_80376
</pre>
<p>This tests for CR0.PE, which is hardcoded to 1 on the 80376 and is 0 on RESET on an i386. The three instructions are bitness agnostic, i.e. the encoding is identical in 16 and 32 bit mode.</p>
<p>Sounds like the perfect CPU? Well, here comes the catch: The 80376 doesn&#8217;t do paging. CR2 and CR3 don&#8217;t exist (it is undocumented whether accessing them causes an exception), CR0.PG is hardcoded to 0 (page 8) and the #PF exception does not exist (page 17). A man can dream though&#8230; a man can dream.</p>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=460&amp;ts=1369319073" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=460</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Emu8080: an HTML5 App to Emulate a Complete CP/M Machine</title>
		<link>http://www.pagetable.com/?p=457</link>
		<comments>http://www.pagetable.com/?p=457#comments</comments>
		<pubDate>Sun, 14 Nov 2010 11:42:06 +0000</pubDate>
		<dc:creator>Michael Steil</dc:creator>
				<category><![CDATA[archeology]]></category>
		<category><![CDATA[hacks]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=457</guid>
		<description><![CDATA[by Stefan Tramm There are a lot of web-based computer emulators out there for ancient machines &#8211; the Commodore 64 and MSX home computers or the more exotic Space Invaders arcade machines. Such emulators are nice to play with but they are incomplete &#8211; they lack an Input/Output subsystem. Emu8080 is the first known Javascript-based [...]]]></description>
			<content:encoded><![CDATA[<p><em>by Stefan Tramm</em></p>
<p>There are a lot of web-based computer emulators out there for ancient machines &#8211; the <a href="http://www.kingsquare.nl/jsc64">Commodore 64</a> and <a href="sites.google.com/site/jsmsxdemo/jsmsx.html">MSX</a> home computers or the more exotic <a href="http://www.bluishcoder.co.nz/js8080/">Space Invaders</a> arcade machines. Such emulators are nice to play with but they are incomplete &#8211; they lack an Input/Output subsystem.</p>
<p>Emu8080 is the first known Javascript-based emulator which adds a floppy disk system, a fast paper tape reader/writer, a line printer and a VT100 terminal emulator to the mix. Modern web browsers offer a local WebSQL database, which is used to implement block storage devices. Drag-and-Drop is used to mount a desktop file onto the virtual tape device. Together with CPU and RAM emulation, you have a complete machine inside your web browser&#8230;</p>
<p>Want to try out? Use Chrome6+ (or Safari5) and visit <a href="http://www.tramm.li/i8080">http://www.tramm.li/i8080</a></p>
<p>Now you are working inside a classical machine monitor for an 8080 microcomputer from the 70&#8242;s. Available commands are:</p>
<ul>
<li><tt>m</tt> to modify memory</li>
<li><tt>d</tt> to dump memory on the screen</li>
<li><tt>l</tt> to disassemble a program (in Z80 Syntax)</li>
<li><tt>g</tt> to start execution</li>
<li><tt>&lt;Enter&gt;</tt> to perform a single step</li>
<li><tt>x</tt> to show and modify CPU registers</li>
<li><tt>h</tt> for help</li>
</ul>
<p>So far this is pretty normal machine emulation.</p>
<p>The first important command is &#8220;r&#8221;. Without any parameters, it lists the available files on the tramm.li server. &#8220;r file&#8221; reads an Intel HEX file into memory, for example &#8220;r basic&#8221; will load the well-known Microsoft 8K BASIC interpreter for the Intel 8080.</p>
<p>But as already mentioned, a disk subsystem is also available. The first step in using it is to either insert a pre-formatted disk or to format an empty disk. To insert a pre-formatted CP/M disk, issue a &#8220;r 0 cpma&#8221; command.</p>
<p>This command expects the image of an 8-inch IBM formatted SS/SD diskette and writes it sector-wise into the browser-local WebSQL database. This needs to be done only once, causing the disk to now be loaded into your browser as Emu8080 drive 0. With the &#8220;b&#8221; command, the boot sector is loaded into &#8220;main memory&#8221;, starting at address 0. Now issue a &#8220;g&#8221; command to start execution. Ta da!, CP/M 2.2 has been loaded and started!</p>
<p>To go back to the monitor, you have two choices: Ctrl-. or via the &#8220;bye&#8221; executable.</p>
<p>Emu8080 supports four drives, so you can either format the other drives (&#8220;F&#8221; command) or search for other images on the internet and load them yourself. But how do we mount these drives? The &#8220;dsk&#8221; commands comes to rescue. It opens a new window, showing the current status of each drive. Every disk is also a drop-area, so you can mount disk images per drag-and-drop from your desktop into the emulator. Technically the FileReader API of Javascript is used, and this API is currently (November 2010) implemented only by Chrome (or Opera). Yes, you do not need the server anymore to transport data into a Javascript application.</p>
<p>Now you can mount disks and boot CP/M. You can edit files with ED.COM or Wordmaster, or write programs in 8080 assembler. But how to get the modified disk images out of the emulator again? The &#8220;dsk [n]&#8221; commands opens a new window, which allows to post the binary disk image to an arbitrary web server, e.g. localhost. (btw: there is no FileWriter API in HTML5). Just change the target URL and the form will post it where ever you want.</p>
<p>Sometimes mounting and posting whole images is overkill, transmitting a single file into the CP/M machine or getting it out may be all you want to do. And here comes the emulated paper tape device to rescue. Just drag a file onto the terminal&#8217;s main window and it will be mounted. Inside CP/M, just use the PIP command: &#8220;pip file.txt=rdr:&#8221; and you will have the tape&#8217;s content in FILE.TXT. Please keep in mind that CP/M is not 8-bit clean.</p>
<p>To get a single file out of the emulator, the paper tape puncher is used. Inside CP/M just use PIP again: &#8220;pip ptp:=rew.asm&#8221; to punch the file out. Then enter the monitor again (Ctrl-. or &#8220;bye&#8221;) and use the &#8220;ptp&#8221; command, which opens a window, where you either post the tape content to an arbitrary web server or simply copy-paste the content.</p>
<p>The final device is a line printer. It just opens a separate window where every character is shown. No escape sequences are implemented &#8211; therefore no bold or underlined characters.</p>
<p>In the unlikely case that the user has no clue about CP/M and its commands, the emulator includes a PDF of the original documentation by Digital Research.</p>
<p>Now, lets take a short look into the technical details:</p>
<ol>
<li><b>WebSQL</b>: The emulator uses the browser local SQL DB as block storage for the four disk drives. The storage is persistent and writable.</li>
<li><b>Drag-and-Drop / FileReader API</b>: The emulator uses drag-and-drop and the FileReader API to read paper tape or disc images from your local machine.</li>
<li><b>HTML5 manifest</b>: The emulator supports the browser local database and browser local file reading. To make it also runnable without an active internet connection, it is built as a HTML 5 App by providing an emu8080.manifest file. This file tells the browser which resources (HTML, JS, CSS, PNG, HEX, CPM, PDF files) must be cached. This means that if you bookmark <a href="http://www.tramm.li/i8080/emu8080.html">http://www.tramm.li/i8080/emu8080.html</a>, you can start the emulator and access the disk drives even without an internet connection &#8212; just like a local application.</li>
<li><b>ShellInABox</b>: Without the fabulous VT100 emulation of ShellInABox, this emulator would not have been possible. The provided example of a BASIC interpreter was the starting point for the 8080 emulator.</li>
<li><b>z80pack</b>: The C based implementation of a Z80 machine was the basis for the IO-subsystem implementation, the custom BIOS, and the boot disk image. The trick for reducing host CPU cycles in tight IO-Loops (eg. when CP/M is waiting for a key press) was taken from this package.</li>
<li><b>js8080</b>: The Space Invaders emulator js8080 gifted the core CPU emulation.</li>
</ol>
<p>One last word on performance. On a usual x86 processor the emulator performs like a 2 MHz 8080. With the monitor command &#8220;instr&#8221; you can tune the performance, by increasing the number of executed 8080 instructions per Javascript timeslice. With today&#8217;s hardware, you can expect the performance of a 8 MHz CPU (which was never available as real silicon).</p>
<p>And for Microsoft BASIC fans, try &#8220;r basic&#8221; and &#8220;g&#8221; afterwards instead of booting CP/M &#8211; welcome to 8K BASIC. Use &#8220;SAVE&#8221; to save your programs on the paper tape :-) and &#8220;LOAD&#8221; to read saved programs.</p>
<p>Neozeed provided the Zork adventure game disk image.</p>
<p>And now &#8212; happy hacking.</p>
<ul>
<li><a href="http://www.tramm.li/i8080/">http://www.tramm.li/i8080/</a></li>
<li><a href="http://www.tramm.li/i8080/emu8080.html">http://www.tramm.li/i8080/emu8080.html</a></li>
</ul>
<p>Other links:</p>
<ul>
<li>Neozeed blogged about the emulator, he also provides a very clear Howto, please take a look at: <a href="http://virtuallyfun.blogspot.com/2010/10/cpm-zork-in-java-script.html">http://virtuallyfun.blogspot.com/2010/10/cpm-zork-in-java-script.html</a></li>
<li>Emu8080 is also mentioned on the Z80 Info Pages (many thanks to Gaby from gaby.de for the reference!): <a href="http://www.z80.info/z80emu.htm#EMU_CPU_VAR">http://www.z80.info/z80emu.htm#EMU_CPU_VAR</a></li>
</ul>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=457&amp;ts=1369319073" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=457</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>HFS+ File System Analysis and Forensics with fileXray</title>
		<link>http://www.pagetable.com/?p=454</link>
		<comments>http://www.pagetable.com/?p=454#comments</comments>
		<pubDate>Mon, 01 Nov 2010 18:18:01 +0000</pubDate>
		<dc:creator>Michael Steil</dc:creator>
				<category><![CDATA[literature]]></category>
		<category><![CDATA[tricks]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=454</guid>
		<description><![CDATA[Modern filesystems are highly optimized database systems that are a core function of modern operating systems. They allow concurrent access by many CPUs, they keep locality up and fragementation down, and they can recover from crashes guaranteeing consistent data structures. If you want to learn about the internals of modern filesystems, you can either read [...]]]></description>
			<content:encoded><![CDATA[<p>Modern filesystems are highly optimized database systems that are a core function of modern operating systems. They allow concurrent access by many CPUs, they keep locality up and fragementation down, and they can recover from crashes guaranteeing consistent data structures.</p>
<p>If you want to learn about the internals of modern filesystems, you can either read up on theory (e.g. Dominic Giampaolo&#8217;s excellent free book <a href="http://www.nobius.org/~dbg/practical-file-system-design.pdf">Practical File System Design</a>), or you can dissect one using a tool like <a href="http://www.filexray.com/">fileXray</a>, which</p>
<ul>
<li>allows you to examine data structures on your Mac OS X HFS+ disk, like the volume header, the journal, regular and special files, etc., down to the B-tree level</li>
<li>gives you insight into statistics like fragmentation and hot file clustering</li>
<li>&#8230;</li>
<li>lets you find out where all these deleted files really go, and what forensic analysis can tell someone about your disks!</li>
</ul>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=454&amp;ts=1369319073" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=454</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>For Lisa, the World Ended in 1995</title>
		<link>http://www.pagetable.com/?p=450</link>
		<comments>http://www.pagetable.com/?p=450#comments</comments>
		<pubDate>Thu, 28 Oct 2010 06:20:18 +0000</pubDate>
		<dc:creator>Michael Steil</dc:creator>
				<category><![CDATA[archeology]]></category>
		<category><![CDATA[hacks]]></category>
		<category><![CDATA[trivia]]></category>
		<category><![CDATA[whines]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=450</guid>
		<description><![CDATA[If you try to set the clock in Lisa OS 3.1 to 2010, you&#8217;re out of luck: You can only enter years from 1981 to 1995. That&#8217;s a span of 15 years &#8211; why? And what happens if the clock runs past the end of 1995? Well, it wraps around to 1 Jan 1980. But [...]]]></description>
			<content:encoded><![CDATA[<p>If you try to set the clock in Lisa OS 3.1 to 2010, you&#8217;re out of luck:</p>
<p><img src="http://www.pagetable.com/docs/lisa_clock/lisa_clock1.png"></p>
<p>You can only enter years from 1981 to 1995. That&#8217;s a span of 15 years &#8211; why? And what happens if the clock runs past the end of 1995?</p>
<p>Well, it wraps around to 1 Jan 1980.</p>
<p>But why does it not allow entering 1980 then? That&#8217;s why:</p>
<p><img src="http://www.pagetable.com/docs/lisa_clock/lisa_clock2.png"></p>
<p>Whenever the clock is set to 1980, it thinks the clock is not set up properly. So it <i>is</i> a 4 bit counter. Too bad, a 5 bit counter could have made it into 2011, and we all know that&#8217;s way more than ever needed.</p>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=450&amp;ts=1369319073" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=450</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Name that Ware</title>
		<link>http://www.pagetable.com/?p=441</link>
		<comments>http://www.pagetable.com/?p=441#comments</comments>
		<pubDate>Tue, 26 Oct 2010 21:59:22 +0000</pubDate>
		<dc:creator>Michael Steil</dc:creator>
				<category><![CDATA[archeology]]></category>
		<category><![CDATA[whines]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=441</guid>
		<description><![CDATA[]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.pagetable.com/docs/name_that_ware.jpg"><img src="http://www.pagetable.com/docs/name_that_ware.jpg" width="440" height="330"></a></p>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=441&amp;ts=1369319073" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=441</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Standalone Commodore BASIC on the iPhone/iPad</title>
		<link>http://www.pagetable.com/?p=437</link>
		<comments>http://www.pagetable.com/?p=437#comments</comments>
		<pubDate>Mon, 18 Oct 2010 04:51:55 +0000</pubDate>
		<dc:creator>Michael Steil</dc:creator>
				<category><![CDATA[6502]]></category>
		<category><![CDATA[archeology]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=437</guid>
		<description><![CDATA[You might remember the hassle about the Commodore 64 emulator in the iPhone App Store about a year ago: First it was approved, but then pulled again, because it allowed access to the C64&#8242;s BASIC &#8211; general-purpose interpreters were not allowed. After Apple relaxed this restriction, BASIC was added again. So now it fills me [...]]]></description>
			<content:encoded><![CDATA[<p>You might remember the <a href="http://gizmodo.com/5354422/commodore-64-iphone-app-approved-removed">hassle</a> about the <a href="http://itunes.apple.com/us/app/commodore-64/id305504539?mt=8">Commodore 64 emulator</a> in the iPhone App Store about a year ago: First it was approved, but then pulled again, because it allowed access to the C64&#8242;s BASIC &#8211; general-purpose interpreters were not allowed. After Apple relaxed this restriction, BASIC was <a href="http://toucharcade.com/2010/09/12/manomio-adds-basic-to-c64-in-light-of-apples-sdk-agreement-update/">added again</a>.</p>
<p>So now it fills me with joy that Ahmad Hawwash managed to get standalone Commodore BASIC into the App Store! His &#8220;<a href="http://itunes.apple.com/us/app/hand-basic-cbm-flavor/id394924289?mt=8">Hand BASIC &#8211; CBM Flavor</a>&#8221; is free of charge, runs on iPhone/iPod touch and iPad, and is based on <a href="http://www.pagetable.com/?p=48">pagetable.com&#8217;s</a> Open Source <a href="http://cbmbasic.sourceforge.net/">cbmbasic</a> project, a recompiled version of the original Commodore 64 binary, so the BASIC interpreter is itself not interpreted, but runs natively and at full speed, which is in the order of 500 times faster than on a C64.</p>
<p>&#8220;Hand BASIC&#8221; has LOAD/SAVE support and comes with several demo programs &#8211; just type <tt>LOAD"$",8</tt> and <tt>LIST</tt> to see them and <tt>LOAD"NAME",8</tt> and <tt>RUN</tt> to run them. Type the (nonstandard/added) <tt>HIDE</tt> keyword to hide the keyboard.</p>
<p><a href="http://www.pagetable.com/docs/cbmbasic_iphone/cbmbasic_iphone.png"><img src="http://www.pagetable.com/docs/cbmbasic_iphone/cbmbasic_iphone.png" width="320" height="480"></a></p>
<p>What would be very interesting now:</p>
<ul>
<li>Some cool BASIC programs that run in here &#8211; games, maybe?</li>
<li>A compiler backend that produces Commodore BASIC code, so I can run any code on the iPhone through this &#8211; with a 38911 byte RAM limitation, of course. (Actually, a program is free to set the TOPMEM pointer higher, allowing up to 62 KB of RAM for code and variables.)</li>
</ul>
<p>Any other ideas? :-)</p>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=437&amp;ts=1369319073" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=437</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
		<item>
		<title>Internals of BRK/IRQ/NMI/RESET on a MOS 6502</title>
		<link>http://www.pagetable.com/?p=410</link>
		<comments>http://www.pagetable.com/?p=410#comments</comments>
		<pubDate>Wed, 29 Sep 2010 22:47:12 +0000</pubDate>
		<dc:creator>Michael Steil</dc:creator>
				<category><![CDATA[6502]]></category>
		<category><![CDATA[archeology]]></category>
		<category><![CDATA[hacks]]></category>
		<category><![CDATA[trivia]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=410</guid>
		<description><![CDATA[After 35 years of measuring the behaviour of the MOS 6502 CPU to better understand what is going on, the Visual6502 simulator finally allows us insight into the chip, so we can understand what the CPU does internally. One interesting thing here is the question how the 6502 handles BRK, IRQ, NMI and RESET. The [...]]]></description>
			<content:encoded><![CDATA[<p>After 35 years of measuring the behaviour of the MOS 6502 CPU to better understand what is going on, the <a href="http://visual6502.org/JSSim/index.html">Visual6502</a> simulator finally allows us insight into the chip, so we can understand what the CPU does internally. One interesting thing here is the question how the 6502 handles BRK, IRQ, NMI and RESET.</p>
<h2>The Specification</h2>
<p>Let&#8217;s revisit the documented part first. The 6502 knows three vectors at the top of its address space:</p>
<table border="1">
<tr>
<th>Signal</th>
<th>Vector</th>
</tr>
<tr>
<td>NMI</td>
<td>$FFFA/$FFFB</td>
</tr>
<tr>
<td>RESET</td>
<td>$FFFC/$FFFD</td>
</tr>
<tr>
<td>IRQ/BRK</td>
<td>$FFFE/$FFFF</td>
</tr>
</table>
<ul>
<li>On a RESET, the CPU loads the vector from $FFFC/$FFFD into the program counter and continues fetching instructions from there.</li>
<li>On an NMI, the CPU pushes the low byte and the high byte of the program counter as well as the processor status onto the stack, disables interrupts and loads the vector from $FFFA/$FFFB into the program counter and continues fetching instructions from there. </li>
<li>On an IRQ, the CPU does the same as in the NMI case, but uses the vector at $FFFE/$FFFF.</li>
<li>On a BRK instruction, the CPU does the same as in the IRQ case, but sets bit #4 (B flag) in the copy of the status register that is saved on the stack.</li>
</ul>
<p>The four operations are very similar, they only differ in the location of the vector, whether they actually push data onto the stack, and whether they set the B flag.</p>
<table border="1">
<tr>
<th>Signal</th>
<th>Vector</th>
<th>Push PC and P</th>
<th>Set B Flag</th>
</tr>
<tr>
<td>NMI</td>
<td>$FFFA/$FFFB</td>
<td align="center">yes</td>
<td align="center">no</td>
</tr>
<tr>
<td>RESET</td>
<td>$FFFC/$FFFD</td>
<td align="center">no</td>
<td align="center">no</td>
</tr>
<tr>
<td>IRQ</td>
<td>$FFFE/$FFFF</td>
<td align="center">yes</td>
<td align="center">no</td>
</tr>
<td>BRK</td>
<td>$FFFE/$FFFF</td>
<td align="center">yes</td>
<td align="center">yes</td>
</tr>
</table>
<h2>BRK</h2>
<p>Ignoring opcode fetches, the <a href="http://www.pagetable.com/?p=39">PLA ROM</a> defines the following cycles of the BRK instruction (<a href="http://archive.6502.org/datasheets/synertek_programming_manual.pdf">6502 Programming Manual</a>, page 131):</p>
<ul>
<li>store PC(hi)</li>
<li>store PC(lo)</li>
<li>store P</li>
<li>fetch PC(lo) from $FFFE</li>
<li>fetch PC(hi) from $FFFF</li>
</ul>
<h2>IRQ</h2>
<p>An IRQ does basically the same thing as a BRK, but it clears the B flag in the pushed status byte. The CPU goes through the same sequence of cycles as in the BRK case, which is done like this:</p>
<p>If there is an IRQ pending and the current instruction has just finished, the interrupt logic in the 6502 forces the instruction register (&#8220;IR&#8221;) to &#8220;0&#8243;, so instead of executing the next instruction, the PLA will decode the instruction with the opcode 0&#215;00 &#8211; which is BRK! Of course it has to kick in a few cycles later again to make sure a B value of 0 is pushed, but otherwise, it&#8217;s just the BRK instruction executing.</p>
<h2>NMI</h2>
<p>Not surprisingly, NMI is done the same way: &#8220;0&#8243; is injected into the instruction stream, but this time, some extra logic makes sure that the addresses $FFFA/$FFFB are put onto the address bus when fetching the vector.</p>
<h2>RESET</h2>
<p>RESET also runs through the same sequence, but it is the most different of the four cases, since it does not write the current PC and status onto the stack &#8211; but this was hacked trivially: The bus cycles exist, but the read/write line is not set to &#8220;write&#8221;, but &#8220;read&#8221; instead. The following trace was created with the transistor data from the Visual 6502 project and shows the first nine cycles after letting go of RESET:</p>
<pre>
#0 AB:00FF D:00 R/W:1 PC:00FF A:AA X:00 Y:00 SP:00 P:02 IR:00  READ $00FF = $00
</pre>
<p><b>Cycle 0</b>: When a 6502 is turned on, the stack pointer is initialized with zero. The BRK/IRQ/NMI/RESET sequence pulls the instruction register (IR) to 0.</p>
<pre>
#1 AB:00FF D:00 R/W:1 PC:00FF A:AA X:00 Y:00 SP:00 P:02 IR:00  READ $00FF = $00
#2 AB:00FF D:00 R/W:1 PC:00FF A:AA X:00 Y:00 SP:00 P:02 IR:00  READ $00FF = $00
#3 AB:0100 D:00 R/W:1 PC:00FF A:AA X:00 Y:00 SP:00 P:02 IR:00  READ $0100 = $00
</pre>
<p><b>Cycle 3</b>: The first stack access happens at address $0100 &#8211; a push first stores the value at $0100 + SP, then decrements SP. In the BRK/IRQ/NMI case, this would have stored the high-byte of the PC. But for RESET, it is a read cycle, not a write cycle, and the result is discarded.</p>
<pre>
#4 AB:01FF D:00 R/W:1 PC:00FF A:AA X:00 Y:00 SP:00 P:02 IR:00  READ $01FF = $00
</pre>
<p><b>Cycle 4</b>: SP is now 0xFF (even if the internal state does not reflect that), so the second stack access (which would have been the low-byte of PC) targets 0x01FF. Again, the result is discarded, and SP decremented.</p>
<pre>
#5 AB:01FE D:00 R/W:1 PC:00FF A:AA X:00 Y:00 SP:00 P:02 IR:00  READ $01FE = $00
</pre>
<p><b>Cycle 5</b>: SP is now 0xFE, and the third stack access, (the status register) happens at 0x01FE. SP is decremented again.</p>
<pre>
#6 AB:FFFC D:E2 R/W:1 PC:00FF A:AA X:00 Y:00 SP:FD P:06 IR:00  READ $FFFC = $E2
</pre>
<p><b>Cycle 6</b>: The internal state of the CPU now shows that SP is 0xFD, because it got decremented 3 times for the three fake push operations. The low-byte of the vector is read.</p>
<pre>
#7 AB:FFFD D:FC R/W:1 PC:00FF A:AA X:00 Y:00 SP:FD P:16 IR:00  READ $FFFD = $FC
</pre>
<p><b>Cycle 7</b>: The high-byte of the vector is read.</p>
<pre>
#8 AB:FCE2 D:A2 R/W:1 PC:FCE2 A:AA X:00 Y:00 SP:FD P:16 IR:00  READ $FCE2 = $A2
</pre>
<p><b>Cycle 8</b>: The first actual instruction is fetched.</p>
<p>Since RESET is not timing critical, it doesn&#8217;t matter whether a few cycles are wasted by doing the fake stack cycles.</p>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=410&amp;ts=1369319073" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=410</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Measuring the ROR Bug in the Early MOS 6502</title>
		<link>http://www.pagetable.com/?p=406</link>
		<comments>http://www.pagetable.com/?p=406#comments</comments>
		<pubDate>Tue, 28 Sep 2010 08:38:29 +0000</pubDate>
		<dc:creator>Michael Steil</dc:creator>
				<category><![CDATA[6502]]></category>
		<category><![CDATA[archeology]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=406</guid>
		<description><![CDATA[The MOS 6502 CPU was introduced in September of 1975, and while the documentation described the three shift/rotate instructions ASL, LSR and ROL, the ROR instruction was missing &#8211; the documentation said that ROR would be available in chips starting in June 1976. In fact, the reason for this omission was that the instruction, while [...]]]></description>
			<content:encoded><![CDATA[<p>The MOS 6502 CPU was introduced in September of 1975, and while the documentation described the three shift/rotate instructions ASL, LSR and ROL, <a href="http://www.pagetable.com/?p=45">the ROR instruction was missing</a> &#8211; the documentation said that ROR would be available in chips starting in June 1976. In fact, the reason for this omission was that the instruction, while being present, didn&#8217;t behave correctly. Only few 6502s with the defect are in existence, and nobody seemed to have checked what was actually going on in these chips.</p>
<p>Simon C got <a href="http://www.pagetable.com/?p=359">my KIM-1</a> working again, which has a 6502 from week 51 of 1975. There are 512 possible inputs to ROR (8 bit A plus 1 bit C; assuming it doesn&#8217;t have dependencies on other registers), and roughly two bytes of output: the 8 bit result and the processor status (flags) register. We ran the following programs on the KIM-1 &#8211; note that we had to split the task into several programs, because the KIM-1 doesn&#8217;t have enough RAM to hold all results.</p>
<p>Program 1a: for A=00..FF, with C=0, execute &#8220;ROR A&#8221;, save result into array</p>
<pre>
.C:0200   A2 00      LDX #$00
.C:0202   8A         TXA
.C:0203   18         CLC
.C:0204   6A         ROR A
.C:0205   9D 00 03   STA $0300,X
.C:0208   E8         INX
.C:0209   D0 F7      BNE $0202
.C:020B   00         BRK
</pre>
<p>Program 1b: for A=00..FF, with C=1, execute &#8220;ROR A&#8221;, save result into array</p>
<pre>
.C:0200   A2 00      LDX #$00
.C:0202   8A         TXA
.C:0203   38         SEC
.C:0204   6A         ROR A
.C:0205   9D 00 03   STA $0300,X
.C:0208   E8         INX
.C:0209   D0 F7      BNE $0202
.C:020B   00         BRK
</pre>
<p>Program 2a: for A=00..FF, with C=0, execute &#8220;ROR A&#8221;, save flags into array</p>
<pre>
.C:0200   A2 00      LDX #$00
.C:0202   8A         TXA
.C:0203   38         SEC
.C:0204   6A         ROR A
.C:0205   08         PHP
.C:0206   68         PLA
.C:0207   9D 00 03   STA $0300,X
.C:020a   E8         INX
.C:020b   D0 F5      BNE $0202
.C:020d   00         BRK
</pre>
<p>Program 2b: for A=00..FF, with C=1, execute &#8220;ROR A&#8221;, save flags into array</p>
<pre>

.C:0200   A2 00      LDX #$00
.C:0202   8A         TXA
.C:0203   38         SEC
.C:0204   6A         ROR A
.C:0205   08         PHP
.C:0206   68         PLA
.C:0207   9D 00 03   STA $0300,X
.C:020a   E8         INX
.C:020b   D0 F5      BNE $0202
.C:020d   00         BRK
</pre>
<p>These are the results:</p>
<p>Program 1a and 1b (result with C=0 and C=1) produced the same output!</p>
<pre>
00 -> 00
01 -> 02
02 -> 04
03 -> 06
04 -> 08
05 -> 0A
[...]
FF -> FE
</pre>
<p>This is a shift left (!!!) of the input value; and it is independent of the carry flag &#8211; just like ASL.</p>
<p>Program 2a (status when C=0) produced the following output:</p>
<pre>
00:     7E (Z=1, N=0, C=0)
01..3F: 7C (Z=0, N=0, C=0)
40..7F: FC (Z=0, N=1, C=0)
80:     7E (Z=1, N=0, C=0)
81..BF: 7C (Z=0, N=0, C=0)
C0..FF: FC (Z=0, N=1, C=0)
</pre>
<p>Program 2b (status when C=1) produced the following output:</p>
<pre>
00:     7F (Z=1, N=0, C=1)
01..3F: 7D (Z=0, N=0, C=1)
40..7F: FD (Z=0, N=1, C=1)
80:     7F (Z=1, N=0, C=1)
81..BF: 7D (Z=0, N=0, C=1)
C0..FF: FD (Z=0, N=1, C=1)
</pre>
<p>These are the correct flags corresponding to the incorrect results in A. The carry flag is the same as the input carry flag, i.e. it is unmodified.</p>
<p>Our preliminary summary is this:</p>
<table border="1">
<tr>
<td>
<pre>
  ROR          Broken ROR on pre-June '76 CPU (Memory or Accumulator)
                   +-+-+-+-+-+-+-+-+
  Operation:       |7|6|5|4|3|2|1|0| <- 0
                   +-+-+-+-+-+-+-+-+                    N Z C I D V
                                                        / / _ _ _ _
</pre>
</td>
</tr>
</table>
<p>So ROR on early 6502s does three things wrong:</p>
<ol>
<li>It shifts left, instead of right (behaves like ASL)</li>
<li>It shifts a zero in, instead of C (behaves like ASL)</li>
<li>It doesn't update C (as if it wasn't a rotate instruction)</li>
</ol>
<p>All three problems are flags that are sent to the ALU: the shift direction, the input bit, and the carry writeback.</p>
<p>Unresolved questions:</p>
<ul>
<li>We only tested ROR A; other addressing modes of ROR might behave differently. Other addressing modes might even be working - but I doubt that, since MOS would certainly have documented the working ones then.</li>
<li>ROR might have more dependencies than A and C.</li>
<li>What is it in the chip that causes the bug? I'm sure the fine guys at <a href="http://visual6502.org/">visual6502.org</a> will be able to figure this one out soon. It is unlikely to be a bug in the <a href="http://www.pagetable.com/?p=39">PLA ROM</a>, because a bug there would not affect different addressing modes of the same instruction with very different timings. It is more likely that it is in the "Random Control Logic" part.</li>
</ul>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=406&amp;ts=1369319073" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=406</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Measuring the Entropy of the MOS 6502 CPU</title>
		<link>http://www.pagetable.com/?p=401</link>
		<comments>http://www.pagetable.com/?p=401#comments</comments>
		<pubDate>Mon, 27 Sep 2010 04:58:13 +0000</pubDate>
		<dc:creator>Michael Steil</dc:creator>
				<category><![CDATA[6502]]></category>
		<category><![CDATA[archeology]]></category>
		<category><![CDATA[puzzle]]></category>
		<category><![CDATA[trivia]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=401</guid>
		<description><![CDATA[Everything can be expressed in bits. It takes 4 kilobits to decompress ZIP data, 25 kilobits to kill a human, 43 megabits for a working Mac OS X kernel, and 10^120 bits to describe our universe. What is the entropy/complexity of the 6502 CPU, you might wonder? You have probably already seen Visual 6502, a [...]]]></description>
			<content:encoded><![CDATA[<p>Everything can be expressed in bits. It takes <a href="http://atariarea.krap.pl/x-asm/inflate.html">4 kilobits to decompress ZIP data</a>, <a href="http://www.bunniestudios.com/blog/?p=353">25 kilobits to kill a human</a>, <a href="file:///mach_kernel">43 megabits for a working Mac OS X kernel</a>, and <a href="http://focus.aps.org/story/v9/st27">10^120 bits to describe our universe</a>. What is the entropy/complexity of the 6502 CPU, you might wonder?</p>
<p>You have probably already seen <a href="http://www.visual6502.org/JSSim/index.html">Visual 6502</a>, a simulator of the 6502 that operates at the transistor level and visualizes what&#8217;s going on inside the CPU. The data the program operates on was derived by converting a high-resolution photograph of the 6502 die into polygons, and converting these polygons into the node and transistor configuration.</p>
<p>If you ignore the polygon data, which is only needed for visualization, the data to fully describe the 6502 consists of a set of nodes and a set of transistors.</p>
<p>There are 1725 nodes in the 6502, and 3510 transistors. Every transistor has one node as an input that turns the transistor on or off. If the transistor is on, it connects two other nodes, and if it is off, it separates them. Every node can either be neutral, or be a pullup &#8211; the latter means that the node will behave as if it was connected to VCC whenever the path through this node is otherwise floating, i.e. not connected to VCC or GND (or an external pulldown).</p>
<p>So the raw information that describes the 6502 is a set of nodes, for which there is one bit of information, whether it is a pullup node or a neutral node, as well as a set of transistors, which is a three-tuple consisting of gate, c1 and c2.</p>
<p>The file <a href="http://github.com/trebonian/visual6502/raw/master/segdefs.js">segdefs.js</a> in visual6502 contains (next to the polygon information) the node state: &#8220;+&#8221; means pullup, &#8220;-&#8221; (or a missing node description) means neutral. The file <a href="http://github.com/trebonian/visual6502/blob/master/transdefs.js">transdefs.js</a> contains the transistor tuples.</p>
<p>Stripped from irrelevant data, the 6502 description would look like this: The node states:</p>
<pre>
BOOL nodes[] = {
    /*  0 */ 1,
    /*  1 */ 0,
    /*  2 */ 0,
    /*  3 */ 1,
    /*  4 */ 1,
    /*  5 */ 1,
    /*  6 */ 1,
    /*  7 */ 0,
    /*  8 */ 1,
    /*  9 */ 0,
    /* 10 */ 1,
    [...]
}
</pre>
<p>&#8230;and the transistors:</p>
<pre>
struct {
	int gate;
	int c1;
	int c2;
} transistors[] = {
    {357, 558, 217},
    {1608, 657, 349},
    {412, 558, 1146},
    {558, 558, 943},
    {826, 230, 657},
    [...]
}
</pre>
<p>A quick estimate would be 1 bit per node (pullup or neutral), and 3 times 11 bits (3 node numbers from 1 to 1725) per transistor, resulting in about 117 kilobits; but there is still a lot of redundancy in this representation.</p>
<p>The transistor tuples can be represented in a much more compact way. First, there is no ordering for the transistors, so if we sort them by gate, we can encode just the difference between the current gate and the previous gate:</p>
<pre>
struct {
	int gate;
	int c1;
	int c2;
} transistors[] = {
    {1, 890, 558},
    {4, 558, 11},
    {5, 558, 146},
    {6, 558, 282},
    {6, 874, 657},
    {7, 657, 1591},
    {7, 657, 1591},
    {7, 657, 1591},
    {8, 150, 558},
    [...]
}
</pre>
<p>In practice, the difference between two gate nodes in the transistor list is a number between 0 and 4, so we could use 3 bits (instead of 11) for the gate. But in fact, it is enough to store a single bit: The nodes have no order either, so we can renumber them so that all nodes that are connected to a gate of a transistor are numbered from 0, and all nodes that are not connected to gates will be numbered above the ones with gates:</p>
<pre>
struct {
	int gate;
	int c1;
	int c2;
} transistors[] = {
    {0, 890, 558},
    {1, 558, 11},
    {2, 558, 146},
    {3, 558, 282},
    {3, 874, 657},
    {4, 657, 1591},
    {4, 657, 1591},
    {4, 657, 1591},
    {5, 150, 558},
    [...]
}
</pre>
<p>This way, there are no holes in the list of gates &#8211; a new transistor has either the next node number as its gate, or the same one again (i.e. a node is gate of several transistors). It is enough to store a single bit for the gate.</p>
<p>The example above already shows that the nodes 657 and 558 show up a lot: These are VCC and GND, respectively. In fact, 234 transistors connect to VCC, and 2493 connect to GND. We could Huffman-encode the c1 and c2 nodes, but in practice, all other nodes except these two are relatively uniformly distributed, so let&#8217;s just special case them.</p>
<p>There is also no ordering between the two nodes the transistor connects, and no transistor will ever connect VCC/GND to VCC/GND, so we only need to do the special VCC/GND encoding for c1, and leave c2 as it is. Let&#8217;s use a single &#8220;1&#8243; bit to represent GND, &#8220;01&#8243; as VCC, and all other 11 bit node numbers will be prefixed with &#8220;00&#8243;, making them occupy 13 bits.</p>
<p>This way, the 3510 values of c1 can be described in 2493 * 1 (the GNDs) + 234 * 2 (the VCCs) + 783 * (2 + 11) (the others) bits = 13140 bits. The c2 values occupy 3510 * 11 bits = 38610 bits. If you add the bit per transistor for the gate (i.e. 3510 bits), we&#8217;re at 55260 bits for the transistor description.</p>
<p>Using arithmetic coding, we can describe a node number in about 10.75 bits instead of 11. This way, we save (783 + 3510) * 0.25 bits = 1073 bits. The transistor description thus fits into 54187 bits.</p>
<p>As stated previously, we also need one bit per node for the pullup information. About half the nodes are pullup, and we don&#8217;t have the freedom of sorting and renaming the nodes any more (we&#8217;ve done that already for the transistor gates), so we&#8217;ll have to go with the 1725 raw bits.</p>
<p>So the final number is 54187 bits + 1725 bits = 55912 bits. That&#8217;s 6989 bytes, or roughly <b>56 kilobits</b>, and about twice as big as <a href="http://www.bunniestudios.com/blog/?p=353">H1N1</a>.</p>
<p>With this number, we can estimate the complexity of a <a href="http://www.pagetable.com/?p=54">Commodore 64</a> to be about 200 kilobits (CPU, VIC, SID, 2xCIA, PLA) &#8211; plus another 160 kilobits of ROM.</p>
<p>But wait: Did you see the duplicate transistors in the sorted list? Yes, there are some duplicates, in fact, there are only 3288 unique transistors. And when looking at it on a higher level, the 130 entry <a href="http://www.pagetable.com/?p=39">instruction decode ROM</a> has duplicates too: Only 115 are unique, leading to redundant paths in the node/transistor graph. The reason for this redundancy is routing: There are only two dimensions in a computer chip (plus layers), so you cannot just connect anything to anything.</p>
<p>The homework for today, dear reader, is to develop an algorithm that minimizes the description of the 6502 by removing duplicate transistors as well as equivalent paths.</p>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=401&amp;ts=1369319074" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=401</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>CPUID on all CPUs (HOWNOTTO)</title>
		<link>http://www.pagetable.com/?p=372</link>
		<comments>http://www.pagetable.com/?p=372#comments</comments>
		<pubDate>Tue, 14 Sep 2010 09:00:14 +0000</pubDate>
		<dc:creator>Michael Steil</dc:creator>
				<category><![CDATA[puzzle]]></category>
		<category><![CDATA[whines]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=372</guid>
		<description><![CDATA[A while ago, an engineer from a respectable company for low-level solutions (no names without necessity!) claimed that a certain company&#8217;s new 4-way SMP system had broken CPUs or at least broken firmware that didn&#8217;t set up some CPU features correctly: While on the older 2-way system, all CPUs returned the same features (using CPUID), [...]]]></description>
			<content:encoded><![CDATA[<p>A while ago, an engineer from a respectable company for low-level solutions (no names without necessity!) claimed that a certain company&#8217;s new 4-way SMP system had broken CPUs or at least broken firmware that didn&#8217;t set up some CPU features correctly: While on the older 2-way system, all CPUs returned the same features (using CPUID), on the 4-way system, two of the CPUs would return bogus data.</p>
<p>I asked for his test code. It ran in kernel mode and looked roughly like this:</p>
<pre>
    int cpu_features[4];

    for (int i = 0; i < 100000; i++) {
        cpu_features[get_cur_cpu_number()] = cpuid_get_features();
        usleep(100);
    }

    for (int j = 0; j < 4; j++)
        printf("CPU %d features: %x\n", j, cpu_features[j]);
</pre>
<p>Questions to the reader:</p>
<ol>
<li>What was the original idea, what is the algorithm?</li>
<li>Why did this work on a 2-way system, but not on a 4-way system?</li>
<li>Which two changes would at least make this code correct (albeit still horrible)?</li>
<li>How would you do it correctly?</li>
<li>Would you buy software from this company?</li>
</ol>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=372&amp;ts=1369319074" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=372</wfw:commentRss>
		<slash:comments>21</slash:comments>
		</item>
		<item>
		<title>Playstation 3 Hacking &#8211; Linux Is Inevitable</title>
		<link>http://www.pagetable.com/?p=376</link>
		<comments>http://www.pagetable.com/?p=376#comments</comments>
		<pubDate>Tue, 07 Sep 2010 07:45:02 +0000</pubDate>
		<dc:creator>Michael Steil</dc:creator>
				<category><![CDATA[hacks]]></category>
		<category><![CDATA[security]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=376</guid>
		<description><![CDATA[In the talk &#8220;Why Silicon Security is still that hard&#8221; by Felix Domke at the 24th Chaos Communication Congress in 2007 (in which he described how he hacked the Xbox 360, and bushing had a cameo at the end explaining how they hacked the Wii), I had a little part, in which I argued that [...]]]></description>
			<content:encoded><![CDATA[<p>In the talk <a href="http://www.youtube.com/watch?v=XtDTNnEvlf8">&#8220;Why Silicon Security is still that hard&#8221;</a> by <a href="http://debugmo.de/">Felix Domke</a> at the 24th Chaos Communication Congress in 2007 (in which he described how he hacked the Xbox 360, and <a href="http://hackmii.com/">bushing</a> had a cameo at the end explaining how they hacked the Wii), I had a little part, in which I argued that &#8220;Linux Is Inevitable&#8221;: If you lock down a system, it will eventually get hacked. In the light of the recent events happening with PlayStation 3 hacking, let&#8217;s revisit them.</p>
<p>This is the original slide from 2007:</p>
<style type="text/css">
  p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; min-height: 14.0px}
  p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; text-align: center; color: #ffffff}
  p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; text-align: center; color: #ffffff}
  p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; text-align: center; color: #ffffff}
  p.p5 {margin: 0.0px 0.0px 0.0px 0.0px; text-align: center}
  span.s1 {letter-spacing: 0.0px}
  table.t1 {border-collapse: collapse}
  td.td1 {width: 122.5px; height: 36.8px; background-color: #929292}
  td.td2 {width: 36.5px; height: 36.8px; background-color: #929292}
  td.td3 {width: 317.0px; height: 36.8px; background-color: #929292}
  td.td4 {width: 98.0px; height: 36.8px; background-color: #929292}
  td.td5 {width: 70.0px; height: 36.8px; background-color: #929292}
  td.td6 {width: 91.0px; height: 36.8px; background-color: #929292}
  td.td7 {width: 36.5px; height: 36.8px; background-color: #000000}
  td.td8 {width: 70.0px; height: 36.8px; background-color: #f91d18}
  td.td9 {width: 91.0px; height: 36.8px; background-color: #f91d18}
  td.td10 {width: 317.0px; height: 36.8px; background-color: #fa9213}
  td.td11 {width: 98.0px; height: 36.8px; background-color: #fbd00b}
  td.td12 {width: 70.0px; height: 36.8px; background-color: #ffffff}
  td.td13 {width: 317.0px; height: 36.8px; background-color: #fbca0c}
  td.td14 {width: 98.0px; height: 36.8px; background-color: #f94317}
  td.td15 {width: 317.0px; height: 36.8px; background-color: #f96d15}
  td.td16 {width: 98.0px; height: 36.8px; background-color: #fabd0e}
  td.td17 {width: 317.0px; height: 36.8px; background-color: #fbfd01}
  td.td18 {width: 98.0px; height: 36.8px; background-color: #fa9013}
  td.td19 {width: 91.0px; height: 36.8px; background-color: #000000}
  td.td20 {width: 317.0px; height: 36.8px; background-color: #fa9f12}
  td.td21 {width: 317.0px; height: 36.8px; background-color: #fa8614}
  td.td22 {width: 317.0px; height: 36.8px; background-color: #f91d18}
  td.td23 {width: 98.0px; height: 36.8px; background-color: #8d0b08}
  td.td24 {width: 70.0px; height: 36.8px; background-color: #000000}
  td.td25 {width: 317.0px; height: 36.8px; background-color: #fbcd0c}
  td.td26 {width: 98.0px; height: 36.8px; background-color: #fbef04}
  td.td27 {width: 98.0px; height: 36.8px; background-color: #fbfd01}
  td.td28 {width: 70.0px; height: 36.8px; background-color: #929292}
</style>
<table cellspacing="0" cellpadding="3" class="t1" border="1" bordercolor="#0000">
<tbody>
<tr>
<td valign="middle" class="td1">
<p class="p2"><span class="s1"><b>device</b></span></p>
</td>
<td valign="middle" class="td2">
<p class="p2"><span class="s1"><b>y</b></span></p>
</td>
<td valign="middle" class="td3">
<p class="p2"><span class="s1"><b>security</b></span></p>
</td>
<td valign="middle" class="td4">
<p class="p2"><span class="s1"><b>hacked</b></span></p>
</td>
<td valign="middle" class="td5">
<p class="p2"><span class="s1"><b>for</b></span></p>
</td>
<td valign="middle" class="td6">
<p class="p2"><span class="s1"><b>effect</b></span></p>
</td>
</tr>
<tr>
<td valign="middle" class="td1">
<p class="p3"><span class="s1"><b>PS2</b></span></p>
</td>
<td valign="middle" class="td7">
<p class="p4"><span class="s1">1999</span></p>
</td>
<td valign="middle" class="td3">
<p class="p4"><span class="s1">?</span></p>
</td>
<td valign="middle" class="td4">
<p class="p4"><span class="s1">?</span></p>
</td>
<td valign="middle" class="td8">
<p class="p4"><span class="s1">piracy</span></p>
</td>
<td valign="middle" class="td9">
<p class="p4"><span class="s1">-</span></p>
</td>
</tr>
<tr>
<td valign="middle" class="td1">
<p class="p3"><span class="s1"><b>dbox2</b></span></p>
</td>
<td valign="middle" class="td7">
<p class="p4"><span class="s1">2000</span></p>
</td>
<td valign="middle" class="td10">
<p class="p5"><span class="s1">signed kernel</span></p>
</td>
<td valign="middle" class="td11">
<p class="p5"><span class="s1">3 months</span></p>
</td>
<td valign="middle" class="td12">
<p class="p5"><span class="s1">Linux</span></p>
</td>
<td valign="middle" class="td9">
<p class="p4"><span class="s1">pay TV decoding</span></p>
</td>
</tr>
<tr>
<td valign="middle" class="td1">
<p class="p3"><span class="s1"><b>GameCube</b></span></p>
</td>
<td valign="middle" class="td7">
<p class="p4"><span class="s1">2001</span></p>
</td>
<td valign="middle" class="td13">
<p class="p5"><span class="s1">encrypted boot</span></p>
</td>
<td valign="middle" class="td14">
<p class="p5"><span class="s1">12 months</span></p>
</td>
<td valign="middle" class="td12">
<p class="p5"><span class="s1">Homebrew</span></p>
</td>
<td valign="middle" class="td9">
<p class="p4"><span class="s1">piracy</span></p>
</td>
</tr>
<tr>
<td valign="middle" class="td1">
<p class="p3"><span class="s1"><b>Xbox</b></span></p>
</td>
<td valign="middle" class="td7">
<p class="p4"><span class="s1">2001</span></p>
</td>
<td valign="middle" class="td15">
<p class="p5"><span class="s1">encrypted/signed bootup, signed executables</span></p>
</td>
<td valign="middle" class="td16">
<p class="p5"><span class="s1">4 months</span></p>
</td>
<td valign="middle" class="td12">
<p class="p5"><span class="s1">Linux</span></p>
<p class="p5"><span class="s1">Homebrew</span></p>
</td>
<td valign="middle" class="td9">
<p class="p4"><span class="s1">piracy</span></p>
</td>
</tr>
<tr>
<td valign="middle" class="td1">
<p class="p3"><span class="s1"><b>iPod</b></span></p>
</td>
<td valign="middle" class="td7">
<p class="p4"><span class="s1">2001</span></p>
</td>
<td valign="middle" class="td17">
<p class="p5"><span class="s1">checksum</span></p>
</td>
<td valign="middle" class="td18">
<p class="p5"><span class="s1">&lt;12 months</span></p>
</td>
<td valign="middle" class="td12">
<p class="p5"><span class="s1">Linux</span></p>
</td>
<td valign="middle" class="td19">
<p class="p4"><span class="s1">-</span></p>
</td>
</tr>
<tr>
<td valign="middle" class="td1">
<p class="p3"><span class="s1"><b>DS</b></span></p>
</td>
<td valign="middle" class="td7">
<p class="p4"><span class="s1">2004</span></p>
</td>
<td valign="middle" class="td20">
<p class="p5"><span class="s1">signed/encrypted executables</span></p>
</td>
<td valign="middle" class="td16">
<p class="p5"><span class="s1">6 months</span></p>
</td>
<td valign="middle" class="td12">
<p class="p5"><span class="s1">Homebrew</span></p>
</td>
<td valign="middle" class="td9">
<p class="p4"><span class="s1">piracy</span></p>
</td>
</tr>
<tr>
<td valign="middle" class="td1">
<p class="p3"><span class="s1"><b>PSP</b></span></p>
</td>
<td valign="middle" class="td7">
<p class="p4"><span class="s1">2004</span></p>
</td>
<td valign="middle" class="td21">
<p class="p5"><span class="s1">signed bootup/executables</span></p>
</td>
<td valign="middle" class="td11">
<p class="p5"><span class="s1">2 months</span></p>
</td>
<td valign="middle" class="td12">
<p class="p5"><span class="s1">Homebrew</span></p>
</td>
<td valign="middle" class="td9">
<p class="p4"><span class="s1">piracy</span></p>
</td>
</tr>
<tr>
<td valign="middle" class="td1">
<p class="p3"><span class="s1"><b>Xbox 360</b></span></p>
</td>
<td valign="middle" class="td7">
<p class="p4"><span class="s1">2005</span></p>
</td>
<td valign="middle" class="td22">
<p class="p5"><span class="s1">encrypted/signed bootup,encrypted/signed executables, encrypted RAM, hypervisor, eFuses</span></p>
</td>
<td valign="middle" class="td14">
<p class="p5"><span class="s1">12 months</span></p>
</td>
<td valign="middle" class="td12">
<p class="p5"><span class="s1">Linux</span></p>
<p class="p5"><span class="s1">Homebrew</span></p>
</td>
<td valign="middle" class="td9">
<p class="p4"><span class="s1">leaked keys</span></p>
</td>
</tr>
<tr>
<td valign="middle" class="td1">
<p class="p3"><span class="s1"><b>PS3</b></span></p>
</td>
<td valign="middle" class="td7">
<p class="p4"><span class="s1">2006</span></p>
</td>
<td valign="middle" class="td22">
<p class="p5"><span class="s1">encrypted/signed bootup,encrypted/signed executables, hypervisor, eFuses, isolated SPU</span></p>
</td>
<td valign="middle" class="td23">
<p class="p4"><span class="s1">not yet</span></p>
</td>
<td valign="middle" class="td24">
<p class="p4"><span class="s1">-</span></p>
</td>
<td valign="middle" class="td19">
<p class="p4"><span class="s1">-</span></p>
</td>
</tr>
<tr>
<td valign="middle" class="td1">
<p class="p3"><span class="s1"><b>Wii</b></span></p>
</td>
<td valign="middle" class="td7">
<p class="p4"><span class="s1">2006</span></p>
</td>
<td valign="middle" class="td25">
<p class="p5"><span class="s1">encrypted bootup</span></p>
</td>
<td valign="middle" class="td26">
<p class="p5"><span class="s1">1 month</span></p>
</td>
<td valign="middle" class="td12">
<p class="p5"><span class="s1">Linux</span></p>
</td>
<td valign="middle" class="td9">
<p class="p4"><span class="s1">piracy</span></p>
</td>
</tr>
<tr>
<td valign="middle" class="td1">
<p class="p3"><span class="s1"><b>AppleTV</b></span></p>
</td>
<td valign="middle" class="td7">
<p class="p4"><span class="s1">2007</span></p>
</td>
<td valign="middle" class="td17">
<p class="p5"><span class="s1">signed bootloader</span></p>
</td>
<td valign="middle" class="td27">
<p class="p5"><span class="s1">2 weeks</span></p>
</td>
<td valign="middle" class="td12">
<p class="p5"><span class="s1">Linux</span></p>
</td>
<td valign="middle" class="td9">
<p class="p4"><span class="s1">Front Row piracy</span></p>
</td>
</tr>
<tr>
<td valign="middle" class="td1">
<p class="p3"><span class="s1"><b>iPhone</b></span></p>
</td>
<td valign="middle" class="td7">
<p class="p4"><span class="s1">2007</span></p>
</td>
<td valign="middle" class="td3">
<p class="p4"><span class="s1">?</span></p>
</td>
<td valign="middle" class="td27">
<p class="p5"><span class="s1">1 month</span></p>
</td>
<td valign="middle" class="td12">
<p class="p5"><span class="s1">Homebrew</span></p>
<p class="p5"><span class="s1">international</span></p>
</td>
<td valign="middle" class="td9">
<p class="p4"><span class="s1">SIM-Lock revenue</span></p>
</td>
</tr>
</tbody>
</table>
<p>The table shows the relationship between the quality of a device&#8217;s security system and the time it took to hack it, as well as the original motivation for hacking and the side effects (collateral damage) it caused.</p>
<h2>Correlation security/time to hack</h2>
<p>There is a pretty clear correlation betwen the quality of the security system and the time required for hacking it &#8211; with the notable exception being the GameCube, which had rather weak security, but since its release coincided with the much more powerful Xbox, much of the hacker community neglected the GameCube until the Xbox was done. What can also be seen is that recently, devices tend to get hacked more quickly; probably simply because there are more and more people interested in hacking.</p>
<h2>Correlation Linux/time to hack</h2>
<p>The other exception is the PlayStation 3, which was not hacked until about three and a half years after its introduction. I argued that this was because there was only very little motivation to hack it: Sony shipped the devices with the &#8220;Other OS&#8221; option and even sponsored a port of Linux to it, allowing any user to install Linux if they wanted. Although Linux was running on top of a hypervisor and did not have access to all of the features of the device, it seems to have been enough to take the enough motivation to hack it out of the hacker community.</p>
<h2>Linux/homebrew is the primary motivation</h2>
<p>This is supported by the by the fact that the motivation for hacking every system in the table was either homebrew (i.e. running unautorized hobbyist applications) or Linux. Hackers seem to love to convert their devices into Linux computers to run a big library of existing software, or to hack the device to make it possible to run versions of existing emulators and games on the native OS.</p>
<h2>Piracy is a side effect</h2>
<p>None of the hacks in the table was done with the motivation to allow running copied games &#8211; but whenever the point of the security system was to prevent piracy, hacking it inevitably enabled piracy as a side effect. Some security systems protected other things like pay TV keys and SIM-locks; these also fell as side effects.</p>
<h2>2010 update</h2>
<p>In September 2009, Sony started shipping the &#8220;slim&#8221; model of the PlayStation 3, with the &#8220;Other OS&#8221; feature removed. With firmware 3.21 in April 2010, the feature was also <a href="http://blog.us.playstation.com/2009/08/27/it-only-does-everything/">removed</a> from existing original models that users chose to upgrade &#8211; which was required for using any of the online features. The missing &#8220;Other OS&#8221; feature on the slim model motivated George Hotz (geohot) to hack into hypervisor mode (Jan 2010), but this approach did not lead to a working hack of the security system. In August 2010, the Australian company OzMods announced the commercial &#8220;PSJailbreak&#8221; USB dongle that hacks into non-hypervisor mode, allowing piracy and homebrew (&#8220;Backup Manager&#8221; says &#8220;backups and homebrew&#8221;).</p>
<p>Although this is the first time that a commercial company is first to hack a system, and the first time that piracy seems to have been a key motivation, removal of &#8220;Other OS&#8221; might have been another motivation, and geohot&#8217;s previous attempts might have helped as an entry point for this hack.</p>
<p>Usually, an open hacker community develops a hack, and commercial companies convert them into modchips. This time, a company developed a hack and a modchip, and the community reverse engineered it and ported the exploit code onto several other devices, allowing people to hack the PlayStation 3 without a dedicated device. And I&#8217;m sure Linux will be adapted soon to run in the new environment.</p>
<h2>Conclusion</h2>
<p>What do we learn from this? Linux is inevitable. Or maybe it should be &#8220;Homebrew is inevitable&#8221;. In the history of mankind, there has yet to be a popular system that is locked down to only allow certain software to run, but does not get hacked to run arbitrary code. I still dare to say that if Sony had not removed &#8220;Other OS&#8221;, the PlayStation 3 would have been the first system to not get hacked. At all.</p>
<p>(Here is an updated 2010 version of the table:)</p>
<table cellspacing="0" cellpadding="3" class="t1" border="1" bordercolor="#0000">
<tbody>
<tr>
<td valign="middle" class="td1">
<p class="p2"><span class="s1"><b>device</b></span></p>
</td>
<td valign="middle" class="td2">
<p class="p2"><span class="s1"><b>y</b></span></p>
</td>
<td valign="middle" class="td3">
<p class="p2"><span class="s1"><b>security</b></span></p>
</td>
<td valign="middle" class="td4">
<p class="p2"><span class="s1"><b>hacked</b></span></p>
</td>
<td valign="middle" class="td5">
<p class="p2"><span class="s1"><b>for</b></span></p>
</td>
<td valign="middle" class="td6">
<p class="p2"><span class="s1"><b>effect</b></span></p>
</td>
</tr>
<tr>
<td valign="middle" class="td1">
<p class="p3"><span class="s1"><b>PS2</b></span></p>
</td>
<td valign="middle" class="td7">
<p class="p4"><span class="s1">1999</span></p>
</td>
<td valign="middle" class="td3">
<p class="p4"><span class="s1">?</span></p>
</td>
<td valign="middle" class="td4">
<p class="p4"><span class="s1">?</span></p>
</td>
<td valign="middle" class="td8">
<p class="p4"><span class="s1">piracy</span></p>
</td>
<td valign="middle" class="td9">
<p class="p4"><span class="s1">-</span></p>
</td>
</tr>
<tr>
<td valign="middle" class="td1">
<p class="p3"><span class="s1"><b>dbox2</b></span></p>
</td>
<td valign="middle" class="td7">
<p class="p4"><span class="s1">2000</span></p>
</td>
<td valign="middle" class="td10">
<p class="p5"><span class="s1">signed kernel</span></p>
</td>
<td valign="middle" class="td11">
<p class="p5"><span class="s1">3 months</span></p>
</td>
<td valign="middle" class="td12">
<p class="p5"><span class="s1">Linux</span></p>
</td>
<td valign="middle" class="td9">
<p class="p4"><span class="s1">pay TV decoding</span></p>
</td>
</tr>
<tr>
<td valign="middle" class="td1">
<p class="p3"><span class="s1"><b>GameCube</b></span></p>
</td>
<td valign="middle" class="td7">
<p class="p4"><span class="s1">2001</span></p>
</td>
<td valign="middle" class="td13">
<p class="p5"><span class="s1">encrypted boot</span></p>
</td>
<td valign="middle" class="td14">
<p class="p5"><span class="s1">12 months</span></p>
</td>
<td valign="middle" class="td12">
<p class="p5"><span class="s1">Homebrew</span></p>
</td>
<td valign="middle" class="td9">
<p class="p4"><span class="s1">piracy</span></p>
</td>
</tr>
<tr>
<td valign="middle" class="td1">
<p class="p3"><span class="s1"><b>Xbox</b></span></p>
</td>
<td valign="middle" class="td7">
<p class="p4"><span class="s1">2001</span></p>
</td>
<td valign="middle" class="td15">
<p class="p5"><span class="s1">encrypted/signed bootup, signed executables</span></p>
</td>
<td valign="middle" class="td16">
<p class="p5"><span class="s1">4 months</span></p>
</td>
<td valign="middle" class="td12">
<p class="p5"><span class="s1">Linux</span></p>
<p class="p5"><span class="s1">Homebrew</span></p>
</td>
<td valign="middle" class="td9">
<p class="p4"><span class="s1">piracy</span></p>
</td>
</tr>
<tr>
<td valign="middle" class="td1">
<p class="p3"><span class="s1"><b>iPod</b></span></p>
</td>
<td valign="middle" class="td7">
<p class="p4"><span class="s1">2001</span></p>
</td>
<td valign="middle" class="td17">
<p class="p5"><span class="s1">checksum</span></p>
</td>
<td valign="middle" class="td18">
<p class="p5"><span class="s1">&lt;12 months</span></p>
</td>
<td valign="middle" class="td12">
<p class="p5"><span class="s1">Linux</span></p>
</td>
<td valign="middle" class="td19">
<p class="p4"><span class="s1">-</span></p>
</td>
</tr>
<tr>
<td valign="middle" class="td1">
<p class="p3"><span class="s1"><b>DS</b></span></p>
</td>
<td valign="middle" class="td7">
<p class="p4"><span class="s1">2004</span></p>
</td>
<td valign="middle" class="td20">
<p class="p5"><span class="s1">signed/encrypted executables</span></p>
</td>
<td valign="middle" class="td16">
<p class="p5"><span class="s1">6 months</span></p>
</td>
<td valign="middle" class="td12">
<p class="p5"><span class="s1">Homebrew</span></p>
</td>
<td valign="middle" class="td9">
<p class="p4"><span class="s1">piracy</span></p>
</td>
</tr>
<tr>
<td valign="middle" class="td1">
<p class="p3"><span class="s1"><b>PSP</b></span></p>
</td>
<td valign="middle" class="td7">
<p class="p4"><span class="s1">2004</span></p>
</td>
<td valign="middle" class="td21">
<p class="p5"><span class="s1">signed bootup/executables</span></p>
</td>
<td valign="middle" class="td11">
<p class="p5"><span class="s1">2 months</span></p>
</td>
<td valign="middle" class="td12">
<p class="p5"><span class="s1">Homebrew</span></p>
</td>
<td valign="middle" class="td9">
<p class="p4"><span class="s1">piracy</span></p>
</td>
</tr>
<tr>
<td valign="middle" class="td1">
<p class="p3"><span class="s1"><b>Xbox 360</b></span></p>
</td>
<td valign="middle" class="td7">
<p class="p4"><span class="s1">2005</span></p>
</td>
<td valign="middle" class="td22">
<p class="p5"><span class="s1">encrypted/signed bootup,encrypted/signed executables, encrypted RAM, hypervisor, eFuses</span></p>
</td>
<td valign="middle" class="td14">
<p class="p5"><span class="s1">12 months</span></p>
</td>
<td valign="middle" class="td12">
<p class="p5"><span class="s1">Linux</span></p>
<p class="p5"><span class="s1">Homebrew</span></p>
</td>
<td valign="middle" class="td9">
<p class="p4"><span class="s1">leaked keys</span></p>
</td>
</tr>
<tr>
<td valign="middle" class="td1">
<p class="p3"><span class="s1"><b>PS3</b></span></p>
</td>
<td valign="middle" class="td7">
<p class="p4"><span class="s1">2006</span></p>
</td>
<td valign="middle" class="td22">
<p class="p5"><span class="s1">encrypted/signed bootup,encrypted/signed executables, hypervisor, eFuses, isolated SPU</span></p>
</td>
<td valign="middle" class="td23">
<p class="p4"><span class="s1">4 years</span></p>
</td>
<td valign="middle" class="td28">
<p class="p4"><span class="s1">Piracy</span></p>
<p class="p4"><span class="s1">Homebrew</span></p>
</td>
<td valign="middle" class="td19">
<p class="p4"><span class="s1">-</span></p>
</td>
</tr>
<tr>
<td valign="middle" class="td1">
<p class="p3"><span class="s1"><b>Wii</b></span></p>
</td>
<td valign="middle" class="td7">
<p class="p4"><span class="s1">2006</span></p>
</td>
<td valign="middle" class="td25">
<p class="p5"><span class="s1">encrypted bootup</span></p>
</td>
<td valign="middle" class="td26">
<p class="p5"><span class="s1">1 month</span></p>
</td>
<td valign="middle" class="td12">
<p class="p5"><span class="s1">Linux</span></p>
</td>
<td valign="middle" class="td9">
<p class="p4"><span class="s1">piracy</span></p>
</td>
</tr>
<tr>
<td valign="middle" class="td1">
<p class="p3"><span class="s1"><b>AppleTV</b></span></p>
</td>
<td valign="middle" class="td7">
<p class="p4"><span class="s1">2007</span></p>
</td>
<td valign="middle" class="td17">
<p class="p5"><span class="s1">signed bootloader</span></p>
</td>
<td valign="middle" class="td27">
<p class="p5"><span class="s1">2 weeks</span></p>
</td>
<td valign="middle" class="td12">
<p class="p5"><span class="s1">Linux</span></p>
</td>
<td valign="middle" class="td9">
<p class="p4"><span class="s1">Front Row piracy</span></p>
</td>
</tr>
<tr>
<td valign="middle" class="td1">
<p class="p3"><span class="s1"><b>iPhone</b></span></p>
</td>
<td valign="middle" class="td7">
<p class="p4"><span class="s1">2007</span></p>
</td>
<td valign="middle" class="td21">
<p class="p5"><span class="s1">signed/encrypted bootup/executables</span></p>
</td>
<td valign="middle" class="td27">
<p class="p5"><span class="s1">11 days</span></p>
</td>
<td valign="middle" class="td12">
<p class="p5"><span class="s1">Homebrew</span></p>
<p class="p5"><span class="s1">SIM-Lock</span></p>
</td>
<td valign="middle" class="td9">
<p class="p4"><span class="s1">piracy</span></p>
</td>
</tr>
<tr>
<td valign="middle" class="td1">
<p class="p3"><span class="s1"><b>iPad</b></span></p>
</td>
<td valign="middle" class="td7">
<p class="p4"><span class="s1">2010</span></p>
</td>
<td valign="middle" class="td21">
<p class="p5"><span class="s1">signed/encrypted bootup/executables</span></p>
</td>
<td valign="middle" class="td27">
<p class="p5"><span class="s1">1 day</span></p>
</td>
<td valign="middle" class="td12">
<p class="p5"><span class="s1">Homebrew</span></p>
<p class="p5"><span class="s1"></span></p>
</td>
<td valign="middle" class="td9">
<p class="p4"><span class="s1">piracy</span></p>
</td>
</tr>
</tbody>
</table>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=376&amp;ts=1369319074" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=376</wfw:commentRss>
		<slash:comments>51</slash:comments>
		</item>
		<item>
		<title>Why is there no CR1 &#8211; and why are control registers such a mess anyway?</title>
		<link>http://www.pagetable.com/?p=364</link>
		<comments>http://www.pagetable.com/?p=364#comments</comments>
		<pubDate>Sat, 03 Jul 2010 05:43:40 +0000</pubDate>
		<dc:creator>Michael Steil</dc:creator>
				<category><![CDATA[archeology]]></category>
		<category><![CDATA[trivia]]></category>
		<category><![CDATA[whines]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=364</guid>
		<description><![CDATA[If you want to enable protected mode or paging on the i386/x86_64 architecture, you use CR0, which is short for control register 0. Makes sense. These are important system settings. But if you want to switch the pagetable format, you have to change a bit in CR4 (CR1 does not exist and CR2 and CR3 [...]]]></description>
			<content:encoded><![CDATA[<p>If you want to enable protected mode or paging on the i386/x86_64 architecture, you use CR0, which is short for control register 0. Makes sense. These are important system settings. But if you want to switch the pagetable format, you have to change a bit in CR4 (CR1 does not exist and CR2 and CR3 don&#8217;t hold control bits), if you want to switch to 64 bit mode, you have to change a bit in an MSR, oh, and if you want to turn on single stepping, that&#8217;s actually in your FLAGS. Also, have I mentioned that CR5 through CR15 don&#8217;t exist &#8211; except for CR8, of course?</p>
<p>Like many (but unfortunately not all) quirks of the i386/x86_64 architecture, this mess can be explained with history.</p>
<h2>8086 &#8211; FLAGS</h2>
<p>x86 history typically starts with the 16 bit 8086, but although it was not binary compatible with its predecessor, it was nevertheless a rather straightforward assembly-level compatible 16 bit extension of the 8 bit Intel 8080 with some ideas of the Zilog Z80. The 8086 is still a classic &#8220;home computer class&#8221; CPU, which was not meant for modern operating systems: It had no MMU of any kind, and no concept of privileged and unpriviliged modes. Therefore, control bits that we see as system state today were encoded into the 16 bit FLAGS register: The interrupt enable bit and the trap flag (which will cause a software interrupt after the next instruction and thus lets you single-step) are encoded into FLAGS right next to the ALU&#8217;s flags like Zero and Carry.</p>
<h2>80286 &#8211; Machine Status Word</h2>
<p>The 80286 then came with a simple form of memory management that allowed more sophisticated (but not yet &#8220;modern&#8221;) operating systems to run &#8211; like the original versions of OS/2. The 16 bit &#8220;Machine Status Word&#8221; was created to host the big switch between legacy mode (real mode) and the new memory-managed mode (protected mode) and a program could access it using the new instructions &#8220;lmsw&#8221; and &#8220;smsw&#8221;. The 80286 had more system state than just this bit: The GDT, the IDT and the TSS had its own registers and dedicated instructions to access them (&#8220;lgdt&#8221;/&#8221;sgdt&#8221;, &#8220;lidt&#8221;/&#8221;sidt&#8221;, &#8220;ltr&#8221;/&#8221;str&#8221;)</p>
<h2>i386 &#8211; Control Registers</h2>
<p>The i386 finally had a real MMU that allowed paging and thus modern operating systems. The MMU required two more registers in the system state, one for the base address of the pagetables, and one to read a fault address from. Intel decided against adding more special purpose registers with dedicated accessor instructions, but instead introduced eight indexed 32 bit wide &#8220;control registers&#8221; CR0 to CR7. The new accessors &#8220;mov cr<i>n</i>, <i>r32</i>&#8220;/&#8221;mov <i>r32</i>, cr<i>n</i>&#8221; allowed copying between registers and control registers and had the 3 bit CR index encoded in the opcode.</p>
<p>The old MSW was also wired into the lower 16 bits of CR0; but CR0 was also extended with new bits like the switch to turn on paging. CR1 was kept reserved, presumably as a second control register for miscellaneous control bits, and CR2 and CR3 were used for the aforementioned fault address and pagetable base pointer. The opcodes to access reserved control registers generated an &#8220;invalid opcode&#8221; fault, making it possible for Intel to reuse the opcodes later if they don&#8217;t use the control registers.</p>
<h2>i486 &#8211; CR4</h2>
<p>The i486 added a few more control bits, and some of them went into CR0. But instead of overflowing the new bits into CR1, Intel decided to skip it and open up CR4 instead &#8211; for unknown reasons.</p>
<h2>Pentium &#8211; MSRs</h2>
<p>On the Pentium, Intel added for the first time control bits that were a property of the implementation as opposed to the architecture, i.e. bits that are microarchitecture-specific and will therefore only work on certain CPUs and not necessarily be supported on later CPUs &#8211; like caching details and debug settings. In order not to waste the valuable CR space with throw-away control bits, Intel introduced the Model-specific Registers (MSRs). The MSR address space is 32 bits, and every MSR is 64 bits wide. The two new instructions &#8220;rdmsr&#8221; and &#8220;wrmsr&#8221; copy between an ECX-indexed MSR and the EDX:EAX registers.</p>
<h2>Pentium II &#8211; SYSENTER MSR</h2>
<p>The SYSENTER instruction that got introduced on the on the Pentium II is a fast way to switch between unprivileged and privileged mode. Instead of looking up the destination segment, instruction pointer and stack pointer in memory, the CPU holds this information in three special-purpose system registers. CR space is valuable, so Intel decided against filling up CR5, CR6 and CR7, so they put it into the MSR address space instead &#8211; at 0&#215;174 through 0&#215;176. This was practically an abuse of the MSR concept.</p>
<h2>AMD K6 &#8211; EFER MSR</h2>
<p>Who can blame AMD for doing similar things then? With the K6, which was introduced at the same time as the Pentium II, AMD diverged from just copying Intel for the first time and actually added features of their own: They added the SYSCALL instruction, and with it, a control bit that turns it on and off, and an extra control register with the target location. Being afraid to collide with Intel extensions they they didn&#8217;t know about, they put the extra system registers into the MSR space: the control register &#8220;EFER&#8221; (Extended Feature Enable Register) at 0xC000_0080 and the Syscall Target Register (STAR) at 0xC000_0081. Intel had been nicely lining up MSRs counting up from 0, so AMD decided to start counting at 0xC000_0080. Understandable as this is, it is basically the same abuse of the MSR concept as Intel&#8217;s with SYSENTER.</p>
<p>A very similar thing happened in the CPUID space, by the way: While Intel encoded all its feature bits in leaf 0x0000_0001, AMD defined leaf 0x8000_0001 for its features.</p>
<h2>x86_64 &#8211; Chaos!</h2>
<p>So far everything looked like it was getting a little more controlled. Both Intel and AMD are only adding new control registers in the MSR space, and since this is a big address space and AMD and Intel extend it on rather opposite locations, it all looks nicer. But then came x86_64: For the first time, Intel was copying a feature that AMD introduced, and it needed to be compatible with all its details. AMD had encoded the availibility of x86_64 in its own CPUID leaf in 0x8000_0001, so Intel had to support this leaf as well. And since Long Mode was turned on in the EFER MSR, Intel had to support an MSR in the AMD space of 0xC000_0000. Long mode also required supporting SYSCALL, so Intel also supported the STAR MSR.</p>
<p>Since x86_64 introduced the REX prefix to double the number of available general-purpose registers, AMD decided to allow this prefix also for &#8220;mov cr&#8221;, doubling the number of control registers and therefore introducing CR8 through CR15 &#8211; also doubling their width. And since AMD introduced them, they owned them, and decided to use CR8 for the &#8220;Task Priority Register&#8221; feature.</p>
<h2>VMX and SVM</h2>
<p>The architecture is messy, sure, but does it matter? Maybe not&#8230; as long as CPUs didn&#8217;t have virtualization extensions! Both Intel VMX and AMD SVM are designed so that they can automatically switch the complete privileged machine state including control registers and certain MSRs. Intel for example special cases CR0, CR3, CR4 and CR8, leaves CR2 to the user. AMD on the other hand has 16 fields for all CRs in its switcher. And because of the two different starting points of the MSR space, Intel VMX required a whitelist bitmap for 8192 MSRs starting at 0x0000_0000 and for another 8192 MSRs starting at 0xC000_0000 &#8211; and of course SYSENTER_CS, EFER, STAR and friends are special-cased. If you want to have a lot of fun, read the VMCS layout reference of Intel&#8217;s manual 3B!</p>
<h2>Future?</h2>
<ul>
<li>CR1 and CR5 to CR7 are still &#8220;owned&#8221; by Intel. AMD has shown that they don&#8217;t want to use them &#8211; and even Intel has not added a control register since 1989.</li>
<li>CR9 through CR15 are technically owned by AMD, since they introduced them with x86_64 and decided to use CR8. Intel adopted the reserved ones when adopting x86_64, but it is unlikely that Intel will ever adopt smaller changes to the architecture from AMD, and AMD is unlikely to use them if they won&#8217;t be part of the architecture, so these will probably never be used either. On the other hand, AMD added these to the auto-switcher list of their SVM Virtual Machine Control Block (VMCB), showing that they haven&#8217;t given up on them yet.</li>
<li>The MSR space is properly de-facto partitioned. Intel continues adding MSRs at 0 and AMD at 0xC000_0000 &#8211; but MSR have already lost their model-specificness in 1997. MSRs are the new CRs.</li>
</ul>
<p>Dear Intel, dear AMD: I like the control registers, and I hate to see them wasted. Why don&#8217;t you finally define CR1 and give it a few control bits in the future? If you&#8217;re scared about collisions, I will be happy to be the arbiter. Ah, whatever: Intel, you get to define all even bits in CR1, and AMD, you get to define all odd bits. Okay? Cool.</p>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=364&amp;ts=1369319074" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=364</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>High-Res Pictures of a MOS KIM-1</title>
		<link>http://www.pagetable.com/?p=359</link>
		<comments>http://www.pagetable.com/?p=359#comments</comments>
		<pubDate>Tue, 29 Jun 2010 06:10:25 +0000</pubDate>
		<dc:creator>Michael Steil</dc:creator>
				<category><![CDATA[6502]]></category>
		<category><![CDATA[archeology]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=359</guid>
		<description><![CDATA[The MOS KIM-1 is a quite rare collector&#8217;s item today. So if you hold one in your hands, you better take some high resolution pictures of the board. Here they are: Note that this is the original revision of the board (pre-Rev A), and the 6502 CPU is from week 51 of the year 1975 [...]]]></description>
			<content:encoded><![CDATA[<p>The <a href="http://en.wikipedia.org/wiki/KIM-1">MOS KIM-1</a> is a quite rare collector&#8217;s item today. So if you hold one in your hands, you better take some high resolution pictures of the board. Here they are:</p>
<p><a href="docs/kim1_board/kim1_front.jpg"><img src="docs/kim1_board/small_kim1_front.jpg"></a><a href="docs/kim1_board/kim1_back.jpg"><img src="docs/kim1_board/small_kim1_back.jpg"></a></p>
<p>Note that this is the original revision of the board (pre-Rev A), and the 6502 CPU is from week 51 of the year 1975 &#8211; so it has the <a href="http://www.pagetable.com/?p=45">ROR bug</a>!</p>
<p>Does anyone know what the three digit numbers 002 and 003 on the 6530 RIOTs mean? Are these the indexes of the ROM images? If so, what is ROM #001 and was there a #000? Also, the back has the number &#8220;0372&#8243; on it &#8211; is this a serial number? Looking at the dates of the chips, this seems to be the oldest KIM-1 of all those I could find on the internet.</p>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=359&amp;ts=1369319074" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=359</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>How much change is in a vending machine?</title>
		<link>http://www.pagetable.com/?p=353</link>
		<comments>http://www.pagetable.com/?p=353#comments</comments>
		<pubDate>Thu, 24 Jun 2010 03:56:25 +0000</pubDate>
		<dc:creator>Michael Steil</dc:creator>
				<category><![CDATA[hacks]]></category>
		<category><![CDATA[puzzle]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=353</guid>
		<description><![CDATA[There is only one way to find out &#8211; all you need is a giant pile of money and a vending machine that sells soda for $1.25: If you put in a dollar note and press the &#8220;return change&#8221; button, you will get the dollar note back directly. If you put in two dollar notes [...]]]></description>
			<content:encoded><![CDATA[<p>There is only one way to find out &#8211; all you need is <a href="http://www.pagetable.com/?p=149">a giant pile of money</a> and a vending machine that sells soda for $1.25: If you put in a dollar note and press the &#8220;return change&#8221; button, you will get the dollar note back directly. If you put in two dollar notes (the maximum it takes) at a time, it will give you change for the two dollars.</p>
<p>Our machine had $29 of change. It started out with 25&cent; coins, and after a while returned a combination of different coins (25&cent; &amp; 10&cent;, then 10&cent; &amp; 5&cent;), finally switching to all 5&cent; coins at the end.</p>
<p>In total, it had</p>
<ul>
<li>25&cent; x 57 = $14.25</li>
<li>10&cent; x 114 = $11.40</li>
<li>5&cent; x 67= $3.35</li>
</ul>
<p>After this, the machine refused to take bills, so it was either full with bills or, more likely, out of change.</p>
<p>But actually, it might still contain up to 95&cent; of change &#8211; today&#8217;s homework is to find out how to measure the remaining change in the machine!</p>
<p><img src="/docs/change/change.jpg"></p>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=353&amp;ts=1369319074" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=353</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>Intel VT VMCS Layout</title>
		<link>http://www.pagetable.com/?p=348</link>
		<comments>http://www.pagetable.com/?p=348#comments</comments>
		<pubDate>Mon, 24 May 2010 21:58:24 +0000</pubDate>
		<dc:creator>Michael Steil</dc:creator>
				<category><![CDATA[whines]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=348</guid>
		<description><![CDATA[I understand that there might be a good reason for Intel to add virtualization extensions to their CPU architecture. Instead of fixing the x86 architecture to (optionally) make it Popek-Goldberg compliant and have all critial instructions trap if not run in Ring 0, they added non-root mode, a very big hammer that allows me to [...]]]></description>
			<content:encoded><![CDATA[<p>I understand that there might be a good reason for Intel to add virtualization extensions to their CPU architecture. Instead of fixing the x86 architecture to (optionally) make it Popek-Goldberg compliant and have all critial instructions trap if not run in Ring 0, they added non-root mode, a very big hammer that allows me to switch my CPU state completely to that of the guest and switches back to my original host state on a certain event in the guest. Well, it&#8217;s a great toy for people who want to play with CPU internals.</p>
<p>Therefore Intel had to add the VMCS, a 4 KB block in memory that holds the complete CPU state of both the host and the guest (segment registers, GDT and IDT pointer, certain MSRs etc.) as well as some control bits (for example, when to exit).</p>
<p>I also understand that Intel doesn&#8217;t allow me to just read and write memory in the VMCS, but abstracts accessing the virtualization state using a vmread/vmwrite interface. This way, the actual layout of this 4 KB page is an implementation detail and can be changed on later CPUs. It also allows for field indexes that are more spread out and encode what kind of field it is.</p>
<p>So I understand very well why Intel encodes into the VMCS field index whether it&#8217;s a control field (0), a read-only field (1), part of the guest state (2) or part of the host state (3), and whether it&#8217;s a 16 bit (0), 32 bit (2), 64 bit (1) or native-sized (3) field. This way, for example, all 16 bit guest state fields (like the guest&#8217;s CS) have indexes starting at 0&#215;0800, and all 64 bit host state fields (like the hosts&#8217;s EFER MSR) start at 0x2C00.</p>
<p>Now what I don&#8217;t understand is what is so hard to be consistent with this convention (Intel Manual 3B, Appendix H).</p>
<ul>
<li><b>VMCS Link Pointer</b> (0&#215;2800): In the first revision of VT, it had already been already decided that there should be a mechanism for having a second 4 KB page in case later versions of VT need more than 4 KB of state. For this, there is there &#8220;VMCS Link Pointer&#8221;, which is a 64 bit physical address. Guess what category this belongs to? Guest state.</li>
<li><b>&#8220;Guest Address Space Size&#8221; bit in the &#8220;VM Entry Controls&#8221; Field</b> (0&#215;4012): This is clearly guest state and not a control field.</li>
<li><b>&#8220;Host Address Space Size&#8221; bit in the &#8220;VM Exit Controls&#8221; Field</b> (0x400C): This is clearly host state and not a control field.</li>
<li><b>VMX-preemption timer value</b> (0x482E): This timer controls after how many ticks execution of the guest should end and control should be returned to the hypervisor. Intel put this into the &#8220;guest state&#8221; bucket: All other guest state fields are properties of the i386/x86_64 architecture that need to be switched, but not this one. This should really be a control field.</li>
</ul>
<p>And here is another favorite of mine: the &#8220;Primary Execution Controls&#8221; field. The 32 bits specify which events in the guest will exit guest execution and trap into the hypervisor (Table 21-6). These events are, among others:</p>
<ul>
<li>exit on HLT</li>
<li>exit on INVLPG</li>
<li>exit on MOV CR3</li>
<li>exit on PAUSE</li>
</ul>
<p>Setting these bits to 1 enables the traps. So if you set all bits to 0, you basically have an unrestricted guest, and if you set all bits to 1, you have the most controlled guest, and you get a notification about every event in the guest. Or so you might think. Actually, there are two bits in the field that don&#8217;t work like this:</p>
<ul>
<li>Use MSR bitmaps</li>
<li>Use I/O bitmaps</li>
</ul>
<p>If these bits are set to 1, it checks a whitelist whether a certain MSR or I/O access is possible. If they are set to 0, all MSR and I/O accesses trap. Compared to all other bits, that&#8217;s backwards. Oh great.</p>
<p>Since Steve Jobs seems to be happy to explain his personal opinion on everything lately, I wrote him an email asking him about this, and he replied:</p>
<pre>
Return-path: &lt;sjobs@apple.com&gt;
Received: from bulkin002-bge351000.mac.com ([unknown] [10.150.69.129])
 by ms231.mac.com
 (Sun Java(tm) System Messaging Server 7u3-12.01 64bit (built Oct 15 2009))
 with ESMTP id &lt;0L2X00HTAZ3Q6GF1@ms231.mac.com&gt; for XXX@mac.com; Mon,
 24 May 2010 13:47:50 -0700 (PDT)
Original-recipient: rfc822;XXX@mac.com
Received: from relay13.apple.com ([17.128.113.29])
 by bulkin002.mac.com (Sun Java(tm) System Messaging Server 6.3-7.02 (built Jun
 27 2008; 32bit)) with ESMTP id &lt;0L2X001EVZ3QKED0@bulkin002.mac.com&gt; for
 XXX@mac.com (ORCPT XXX@mac.com); Mon, 24 May 2010 13:47:50 -0700 (PDT)
X-AuditID: 1180721d-b7c17fe00000693e-19-4bfae5f6545a
Received: from [17.201.27.84]
	(using TLS with cipher AES128-SHA (AES128-SHA/128 bits))
	(Client did not present a certificate)	by relay13.apple.com (Apple SCV relay)
 with SMTP id DB.14.26942.6F6EAFB4; Mon, 24 May 2010 13:47:50 -0700 (PDT)
From: Steve Jobs &lt;sjobs@apple.com&gt;
Content-type: text/plain
Content-transfer-encoding: 7bit
Subject: Re: Intel VT VMCS Layout
Date: Mon, 24 May 2010 13:47:48 -0700
Message-id: &lt;3E789F1B-7E13-FFD2-80F6-8E8D4CDDE7FB@apple.com&gt;
To: Michael Steil &lt;XXX@mac.com&gt;
MIME-version: 1.0 (Apple Message framework v1077)
X-Mailer: Apple Mail (2.1077)
X-Brightmail-Tracker: AAAAAQAAAZE=

The whole VMCS is a big mess, I hate it.

&gt; Hi Steve, what do you think about the ordering of the VMCS fields in
&gt; Intel's VT extenions?
&gt;
&gt;   Michael
</pre>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=348&amp;ts=1369319074" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=348</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Michael Steil rocks</title>
		<link>http://www.pagetable.com/?p=340</link>
		<comments>http://www.pagetable.com/?p=340#comments</comments>
		<pubDate>Wed, 05 May 2010 04:19:37 +0000</pubDate>
		<dc:creator>Michael Steil</dc:creator>
				<category><![CDATA[hacks]]></category>
		<category><![CDATA[puzzle]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=340</guid>
		<description><![CDATA[Google is always right. Exercise for the reader: Change it.]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.google.com/search?q=michael+steil+rocks">Google</a> is always right.</p>
<p><img src="/docs/michael_steil_rocks/michael_steil_rocks.png"></p>
<p>Exercise for the reader: Change it.</p>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=340&amp;ts=1369319074" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=340</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Microsoft vs. Standards</title>
		<link>http://www.pagetable.com/?p=333</link>
		<comments>http://www.pagetable.com/?p=333#comments</comments>
		<pubDate>Fri, 23 Apr 2010 03:04:29 +0000</pubDate>
		<dc:creator>Michael Steil</dc:creator>
				<category><![CDATA[puzzle]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=333</guid>
		<description><![CDATA[Here is a fun game for long car rides: One person names a respected standard implemented by dozens of IT companies, and the other person names Microsoft&#8217;s competing technology. Example: MPEG Audio (MP3/AAC) &#8211; Windows Media Audio. (When you have run out of examples, you can try this game with other major players in the [...]]]></description>
			<content:encoded><![CDATA[<p>Here is a fun game for long car rides: One person names a respected standard implemented by dozens of IT companies, and the other person names Microsoft&#8217;s competing technology. Example: MPEG Audio (MP3/AAC) &#8211; Windows Media Audio.</p>
<p>(When you have run out of examples, you can try this game with other major players in the IT business.)</p>
<p>Let&#8217;s play this game in the comments to this blog entry: Just add as many of these pairs that you can think of &#8211; extra points if Microsoft&#8217;s technology has a closed specification.</p>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=333&amp;ts=1369319074" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=333</wfw:commentRss>
		<slash:comments>34</slash:comments>
		</item>
		<item>
		<title>Who invented the computer?</title>
		<link>http://www.pagetable.com/?p=330</link>
		<comments>http://www.pagetable.com/?p=330#comments</comments>
		<pubDate>Tue, 20 Apr 2010 19:24:02 +0000</pubDate>
		<dc:creator>Michael Steil</dc:creator>
				<category><![CDATA[archeology]]></category>
		<category><![CDATA[trivia]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=330</guid>
		<description><![CDATA[In 1837, Charles Babbage designed a general purpose computer, the Analytical Engine, but never built it. Between 1934 and 1937, Church, Turing et al. defined the general purpose computer, but didn&#8217;t design one. In 1941, Konrad Zuse built the first general purpose computer, the Z3, but didn&#8217;t know it was general purpose and didn&#8217;t use [...]]]></description>
			<content:encoded><![CDATA[<ul>
<li>In 1837, Charles Babbage designed a general purpose computer, the <a href="http://en.wikipedia.org/wiki/Analytical_engine">Analytical Engine</a>, but never built it.</li>
<li>Between 1934 and 1937, Church, Turing et al. <a href="http://en.wikipedia.org/wiki/Church-Turing_thesis">defined</a> the general purpose computer, but didn&#8217;t design one.</li>
<li>In 1941, Konrad Zuse built the first general purpose computer, the <a href="http://en.wikipedia.org/wiki/Z3_(computer)">Z3</a>, but <a href="http://www.zib.de/zuse/Inhalt/Kommentare/Html/0684/universal2.html">didn&#8217;t know</a> it was general purpose and didn&#8217;t use it that way.</li>
<li>From 1943 to 1946, Mauchly and Eckert finally built a computer, <a href="http://en.wikipedia.org/wiki/ENIAC">ENIAC</a>, that was designed to be general-purpose.</li>
</ul>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=330&amp;ts=1369319074" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=330</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
		<item>
		<title>Standards and Intellectual Property</title>
		<link>http://www.pagetable.com/?p=327</link>
		<comments>http://www.pagetable.com/?p=327#comments</comments>
		<pubDate>Sat, 10 Apr 2010 00:32:19 +0000</pubDate>
		<dc:creator>Michael Steil</dc:creator>
				<category><![CDATA[default]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=327</guid>
		<description><![CDATA[I am sitting here, working with my PC: My keyboard and my mouse are connected wirelessly via Bluetooth and my monitor is hooked up through DVI. The graphics card is sitting in a PCI slot, main memory is DDR-SDRAM, and my optical drive can do CDs and DVDs. While my internal hard disk speaks the [...]]]></description>
			<content:encoded><![CDATA[<p>I am sitting here, working with my PC: My keyboard and my mouse are connected wirelessly via <a href="http://www.bluetooth.com/English/Technology/Building/Pages/Qualifications.aspx">Bluetooth</a> and my monitor is hooked up through <a href="http://www.ddwg.org/downloads.asp">DVI</a>. The graphics card is sitting in a <a href="http://www.pcisig.com/developers/procedures/">PCI</a> slot, main memory is <a href="http://www.jedec.org/sites/default/files/JM21N.pdf">DDR-SDRAM</a>, and my optical drive can do <a href="https://www.ip.philips.com/services/?module=IpsLicenseProgram&#038;command=View&#038;id=15&#038;part=2">CDs</a> and <a href="http://www.dvd6cla.com/">DVDs</a>. While my internal hard disk speaks the <a href="https://www.sata-io.org/developers/purchase_spec.asp">SATA</a> protocol, my home directory is actually sitting on an <a href="http://www.sdcard.org/developers/howto/">SD</a> card that is connected through a <a href="http://www.usb.org/developers/docs/">USB</a> reader. My internet connection is done through <a href="http://broadband-forum.org/technical/ipdeclarations.php">DSL</a>. On the software side, I am using GNU/Linux and browsing the internet with Firefox. No way I would ever watch a video in <a href="http://www.mpegla.com/">H.264</a> format.</p>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=327&amp;ts=1369319074" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=327</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Buggy Drivers</title>
		<link>http://www.pagetable.com/?p=324</link>
		<comments>http://www.pagetable.com/?p=324#comments</comments>
		<pubDate>Thu, 01 Apr 2010 22:21:56 +0000</pubDate>
		<dc:creator>Michael Steil</dc:creator>
				<category><![CDATA[default]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=324</guid>
		<description><![CDATA[]]></description>
			<content:encoded><![CDATA[<p><a href="/docs/buggy_drivers/buggy_drivers.jpg"><img src="/docs/buggy_drivers/buggy_drivers.jpg" width="440" height="330"></a></p>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=324&amp;ts=1369319074" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=324</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Announcement: &#8216;libcpu&#8217; Binary Translator</title>
		<link>http://www.pagetable.com/?p=317</link>
		<comments>http://www.pagetable.com/?p=317#comments</comments>
		<pubDate>Tue, 29 Dec 2009 19:47:09 +0000</pubDate>
		<dc:creator>Michael Steil</dc:creator>
				<category><![CDATA[default]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=317</guid>
		<description><![CDATA[I just did a Lightning Talk at the 26th Chaos Communication Congress 26C3 about our new project &#8220;libcpu&#8221;, and it has already been picked up by Golem.de and reddit.com, so I might as well announce it here: &#8220;libcpu&#8221; is an open source library that emulates several CPU architectures, allowing itself to be used as the [...]]]></description>
			<content:encoded><![CDATA[<p>I just did a <a href="http://events.ccc.de/congress/2009/wiki/Lightning_Talks_Schedule">Lightning Talk</a> at the <a href="http://events.ccc.de/congress/2009/wiki/Main_Page">26th Chaos Communication Congress 26C3</a> about our new project <a href="http://www.libcpu.org/wiki/index.php/Main_Page">&#8220;libcpu&#8221;</a>, and it has already been picked up by <a href="http://www.golem.de/0912/72116.html">Golem.de</a> and <a href="http://www.reddit.com/r/programming/comments/ajjlz/libcpu_is_an_open_source_library_that_emulates/">reddit.com</a>, so I might as well announce it here:</p>
<p><cite>&#8220;libcpu&#8221; is an open source library that emulates several CPU architectures, allowing itself to be used as the CPU core for different kinds of emulator projects. It uses its own frontends for the different CPU types, and uses LLVM for the backend. libcpu is supposed to be able to do user mode and system emulation, and dynamic as well as static recompilation.</cite></p>
<p>Here are my slides: <a href="/docs/libcpu/26C3-libcpu.pdf">26C3-libcpu.pdf</a></p>
<p>Here is the video recording: <a href="/docs/libcpu/26C3-libcpu.mp4">26C3-libcpu.mp4</a></p>
<p>Read more at <a href="http://www.libcpu.org/wiki/">http://www.libcpu.org/</a></p>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=317&amp;ts=1369319074" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=317</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Having Fun with Branch Delay Slots</title>
		<link>http://www.pagetable.com/?p=313</link>
		<comments>http://www.pagetable.com/?p=313#comments</comments>
		<pubDate>Mon, 23 Nov 2009 02:56:08 +0000</pubDate>
		<dc:creator>Michael Steil</dc:creator>
				<category><![CDATA[tricks]]></category>
		<category><![CDATA[trivia]]></category>

		<guid isPermaLink="false">http://www.pagetable.com/?p=313</guid>
		<description><![CDATA[Branch Delay Slots are one of the awkward features of RISC architectures. RISC CPUs are pipelined by definition, so while the current instruction is in execution, the following instruction(s) will be in the pipeline already. If there is for example a conditional branch in the instruction stream, the CPU cannot know whether the next instruction [...]]]></description>
			<content:encoded><![CDATA[<p>Branch Delay Slots are one of the awkward features of RISC architectures. RISC CPUs are pipelined by definition, so while the current instruction is in execution, the following instruction(s) will be in the pipeline already. If there is for example a conditional branch in the instruction stream, the CPU cannot know whether the next instruction is the one following the branch or the instruction at the target location until it has evaluated the branch. This would cause a bubble in the pipeline; therefore some RISC architectures have a branch delay slot: The instruction after the branch will always be executed, no matter whether the branch is taken or not.</p>
<p>So in practice, you can put the instruction that would be before the branch right after the branch, if this instruction is independent of the branch instruction, i.e. doesn&#8217;t access the same registers. Otherwise, you can fill it with a NOP. Out-of-order architectures can do this reordering at runtime, so there would be no need for a delay slot. Nevertheless, the delay slot is a feature of the architecture, not the implementation.</p>
<p>Some RISCs like PowerPC and ARM do not have a delay slot, but for example MIPS, SPARC, PA-RISC have it. But there are some variations: MIPS and PA-RISC have an annihilation/nullify/likely bit in the instruction, so the programmer can choose that the instruction in the delay slot only gets executed if the branch is taken.</p>
<p>Other CPUs, like SPARC, PA-RISC or the ill-fated Motorola M88K have optional delay slots: The programmer can set a bit in the opcode if he cannot come up with a good instruction for the delay slot, and save the wasted NOP in the program code this way &#8211; the CPU will put a bubble into the pipeline.</p>
<p>Now the interesting question is what happens if the branch and the delay instruction are not independent. What if the delay instruction writes r5 and the branch jumps to r5? What if it&#8217;s a branch-and-link, and the delay instruction modifies the link register? On MIPS, this is illegal, and undefined.</p>
<p>In practice, MIPS won&#8217;t halt and catch fire though. As you would expect from the design of a CPU pipeline, the CPU basically executes the branch and the delay instruction in order, as they are stored in the instruction stream, and it only delays the write to PC, i.e. the actual jump until after the delay instruction. So, for example, if you modify a register that the branch depends on, it will not influence the branch, but be in effect after the jump. </p>
<p>On the aforementioned Motorola M88K, this behaviour is documented, and GCC even makes use of it:</p>
<pre>
820:   7d ad 00 08   cmp   r13,r13,0x08    ; compare

824:   d4 6d 00 05   bb0.n 0x03,r13,0x834  ; cond. branch
828:   63 df 00 00   addu  r30,r31,0       ; delay slot

82c:   cc 00 00 7f   bsr.n 0xa28           ; function call
830:   60 21 01 ac   addu  r1,r1,0x1ac     ; delay slot: fix up link

834:   00 00 00 00   nop
</pre>
<p>The first three instructions are a compare/branch sequence. If the branch is taken, execution will continue at 0&#215;834, otherwise at 0x82c, after the delay slot. The delay instruction is independent of the branch, nothing special here yet.</p>
<p>But now look at the following two instructions: 0x82c and 0&#215;830 are not independent. r1 is the M88K&#8217;s link register, so the &#8220;bsr&#8221; writes the addres of the following instruction after the delay slot (0&#215;834) into r1. The delay slot also writes into r1: It adds 0x1ac to it. These instructions are executed in order, but the actual branch to 0xa28 will only be done after the delay instruction.</p>
<p>So what these two instructions effectively do is call a function, but set up the return address to skip the next 0x1ac bytes (107 instructions) after return. If the conditional branch at 0&#215;824 is taken, the code at 0&#215;834 will be executed, otherwise, 0xa28 is called, and the &#8220;taken&#8221; case of the conditional branch is skipped. This trick can be used whenever you have C code with an &#8220;if&#8221; statement of which one case is a single function call:</p>
<pre>
if (...) {
    call_something();
} else {
    [...]
}
</pre>
<img src="http://www.pagetable.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=313&amp;ts=1369319074" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://www.pagetable.com/?feed=rss2&amp;p=313</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
	</channel>
</rss>
