Jump to content

kl99

Members
  • Content Count

    1,055
  • Joined

  • Last visited

  • Days Won

    3

Posts posted by kl99


  1. Initialize Variables to identical value together

    100 A,B=1
    110 PRINT A
    120 PRINT B

    Instead of A=1 :: B=1 you can use A,B=1.

     

    How many bytes in your line takes a number? Does every number use the same number of bytes?

     

    First of all, how many digits your number has is important. The number 10 uses one more byte than 0-9.

    A negative number also takes one more byte for storing the negative character.

    Therefore really bad are numbers typically used with CALL LOAD and CALL PEEK, where you have to pass a >83xx hex number.

    The internal timer that sits on >8379 has to be called with "-31879", which uses 5 more byte than the number 4.

    If the precise value doesn't count, it makes sense to reduce numbers like 100 for defining the length of a sound to 99 or to a constant (tip above) that is close to that number. For the same reason it also makes sense to prefer to use Ascii Chars 32-99 instead of 100-159 to save a byte on each reference.

    A special case are line numbers. I didn't see a change to the length for defining the code for the line if the line number was defined by 1 digit or 5. Even if you have references to lines like you have in GOTO x or GOSUB x or THEN x ELSE x.

    If somebody studied this in more detail, please share with us.

     


  2. Let's take Gladiator by FarmerPotato, written in XB and extend each line with ! characters to see how many more "bytes" would fit in each line.

    10 CALL CLEAR :: CALL SCREEN(8):: CALL MAGNIFY(2):: S=2 :: T=1 :: R=80 :: C=128 :: Q=160 :: E=2 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    20 CALL CHAR(113,"003030300000000000000030303000000000000000303030",116,"2556360A060A090F661F66060A0A00090606076E1665")!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    30 CALL CHAR(97,"606848706070506860604078606050D86060406070686070",100,"1819121C101814641818101E1030484C30302030303E186C")!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    40 CALL CHAR(105,"102040000000000000000000007000000000000000000070",108,"020408000000000000000000000E0000000000000000000E")!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    50 CALL SPRITE(#1,104+S,12,R-4,C+6,#2,112+T,7,R-1,C-1,#3,96+S,2,R,C,#4,115+E,16,R,Q)!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    60 L=K :: CALL JOYST(1,X,Y):: CALL KEY(1,K,Z):: Y=2-Y/4 :: IF K=18 THEN S=Y ELSE IF L=18 THEN F=4 :: S=Y+3 ELSE T=Y :: IF X THEN C=C+X ELSE IF S>3 THEN S=S-3 :: F=0 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    70 E=INT(RND*3+1):: Q=Q-1 :: CALL PATTERN(#1,104+S,#2,112+T,#3,96+S,#4,115+E):: CALL LOCATE(#1,R-4,C+6,#2,R-1,C-1,#3,R,C,#4,R,Q)!!!!!!!!!!
    80 IF C+8+F<Q THEN 60 ELSE IF F AND S<>E+3 THEN 100 ELSE IF T=E OR S-3=E THEN C=C-8 :: Q=Q+8 :: GOTO 70 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    90 CALL COLOR(#4,9):: FOR I=1 TO 7 :: CALL SOUND(-100,999,2):: CALL SOUND(-100,880,2):: NEXT I :: C=C-8 :: Q=Q+16 :: GOTO 50 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    100 CALL COLOR(#3,9):: FOR I=1 TO 7 :: CALL SOUND(-100,999-I*100,2):: NEXT I :: C=C-16 :: Q=Q+8 :: GOTO 50 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    

    You can fit 502 ! characters in those 10 untouched lines.

     

    Now let's introduce 5 numeric variables as Numeric Constants for M=1,N=2,O=3,P=4,_=0

    10 CALL CLEAR :: M=1 :: N=2 :: O=3 :: P=4 :: CALL SCREEN(8):: CALL MAGNIFY(N):: S=N :: T=M :: R=80 :: C=128 :: Q=160 :: E=N !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    20 CALL CHAR(113,"003030300000000000000030303000000000000000303030",116,"2556360A060A090F661F66060A0A00090606076E1665")!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    30 CALL CHAR(97,"606848706070506860604078606050D86060406070686070",100,"1819121C101814641818101E1030484C30302030303E186C")!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    40 CALL CHAR(105,"102040000000000000000000007000000000000000000070",108,"020408000000000000000000000E0000000000000000000E")!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    50 CALL SPRITE(#M,104+S,12,R-P,C+6,#N,112+T,7,R-M,C-M,#O,96+S,N,R,C,#P,115+E,16,R,Q)!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    60 L=K :: CALL JOYST(M,X,Y):: CALL KEY(M,K,Z):: Y=N-Y/P :: IF K=18 THEN S=Y ELSE IF L=18 THEN F=P :: S=Y+O ELSE T=Y :: IF X THEN C=C+X ELSE IF S>O THEN S=S-O :: F=_ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    70 E=INT(RND*O+M):: Q=Q-M :: CALL PATTERN(#M,104+S,#N,112+T,#O,96+S,#P,115+E):: CALL LOCATE(#M,R-P,C+6,#N,R-M,C-M,#O,R,C,#P,R,Q)!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    80 IF C+8+F<Q THEN 60 ELSE IF F AND S<>E+O THEN 100 ELSE IF T=E OR S-O=E THEN C=C-8 :: Q=Q+8 :: GOTO 70 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    90 CALL COLOR(#P,9):: FOR I=M TO 7 :: CALL SOUND(-100,999,N):: CALL SOUND(-100,880,N):: NEXT I :: C=C-8 :: Q=Q+16 :: GOTO 50 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    100 CALL COLOR(#O,9):: FOR I=M TO 7 :: CALL SOUND(-100,999-I*100,N):: NEXT I :: C=C-16 :: Q=Q+8 :: GOTO 50 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    

    Suddenly you can fit 566 ! characters in those lines, meaning across 10 lines we saved 64 bytes.

    The definition of the constants in Line 10 did cost use some bytes but as soon as we start to reference those variables instead of using the actual number, we save bytes.

    This was only basic replacement of each reference of the number 0, 1, 2, 3, 4 and saved us already a lot.

    Now let's tweak a bit more...

    50 CALL SPRITE(#M,104+S,P*O,R-P,C+6,#N,112+T,7,R-M,C-M,#O,96+S,N,R,C,#P,115+E,P*P,R,Q)!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    

    Instead of "12" we use P*O and instead of "16" we use P*P and voila we save 2 more bytes alone in that line.

     

    Line 10 can be tweaked for 2 additional bytes by not defining Q=160 but with R+R:

    10 CALL CLEAR :: M=1 :: N=2 :: O=3 :: P=4 :: CALL SCREEN(8):: CALL MAGNIFY(N):: S=N :: T=M :: R=80 :: C=128 :: Q=R+R :: E=N !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

    If we define a constant for the number 100 in Line 90 and use it twice in the same line, then we need for the definition plus 2 references as much bytes as the untouched line.

    And each further occurence of a 3 digit number saves us 4 bytes.

    90 H=100 :: CALL COLOR(#P,9):: FOR I=M TO 7 :: CALL SOUND(-H,999,N):: CALL SOUND(-H,880,N):: NEXT I :: C=C-8 :: Q=Q+P*P :: GOTO 50 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    100 CALL COLOR(#O,9):: FOR I=M TO 7 :: CALL SOUND(-H,999-I*H,N):: NEXT I :: C=C-P*P :: Q=Q+8 :: GOTO 50 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

    let's check the program in completeness after such kind of tweaks...

    10 CALL CLEAR :: M=1 :: N=2 :: O=3 :: P=4 :: D=8 :: H=100 :: J=112 :: CALL SCREEN(D):: CALL MAGNIFY(N):: S=N :: T=M :: R=80 :: C=P*P*D :: Q=R+R :: E=N !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    20 CALL CHAR(J+M,"003030300000000000000030303000000000000000303030",J+O,"2556360A060A090F661F66060A0A00090606076E1665")!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    30 CALL CHAR(H-O,"606848706070506860604078606050D86060406070686070",H,"1819121C101814641818101E1030484C30302030303E186C")!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    40 CALL CHAR(105,"102040000000000000000000007000000000000000000070",J-P,"020408000000000000000000000E0000000000000000000E")!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    50 CALL SPRITE(#M,H+P+S,P*O,R-P,C+6,#N,J+T,7,R-M,C-M,#O,H-P+S,N,R,C,#P,J+O+E,P*P,R,Q)!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    60 L=K :: CALL JOYST(M,X,Y):: CALL KEY(M,K,Z):: Y=N-Y/P :: IF K=18 THEN S=Y ELSE IF L=18 THEN F=P :: S=Y+O ELSE T=Y :: IF X THEN C=C+X ELSE IF S>O THEN S=S-O :: F=_ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    70 E=INT(RND*O+M):: Q=Q-M :: CALL PATTERN(#M,H+P+S,#N,J+T,#O,H-P+S,#P,J+O+E):: CALL LOCATE(#M,R-P,C+6,#N,R-M,C-M,#O,R,C,#P,R,Q)!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    80 IF C+D+F<Q THEN 60 ELSE IF F AND S<>E+O THEN 100 ELSE IF T=E OR S-O=E THEN C=C-D :: Q=Q+D :: GOTO 70 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    90 CALL COLOR(#P,9):: FOR I=M TO 7 :: CALL SOUND(-H,999,N):: CALL SOUND(-H,880,N):: NEXT I :: C=C-D :: Q=Q+P*P :: GOTO 50 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    100 CALL COLOR(#O,9):: FOR I=M TO 7 :: CALL SOUND(-H,999-I*H,N):: NEXT I :: C=C-P*P :: Q=Q+D :: GOTO 50 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

    now we have 607 ! characters, meaning we saved over 100 bytes across the 10 lines.

    • Like 4

  3. Hi,

    Programming within only 10 lines of code requires a different coding style.

    Let us take this thread to share the findings and ideas everyone had to tweak in some more bytes.

     

    Here is my first:

     

    Variable Name Length

    Use single char variable names. BASIC allows A,B,C,D,E,F,G,...X,Y,Z,@,[,],_ as Names for the first character, which in most cases should be enough. Same for String Variables or Arrays.

     

    Skip Variable Initialize to 0

    You can skip initializing a variable to 0 before its first reference as this is done by the system.

     

    Replace repeating numbers in code

    You save length in your code lines if you replace a number (BASIC calls them numeric constant) that is showing up multiple times across your program by a reference to a variable having that numeric value.

    The more occurences you can replace the more you save. The more digits the number had the more you save.

     

    A nice combination of this tip with the tip skipping initialize to 0 would be replacing each occurence of the number 0 in your program with "_" and simply never initialize or change its value.

     

    • Like 2

  4. On 8/7/2019 at 4:44 PM, Vorticon said:

    In retrospect, you are probably right particularly after seeing kl99's exploits with RXB! Brilliant! Since I am considering making this a yearly contest with even better prizes, I think in the future there will indeed be 3 categories: TI Basic, TIXB and Other Basic (RXB or any other non-TI XB).

    Can we include TI-99/2 and TI-99/8 Basic as allowed languages for the 3rd category next time?

    Will it be established as a 10 liner contest each year?


  5. 6 hours ago, FarmerPotato said:

    What I still have is a binder of progress reports about the 99/4B. There is a spec for the Hexbus disk. Yes, also a report on TI testing different consumer cassette recorders. The remainder is common things like printouts of the Disk Drive Interface and so on.

     

     

     

    Are you for real??? Getting those Documents for the 99/4B would be adding a real value to the community.

     

    We might have the spec already for the Hexbus Disk if it is one of the following Specifications:

    - Hex-Bus™ Disk Drive/Controller 5102 Preliminary Manual
    - Hex-Bus™ Floppy Disk System Product Specification
    - Software Specification for the Hexbus Floppy Disk System

     

    • Like 1

  6. I just discovered this possibility that might be useful in a certain situation.

    You can not only use RUN inside a program in combination with some FILE to load another file.

    You can also use RUN inside a program with a certain Program Line.
    The difference to a GOTO with the same Program Line is that all variables are reintialized.

     

    Extended Basic


    100 A=1
    110 RUN 130
    120 B=2
    130 C=3
    140 PRINT "A : ":A;" REINITIALIZED BY RUN"
    150 PRINT "B : ":B;" SKIPPED LIKE WITH GOTO"
    160 PRINT "C : ":C

     

    RUN leads to the following output

     

    A :

     0  REINITIALIZED BY RUN
    B :
     0  SKIPPED LIKE WITH GOTO
    C :
     3

     

    • Like 3
    • Thanks 1

  7. 57 minutes ago, MueThor said:

    Dear HOME AUTOMATION, senior_falcon and all others,

     

    Thank you for your help. I finally got the programs to run on at least one of the two apps (V9T9 and Classic99). Now, when joysticks are needed for the games, does there exist a sort of module for the apps to replace these joysticks by keys of the keyboard?

     

     

    Regards,

     

    Typically the Emulator maps or lets you map the Joystick Up, Down, Left, Right to the Keyboard Keys Up, Down, Left, Right.

    And on the TI-99/4A the Key Q is the Joystick 1 Fire Button.

    At least for Classic99 there is Options\Options and then Enable Joystick and whether you want to use the PC Keyboard for it instead.


  8. 13 hours ago, jrhodes said:

    Any plans to expand this, allowing for possible improvements beyond the limits of the 10-line contest constraints?

    Yes, it has too much potential to keep it as such. I wrote already that I run out of time with completing the code, therefore I am still working on it.

    Also the 10-line limit makes it slower than necessary. And the levels could be loaded from dedicated files on the disk to make it more flexible.

    • Like 4
    • Thanks 1

  9. This is a "decoded" view with variables named different to give some hint on their purpose.

    Also I tried syntax highlighting to improve readability.

    And each statement in the same program line starts in a dedicated row, with :: being removed.

    For readability I removed the Constant Definitions and set the Numbers directly.

     

    1   Level$="-(([email protected](""@MB,""TMJB<PH\BGH\""^B
                JHE(""(@8&TMG9RJJJRLKIFJJDKH2<
                P8""66N6NTHBB""(@9R*B*A(2828PC
                BH(@@([email protected]&""""""""_"

    2   GOSUB 8
        CALL CHAR(33,RPT$("38",7),
                  94,"0000000000FEFEFE0",
                  96,Sprite$)
        SndEncoded$="CjEpECjEJCgDpECgDJCgDpJCg
                     DTCjEpECjEJCgDpECgDJClCp
                     EClC^[email protected]\"

    3   FOR SndPos=1 TO 73
          SndPiece=ASC(SEG$(SndEncoded$,SndPos,1))
          SndDecoded$=SndDecoded$&CHR$(SndPiece-(SndPiece>63)*(SndPiece<96)*64-(SndPiece>96)*32)
        NEXT SndPos
        CALL MOVES("$V",73,SndDecoded$,1760)
        FOR Column=1 TO 31
          CALL VCHAR(7,Column,32,12,19,Column,120,48)
        NEXT Column

    4   IF
          SpriteXChr=0
        THEN
          CALL MAGNIFY(3)
          SpriteXChr=25
          SpriteYPix=59
          CALL IO(1,1760)
        ELSE
          IF
            (Steps+1=LEN(Level$))
          THEN
            END
          ELSE
            IF
              (SpriteXChr<5)+(SpriteYPix>107)
            THEN
              CALL POKEV(771,SharedVar AND 1)
              CALL SOUND(-96,-1,0)
              Steps=0
              SharedVar=SharedVar+1
              IF
                SharedVar<16
              THEN
                4
              ELSE
                SpriteXChr=0
                Lives=Lives-1
                IF
                  Lives<1
                THEN
                  END
                ELSE
                  GOTO 4

    5   BitFilter=1
        Steps=Steps+1
        LevelData=ASC(SEG$(Level$,Steps,1))-32
        FOR Row=8 TO 14 STEP 3
          CALL VCHAR(Row,25,32-((LevelData AND BitFilter)>0),3)
          CALL HCHAR(Row+2,26,95+((LevelData AND 2*BitFilter)>0),4)
          BitFilter=BitFilter*4
        NEXT Row
        SharedVar=0
        CALL LOAD(-31879,0)
        IF
          Steps=1
        THEN
          9

    6   CALL KEY(1,Ignored,FireInput)
        CALL JOYST(1,JoyInput,Ignored)
        IF
          FireInput+JoyInput=0
        THEN
          8
        IF
          FireInput=0
        THEN
          7
        PositCheck=SpriteYPix*4+SpriteXChr+52
        CALL PEEKV(PositCheck,ScreenVal)
        CALL PEEKV(PositCheck-96,ScreenVal2)
        IF
          (ScreenVal=191)+(ScreenVal2<>191)
        THEN
          7
        SpriteYPix=SpriteYPix-24
        CALL POKEV(768,SpriteYPix)
        SharedVar=1

    7   IF
          JoyInput=0
        THEN
          8
        PositCheck=SpriteYPix*4+SpriteXChr+52
        CALL PEEKV(PositCheck,ScreenVal)
        CALL PEEKV(PositCheck-1-(JoyInput=4)*5,ScreenVal2)
        IF
          (ScreenVal2<>128)OR((ScreenVal=191)*(SharedVar=0))
        THEN
          8
        SharedVar=0
        SpriteXChr=MIN(MAX(5,SpriteXChr+SGN(JoyInput)*5),25)
        CALL POKEV(769,SpriteXChr*8+3)

    8   IF
          Initialized=1
        THEN
          CALL PEEK(-31879,Timer)
          IF
            Timer<40
          THEN
            6
          ELSE
            SpriteXChr=SpriteXChr-5
            IF
              SpriteXChr>0
            THEN
              9
            ELSE
              PositCheck=SpriteYPix*4+61
              CALL PEEKV(PositCheck,ScreenVal)
              SpriteXChr=2-3*(ScreenVal=128)
        ELSE
          Sprite$="070F1F3F2D2510187F988D4D3F4F4438
                   E0F8FCFE5C5008C8F0ACB2BAF4E4887"

    9   CALL MOVES( "VV",24,230,225,
                    "VV",24,262,257,
                    "VV",24,294,289,
                    "VV",24,326,321,
                    "VV",24,358,353,
                    "VV",24,390,385,
                    "VV",24,422,417,
                    "VV",24,454,449,
                    "VV",24,486,481)

    10  IF
          Initialized=1
        THEN
          CALL POKEV(768,SpriteYPix,SpriteXChr*8+3,192,1)
          PositCheck=SpriteYPix*4+SpriteXChr+52
          CALL PEEKV(PositCheck,ScreenVal)
          IF
            (SpriteYPix>108)+(ScreenVal=190)
          THEN
            4
          ELSE
            SpriteYPix=SpriteYPix+24
            CALL POKEV(768,SpriteYPix)
            GOTO 10
        ELSE
          Initialized=1
          Lives=3
          RETURN

     

    String Constants:

    Level$

    String containing the Level Data. One Byte represents the information for one single Level Scroll Step.

    Uses Ascii code values from 32-95 to represent 6bit of data.

    Sprite$

    Sprite Definition Hexadecimal Code, Sprite uses 4 characters.

    SndEncoded$

    Soundlist in encoded form to not have to use hexadecimal format which would require 2 bytes for one byte of data. With this it one byte of data only requires one byte of data.

     

    String Variable:

    SndDecoded$

    Soundlist in the necessary form to store in VDP Ram. The soundlist will be called from the Interrupt Service Routine. It consists of the Intromusic plus the repeating sound. The live lost sound is done with a CALL SOUND.

     

    Numeric Variables:

    BitFilter

    Column

    Helping Variable referring the current Column that gets cleared/drawn. It starts with Column 1 and ends with column 31.

    FireInput

    JoyInput

    Ignored

    Necessary Variable for CALL KEY and CALL JOYST which is assigned by those subprograms but not used by the program.

    Initialized

    This is used as a Flag to direct the program execution within Program Lines 8 and 10. In case this Flag is set, meaning containing Intialized=1, then the Program Lines 8 & 10 run another way than if the same Program Line 8 is called before the Initialize has happened.

    LevelData
    Lives

    The Variable that represents the number of Lives (Tries) you have. It is initialized with 3. The program checks if there is a life left in case you loose a live. If not, the program ends.
    PositCheck
    RowSharedVar
    ScreenVal

    ScreenVal2
    SndPiece
    SndPos
    SpriteXChr

    Refers to the current X location of the Player Sprite. It is not representing the Pixel Column but actually the Character (1-32) Column where the Player is rendered. Values are 5,10,15,20 or 25. If the Player gets stuck in the left, the Value can shortly be 0 or 2.

    SpriteYPix

    Refers to the current Y location of the Player Sprite. It is representing the Pixel Column. Values are 59,83,107. If the player falls down the Value can shortly be 131.

    Steps

    Refers to the number of the current Level Step that is being rendered at the most right screen. The screen shows 5 full rendered Steps, and at the very left in addition one 3/5 Step.
    Timer

    The game is using the system timer in the CPU Ram at location >8379. This is part of the GPL Status Block. I reset this Timer to 0 after drawing the next Level Step on the right side and directly before returing the program control to the Joystick Input. The GPL interpreter/TI operating system increments this Timer automatically. Like this i can read the value again after a while to figure out whether the Player should still have time to move the Sprite or whether it is time to perform the Scrolling. Checking this Variable against another Value than 40 will change the speed of the game. The check against 40 in Program Line 8 means the Player has time between 0-39 to move around with the game scrolling. If you check it against a lower Number than 40, the Player will have less time, but the Scrolling will be more smooth. Defining this Number to a good value needs to match the Level Data to still be able to reach the end of the Level.

     

    Program Flow = WIP

     

    RUN from RXB prompt...

     

    Line 1 Define Level$

    Line 2 GOSUB 8

    ...

    Line 8 IF Initialized=1 THEN ...  ELSE Define Sprite$

    Line 9 harmless line that we can execute with no benefit this time

    Line 10 IF Initialized=1 THEN ... ELSE Define Initialized & Lives :: RETURN

     

    The Initialized Flag was a speed compromise to use the free space within Program Lines 8 and 10.
    Like this Program Line 8 sets the 63 byte long character definition for Sprite$.

    Like this Program Line 10 defines 5 numeric constants, the numeric variable Lives and 1 string constant.

    Remember that Line 8, 9 and 10 are called as a Subprogram and require a RETURN at the End of Line 10.

    When called later 8, 9 and 10 are no longer a Subprogram.

     

    The Program Flow continues after the RETURN from the GOSUB call like this:

    Line 2 [GOSUB 8] :: Load Characters for Platforms, Screen and Sprite$
           Define SndEncoded$

    Line 3 Create SndDecoded$ from SndEncoded$ and write it to VDP Ram.

           Draw the background and empty the foreground screen.

    Line 4 IF SpriteXChr=0 THEN
             CALL MAGNIFY(3)
             Define SpriteXChr & SpriteYPix
             Activate Soundchip for autoplaying the Soundlist
            ELSE ...

    Line 5 Render one Level Step at the right
           Reset Timer
           IF Steps=1 THEN 9

    ...

    Line 9 Scrolling Screen Lines to the left

    Line 10 IF Initialized=1 THEN
          Render/Rerender Sprite
          IF
            (SpriteYPix did completely fall down)

            or

            (Sprite is on a Platform)
          THEN
            4
          ELSE
            Player falls down one step (24 pixels)
            GOTO 10
        ELSE ...

     

    The Program is finally fully initialized and will never come back to Lines 1, 2 or 3:

     

    Line 4 IF Player reached the end of the Level THEN END
           IF Player got stuck at the left or Player did completely fall down
            THEN
              IF Last Life Lost THEN END

              Handle Life Lost
              Reset SpriteXChr
              GOTO 4

    Line 5 Render one Level Step at the right
           Reset Timer

    Line 6 Input, Handling Jump Input including Sprite update

    Line 7 Handling Left/Right Input including Sprite update

    Line 8 Check for Timer and jump to Line 6 if End of Timer is not reached.

           Prepare Sprite Update, Handle Sprite at very left situation.

    Line 9 Scrolling Screen Lines to the left

    Line 10 IF Initialized=1 THEN
              Render/Rerender Sprite
              IF
                (SpriteYPix did completely fall down)

               or

              (Sprite is on a Platform)
              THEN
                4
              ELSE
                Player falls down one step (24 pixels)
              GOTO 10
            ELSE ...

    • Like 2

  10. 2 hours ago, Asmusr said:

    It runs at the same speed in both emulators on my machine. Perhaps your host is too slow for JS99er? How many FPS do you get according to the JS99er log?

     

    Hi Asmusr!

    Thanks for the analysis tip. In fact I was below 40fps in my default Browser Firefox, too many Tabs. Chrome gave it full speed, cool! Did a full windows restart to get it at least to 53fps in Firefox. I have changed the warning on Js99er and removed the recommendation to only use Classic99.

    • Like 3

  11. How is a Level defined?

     

    A level is defined in L$. Each byte in there provides the information for 1 Level Step.
    A Level Step is what the game scrolls in one go: Each of the 3 vertical and each of the 3 horizontal lines either show or not show.

    1 Level Step therefore contains 6 bit of used data, that are read out to figure out which horizontal and vertical bars to render in a given Level Step.

    There is a Level complete character "_" to end the Level and therefore the game. This should be placed as last character to inform the Game Engine to stop.

    A Level Step is defined by setting one single Ascii Char, using Range 32-95.

    I reserved 113 Bytes for the Level Content.
     

    It basically looks like this:

     

    Binary    Bit Asc    Asc    Dec            Pattern
                        
    000001    0    !    33    1            top |
    000010    1    "    34    2            top _
    000100    2    $    36    4            mid |
    001000    3    (    40    8            mid _
    010000    4    0    48    16            low |
    100000    5    @    64    32            low _

     

    Since we can only store Ascii codes from 32-159 in a CALL CHAR statement, I added an offset of 32 to the actual value representing that bit.

     

    Starting from Ascii Code 32 you add the number on the right for the given bar you wanna show.

    See pictures to get clearness.


    The Game Engine performs the check based on the Information on the screen. If there is a wall that blocks the player he can not pass it. If there is a hole the player will fall into it. So you can be as creative with Level creation as you want. Of course there should be a way to reach the end of the level.

     

     

    gex_level-step1.png

    gex_level-step2.png

    gex_level-step3.png

    • Like 4

  12. First things first, an actual Level!

     

    If you want to have a decent Level, try out this one that I made up just before.

    In Line 1 you define the Level by setting the string variable L$:

    L$="-(([email protected](""@MB,""TMJB<PH\BGH\""^BJHE(""(@8&TMG9RJJJRLKIFJJDKH2<P8""66N6NTHBB""(@9R*B*A(2828PCBH(@@([email protected]&""""""""_"

    Line 1 should look like this:

    1 _=0 :: K=1 :: H=4 :: I=8 :: M=H*I :: B=M-I :: D=52 :: L$="-(([email protected](""@MB,""TMJB<PH\BGH\""^BJHE(""(@8&TMG9RJJJRLKIFJJDKH2<P8""66N6NTHBB""(@9R*B*A(2828PCBH(@@([email protected]&""""""""_"

    It now uses the maximum of 112 Level Steps to still fit with the Game Engine in 10 Lines. This was a rule for the contest.

     

    The complete game then looks like this. Please be aware that only the Level Data was changed.

     

    I figured out that atariage.com cannot handled Ascii Code 127 at all, which is part of the String Definition for the Autosound.

    I therefore removed the Full Text version for copying via clipboard. Sorry for that confusion.

     

    Instead go for the Disk Image containing the original Contest Entry loaded via OLD DSK1.GAMENGINEX
    or with the Level Data included via OLD DSK1.LEVEL1

     

    Go to this post for the files:

    https://atariage.com/forums/topic/294259-ti-game-engine-x/?do=findComment&comment=4321477

     

    • Like 4

  13. Requirements:

    Memory: 32K Memory Expansion
    Input: Joystick No 1

    Cartridge: RXB 2015 E

    Preferred Emulator: Classic99 (developed and tested so far) 

     

    Instructions:
    You need to reach the end of the Level. You can move to the left and to the right. You can Jump and you will fall down, whenever there is no platform below you. The end of the level is always on the far right, and the game is scrolling automatically to the left. So be quick.

     

    You can combine a Jump with a move to the right or left to reach a higher platform next to you.

     

    You will loose a life if you fall into the ground or if you get stuck because of the automatic scrolling.

     

    You have got 3 lives and have to do the whole level in one attempt.

     

    Player Movement:
    Joystick Left: Moving Left
    Joystick Right: Moving Right
    Joystick Fire: Jump

     

    This game is inspired by a Game & Watch LCD Handheld called Super Mario Bros, released by Nintendo.

     

    The game was created specifically in mind to participate in a Extended Basic Programming Contest, taking place in 2019.
    The contest was about creating a game with a maximum of 10 lines of code.

     

    This game as such is under Copyright of Klaus Lukaschek.

     

    Thanks to Vorticon for hosting the contest, Tursi for the Classic99 Emulator, Mike Wight for making The Cyc, Matthew Hagerty and Marc Hull and Tursi for sharing their Sound Programming Knowledge, Rich Gilbertson for creating his RXB, Ciro Barile for inspiration and motivation and testing, my wife Sandra for her support, my brother Reinhard for learning how to program together.

     

    I would love to have had some more time as the released version is running a very small level.

     

    Some Tech Talk:

    • Multiple Statements per Line
    • Usage of Variables instead of direct Numbers Constants to win Line Length in critical areas
    • Scrolling part of the screen to the left by using CALL MOVES to copy bytes from VDP Ram to VDP Ram
    • Usage of Logical AND and OR in several places
    • Logical AND is used for bitwise operations
    • Sharing of Program Lines 8-10 for being called via GOSUB with a conditional RETURN or called as normal flow after processing Line 7.
    • Storing a repeating sound list in VDP Ram to be called by the Interrupt Service Routine.
    • CALL IO to talk to the Soundchip.
    • Soundlist is not stored in hexadecimal form to have 1 Byte consuming only 1 Byte, for this a transformation of the string is necessary.
    • Level Data consumes 1 Byte per Column
    • Definition and update of Player Sprite Location via CALL POKEV instead of CALL SPRITE and CALL LOCATE
    • Check for Level collision via CALL PEEKV instead of CALL GCHAR
    • Trimmed any '0' in the end of a CALL CHAR definition.
    • All numeric variables (constants) only have one character as their name.
    • Usage of _ and [ and ] and @ as variable names.
    • Usage of the system timer in >8379 to sync actions.
    • The game is actually an engine, limited to only containing one level for contest reason, therefore many levels can be created.
    • The name X refers to 10 meaning creating a Game Engine with only 10 lines of code.

     

    Requires RXB!

    OLD DSK1.GAMENGINEX

    GAMEENGX.dsk

    There was a more completed level released by me after the deadline of the contest.

    OLD DSK1.LEVEL1

     

    Classic99 Files:

    GAMEGINEX

    LEVEL1

     

    Please ensure that your system&emulator pasting feature respects the seven Ascii Code 127 characters within the S$ string in Line 2.
    For the Js99er Emulator check for the FPS rate to ensure the correct speed. It runs considerable slower in the attached RXB version in Js99er.
    I used Classic99 for development and testing.

     

    And as stated before. It is actually an Engine which includes a short level. And I realized reaching the end of the level is not done nicely in the released version.

    I will document how different levels can be created.

     

    • Like 5

  14. This is a thread, dedicated to the RXB game called "TI Game Engine X".
    I wrote this game as entry for the programming contest that did occur until 31th July 2019.

    Since the time was running out a bit, I wasn't able to completely showcase its possibilities.

     

    First I will post the main program, its instructions again and then I will post a nice level for you.

    • Like 1

  15. Hi Guys,

    yesterday I have run into a nasty Syntax Error in Extended Basic, which also occurs in RXB.

    I don't understand it and wonder if the line really contains a Syntax Error or this is a Interpreter Bug.

     

    Version 1:

    1 IF A=1 THEN 2 ELSE FOR I=1 TO 2 :: PRINT I :: NEXT I
    2 END

    Version 2:

    1 IF A=1 THEN 2 :: FOR I=1 TO 2 :: PRINT I :: NEXT I
    2 END

     

    Both versions complain about a Syntax Error in Line 1.

     

    I would like to analyze it with the help of you and maybe RXB can be even fixed.


  16. TI Game Engine X
    identical to Disk Image Content (OLD DSK1.GAMENGINEX)

    1 _=0 :: K=1 :: H=4 :: I=8 :: M=H*I :: B=M-I :: D=52 :: L$="-(([email protected](""@MB,""TMJB<PH\BGH\""^BJHE_"
    2 F=230 :: GOSUB 8 :: G=C*I :: CALL CHAR(M+K,RPT$("38",7),94,"0000000000FEFEFE0",C,P$):: S$="CjEpECjEJCgDpECgDJCgDpJCgDTCjEpECjEJCgDpECgDJClCpEClC^[email protected]\"
    3 FOR T=K TO C-B+K :: Y=ASC(SEG$(S$,T,K)):: T$=T$&CHR$(Y-(Y>63)*(Y<C)*I*I-(Y>C)*M):: NEXT T :: CALL MOVES("$V",T,T$,1760):: A=-31879 :: FOR N=K TO M-K :: CALL VCHAR(7,N,M,H+I,B-J,N,120,48):: NEXT N
    4 IF X=_ THEN CALL MAGNIFY(L):: X=J*J :: Y=59 :: CALL IO(K,1760)ELSE IF (@+K=LEN(L$))THEN END ELSE IF (X<J)+(Y>107)THEN CALL POKEV(G+L,Q AND K):: CALL SOUND(-C,-K,_):: S=_ :: Q=Q+K :: IF Q<H*H THEN 4 ELSE X=_ :: ]=]-K :: IF ]<K THEN END ELSE GOTO 4
    5 U=K :: S=S+K :: Z=ASC(SEG$(L$,S,K))-M :: FOR R=I TO 14 STEP L :: CALL VCHAR(R,J*J,M-((Z AND U)>_),L):: CALL HCHAR(R+2,B+2,95+((Z AND U+U)>_),H):: U=U*H :: NEXT R :: Q=_ :: CALL LOAD(A,_):: IF S=K THEN 9
    6 CALL KEY(K,W,O):: CALL JOYST(K,U,R):: IF O+U=_ THEN 8 :: IF O=_ THEN 7 :: P=Y*H+X+D :: CALL PEEKV(P,V):: CALL PEEKV(P-C,W):: IF (V=E)+(W<>E)THEN 7 :: Y=Y-I*L :: CALL POKEV(G,Y):: Q=K
    7 IF U=_ THEN 8 :: P=Y*H+X+D :: CALL PEEKV(P,V):: CALL PEEKV(P-K-(U=H)*J,W):: IF (W<>M*H)OR((V=E)*(Q=_))THEN 8 :: Q=_ :: X=MIN(MAX(J,X+SGN(U)*J),J*J):: CALL POKEV(G+K,X*I+L)
    8 IF [=K THEN CALL PEEK(A,T):: IF T<I*J THEN 6 ELSE @=S :: X=X-J :: IF X>_ THEN 9 ELSE P=Y*H+61 :: CALL PEEKV(P,V):: X=2-L*(V=M*H)ELSE P$="070F1F3F2D2510187F988D4D3F4F4438E0F8FCFE5C5008C8F0ACB2BAF4E4887"
    9 CALL MOVES(M$,B,F,F-J,M$,B,F+M,257,M$,B,294,289,M$,B,F+C,321,M$,B,358,353,M$,B,390,385,M$,B,422,417,M$,B,454,449,M$,B,486,481)
    10 IF [=K THEN CALL POKEV(G,Y,X*I+L,C+C,K):: P=Y*H+X+D :: CALL PEEKV(P,V):: IF (Y>108)+(V=190)THEN 4 ELSE Y=Y+I*L :: CALL POKEV(G,Y):: GOTO 10 ELSE E=191 :: J=5 :: M$="VV" :: [=K :: L=3 :: ]=L :: C=M*L :: RETURN


    Please ensure that your system&emulator pasting feature respects the seven Ascii Code 127 characters within the S$ string in Line 2.
    For the Js99er Emulator check for the FPS rate to ensure the correct speed. It runs considerable slower in the attached RXB version in Js99er.
    I used Classic99 for development and testing.

    And as stated before. It is actually an Engine which includes a short level. And I realized reaching the end of the level is not done nicely in the released version.

    I will document how different levels can be created.

     

    Editing Notes:

    I figured out that atariage.com cannot handled Ascii Code 127 at all, which is part of the String Definition for the Autosound.

    I therefore removed the Full Text version for copying via clipboard as it can not be copied like that. Sorry for that confusion.

     

    Further, I created a dedicated Discussion Thread for the release with informations and updates like a decent Level and Levelcreation guide:

     

    • Like 3

  17. TI Game Engine X

    Klaus Lukaschek

    Atariage User: kl99

     

    Requirements:
    Memory: 32K Memory Expansion
    Input: Joystick No 1

    Cartridge: RXB 2015 E

    Preferred Emulator: Classic99 (developed and tested so far)


    You need to reach the end of the Level. You can move to the left and to the right. You can Jump and you will fall down, whenever there is no platform below you. The end of the level is always on the far right, and the game is scrolling automatically to the left. So be quick.

     

    You can combine a Jump with a move to the right or left to reach a higher platform next to you.

     

    You will loose a life if you fall into the ground or if you get stuck because of the automatic scrolling.

     

    You have got 3 lives and have to do the whole level in one attempt.

     

    Player Movement:
    Joystick Left: Moving Left
    Joystick Right: Moving Right
    Joystick Fire: Jump

     

    This game is inspired by a Game & Watch LCD Handheld called Super Mario Bros, released by Nintendo.

     

    The game was created specifically in mind to participate in a Extended Basic Programming Contest, taking place in 2019.
    The contest was about creating a game with a maximum of 10 lines of code.

     

    This game as such is under Copyright of Klaus Lukaschek.

     

    Thanks to Vorticon for hosting the contest, Tursi for the Classic99 Emulator, Mike Wight for making The Cyc, Matthew Hagerty and Marc Hull and Tursi for sharing their Sound Programming Knowledge, Rich Gilbertson for creating his RXB, Ciro Barile for inspiration and motivation and testing, my wife Sandra for her support, my brother Reinhard for learning how to program together.

     

    I would love to have had some more time as the released version is running a very small level.

     

    Some Tech Talk:

    • Multiple Statements per Line
    • Usage of Variables instead of direct Numbers Constants to win Line Length in critical areas
    • Scrolling part of the screen to the left by using CALL MOVES to copy bytes from VDP Ram to VDP Ram
    • Usage of Logical AND and OR in several places
    • Logical AND is used for bitwise operations
    • Sharing of Program Lines 8-10 for being called via GOSUB with a conditional RETURN or called as normal flow after processing Line 7.
    • Storing a repeating sound list in VDP Ram to be called by the Interrupt Service Routine.
    • CALL IO to talk to the Soundchip.
    • Soundlist is not stored in hexadecimal form to have 1 Byte consuming only 1 Byte, for this a transformation of the string is necessary.
    • Level Data consumes 1 Byte per Column
    • Definition and update of Player Sprite Location via CALL POKEV instead of CALL SPRITE and CALL LOCATE
    • Check for Level collision via CALL PEEKV instead of CALL GCHAR
    • Trimmed any '0' in the end of a CALL CHAR definition.
    • All numeric variables (constants) only have one character as their name.
    • Usage of _ and [ and ] and @ as variable names.
    • Usage of the system timer in >8379 to sync actions.
    • The game is actually an engine, limited to only containing one level for contest reason, therefore many levels can be created.
    • The name X refers to 10 meaning creating a Game Engine with only 10 lines of code.

    GAMEENGX.dsk

    • Like 4

  18. Hi, a question about strings in the basic program, be it as DATA "abc"or defined as variable A$="abc".

    Is it allowed from the contest point of view to store non printable characters in those string definitions?

    I am trying to sqeeze in some sound data which goes up to ascii 159 and also below ascii 32, currently i have a hexcode representation and go via CALL CHAR to VDP, but a hexcode represenation consumes twice the size in the program that is actually required.

    • Like 1

  19. Working intensive on my entry. Lost some time because of a one-week sickness.

    In case you try to squeeze every byte into your lines, you are able to figure out how many bytes are free in each line by adding as many "!" characters as the line will still fit without throwing "* Line Too Long".

    This will show you how many tokenized bytes are still available in each of your lines.

     

    And if you have space in one line but are low on bytes in another, you can replace a hardcoded number by a numeric variable.

     

    2 CALL CLEAR :: CALL CHAR(100,"1234567890123456789012345678901234567890123456789012345678901234",R,"1234567890123456789012345678901234567890123456789012345678901234")

    --> * LINE TOO LONG

     

    But this fits:
    1 Q=100 :: R=Q+4
    2 CALL CLEAR :: CALL CHAR(Q,"1234567890123456789012345678901234567890123456789012345678901234",R,"1234567890123456789012345678901234567890123456789012345678901234")

     

    Also you can skip remaining zeros on Character Definitions like this

    1 CALL CHAR(33,"0")

    defines the Character 33 as completely empty.

     

     

    • Like 3
    • Thanks 1
×
×
  • Create New...