stardot / b-em

An opensource BBC Micro emulator for Win32 and Linux
http://stardot.org.uk/forums/viewtopic.php?f=4&t=10823
GNU General Public License v2.0
112 stars 56 forks source link

Tube ULA: 2-byte R3 transfers misbehaving #216

Open SamSkivington opened 6 months ago

SamSkivington commented 6 months ago

I'm writing a suite of Tube ULA tests and have noticed, with the Music 5000 (filt) release at least, that 2-byte transfers using R3 is causing all kinds of issues.

Gradually evolving Tube tests SSD is here: https://samskivington.com/public/beeb-discs/tubeTests.ssd

Expected: Second test in the boot menu loads and runs the test to completion

Actual: Test hangs after writing two bytes to R3 (Tube action code 3).

hoglet67 commented 6 months ago

Sam,

Is it possible to share the source code for the tests, so that we can see what they are doing which would really help with debugging?

I also recently wrote some tube R3 tests which were posted here: https://stardot.org.uk/forums/viewtopic.php?p=409877#p409877

Do you mind if I ask what your motivation for writing the tests is?

Dave

hoglet67 commented 6 months ago

Steve,

I think this is the bug that is breaking two-byte mode in Sam's test:

It's in tube.c line 83:

    if (tubeula.r1stat & 8 && (tubeula.ph3pos == 0 || tubeula.hp3pos > (tubeula.r1stat & 16) ? 1 : 0)) {

An extra set of parenthesis is needed:

    if (tubeula.r1stat & 8 && (tubeula.ph3pos == 0 || tubeula.hp3pos > ((tubeula.r1stat & 16) ? 1 : 0))) {

BTW, there are lots of other minor issues that show up with my R3 test case.

Dave

SamSkivington commented 6 months ago

Hiya.

The motivation for writing the tests is to save me time putting SD cards in and out, or constantly loading/unloading disc images whilst I'm developing a game (Chuckie Egg was a nightmare until I found a release of b-em that didn't break with a way of doing transfers - VDFS to the rescue). Also, two people have said they are experiencing problems with CE2023 and their PiTubeDirect so, whilst my physical machines are packed away over Christmas, I thought I'd create some tests to get to the bottom of that.

Main code in the test is this:

    ;   claiming the Tube isn't actually required
    ;   but doing it here to fully adhere to the Acorn protocol
_loopClaimTube
    lda #TUBE_ACTION_CLAIM | TUBE_CLAIM_ID
    jsr TUBE_ENTRY_POINT_GENERAL_PURPOSE
    bcc _loopClaimTube

    bit ZP_TWO_BYTE_R3
    bmi _twoByte

    ldx #($10000 - (TestRamEnd - TestRamStart)) & $ff
    ldy #($10000 - (TestRamEnd - TestRamStart)) >> 8
    lda #TUBE_ACTION_TRANSFER_BYTES_TO_PARASITE
    bpl _doTransfer

_twoByte
    ldx #($10000 - (((TestRamEnd - TestRamStart) + 1) & $fffe)) & $ff
    ldy #($10000 - (((TestRamEnd - TestRamStart) + 1) & $fffe)) >> 8
    lda #TUBE_ACTION_TRANSFER_WORDS_TO_PARASITE

_doTransfer
    stx ZP_TUBE_TRANSFER_COUNTER
    sty ZP_TUBE_TRANSFER_COUNTER + 1

    ldx #_tubeTransferToAddress & $ff
    ldy #_tubeTransferToAddress >> 8
    jsr TUBE_ENTRY_POINT_GENERAL_PURPOSE

    ldx #_txtTransferringFile & $ff
    ldy #_txtTransferringFile >> 8
    jsr PrintString

    lda #0
    sta ZP_TUBE_TRANSFER_FROM_POINTER
    lda #$60
    sta ZP_TUBE_TRANSFER_FROM_POINTER + 1

    ldy #0
_loopTransfer
    lda (ZP_TUBE_TRANSFER_FROM_POINTER), y
    jsr TubeHostWriteR3

    ldx #ZP_TUBE_TRANSFER_FROM_POINTER
    jsr IncreasePointer
    ldx #ZP_TUBE_TRANSFER_COUNTER
    jsr IncreasePointer

    ;   Z will be set only if the counter is now $0000
    bne _loopTransfer

. . .

.proc TubeHostWriteR3

_loopWaitUntilEmpty
    bit TUBE_STATUS_REGISTER_3_HOST
    bvc _loopWaitUntilEmpty

    sta TUBE_DATA_REGISTER_3_HOST
    rts
.endproc

I can fill in the gaps if the naming doesn't make values and addresses clear.

SamSkivington commented 6 months ago

If it helps, here's a reference implementation of the Tube ULA I wrote for jsBeeb. It certainly doesn't cover things like the magic numbers when R3 is empty or writing even though R3 is in one byte mode and only has one byte in it - didn't actually think to try those. :)

https://github.com/mattgodbolt/jsbeeb/blob/main/tube.js

With an oops! here https://github.com/mattgodbolt/jsbeeb/issues/404

SteveFosdick commented 6 months ago

I have put Dave's fix on a new branch, sf/issue216, and pushed this to GitHub. This passes Sam's test case. I will look at the other issues found by Dave's tests. If you need a Windows built before I have finished that do let me know.

SamSkivington commented 6 months ago

Hey Steve, a Windows build would be very useful, yes please, for checking I can get through that route for faster game loading with the next one. And thank you muchly. :)

SteveFosdick commented 6 months ago

Windows build as a pre-release: https://github.com/stardot/b-em/releases/tag/issue216%231

SamSkivington commented 6 months ago

Yep. Now working as expected. Again, thank you very much.

SteveFosdick commented 6 months ago

I have now pushed a series of further commits which fix the rest of the discrepancies found by Hoglet's test cases. The only parts of the output I cannot get identical are when a random byte is loaded into parasite to host FIFO on reset (short of hard-coding the value).