### Author Topic: Assembly routine to move a bullet  (Read 1347 times)

0 Members and 1 Guest are viewing this topic.

#### AMSDOS

• Supporter
• 6128 Plus
• Posts: 3.939
• Country:
• Liked: 1159
• Likes Given: 1931
##### Assembly routine to move a bullet
« on: 07:26, 14 September 17 »
I previously posted a structured BASIC Shoot-em-up engine in this thread with uses this bit of BASIC to move a bullet or two:

Code: [Select]
`1210 FOR n=b TO t1220   LOCATE bx(n),by(n)1230   PRINT" ";1240   PEN 31250   bx(n)=bx(n)+11260   LOCATE bx(n),by(n)1270   PRINT b\$;1280   IF bx(n)=38 THEN LOCATE 38,by(n):PRINT" ";:b=b+11290 NEXT n1300 IF bx(n-1)=38 AND b=3 THEN GOSUB 1590`

though now I curious to try and write this in Assembly, this is what I've done so far:

Code: [Select]
` org &9000 ;; CALL &9000,bx(n),by(n),tot ld a,(ix+00) ;; tot;; ld h,(ix+05) ;; blank value ld l,(ix+04) ;; l:=bx(n) ld (scount),a ;; scount:=tot ld d,0 ;; d:=0 ld e,a ;; e:=tot ld a,l ;; a:=bx(n) ld hl,bx ;; hl:=addr(bx) call poke ;; poke hl+tot-1,bx(n) ld l,(ix+02) ;; l:=by(n);; ld h,(ix+03) ;; blank value ld a,(scount) ;; a:=scount (tot) ld d,0 ;; d:=0 ld e,a ;; e:=scount (tot) ld a,l ;; a:=by(n) ld hl,by ;; hl:=addr(by) call poke ;; poke hl+tot-1,by(n).loop ;; main loop ld a,(bx) ld h,a ld a,(by) ld l,a call &bb75 ld a,32 call &bb5a ld a,(bx) inc a ld (bx),a ld a,(bx) ld h,a ld a,(by) ld l,a call &bb75 ld a,45 call &bb5a ld a,(fcount) ;; a:=fcount inc a ;; a:=a+1 ld (fcount),a ;; fcount:=a ld b,a ;; b:=a ld a,(scount) ;; a:=scount (tot) cp b ;; if a<>b then jr nz,loop ;;   goto loop ld a,(frest) ld hl,fcount ld (hl),a ret ;; back to BASIC.poke add hl,de ;; addr(bx or by):=addr(bx or by)+tot dec hl ;; addr(bx or by):=addr(bx or by)-1 ld (hl),a ;; poke addr(bx or by),bx(n) or by(n) ret ;; return.bx defb 0,0 ;; bx(1)..bx(2) - Bullets x 1 and 2.by defb 0,0 ;; by(1)..by(2) - Bullets y 1 and 2.fcount defb 0 ;; fcount.scount defb 0 ;; scount (tot).frest defb 0 ;; frest  (bot)`

At the moment it works when 1 bullet has to move and the good news is it's very fast. What I've done in the initial code is to get the values for bx & by array's & tot which can either be 1 or 2 to correctly put the bullets in bx(1) or bx(2) and by(1) or by(2). When I've setup the loop though, I'm having problems in how I need to gather the data from bx(2) & by(2), and what I want to try with the loop is to have it pass back to access the data from those positions.

Earlier I was doing something this to access it:

Code: [Select]
`.loop ld hl,bxpos ld a,(hl) ld d,a ld hl,bypos ld a,(hl) ld e,a ex hl,de call &bb75 .. ld hl,(bxpos) inc hl ld (bxpos),hl.bxpos defw bx.bypos defw by`

though it led to other complications (mainly lack of control), though I thought I should have enough information that I'm passing from BASIC in order simply have it loop around. Anyone got any suggestions what I need to add to make the loop work for the 2nd pass?
* Using the old Amstrad Languages    * with the Firmware
* I also like to problem solve code in BASIC    * And type-in Type-Ins!

Home Computing Weekly Programs
Popular Computing Weekly Programs
Updated Other Program Links on Profile Page (Update April 16/15 phew!)
Programs for Turbo Pascal 3

#### AMSDOS

• Supporter
• 6128 Plus
• Posts: 3.939
• Country:
• Liked: 1159
• Likes Given: 1931
##### Re: Assembly routine to move a bullet
« Reply #1 on: 10:04, 14 September 17 »
Seems to be too difficult to do a 2-Bullet routine approach, so I've gone to the 1-Bullet, the loop has been removed, bx, by are single bytes & no 3rd parameter, so no calculating where everything has to go. The only thing which needs checking is when bx gets to the end of the screen, delete the character & reset bx/by to 0.

Code: [Select]
` org &9000 ;; CALL &9000,bx,by ld a,(ix+02) ;; a:=bx ld (bx),a ;; bx:=a ld a,(ix+00) ;; a:=by ld (by),a ;; by:=a ld hl,(by) ;; l:=bx h:=by call &bb75 ld a,32 call &bb5a ld a,(bx) ;; a:=bx inc a ;; a:=a+1 ld (bx),a ;; bx:=a ld hl,(by) ;; l:=bx h:=by call &bb75 ld a,45 call &bb5a ret ;; back to BASIC.by defb 0 ;; x position of bullet.bx defb 0 ;; y position of bullet`
* Using the old Amstrad Languages    * with the Firmware
* I also like to problem solve code in BASIC    * And type-in Type-Ins!

Home Computing Weekly Programs
Popular Computing Weekly Programs
Updated Other Program Links on Profile Page (Update April 16/15 phew!)
Programs for Turbo Pascal 3

#### AMSDOS

• Supporter
• 6128 Plus
• Posts: 3.939
• Country:
• Liked: 1159
• Likes Given: 1931
##### Re: Assembly routine to move a bullet
« Reply #2 on: 13:21, 14 September 17 »
What I ended up doing after I added some checking to my assembly code is taking that BASIC example earlier and incorporating the machine code into it:

Code: [Select]
`100 ' Setup Inks and Screen Mode110 INK 0,0120 INK 1,26130 INK 2,20140 INK 3,18150 BORDER 11160 PAPER 0170 PEN 1180 MODE 1190 GOSUB 1700 ' Poke Move Bullet to Memory200 ' Define Characters & Objects210 DEFINT a-z220 s\$=CHR\$(143)230 a\$="@"240 b\$="-"250 x=1260 y=1270 DIM bx(2)280 DIM by(2)290 b=1300 t=0310 sc=0320 ay=1+INT(RND*23)330 ax=37340 GOSUB 810 ' Print Ship350 GOSUB 1010 ' Print Alien360 LOCATE 1,25370 PRINT"Score:"400 ' Main Loop410 WHILE 1420   IF INKEY(1)<>-1 AND x<30 THEN GOSUB 910:x=x+1:GOSUB 810430   IF INKEY(8)<>-1 AND x>1 THEN GOSUB 910:x=x-1:GOSUB 810440   IF INKEY(0)<>-1 AND y>1 THEN GOSUB 910:y=y-1:GOSUB 810450   IF INKEY(2)<>-1 AND y<24 THEN GOSUB 910:y=y+1:GOSUB 810460   GOSUB 710470   GOSUB 1140 : GOSUB 1010 ' Delete & Reprint Alien480   IF INKEY(47)<>-1 AND t<>2 THEN t=t+1:bx(t)=x+1:by(t)=y490   IF t<>0 THEN GOSUB 1210500 WEND600 ' Has bullet or alien collided?610 IF ((bx(1)=ax) AND (by(1)=ay)) OR ((bx(2)=ax) AND (by(2)=ay)) THEN GOSUB 1410620 RETURN700 ' Has Alien Collided with Ship?710 IF (x=ax) AND (y=ay) THEN GOSUB 1410:LOCATE 15,12:PRINT"You're Dead!":END720 RETURN800 ' Display Ship810 LOCATE x,y820 PEN 1830 PRINT s\$;840 RETURN900 ' Delete Ship910 LOCATE x,y920 PRINT" ";930 RETURN1000 ' Display and Move Alien1010 LOCATE ax,ay1020 PEN 21030 PRINT a\$;1040 ax=ax-11050 GOSUB 7101060 WHILE ax=01070   LOCATE 1,ay1080   PRINT" ";1090   ax=371100   ay=1+INT(RND*23)1110 WEND1120 GOSUB 6101130 RETURN1140 LOCATE ax+1,ay1150 PRINT" ";1160 RETURN1200 ' Routine to Move Shots Fired1210 FOR n=b TO t1220   CALL &9000,bx(n),by(n)1230   bx(n)=PEEK(&9049):by(n)=PEEK(&9048)1280   IF PEEK(&9049)=0 THEN b=b+11290 NEXT n1300 IF PEEK(&9049)=0 AND b=3 THEN GOSUB 15901310 GOSUB 6101320 RETURN1400 ' Death Sequence for Alien or Ship should they Collide1410 LOCATE ax,ay1420 PRINT" ";CHR\$(238);1430 sc=sc+201440 LOCATE 8,251450 PRINT sc;1460 ax=391470 ay=1+INT(RND*23)1480 FOR v=15 TO 0 STEP -11490   BORDER 61500   SOUND 1,0,3,v,,,311510   BORDER 111520   SOUND 2,1000,3,v,,,31 1530 NEXT v1540 FOR c=1 TO t1550   LOCATE bx(c),by(c)1560   PRINT" ";1570   bx(c)=0:by(c)=01580 NEXT c1590 b=1:t=01600 RETURN1700 MEMORY &8FFF:ln=1760:FOR adr=&9000 TO &904F STEP 161710 READ b\$:chk=0:FOR i=0 TO 151720 v=VAL("&"+MID\$(b\$,i*2+1,2))1730 POKE adr+i,v:chk=chk+v:NEXT1740 IF chk<>VAL("&"+RIGHT\$(b\$,3)) THEN PRINT"ERROR In Line";ln:STOP1750 ln=ln+10:NEXT:RETURN1760 DATA DD7E02324990DD7E003248902A4890CD69C1770 DATA 75BB3E20CD5ABB3A49903C3249902A4863C1780 DATA 90CD75BB3E2DCD5ABB3A4990FE2620177481790 DATA 3A4990673A48906FCD75BB3E20CD5ABB7381800 DATA AF324990324890C9000000000000000038D`

however I was able to make it a 2-bullet shoot-em-up by using BASIC code for where I was having difficulty writing the assembly which includes the Array and the varying FOR Loop which is subject to change depending on what the 'b' & 't' variables equal (which is what I'm mostly having trouble grasping to write in assembly). Naturally once the positions have been recalculated in the M/C routine, bx(n) & by(n) needs to know the new values, which is what Line 1230 does & b is altered when the address position of bx @ &9049 equals 0. Likewise the second IF in line 1300 checks if bx =0 and b=3 to reset.

It's definitely an improvement over the original BASIC, there is some slowdown, though not as noticeable as the original, which I'm happy with.

This was what I came up with, with the routine above after I added the check routine:

Code: [Select]
` org &9000 ;; CALL &9000,bx,by ld a,(ix+02) ;; a:=bx ld (bx),a ;; bx:=a ld a,(ix+00) ;; a:=by ld (by),a ;; by:=a ld hl,(by) ;; l:=bx h:=by call &bb75 ld a,32 call &bb5a ld a,(bx) ;; a:=bx inc a ;; a:=a+1 ld (bx),a ;; bx:=a ld hl,(by) ;; l:=bx h:=by call &bb75 ld a,45 call &bb5a ld a,(bx) ;; a:=bx cp 38 ;; if a<>38 jr nz,exit ;;  then goto exit ld a,(bx) ld h,a ld a,(by) ld l,a call &bb75 ;; locate bx,by ld a,32 call &bb5a ;; print" " xor a ;; a:=0 ld (bx),a ;; bx:=0 ld (by),a ;; by:=0.exit ret ;; back to BASIC.by defb 0 ;; x position of bullet.bx defb 0 ;; y position of bullet`
* Using the old Amstrad Languages    * with the Firmware
* I also like to problem solve code in BASIC    * And type-in Type-Ins!

Home Computing Weekly Programs
Popular Computing Weekly Programs
Updated Other Program Links on Profile Page (Update April 16/15 phew!)
Programs for Turbo Pascal 3

#### ervin

• Supporter
• 6128 Plus
• Posts: 1.444
• Country:
• Liked: 1140
• Likes Given: 1370
##### Re: Assembly routine to move a bullet
« Reply #3 on: 15:50, 14 September 17 »
That's rather cool.

I wonder if you could make a simple version of something like Tempest with this engine?

#### AMSDOS

• Supporter
• 6128 Plus
• Posts: 3.939
• Country:
• Liked: 1159
• Likes Given: 1931
##### Re: Assembly routine to move a bullet
« Reply #4 on: 11:43, 15 September 17 »
That's rather cool.

Thanks.

Quote
I wonder if you could make a simple version of something like Tempest with this engine?

I'll have to play Tempest to find out, from the screenshots I looked it looks like you bear down on the aliens and give them a good blasting. At the moment the idea I'm playing at with this is a Defender / Planet Smashers sort of game. Defender in it's Horizontal nature, Planet Smashers in that if the Alien gets past you a little bit of shielding is depleted. It's pretty simple, though I'll only have 10 Lines to write it in, which means I won't be able to use this Assembly code (unless I submit for the WILD category).

* Using the old Amstrad Languages    * with the Firmware
* I also like to problem solve code in BASIC    * And type-in Type-Ins!

Home Computing Weekly Programs
Popular Computing Weekly Programs
Updated Other Program Links on Profile Page (Update April 16/15 phew!)
Programs for Turbo Pascal 3

#### fgbrain

• CPC6128
• Posts: 247
• Country:
• Liked: 161
• Likes Given: 326
##### Re: Assembly routine to move a bullet
« Reply #5 on: 22:03, 15 September 17 »
Just went through your code and I can suggest a small optimization trick:
Code: [Select]
`LD HL„bx INC (HL)  or DEC (HL)`

is faster and shorter...

Moreover, you can just use this code
Code: [Select]
`LD HL,(by)CALL #BB75`
_____

6128 (UK keyboard, Crtc type 0/2), 6128+ (UK keyboard), 3.5" and 5.25" drives, Reset switch and Digiblaster (selfmade), Inicron Romram box, Bryce Megaflash, SVideo & PS/2 mouse, , Magnum Lightgun, X-MEM, X4 Board, C4CPC, Multiface2 X4, RTC X4 and Gotek USB Floppy emulator.

#### AMSDOS

• Supporter
• 6128 Plus
• Posts: 3.939
• Country:
• Liked: 1159
• Likes Given: 1931
##### Re: Assembly routine to move a bullet
« Reply #6 on: 12:45, 16 September 17 »
Just went through your code and I can suggest a small optimization trick:
Code: [Select]
`LD HL„bx INC (HL)  or DEC (HL)`

is faster and shorter...

Ah yes thanks!

Quote
Moreover, you can just use this code
Code: [Select]
`LD HL,(by)CALL #BB75`

Yes I forgot to change that because initially I thought I had to increase the value of bx to delete it when it gets close to the end of the screen. Once I realised I didn't need it, I reversed the by, bx labels so I could get the right values into h & l for the Locate routine, but couldn't be bother changing the rest!

I've amended the program so the lines to change are as follows:

Code: [Select]
`1760 DATA DD7E02324190DD7E003240902A4090CD6841770 DATA 75BB3E20CD5ABB214190342A4090CD756D21780 DATA BB3E2DCD5ABB3A4190FE2620122A40906631790 DATA CD75BB3E20CD5ABBAF324190324090C97BA1800 DATA 000000000000000000000000000000000001230   bx(n)=PEEK(&9041):by(n)=PEEK(&9040)1280   IF PEEK(&9041)=0 THEN b=b+11300 IF PEEK(&9041)=0 AND b=3 THEN GOSUB 1590`

In addition to while I was testing the routine I found a bug, which can be corrected by altering the following line:

Code: [Select]
`1540 FOR c=b TO t`

The reason this is occurring now is because the M/C routine is returning bx(1) and by(1) to 0, this was quite tricky to track down as when I first discovered it, I tried to determine why it occurred, but it wasn't happening when I was too busy shooting blobs onscreen, however if the 1st bullet reaches the end of the screen, it gets deleted and reset to 0, the error occurs when I use my 2nd bullet to shoot the blob which triggers the Improper Argument. The routine between 1540..1580 is used to delete any remaining bullets onscreen (should one find a blob), as the 1st has disappeared, it makes that routine invalid, the b variable can be used to skip should that possibility occur, if the 2nd bullets misses then the routine won't get that far to become a problem (since it's part of the detect, though would if the blob hits the square, need to check if that could cause an error).
* Using the old Amstrad Languages    * with the Firmware
* I also like to problem solve code in BASIC    * And type-in Type-Ins!

Home Computing Weekly Programs
Popular Computing Weekly Programs