sometimes99er Posted July 16, 2015 Share Posted July 16, 2015 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 8 Quote Link to comment Share on other sites More sharing options...
Omega-TI Posted July 16, 2015 Share Posted July 16, 2015 DAMN! That 3D effect just POPS outta the screen! GREAT JOB! You guys never cease to amaze me in what you can pull off in such a small amount of code. 5 Quote Link to comment Share on other sites More sharing options...
+Ksarul Posted July 16, 2015 Share Posted July 16, 2015 I really like this! Thank you for coding it! Quote Link to comment Share on other sites More sharing options...
Opry99er Posted July 16, 2015 Share Posted July 16, 2015 Too flippin cool. As always, blown away... Quote Link to comment Share on other sites More sharing options...
sometimes99er Posted July 17, 2015 Author Share Posted July 17, 2015 Thanks for feedback. Quote Link to comment Share on other sites More sharing options...
Willsy Posted July 17, 2015 Share Posted July 17, 2015 (edited) 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 Edited July 17, 2015 by Willsy Quote Link to comment Share on other sites More sharing options...
Shift838 Posted July 17, 2015 Share Posted July 17, 2015 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 Quote Link to comment Share on other sites More sharing options...
Asmusr Posted July 17, 2015 Share Posted July 17, 2015 I thought I would return your earlier compliment try this in TurboForth... Nice, but instead of a random delay, could you wait for vsync? Quote Link to comment Share on other sites More sharing options...
Willsy Posted July 17, 2015 Share Posted July 17, 2015 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 Quote Link to comment Share on other sites More sharing options...
Willsy Posted July 17, 2015 Share Posted July 17, 2015 @Rasmus - yes what's its address? Quote Link to comment Share on other sites More sharing options...
Shift838 Posted July 17, 2015 Share Posted July 17, 2015 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. Quote Link to comment Share on other sites More sharing options...
senior_falcon Posted July 18, 2015 Share Posted July 18, 2015 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 170160 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 1 Quote Link to comment Share on other sites More sharing options...
sometimes99er Posted July 18, 2015 Author Share Posted July 18, 2015 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 1 Quote Link to comment Share on other sites More sharing options...
Willsy Posted July 18, 2015 Share Posted July 18, 2015 (edited) 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: Then type UTILS and hit enter, and you'll see the UTILS menu: 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. 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. 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 ) 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 July 18, 2015 by Willsy 2 Quote Link to comment Share on other sites More sharing options...
Opry99er Posted July 18, 2015 Share Posted July 18, 2015 Mind.....blown..... 1 Quote Link to comment Share on other sites More sharing options...
Willsy Posted July 18, 2015 Share Posted July 18, 2015 https://www.youtube.com/watch?v=zYLqYW_RUaA 1 Quote Link to comment Share on other sites More sharing options...
sometimes99er Posted July 18, 2015 Author Share Posted July 18, 2015 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. So, here's the Forth code with a machine code version of VSYNC: Super smooth. Yippee ki-yay! Thanks for doing VSYNC and explaining. 1 Quote Link to comment Share on other sites More sharing options...
senior_falcon Posted July 21, 2015 Share Posted July 21, 2015 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. 1 Quote Link to comment Share on other sites More sharing options...
sometimes99er Posted July 21, 2015 Author Share Posted July 21, 2015 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. Quote Link to comment Share on other sites More sharing options...
senior_falcon Posted July 21, 2015 Share Posted July 21, 2015 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.) Quote Link to comment Share on other sites More sharing options...
sometimes99er Posted July 21, 2015 Author Share Posted July 21, 2015 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. 1 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.