LORES: different between ROM 1.0 and ROM1.1?

The Oric video chip is not an easy beast to master, so any trick or method that allows to achieve nice visual results is welcome. Don't hesitate to comment (nicely) other people tricks and pictures :)
User avatar
Symoon
Archivist
Posts: 2436
Joined: Sat Jan 14, 2006 12:44 am
Location: Paris, France

LORES: different between ROM 1.0 and ROM1.1?

Post by Symoon »

Maybe this has been spotted and discussed before, but anyway... Did anyone notice that LORES 1 modes, which display the 2nd character set, have a different shape between Oric-1 and Oric Atmos?
Noticed that when testing an unknown little game which runs in LORES.
Atmos:
Lores1_Atmos.png
Lores1_Atmos.png (1.05 KiB) Viewed 10082 times
Oric-1:
Lores1_Oric1.png
Lores1_Oric1.png (1.04 KiB) Viewed 10082 times
User avatar
mikeb
Flight Lieutenant
Posts: 282
Joined: Wed Sep 05, 2018 8:03 pm
Location: West Midlands, UK
Contact:

Re: LORES: different between ROM 1.0 and ROM1.1?

Post by mikeb »

Yes, this is a long standing feature :)

The character cells are supposed to be an equal 2 x 3 grid for teletext/viewdata blocks

For Oric this means 3 pixels left, 3 pixels right, as there are only 6 bits in a character that become visible pixels (the other 2 bits are for attributes etc.)

xx 000 000
xx 000 111
xx 111 000
xx 111 111

But I think the routines that generate the codes for Oric-1 forgot this, and used the full 8 bits.

0000 0000
0000 1111
1111 0000
1111 1111

Meaning the shapes onscreen are wrong :-

00 0000
00 1111
11 0000
11 1111

So the left hand lo-res cell is too small, the right hand is too big. Off by one pixel.
User avatar
Symoon
Archivist
Posts: 2436
Joined: Sat Jan 14, 2006 12:44 am
Location: Paris, France

Re: LORES: different between ROM 1.0 and ROM1.1?

Post by Symoon »

Ha ha thanks!
What's curious thought, is that the character generation routine seems to be the same for both ROMs ($F7E0 / $F816)? But I've checked quickly, maybe I'm not looking at the right place.
User avatar
mikeb
Flight Lieutenant
Posts: 282
Joined: Wed Sep 05, 2018 8:03 pm
Location: West Midlands, UK
Contact:

Re: LORES: different between ROM 1.0 and ROM1.1?

Post by mikeb »

No idea how it was fixed, $F263 is the highest address that "Rambling In The ROM" got to in OUM, so that would be where I would look for details.

There must be a subtle difference between the routines (a stray ROL or something) hidden in there that fixes it.

Edit to add: I just compared Leycester Whewell's commented ATMOS ROM disassembly (from the Advanced User Guide) with Bob Maunders un-commented Oric-1 disassembly.

You're right, the routines are the same and are both correct, the problem is GIGO -- Garbage In, Garbage Out.

ATMOS
Code: $F816 to $F860

$F861 Four Data Bytes used by the routine :-
$00 (00 000 000)
$38 (00 111 000)
$07 (00 000 111)
$3F (00 111 111)

These are correct and make allowances for the two first bits being non-visible pixels, so the cells are 3+3 pixels/bits wide.

ORIC:
Code: $F7E0 to $F82A

$F82A Data :-
$00 (00 00 0000)
$F0 (11 11 0000)
$0F (00 00 1111)
$FF (11 11 1111)

These are wrong, and assume that all bits are treated as visible, simply cleaving the byte into 2 nybbles. I've spaced them to show the 2 bits left, 4 bits right offset.

The fix for Oric, (as a post-ROM generation, user correction), is to just ROR every location down one bit, and clear the top two bits just for neatness (AND with $03F)
User avatar
Symoon
Archivist
Posts: 2436
Joined: Sat Jan 14, 2006 12:44 am
Location: Paris, France

Re: LORES: different between ROM 1.0 and ROM1.1?

Post by Symoon »

mikeb wrote: Fri Jul 19, 2019 5:58 pm The fix for Oric, (as a post-ROM generation, user correction), is to just ROR every location down one bit, and clear the top two bits just for neatness (AND with $03F)
Better late than never, here's LoresFix 1.0, quickly done, that fixes Oric-1's LORES 1 mode.

Code: Select all

  AD 08 B9   LDA $B908      Let's control if we already seem to have the right values
  C9 38      CMP #$38       by testing one
  F0 20      BEQ exit       If so, exit!
  A2 00      LDX #$00       else get ready to change a whole page

loopB9:
  BD 00 B9   LDA $B900,X    Load a byte from page $B9
  F0 06      BEQ nextB9     If $00, nothing to do, skip to next
  6A         ROR            else shift once to the right
  29 3F      AND #$3F       then set the two left bytes to 0 ($3F=00111111)
  9D 00 B9   STA B900,X     and replace the value in RAM
nextB9:
  CA         DEX            Next byte
  D0 F2      BNE loopB9     As long as X is not zeroed again, loop
  A2 00      LDX #$00       else get ready to change a whole page --- Ooooh this is useless, thanks ISS for spotting this!

loopBA:
  BD 00 BA   LDA $BA00,X    Load a byte from page $BA
  F0 06      BEQ nextBA     If $00, nothing to do, skip to next
  6A         ROR            else shift once to the right
  29 3F      AND #$3F       then set the two left bytes to 0 ($3F=00111111)
  9D 00 BA   STA BA00,X     and replace the value in RAM
nextBA:
  CA         DEX            Next byte
  D0 F2      BNE loopBA        As long as X is not zeroed again, loop

exit:
  60         RTS
So, Lores Fix simply shifts in RAM the default LORES characters by 1 bit to the right, having them centered again. You can run it as much as you want, the chars won't shift again if they are at the right value ;) Can be relocated anywhere in RAM. Will have to be run again after a warm reset.
Here's the TAP file, set in page 1, with auto-run

File removed, see below for better version
Last edited by Symoon on Tue Sep 03, 2024 4:55 pm, edited 2 times in total.
User avatar
iss
Wing Commander
Posts: 1679
Joined: Sat Apr 03, 2010 5:43 pm
Location: Bulgaria
Contact:

Re: LORES: different between ROM 1.0 and ROM1.1?

Post by iss »

Cool!
Here:

Code: Select all

...
nextB9:
  CA         DEX            Next byte
  D0 F2      BNE loopB9     As long as X is not zeroed again, loop
  A2 00      LDX #$00       else get ready to change a whole page

loopBA:
...
you don't need the line:

Code: Select all

  A2 00      LDX #$00       else get ready to change a whole page
because reg. X is already #$00 and so 2 bytes shorter 8) .
User avatar
Symoon
Archivist
Posts: 2436
Joined: Sat Jan 14, 2006 12:44 am
Location: Paris, France

Re: LORES: different between ROM 1.0 and ROM1.1?

Post by Symoon »

iss wrote: Tue Sep 03, 2024 9:21 am you don't need the line:

Code: Select all

  A2 00      LDX #$00       else get ready to change a whole page
because reg. X is already #$00 and so 2 bytes shorter 8) .
Ooooh thanks.
Will fix this ;)
User avatar
Symoon
Archivist
Posts: 2436
Joined: Sat Jan 14, 2006 12:44 am
Location: Paris, France

Re: LORES: different between ROM 1.0 and ROM1.1?

Post by Symoon »

iss wrote: Tue Sep 03, 2024 9:21 am because reg. X is already #$00 and so 2 bytes shorter 8) .
New version, optimised by ISS, 5% less bytes ;-)
LoresFix10.tap
(66 Bytes) Downloaded 32 times

Code: Select all

  AD 08 B9   LDA $B908      Let's control if we already seem to have the right values
  C9 38      CMP #$38       by testing one
  F0 1E      BEQ exit       If so, exit!
  A2 00      LDX #$00       else get ready to change a whole page

loopB9:
  BD 00 B9   LDA $B900,X    Load a byte from page $B9
  F0 06      BEQ nextB9     If $00, nothing to do, skip to next
  6A         ROR            else shift once to the right
  29 3F      AND #$3F       then set the two left bytes to 0 ($3F=00111111)
  9D 00 B9   STA B900,X     and replace the value in RAM
nextB9:
  CA         DEX            Next byte
  D0 F2      BNE loopB9     As long as X is not zeroed again, loop

loopBA:
  BD 00 BA   LDA $BA00,X    X already at 0 here. Load a byte from page $BA
  F0 06      BEQ nextBA     If $00, nothing to do, skip to next
  6A         ROR            else shift once to the right
  29 3F      AND #$3F       then set the two left bytes to 0 ($3F=00111111)
  9D 00 BA   STA BA00,X     and replace the value in RAM
nextBA:
  CA         DEX            Next byte
  D0 F2      BNE loopBA     As long as X is not zeroed again, loop

exit:
  60         RTS
User avatar
Symoon
Archivist
Posts: 2436
Joined: Sat Jan 14, 2006 12:44 am
Location: Paris, France

Re: LORES: different between ROM 1.0 and ROM1.1?

Post by Symoon »

iss wrote: Tue Sep 03, 2024 9:21 am because reg. X is already #$00 and so 2 bytes shorter 8) .
Maybe I could also have removed the two BEQ nextB9 / BEQ nextBA. Sort of luxury here: not that much time saved, for a "run me once" program... And 4 bytes saved.
User avatar
Sodiumlightbaby
Flight Lieutenant
Posts: 308
Joined: Thu Feb 22, 2024 11:38 am

Re: LORES: different between ROM 1.0 and ROM1.1?

Post by Sodiumlightbaby »

I'm not a seasoned 6502 assembly expert, but as far as I know ULA ignores the top two bits of then character data byte. Could not the inner loop be boiled down from

Code: Select all

loopB9:
  BD 00 B9   LDA $B900,X    Load a byte from page $B9
  F0 06      BEQ nextB9     If $00, nothing to do, skip to next
  6A         ROR            else shift once to the right
  29 3F      AND #$3F       then set the two left bytes to 0 ($3F=00111111)
  9D 00 B9   STA B900,X     and replace the value in RAM
to

Code: Select all

  5E 00 B9    LSR $B900,X
(And then same for BA) Or am I missing something?

Edit: The initial test could perhaps also be slimmed down a little. Assuming $B908 has MSB set originally.

Code: Select all

BIT $B908
BPL exit
Upside we don't clobber the A register anymore

Edit2:
... and do both B9 and BA pages in the same loop :D
User avatar
Symoon
Archivist
Posts: 2436
Joined: Sat Jan 14, 2006 12:44 am
Location: Paris, France

Re: LORES: different between ROM 1.0 and ROM1.1?

Post by Symoon »

Sodiumlightbaby wrote: Thu Sep 05, 2024 8:29 am

Code: Select all

  5E 00 B9    LSR $B900,X
(And then same for BA) Or am I missing something?
It works indeed if the program is ran once!
I began making a TAP file of it but had (already) forgotten that we have ton consider that the program can:
- be ran on Atmos (then has to find exactly #$38 on $B908 to avoid shifting correct values)
- be ran more than once on Oric-1 (if set at the beginning of a program for instance), so looking for #$38 in $B908 also avoids shifting several times all the bits. Problem: "LSRing" won't set it to #$38 as bit 6 will be set, and bit 7 will be 0 or 1 according to C previously.

But great ideas, maybe we can change the test location to find a specific value that would give good results with LSR and BIT, haven't looked for it yet!

EDIT: testing F0 in $B908 (ROM 1.0 value) then exiting with a BNE should at least work so we can use LSR :wink: . I'm so unfamiliar with BIT that I have to think twice here!
Last edited by Symoon on Thu Sep 05, 2024 11:39 am, edited 1 time in total.
User avatar
Sodiumlightbaby
Flight Lieutenant
Posts: 308
Joined: Thu Feb 22, 2024 11:38 am

Re: LORES: different between ROM 1.0 and ROM1.1?

Post by Sodiumlightbaby »

What is the value of $B908 on Basic 1.0?
User avatar
Symoon
Archivist
Posts: 2436
Joined: Sat Jan 14, 2006 12:44 am
Location: Paris, France

Re: LORES: different between ROM 1.0 and ROM1.1?

Post by Symoon »

Sodiumlightbaby wrote: Thu Sep 05, 2024 11:33 am What is the value of $B908 on Basic 1.0?
Just editied my message while you were asking lol.
User avatar
Sodiumlightbaby
Flight Lieutenant
Posts: 308
Joined: Thu Feb 22, 2024 11:38 am

Re: LORES: different between ROM 1.0 and ROM1.1?

Post by Sodiumlightbaby »

Great! Using BIT would be a simplified test just checking if bit 7 is '1' or not. One of the things BIT does is move bit7 to the N flag so we can use BMI or BPL to branch if bit7 is '1' or '0'. Should work but CMP with $F0 is perhaps more readable :wink:
User avatar
Symoon
Archivist
Posts: 2436
Joined: Sat Jan 14, 2006 12:44 am
Location: Paris, France

Re: LORES: different between ROM 1.0 and ROM1.1?

Post by Symoon »

Symoon wrote: Thu Sep 05, 2024 11:26 am "LSRing" won't set it to #$38 as bit 6 will be set, and bit 7 will be 0 or 1 according to C previously.
I was completely wrong with LSR and bit 7, as it shifts a zero in.

So I now have the new listing, thanks to all your remarks and a bit of thinking here, we are now at 16 bytes ;)

Code: Select all

  AE 18 B9   LDX $B918      Test if we have a ROM 1.0: value FF in $B918 (3F on ROM 1.1, 7F once shifted on ROM 1.0)
  E8         INX            increment by 1 to get 00 if we had FF, thus get ready to change a whole page
  D0 09      BNE exit       if result was different from 00, it's not a ROM 1.0 or it was already fixed, so exit!

loop:
  5E 00 B9   LSR $B900,X    shift bytes from page $B9
  5E 00 BA   LSR $BA00,X    shift bytes from page $BA
  CA         DEX            Next byte
  D0 F7      BNE loop       As long as X is not zeroed again, loop

exit:
  60         RTS
The thing now is that, it seems to make strange things with BASIC. I first though it was because I ran the code from page 1, but I relocated it from BFE0 to BFFF, and there are still problems:
- run the code on Oric-1
- try to enter a basic line like: 50 JIJ
- you should get an ?OUT OF MEMORY ERROR

Strange things already happened with the previous versions. Are we messing up something in the Oric-1 system by changing values between B900 and BAFF?
EDIT: tried to save/restore X, etc. before/after, but no change.
EDIT 2: actually, it's the loading routines in ROM 1.0 that mess with the "end of basic" pointer, even when loading a memory block :roll: 9C-9D in zero page have a wrong value after the loading.
Seems also the $100 address is not a good idea when playing with Basic or the interpreter afterwards.
Post Reply