<?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-35874866</id><updated>2011-09-16T19:47:22.355+01:00</updated><title type='text'>Xe03 Spectrum</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://xe03-spectrum.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/35874866/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://xe03-spectrum.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Russell Kay</name><uri>http://www.blogger.com/profile/01843594387783155118</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>18</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-35874866.post-8403912361325770915</id><published>2007-12-16T20:57:00.000Z</published><updated>2007-12-16T21:16:36.675Z</updated><title type='text'>XEO3 Lives!</title><content type='html'>Well I will forgive you for thinking that this project has gone on indefinite hiatus, but it has not been forgotten, when I have had the time (we have had a daughter, now 6 months old, so my "free" time has been limited), I have been moving the project to my new assembler, RKASM.&lt;br /&gt;&lt;br /&gt;I am pleased to report that it has all been moved over, and while I would like to do a bit of optimisation (plenty of scope for that), I have it all compiling and back in ship shape.&lt;br /&gt;&lt;br /&gt;I've actually had it mostly done for a while now, but I could not get it running on the emulator... turns out I had just one or two bits wrong in the SNA file format&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;No system variables in the output file... caused interrupts to go haywire&lt;/li&gt;&lt;li&gt;Wrong page value written out for port $7ffd&lt;/li&gt;&lt;li&gt;Wrong interrupt mode value....&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Once I had sorted these out it worked like a charm and then I just had a couple of crashes to sort out, just little bugs in the assembler... but these are all sorted.&lt;/p&gt;&lt;p&gt;Now I want to add a few items to the assembler to help with packing all the code in (there is a lot of wasted space at the moment), so I am going to add in sections, like I would use with a linker.. but I am going to omit the linker and just build it into the assembler so it will reorder the sections before saving out.&lt;/p&gt;&lt;p&gt;At that point, I'll fix the 128K code (currently broken) and sort out how I will work with the level data (looking at having everything loaded and not have any loading going on, using a single 128K snapshot).&lt;/p&gt;&lt;p&gt;Once I have that in place I will then be in a position to add content and work on the first level!&lt;/p&gt;&lt;p&gt;I think I'll even put the assembler up as a download for anyone else sad enough wants to use... once I have speeded it all up, shamefully it is taking a full 3s to assemble the code (not very big)... but I know that this is mostly going on tokenising the input stream, as that is painfully slow (and written far too quickly), the good news is that this is easily fixed... I just need to find the time to do so... probably over Christmas sometime.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/35874866-8403912361325770915?l=xe03-spectrum.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://xe03-spectrum.blogspot.com/feeds/8403912361325770915/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=35874866&amp;postID=8403912361325770915' title='20 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/35874866/posts/default/8403912361325770915'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/35874866/posts/default/8403912361325770915'/><link rel='alternate' type='text/html' href='http://xe03-spectrum.blogspot.com/2007/12/xeo3-lives.html' title='XEO3 Lives!'/><author><name>Russell Kay</name><uri>http://www.blogger.com/profile/01843594387783155118</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>20</thr:total></entry><entry><id>tag:blogger.com,1999:blog-35874866.post-3812240453461944533</id><published>2007-09-12T16:50:00.000+01:00</published><updated>2007-09-12T17:00:26.566+01:00</updated><title type='text'>RKASM!</title><content type='html'>&lt;p&gt;Well Mike has been complaining that my posts are very sporadic (he's a fine one to talk!). So I thought I would update you all on progress since SigGraph...&lt;br /&gt;&lt;br /&gt;Well while I was away I implemented the sprite movement and bullets (including the collision detection), so I now have a pretty full game system in there now...&lt;br /&gt;&lt;br /&gt;But I was getting very annoyed with the assembler that I have been using, mainly because I wanted to have a linker and a lot more power for putting everything together. I decided to take a leaf out of Mikes book and write the tools that I need.&lt;br /&gt;&lt;br /&gt;So I've been writing a Z80 assembler for the Spectrum that does exactly what I wanted it to do, it is called RKASM (Russell Kay assembler) which is not very original.&lt;br /&gt;&lt;br /&gt;My main goals just now are to get something that can assemble the code that I have already, for that I need&lt;br /&gt;* basic instructions&lt;br /&gt;* ORG, EQU, ALIGN&lt;br /&gt;* SNA output.&lt;br /&gt;* macros&lt;br /&gt;* structs&lt;br /&gt;&lt;br /&gt;I have the top 3 done already and I'm working on the last 2.&lt;br /&gt;&lt;br /&gt;After that I'm going to add sections and linking semantics into the assembler, so that I can then organise things to my satisfaction within the game.&lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/35874866-3812240453461944533?l=xe03-spectrum.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://xe03-spectrum.blogspot.com/feeds/3812240453461944533/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=35874866&amp;postID=3812240453461944533' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/35874866/posts/default/3812240453461944533'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/35874866/posts/default/3812240453461944533'/><link rel='alternate' type='text/html' href='http://xe03-spectrum.blogspot.com/2007/09/rkasm.html' title='RKASM!'/><author><name>Russell Kay</name><uri>http://www.blogger.com/profile/01843594387783155118</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>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-35874866.post-4712523442220393658</id><published>2007-08-07T23:42:00.000+01:00</published><updated>2007-08-07T23:47:02.154+01:00</updated><title type='text'>Live from San Diego!</title><content type='html'>Well Mike and I are both in San Diego at SigGraph getting our brains filled up with knowledge once again. There are lots of amazing papers, tricks and techniques that are being discussed here, unfortunately not too many that are applicable to the spectrum. It is amazing to think how things have moved on in a relatively short period of time, most of the things being discussed were impossible (at realtime rates at least) even a few years ago, never mind 25 years ago.&lt;br /&gt;&lt;br /&gt;Anyway I have had a chance on the plane over and between some sessions to add a functional section of the path moving code, so I can now have (logically at least, not hooked it up to the render code yet, though it is trivial) sprites moving around the screen, following paths that are specified in the level data.&lt;br /&gt;&lt;br /&gt;I have followed Mikes layout as much as possible so that we can share a lot of the path data... It will not always be possible because of the resolution differences but I will where possible.&lt;br /&gt;&lt;br /&gt;Anyway I'll post more details in the near future.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/35874866-4712523442220393658?l=xe03-spectrum.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://xe03-spectrum.blogspot.com/feeds/4712523442220393658/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=35874866&amp;postID=4712523442220393658' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/35874866/posts/default/4712523442220393658'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/35874866/posts/default/4712523442220393658'/><link rel='alternate' type='text/html' href='http://xe03-spectrum.blogspot.com/2007/08/live-from-san-diego.html' title='Live from San Diego!'/><author><name>Russell Kay</name><uri>http://www.blogger.com/profile/01843594387783155118</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-35874866.post-5439382287039164495</id><published>2007-07-16T20:41:00.000+01:00</published><updated>2007-07-16T21:24:19.261+01:00</updated><title type='text'>Lists</title><content type='html'>So the sprite cache is in, I thought I should tell you all how it works, for the record.&lt;br /&gt;&lt;br /&gt;The sprite cache is used to maintain a least recently used list of all the entries so that we can reuse an entry that will have as little impact as possible, the whole point of the sprite cache is to minimise the work done when drawing a sprite.&lt;br /&gt;&lt;br /&gt;The main data structure is a doubly linked list that is setup like a queue where we know the top item and the end item. So each time a sprite is rendered it is moved to the top of the queue, then when we need a sprite entry we use the end of the queue.&lt;br /&gt;&lt;br /&gt;Now normally a doubly linked list needs to be updated in an operation like moving to the top of the list requires some coniditionals (for updating the head and tail of the list). So in C# (I like to prototype the ideas first and these days C# is the language of choice). &lt;br /&gt;&lt;br /&gt;so in this snippet m_cachePrev and m_cacheNext are arrays of ints (pointing at the previous and next entries in the list, First is the first entry in the list and End is the last entry in the list.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;        public void MoveToTop( int _index )&lt;br /&gt;        {&lt;br /&gt;            // unhook previous entry&lt;br /&gt;            int prev = m_cachePrev[ _index ];&lt;br /&gt;            int next = m_cacheNext[_index];&lt;br /&gt;&lt;br /&gt;            if (next != End)&lt;br /&gt;                m_cachePrev[next] = prev;&lt;br /&gt;            else&lt;br /&gt;                Last = prev;&lt;br /&gt;&lt;br /&gt;            if (prev != End)&lt;br /&gt;                m_cacheNext[prev] = next;&lt;br /&gt;            else&lt;br /&gt;                First = next;&lt;br /&gt;&lt;br /&gt;            m_cachePrev[_index] = End;&lt;br /&gt;            m_cacheNext[_index] = First;&lt;br /&gt;            m_cachePrev[First] = _index;&lt;br /&gt;            First = _index;&lt;br /&gt;        }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now on the 6502 because the flags are set on load then Mike can get some benefits and speed ups, so this type of code is fine for Mike, but on the Z80 the flags are not set when an entry is loaded but only after specific operations. So I have been looking for a method of doing this that minimised the branching to make the Z80 code a bit nicer, well my first area of attack was on the First and End entries and the checks that go in there.&lt;br /&gt;&lt;br /&gt;So why do we use End as an indicator that this is the start or end of the list? Well just convention really (normally End would be set to NULL) but if End was set to an entry within the array then First and Last could be set to those entries. So I have set End to be the last index of the array and allocate an extra entry (so if we have 128 entries in the cache then the 129th entry becomes the First and Last entries)&lt;br /&gt;&lt;br /&gt;First == m_cacheNext[ End ];&lt;br /&gt;Last == m_cachePrev[ End ];&lt;br /&gt;&lt;br /&gt;then we can lose the conditionals because the actions would be the same. So the code becomes in C#&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;            // unhook previous entry&lt;br /&gt;            int prev = m_cachePrev[_index];&lt;br /&gt;            int next = m_cacheNext[_index];&lt;br /&gt;&lt;br /&gt;            m_cachePrev[next] = prev;&lt;br /&gt;            m_cacheNext[prev] = next;&lt;br /&gt;&lt;br /&gt;            m_cachePrev[_index] = End;&lt;br /&gt;            m_cacheNext[_index] = First;&lt;br /&gt;            m_cachePrev[First] = _index;&lt;br /&gt;            First = _index;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;and then in Z80 this becomes&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;DSO_MoveToTop: &lt;br /&gt;             ld  h,high sprite_cache_entry_prev&lt;br /&gt;  ld  b,h&lt;br /&gt;  ld  l,c&lt;br /&gt;  ld  e,(hl)       ; e = prev&lt;br /&gt;  ld  (hl),SPRITE_CACHE_END   ; m_cachePrev[_index] = SPRITE_CACHE_END&lt;br /&gt;  ld  h,high sprite_cache_entry_next&lt;br /&gt;  ld  d,h&lt;br /&gt;  ld  c,(hl)       ; c = next&lt;br /&gt;  ld  a,e&lt;br /&gt;  ld  (bc),a       ; m_cachePrev[next] = prev&lt;br /&gt;  ld  a,c&lt;br /&gt;  ld  (de),a       ; m_cacheNext[prev] = next&lt;br /&gt;  ld  e,SPRITE_CACHE_END&lt;br /&gt;  ld  a,(de)       ; a = First&lt;br /&gt;  ld         (hl),a                ; m_cacheNext[_index] = First&lt;br /&gt;  ld  c,a&lt;br /&gt;  ld  a,l&lt;br /&gt;  ld  (bc),a       ; m_cachePrev[First] = _index&lt;br /&gt;  ld  (de),a       ; First = _index&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;If you spot any optimisations then let me know.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/35874866-5439382287039164495?l=xe03-spectrum.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://xe03-spectrum.blogspot.com/feeds/5439382287039164495/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=35874866&amp;postID=5439382287039164495' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/35874866/posts/default/5439382287039164495'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/35874866/posts/default/5439382287039164495'/><link rel='alternate' type='text/html' href='http://xe03-spectrum.blogspot.com/2007/07/lists.html' title='Lists'/><author><name>Russell Kay</name><uri>http://www.blogger.com/profile/01843594387783155118</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-35874866.post-9038598180922553163</id><published>2007-07-11T20:28:00.000+01:00</published><updated>2007-07-11T20:35:44.732+01:00</updated><title type='text'>Progress!</title><content type='html'>Well the sprites have been in for some time now and I've taken the time to reorganise the code and tidy things up and do some tests. &lt;br /&gt;&lt;br /&gt;I can get 10 masked sprites on screen and still have time to render bullets and even some map sprites (these are cheaper to do as they do not need to be masked, but they do need to be ORed), so I feel fairly comfortable with where I am and I could do a fairly faithful representation of the Plus4 version. &lt;br /&gt;&lt;br /&gt;The main difference is that 10 - 16x16 sprites makes the screen fairly busy, as the Plus4 has a wider effective screen than the Spectrum, so I might revise that down for aesthetic (rather than technical reasons).&lt;br /&gt;&lt;br /&gt;So the next thing to do, are the path code for the enemies and it will start to feel like a game.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/35874866-9038598180922553163?l=xe03-spectrum.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://xe03-spectrum.blogspot.com/feeds/9038598180922553163/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=35874866&amp;postID=9038598180922553163' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/35874866/posts/default/9038598180922553163'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/35874866/posts/default/9038598180922553163'/><link rel='alternate' type='text/html' href='http://xe03-spectrum.blogspot.com/2007/07/progress.html' title='Progress!'/><author><name>Russell Kay</name><uri>http://www.blogger.com/profile/01843594387783155118</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-35874866.post-1854798839975130193</id><published>2007-07-05T12:48:00.000+01:00</published><updated>2007-07-05T12:59:09.017+01:00</updated><title type='text'>Now with added sprites!</title><content type='html'>I now have a simple sprite routine up and running as outlined below, it all seems to be working pretty well and the sprite cache is working too which is a double plus.&lt;br /&gt;&lt;br /&gt;Currently it is not using masks or anything like that so it all looks very dull, but all the logic is in place now.&lt;br /&gt;&lt;br /&gt;I have to tidy up a few things, and I'll post the sprite cache linked list code in the near future as I have managed to make it branchless which improves the readability of it and I believe performance on the Z80 (as the flags are not set on load for Z80, so I have to introduce an instruction to check for zero).&lt;br /&gt;&lt;br /&gt;Anyway, progress is being made and I hope to have something with several sprites flying around over the next few days.&lt;br /&gt;&lt;br /&gt;And then I'll work on getting the path code working so that we can have formations of enemies.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/35874866-1854798839975130193?l=xe03-spectrum.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://xe03-spectrum.blogspot.com/feeds/1854798839975130193/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=35874866&amp;postID=1854798839975130193' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/35874866/posts/default/1854798839975130193'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/35874866/posts/default/1854798839975130193'/><link rel='alternate' type='text/html' href='http://xe03-spectrum.blogspot.com/2007/07/now-with-added-sprites.html' title='Now with added sprites!'/><author><name>Russell Kay</name><uri>http://www.blogger.com/profile/01843594387783155118</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>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-35874866.post-1549692441086518395</id><published>2007-04-25T17:20:00.000+01:00</published><updated>2007-04-25T17:30:34.547+01:00</updated><title type='text'>I'm Back!!!!</title><content type='html'>Well it has been a while... but I'm back on the Spectrum XeO3, so many things have intervened in the meantime between work and home, but I'm back looking at the Sprite routines for XeO3 and I'm looking to get them sorted out in the next couple of months (being realistic about the time I can devote to the project).&lt;br /&gt;&lt;br /&gt;So major news to date is that I'm going to be a Dad again soon, so we have been preparing for that (and it gives me deadline for sorting out these pesky sprite routines, before changing nappies takes over).&lt;br /&gt;&lt;br /&gt;Anyway Mike and I have been talking about the sprite cache system that he has been using on the Plus4 and I think it is the way to go for the Spectrum too, so I've been looking at his routines and seeing what would be the best way to translate them into Z80.&lt;br /&gt;&lt;br /&gt;In Pseudo code the DrawSprite routine looks something like this&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;  Draw Sprite&lt;br /&gt;  Calc sprite function to use (could be hard coded to Draw Sprite routine name).&lt;br /&gt;  Calc address on screen&lt;br /&gt;  if sprite_number+rotation not in cache&lt;br /&gt;   [Add to cache]&lt;br /&gt;    Get lowest entry on the stack&lt;br /&gt;    Remove entry from the cache&lt;br /&gt;    Add this sprite to the cache&lt;br /&gt;    Rotate the sprite and put it into the cache.&lt;br /&gt;  [Get address in cache]&lt;br /&gt;   Move this cache entry to the top of the list&lt;br /&gt;   retrieve sprite data address&lt;br /&gt;  Push information onto sprite stack&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;This uses the sprite stack that I talked about earlier to do the actual rendering, but caches the rotated graphic for each sprite entry, this enables the use of lots of different sprite types without having to store all the possible rotations in memory at once (they are only rotated when required). Usually in the bad old days graphics would all be pre-rotated and restricted at what x coords they could be rendered at (Miner Willy springs to mind, his walk animation required it to move across the screen).&lt;br /&gt;&lt;br /&gt;So I'm going to write the general sprite cache routine over the next week or so and then spend a few weeks debugging it properly, so that the game code can just issues a simple DrawSprite call and everything will just work...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/35874866-1549692441086518395?l=xe03-spectrum.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://xe03-spectrum.blogspot.com/feeds/1549692441086518395/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=35874866&amp;postID=1549692441086518395' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/35874866/posts/default/1549692441086518395'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/35874866/posts/default/1549692441086518395'/><link rel='alternate' type='text/html' href='http://xe03-spectrum.blogspot.com/2007/04/im-back.html' title='I&apos;m Back!!!!'/><author><name>Russell Kay</name><uri>http://www.blogger.com/profile/01843594387783155118</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-35874866.post-116414883404248927</id><published>2006-11-21T22:35:00.001Z</published><updated>2006-11-21T22:40:34.053Z</updated><title type='text'>It's been a while</title><content type='html'>Well I thought I should write something as it's been a while since I last posted.&lt;br /&gt;&lt;br /&gt;Currently I'm writing some tools to convert map data into the correct format for the scrolling routines and eliminate a lot of the mistakes I've been making because I've had to type the data in by hand. It's taken a while because well ... no excuses really I've just not had the time recently.&lt;br /&gt;&lt;br /&gt;Anyway I've gotten it mostly written now C# is a wonderful thing (best thing MS have done in a long time) so XeO3Gen now exists to convert maps into the correct format. Now I just need to modify the code to use the new format (that's tomorrows job).&lt;br /&gt;&lt;br /&gt;And for the trivia fans the name XeO3Gen is an homage to the tool I wrote for Lemmings 2 (l2gen) that converted all the graphics and style files for the target machines.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/35874866-116414883404248927?l=xe03-spectrum.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://xe03-spectrum.blogspot.com/feeds/116414883404248927/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=35874866&amp;postID=116414883404248927' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/35874866/posts/default/116414883404248927'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/35874866/posts/default/116414883404248927'/><link rel='alternate' type='text/html' href='http://xe03-spectrum.blogspot.com/2006/11/its-been-while_21.html' title='It&apos;s been a while'/><author><name>Russell Kay</name><uri>http://www.blogger.com/profile/01843594387783155118</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-35874866.post-116414882757719935</id><published>2006-11-21T22:35:00.000Z</published><updated>2006-11-21T22:40:27.593Z</updated><title type='text'>It's been a while</title><content type='html'>Well I thought I should write something as it's been a while since I last posted.&lt;br /&gt;&lt;br /&gt;Currently I'm writing some tools to convert map data into the correct format for the scrolling routines and eliminate a lot of the mistakes I've been making because I've had to type the data in by hand. It's taken a while because well ... no excuses really I've just not had the time recently.&lt;br /&gt;&lt;br /&gt;Anyway I've gotten it mostly written now C# is a wonderful thing (best thing MS have done in a long time) so XeO3Gen now exists to convert maps into the correct format. Now I just need to modify the code to use the new format (that's tomorrows job).&lt;br /&gt;&lt;br /&gt;And for the trivia fans the name XeO3Gen is an homage to the tool I wrote for Lemmings 2 (l2gen) that converted all the graphics and style files for the target machines.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/35874866-116414882757719935?l=xe03-spectrum.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://xe03-spectrum.blogspot.com/feeds/116414882757719935/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=35874866&amp;postID=116414882757719935' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/35874866/posts/default/116414882757719935'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/35874866/posts/default/116414882757719935'/><link rel='alternate' type='text/html' href='http://xe03-spectrum.blogspot.com/2006/11/its-been-while.html' title='It&apos;s been a while'/><author><name>Russell Kay</name><uri>http://www.blogger.com/profile/01843594387783155118</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>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-35874866.post-116336650426013798</id><published>2006-11-12T21:15:00.000Z</published><updated>2006-11-12T21:21:44.270Z</updated><title type='text'>I've always hated the taste of SPAM</title><content type='html'>First time I've seen SPAM on a blog....&lt;br /&gt;&lt;br /&gt;Anyway I've realised that I need to address the amount of time and memory that the scrolling graphics is going to take up, so I've been thinking how to change the routines as it stands (currently the scrolling is taking around half a frame of processing), now I know that I can improve that by storing the graphic pre-rotated but that means that each set of 4 tiles (they need to be grouped together0 will take 2K for all 16 rotations, which means that on a 48K Spectrum I would get very uninspiring graphics.&lt;br /&gt;&lt;br /&gt;Well I think I have a new method but it will take a bit of experimentation.. so I'll keep you up to date with the progress.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/35874866-116336650426013798?l=xe03-spectrum.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://xe03-spectrum.blogspot.com/feeds/116336650426013798/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=35874866&amp;postID=116336650426013798' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/35874866/posts/default/116336650426013798'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/35874866/posts/default/116336650426013798'/><link rel='alternate' type='text/html' href='http://xe03-spectrum.blogspot.com/2006/11/ive-always-hated-taste-of-spam.html' title='I&apos;ve always hated the taste of SPAM'/><author><name>Russell Kay</name><uri>http://www.blogger.com/profile/01843594387783155118</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-35874866.post-116310955744167084</id><published>2006-11-09T21:24:00.000Z</published><updated>2006-11-10T20:31:01.380Z</updated><title type='text'>Xe03: Sprites</title><content type='html'>Well I've not fallen off the face of the planet, Mike and I have been busy beavering away and we've both been looking at the issue of sprites, I've been unsure on the best way to do them on the Spectrum and wondering how he has acheived so much on the Plus/4. Anyway see Mikes blog for some of the fruits of those discussions about different techniques.&lt;br /&gt;&lt;br /&gt;So now that I have the scrolling working and rendering I want to draw as many sprites as possible (Mike manages 10 masked sprites on the Plus/4) onto the main play area. On the 48K (which is still my target, as much as Mike keeps saying that I should look at 128K). So to achieve this I have to ensure that I draw the sprites before the raster displays the area that I am rendering to. Therefore I need to draw the sprites in a sorted order (from the top of the screen to the bottom) to stay ahead of the raster. Since the scrolling takes from the top of the screen (where I sync to) to the bottom of the screen (well a few scan lines over) I have the whole of the lower border, VBlank, upper border and then the screen area (staying ahead of the raster). Which is a fair amount of time...&lt;br /&gt;&lt;br /&gt;So I have to get a really fast sprite routine, and I invite you all to give suggestions on the best way. Following some discussions on the World of Spectrum (&lt;a href="http://www.worldofspectrum.org/forums"&gt;www.worldofspectrum.org/forums&lt;/a&gt;) I'm using the zig-zag pattern of sprites i.e. for a sprite that is of the format&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;ABC&lt;br /&gt;DEF&lt;br /&gt;GHI&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;then the bytes would be arranged normally as&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;A0 B0 C0&lt;br /&gt;A1 B1 C1&lt;br /&gt;A2 B2 C2&lt;br /&gt;...&lt;br /&gt;G7 H7 I7&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In Zig Zag they are arranged as&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;A0 B0 C0&lt;br /&gt;C1 B1 A1&lt;br /&gt;A2 B2 C2&lt;br /&gt;C3 B3 A3&lt;br /&gt;...&lt;br /&gt;I7 H7 G7&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In this way it minimises the number of increments and decrements that a sprite routine has to do (also means that the screen address does not need to be reloaded at all).&lt;br /&gt;&lt;br /&gt;So the basic structure of a sprite routine is&lt;br /&gt;&lt;pre&gt;// byte 0&lt;br /&gt;    get source&lt;br /&gt;    logical operation with dest&lt;br /&gt;    store in dest&lt;br /&gt;    next source&lt;br /&gt;    inc dest&lt;br /&gt;// byte 1&lt;br /&gt;    get source&lt;br /&gt;    logical operation with dest&lt;br /&gt;    store in dest&lt;br /&gt;    next source&lt;br /&gt;    inc dest&lt;br /&gt;// byte 2&lt;br /&gt;    get source&lt;br /&gt;    logical operation with dest&lt;br /&gt;    store in dest&lt;br /&gt;    next source&lt;br /&gt;    move dest down one line&lt;br /&gt;// byte 3&lt;br /&gt;    get source&lt;br /&gt;    logical operation with dest&lt;br /&gt;    store in dest&lt;br /&gt;    next source&lt;br /&gt;    dec dest&lt;br /&gt;// byte 4&lt;br /&gt;    get source&lt;br /&gt;    logical operation with dest&lt;br /&gt;    store in dest&lt;br /&gt;    next source&lt;br /&gt;    dec dest&lt;br /&gt;// byte 5&lt;br /&gt;    get source&lt;br /&gt;    logical operation with dest&lt;br /&gt;    store in dest&lt;br /&gt;    next source&lt;br /&gt;    move dest down one line&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;So going with my old favourite, I'm going to use the stack pointer to point at the source data and then store my Mask and Data together so that a single pop will read both of them and my inner core will become&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;     pop   de&lt;br /&gt;     ld    a,(hl)&lt;br /&gt;     and   e&lt;br /&gt;     or    d&lt;br /&gt;     ld    (hl),a&lt;br /&gt;     inc    l&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Using the stack means that we fetch the data and increment to the next byte all at once, the logical operation is fairly simple and the step to the next screen byte is a simple increment all nice and easy!!&lt;br /&gt;&lt;br /&gt;Now I've done some timings and I can get around 14 (24x16) of these in our time frame which is pretty good.&lt;br /&gt;&lt;br /&gt;The observant among you will have noticed that I'm not doing any rotation in this routine, that's because I'm going to implement a sprite cache like Mikes and store all the sprites rotated in the cache (remaking them when I need to), which means I don't need to do that in here (remember staying ahead of the raster).&lt;br /&gt;&lt;br /&gt;Lastly I need to feed these routine as quickly as possible so I am using a small routine that reads a table and calls the correct draw routine as quickly as possible&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;DrawSprites:    di&lt;br /&gt;                ld   (DS_sp_restore+1),sp&lt;br /&gt;&lt;br /&gt;                ld   de,6&lt;br /&gt;                ld   hl,SpriteStack&lt;br /&gt;DS_lp:          ld   sp,hl&lt;br /&gt;                exx&lt;br /&gt;                pop  hl   ; routine address&lt;br /&gt;                ld   a,h&lt;br /&gt;                and  a&lt;br /&gt;                jr  z,DS_exit&lt;br /&gt;&lt;br /&gt;                ld  (DS_jump_address+1),hl&lt;br /&gt;                pop  de   ; screen address&lt;br /&gt;                pop  hl   ; graphics address&lt;br /&gt;                ld   sp,hl&lt;br /&gt;                ex   de,hl&lt;br /&gt;DS_jump_address jp   #ffff&lt;br /&gt;DS_sp_lp_back:  exx&lt;br /&gt;                add  hl,de&lt;br /&gt;                jr   DS_lp&lt;br /&gt;&lt;br /&gt;DS_exit:&lt;br /&gt;DS_sp_restore:  ld   sp,#ffff&lt;br /&gt;                ei&lt;br /&gt;                ret  &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;So if you can spot a quicker way to do things let me know, because I want to make the Spectrum version better than the C64 or Plus4... ;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/35874866-116310955744167084?l=xe03-spectrum.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://xe03-spectrum.blogspot.com/feeds/116310955744167084/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=35874866&amp;postID=116310955744167084' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/35874866/posts/default/116310955744167084'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/35874866/posts/default/116310955744167084'/><link rel='alternate' type='text/html' href='http://xe03-spectrum.blogspot.com/2006/11/xe03-sprites.html' title='Xe03: Sprites'/><author><name>Russell Kay</name><uri>http://www.blogger.com/profile/01843594387783155118</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>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-35874866.post-116254490406873725</id><published>2006-11-03T09:01:00.000Z</published><updated>2006-11-03T09:20:54.050Z</updated><title type='text'>Scrolling Working!</title><content type='html'>&lt;object height="350" width="425"&gt;&lt;param name="movie" value="http://www.youtube.com/v/4IfN_4urgJI"&gt;&lt;embed src="http://www.youtube.com/v/4IfN_4urgJI" type="application/x-shockwave-flash" width="425" height="350" style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;"&gt; &lt;/embed&gt; &lt;/object&gt;&lt;p&gt;Well I got the scrolling working yesterday, so I thought I would put a video up for you all to see, still programmer art so it does not look very nice, and I have a particularly bad sprite routine in there just now (I know I can optimise the heck out of that one), I've been mainly worried about the scrolling up to now. &lt;/p&gt;&lt;p&gt;It is still taking a bit too much time just now, but I'm going to get the sprite routines in and start adding some gameplay in there before I go back and make more decisions on the scrolling.&lt;/p&gt;&lt;p&gt;Currently I have a cache of 16 tile pairs per screen that I am scrolling (as I'm trying to avoid storing prerotations) and 4 tile pairs per screen line, but I know I can expand that to 8 tile pairs per screen line, and I can move to pre-rotated tiles if need be (to lift the 16 tile pairs restriction). So I am fairly comfortable with this.&lt;/p&gt;&lt;p&gt;Also if I need them I can overlay sprites on the background as well to make it look nicer if need be, though my aim is to have as many sprites moving as possible to keep the action frenetic.&lt;/p&gt;&lt;p&gt;Anyway it's just a little taster to show progress... and remember I am no artist....&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/35874866-116254490406873725?l=xe03-spectrum.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://xe03-spectrum.blogspot.com/feeds/116254490406873725/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=35874866&amp;postID=116254490406873725' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/35874866/posts/default/116254490406873725'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/35874866/posts/default/116254490406873725'/><link rel='alternate' type='text/html' href='http://xe03-spectrum.blogspot.com/2006/11/scrolling-working.html' title='Scrolling Working!'/><author><name>Russell Kay</name><uri>http://www.blogger.com/profile/01843594387783155118</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>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-35874866.post-116189352976381765</id><published>2006-10-26T19:50:00.000+01:00</published><updated>2006-10-26T21:22:15.610+01:00</updated><title type='text'>Scrolling routine</title><content type='html'>So I thought that I would discuss the scrolling routine to let everyone see what I'm doing, on the Spectrum there is no hardware so we have to do everything with the processor so I have to re-render the whole scrolling area as it is constantly moving, so in pseudo code the routine is.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="font-family:courier new;"&gt;                 Initialise&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;outer_loop:      Read jump Address, graphic address and screen address from table&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                 if jump address high byte is 0 then jump to exit&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;inner_loop:      Pop graphics into registers&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                 jmp Jump address&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;return_from_jump:advance to the next line of the screen&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                 jump to outer_loop &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;exit:            restore&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                 return.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;jump_address:    push registers to screen&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                 jump to return_from_jump&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;As I have said before the fastest way on the Z80 to access memory is to use the stack, it takes 11T states to pop 16 bits from memory, whereas it takes 20T states to read 16 bits normally with a "ld hl,(NN)" instruction. The problem with using the stack pointer is that it means that we cannot do anything that would use the stack (i.e. call sub-routines or allow any interrupts), so initialisation looks like this&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="font-family:courier new;"&gt;Scroll_Render:  ld  de,SR_renderData&lt;br /&gt;                di     &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                ld  (SR_sp_restore+1),sp     &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                ld  (SR_outer_loop+1),de&lt;/span&gt;&lt;br /&gt; &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;So this little bit of code disables the interrupts and then saves the sp register into some self modifiying code to restore the current stack pointer value, then saves the address of the table (SR_renderData) into another bit of self modifying code. The Z80 has very limited instructions for setting the value of sp only&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="font-family:courier new;"&gt;  ld sp,NN&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  ld sp,(NN)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  ld sp,hl&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  ld sp,ix&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  ld sp,iy&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;so to set sp to a definitive value I use the ld sp,NN instruction and then set the value of NN by writing to that address (the address of the opcode +1).&lt;br /&gt;&lt;br /&gt;The outer loop then has to read the values from the table&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="font-family:courier new;"&gt;SR_outer_loop:  ld   sp,#ffff     &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                pop  hl     &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                ld   a,h     &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                and  a     &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                jr   z,SR_exit&lt;br /&gt;                ld   (SR_prepare_jump+1),hl     &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                pop  ix     &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                pop  iy     &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                ld   (SR_outer_loop+1),sp&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;So the first ld sp,NN is initially modified with the the start address of the table, the values are then popped of the stack (advancing sp at the same time) and then the last instruction stores the new value of sp back in the instruction that loads sp for the next time around the loop. Oh and a jump instruction (coming up in the next section) is then modified so that the jump goes to the correct place.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="font-family:courier new;"&gt;SR_inner_loop:  ld   sp,ix     &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                pop  hl     &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                pop  de     &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                pop  bc     &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                pop  af     &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                ld   sp,iy&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SR_prepare_jump:jp   #ffff&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SR_jump_return: ld   de,8     &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                add  ix,de     &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                inc  iyh     &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                ld   a,iyh     &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                and  7     &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                jr   nz,SR_inner_loop     &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                jr   SR_outer_loop&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In this section we prepare the registers with the graphics for this line of the screen, the IX register holds the base of the graphics which is then used to set sp, the graphics are popped into the register and then sp is set to the screen address (IY) then we jump to the correct routine (self modified from earlier), the return address from the routine is just below which advances the graphic address and then the screen address is incremented to the next line down, then we keep going until the end of the table.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SR_exit:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SR_sp_restore:  ld  sp,#ffff     &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                ei     &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                ret&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This section just restores sp back to it's original address, renables the interrupts and then returns back to the calling routine (in this case the main loop).&lt;br /&gt;&lt;br /&gt;Now the routines that are called for rendering each line, will actually be constructed from the map section that we want to render so these will change all the time (and I'll be writing some code later to create them), but they look like this&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;SR_line_00:   push hl&lt;br /&gt;    push de&lt;br /&gt;    push bc&lt;br /&gt;    push af&lt;br /&gt;    push hl&lt;br /&gt;    push de&lt;br /&gt;    push bc&lt;br /&gt;    push af&lt;br /&gt;    push hl&lt;br /&gt;    push bc&lt;br /&gt;    push de&lt;br /&gt;    push af&lt;br /&gt;    push hl&lt;br /&gt;    push bc&lt;br /&gt;SR_line_00ret:                  jp      SR_jump_return&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This code is relatively simple and since each opcode is only 1 byte it will be relatively simple to construct, the jp address always returns to the same place for each bit of code so that is even easier.&lt;br /&gt;&lt;br /&gt;Now those who are still awake and have reached this section will have noticed that I have avoided using the exchange register set in this routine completely, this is because currently I am only using 4 different graphic tiles per line for the map but if I use the exchange registers then I could get a total of 8 different tiles on each line. But I have to trade that off against the amount of time it will take to setup i.e. 8 pops and not 4 as it is just now (and also complicating the line rendering code as it will have to swap the register sets as well as it push's), this will slow down rendering. I do have an option though of moving the line setup code into the rendering as well, this would be relatively simple and mean that only the registers that are used would be popped (so if only one is used then only that one is popped) this would give a lot more flexibility.&lt;br /&gt;&lt;br /&gt;Anyway thats all for just now, back to the assembler...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/35874866-116189352976381765?l=xe03-spectrum.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://xe03-spectrum.blogspot.com/feeds/116189352976381765/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=35874866&amp;postID=116189352976381765' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/35874866/posts/default/116189352976381765'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/35874866/posts/default/116189352976381765'/><link rel='alternate' type='text/html' href='http://xe03-spectrum.blogspot.com/2006/10/scrolling-routine.html' title='Scrolling routine'/><author><name>Russell Kay</name><uri>http://www.blogger.com/profile/01843594387783155118</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>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-35874866.post-116186591746092895</id><published>2006-10-26T13:31:00.000+01:00</published><updated>2006-10-26T13:39:33.183+01:00</updated><title type='text'>All change</title><content type='html'>&lt;a href="http://photos1.blogger.com/blogger/3136/4000/1600/Xeo3_25_10_2006_rewritten_scroll.jpg"&gt;&lt;img style="FLOAT: left; MARGIN: 0px 10px 10px 0px; CURSOR: hand" alt="" src="http://photos1.blogger.com/blogger/3136/4000/320/Xeo3_25_10_2006_rewritten_scroll.jpg" border="0" /&gt;&lt;/a&gt;Mike has been educating me on the wonders of Cascading Styling Sheets so it's all change today on the blog.&lt;br /&gt;&lt;br /&gt;Last night I optimised the rendering code quite a bit and managed to shave off a lot of time (around 40 scan lines!!!) it was all down to reorganising things and using tables rather than calculating.&lt;br /&gt;&lt;br /&gt;The picture attached shows how much time I've saved in the timing bars (cyan is the render time for the scrolling area, red is the sprite rendering time) so you can see the change from the last post.&lt;br /&gt;&lt;br /&gt;So I have now moved some of the calulcation to tables and I've made better use of the available registers. Tonight I'll post the code for everyone to look at (and criticise :) )&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/35874866-116186591746092895?l=xe03-spectrum.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://xe03-spectrum.blogspot.com/feeds/116186591746092895/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=35874866&amp;postID=116186591746092895' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/35874866/posts/default/116186591746092895'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/35874866/posts/default/116186591746092895'/><link rel='alternate' type='text/html' href='http://xe03-spectrum.blogspot.com/2006/10/all-change.html' title='All change'/><author><name>Russell Kay</name><uri>http://www.blogger.com/profile/01843594387783155118</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-35874866.post-116163468047250380</id><published>2006-10-23T20:55:00.000+01:00</published><updated>2006-10-26T13:30:34.063+01:00</updated><title type='text'>Pictures!!!</title><content type='html'>&lt;a href="http://photos1.blogger.com/blogger/3136/4000/1600/Xeo3_23_10_2006_in_progress.1.jpg"&gt;&lt;img style="FLOAT: left; MARGIN: 0px 10px 10px 0px; CURSOR: hand" alt="" src="http://photos1.blogger.com/blogger/3136/4000/320/Xeo3_23_10_2006_in_progress.1.jpg" border="0" /&gt;&lt;/a&gt;&lt;a href="http://photos1.blogger.com/blogger/3136/4000/1600/Xeo3_23_10_2006_in_progress.0.jpg"&gt;&lt;/a&gt;Mike has been pestering me to put up an in-progress picture, and I have to emphasise that this is very much in-progress (including programmer art).&lt;br /&gt;&lt;br /&gt;Basically this shows the scrolling area being redrawn every frame with a sprite being rendered on top (actually it is currently 4 sprites in the same position).&lt;br /&gt;&lt;br /&gt;The border colours are showing how long is being taken for the 2 routines (Cyan is the scroll render and red is the sprite drawing). So the scroll render is taking around 2/3rds of a full frame and we are only rendering the top 2/3rds of the screen (128 pixels).&lt;br /&gt;&lt;br /&gt;I've been talking tactics with Mike and I've had to rethink some things over the weekend as the Z80 was just not fast enough for what I was thinking... it really take some time to readjust to how little can really be done by these processors, we really are spoiled by current machines!&lt;br /&gt;&lt;br /&gt;I still have to write the processing part of the scrolling which will create the code to render the screen and rotate the tiles of the actual screen, but we have already decided that the game will run in 2 frames (i.e. it will update at 25fps, the same as the Plus/4 and the C64) so I have plenty of time.&lt;br /&gt;&lt;br /&gt;Mike also pointed out that the 128K Spectrum would allow me to double buffer the screen (which would mean I would not need to use the floating bus technique), currently I'm a purist aiming at the 48K Spectrum but I will be doing a 128K version as well so I'll keep that knowledge in my back pocket.&lt;br /&gt;&lt;br /&gt;I need to get back to this processing stuff now so that I can get it all moving...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/35874866-116163468047250380?l=xe03-spectrum.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://xe03-spectrum.blogspot.com/feeds/116163468047250380/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=35874866&amp;postID=116163468047250380' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/35874866/posts/default/116163468047250380'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/35874866/posts/default/116163468047250380'/><link rel='alternate' type='text/html' href='http://xe03-spectrum.blogspot.com/2006/10/pictures.html' title='Pictures!!!'/><author><name>Russell Kay</name><uri>http://www.blogger.com/profile/01843594387783155118</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>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-35874866.post-116120356976942582</id><published>2006-10-18T21:12:00.000+01:00</published><updated>2006-10-18T21:32:49.783+01:00</updated><title type='text'>Old and New</title><content type='html'>So I've spent a while now implementing scrolling on the Spectrum and its the first Z80 code of any size for a long time and I'd forgotten how processors have moved on over the years. I've been frustrated by little things that you take forgranted on x86, Mips etc.&lt;br /&gt;&lt;br /&gt;1. No instruction to add a constant value to a register, only register to register.&lt;br /&gt;2. Rotate instructions only rotate by one at a time... oh to be able to rotate by a variable amount.&lt;br /&gt;3. Lots of registers but a lack of addressing modes, a lot of instructions only allow register to register interactions and that means you need to shuffle them around all the time (and a lack of shuffling instructions (at least for 16bit regs)).&lt;br /&gt;&lt;br /&gt;Some things are good though, the ability to use the flags registers as return states (mainly because a lot of instructions do not set them), this makes things much easier in many ways.&lt;br /&gt;&lt;br /&gt;More modern  processors make it much easier and what is natural these days is far too slow for the old processors, I need to think much more about minimising the amount of work that needs to be done by the Z80, a readjustment in my thinking is needed...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/35874866-116120356976942582?l=xe03-spectrum.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://xe03-spectrum.blogspot.com/feeds/116120356976942582/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=35874866&amp;postID=116120356976942582' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/35874866/posts/default/116120356976942582'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/35874866/posts/default/116120356976942582'/><link rel='alternate' type='text/html' href='http://xe03-spectrum.blogspot.com/2006/10/old-and-new.html' title='Old and New'/><author><name>Russell Kay</name><uri>http://www.blogger.com/profile/01843594387783155118</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>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-35874866.post-116085723244960124</id><published>2006-10-14T21:03:00.000+01:00</published><updated>2006-10-26T13:28:44.523+01:00</updated><title type='text'>Waiting for the right moment!</title><content type='html'>The Spectrum is an interesting beast because it basically has no hardware and you need to do everything in software. When rendering the best way to do things is to render behind the raster that is sending everything to the TV screen.&lt;br /&gt;&lt;br /&gt;The only synchronisation that is available is with the vertical sync of the raster, but this leaves a lot of time (in terms of machine cycles) before the start of the screen, where we want to start rendering to allow us to draw just behind the raster, if we render before hand then we will see flicker, just behind and the display will be rock solid (which is what we are aiming for).&lt;br /&gt;&lt;br /&gt;Fortunately on the Spectrum there is a little known way that this can be done, once again a technique which was used on Cobra (a technical masterpiece), it uses the floating bus on the Spectrum (see &lt;a href="http://www.ramsoft.bbk.org/floatingbus.html"&gt;http://www.ramsoft.bbk.org/floatingbus.html&lt;/a&gt; for an explanation). The code is relatively simple&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SyncToScreen: ld bc,#3f28&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;STS_lp:       ld a,c &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;              in a,(#ff) &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;              cp b &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;              jr nc,STS_lp &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;              ret&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This routine basically waits until an attribute is being output from the ULA of the Spectrum, which if it is started during the border region of the display, then it will wait for the first line of the screen... exactly what we need!&lt;br /&gt;&lt;br /&gt;So now our armoury of techniques is filling up I really need to get on and write some real code...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/35874866-116085723244960124?l=xe03-spectrum.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://xe03-spectrum.blogspot.com/feeds/116085723244960124/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=35874866&amp;postID=116085723244960124' title='15 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/35874866/posts/default/116085723244960124'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/35874866/posts/default/116085723244960124'/><link rel='alternate' type='text/html' href='http://xe03-spectrum.blogspot.com/2006/10/waiting-for-right-moment.html' title='Waiting for the right moment!'/><author><name>Russell Kay</name><uri>http://www.blogger.com/profile/01843594387783155118</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>15</thr:total></entry><entry><id>tag:blogger.com,1999:blog-35874866.post-116060137031798477</id><published>2006-10-11T22:00:00.000+01:00</published><updated>2006-10-11T22:16:10.326+01:00</updated><title type='text'>First Post</title><content type='html'>Well here we are, first post on a journey back into time.&lt;br /&gt;&lt;br /&gt;It's been around 20 years since I last touched a real Spectrum to program it, but here I am back again!!!&lt;br /&gt;&lt;br /&gt;Mike has given me this chance to put together a Spectrum version of Xenon TriOxide, so I've been re-acquainting myself with an old friend.&lt;br /&gt;&lt;br /&gt;The game is a scrolling shoot em up, and the best scrolling method on the Spectrum was used in Cobra, where the screen is redrawn every frame by "push"ing the map onto the screen.&lt;br /&gt;&lt;br /&gt;The technique is fairly simple the stack pointer is set to a screen address and then code is executed which draws the screen, this code is created procedurally from the game map, it is a simple tower of push instructions, in psuedo code it is reasonably simple&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-family:courier new;"&gt;disable interrupts&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:courier new;"&gt;store SP into memory location (of the ld sp,NNNN instruction below)&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:courier new;"&gt;set SP to screen address (right most column of screen)&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:courier new;"&gt;initialises registers with the graphics&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:courier new;"&gt;Execute the  constructed code&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:courier new;"&gt;Loop for all the screen lines that are to be rendered&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:courier new;"&gt;ld sp,NNNN (this instruction will now contain the stored SP register)&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:courier new;"&gt;enable interrupts&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;This is the fastest way to redraw the screen.&lt;br /&gt;&lt;br /&gt;Tomorrow I'll talk about how to synchronise the screen so that we don't get any flicker.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/35874866-116060137031798477?l=xe03-spectrum.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://xe03-spectrum.blogspot.com/feeds/116060137031798477/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=35874866&amp;postID=116060137031798477' title='38 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/35874866/posts/default/116060137031798477'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/35874866/posts/default/116060137031798477'/><link rel='alternate' type='text/html' href='http://xe03-spectrum.blogspot.com/2006/10/first-post.html' title='First Post'/><author><name>Russell Kay</name><uri>http://www.blogger.com/profile/01843594387783155118</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>38</thr:total></entry></feed>
