Jump to content
IGNORED

Bricks (demo)


Recommended Posts

Here's a little XB demo. Nothing too beautiful about it.

 

First of all I'm having a little brick. It's 2 characters wide, and 1 character high. Has a bit of 3D effect inside. And then there's a shadow from the brick. An effect often used in those breakout style games.

 

The bricks are put randomly to the screen. The shadow are then put to the screen too. The shadow has to respect a few rules though. First of all the shadow is only drawn if there's not a brick there. Secondly if there's already some shadow there, the old and new shadows has to merge together. - Like if there's some shadow there from a brick above, and we're trying to put some shadow to the right of a brick, then that screen character has to contain shadows from both bricks. This is done using bit mask operations. Nothing too clever about this, but a nice touch anyhow.

 

The code could probably be much better with different aspects in mind. Readability, speed, comments, structure, compactness, cleverness etc. Some of these probably contradict the other - much like real life. Anyway, if you have any questions, go ahead, and I'll try to dissect and explain.

 

This message only has the code included below, no graphics, animation or video for now.


Edit. My code and smiley has disappeared. And I can't find my original code in my archive.
 

Edited by sometimes99er
Forum update or something
  • Like 1
Link to comment
Share on other sites

Pretty cool! I changed the shadow to 1 pixel though, 2 pixels seemed too big. It would also be nice to have a gray shadow to be more subtle, but that would mean removing the white bricks. I tried to round the corners, but forgot that the background color of the character would show through instead of the screen background. Doh! :-)

 

Use the TI BASIC Translator to make XB code (http://codehackcreate.com/archives/237)

 

CALL CLEAR::
CALL SCREEN(14)

// Shadow masks
P1$(0)="0000"::
P1$(1)="8000"::
P1$(2)="3F00"::
P1$(3)="FF00"

P2$(0)="0"::
P2$(1)="80808080808"

// Define characters
FOR B=0 TO 1::
 FOR A=0 TO 3::
   CALL CHAR(32 + A + B * 4, P1$(A) & P2$(B))::
 NEXT A::
NEXT B

// Set up colors and define brick characters.  The definition
// is for the dark color of the brick.
FOR A=0 TO 6::
 CALL CHAR(40+A*8, "0000000000003F7F010303030303FFFF")
 READ FC, BC::
 CALL COLOR(2+A, FC, BC)::
NEXT A

DATA 3,4,5,6,7,9,9,10,11,12,13,3,15,16

RandomNumber:
 R=INT(RND*23)+1::
 C=INT(RND*30)+1::

CALL GCHAR(R, C, G)::
IF G>39 THEN RandomNumber

CALL GCHAR(R, C+1, G)::
IF G>39 THEN RandomNumber

I=INT(RND*7)*8+40::
CALL HCHAR(R, C, I)::
CALL HCHAR(R, C+1, I+1)

// Check to the right
CheckRight:
 CALL GCHAR(R, C+2, G)::
 IF G>38 THEN CheckDown
 CALL HCHAR(R, C+2, G OR 4)

CheckDown:
 CALL GCHAR(R+1, C, G)::
 IF G>38 THEN CheckCorner
 CALL HCHAR(R+1, C, G OR 2)

CheckCorner:
 CALL GCHAR(R+1, C+1, G)::
 IF G>38 THEN CheckDiagonal
 CALL HCHAR(R+1, C+1, G OR 3)

CheckDiagonal:
 CALL GCHAR(R+1, C+2, G)::
 IF G>38 THEN RandomNumber

CALL HCHAR(R+1, C+2, G OR 1)::
GOTO RandomNumber

  • Like 2
Link to comment
Share on other sites

@matthew180

 

Hehe, the shadow was one pixel to start with. Also a more subtle shadow was on my mind (white background and grey shadow). This is one of a hundred or more small sketches for basically trying to squish something out of GM1 (standard graphic mode). Your bit twiddling from the odd or even thread was the reason this sketch suddenly went XB kaboom. Thanks for feedback, and thanks for taking the time to break it down so nicely with comments and white space. Nice utility you got there for sure.

 

@idflyfish & @Willsy

 

Thanks, and absolutely. A TurboForth version would be nice. Sort of maybe learning by example. Feel free to use any of my TI work as basis for TF examples.

 

@lucien2

 

Thanks. Well, lines from 200 and on, kind of asks for a subroutine. It would make it a bit more compact, and/but at a minor cost of speed.

 

@JonnyBritish

 

Thanks for the screenshot.

 

:)

Edited by sometimes99er
Link to comment
Share on other sites

In GPL:

 

      GROM >C000
      DATA >AA00,>0100,>0000
      DATA MENU
      DATA >0000,>0000,>0000,>0000
MENU   DATA >0000
      DATA START
      STRI 'BRICKS'

RND    EQU  >8378

P1     DATA >0000,>C0C0,>3F3F,>FFFF
P2     DATA >0000,>0000,>0000
      DATA >C0C0,>C0C0,>C0C0
P3     DATA >0000,>0000,>0000,>3F7F
      DATA >0103,>0303,>0303,>FFFF
COL    BYTE >10,>23,>45,>68
      BYTE >89,>AB,>C2,>EF
A      EQU  >8300
B      EQU  >8301
IH     EQU  >8302
IL     EQU  >8303
VIH    EQU  >8304
VIL    EQU  >8305
R      EQU  >8306
C      EQU  >8307
GH     EQU  >8308
GL     EQU  >8309

START  BACK 13

* SHADOW PATTERNS
      CLR  @A
      CLR  @B
      CLR  @IH
      CLR  @VIH
L1     ST   @B,@VIL
      SLL  2,@VIL
      ADD  @A,@VIL
      SLL  3,@VIL
      ST   @A,@IL
      SLL  1,@IL
      MOVE 2,G@P1(@IH),V@>900(@VIH)
      INCT @VIL
      ST   @B,@IH
      MUL  6,@IH
      MOVE 6,G@P2(@IH),V@>900(@VIH)
      INC  @A
      CGE  4,@A
      BR   L1
      CLR  @A
      INC  @B
      CGE  2,@B
      BR   L1

* BRICK PATTERNS
      DCLR @IH
L2     MOVE 16,G@P3,V@>940(@IH)
      DADD 64,@IH
      DCGE 7*64,@IH
      BR   L2

* COLORS
      MOVE 8,G@COL,V@>384


* MAIN LOOP
L3

* RANDOM POSITION
      RAND 22
      ST   @RND,@R
      RAND 29
      ST   @RND,@C
      ST   @R,@VIL
      CLR  @VIH
      DSLL 5,@VIH
      DADD @C,@VIL

* IS IT FREE?
      DST  V*VIH,@GH
      CGT  39,@GH
      BS   L3
      CGT  39,@GL
      BS   L3

* DRAW BRICK
      RAND 6
      ST   @RND,@IL
      SLL  3,@IL
      ADD  40,@IL
      ST   @IL,V*VIH
      INC  @IL
      DINC @VIH
      ST   @IL,V*VIH

* DRAW SHADOWS
      DINC @VIH
      ST   4,@A
      CALL SHADOW
      DADD 30,@VIH
      ST   2,@A
      CALL SHADOW
      DINC @VIH
      ST   3,@A
      CALL SHADOW
      DINC @VIH
      ST   1,@A
      CALL SHADOW

      B    L3
* END MAIN LOOP


* DRAW SHADOW
SHADOW ST   V*VIH,@GL
      CGT  38,@GL
      BS   SHADO0
      OR   @A,@GL
      ST   @GL,V*VIH
SHADO0 RTN

      END

  • Like 1
Link to comment
Share on other sites

Here it is in TurboForth:

: SHAPE1 DATA 4 $C0C0 0 0 0 33 DCHAR ; SHAPE1
: SHAPE2 DATA 4 $3F3F 0 0 0 34 DCHAR ; SHAPE2
: SHAPE3 DATA 4 $FFFF 0 0 0 35 DCHAR ; SHAPE3
: SHAPE4 DATA 4 0 $C0C0 $C0C0 $C0C0 36 DCHAR ; SHAPE4
: SHAPE5 DATA 4 $C0C0 $C0C0 $C0C0 $C0C0 37 DCHAR ; SHAPE5
: SHAPE6 DATA 4 $3F3F $C0C0 $C0C0 $C0C0 38 DCHAR ; SHAPE6
: SHAPE7 DATA 4 $FFFF $C0C0 $C0C0 $C0C0 39 DCHAR ; SHAPE7
: SHAPE8 DATA 8 $0000 $0000 $0000 $3F7F $0103 $0303 $0303 $FFFF ;

CREATE COLORS
 2 C,  3 C,  4 C,  5 C, 6 C,  8 C, 8 C,
 9 C, 10 C, 11 C, 12 C, 2 C, 14 C, 15 C,
: INIT
 1 GMODE  13 SCREEN  4 1 0 COLOR
 7 0 DO  \ define bricks and set colours from colour table...
   SHAPE8 I 8 * 40 + DCHAR
  I 5 + COLORS I CELLS + DUP C@ SWAP 1+ C@ COLOR
 LOOP ;

0 VALUE SEED  $8379 V@ TO SEED
: RND SEED 31421 * 6927 @ + DUP TO SEED ;
: 3DROP COMPILE DROP COMPILE 2DROP ; IMMEDIATE

0 VALUE R  0 VALUE C  0 VALUE BRICK
: MAIN-LOOP 
 INIT
 BEGIN
   BEGIN RND 23 MOD TO R  RND 30 MOD TO C  R C GCHAR  
     38 <  R C 1+ GCHAR  38 <  AND  UNTIL
   RND 7 MOD 8 * 40 + TO BRICK
   R C BRICK 1 HCHAR
   R C 1+ BRICK 1+ 1 HCHAR
   \ do shadow tests...
   R C 2+ 2DUP GCHAR DUP 39 < IF 4 OR 1 HCHAR ELSE 3DROP THEN
   R 1+ C 2DUP GCHAR DUP 39 < IF 2 OR 1 HCHAR ELSE 3DROP THEN
   R 1+ C 1+ 2DUP GCHAR DUP 39 < IF 3 OR 1 HCHAR ELSE 3DROP THEN
   R 1+ C 2+ 2DUP GCHAR DUP 39 < IF 1 OR 1 HCHAR ELSE 3DROP THEN
 AGAIN
;
MAIN-LOOP

http://www.youtube.com/watch?v=CUP9vu0lNB0

 

Hope you like it. :P

 

[Edit: No CPU overdrive was used in the above videos. Just paste the code into classic99 to try it out. Enjoy]

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

@Willsy

 

Thanks my friend. Just read the TF code once, and I got most of it, apart from some C@, V@, @ and COMPILE stuff. Where would one look this up most easily ?

 

:)

 

Good morning!

 

Ok, a quick explanation of the code.

 

I'll skip the definition of the graphics, I'm sure you understand that.

 

Let's look at the color data:

 

CREATE COLORS
2 C,  3 C,  4 C, etc....

 

CREATE simply creates an entry in dictionary with the name that follows CREATE. So, in the above code, a dictionary entry called COLORS is created. When we *execute* COLORS (by simply using it's name in the code) it is programmed to simply push the address of the word (the address of the 'code space') of the word. Who programs COLORS to do this? CREATE does! (You could think of CREATE as a class and COLORS as an object of type CREATE, with one single method - to push the address of its code-space).

 

Ok, I hope that wasn't too hard to understand. Next, we use C, ("compile a char") to 'compile' numbers (called literals) directly into memory.

 

So...

2 C,  3 C,  4 C,  5 C, 6 C,  8 C, 8 C,

...compiles 2 3 4 5 6 8 and 8 (as bytes) into memory. TF takes care of where they will be compiled (there is an internal pointer called HERE which always points to the *next* compilation address - C, uses HERE to get the address, and increments HERE by 1 afterwards).

 

So, by "compiling" those numbers *directly after* COLORS, we find that when we execute COLORS the address returned is the address of first byte of the numbers we just compiled. What we just did is *exactly* the same as this in machine code:

colors    data 2,3,4,5,6,8,8

 

So, using simple terms, we compiled a list of bytes, and COLORS returns the address of the start of that list.

 

Try this in TF:

CREATE LIST
1 C, 2 C, 3 C, 4 C, 5 C, 6 C,
: TEST  LIST 6 0 DO DUP I + C@ . LOOP DROP ;

 

C@ means "fetch byte". Words in Forth have prototypes, a bit like C, but their format is different, because Forth is stack based. Forth "prototypes" are called "stack signatures". Here is the stack signature for C@:

 

C@: address -- byte

 

The important thing in a time signature is the -- symbol. The stuff on the left shows the stack BEFORE the word executes. The stuff on the right shows the stack AFTER the word executes. So, we can see that C@ expects an address on the stack, and replaces that address with the value (byte) at that address.

 

Here is SWAP:

 

SWAP: a b -- b a

So, swap takes the top two stack items, a and b and exchanges them, giving us b a.

 

V@ is the same as C@ - however, it reads a byte from VDP:

 

V@: vdp_address -- byte_value

 

VALUEs are very much like variables:

 

9900 VALUE TI ok:0
TI . 9900 ok:0
50 TO TI ok:0
TI . 50 ok:0

 

1+ and 2+ add 1 and two to the top-of-stack:

 

1+: a -- a+1

2+: a -- a+2

 

2DUP DUPlicates the top TWO items:

 

2DUP: a b -- a b a b

 

The word 3DROP needs special explanation. 3DROP is a "compiling" word. Compiling words are quite unique to Forth, so it usually takes people a while to get their head around them.

 

The first thing to notice is the word IMMEDIATE after the end of the definition of 3DROP - this is very important. When 3DROP is compiled into memory, nothing very special happens. It just gets compiled like any other word. However, when 3DROP is referenced in another word, something very special happens....

 

Normally, when the compiler is compiling a word, it just compiles a call to each word that it finds. However, if the word referenced is marked as IMMEDIATE, rather than compiling it, the compiler instead EXECUTES the word. So, when the compiler is compiling MAIN-LOOP it sees a reference to 3DROP and instead of compiling 3DROP, it executes it. Ok, so what happens then? Well, 3DROP actually compiles some words itself into memory (pointed to by HERE). It compiles a DROP then a 2DROP. Where do these get compiled to? They get compiled into the current location in MAIN-LOOP because that was where HERE was pointing to when 3DROP executed!

 

So, 3DROP is a macro that compiles its payload into the "current definition".

 

So, MAIN-LOOP looks like this in the source code:

IF 4 OR 1 HCHAR ELSE 3DROP THEN

 

However, in memory, it looks like this:

IF 4 OR 1 HCHAR ELSE DROP 2DROP THEN

 

Hope this helps to de-mystify Forth a little bit. It really is very simple. It's like a "super machine-code" - very very simple. :)

  • Like 1
Link to comment
Share on other sites

Okay, thanks. Doesn't look like a load, ready, fire and enjoy thing. :)

I might not have been all that appreciative, or should I say, I haven't got the free time to dig into it as is. I'll look into it sooner or later, to, at least produce a GROM - just to see how it performs compared with TurboForth, knowing that they could probably both be optimized etc. Any feelings about how these two beasts (would) compare ?

 

I think Mini Memory was a fine extension back then. Making more power available for common man or poor man. Candidates for built in or small extensions might have been GPL and Forth programming langauges. Mini Mem did it with a 4K RAM in the cart, and I guess Forth would've been able to do something similar ? Would a GPL cart with no RAM (other than 256 bytes Scratch and 16 K VDP) have been a possibility ?

 

:)

 

How about in LOGO II?? ;)

Personally I don't think it's very hot, but sure, would be nice to see it.

 

:)

 

@Willsy

 

Thanks my friend. Just read the TF code once, and I got most of it, apart from some C@, V@, @ and COMPILE stuff. Where would one look this up most easily ?

 

:)

 

Good morning!

Hehe, thanks for the explanation and a good afternoon to you. Think I understand all - will have to experiment later.

 

:)

Link to comment
Share on other sites

Any feelings about how these two beasts (would) compare ?

 

I changed the TF code from this

BEGIN RND 23 MOD TO R  RND 30 MOD TO C  R C GCHAR  
     38 <  R C 1+ GCHAR  38 <  AND  UNTIL

to this

BEGIN RND 23 MOD TO R  RND 30 MOD TO C  R C GCHAR  
     40 <  R C 1+ GCHAR  40 <  AND  UNTIL

to fill the holes, but there are still two holes that are not filled (maybe the random routine?).

 

http://www.youtube.com/watch?v=tNDbEwglJIo

 

Okay, thanks. Doesn't look like a load, ready, fire and enjoy thing. :)

 

LOL, the edit/compile/run cycle in GPL is just two steps longer than assembly.

1. Edit

2. Assemble

3. Run "GPL@LOADER"

4. Load object into GRAM

5. Run from master title menu

  • Like 2
Link to comment
Share on other sites

I changed the TF code from this

BEGIN RND 23 MOD TO R  RND 30 MOD TO C  R C GCHAR  
     38 <  R C 1+ GCHAR  38 <  AND  UNTIL

to this

BEGIN RND 23 MOD TO R  RND 30 MOD TO C  R C GCHAR  
     40 <  R C 1+ GCHAR  40 <  AND  UNTIL

to fill the holes, but there are still two holes that are not filled (maybe the random routine?).

 

Yeah, it's the RND routine, which is just reading from memory addresses. I'm no mathematician!

 

GPL and TF seem to be very very close indeed - they looked exactly the same speed to me. I thought TF would be a little bit faster than GPL, but it looks about the same.

 

Mark

  • Like 1
Link to comment
Share on other sites

@lucien2

 

Excellent video. And thanks for the how2 overview. Should go back and watch the video. The 6+ minutes scared me.

 

 

GPL and TF seem to be very very close indeed - they looked exactly the same speed to me. I thought TF would be a little bit faster than GPL, but it looks about the same.

Street cred to both languages/implementations. Me too, I thought TF would be maybe at least twice as fast, but I guess GPL surprises a bit.

 

:)

Link to comment
Share on other sites

@lucien2

 

Excellent video. And thanks for the how2 overview. Should go back and watch the video. The 6+ minutes scared me.

 

 

GPL and TF seem to be very very close indeed - they looked exactly the same speed to me. I thought TF would be a little bit faster than GPL, but it looks about the same.

Street cred to both languages/implementations. Me too, I thought TF would be maybe at least twice as fast, but I guess GPL surprises a bit.

 

:)

It certainly does surprise! Would it run at that speed in a real console, running from GROM?

  • Like 1
Link to comment
Share on other sites

Okay, thanks. Doesn't look like a load, ready, fire and enjoy thing. :)

 

 

The syntax for GPL is very much like XB.

 

XB

10 X=200

GPL

L10 ST 200,@X

The L10 is a label line 10 in XB and ST is STore, so the only other difference is the @ which means AT

You can also do

X EQU 200

 

Which is like a constant instead of the ST that is more like a variable.

 

Now Assembly only has 16 Registers and GPL only has 256 bytes of Scratch Pad but the same program in GPL will use less storage and variables then XB or Assembly. Only Forth is more compact, but again much more complicated to learn.

Edited by RXB
Link to comment
Share on other sites

LOL, the edit/compile/run cycle in GPL is just two steps longer than assembly.

1. Edit

2. Assemble

3. Run "GPL@LOADER"

4. Load object into GRAM

5. Run from master title menu

 

Yes and you have another step with CSAVE to create GRAM Module Files.

But once that is done you can have a Module always set up and run permanently.

That is something that Assembly or Forth could never do.

 

Be instantly up and running from menu screen even if the computer is turned off and on. That more then pays for the trouble.

 

If not for Cartidges and that Slot there would be no TurboForth cart. By the way I need to order one.

Edited by RXB
Link to comment
Share on other sites

 

Yes and you have another step with CSAVE to create GRAM Module Files.

But once that is done you can have a Module always set up and run permanently.

That is something that Assembly or Forth could never do.

 

Be instantly up and running from menu screen even if the computer is turned off and on. That more then pays for the trouble.

 

If not for Cartidges and that Slot there would be no TurboForth cart. By the way I need to order one.

 

 

 

 

Hmmmm... every time I turn on my TI I am instantly greeted with "Menu" (assembly program) and can select 24 assembly or XBASIC program to run instantly at the touch of a button. No loading required (on my part anyway.)

Link to comment
Share on other sites

Yes and you have another step with CSAVE to create GRAM Module Files.

But once that is done you can have a Module always set up and run permanently.

That is something that Assembly or Forth could never do.

 

Be instantly up and running from menu screen even if the computer is turned off and on. That more then pays for the trouble.

 

If not for Cartidges and that Slot there would be no TurboForth cart. By the way I need to order one.

 

 

 

 

Hmmmm... every time I turn on my TI I am instantly greeted with "Menu" (assembly program) and can select 24 assembly or XBASIC program to run instantly at the touch of a button. No loading required (on my part anyway.)

 

 

And where does this reside?

 

Afraid you missed my point. The TI was built to access 640K of GROM from the cartridge slot in 1979. This was just the console and nothing else. Really what can you do with 8K Cartridge RAM and just a console?

 

(Answer: Sell cartriges like hot cakes just like TI did. Hottest item they sold, and attempted to shut down others that created them.)

 

I fully understand things change but give credit to what made this possible. When the TI99 was introduced it was the GROM slot that sold the machine not the DISK programs or TAPE programs. Later DISK and TAPE took off.

 

Everyone started with EA/MM/XB/LOGO/PASCAL or the Basic built in. All of these are GPL. Just please give credit instead of dissing GROM. All of these hacks copy what GPL does right out of the box since it was introduced.

Link to comment
Share on other sites

Yes and you have another step with CSAVE to create GRAM Module Files.

But once that is done you can have a Module always set up and run permanently.

That is something that Assembly or Forth could never do.

 

Be instantly up and running from menu screen even if the computer is turned off and on. That more then pays for the trouble.

 

If not for Cartidges and that Slot there would be no TurboForth cart. By the way I need to order one.

 

 

 

 

Hmmmm... every time I turn on my TI I am instantly greeted with "Menu" (assembly program) and can select 24 assembly or XBASIC program to run instantly at the touch of a button. No loading required (on my part anyway.)

 

 

And where does this reside?

 

Afraid you missed my point. The TI was built to access 640K of GROM from the cartridge slot in 1979. This was just the console and nothing else. Really what can you do with 8K Cartridge RAM and just a console?

 

(Answer: Sell cartriges like hot cakes just like TI did. Hottest item they sold, and attempted to shut down others that created them.)

 

I fully understand things change but give credit to what made this possible. When the TI99 was introduced it was the GROM slot that sold the machine not the DISK programs or TAPE programs. Later DISK and TAPE took off.

 

Everyone started with EA/MM/XB/LOGO/PASCAL or the Basic built in. All of these are GPL. Just please give credit instead of dissing GROM. All of these hacks copy what GPL does right out of the box since it was introduced.

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