Jump to content

Photo

Alien invasion

XB Demo Scroll

20 replies to this topic

#1 sometimes99er OFFLINE  

sometimes99er

    River Patroller

  • 4,225 posts
  • Location:Denmark

Posted Thu Jul 16, 2015 11:28 AM

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)::P$="38440F1D3F6F2909081C0000000000001C22F0B8FCF694901038000000000000"
180 CALL CHAR(40,P$)::P$=SEG$(P$,31,2)&SEG$(P$,1,30)&SEG$(P$,63,2)&SEG$(P$,33,30)::GOTO 180


#2 --- Ω --- OFFLINE  

--- Ω ---

    Hexacorerunner

  • 13,924 posts
  • Location:82.102.25.76

Posted Thu Jul 16, 2015 12:14 PM

DAMN!  That 3D effect just POPS  outta the screen! 

GREAT JOB!

 

gallery_35324_1027_2037025.gif

 

You guys never cease to amaze me in what you can pull off in such a small amount of code.



#3 Ksarul OFFLINE  

Ksarul

    Quadrunner

  • 5,270 posts

Posted Thu Jul 16, 2015 5:35 PM

I really like this! Thank you for coding it! :)



#4 Opry99er OFFLINE  

Opry99er

    Quadrunner

  • 10,731 posts
  • Location:Hustisford, WI

Posted Thu Jul 16, 2015 5:38 PM

Too flippin cool. As always, blown away...

#5 sometimes99er OFFLINE  

sometimes99er

    River Patroller

  • Topic Starter
  • 4,225 posts
  • Location:Denmark

Posted Fri Jul 17, 2015 1:32 AM

Thanks for feedback.  :thumbsup:



#6 Willsy OFFLINE  

Willsy

    River Patroller

  • 3,100 posts
  • Location:Uzbekistan (no, really!)

Posted Fri Jul 17, 2015 5:23 AM

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)::P$="38440F1D3F6F2909081C0000000000001C22F0B8FCF694901038000000000000"
180 CALL CHAR(40,P$)::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, Fri Jul 17, 2015 5:23 AM.


#7 Shift838 ONLINE  

Shift838

    River Patroller

  • 2,565 posts
  • SHIFT838
  • Location:Deer Park, Texas

Posted Fri Jul 17, 2015 2:51 PM

I get an issue when puting that code into TurboForth 1.2.1

 

I get to the below line and it just freezes up in my Classic99 

 

else drop then



#8 Asmusr OFFLINE  

Asmusr

    River Patroller

  • 3,110 posts
  • Location:Denmark

Posted Fri Jul 17, 2015 3:14 PM

 

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

 

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



#9 Willsy OFFLINE  

Willsy

    River Patroller

  • 3,100 posts
  • Location:Uzbekistan (no, really!)

Posted Fri Jul 17, 2015 3:33 PM

Chris if you're pasting in directly from the Web page it won't work. Paste it into notepad then copy and paste that into classic 99

#10 Willsy OFFLINE  

Willsy

    River Patroller

  • 3,100 posts
  • Location:Uzbekistan (no, really!)

Posted Fri Jul 17, 2015 3:35 PM

@Rasmus - yes what's its address?

#11 Shift838 ONLINE  

Shift838

    River Patroller

  • 2,565 posts
  • SHIFT838
  • Location:Deer Park, Texas

Posted Fri Jul 17, 2015 3:48 PM

Chris if you're pasting in directly from the Web page it won't work. Paste it into notepad then copy and paste that into classic 99

 

I tried putting it in notepad first then copying the text and still have the same issue.



#12 senior_falcon OFFLINE  

senior_falcon

    Stargunner

  • 1,485 posts
  • Location:Lansing, NY, USA

Posted Fri Jul 17, 2015 9:05 PM

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
 



#13 sometimes99er OFFLINE  

sometimes99er

    River Patroller

  • Topic Starter
  • 4,225 posts
  • Location:Denmark

Posted Fri Jul 17, 2015 10:34 PM

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


#14 Willsy OFFLINE  

Willsy

    River Patroller

  • 3,100 posts
  • Location:Uzbekistan (no, really!)

Posted Sat Jul 18, 2015 3:15 AM

:)

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:
Attached File  TF1.PNG   6.45KB   2 downloads
 
Then type UTILS and hit enter, and you'll see the UTILS menu:
Attached File  tf2.PNG   8.28KB   2 downloads
 
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.
Attached File  tf3.PNG   2.58KB   2 downloads
 
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.
Attached File  tf4.PNG   11.03KB   2 downloads
 
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 )
Attached File  tf5.PNG   2.45KB   2 downloads
 
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: Attached File  aliens.txt   1.66KB   9 downloads

 

Sorry for hijacking this thread!


Edited by Willsy, Sat Jul 18, 2015 3:22 AM.


#15 Opry99er OFFLINE  

Opry99er

    Quadrunner

  • 10,731 posts
  • Location:Hustisford, WI

Posted Sat Jul 18, 2015 4:24 AM

Mind.....blown.....

#16 Willsy OFFLINE  

Willsy

    River Patroller

  • 3,100 posts
  • Location:Uzbekistan (no, really!)

Posted Sat Jul 18, 2015 4:37 AM



#17 sometimes99er OFFLINE  

sometimes99er

    River Patroller

  • Topic Starter
  • 4,225 posts
  • Location:Denmark

Posted Sat Jul 18, 2015 5:31 AM

Here's Alien invasion adapted for XB256. The pixel scrolling routines make it quite a bit faster. This is running in XB, not compiled.


Thanks for doing it.  :thumbsup:

 

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


Super smooth. Yippee ki-yay!  :thumbsup:
 
Thanks for doing VSYNC and explaining.  :)

#18 senior_falcon OFFLINE  

senior_falcon

    Stargunner

  • 1,485 posts
  • Location:Lansing, NY, USA

Posted Mon Jul 20, 2015 7:42 PM

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.



#19 sometimes99er OFFLINE  

sometimes99er

    River Patroller

  • Topic Starter
  • 4,225 posts
  • Location:Denmark

Posted Mon Jul 20, 2015 10:56 PM

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.

 

;)



#20 senior_falcon OFFLINE  

senior_falcon

    Stargunner

  • 1,485 posts
  • Location:Lansing, NY, USA

Posted Tue Jul 21, 2015 9:30 AM

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.)



#21 sometimes99er OFFLINE  

sometimes99er

    River Patroller

  • Topic Starter
  • 4,225 posts
  • Location:Denmark

Posted Tue Jul 21, 2015 10:14 AM

Okay. :)

 

Thought it was more than a feeling, about the lack of speed with GCHAR. A quick test however, shows it's on par with a simple HCHAR. ;)







Also tagged with one or more of these keywords: XB, Demo, Scroll

0 user(s) are browsing this forum

0 members, 0 guests, 0 anonymous users