Jump to content
IGNORED

WHILE CONT1?


gar0u

Recommended Posts

I'd like to think I have a good handle on flow control, but this code has me stumped:

 

DO

    WAIT

    c = CONT1

LOOP WHILE c

 

DO

    WAIT

    c = CONT1

LOOP WHILE c = 0

 

The first DO loop is waiting for input from controller 1, which is assigned to the variable 'c', and I assume 'c' is initialized to 0, so the condition is false until it gets any input from the controller, which is interpreted as > 0 and casts to true.

 

But what is the purpose of the second DO loop?

 

Thanks for the help.  I'm trying to not skip over anything that doesn't make sense.

 

(I also think I have a neat idea for a game, so I'm working my way through both of Oscar's books very diligently while planning out my game on paper.  Looking forward to doing some test implementations of things...)

Link to comment
Share on other sites

4 hours ago, gar0u said:

I'd like to think I have a good handle on flow control, but this code has me stumped:

 

DO

    WAIT

    c = CONT1

LOOP WHILE c

 

DO

    WAIT

    c = CONT1

LOOP WHILE c = 0

 

The first DO loop is waiting for input from controller 1, which is assigned to the variable 'c', and I assume 'c' is initialized to 0, so the condition is false until it gets any input from the controller, which is interpreted as > 0 and casts to true.

 

But what is the purpose of the second DO loop?

 

Thanks for the help.  I'm trying to not skip over anything that doesn't make sense.

 

(I also think I have a neat idea for a game, so I'm working my way through both of Oscar's books very diligently while planning out my game on paper.  Looking forward to doing some test implementations of things...)


I believe you have it backwards.  The first loop will wait until the controller is fully idle, looping while any input signal is different from zero.

 

The second one will then loop while the controller is idle, waiting for a fresh new input.

 

The end effect is to guarantee that a fresh new input signal is received.  This is useful for game transitions, where you want to guarantee that only new input is processed, and ignore any input that was left pressed from before.

 

For example, if you have a screen that says "press any key to continue," you want to make sure that the first key pressed arrives after the message is displayed.  Otherwise, you risk skipping that phase completely, if the player left his thumb on the disc on the previous screen.

 

    dZ.

Link to comment
Share on other sites

I had asked about CONT1 and CONT2 while proofreading Advanced Game Programming For Intellivision.  I know that when there is no input on one of the controllers, all the bits are raised at the memory address associated with that controller.

 

It turns out CONT1 is a mnemonic for "PEEK($1FF) XOR $FF" and CONT2 is a mnemonic for "PEEK($1FE) XOR $FF".  Another thing to know, which I pointed out in Appendix E, is that an expression evaluates to TRUE if it is any value other than 0.

 

What that means is, "LOOP WHILE c" will keep code execution in that first loop until c=0, which will be the case when there is no input from Controller 1, as @DZ-Jay pointed out.  The second loop waits until there is input from Controller 1.  The last line could also be written as "LOOP UNTIL c".

 

I have something similar, also in Appendix E, which is a DEF (definition) for "getInput" which waits for a keypress from either keypad:

DEF FN getInput = \
  DO: WAIT: \
    Input = CONT.KEY: \
  LOOP WHILE Input = 12: \
  DO: WAIT: \
  LOOP UNTIL CONT.KEY = 12  ' Keypad value saved to Input

To use this, you would just type "getInput" as a line of code.  Obviously, I'm using the variable "Input" instead of "c", so you would modify the code accordingly.  I hope this helps.

Link to comment
Share on other sites

56 minutes ago, Zendocon said:

It turns out CONT1 is a mnemonic for "PEEK($1FF) XOR $FF" and CONT2 is a mnemonic for "PEEK($1FE) XOR $FF".  Another thing to know, which I pointed out in Appendix E, is that an expression evaluates to TRUE if it is any value other than 0.


 

Hi, @Zendocon,

 

I do not know if it is in the books (although I suspect it is in the first one), but that information is described in the IntyBASIC User Manual, which should be the first stop for anybody using IntyBASIC.
 

   dZ.

Edited by DZ-Jay
Link to comment
Share on other sites

Thank you both for the responses.  That makes sense that the first loop is waiting for the controller input to "settle down", then the second loop reads the requested input.

 

I'll check out the IntyBASIC User Manual.

Link to comment
Share on other sites

4 hours ago, DZ-Jay said:

Hi, @Zendocon,

 

I do not know if it is in the books (although I suspect it is in the first one), but that information is described in the IntyBASIC User Manual, which should be the first stop for anybody using IntyBASIC.
 

   dZ.

I didn't even bother with the IntyBASIC user manual.  I got started with IntyBASIC after the first book was released.  The only thing I did prior was tweak the music in the Music sample program.  That's also why my CONST.BAS file in all my projects has all of my own constants defined, duplicating what is in the standard one for IntyBASIC.  In my released games so far, I was using PEEK($1ff) and PEEK($1fe) when I needed something on the fly.

Link to comment
Share on other sites

8 hours ago, Zendocon said:

I didn't even bother with the IntyBASIC user manual.  I got started with IntyBASIC after the first book was released.  The only thing I did prior was tweak the music in the Music sample program.  That's also why my CONST.BAS file in all my projects has all of my own constants defined, duplicating what is in the standard one for IntyBASIC.  In my released games so far, I was using PEEK($1ff) and PEEK($1fe) when I needed something on the fly.

Well then, maybe you should take a peek at the manual.  There is a lot of good information in there about how the language works and its limitations. ;)

 

     -dZ.

Link to comment
Share on other sites

4 hours ago, carlsson said:

Just about everything in the manual.txt file is reprinted in the first book anyway.

Well, there you go!

 

The manual includes these helpful nuggets:

  CONT              Contains AND'ed $01fe and $01ff complemented content
                    (from both controllers)
...

  CONT1             Contains complemented content of address $01ff (left controller)

...

  CONT2             Contains complemented content of address $01fe (right controller)

...

  WHILE expr:[statement]:WEND
  WHILE expr
  [statement]
  WEND

     Looping statement that keeps looping as long as the expression evaluates
     to non-zero.

...

  DO:[statement]:LOOP UNTIL expr
  DO
    [statement]
  LOOP UNTIL expr

     Looping statements that keep looping WHILE expression evaluates to
     non-zero, or UNTIL expression evaluates to non-zero.

 

There are quite more technical details revealing the nuances of the language implementation, such as:

  A=A=B             If A and B are the same the result is $ffff (-1) else zero

...

                    o Comparisons now return $ffff for true results, useful with NOT

 

Edited by DZ-Jay
Link to comment
Share on other sites

One thing to note is that comparisons against zero are generally more efficient, if just slightly so, especially in DO/WHILE.  This is because comparing against zero is a native CPU operation, while comparing against constants require loading the values into CPU registers first.

 

Also, complex logical expressions with multiple terms are less efficient than nesting them one at a time.  This is because something like the following:

IF (A=B) AND (C=D) THEN

Requires each term to be evaluated and then assigned a temporary logical value of zero (false) or true (-1) before performing the AND operation.  In essence, the evaluated result of each term is normalized to a logical value in order to evaluate the greater expression.

 

This is in contrast to writing the same like this:

IF (A=B) THEN
  IF (C=D) THEN
   ...

Which does not need to normalize or store any interim results:  each term is evaluated and the results are directly applied to either process the inner block, or skip it.

 

     -dZ.

Link to comment
Share on other sites

53 minutes ago, DZ-Jay said:

One thing to note is that comparisons against zero are generally more efficient, if just slightly so, especially in DO/WHILE.  This is because comparing against zero is a native CPU operation, while comparing against constants require loading the values into CPU registers first.

Funny you bring that up.  I actually mentioned that in Appendix E of the Advanced book, where I shared a snippet of code from X-Ray, including a line at the end of a DO block with an expression that either does or doesn't evaluate to 0 in lieu of TRUE or FALSE.

Link to comment
Share on other sites

4 hours ago, DZ-Jay said:

 


IF (A=B) AND (C=D) THEN

Requires each term to be evaluated and then assigned a temporary logical value of zero (false) or true (-1) before performing the AND operation.  In essence, the evaluated result of each term is normalized to a logical value in order to evaluate the greater expression.

 

 

 

     -dZ.

As a casual user of IntyBasic, and coming from a C/C++ background, I've been bitten more than once by writing

 

IF (A AND B) ...

 

which can be false even when both A and B are non-zero.

Proper ways to check that both conditions are true are either

IF (A <> 0 AND B <> 0), or use nesting:

IF (A) THEN

IF (B) THEN

 

One of my wish list items for IntyBasic is introduction of true logical and/or operators,

like C's && and ||, complete with short circuit evaluation for performance reasons.

 

@nanochess, are you listening?

  • Like 1
Link to comment
Share on other sites

1 hour ago, Peripheral said:

As a casual user of IntyBasic, and coming from a C/C++ background, I've been bitten more than once by writing

 

IF (A AND B) ...

 

which can be false even when both A and B are non-zero.

Proper ways to check that both conditions are true are either

IF (A <> 0 AND B <> 0), or use nesting:

IF (A) THEN

IF (B) THEN

 

One of my wish list items for IntyBasic is introduction of true logical and/or operators,

like C's && and ||, complete with short circuit evaluation for performance reasons.

 

@nanochess, are you listening?

Well, there are no "boolean" variables in IntyBASIC.  If you define "A" and "B" as integers in C, you will get the same effect:  a bitwise operation. ;)

 

But your point is very valid:  programmers should keep in mind that in IntyBASIC logical "truth" is represented by any non-zero value in most circumstances.  It is only given a precise value of "-1" when assigning the result of a logical expression to a variable, or when using such result as part of a greater expression, as I mentioned in my prior examples.

 

     -dZ.

  • Like 1
Link to comment
Share on other sites

Reminds me of writing a rudimentary text editor for a class project.  ASCII codes 10 and 13 are both often recognized as newline characters, so at first glance to freshmen, this line

if (keycode = 10 || 13) {
	// Newline
}

ought to execute the "Newline" block.  But "10 || 13" bitwise results in 15, so that block is never executed, because none of the characters in the file used ASCII code 15.

Link to comment
Share on other sites

1 hour ago, carlsson said:

Is there any programming language that allows the later example? I know some have constructs like keycode in [10, 13] but that is a slightly different syntax.

I think languages that have distinct operators for bitwise and logical operations.  VB.Net or C#?  I don't know.

 

But even then, what does it even mean to say "(10 || 13)"?  It is either a bitwise operation or a logical expression; and in either case, the results would be functionally equivalent.

 

I do not know of any language that allows you to compare compare one term with all elements within a set using purely logical operators.  The closest thing I can think of is the "in set" operator, like some functional languages (and Pascal) have.  Still that's an explicit operation in a set.


I think that @Zendocon's point was that a naive or inexperienced programmer may commit such a mistake, not knowing really knowing how logical expressions work in practice.  I would agree with that, but then again, that just suggests they should read the manual. ;)

 

   dZ.

  • Like 1
Link to comment
Share on other sites

4 hours ago, DZ-Jay said:

Well, there are no "boolean" variables in IntyBASIC.  If you define "A" and "B" as integers in C, you will get the same effect:  a bitwise operation. ;)

 

     -dZ.

It depends on what you choose to replace "AND" with.  You're assuming "&".  I'm looking for an "&&" operator, which clearly does not give the same effect as IntyBasic AND.

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