Jump to content
Jet Set Willy & Manic Miner Community

The AND, OR and XOR instructions


jetsetdanny

Recommended Posts

I am currently working on the Readme file which will accompany the Special Edition of "Willy's New Mansion". I am describing in it, among other things, the way the patch vectors (PVs) which I created work.

 

I have come up against a problem in the description of two of the PVs which has to do with the AND instruction. I will be very grateful for assistance from anyone who is able to answer my query.

 

Many of Geoff Eddy's PVs, on which I based some of my solutions, use the following code to make something happen every n ticks:

 

3A CB 85    LD   A, (#85CB)       pick up the minute counter
E6 0F         AND  #0F                 and make things happen every 16 ticks
C8              RET  Z                     only
 
As I understand, the operand of the AND (E6) instruction determines how many ticks something is supposed to happen. For example, #07 (7 in decimal) will correspond to "every 8 ticks", #0F (15 in decimal) will correspond to "every 16 ticks", #1F (31 in decimal) will correspond to "every 32 ticks" and so on.
 
I followed the pattern and used this kind of code in my PVs. However - to be honest - I made a mistake and used:
 
#C0 (192 in decimal) to make something happen "every 192 ticks" - while now, with the benefit of hindsight, I think it should have been #BF (191 in decimal);
 
#E0 (224 in decimal) to make something happen "every 224 ticks" - while now, with the benefit of hindsight, I think it should have been #DF (223 in decimal).
 
The results are fine, I am satisfied with my PVs and I am not going to modify them; it's just their description that I am now struggling with.
 
So my questions are: using the above code, does #C0 make something happen "every 193 ticks" (as would seem logical) and does #E0 make something happen "every 225 ticks", or is it not true, because the code works (with these values in place) in a different way?
 
Looking at the results of applying these values, it seems to me that they do *not* correspond to things happening "every 193 or every 225 ticks". In fact, there is quite a significant difference between how the PV in question works with the value of #BF and #C0, and it doesn't look at all like it's the question of something happening "every 192 ticks" or "every 193 ticks" (where the difference would be hardly noticeable, I think). So I *suspect* something else is in play, which has to do with the way the AND instruction works, which I don't understand.
 
It may seem strange that I have created something and now have a problem describing how it works. However, it happens in the real world as well from time to time, doesn't it? (e.g. scientists creating a new material with amazing properties through experiments, and then trying to explain *why* it has these properties by looking at its molecular structure, etc. - at least that's what I imagine might happen  :) ).
 
Any help on this would be appreciated, in the sense of describing how:
 
3A CB 85        LD   A, (#85CB)
E6 C0 / E0      AND  #C0 / AND #E0
C8                   RET  Z 
 
works will be appreciated before 10 May, when the Special Edition of "Willy's New Mansion" is due to be released (speak now or forever hold your peace! :) ). 
Link to comment
Share on other sites

The carry flag is cleared I think.

 

I could be wrong but something tells me this tend to work um 'better' if an even value instead of an odd (use say 192 or 194 instead of 193) one.

 

http://z80-heaven.wikidot.com/instructions-set:and and also http://z80-heaven.wikidot.com/flags-and-bit-level-instructions#toc7

 

I think its operating on its actual 'binary' value ie the eight bits rather than the 'sum' itself. :unsure:

Link to comment
Share on other sites

'AND #C0' sets the zero flag if A holds any value from 0 to 63 (00-3F), and 'AND #E0' sets the zero flag if A holds any value from 0 to 31 (00-1F).

 

Note that you can't use 'AND N-1' to set the zero flag on every Nth pass through a loop that increments A unless N is 1, 2, 4, 8, 16, 32, 64, 128 or 256.

Edited by SkoolKid
Link to comment
Share on other sites

Doubling the in-game clock speed was achieved via the command 'E6 7F', or AND 01111111 (in binary), with the in-game clock being incremented every time the output of the AND command is zero.  The fact that the highest (7th) bit of the operand is zero, is key to how it works.

The only eight-bit binary numbers that yield an output of zero (00000000) when AND 01111111 is applied, are 00000000 and 10000000 (i.e. 0 and 128 in decimal respectively).  All other numbers have at least one bit set to 1 in the 'Bit 0 to Bit 6' range, so the AND 01111111 gate passes a non-zero output.

 

Hence the minutes are incremented every 128 ticks, instead of every 256 ticks.  [incidentally, the command 'E6 FF' or AND 11111111 would essentially leave the routine unchanged, with a clock increment occurring every 256 ticks.]

Had you made an analogous error to the one you're now reporting, you would have put 'E6 80', or AND 10000000, into the routine that increments the clock. I believe the effect of that would have been to increment the clock every tick (i.e. every pass through the Main Loop) for the first 128 ticks (from 00000000 ticks to 01111111 ticks - the output is always zero during this phase because the highest bit of the tick counter is zero and the AND command resets all the other bits to zero), followed by NO clock increments at all for the next 128 ticks (from 10000000 ticks to 11111111 ticks - the highest bit of the output is set to 1 so you never get an output of zero during this phase), then it would resume incrementing the clock on every tick for the next 128...

So as you say, a change of just '1' in the value of the operand of the AND command, can have a dramatic effect on the impact of the AND command!

 

EDIT: I just tried out the above and it played out exactly as I predicted!  The minutes rolled by rapidly throughout the first rendition of 'Rich Man', before stopping at 9:07am (i.e. the incrementation ceased after the 128th minute).  Then after another rendition of 'Rich Man' [there are two tune renditions for every 256 'ticks'], the clock resumed rapidly ticking over, before stopping again at 11:15am.

 

(N.B. I think the reason for the extra minute which was apparently counted second time round, is that the minutes started incrementing again when the tick counter rolled over to a value of zero - whereas the tick counter had started at zero at the very beginning of the game).

Edited by IRF
Link to comment
Share on other sites

I'm hoping that digesting the above helps you to get your head around the precise mechanics of the AND command, and in turn gain a deeper understanding of how your patch vectors work!

 

Indeed, typing out the above (and 'gathering my thoughts' in the process) has given me fresh insight into how your 'alternative screen flash routine' operates. (That isn't by any chance one of the examples that sparked this query, is it?)

 

I've come up with a variant of your 'alternative screen flash routine', which I might install into The Nightmare Room in WRN, which uses an operand for the AND command of D0. It causes two blackouts, of short but equal duration, each of which is followed by two short bursts of screen flash - as if the lights in the room are flickering back on after each blackout! It looks great, but now I can understand how it's being brought about, which is even better!

 

AND D0 in binary is AND 1101 0000, and so values of the 'tick counter' (loaded up to the A register) of between 0 and 15 (00001111 in binary) give a zero output, meaning that the screen flash counter is assigned a fixed value for 16 passes through the Main Loop - resulting in the screen taking on a fixed colour (my choice being Black for a true blackout!) during that period. Then from A=16 (00010000) onwards, the output of the AND D0 command is non-zero, so the screen flash effect resumes (via decrementation of the screen flash counter), until the A register reaches a value of 32 (00100000), whereupon once again the AND 11010000 gate outputs zero, causing the screen colour to be fixed (on Black) once again. Then when A reaches 00110000 (48 in decimal), the second blackout stops and the screenflash resumes (until A is decremented to zero, at around 64 'ticks' - although that can be varied via the operand of the subsequent '3E' instruction), and the output of the AND 11010000 command then remains non-zero until A (determined by the tick counter) wraps back around to zero at the start of the next 256-tick cycle.

 

So the blackout/light flashing routine lasts for about 1/4 of each cycle - perfect for disorienting Willy in the tricky Nightmare Room, without making it impossible to complete!

Edited by IRF
Link to comment
Share on other sites

Danny, I forgot to mention that when I set the operand of the AND command to D0, I altered it from the original value which you had set of E0, which is one of the values that you mentioned at the start of this thread - and that's what made me wonder if it was indeed the Screen Flash Patch Vector that you were having trouble summarising in the readme?

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

Important Information

By using this site, you agree to our Terms of Use.