[JADEMCR.8xp Jade macro file for AsmDream
[JADEEQU.8xp Jade equate file for AsmDream
If you plan to program for Jade on the computer, you can use the included Jade.inc file for equates and macros.
:→SRC :θ=0 :prgmPROGRAM :START :<code> :End
#include 'Jade.inc'
.org 0
start:
<code>
Instructions tell the processor what to do. In Jade, there are two main types of instructions-- those that uses constants or 'immediate' values and those that use addresses. RAM holds data in bytes, and each byte has a unique address. Since there are 256 bytes, we use numbers 0 to 255 to identify each byte. The naming scheme of the instructions usually reflects which type of instruction it is, except in the cases where it makes no sense for it to be any other type. So without further ado, the first instruction:
ldc(addr1,const) ;copies or 'loads' the constant value to the byte at addr1
lda(addr1,addr2) ;copies or 'loads' the byte at addr2 to the byte at addr1
Notice that the instruction suffix is a c when a constant is being used, and an a when an address reference is being used. These is the most basic ways of moving data around. An example of its use might be:
ldc(status,80h)
Instruction Flags Description LDA(addr1,addr2) -- load the byte at addr2 to addr1 LDC(addr1,const) -- load the the constant value to add1 ADDA(addr1,addr2) cz Add the byte at addr2 to addr1, store the result at addr1 ADDC(addr1,const) cz Add the constant to addr1, store the result at addr1
Here is a quick break. Flags are used to provide additional information about the result of an instruction. The 'c' flag indicates overflow in most cases, and the 'z' flag indicates that the result was 0 in most cases. The CP instructions are a little different, and they will be explained later.
ADCA(addr1,addr2) cz Add the byte+'c' to addr1, store the result to addr1
ADCC(addr1,const) cz Add the constant+'c'to addr1, store the result at addr1
SUBA(addr1,addr2) cz Subtract the byte at addr2 from addr1, the result to addr1
SUBC(addr1,const) cz Subtract the constant from addr1, the result to addr1
SBCA(addr1,addr2) cz Subtract the byte+'c' from addr1, the result to addr1
SBCC(addr1,const) cz Subtract the constant+'c' from addr1, the result to addr1
XORA(addr1,addr2) 0z Performs bitwise XOR on the bytes, the result to addr1
XORC(addr1,sonst) 0z Performs bitwise XOR on the bytes, the result to addr1
ORA(addr1,addr2) 0z Performs bitwise OR on the bytes, the result to addr1
ORC(addr1,const) 0z Performs bitwise OR on the bytes, the result to addr1
ANDA(addr1,addr2) 0z Performs bitwise AND on the bytes, the result to addr1
ANDC(addr1,const) 0z Performs bitwise AND on the bytes, the result to addr1
CPA(addr1,addr2) cz Compares the two bytes, returns flags
CPC(addr1,const) cz Compares the two bytes, returns flags
The flags returned by CP work like this:
-If the bytes are equal, z flag is set, else it is reset
-If the second byte is less than the first, the c fag is set, else it is reset.
ROTL(addr1) cz rotate the bits left at the byte
ROTR(addr1) cz rotate the bits right at the byte
SHFTL(addr1) cz shift the bits left at the byte, carrying in the c flag
SHFTR(addr1) cz shift the bits left at the byte, carrying in the c flag
PUSHA(addr1) -- push the value at addr1 onto the stack, increment SP
PUSHC(const) -- push the constant onto the stack, increment SP
POPA(addr1) -- decrements SP and pops the value off the stack to addr1
EX(addr1,addr2)[note] -- swaps the bytes at add1 and addr2
INV(addr1) -- Inverts the bits of the byte at addr1
BITS(addr1,const) 0z Performs bitwise AND on the two values, no value returned
LDIRA(addr1,size) -- Copies the subsequent bytes to where addr1 points
LDIRC(const,size) -- Copies the subsequent bytes to where const points
These two instructions should be followed by a '.db ' statement with the data
Instruction: Description: RET() Pops the last two bytes off the stack and stores them to PC Note that RET() is generally used to end subroutines. Its full name is RETurn. SETZ() Sets the 'z' flag SETC() Sets the 'c' flag TOGZ() Toggles the 'z' flag TOGC() Toggles the 'c' flag JP1(addr) Jumps to the address in the first 256 bytes of code space JP2(addr) Jumps to the address in the second 256 bytes of code space JRF(offset) Jumps forward a given number of bytes JRB(offset) Jumps backwards a given number of bytes CALL1(addr) Executes the subroutine at the address in the first 256 bytes of code space CALL2(addr) Executes the subroutine at the address in the second 256 bytes of code space CALLF(offset) Executes the subroutine that is a relative distance forward. CALLB(offset) Executes the subroutine that is a relative distance backwards.
The call instructions push the value of PC onto the stack (two bytes), then jumps to the subroutine. Because the subroutine ends with RET(), it returns to the byte after the CALL() instruction.
IND1() The next argument will be interpreted as indirection IND2() The second argument will be interpreted as indirection
ldcz(status,80h) To turn it off if the c flag is set: ldcc(status,80h) To just turn it off: ldc(status,80h) This is why there is no instruction to reset the c or z flag. You just use these: togcc() togzz()
sLSB# This is the Least Significant Byte (lower byte) of the sprite data address
sMSB# This is the high byte of the sprite data address. 0 if it is in RAM, 1 or
2 depending on which 256-byte section it is on in the code space
sX# This is the x-coordinate of the sprite (0 to 95 is on screen)
sY# This is the y-coordinate of the sprite (0 to 63 is on screen)
sMethod# This is how the sprite will be drawn to the screen (the logic method):
1=AND logic
2=XOR logic
3=OR logic
# corresponds to the sprite number and is 0 to 7. Then it is easy to control sprites with Jade, and this is typically a style called hardware sprites. For example, to increment the X coordinate of sprite0:
inc(sX0) And now to make Jade draw the sprites...
orc(status,2)Jade will then reset that bit immediately after drawing it so that it doesn't waste CPU time drawing the sprites over and over. But we aren't neceassarily finished. In order to update the LCD with the new image, we must set bit 0 of the status port. using a similar trick:
orc(status,1)The bit will immediately be reset once the LCD is drawn to save CPU time. You can set both bits at the same time, but the LCD will be updated first, then the sprites. A common technique is to draw your sprites with XOR logic. Drawing a sprite twice with XOR logic results in no net change, but you can show the user the effect of one XORed sprite, without updating the LCD to show them the second:
orc(status,2) orc(status,3)The status port also allows you to turn off Jade by setting bit 7. So for example, both of these will work:
orc(status,80h) ldc(status,80h)The former method preserves the other bits, but if you are turning off Jade, it doesn't really matter.
key0
bit 0 = Down
bit 1 = Left
bit 2 = Right
bit 3 = Up
bit 4 = --
bit 5 = --
bit 6 = --
bit 7 = --
key1
bit 0 = Enter
bit 1 = +
bit 2 = -
bit 3 = *
bit 4 = /
bit 5 = ^
bit 6 = Clear
bit 7 = --
key2
bit 0 = (-)
bit 1 = 3
bit 2 = 6
bit 3 = 9
bit 4 = )
bit 5 = TAN
bit 6 = VARS
bit 7 = --
key3
bit 0 = .
bit 1 = 2
bit 2 = 5
bit 3 = 8
bit 4 = (
bit 5 = COS
bit 6 = PRGM
bit 7 = STAT
key4
bit 0 = 0
bit 1 = 1
bit 2 = 4
bit 3 = 7
bit 4 = ,
bit 5 = SIN
bit 6 = APPS
bit 7 = X,T,O,N
key5
bit 0 = --
bit 1 = Sto>
bit 2 = LN
bit 3 = LOG
bit 4 = X^2
bit 5 = X^-1
bit 6 = MATH
bit 7 = ALPHA
key6
bit 0 = GRAPH
bit 1 = TRACE
bit 2 = ZOOM
bit 3 = WINDOW
bit 4 = Y=
bit 5 = 2ND
bit 6 = MODE
bit 7 = DEL
stackptr holds the value of the stack pointer (0 to 127) PClow holds the LSB of the program counter PChigh holds the MSB of the program counter (only 0 or 1)