Jump to content
IGNORED

Alien invasion


sometimes99er

Recommended Posts

Derived from TI Basic Scrolling. ;)

 

It would be interesting to see a version with 2x2 tiles.

Well, couldn't help trying out something in XB ... :)

 

100 CALL CLEAR::CALL SCREEN(2)::CALL MAGNIFY(3)::CALL COLOR(2,1,1,3,16,1)
110 CALL CHAR(48,"071F3F7F7EF8E0C0C0C0004000000000E0F8FCB40200000000")
120 CALL CHAR(52,"0800000001071F3F3E34E030703010001000004AFCFFCFC501")
130 CALL CHAR(56,"0000000000000000010B1F0F0F0F0F0F000000000000303AFEFFFFFEFEFCF8F")
140 FOR I=0 TO 11::DISPLAY AT(I*2+1,1):RPT$("(*",14)&RPT$(")+",14);
150 IF I>8 THEN 170
160 R=RND*220+1::CALL SPRITE(#I*3+1,48,16,I*21+4,R,#I*3+2,52,5,I*21+4,R,#I*3+3,56,6,I*21+4,R)
170 NEXT I::CALL COLOR(2,7,1):$="38440F1D3F6F2909081C0000000000001C22F0B8FCF694901038000000000000"
180 CALL CHAR(40,P$):$=SEG$(P$,31,2)&SEG$(P$,1,30)&SEG$(P$,63,2)&SEG$(P$,33,30)::GOTO 180
  • Like 8
Link to comment
Share on other sites

Derived from TI Basic Scrolling. ;)

 

 

Well, couldn't help trying out something in XB ... :)

 

100 CALL CLEAR::CALL SCREEN(2)::CALL MAGNIFY(3)::CALL COLOR(2,1,1,3,16,1)
110 CALL CHAR(48,"071F3F7F7EF8E0C0C0C0004000000000E0F8FCB40200000000")
120 CALL CHAR(52,"0800000001071F3F3E34E030703010001000004AFCFFCFC501")
130 CALL CHAR(56,"0000000000000000010B1F0F0F0F0F0F000000000000303AFEFFFFFEFEFCF8F")
140 FOR I=0 TO 11::DISPLAY AT(I*2+1,1):RPT$("(*",14)&RPT$(")+",14);
150 IF I>8 THEN 170
160 R=RND*220+1::CALL SPRITE(#I*3+1,48,16,I*21+4,R,#I*3+2,52,5,I*21+4,R,#I*3+3,56,6,I*21+4,R)
170 NEXT I::CALL COLOR(2,7,1):$="38440F1D3F6F2909081C0000000000001C22F0B8FCF694901038000000000000"
180 CALL CHAR(40,P$):$=SEG$(P$,31,2)&SEG$(P$,1,30)&SEG$(P$,63,2)&SEG$(P$,33,30)::GOTO 180

 

I thought I would return your earlier compliment ;-) try this in TurboForth...

1000 constant DELAY
create alien hex
3844 , 0F1D , 3F6F , 2909 ,
081C , 0000 , 0000 , 0000 ,
1C22 , F0B8 , FCF6 , 9490 ,
1038 , 0000 , 0000 , 0000 ,
: udgs ( -- )
  data 4 071F 3F7F 7EF8 E0C0 100 dchar
  data 4 C0C0 0040 0000 0000 101 dchar
  data 4 E0F8 FCB4 0200 0000 102 dchar
  data 4 0000 0000 0000 0000 103 dchar
  data 4 0800 0000 0107 1F3F 104 dchar
  data 4 3E34 E030 7030 1000 105 dchar
  data 4 1000 004A FCFF CFC5 106 dchar
  data 4 0100 0000 0000 0000 107 dchar
  data 4 0000 0000 0000 0000 108 dchar
  data 4 010B 1F0F 0F0F 0F0F 109 dchar
  data 4 0000 0000 0000 303A 10A dchar
  data 4 FEFF FFFE FEFC F8F0 10B dchar
;
decimal
0 value row
0 value i*21+4
0 value index
: sprites ( index -- )
  dup 8 < if
    to index
    index 21 * 4 + to i*21+4
    220 rnd to row
    0 index 3 * +  i*21+4 row 0 15 sprite
    1 index 3 * +  i*21+4 row 4  4 sprite
    2 index 3 * +  i*21+4 row 8  5 sprite
  else drop then
; 
: aliens ( -- )
  12 0 do
    0 i 2* gotoxy   
    s" (*(*(*(*(*(*(*(*(*(*(*(*(*(*(*(*" type
    s" )+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+" type
    i sprites
  loop ;
: shift-alien ( -- )
  alien 16 ascii ( dchar
  [ alien 15 + ] literal c@  
  alien [ alien 1+ ] literal 15 cmove>
  alien c!
  [ alien 31 + ] literal c@
  [ alien 16 + ] literal [ alien 17 + ] literal 15 cmove>
  [ alien 16 + ] literal c!
;
: go ( -- )
  1 gmode   1 screen   2 magnify
  5 6 0 color   6 15 0 color
  udgs  aliens
  500 0 do
    shift-alien
    DELAY 0 do loop
  loop
;

Try differnt delay times. For example:

 

500 to delay go

250 to delay go

1 to delay go

 

:thumbsup:

Edited by Willsy
Link to comment
Share on other sites

gallery_34177_1071_785881.gif

Here's Alien invasion adapted for XB256. The pixel scrolling routines make it quite a bit faster. This is running in XB, not compiled. Code is below, with line 181 where the scrolling happens. (Scroll down 2 character definitions starting at ASC 40 and 2 character definitions starting at ASC 42):

90 CALL LINK("SCRN2")
100 CALL CLEAR :: CALL SCREEN(2):: CALL MAGNIFY(3):: CALL COLOR(2,1,1,3,16,1)
110 CALL CHAR(48,"071F3F7F7EF8E0C0C0C0004000000000E0F8FCB40200000000")
120 CALL CHAR(52,"0800000001071F3F3E34E030703010001000004AFCFFCFC501")
130 CALL CHAR(56,"0000000000000000010B1F0F0F0F0F0F000000000000303AFEFFFFFEFEFCF8F")
140 FOR I=0 TO 11 :: DISPLAY AT(I*2+1,1):RPT$("(*",14)&RPT$(")+",14);
150 IF I>8 THEN 170
160 R=RND*220+1 :: CALL SPRITE(#I*3+1,48,16,I*21+4,R,#I*3+2,52,5,I*21+4,R,#I*3+3,56,6,I*21+4,R)
170 NEXT I :: CALL LINK("COLOR2",2,7,1):: P$="38440F1D3F6F2909081C0000000000001C22F0B8FCF694901038000000000000"
180 CALL LINK("CHAR2",40,P$)
181 CALL LINK("SCPXDN",40,2,1,42,2,1):: GOTO 181

  • Like 1
Link to comment
Share on other sites

Nice, but instead of a random delay, could you wait for vsync?

:)

 

Yeah. I remember back in the early days of TurboForth, asking for a word like WAIT, - to be able to sync with VDP display.

 

I don't know if this is the "ultimate" way to do it, and if the read of the VDP Status register (to clear the interrupt bit there) is necessary ? Also/but with the vsync it seems essential, for many games and demos, to get the sprite collision flag while you're at it (vsync).

 

 

*	Wait
	CLR	@COINC
	MOVB	@VDPSTA,R0
	CLR	R12
VSYNC1	TB	2			* Test CRU bit for VDP interrupt
	JEQ	VSYNC1	   
	MOVB	@VDPSTA,R0
	ANDI R0,>2000
	SOC	R0,@COINC		* Save coincidence flag
*	Return
  • Like 1
Link to comment
Share on other sites

:)

 

Yeah. I remember back in the early days of TurboForth, asking for a word like WAIT, - to be able to sync with VDP display.

 

I don't know if this is the "ultimate" way to do it, and if the read of the VDP Status register (to clear the interrupt bit there) is necessary ? Also/but with the vsync it seems essential, for many games and demos, to get the sprite collision flag while you're at it (vsync).

 

 

*	Wait
	CLR	@COINC
	MOVB	@VDPSTA,R0
	CLR	R12
VSYNC1	TB	2			* Test CRU bit for VDP interrupt
	JEQ	VSYNC1	   
	MOVB	@VDPSTA,R0
	ANDI R0,>2000
	SOC	R0,@COINC		* Save coincidence flag
*	Return

 

Okay, that's quite easy to do.

 

TurboForth has an assembler (fbForth also). But it's not like the Editor Assembler. It integrates into the Forth system itself, so when the assembler is loaded, the system just 'understands' assembly language in the same way as it understands Forth words. You can type assembly code at the keyboard just like you can type Forth code. You can then immediately run it and test it, just like a Forth word. How cool is that!

 

The assembly language is of a different flavour to regular assembler. The biggest thing is that the assembly instruction comes *after* the operands!

 

Regular Assembler:

MOV R0,R5

 

Forth Assembler:

R0 R5 MOV,

 

The reason for this? Each assembler instruction is *in reality* a Forth word, and it is a mini assembler. So, MOV, is a Forth word that knows how to compile MOV instructions and all its variants. R0 is (in reality) just a word that pushes 0 to the stack. R5 is a word that pushes 5 to the stack. MOV, takes the operands off the stack and assembles them into machine code.

 

So, with a little experience, it's very easy to write machine code in TurboForth. Here's the VSYNC code which took me about a minute to write (copied from Sometimes' code):

 

 

$8802 constant VDPSTA
asm: VSYNC ( -- coinc )
    r12 r11 mov,        \ save r12
    r1 clr,
    VDPSTA @@ r0 movb,  \ get vdp status in r0
    r12 clr,            \ clear for cru operations
    begin,
      2 tb,             \ test vsync
    ne until,           \ loop until not equal
    VDPSTA @@ r0 movb,  \ dunno why we need this :-)
    r0 $2000 andi,      \ check sprite coincidence
    sp dect,            \ make space on data stack
    r0 *sp mov,         \ move coinc to stack
    r11 r12 mov,        \ restore r12
;asm

 

 

Two things to note:

  • I used a constant to define VDPSTA, just to be clever. You could just use the value $8802 in your code and save a few bytes of memory.
  • I decided the best (most Forthy way) of dealing with the coinc information is to just push the coinc flag to the data stack. That's how Forth words communicate, via the stack, so this word pushes the coinc flag to the stack, as shown in the stack signature. If you are using VSYNC in Forth in code and you don't want the coinc flag, just DROP it.

So, how do we actually *use* this in TurboForth? Well, TurboForth comes with a utilities disk (I think default installs of Classic99 have it installed in DSK1 - Look for a file called BLOCKS in the DSK1 folder.)

 

All you have to do is let TurboForth boot. It will find the BLOCKS file and boot from it. It'll present you with a menu:

post-24932-0-31888500-1437208376_thumb.png

 

Then type UTILS and hit enter, and you'll see the UTILS menu:

post-24932-0-17458500-1437208494_thumb.png

 

You'll see the assembler is listed on block 9. So, just type 9 LOAD and press enter, and the assembler is loaded from the disk, in source code form and compiled on the fly.

post-24932-0-49587100-1437208620_thumb.png

 

That's it. The system can now accept Assembler definitions in the same way as Forth definitions.

 

You can now past the code above in. In my experience, pasting directly from web pages causes problems. I copy the text from the web page, paste into Notepad++ then copy and paste that into Classic99.

post-24932-0-67901000-1437208782_thumb.png

 

You would test it like you would test any other Forth word: By typing its name. Note that it pushes a value to the stack.

 

So, quite cool. There's one problem though. As written, it would mean the assembler has to be loaded every time you want to want run/load this program. That's not a major deal, the assembler is only 2.7K - but it would be nice if we could use machine code (note: machine code, not assembler) to represent our assembler code, so that we don't need the assembler.

 

We can.

 

Type FILES again. Note the Assembler to code utility on block 29. Go ahead and load that. ( 29 LOAD )

post-24932-0-01678300-1437209224.png

 

Using this utility, we can convert the assembler code into machine code. Even better, rather that writing the assembler code to a file, in Classic99 we can have it write the machine code out to the paste buffer, and you can then paste it into your source code in Notepad++ or whatever:

 

asm>code vsync clip

 

CLIP is the Classic99 virtual paste buffer. It works like a disk - anything you write to it ends up in the paste buffer. At this point. a CODE equivalent of VSYNC is in the paste buffer:

 

CODE: VSYNC                                                   
C2CC 04C1 D020 8802 04CC 1F02 13FE D020 8802 0240 2000 0644   
C500 C30B ;CODE                                               

 

Now, the original assembler definition above can be replaced with this machine code definition. However, there's a little gotcha. The values produced by the ASM>CODE utility are in hex. So, the system needs to be in hex when loading CODE definitions:

 

hex
CODE: VSYNC                                                   
C2CC 04C1 D020 8802 04CC 1F02 13FE D020 8802 0240 2000 0644   
C500 C30B ;CODE 
decimal

 

So, here's the Forth code with a machine code version of VSYNC:

 

1000 constant DELAY
create alien hex
3844 , 0F1D , 3F6F , 2909 ,
081C , 0000 , 0000 , 0000 ,
1C22 , F0B8 , FCF6 , 9490 ,
1038 , 0000 , 0000 , 0000 ,
: udgs ( -- )
  data 4 071F 3F7F 7EF8 E0C0 100 dchar
  data 4 C0C0 0040 0000 0000 101 dchar
  data 4 E0F8 FCB4 0200 0000 102 dchar
  data 4 0000 0000 0000 0000 103 dchar
  data 4 0800 0000 0107 1F3F 104 dchar
  data 4 3E34 E030 7030 1000 105 dchar
  data 4 1000 004A FCFF CFC5 106 dchar
  data 4 0100 0000 0000 0000 107 dchar
  data 4 0000 0000 0000 0000 108 dchar
  data 4 010B 1F0F 0F0F 0F0F 109 dchar
  data 4 0000 0000 0000 303A 10A dchar
  data 4 FEFF FFFE FEFC F8F0 10B dchar
;
 
decimal
0 value row
0 value i*21+4
0 value index
: sprites ( index -- )
  dup 8 < if
    to index
    index 21 * 4 + to i*21+4
    220 rnd to row
    0 index 3 * +  i*21+4 row 0 15 sprite
    1 index 3 * +  i*21+4 row 4  4 sprite
    2 index 3 * +  i*21+4 row 8  5 sprite
  else drop then
;
 
: aliens ( -- )
  12 0 do
    0 i 2* gotoxy  
    s" (*(*(*(*(*(*(*(*(*(*(*(*(*(*(*(*" type
    s" )+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+" type
    i sprites
  loop ;
 
: shift-alien ( -- )
  alien 16 ascii ( dchar
  [ alien 15 + ] literal c@ 
  alien [ alien 1+ ] literal 15 cmove>
  alien c!
  [ alien 31 + ] literal c@
  [ alien 16 + ] literal [ alien 17 + ] literal 15 cmove>
  [ alien 16 + ] literal c!
;
 
hex
CODE: VSYNC                                                  
C2CC 04C1 D020 8802 04CC 1F02 13FE D020 8802 0240 2000 0644  
C500 C30B ;CODE
decimal
 
: go ( -- )
  1 gmode   1 screen   2 magnify
  5 6 0 color   6 15 0 color
  udgs  aliens
  500 0 do
    VSYNC drop shift-alien
  loop
;

 

It's also attached as a text file: aliens.txt

 

Sorry for hijacking this thread!

Edited by Willsy
  • Like 2
Link to comment
Share on other sites

I just ran some speed tests on Alien Invasion. To scroll down 10 rows of aliens:

Standard XB program was about 74 seconds

XB256 using screen2 and CALL LINK("CHAR2") instead of CHAR was about 36 seconds.

Using XB256 with . the scrolling routines posted in the program above was about 13 seconds.

The big surprise for me was how sluggish CHAR is. When I saw the demo I thought that two CHARs were being done which gives that cool look like the aliens are walking. Maybe I should modify XB256 by adding CALL LINK("CHAR") which would run the same as CHAR2.

  • Like 1
Link to comment
Share on other sites

The big surprise for me was how sluggish CHAR is. Maybe I should modify XB256 by adding CALL LINK("CHAR") which would run the same as CHAR2.

As I understand, certain XB256 programs can not be compiled, if they use XB functionality not available in the compiler ? But then most could "easily" have the parts rewritten ?

 

So the suggested added function would only benefit programs not compiled and then having to make heavy use of CHAR one way or another (loops or between "chapters"). In that case, I would not include it.

 

If you decide to do it anyway, you might also look at what I think is a relatively slow GCHAR.

 

;)

Link to comment
Share on other sites

As I understand, certain XB256 programs can not be compiled, if they use XB functionality not available in the compiler ? But then most could "easily" have the parts rewritten ?

 

So the suggested added function would only benefit programs not compiled and then having to make heavy use of CHAR one way or another (loops or between "chapters"). In that case, I would not include it.

 

If you decide to do it anyway, you might also look at what I think is a relatively slow GCHAR.

 

;)

Almost all of XB256 is supported by the compiler. The only useful thing that is not supported is the disk catalog program CALL LINK("CAT"). This is an old program of mine and not very tightly coded and I didn't think it made sense to spend the memory on it. There are a couple other routines for creating sound lists, which you would want to do from XB anyway. Of course, a program written for XB256 must still follow the limitations of the compiler - integer arithmetic, no trig functions, etc.

 

True, CALL LINK("CHAR",...) would only benefit an XB program. When compiled, CALL LINK("CHAR") and CALL CHAR would create identical code, so other than making the XB program run faster there would be no reason to choose one over the other. The speed increase in XB is big - CALL LINK("CHAR2") is almost 5 times faster than CALL CHAR when using a 64 character hexadecimal string! CALL CHAR takes almost .3 seconds with a string that length! Adding CALL LINK("CHAR") would be trivial-just set a pointer to the start of the table, then jump to the CHAR2 code.

 

You may feel that GCHAR is slow, but actually it runs about as fast as it can. In general, a CALL takes around .02 seconds and that is about how much time GCHAR takes. CALL LINK also takes about .02 seconds to go to an assembly subroutine and return, so you can see there is not much room for improvement there. (BASIC CALLS take about .05 seconds which is why it is so slow.)

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...