Jump to content
IGNORED

Read value of unpopulated bits


Windless

Recommended Posts

Hi,

 

  I think I remember reading somewhere that bits which are unpopulated are in high impedance state and trying to read them will return whatever is on the bus, which due to capacity of the port will probably be last thing you read or wrote there if it's not too long ago.

 

  I am interested in the reading the CXM1P, which only populated bits 7 and 6. Is it reliable to assume that :

	lda	#%00000000
	ldx	CXM1P

will give a value for `x` that will have all its 6 lower bits at `0` at least 99 times out of 100 ?

 

Thanks,

Windless.

 

(I only have emulators here, can't test on real hardware for now :( )

Edited by Windless
Link to comment
Share on other sites

I'm definitely no expert on this, but I'm pretty certain that the unpopulated/unused bits of ANY of the collision registers will ALWAYS read 0.

 

(I think you are asking if they will "briefly" hold some other values that were previously on the bus, and I think they will not)

Link to comment
Share on other sites

6 hours ago, glurk said:

I'm definitely no expert on this, but I'm pretty certain that the unpopulated/unused bits of ANY of the collision registers will ALWAYS read 0.

 

(I think you are asking if they will "briefly" hold some other values that were previously on the bus, and I think they will not)

What makes you thing so? For other unused bits, this is regularly the case (on most consoles). That is why buggy code like lda $0 instead of lda #$0 works.

Link to comment
Share on other sites

Well, I find it to be an interesting question.  But I actually find both the OP's question and your answer to be unclear.

 

At least on 8-bit systems, code regularly does things like LDA P0PF, BEQ LABEL.  And P0PF is a collision register with unused bits.  I've tested that on real hardware, and it works, the unused bits always equal 0.  So I DID ASSUME that the 2600 would work the same way.

 

Are you saying this is not the case on the 2600?  Or are you saying that it is the case?  As a coding best practice, I always try to code to read the defined bits, and mask off the others.  But I suppose one could write tighter code if the state of the undefined bits is actually guaranteed.  So I find it interesting in that regard, hence my posting.

 

Link to comment
Share on other sites

The TIA only drives bits 6 and 7. Those two bits (and only those!) are 0 if unused by the register. E.g. CXBLPF, only uses bit 7. Bit 6 will always read 0 in that case. If you read from addresses $1e and $1f, which do not correspond to any of the TIA read registers, both bits 6 and 7 are 0.

 

Bits 5 to 0 are floating when reading from the TIA, so nothing is driving them, and their state is usually the last byte that was on the bus (e.g. the address of the register itself, if you're using zero page addressing mode).


Anyway this is unstable and so you must not rely on the state of those 6 bits when reading the TIA, else the code can fail unpredictably.

 

You can see that the tri-state drivers are only on data pins d6 and d7 on page 2 of the TIA schematics.
https://atariage.com/2600/archives/schematics_tia/index.html

A better description here:
https://atariage.com/forums/blogs/entry/2715-introduction-to-processor-hardware/

 

  • Like 1
Link to comment
Share on other sites

1 hour ago, glurk said:

Well, I find it to be an interesting question.  But I actually find both the OP's question and your answer to be unclear.

 

At least on 8-bit systems, code regularly does things like LDA P0PF, BEQ LABEL.  And P0PF is a collision register with unused bits.  I've tested that on real hardware, and it works, the unused bits always equal 0.  So I DID ASSUME that the 2600 would work the same way.

 

Are you saying this is not the case on the 2600?  Or are you saying that it is the case?  As a coding best practice, I always try to code to read the defined bits, and mask off the others.  But I suppose one could write tighter code if the state of the undefined bits is actually guaranteed.  So I find it interesting in that regard, hence my posting.

 

 

From the Stella Programmer's Guide. Only the bits where there is a 1 in the column will be set by the reading of that register.

 

image.png.c8f46890a0ced4362fbebae9e9ac403e.png

The other bits will be set to whatever the most recent value on the bus was. This will vary depending on which TIA register mirror you are reading. For example, reading CXM1P

 

   LDA $01

 

Assuming there is no collision, the A register will contain 00000001

 

If we use a mirror of the CXM1P however,

 

  LDA $11

 

The A register will contain 00010001

 

This is because in the first cases the most recent value on the bus was $01 and in the second case the most recent value was $11. The most significant bits are set to the value in the TIA register, but the other bits are untouched.

 

Link to comment
Share on other sites

1 hour ago, JetSetIlly said:

Out of curiosity, do we know the specifics of which consoles are affected and specifically why?

Not that I'm aware of.

 

IIRC, I've seen bugs related to undriven bits most often reported for 6-switch consoles. But I don't think there are enough reports to really draw conclusions.


Moreover I guess that the console itself isn't the only factor that needs to be considered.


It seems (as also suggested in the last paragraph of the blog I linked above), that eproms are more likely to affect undriven bits than mask roms, and in fact homebrews seem to be  more prone to glitch because of this.

 

On the other hand, while many old commercial games have the "zero page instead of immediate" bug and fail in emulation if you randomize the undriven pins, I only remember a couple of reports of them failing on real hardware. (e.g. here)

 

So the same code can behave differently on the same console depending on the cartridge hardware.

 

  • Like 2
Link to comment
Share on other sites

Apparently, emulators seems to agree that when reading e.g. XCM1P, the last thing on the data bus is the address of XCM1P (e.g. %00000010) (because the opcode which ends with the address has just been read as data), and reading will only modify the two first bits, hence reading %xx000010. Reading XCM0P (address %00000000) will read reading %xx000000.

 

If someone wants to check the actual behaviour on a 2600, here are the code and rom. Just ask if womeone needs a PAL/SECAM version.

 

The expected result is a blue screen with 3 green lines and a black line.

 

Thanks you,

Windless.

 

Edit : I missed all your answers while I was coding, thank you! I'll leave my test code here anyway :)

 

expected result.png

unimplemented_read_test.asm unimplemented_read_test.rom

Edited by Windless
Link to comment
Share on other sites

Just now, Karl G said:

I'm curious what prompted the question? Are you writing something that would require less cycles if you can assume that undefined bits are read as zero?

I was trying to find different ways to gain 1 cycle on a routines that can't work without it, and I came to that question (thought it wouldn't solve my problem anyway :( )

Link to comment
Share on other sites

4 minutes ago, Windless said:

I was trying to find different ways to gain 1 cycle on a routines that can't work without it, and I came to that question (thought it wouldn't solve my problem anyway :( )

If there's a portion of code you would be willing to share, there are a lot of clever people who enjoy the challenge of shaving off a few cycles. There might be something that you haven't considered (I'd make a new topic for it, though).

  • Like 1
Link to comment
Share on other sites

If you're going to be branching based on the collision bits, you might want to look at the BIT instruction:

 

Quote

BIT sets the Z flag as though the value in the address tested were ANDed with the accumulator. The N and V flags are set to match bits 7 and 6 respectively in the value stored at the tested address.

(from http://www.6502.org/tutorials/6502opcodes.html#BIT )

 

For example, if you do BIT CXM1P, then you can use BMI to branch when there's a M1P0 collision, and BVS to branch when there's a M1P1 collision.

  • Like 1
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...