BBC BASIC - Changing Colours In Assembler Code
Pages: 1 2
Angel Perez (2908) 84 posts |
Sure, in BASIC, I can use the COLOUR and GCOL statements to change the colour of the text and graphics but is there an assembler code equivalent I could use? My main concern is to draw sprites by printing user-defined text characters (UDC) with changes to the colours for each layer drawn over the previous with just one CALL statement rather than multiple GCOL and CALL statements (a GCOL statement for every colour for each layer I draw.) |
Steve Fryatt (216) 2105 posts |
“COLOUR c” is just another way to write “VDU 17,c” and “GCOL m,c” is just another way to write “VDU 18,m,c”. As such, you just need to send two or three bytes (characters) to the VDU stream, which you can do with OS_WriteC, OS_Write0, OS_WriteS, OS_WriteN, or OS_WriteI. For example, in BASIC,
would be equivalent. Similarly,
would be the same thing. You should be able to convert those over to assembler in a way that suits what you’re trying to do. |
Angel Perez (2908) 84 posts |
In assembler, I would typically write something like this: ] The only problem is that, as with the VDU 17 or VDU 18 calls, the instructions tend to change to the colour at the brightest tint and I intend to use darker tint intensities in between. In 256-color modes, the value of 6 is supposed to give me brown but at the TINT intensity at 192 I would get like a bright “orange” rather than brown itself. With the tint set at 0 I would get the brown coloration I use for earth and anything else brown. |
Steve Fryatt (216) 2105 posts |
You might want to take a look at ColourTrans in that case. It provides calls such as ColourTrans_SetGCOL which could prove useful. |
Angel Perez (2908) 84 posts |
Now Steve… Suppose I want to change the user-defined characters at run time, in a loop, say, for instance, to animate a UD text-character-based sprite the same way as in BASIC I would write: 9999 VDU 23, Is there a way to do that same thing in assembler based on the “OS_WriteC” and other related SWI calls? I would typically define 10 bytes within a label for the SWI call to index, the “23” after the VDU call and the ASCII index pointer, which is between 32 and 255 (or between &20 and &FF,) followed by the 8 bytes to define that character. I believe I will need a second register (such as R1) as the index pointer to the address within the . |
Angel Perez (2908) 84 posts |
I will need a few examples of code for use of the ColourTrans calls. |
Rick Murray (539) 13840 posts |
Do you have the StrongHelp OS manual? It is invaluable, and would tell you that the SWI you’re looking for is OS_WriteN – pointer in R0, number of bytes to write in R1. Or if the data is to be built on-the-fly, call OS_WriteC for each byte. |
Angel Perez (2908) 84 posts |
Besides that, I will need a code example as a guide. Plus, equivalents to MOVE statements. |
Rick Murray (539) 13840 posts |
MOVE (and the drawing commands like RECTANGLE [FILL]) can be done with OS_Plot. Again, I refer you to either StrongHelp or book one of the PRMs. Try this: |
Angel Perez (2908) 84 posts |
Is the StrongHelp manual invaluable? Is it? Woohoo! I discovered that earlier but I couldn’t understand them yet until I learned about coding in assembly language! Now about the OS_Plot SWI call: to perform a command equivalent to the BASIC MOVE statement, notice that a value of 64 given to the OS_Plot call will draw a pixel on the screen. But just like there is an optional suffix called BY, used in the statement MOVE, as in the case of such related graphics commands, in the OS_Plot call, there should be a way to give the x and y parameters a relative value. |
Angel Perez (2908) 84 posts |
Thus, Rick, to perform a piece of code equivalent to, for instance: MOVE 640,512 MOV R0,#&44 |
Angel Perez (2908) 84 posts |
But when I am giving relative coordinate values in assembly code, how do I give an equivalent negative value? If I attempt to use a relative value like -5, I will get a “Bad immediate constant” message. In BASIC, the coordinate ranges for commands like MOVE, PLOT and POINT are between -32768 and 32768 in both directions, vertically and horizontally. But using OS_Plot for those same purposes, including relative coordinate indexing, is tricky. |
Rick Murray (539) 13840 posts |
MVN |
Kuemmel (439) 384 posts |
…as instruction plus immediate have to be encoded in a 32Bit word the use of direct constants is limited in the ARM world. Of course you can apply different tricks like shifting to get some more range. May be you can have a look here If you don’t need the speed it’s may be more practial to store your coordinates in data and load it with LDR/LDMIA => e.g. LDR R1,data / .data / EQUD number |
Martin Avison (27) 1494 posts |
Much better for documentation when using Basic Assembler is to write SWI “OS_Plot” and let Basic do the conversion.
Beware that this is Move NOT and not Move Negative! |
Rick Murray (539) 13840 posts |
I was assuming that given a pointer, OP would Google for more info. There’s no shortage of it.
I wonder if there’d be any milage in having BASIC silently translate MOV negative into the appropriate MVN like objasm does… |
Martin Avison (27) 1494 posts |
I have often thought about looking at that … usually when I have found a MVN with the wrong constant! |
Steve Drain (222) 1620 posts |
That is one of the things I have used most often in Extended BASIC Assembler, along with the eqivalent substitutions for ADD, SUB, CMP etc. A mass appeal to Adrian Lees is needed. ;-) |
Angel Perez (2908) 84 posts |
But Kuemmel, though, when dealing with ARM assembly language equivalents to MOVE, MOVE BY, PLOT, PLOT BY and POINT, we are dealing with 16-bit numbers, not 32-bit. (-32768 to 32767) for both X and Y axes. &0000 to &7FFF = 0 to 32767; &8000 to FFFF = -32768 to -1. Therefore the graphics commands work with 16 bit coordinate value data. But MVN? The #9 you refer to is rather like a register such as R0 being loaded with %11111111111111111111111111110110. I didn’t know you can actually load a constant with LDR. I am kind of curious on that one. |
Steve Fryatt (216) 2105 posts |
Or in the BASIC Assembler, the slightly clearer
|
Steve Fryatt (216) 2105 posts |
OS_Plot isn’t an ARM assembly language equivalent. PLOT and PLOT BY just call OS_Plot directly (unless they do it via VDU 25, I suppose); MOVE (BY), PLOT (BY) and POINT are just short-hand forms of a PLOT statement.
OS_Plot is dealing with 32-bit numbers, however: it’s a SWI, and takes 32-bit parameters. You might want to go and read up on how the ARM instruction set works, because it’s fairly crucial to understanding what you’re doing. The space allocated in MOV (and many other instructions) for an immediate constant is 8 bits long, which can be shifted anywhere in the 32-bit word. So you could have MOV R0, #&FF or MOV R0, #&FF0 or MOV R0, #&FF00 through to MOV R0, #&FF000000. You couldn’t have MOV R0, #&F0F. -10 is &FFFFFFF6, which clearly has more than 8 consecutive bits set: you can’t do MOV R0, #-10. However, NOT &FFFFFFF6 is &9, and that does fit into the 8-bit rule. You can therefore load -10 into R0 by MVN R0, #NOT-10 and allowing MVN to NOT the value back again before storing it in R0. ETA: If you need to load 65535 into a register as an immediate constant, your options are to do it in two stages:
or to store the value in memory and LDR it:
Sometimes one will be more appropriate than the other. |
Angel Perez (2908) 84 posts |
The BASIC numeric function USR% inside the parentheses of the USR() function. USR is a useful tool for debugging your code! |
Fred Graute (114) 645 posts |
+1 Another thing I’d love to see added is ADRL.
Not anywhere, the value is actually rotated by an even number of bits. You can use MOV #&3FC (&FF ROR #30) but not MOV #&1FE (&FF ROR #31).
Another way is:
Useful for creating masks to restrict numbers to a certain range. To create a mask for a 19 bit range you’d use:
if the value is within +/- 4k you can use:
The assembler will convert it to PC-relative LDR. If this is all a bit pedantic then apologies, I’ve been pouring the ARMv8 ISA this evening to see how much work it would be it add to StrongED’s syntax colouring. Alas it’s not really RISC anymore, it’s more like a Z80 on steroids. |
Angel Perez (2908) 84 posts |
Well, Steve Fyatt… The all-too-familiar arithmetic mnemonic, ADD! When I try out that piece of code to load &FFFF into R0, I could use the USR function to confirm it. MOV R0,#&FF |
Martin Avison (27) 1494 posts |
You have referred to this a couple of times, but I am not sure what you mean. [plug mode] |
Pages: 1 2