A noob's guide to QL machine code
Posted: Sat Dec 28, 2024 11:05 am
Long time, no see, but I'm going to have to make this brief return.
I have decided that my opening salvo for the 2025 CSSCGC - just to give the new host a warm welcome - will be a QL conversion of a Spectrum game from an old type-in listing. The Spectrum BASIC program is barely more than 2K, and uses a few UDGs, which are... not common in QL-land. But, now that I've moved onto the Next* and started using sprites, I saw no reason why I could not do something similar on the QL.
Recently, I've written a couple of SuperBASIC routines to plot points accurately on the screen in both MODE 4 and MODE 8, by poking directly to the screen memory with a bit of logical operation to leave the pixels I'm not plotting alone, and just change the pixel I want to the colour I want. It works, but it's SLOW, especially on a regular-speed QL, and the CSSCGC host will likely only be using an unregistered QemuLator where the original-speed QL is all that's available.
Using this plot routine I've at least managed to draw my sprites which I am now reproducing on screen with a series of POKE_W commands (I couldn't get POKE_L to work - the numbers involved were too big!). This is faster, but still too slow. Not to worry... I'll use machine code. After all, I've done it before...
...and I have completely forgotten how I did it. I had some Z80 code that I managed to translate into 68K - but I have no record of how that was then assembled to work on the QL. I don't ever remember using an assembler, so I must have hand-assembled it. This was, for all intents and purposes, three years ago - and now that I have found the resources I used at the time, I cannot for the life of me work out how I could have done it and made it work.
I had Andrew Pennell's "Assembly Language: Programming The Sinclair QL", which has a convenient list of all the opcodes I'd ever need, but the information (page 69 onwards) is presented in a way that is so dense and difficult to read, mark, learn and inwardly digest that I can't possibly have read it and managed to get anything right. For instance, it is not at all obvious if ADD.B D0,A0 is a legitimate instruction, and if it is, what bytes I should poke in order to achieve it. (Though I see elsewhere that I should use ADDA.B D0,A0 anyway...)
If I'm making Z80 code, which I'm getting half-decent at now, I'd use an assembler. (SPIN, usually, because it has one built in and I can assemble, save snapshot, run, reload if necessary, adjust, assemble, run again in a few seconds). I have left notes implying that I used GWASL last time, but I can't get it to work ("bad parameter" on QemuLator and "invalid parameter" on QPC2 whether I use EXEC or EXEC_W to start it, although neither of these is accessed from FLP1 as in the instructions... because I never have a virtual disc drive attached to either emulator, it's MDV1 on QemuLator or DOS1 on QPC2).
Daniele Terdina's recently-released assembler looks interesting... except that I have zero chance of compiling it from source, so that's not a viable option. And even though it's apparently not complete, it'll surely do the basics, but it's all academic.
Are there any other assemblers out there that are easy to use, before I attempt to type in a very long SuperBASIC listing from a QL machine code book I bought at Crash Live for peanuts, that'll take longer to type in and debug than it will to write the entire rest of the program?
I need this done by the end of the month, machine code and all, at the absolute latest, so time is of the essence. I don't need much machine code - the barest of bare basics. If it was Z80 it'd be little more than a string of LDs and a RET.
* Who was it who said something about a potential QL core for the Next, three or four years ago? It's finally happened, and was revealed at Crash Live. I'm going to get that up and running at some stage.
I have decided that my opening salvo for the 2025 CSSCGC - just to give the new host a warm welcome - will be a QL conversion of a Spectrum game from an old type-in listing. The Spectrum BASIC program is barely more than 2K, and uses a few UDGs, which are... not common in QL-land. But, now that I've moved onto the Next* and started using sprites, I saw no reason why I could not do something similar on the QL.
Recently, I've written a couple of SuperBASIC routines to plot points accurately on the screen in both MODE 4 and MODE 8, by poking directly to the screen memory with a bit of logical operation to leave the pixels I'm not plotting alone, and just change the pixel I want to the colour I want. It works, but it's SLOW, especially on a regular-speed QL, and the CSSCGC host will likely only be using an unregistered QemuLator where the original-speed QL is all that's available.
Using this plot routine I've at least managed to draw my sprites which I am now reproducing on screen with a series of POKE_W commands (I couldn't get POKE_L to work - the numbers involved were too big!). This is faster, but still too slow. Not to worry... I'll use machine code. After all, I've done it before...
...and I have completely forgotten how I did it. I had some Z80 code that I managed to translate into 68K - but I have no record of how that was then assembled to work on the QL. I don't ever remember using an assembler, so I must have hand-assembled it. This was, for all intents and purposes, three years ago - and now that I have found the resources I used at the time, I cannot for the life of me work out how I could have done it and made it work.
I had Andrew Pennell's "Assembly Language: Programming The Sinclair QL", which has a convenient list of all the opcodes I'd ever need, but the information (page 69 onwards) is presented in a way that is so dense and difficult to read, mark, learn and inwardly digest that I can't possibly have read it and managed to get anything right. For instance, it is not at all obvious if ADD.B D0,A0 is a legitimate instruction, and if it is, what bytes I should poke in order to achieve it. (Though I see elsewhere that I should use ADDA.B D0,A0 anyway...)
If I'm making Z80 code, which I'm getting half-decent at now, I'd use an assembler. (SPIN, usually, because it has one built in and I can assemble, save snapshot, run, reload if necessary, adjust, assemble, run again in a few seconds). I have left notes implying that I used GWASL last time, but I can't get it to work ("bad parameter" on QemuLator and "invalid parameter" on QPC2 whether I use EXEC or EXEC_W to start it, although neither of these is accessed from FLP1 as in the instructions... because I never have a virtual disc drive attached to either emulator, it's MDV1 on QemuLator or DOS1 on QPC2).
Daniele Terdina's recently-released assembler looks interesting... except that I have zero chance of compiling it from source, so that's not a viable option. And even though it's apparently not complete, it'll surely do the basics, but it's all academic.
Are there any other assemblers out there that are easy to use, before I attempt to type in a very long SuperBASIC listing from a QL machine code book I bought at Crash Live for peanuts, that'll take longer to type in and debug than it will to write the entire rest of the program?
I need this done by the end of the month, machine code and all, at the absolute latest, so time is of the essence. I don't need much machine code - the barest of bare basics. If it was Z80 it'd be little more than a string of LDs and a RET.
* Who was it who said something about a potential QL core for the Next, three or four years ago? It's finally happened, and was revealed at Crash Live. I'm going to get that up and running at some stage.