Lesson 12: Morphic Code and sprite functions.
(This lesson will be revised in the future, with a 100% correctly functioning example for instance)
One of the first questions I am sure you have is what exactly does morphic code mean? Well it is simply this: code that has the ability to change itself. This is mostly seen in done in virii to hide itself from AV scanners. That is why some virii are referred to as polymorphic. But we are not going to really be working with polymorphism in quite the same manner. We are going to be staying bimorphic while we talk about the calc-- that is we will either be doing one thing or another.
Still with me? Okay, let me use an example and I think you will be able to understand this quite clearly. Take a sprite function. It does one thing. Takes inputs, and draws a sprite to the screen. Now imagine that we could extend its functions. Lets say we wanted to use the very same functions to erase sprites too. Okay, we could have a var in memory as a flag to tell what mode we are going to operating in. But to check that it going to add a lot of overhead to the time it takes to draw the sprite, because for every pixel, the mode will have to be pulled out of memory, and then a jump is going to have to be executed to go to either the drawing or erasing code. Yikes, in the name of speed, you minus well sacrifice the size. But there is a way to get the best of both worlds, and that is to use morphic code. If you look at the code to draw a pixel and erase a pixel, it is virtually all the same except for the operations done directly prior to copying to the screen. So what we do is before we call the sprite function, we write into the program the instructions that we want.
So if we want to draw, we write in OR (HL)
And if we wanted to erase, we would write in CPL \ AND (HL)
So a bit of overhead is added once you first call, but from there on it is smooth sailing. And you don't have to make the modification all the time. Only when you are going to be changing modes. If you want to draw five sprites in a row, set to draw once and then call the sprite function from there on out.
Okay, this all sounds good on paper. But how about some actual code to back this all up. Well lucky for you, I prepared some examples. Now take in mind when you look at this example that it is not the easiest thing to write a sprite function, but the morphic section does work. (the sprite function, for some reason, does not draw the sprites correctly, but it does erase what it draws, so I'm happy)
To change code may seem like an evil task, but it is nothing hard. It is the same principle you use to save highscores. Instead of writing to a label in front of .db's, you write to a program label.
Now the real good question is how do you know what to write? You just cant write LD HL,OR (HL) TASM just wont accept it. So you have to go get a chart of opcodes. This chart will tell you the command and its hex machine code. Take that code and write that. Look up OR (HL) in the table, its at $B6. See?
One thing to remember also, all the morphic modes must be the same length. Uh-oh, to draw only takes one command, but erasing takes two! Pad with NOP is the solution you want. Do not forget also to leave adequate room in your program for the morphs to be written, and also do not forget how the calc write to memory!! (Words are written low byte first) You wouldn't want your commands to be executed in the wrong order.
So that is the one solid example of morphic code that applies to the calc. And to be completely honest, there is not that many more. But anyway, its a nice trick to know to help you out when you are coding.