211
CaDan SHMUP / Re: Yet another shooter
« on: September 23, 2011, 11:13:10 pm »
Nowhere near done with the bullet engine. Instead, I'm working on the script system. Just enough so that I can get use it to run full tests on the bullet engine that I'm gonna be making. I have a specification of what I want of it so far, but at the moment, I suppose I could poll the people here to see if there's anything I might be missing with respect to the general purpose commands. Yes, the stage itself can shoot at you. And yes, this is what I'm going to be doing to test out the bullet engine. Bullets flying in from NOWHERE! Mwahahaha*COUGH*... Yeah...
Code: [Select]
Script system outline:
Internal notes:
Warning: Do not use the following for names of a script system command
"db", "dw", "end", "org", "byte", "word", "fill", "block", "addinstr",
"echo", "error", "list", "nolist", "equ", "show", "option", "seek"
These are reserved by SPASM
Naming conventions:
rx = virtual register 0-7
nn = 1 byte value
ww = 2 byte value
b = Some value between 0-7
s = Some value between 0-15
Some names will have a more descriptive label for its use. If one is used,
read the description to determine the data's size.
VERY IMPORTANT NOTE: ALL SCRIPT NAMES HAVE A PERIOD (.) PRECEDING THE NAMES
EVEN THOUGH THEY DO NOT SHOW IN THIS LIST. ALWAYS REMEMBER.
COMMANDSET AND NAME
==============================================================================
------------------------------------------------------------------------------
- NORMAL EVERYDAY USE --------------------------------------------------------
------------------------------------------------------------------------------
000 | No operation. The script system halts on encountering this.
NOP | Used for filler or something.
------------------------------------------------------------------------------
001-008 | LOAD(rx,nn)
LOAD | Stores a constant (1 byte) into a register.
2 bytes |
------------------------------------------------------------------------------
009-016 | ADD(rx,nn)
ADD | Adds a constant (1 byte) with a register, then stores the
2 bytes | results back to the register. Affects zero and carry flags.
| There's no subtract operand for this mode. Use a negative
| constant for doing that. There is no add with carry.
------------------------------------------------------------------------------
017-024 | CLEAR(rx)
CLEAR | Sets a register to zero.
1 byte |
------------------------------------------------------------------------------
025-032 | AND(rx,nn)
AND | Do a bitwise AND operation between a register and a constant
2 bytes | and store the result back into the register.
| Affects the zero flag. Does not affect the carry flag.
------------------------------------------------------------------------------
033-040 | XOR(rx,nn)
XOR | Do a bitwise XOR operation between a register and a constant
2 bytes | and store the result back into the register.
| Affects the zero flag. Does not affect the carry flag.
------------------------------------------------------------------------------
041-048 | OR(rx,nn)
OR | Do a bitwise OR operation between a register and a constant
2 bytes | and store the result back into the register.
| Affects the zero flag. Does not affect the carry flag.
------------------------------------------------------------------------------
049-056 | CPL(rx)
CPL | Inverts all bits in a register.
1 byte | Affects the zero flag.
| If you want to do NEG instead, just CPL, then INC it.
------------------------------------------------------------------------------
057-064 | WAIT(rx)
WAIT | Makes the script system wait for the number of game cycles
1 byte | that is stored in a register. Remember that 24 cycles is
| about one second's worth of time in normal gameplay mode.
| You should be setting that register to some known value
| before using this instruction. Feeding in 0 is using 256.
------------------------------------------------------------------------------
065-072 | CMP(rx,nn)
CMP | Performs subtraction between a register and a constant in
2 bytes | the form: register-constant. The result is NOT stored back,
| but instead, used to affect the zero and carry flags.
| Good for use with conditional jumps.
------------------------------------------------------------------------------
073-080 | TEST(rx,nn)
TEST | Performs a bitwise AND operation between a register and a
2 bytes | constant, but does NOT store the results back to the
| register. Instead, it's used to affect the zero flag.
| Used when you need to figure out which bits are set in a
| register, perhaps for conditional jumps?
------------------------------------------------------------------------------
081-088 | TRACK(rx)
TRACK | Output-only. Sets the given register to an angle that would,
1 byte | when used with the SHOOT command, fire a bullet directly
| toward the player.
------------------------------------------------------------------------------
089-096 | SHOOT(rx)
SHOOT | Fires a shot at the angle given in a register. 'nuff said.
1 byte |
------------------------------------------------------------------------------
097-104 | SETSTATS(rx,nn)
SETSTATS | Stores rx to an external variable. If you need to define
2 bytes | your own variables, look in the code developer's guide for
| more information.
------------------------------------------------------------------------------
105-112 | GETSTATS(rx,nn)
GETSTATS | Retrieves rx from an external variable. Again, if you need
2 bytes | to define your own variables, look in the code developer's
| guide for more information.
------------------------------------------------------------------------------
113-120 | MULT(rx,nn)
MULT | Multiplies a register by a constant, then stores the least
2 bytes | significant byte (LSB) of the result back into the register.
| NOTE: If it's possible, try to use the rotate/shift
| commands if you're dividing or multiplying by
| multiples of 2. It's much friendlier that way.
| The most significant byte (MSB) is stored in "sta.overflow"
| be accessed by the getstats command. Flags are affected as
| follows: Carry is set if the MSB is not zero. Zero is set if
| the result in the LSB was zero (even if the whole isn't)
------------------------------------------------------------------------------
121-128 | DIVIDE(rx,nn)
DIVIDE | Dividend (rx) / Divisor (nn) -> Quotient to (rx)
2 bytes | This is a slow operation. See if you can't use right shifts
| instead.
| The remainder is stored in "sta.overflow", which is accessed
| via getstats command. Flags are affected as follows:
| Carry is set if there is a remainder. Zero is set if the
| quotient is zero (does not check remainder).
|
------------------------------------------------------------------------------
129-136 | INC(rx)
INC | Increments rx by one. Same as ADD(rx,1) but much faster and
1 byte | uses less memory. Affects only the zero flag, to remain
| consistent with how the Z80 does things.
------------------------------------------------------------------------------
137-144 | DEC(rx)
DEC | Decrements rx by one. Same as ADD(rx,-1) but much faster and
1 byte | uses less memory. Affects only the zero flag, to remain
| consistent with how the Z80 does things.
------------------------------------------------------------------------------
145-152 | DJNZ(rx,label)
DJNZ | Automatically decrements the given register and takes the
2 bytes | specified relative jump while the register does not become
| zero that cycle. Just like Z80's djnz instruction, except
| you can use any register.
------------------------------------------------------------------------------
------------------------------------------------------------------------------
153 | MOVE(rxa,rxb)
MOVE | Copies the contents of register B over to register A.
2 bytes | Register A is overwritten with B and B stays the same.
------------------------------------------------------------------------------
154 | SWAP(rxa,rxb)
SWAP | The values in register A and register B are swapped.
2 bytes | Nothing is destroyed in this operation.
------------------------------------------------------------------------------
155 | ADDRX(rxa,rxb)
ADDRX | Adds register A and register B, then stores the result
2 bytes | back into register A. Affects only the carry flag.
------------------------------------------------------------------------------
156 | SUBRX(rxa,rxb)
SUBRX | Subtracts register B from register A in the form of
2 bytes | rxa-rxb, then stores the result back into register A.
| Affects
|
|
------------------------------------------------------------------------------
157 | ROTR(rx,b) / ROTL(rx,b)
ROTR/ROTL | Rotates a given register a number of bits right or left
2 bytes | (respectively). All bits that leave one side of the register
| Immediately appears on the other side of the register.
| Flags are NOT affected.
| INTERNAL NOTE: Distinguishing between ROTR and ROTL is done
| with bit 7 of the data byte. (1=ROTL)
------------------------------------------------------------------------------
158 | SHIFTR(rx,b) / SHIFTL(rx,b)
SHIFTR/SHIFTL | Shifts a given register a number of bits right or left
2 bytes | (respectively. All bits that leave are gone forever. Bits
| shifted in will always be zero.
| Flags are NOT affected.
| INTERNAL NOTE: Distinguishing between ROTR and ROTL is done
| with bit 7 of the data byte. (1=SHIFTL)
------------------------------------------------------------------------------
159 | MULTRX(rxa,rxb)
MULTRX | Multiplies register A with register B, then stores the
2 bytes | LSB of the result back to register A.
------------------------------------------------------------------------------
160 | DIVIDERX(rxa,rxb)
DIVIDERX | Divides register A with register B in the form of rxa/rxb,
2 bytes | then stores the quotient to register A.
------------------------------------------------------------------------------
161 | ANDRX(rxa,rxb)
ANDRX | Performs the bitwise AND function between register A and
2 bytes | register B, then stores the result to register A. Affects
| the zero flag.
------------------------------------------------------------------------------
162 | ORRX(rxa,rxb)
ORRX | Performs the bitwise OR function between register A and
2 bytes | register B, then stores the result to register A. Affects
| the zero flag.
------------------------------------------------------------------------------
163 | XORX(rxa,rxb)
XORRX | Performs the bitwise XOR function between register A and
2 bytes | register B, then stores the result to register A. Affects
| the zero flag.
------------------------------------------------------------------------------
164 | CMPRX(rxa,rxb)
CMPRX | Performs virtual subtraction between register A and register
2 bytes | B. Does NOT store the result anywhere, but the carry and
| zero flags are affected as though subtraction took place.
| Useful for testing conditions.
------------------------------------------------------------------------------
165 | TEXTRX(rxa,rxb)
TESTRX | Performs a virtual AND function between register A and
2 bytes | register B. Does NOT store the result anywhere, but the
| zero flag is affected as though an AND function was done.
| Useful for testing bits to see if they're set.
------------------------------------------------------------------------------
166 | JUMPNC(label) [+ or - 127 bytes in either direction]
JUMPNC | Sets the script's execution pointer to wherever you defined
2 bytes | the label only if the result of flag altering command prior
| to this instruction stayed between 0 and 255 (carry flag
| reset)
------------------------------------------------------------------------------
167 | JUMPC(label) [+ or - 127 bytes in either direction]
JUMPC | Sets the script's execution pointer to wherever you defined
2 bytes | the label only if the result of flag altering command prior
| to this instruction crossed zero. (Carry flag set)
------------------------------------------------------------------------------
168 | JUMPNZ(label) [+ or - 127 bytes in either direction]
JUMPNZ | Sets the script's execution pointer to wherever you defined
2 bytes | the label only if the result of flag altering command prior
| to this instruction was NOT zero. (Zero flag reset)
------------------------------------------------------------------------------
169 | JUMPZ(label) [+ or - 127 bytes in either direction]
JUMPZ | Sets the script's execution pointer to wherever you defined
2 bytes | the label only if the result of flag altering command prior
| to this instruction was zero. (Zero flag set)
------------------------------------------------------------------------------
170 | JUMP(label) [+ or - 127 bytes in either direction]
JUMP | Unconditionally sets the script's execution pointer to
2 bytes | wherever the label is defined. Just like Z80's JR.
------------------------------------------------------------------------------
171 | NEWPOSRT(rx_angle,rx_radius)
NEWPOSRT | Changes the firing position from the center of the enemy to
3 bytes | radius away from that center at some angle, both of which
| are stored in registers. ANGLE is between 0 and 255, and
| RADIUS can be anything, just note that 90 is the length of
| the longest possible line on the screen. Keep that in mind
| so you don't clip.
| NOTE: Position is reset to center after a pause, or another
| use of the NEWPOSRT command.
------------------------------------------------------------------------------
172 | NEWPOSXY(rx_x,rx_y)
NEWPOSXY | Changes the firing position from the center of the enemy to
3 bytes | some offset X,Y away from the enemy. You MUST understand
| that Y is reversed (positive values move down, negative
| moves upward). To obtain negative values of a certain number
| you should CPL/INC it. Or store a negative number to the
| register to begin with. The screen is 64 by 64 pixels.
| NOTE: Position is reset to center after a pause, or another
| use of the NEWPOSRT command.
------------------------------------------------------------------------------
173 | USESPRITE(rx_resourceID,rx_locationID)
SETSPRITE | Sets a sprite found in resourceID to an active enemy sprite
3 bytes | found in locationID. resourceID refers to a place on the
| current script's resource table, which should be set at
| "codegen"-time. locationID refers to a number 0-3, which
| refers to which sprite slot to use (there are four).
------------------------------------------------------------------------------
174 | JUMPTABLE(rx_offset,nn_table_length) \.db label1,label2,...
JUMPTABLE | Allows you branch to different routines depending on what
3+n bytes | is in a register. You MUST put the table immediately after
| this instruction. Example:
|
| LOAD(r1,0) ;sets r1 to zero
| JUMPTABLE(r1,4) ;r1 is the offset, 4 is the number of labels
| .db Label_0 ;<-- Will be chosen, since it's the 0th one.
| .db Label_1 ;Next label. If r1=1, then this is taken.
| .db Label_2 ;Same, except if r1=2...
| .db Label_3 ;And again... If r1=3...
|
| Note: If r1 is a value outside the bounds, the table is
| skipped over and code beneath is will run.
| Note: The labels are relative addresses, + or - 127 bytes
| in either direction. This makes it prohibitive to use
| very large tables. If you need to make tables that
| large, use jump nodes as intermediaries.
| IMPORTANT NOTE: THE TABLE CANNOT BE LARGER THAN 16 LABELS!
| If you try to make it larger anyway, garden
| gnomes will (likely) invade your home.
| A typical use for this routine is retrieving the built-in
| difficulty level, and then branching to different attacks
| based on the difficulty, so one script does many things.
| See how *you* can abuse this sucker. I won't be stopping you
------------------------------------------------------------------------------
175 | CALL(ww_relativelabel)
CALL | Lets you run a subroutine so you can save precious space by
3 bytes | not having to replicate redudnant code. The spacing for this
| label is double-wide, so it can reach anywhere you need it
| to. DO NOT TRY TO CALL ANYTHING WHILE IN A SUBROUTINE.
| Endless loops and never getting back to the main code will
| result. It's safe this time around to do a PAUSE or a WAIT
| while you're in a subroutine, however. It's safe this time
| around to do a PAUSE/WAIT combination while in a subroutine.
------------------------------------------------------------------------------
176 | RETURN
RETURN | Exits a subroutine. Don't try to use this if you're not in
1 byte | a subroutine. Main script code all have exit points, and
| using this command is NOT one of them. You might end up
| crashing your calc or something.
------------------------------------------------------------------------------
177 | XYTORT(rxa_x,rxb_y,rxc_r,rxd_t)
XYTORT | Takes of the x,y coordinates found in registers A and B
3 bytes | (respectively), then uses the position given by the center
| of the enemy in use (or whereever newposxy/newposrt has
| changed it to) to output a distance and an angle in
| registers C and D, respectively.
------------------------------------------------------------------------------
178 | RTTOXY(rxa_r,rxb_t,rxc_x,rxd_y)
RTTOXY | Similar to above, except it takes a distance and an angle,
3 bytes | then converts it to its corresponding x,y coordinates,
| outputting to registers C and D, respectively.
| The starting position is the center of the enemy in use or
| wherever you changed it to via newposxy/newposrt.
|
------------------------------------------------------------------------------
179 | GETPLAYERXY(rxa_x,rxb_y)
GETPLAYERXY | Outputs the player's X,Y coordinates to registers A and B,
2 bytes | respectively. If you only need an angle, you should be using
| the TRACK command instead. Much faster that way.