<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-37072216</id><updated>2011-09-08T15:30:54.367+01:00</updated><title type='text'>XeO3-CPC</title><subtitle type='html'>Home of Xenon TriOxide CPC</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://xeo3-cpc.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37072216/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://xeo3-cpc.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>XeO3-CPC</name><uri>http://www.blogger.com/profile/00835792623120047905</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>6</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-37072216.post-116363470634703986</id><published>2006-11-15T23:47:00.000Z</published><updated>2006-11-15T23:51:46.370Z</updated><title type='text'>Arrrgh</title><content type='html'>Scrolling is nearly working, but I think my logic was a bit screwy and I'm not drawing the right bits at the right time. Keeping in mind what's currently displayed where is making my brain hurt. Hopefully the end result will be worth it.&lt;br /&gt;&lt;br /&gt;Fingers crossed for some video footage sometime this weekend (time permitting as I'm going to the video game history thing at the Science museum too!)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37072216-116363470634703986?l=xeo3-cpc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://xeo3-cpc.blogspot.com/feeds/116363470634703986/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37072216&amp;postID=116363470634703986' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37072216/posts/default/116363470634703986'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37072216/posts/default/116363470634703986'/><link rel='alternate' type='text/html' href='http://xeo3-cpc.blogspot.com/2006/11/arrrgh.html' title='Arrrgh'/><author><name>XeO3-CPC</name><uri>http://www.blogger.com/profile/00835792623120047905</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37072216.post-116317211137935217</id><published>2006-11-10T14:37:00.000Z</published><updated>2006-11-10T15:21:51.546Z</updated><title type='text'>Scrolling Theory</title><content type='html'>Ok, so we have two video screens, one which will be located in bank 2 (paged in at #8000) and the other in bank 3 (#c000) which will contain roughly the same but shifted left by one pixel. And we'll scroll these using a combination of CRTC register 3 (for a 2 pixel shift) and standard address offsetting using CRTC registers 12 and 13 to perform the main scroll.&lt;br /&gt;&lt;br /&gt;So, what does that look like in pseudo code?&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Frame 1&lt;/strong&gt;&lt;br /&gt;reset CRTC register 3&lt;br /&gt;select the screen at #8000&lt;br /&gt;draw a shifted column of bytes at #c000 + offset +  screen width&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Frame 2&lt;/strong&gt;&lt;br /&gt;select the screen at #c000&lt;br /&gt;draw an unshifted column at #8000 + offset  +  screen width&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Frame 3&lt;/strong&gt;&lt;br /&gt;move the display using CRTC register 3&lt;br /&gt;select the screen at #8000&lt;br /&gt;draw a shifted column of bytes at #c001 + offset  +  screen width&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Frame 4&lt;br /&gt;&lt;/strong&gt;select the screen at #c000&lt;br /&gt;draw an unshifted column at #8001 + offset  +  screen width&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Frame 5&lt;/strong&gt;&lt;br /&gt;Increment the hardware offset&lt;br /&gt;reset CRTC register 3&lt;br /&gt;select the screen at #8000&lt;br /&gt;draw a shifted column of bytes at #c000 + offset +  screen width&lt;br /&gt;&lt;br /&gt;and then repeat from Frame 2 onwards&lt;br /&gt;&lt;br /&gt;Note that in each case we're always writing to the unselected video memory, so that we don't need to worry about tearing.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37072216-116317211137935217?l=xeo3-cpc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://xeo3-cpc.blogspot.com/feeds/116317211137935217/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37072216&amp;postID=116317211137935217' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37072216/posts/default/116317211137935217'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37072216/posts/default/116317211137935217'/><link rel='alternate' type='text/html' href='http://xeo3-cpc.blogspot.com/2006/11/scrolling-theory.html' title='Scrolling Theory'/><author><name>XeO3-CPC</name><uri>http://www.blogger.com/profile/00835792623120047905</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37072216.post-116286065741549610</id><published>2006-11-07T00:49:00.000Z</published><updated>2006-11-09T23:36:05.816Z</updated><title type='text'>Pages and pages of flipping pixels</title><content type='html'>&lt;a href="http://photos1.blogger.com/blogger/2/4157/1600/pixels.png"&gt;&lt;img style="FLOAT: right; MARGIN: 0px 0px 10px 10px; CURSOR: hand" alt="" src="http://photos1.blogger.com/blogger/2/4157/320/pixels.png" border="0" /&gt;&lt;/a&gt; Ok, time for a brief aside from scrolling and a quick look at the CPC's pixel format and a nifty Z80 technique.&lt;br /&gt;&lt;br /&gt;In Mode 0 we have 2 pixels encoded within each byte of display memory, but not in the worlds most straightforward format (as demonstrated by the diagram showing the bit mappings.)&lt;br /&gt;&lt;br /&gt;Now what happens if we want to flip the left and right pixels over? No simple combination of rotates is going to manage it, so instead we'd have to resort to some basic arithmetic. And so, our naive Z80 routine looks something like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;LD C, %01010101  ; [2]  This is our pixel mask&lt;br /&gt;&lt;br /&gt;LD A, (HL)       ; [2] Fetch the byte to flip&lt;br /&gt;AND C            ; [1] Strip out the right pixel&lt;br /&gt;RLCA             ; [1] Shift it left&lt;br /&gt;LD B,A           ; [1]&lt;br /&gt;LD A,C           ; [1]&lt;br /&gt;RLCA             ; [1] Shift the mask&lt;br /&gt;AND (HL)         ; [2] Strip out the left pixel&lt;br /&gt;RRCA             ; [1]&lt;br /&gt;OR B             ; [1] Recombine the pixels&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;So that's a massive 11 NOPS per pixel pair (ignoring the setup cost). It's glacially slow. Damn. Clearly we can't afford to spend anything like that long, but pre-shifting all our graphics will surely be prohibitively expensive? Time for a rethink. Given that there are 256 possible combinations of pixels, all we need is a 256 byte table that maps any given byte on to it's flipped alternative. The Z80s 16-bit register pairs make this very efficient, as long as we &lt;em&gt;page align&lt;/em&gt; the data. A &lt;em&gt;page&lt;/em&gt; is a block of 256 bytes which share a common high byte (eg 0xFEnn), allowing us to perform an index lookup by direct manipulation of the least significant register.&lt;br /&gt;&lt;br /&gt;So our improved code looks more like:&lt;br /&gt;&lt;pre&gt;LD D,page        ; [2]  Initialise the lookup table pointer&lt;br /&gt;&lt;br /&gt;LD E,(HL)        ; [2]  Fetch byte&lt;br /&gt;LD A,(DE)        ; [2]  Flip the pixels&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;That's a mere 4 NOPs per pixel pair ignoring setup costs. A significant enough saving that we can easily justify the extra memory it requires. And it has the added advantage that by using a different lookup table we can apply special effects to our drawing, which may come in handy later on.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;em&gt;As an aside to the aside, Z80 coders not familiar with the CPC may well be wondering whats with all the odd timing info and the mention of NOPs. I'll make a proper post on it before I post too much more code, but for now just accept that 1 NOP = 1us and gives us a much more accurate instruction timing on the CPC.&lt;/em&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37072216-116286065741549610?l=xeo3-cpc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://xeo3-cpc.blogspot.com/feeds/116286065741549610/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37072216&amp;postID=116286065741549610' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37072216/posts/default/116286065741549610'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37072216/posts/default/116286065741549610'/><link rel='alternate' type='text/html' href='http://xeo3-cpc.blogspot.com/2006/11/pages-and-pages-of-flipping-pixels.html' title='Pages and pages of flipping pixels'/><author><name>XeO3-CPC</name><uri>http://www.blogger.com/profile/00835792623120047905</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37072216.post-116285043378655386</id><published>2006-11-06T21:17:00.000Z</published><updated>2006-11-06T22:01:52.023Z</updated><title type='text'>Give with one hand, take with the other....</title><content type='html'>So, we've got our ultra smooth scrolling at a cost of barely any cycles. We're laughing right, this is going to be a piece of cake? Well, no. All those savings come at a price and that price is a big increase in complexity.&lt;br /&gt;&lt;br /&gt;A static bitmap display has some nice properties, locating the next byte to the right is a simple INC HL instruction (or even an INC L if we're careful) which makes drawing nice and easy. Moving vertically is slightly more tricky, but it's consistent and thus not too much of a strain.&lt;br /&gt;&lt;br /&gt;When we start hardware scrolling the screen, things get a bit messy. The display memory starts to wrap around and we can no longer rely on simple calculations, even moving one byte to the right now potentially involves significant maths and we can say goodbye to all those precious cycles. That's bad, so it's necessary to look closer at how the wrap affects screen addressing.&lt;br /&gt;&lt;br /&gt;Essentially, it divides the screen into at most three separate areas; a top and bottom area which we know will be internally contiguous and a single character high row on which we will have to deal with the address wrap. All of our drawing routines need to be aware of this, using high speed instructions where possible and falling back on slower code when we don't get a choice.&lt;br /&gt;&lt;br /&gt;As if that weren't enough, recall that to get pixel perfect precision we introduced a second buffered display. This is drawn shifted across by a single pixel to compensate for the lack of finesse we achieved in hardware. This means that for absolutely everything we draw, be it sprites or background tiles we need to be able to draw it with pixel precision. And naturally the CPC's pixel format isn't exactly designed to make that easy.&lt;br /&gt;&lt;br /&gt;Kinda makes nicking that crushingly slow Speccy routine look tempting, doesn't it?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37072216-116285043378655386?l=xeo3-cpc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://xeo3-cpc.blogspot.com/feeds/116285043378655386/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37072216&amp;postID=116285043378655386' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37072216/posts/default/116285043378655386'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37072216/posts/default/116285043378655386'/><link rel='alternate' type='text/html' href='http://xeo3-cpc.blogspot.com/2006/11/give-with-one-hand-take-with-other.html' title='Give with one hand, take with the other....'/><author><name>XeO3-CPC</name><uri>http://www.blogger.com/profile/00835792623120047905</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37072216.post-116281870032652016</id><published>2006-11-06T12:47:00.000Z</published><updated>2006-11-06T13:11:43.036Z</updated><title type='text'>The CPC can't scroll</title><content type='html'>The CPC is rubbish at scrolling.&lt;br /&gt;&lt;br /&gt;There I said it. Because it's true. You have a 4Mhz CPU and a 16KB bitmapped display and no hardware assistance whatsoever. Even contemplating writing a scroller on it is plain stupid. A brief look at most existing titles will only serve to confirm this. It is a well established fact in retro gaming circles that you don't play the CPC version of games that scroll, because the other machines (even the humble Speccy) will generally do a better job.&lt;br /&gt;&lt;br /&gt;Well, actually that's only &lt;em&gt;almost&lt;/em&gt; true. There is a tiny bit of hardware assistance. The CRTC is wired up in what is perhaps best described as a funky way, allowing us some hardware assisted scrolling. Sadly it's not enormously useful on it's own, as it moves in chunks of 4 pixels at a time (in the low-res, high colour Mode 0). That means that at 50fps, objects would enter and leave the screen in under 1 second, a challenge for even the most hardened shoot-em-up fan.&lt;br /&gt;&lt;br /&gt;It's at this point that 99% of CPC games opt for the, &lt;em&gt;"we'll  just use the software scroller from the Speccy version and run suckily slowly". &lt;/em&gt;Great for getting finished in time for payday, but not so good gameplaywise. Thankfully over the years, demo coders have perfected the art of pushing the CPC hardware a little further. With a bit more CRTC based jiggery pokery we can shift the position of the screen on the monitor left by 2 pixels. Normally that would look odd, but if we stretch the display to eliminate the left and right borders, we now have smooth 2 pixel scrolling at 50 fps in a handful of CPU cycles. Combine that with a page flipped display and we can have ultra smooth pixel perfect scrolling at almost no cost.&lt;br /&gt;&lt;br /&gt;Sounds too good to be true? Well....&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37072216-116281870032652016?l=xeo3-cpc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://xeo3-cpc.blogspot.com/feeds/116281870032652016/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37072216&amp;postID=116281870032652016' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37072216/posts/default/116281870032652016'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37072216/posts/default/116281870032652016'/><link rel='alternate' type='text/html' href='http://xeo3-cpc.blogspot.com/2006/11/cpc-cant-scroll.html' title='The CPC can&apos;t scroll'/><author><name>XeO3-CPC</name><uri>http://www.blogger.com/profile/00835792623120047905</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37072216.post-116280861762425506</id><published>2006-11-06T10:17:00.000Z</published><updated>2006-11-06T10:26:15.693Z</updated><title type='text'>Intros</title><content type='html'>So, this is the unofficial home of XeO3 for the CPC. Or rather the official home of the unofficial version of XeO3. Which may become official. Or not.&lt;br /&gt;&lt;br /&gt;Ahem.&lt;br /&gt;&lt;br /&gt;I'm looking at targetting a CPC6128 version, because getting a decent framerate and smooth scrolling on just a 464 is probably not possible. If all goes well, it'll probably be followed up by a full on hardcore 6128+ version, but only time will tell. Like the other versions the game will vary slightly to be best optimised for the CPC hardware, but with hopefully enough echoes of the other versions to make it fit in.&lt;br /&gt;&lt;br /&gt;I'm still getting my head round the scrolling routines, as it's going to be a bit of a challenge. Technical stuff to follow later hopefully.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37072216-116280861762425506?l=xeo3-cpc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://xeo3-cpc.blogspot.com/feeds/116280861762425506/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37072216&amp;postID=116280861762425506' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37072216/posts/default/116280861762425506'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37072216/posts/default/116280861762425506'/><link rel='alternate' type='text/html' href='http://xeo3-cpc.blogspot.com/2006/11/intros.html' title='Intros'/><author><name>XeO3-CPC</name><uri>http://www.blogger.com/profile/00835792623120047905</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry></feed>
