Forgot your password?
typodupeerror
User Journal

Mr Z's Journal: Good, working code heading for the wastebin *sniff* 2

Journal by Mr Z

Shameless rambling about a personal project...

I'm working on a video game that is similar to Moon Patrol. It's a game for the venerable, underpowered Intellivision video game system. You can find more information and a developer's kit on the Intellivision on my SDK-1600 page.

Well, I spent Thanksgiving up through now working on various aspects of the game. One large piece was working out a method for controlling the 'bad guys.' I figured I'd write a small interpreter that would read a "Bad Guy Motion Program", and move the guys around. I even wrote a very simplistic assembler to assemble the command words for the interpreter. The whole thing actually works pretty reliably.

Turns out, though, that I need something else. My current approach is 'timer based.' That is, the motion programs are essentially of the form "Set velocity to dx,dy", "wait XX tics", "set velocity to dx,dy", "wait XX tics", "fire", "wait XX tics", "leave the screen." The problems are twofold:

  • In Moon Patrol, at least, the bad guys are cued into the level and cued out of the level by location. That is, when I cross a particular marker, the bad guys show up. When I cross a different particular marker, they leave. I'd like similar behavior for my game, but the timer method causes the bad guys to leave too soon if the tank is driving slowly, and too late if the tank is driving quickly.
  • The bad guys always move in EXACTLY the same pattern. In Moon Patrol, at least, the bad guys move consistently only if you move consistently. That is -- their movements seem rule based, not hardcoded.

So, I'm going to have to scrap my current interpreter. I'm torn between writing a new interpreter (or extending this one) to allow me to write rule-based motion programs for the bad guys, or just writing the rule-based programs directly in CP-1600 assembly. The latter is less convenient, I think, but will likely be smaller and is more likely to fit in my cycle budget.

So it appears I will probably scrap the interpreter.

The interpreter wasn't much, but it was something. And it worked. And I was proud of it. It provided some neat concepts, such as a looping construct that combined initialization, decrement, and branching into a single instruction. FWIW, here's how the looping instruction worked:

I offer two loop-counters per program. The LOOPA instruction uses the 'A' loop counter, and LOOPB uses the 'B' loop counter. The counters are initialized to 0 at the start of the program. Upon reaching an instruction of the form "LOOP[AB] label, count", the loop instruction checks the corresponding loop counter. If it's 0, it's initialized to the specified count and a branch is made to the label. If it's non-zero, it's decremented, and if the result is non-zero the branch is taken. That's it.

Here's an example motion program that causes a bad-guy to move in a box-shaped spiral:

####
## sample motion programs
####
MP_BOX PROC

@@box
. . . . GO (3) rg1
. . . . GO (3) dn1
@@boxb GO (3) lf1
. . . . GO (2) up1
. . . . LOOPA @@box, 5 # do the box 5 times

. . . . GO (2) rg2
. . . . GO (2) dn2
. . . . LOOPB @@boxb, 4 # slide over and do this 4 times total.
. . . . GO (9) lf3
. . . . DIE
. . . . ENDP

The names "lf1", "dn2" represent directions and velocities. The number in parentheses is number of ticks to wait after the instruction executes (at a 30Hz tick-rate). Nothing particularly mind-bending.

Now it looks as though I might bin all this code and write up motion programs in straight assembly. *sigh*

Ah well, here's the interpreter (or at least the heart of it) for posterity.

;; ======================================================================= ;;
;;. UPBGM -- Update Bad Guy Motion.. Called on a 30Hz tick.. . . . . . . . ;;
;; ======================================================================= ;;
UPBGM. PROC
. . . . PSHR. . R5

. . . . MVII. . #BGMPTBL, R4
. . . . CLRR. . R1

. . . . ;; --------------------------------------------------------------- ;;
. . . . ;;. Iterate through the motion programs . . . . . . . . . . . . . . ;;
. . . . ;;. R0 -- scratch. . . . . . . . . . . . . . . . . . . . . . . . . ;;
. . . . ;;. R1 -- Slot # for MOB (within group 1). . . . . . . . . . . . . ;;
. . . . ;;. R2 -- Program counter for current record . . . . . . . . . . . ;;
. . . . ;;. R3 -- scratch. . . . . . . . . . . . . . . . . . . . . . . . . ;;
. . . . ;;. R4 -- Pointer to BGMP state tables . . . . . . . . . . . . . . ;;
. . . . ;;. R5 -- scratch. . . . . . . . . . . . . . . . . . . . . . . . . ;;
. . . . ;; --------------------------------------------------------------- ;;
. . . . B . . . @@first_bgmp. . ; skip first INCR R1

@@next_bgmp:
. . . . INCR. . R1. . . . . . . ; next slot #

. . . . CMPI. . #5,. . R1. . . ; Is this the end?
. . . . BGE . . @@done_bgmp . . ; Yes, done.

@@first_bgmp:
. . . . SDBD
. . . . MVI@. . R4,. . R2. . . ; Get program counter
. . . . TSTR. . R2. . . . . . . ; If it's zero, motion program is inactive
. . . . BNEQ. . @@active_bgmp. ; Non-zero, it's active.

. . . . ADDI. . #3,. . R4. . . ; Skip rest of record.
. . . . CMPI. . #BGMPTBL+25, R4 ; Is this the end?
. . . . BLT . . @@next_bgmp . . ; No, do the next one.
. . . . B . . . @@done_bgmp . . ; Yes, done.

@@active_bgmp:
. . . . MOVR. . R4,. . R3
. . . . MVI@. . R4,. . R0. . . ; Get delay counter for this motion program
. . . . ADDI. . #2,. . R4. . . ; point to next record
. . . . DECR. . R0. . . . . . . ; Count down the delay counter.
. . . . MVO@. . R0,. . R3. . . ; Store the updated delay counter

. . . . BPL . . @@next_bgmp. . ; If not expired, go to the next program.

@@expired:
. . . . MVI@. . R2, . . R0. . . ; Get next program word.
. . . . INCR. . R2
. . . . MVO@. . R0, . . R3. . . ; Store out lower byte as delay count.
. . . . XOR@. . R3, . . R0. . . ; Clear delay byte
. . . . SWAP. . R0. . . . . . . ; Extract command byte.

. . . . SUBI. . #64,. . R0. . . ; Less than 64?. It's a motion command.
. . . . BMI . . @@cmd_move. . . ;
. . . . SLL . . R0,. . 1
. . . . ADDR. . R0,. . PC. . . ; Otherwise, vector to the other commands.
. . . . B . . . @@cmd_loopa . . ;. 0 : LOOPA
. . . . B . . . @@cmd_loopb . . ;. 1 : LOOPB
. . . . B . . . @@cmd_jump. . . ;. 2 : JUMP
. . . . B . . . @@cmd_fire. . . ;. 3 : FIREA
. . . . B . . . @@cmd_fire. . . ;. 4 : FIREB
. . . . B . . . @@cmd_fire. . . ;. 5 : FIREC
. . . . B . . . @@cmd_die . . . ;. 6 : DIE
. . . . B . . . @@cmd_attr. . . ;. 7 : ATTR
. . . . B . . . @@cmd_seths . . ;. 8 : SETHS
. . . . B . . . @@cmd_clrhs . . ;. 9 : CLRHS
; . . . B . . . @@cmd_wait. . . ; 10 : WAIT aka. NOP.

. . . . ;; --------------------------------------------------------------- ;;
. . . . ;;. WAIT/NOP:. Just set the delay counter and go to next command.. ;;
. . . . ;; --------------------------------------------------------------- ;;
@@cmd_wait:

@@finish_cmd:
. . . . SUBI. . #5,. . R4. . . ; Rewind to program pointer in record.
. . . . MVO@. . R2,. . R4. . . ; \.
. . . . SWAP. . R2. . . . . . . ;. |-- Store program counter as double-byte
. . . . MVO@. . R2,. . R4. . . ; /. . data
. . . . ADDI. . #3,. . R4. . . ; point to next record.

. . . . B . . . @@next_bgmp. . ; No, do the next one.

. . . . ;; --------------------------------------------------------------- ;;
. . . . ;;. LOOPA/LOOPB:. Count down the loop counter.. If it goes -ve, . . ;;
. . . . ;;. we're just starting the loop so initialize it and branch. . . . ;;
. . . . ;;. If it goes 0, the loop is just finishing, so fall through.. . . ;;
. . . . ;;. Otherwise, store updated counter and branch.. . . . . . . . . . ;;
. . . . ;; --------------------------------------------------------------- ;;
@@cmd_loopb:
. . . . INCR. . R3. . . . . . . ; Point to loop counter B
@@cmd_loopa:
. . . . INCR. . R3. . . . . . . ; Point to loop counter A

. . . . MVI@. . R2,. . R0. . . ; Read argument to loop into R0
. . . . INCR. . R2. . . . . . . ;

. . . . MVI@. . R3,. . R5. . . ; read loop counter
. . . . DECR. . R5. . . . . . . ; count it down
. . . . BMI . . @@init_loop . . ; if it goes negative, we need to init it.
. . . . BEQ . . @@done_loop . . ; if it goes to zero, it's expiring

. . . . ;; --------------------------------------------------------------- ;;
. . . . ;;. +ve case:. Store updated counter and branch.. . . . . . . . . . ;;
. . . . ;; --------------------------------------------------------------- ;;
@@exec_loop:. . . . . . . . . . ; otherwise it was an active loop.
. . . . MVO@. . R5,. . R3. . . ; store updated loop counter

@@loop_jump:
. . . . ANDI. . #$FF,. R0. . . ; execute the jump.
. . . . XORI. . #$80,. R0. . . ;
. . . . SUBI. . #$80,. R0. . . ;
. . . . ADDR. . R0,. . R2. . . ;

. . . . B . . . @@finish_cmd. . ; finish this command.

. . . . ;; --------------------------------------------------------------- ;;
. . . . ;;. -ve case:. Initialize the loop counter and branch.. . . . . . . ;;
. . . . ;; --------------------------------------------------------------- ;;
@@init_loop:
. . . . SWAP. . R0. . . . . . . ;
. . . . MVO@. . R0,. . R3. . . ; initialize the loop counter.
. . . . SWAP. . R0. . . . . . . ;
. . . . B . . . @@loop_jump

. . . . ;; --------------------------------------------------------------- ;;
. . . . ;;. Zero case:. Zero out the counter and don't branch.. . . . . . . ;;
. . . . ;; --------------------------------------------------------------- ;;
@@done_loop:
. . . . MVO@. . R5,. . R3. . . ; store updated loop counter
. . . . B . . . @@finish_cmd. . ; and that's it.

. . . . ;; --------------------------------------------------------------- ;;
. . . . ;;. JUMP:. Just read the argument into the program counter.. . . . ;;
. . . . ;; --------------------------------------------------------------- ;;
@@cmd_jump:
. . . . MVI@. . R2,. . R2
. . . . B . . . @@finish_cmd. . . . . . ; Done.

. . . . ;; --------------------------------------------------------------- ;;
. . . . ;;. MOVE:. Read the X velocity, Y velocity into SPXYV table.. . . . ;;
. . . . ;; --------------------------------------------------------------- ;;
@@cmd_move:

. . . . MOVR. . R1,. . R5. . . . . . . ;\
. . . . ADDR. . R5,. . R5. . . . . . . ; |-- convert slot number to sprite
. . . . ADDI. . #SPXYV, R5. . . . . . . ;/. . X/Y velocity table pointer

. . . . ADDI. . #@@xvel_tbl + 64, R0. . ; Index into X velocity lookup table
. . . . MOVR. . R0,. . R3

. . . . MVI@. . R3,. . R0. . . . . . . ; Get X velocity from lookup
. . . . MVO@. . R0,. . R5. . . . . . . ; Write it to X vel for this sprite

. . . . ADDI. . #@@yvel_tbl - @@xvel_tbl, R3. . ; Index into Y vel lookup tbl
. . . . MVI@. . R3,. . R0. . . . . . . ; Get Y velocity from lookup
. . . . MVO@. . R0,. . R5. . . . . . . ; Write it to Y vel for this sprite.

. . . . B . . . @@finish_cmd. . . . . . ; Done.

. . . . ;; --------------------------------------------------------------- ;;
. . . . ;;. FIREA:. Make this bad guy drop a bomb. . . . . . . . . . . . . ;;
. . . . ;;. FIREB:. Make this bad guy fire a crater-maker. . . . . . . . . ;;
. . . . ;;. FIREC:. Make this bad guy shoot horizontally to the left.. . . ;;
. . . . ;; --------------------------------------------------------------- ;;
@@cmd_fire:.
. . . . MVII. . #@@firetype - 6, R3
. . . . ADDR. . R0,. . R3
. . . . MVI@. . R3,. . R0. . . ; read X/Y velocity
. . . . INCR. . R3
. . . . MVI@. . R3,. . R3. . . ; read sprite attribute index
. . . . CALL. . BGFIRE
. . . . B . . . @@finish_cmd

@@firetype:
. . . . DECLE. ((VBIAS + $40) SHL 8) + (VBIAS + $00) ; drop the bomb
. . . . DECLE. SPATBL.b2

. . . . DECLE. ((VBIAS + $40) SHL 8) + (VBIAS + $40) ; drop the crater maker
. . . . DECLE. SPATBL.b1

. . . . DECLE. ((VBIAS + $00) SHL 8) + (VBIAS - $80) ; fire left.
. . . . DECLE. SPATBL.b4

. . . . ;; --------------------------------------------------------------- ;;
. . . . ;;. DIE:. Time for this guy to die.. . . . . . . . . . . . . . . . ;;
. . . . ;; --------------------------------------------------------------- ;;
@@cmd_die:
. . . . CALL. . BGKILL
. . . . B . . . @@finish_cmd

. . . . ;; --------------------------------------------------------------- ;;
. . . . ;;. ATTR:. Set the Sprite Attribute for this sprite.. . . . . . . . ;;
. . . . ;; --------------------------------------------------------------- ;;
@@cmd_attr:
. . . . MVI@. . R2, . . R0. . . ; Get attribute
. . . . INCR. . R2
. . . . MOVR. . R1, . . R3. . . ; \
. . . . ADDI. . #SPAT,. R3. . . ;. |-- Store attribute number into slot
. . . . MVO@. . R0, . . R3. . . ; /. . in sprite attribute table.

. . . . B. . . @@finish_cmd

. . . .
. . . . ;; --------------------------------------------------------------- ;;
. . . . ;;. CLRHS:. Set the horizontal-scroll bit for this sprite. . . . . ;;
. . . . ;; --------------------------------------------------------------- ;;
@@cmd_clrhs:

. . . . ;; ---------------------------------------------------------------- ;;
. . . . ;;. SETHS:. Set the horizontal-scroll bit for this sprite. . . . . ;;
. . . . ;; ---------------------------------------------------------------- ;;
@@cmd_seths:
@@do_hs:
. . . . MOVR. . R1, . . R3
. . . . ADDI. . #@@shl_tbl, R3
. . . . MVI@. . R3, . . R3
. . . . MOVR. . R3, . . R0
. . . . COMR. . R3
. . . . AND . . SPHSCR, R3
;;. . . ADCR. . PC
. . . . XORR. . R0, . . R3
. . . . MVO . . R3, . . SPHSCR

. . . . B . . . @@finish_cmd

@@shl_tbl:
. . . . DECLE. 1, 2, 4, 8, 16
. . . .

@@done_bgmp:
. . . . PULR. . PC

@@xvel_tbl:
. . . . DECLE. VBIAS - $20, VBIAS - $40, VBIAS - $60, VBIAS - $7F. ; lf0..lf3
. . . . DECLE. VBIAS + $20, VBIAS + $40, VBIAS + $60, VBIAS + $7F. ; rg0..rg3
. . . . DECLE. VBIAS,. . . VBIAS,. . . VBIAS,. . . VBIAS. . . . ; up0..up3
. . . . DECLE. VBIAS,. . . VBIAS,. . . VBIAS,. . . VBIAS. . . . ; dn0..dn3

. . . . DECLE. VBIAS - $20, VBIAS - $40, VBIAS - $60, VBIAS - $7F. ; lu0..lu3
. . . . DECLE. VBIAS + $20, VBIAS + $40, VBIAS + $60, VBIAS + $7F. ; ru0..ru3
. . . . DECLE. VBIAS - $20, VBIAS - $40, VBIAS - $60, VBIAS - $7F. ; ld0..ld3
. . . . DECLE. VBIAS + $20, VBIAS + $40, VBIAS + $60, VBIAS + $7F. ; rd0..rd3

. . . . DECLE. VBIAS,. . . VBIAS - $08
. . . . ;; directions 33 .. 63 not defined yet.. in no hurry....

@@yvel_tbl:
. . . . DECLE. VBIAS,. . . VBIAS,. . . VBIAS,. . . VBIAS. . . . ; lf0..lf3
. . . . DECLE. VBIAS,. . . VBIAS,. . . VBIAS,. . . VBIAS. . . . ; rg0..rg3
. . . . DECLE. VBIAS - $20, VBIAS - $40, VBIAS - $60, VBIAS - $7F. ; up0..up3
. . . . DECLE. VBIAS + $20, VBIAS + $40, VBIAS + $60, VBIAS + $7F. ; dn0..dn3

. . . . DECLE. VBIAS - $20, VBIAS - $40, VBIAS - $60, VBIAS - $7F. ; lu0..lu3
. . . . DECLE. VBIAS - $20, VBIAS - $40, VBIAS - $60, VBIAS - $7F. ; ru0..ru3
. . . . DECLE. VBIAS + $20, VBIAS + $40, VBIAS + $60, VBIAS + $7F. ; ld0..ld3
. . . . DECLE. VBIAS + $20, VBIAS + $40, VBIAS + $60, VBIAS + $7F. ; rd0..rd3

. . . . DECLE. VBIAS,. . . VBIAS
. . . . ;; directions 33 .. 63 not defined yet.. in no hurry....

. . . . ENDP

And there it is. (The dots are added to preserve the original formatting, although it appears I'm not entirely successful. Ah well... it's pretty close.)

--Joe

This discussion has been archived. No new comments can be posted.

Good, working code heading for the wastebin *sniff*

Comments Filter:
  • Haven't found any programming contests lately?

    Also, why are you still hanging out on /.? We could use you [kuro5hin.org] over on k5! :)
    • Nope, no programming contests lately -- I wax and wane with those. I want to try to get my video game out the door -- it's been in development for too long.

      As for hanging out on /.? Because /. takes less mental effort. :-)

      --Joe

Things equal to nothing else are equal to each other.

Working...