hoglet67 / PiTubeDirect

Bare-metal Raspberry Pi project that attaches to the Acorn TUBE interface and emulates many BBC Micro Co Processors
GNU General Public License v3.0
187 stars 23 forks source link

JIT 6502: Text Corruption in Tube Elite #122

Closed hoglet67 closed 3 years ago

hoglet67 commented 3 years ago

Here's the Tube Elite Carousel screen on Co Pro 24: capture3

Compare it to what we see on Co Pro 0: capture2

Ignore the differences in ship rendering.

Why the heck has Acornsoft changed to ACORNSOFV?

Happens on all Pi models, internal and external tube, regardless of whether Pi-VDU is enabled on not.

And it's not isolated to that one screen...

Example 2:

capture5

capture6

Example 3:

capture4

capture7

There are many other screens with text on them, all are fine.

Very strange bug! Only seems to affect lower case characters.

hoglet67 commented 3 years ago

This looks like an issue in the text token decompression code.

Specifically, there is a bit of the code which copes with case mangling by ORing then ANDing:

.DTS
     1683   C9 41      CMP #&41
     1685   90 10      BCC &1697
     1687   2C 9B 24   BIT &249B
     168A   30 05      BMI &1691
     168C   2C 97 24   BIT &2497
     168F   30 03      BMI &1694
.DT10
     1691   0D 96 24   ORA &2496         <<<<
.DT5
     1694   2D 9C 24   AND &249C

Here's the corresponding source: https://www.bbcelite.com/6502sp/main/subroutine/detok2.html#dts

It looks like DTW1 (&2496) is wrongly getting set to &02 when it should be &00 or &20. That why some lower case characters are now upper case, and off by two.

One place that sets DTW1 uses a rather unusual pattern:

.MT1
     16E9   A9 00      LDA #&00
     16EB   2C
.MT2
     16EC   A9 20      LDA #&20
     16EE   8D 96 24   STA &2496
     16F1   A9 00      LDA #&00
     16F3   8D 9B 24   STA &249B
     16F6   60         RTS

Here's the corresponding source: https://www.bbcelite.com/6502sp/main/subroutine/mt1.html

This pattern of using &2C (BIT &xxxx) to skip over the next two bytes, instead of &80 02 (BRA rel) saves a whole byte, and is quite a common 6502 trick.

When MT1 is entered, a &2C opcode is hit at &16EB (BIT absolute) causes the LDA at &16EC to be skipped.

My guess is this is confusing the Jitter, because sometimes the instruction at &16EC is opcode and sometimes it's operand.

Here's an example of manually calling this code, and triggering a malfunction: capture9

Specifically, in the final call to MT2 (&16EC) the LDA #&20 is getting skipped, and A is taking the value of A% which happens to be &C8 at that point.

Dave

dp111 commented 3 years ago

Coming to think of it I may have broken BIT (2C) recently. I will have a look.

On Fri, 27 Aug 2021 at 16:02, David Banks @.***> wrote:

This looks like an issue in the text token decompression code.

Specifically, there is a bit of the code which copes with case mangling by ORing then ANDing:

.DTS 1683 C9 41 CMP #&41 1685 90 10 BCC &1697 1687 2C 9B 24 BIT &249B 168A 30 05 BMI &1691 168C 2C 97 24 BIT &2497 168F 30 03 BMI &1694 .DT10 1691 0D 96 24 ORA &2496 <<<< .DT5 1694 2D 9C 24 AND &249C

Here's the corresponding source: https://www.bbcelite.com/6502sp/main/subroutine/detok2.html#dts

It looks like DTW1 (&2496) is wrongly getting set to &02 when it should be &00 or &20. That why some lower case characters are now upper case, and off by two.

One place that sets DTW1 uses a rather unusual pattern:

.MT1 16E9 A9 00 LDA #&00 16EB 2C .MT2 16EC A9 20 LDA #&20 16EE 8D 96 24 STA &2496 16F1 A9 00 LDA #&00 16F3 8D 9B 24 STA &249B 16F6 60 RTS

This pattern of using &2C (BIT &xxxx) to skip over the next two bytes, instead of &80 02 (BRA rel) saves a whole byte, and is quite a common 6502 trick.

When MT1 is entered, a &2C opcode is hit at &16EB (BIT absolute) causes the LDA at &16EC to be skipped.

My guess is this is confusing the Jitter, because sometimes the instruction at &16EC is opcode and sometimes it's operand.

Here's an example of manually calling this code, and triggering a malfunction: [image: capture9] https://user-images.githubusercontent.com/1951463/131147289-9a875a45-c484-4e71-b9ae-245852de7919.png

Specifically, in the final call to MT2 (&16EC) the LDA #&20 is getting skipped, and A is taking the value of A% which happens to be &C8 at that point.

Dave

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/hoglet67/PiTubeDirect/issues/122#issuecomment-907268011, or unsubscribe https://github.com/notifications/unsubscribe-auth/AEVVFIWZYAXPJ2HFKRPU5FTT66SINANCNFSM5C5OVNEQ . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.

hoglet67 commented 3 years ago

I can confirm that is was introduced with this commit: ea7a408d1

It still passes the Dorman tests though.

hoglet67 commented 3 years ago

Commit 9d8f1e4e reverts ea7a408

Leaving open as Dominic plans to spend more time on BIT at the weekend.

hoglet67 commented 3 years ago

Dominic said: BIT : I looked at it last night and I'm actually happy how it is. I can't think of anything better todo, unless I start having an ARMv8 version of the BIT instruction.