Indirection operations

bbc micro/electron/atom/risc os coding queries and routines
Post Reply
AJW
Posts: 718
Joined: Sun Feb 15, 2004 2:01 pm
Contact:

Indirection operations

Post by AJW » Thu May 14, 2020 9:04 am

What would be the best way to write to screen memory when there's a double byte offset? The offset has low byte in &70 and high byte &71 Then I add to start of screen memory address and set Result=&74
I cant use
STA (Result) Y
as it doesnt need a further offset and I get Index eror anyway when I try it

User avatar
0xC0DE
Posts: 549
Joined: Tue Mar 19, 2019 7:52 pm
Location: The Netherlands
Contact:

Re: Indirection operations

Post by 0xC0DE » Thu May 14, 2020 11:29 am

Something like this:

Code: Select all

   10MODE5
   20SCREENSTART%=&5800
   30SCREENOFFSET%=&1234
   40BYTEVAL%=&5A
   50zOFFSET%=&70
   60zSCREENADDR%=&74
   70?zOFFSET%=SCREENOFFSET% MOD 256
   80zOFFSET%?1=SCREENOFFSET% DIV 256
   90FOR I=0 TO 2 STEP 2
  100P%=&900
  110[OPTI
  120LDA #SCREENSTART% MOD 256
  130CLC
  140ADC zOFFSET%
  150STA zSCREENADDR%
  160LDA #SCREENSTART% DIV 256
  170ADC zOFFSET%+1
  180STA zSCREENADDR%+1
  190LDY #0
  200LDA #BYTEVAL%
  210STA (zSCREENADDR%),Y
  220RTS
  230]:NEXT I
  240CALL &900
Please note, SCREENSTART% depends on the screen mode and could be set dynamically (at runtime) if you wanted to.
0xC0DE
:idea: Follow me on Twitter :idea: Visit my YouTube channel featuring my demos for Acorn Electron and BBC Micro

User avatar
BigEd
Posts: 2997
Joined: Sun Jan 24, 2010 10:24 am
Location: West
Contact:

Re: Indirection operations

Post by BigEd » Thu May 14, 2020 11:53 am

If you use Y to hold one of the two lower bytes, I think you can get the addition for free - just need to add the high bytes.

User avatar
0xC0DE
Posts: 549
Joined: Tue Mar 19, 2019 7:52 pm
Location: The Netherlands
Contact:

Re: Indirection operations

Post by 0xC0DE » Thu May 14, 2020 12:15 pm

The program would then become:

Code: Select all

   10MODE5
   20SCREENSTART%=&5800
   30SCREENOFFSET%=&1234
   40BYTEVAL%=&5A
   50zOFFSET%=&70
   60zSCREENADDR%=&74
   70?zOFFSET%=SCREENOFFSET% MOD 256
   80zOFFSET%?1=SCREENOFFSET% DIV 256
   90FOR I=0 TO 2 STEP 2
  100P%=&900
  110[OPTI
  120LDA #SCREENSTART% MOD 256
  130STA zSCREENADDR%
  140LDA #SCREENSTART% DIV 256
  150CLC
  160ADC zOFFSET%+1
  170STA zSCREENADDR%+1
  180LDY zOFFSET%
  190LDA #BYTEVAL%
  200STA (zSCREENADDR%),Y
  210RTS
  220]:NEXT I
  230CALL &900
0xC0DE
:idea: Follow me on Twitter :idea: Visit my YouTube channel featuring my demos for Acorn Electron and BBC Micro

AJW
Posts: 718
Joined: Sun Feb 15, 2004 2:01 pm
Contact:

Re: Indirection operations

Post by AJW » Thu May 14, 2020 5:59 pm

0xC0DE wrote:
Thu May 14, 2020 11:29 am
Something like this:

Code: Select all

   10MODE5
   20SCREENSTART%=&5800
   30SCREENOFFSET%=&1234
   40BYTEVAL%=&5A
   50zOFFSET%=&70
   60zSCREENADDR%=&74
   70?zOFFSET%=SCREENOFFSET% MOD 256
   80zOFFSET%?1=SCREENOFFSET% DIV 256
   90FOR I=0 TO 2 STEP 2
  100P%=&900
  110[OPTI
  120LDA #SCREENSTART% MOD 256
  130CLC
  140ADC zOFFSET%
  150STA zSCREENADDR%
  160LDA #SCREENSTART% DIV 256
  170ADC zOFFSET%+1
  180STA zSCREENADDR%+1
  190LDY #0
  200LDA #BYTEVAL%
  210STA (zSCREENADDR%),Y
  220RTS
  230]:NEXT I
  240CALL &900
Please note, SCREENSTART% depends on the screen mode and could be set dynamically (at runtime) if you wanted to.
thanks. Is this wrong?:

120LDA lksp2% X ; load low byte of offset val
130STA &70
140INX:LDA lksp2% X \ get high byte
145INX
150STA &71

AJW
Posts: 718
Joined: Sun Feb 15, 2004 2:01 pm
Contact:

Re: Indirection operations

Post by AJW » Wed May 20, 2020 5:26 pm

Here again trying to get a soft-scrolling map that works using screen offset lookup tables, using assembler. The tables seem to work fine in a BASIC version. It calls a 16x16 Mode 1 sprite plotter (.plot) that works fine alone. the map is 20x7 onscreen blocks at one time. &72 and &73 are passed to the sprite plotter as base addresss.

160.upscrn
170LDX#0:STX&79: \load map sprite counter
180.upscrnlp1
190LDA lksp3%,X \low byte of offset
200STA &81:INX
210LDA lksp3%,X \get high byte
220STA &82:INX:STX&79:CLC
230LDA &81:ADC&72:STA&72 \add low byte to plotter base address
240LDA &82:ADC&73:STA&73 \add high byte
250JSR plot
260LDX&79:CPX#10 \ just trying to print 10 blocks at the moment
270BCC upscrnlp1
283RTS

All I get are a couple of sprite blocks of noise.

User avatar
0xC0DE
Posts: 549
Joined: Tue Mar 19, 2019 7:52 pm
Location: The Netherlands
Contact:

Re: Indirection operations

Post by 0xC0DE » Thu May 21, 2020 8:44 am

At first glance this code looks OK. However, it's pretty difficult to help you with only this part of the program to look at. For instance, maybe you forget to initialize something that subroutine plot relies on. Or your tables may be incorrect.
0xC0DE
:idea: Follow me on Twitter :idea: Visit my YouTube channel featuring my demos for Acorn Electron and BBC Micro

AJW
Posts: 718
Joined: Sun Feb 15, 2004 2:01 pm
Contact:

Re: Indirection operations

Post by AJW » Thu May 21, 2020 9:20 am

Thanks. I think its the base address Im feeding the plot routine is repetitively added in. However i noticed a load from sprite data operation had stopped working:

LDA sp%,X works
LDA (&77),X doesn't

Where sp%=&C00 and !&77=&C00

User avatar
0xC0DE
Posts: 549
Joined: Tue Mar 19, 2019 7:52 pm
Location: The Netherlands
Contact:

Re: Indirection operations

Post by 0xC0DE » Thu May 21, 2020 9:31 am

AJW wrote:
Thu May 21, 2020 9:20 am
Thanks. I think its the base address Im feeding the plot routine is repetitively added in. However i noticed a load from sprite data operation had stopped working:

LDA sp%,X works
LDA (&77),X doesn't

Where sp%=&C00 and !&77=&C00
That's because LDA (&77),X does not exist. You probably meant LDA (&77),Y which should work perfectly if &77 and &78 contain the correct address (LSB first).
0xC0DE
:idea: Follow me on Twitter :idea: Visit my YouTube channel featuring my demos for Acorn Electron and BBC Micro

AJW
Posts: 718
Joined: Sun Feb 15, 2004 2:01 pm
Contact:

Re: Indirection operations

Post by AJW » Thu May 21, 2020 10:41 am

!&77=&C00 should do that?

User avatar
0xC0DE
Posts: 549
Joined: Tue Mar 19, 2019 7:52 pm
Location: The Netherlands
Contact:

Re: Indirection operations

Post by 0xC0DE » Thu May 21, 2020 10:51 am

AJW wrote:
Thu May 21, 2020 10:41 am
!&77=&C00 should do that?
Yes, but please note that this also writes 0 to &79 and &7A. It writes 4 bytes at once!
0xC0DE
:idea: Follow me on Twitter :idea: Visit my YouTube channel featuring my demos for Acorn Electron and BBC Micro

User avatar
BeebMaster
Posts: 3233
Joined: Sun Aug 02, 2009 5:59 pm
Location: Lost in the BeebVault!
Contact:

Re: Indirection operations

Post by BeebMaster » Thu May 21, 2020 12:24 pm

By coincidence, I posted some code earlier in the week which uses this addressing mode, to fetch 16,384 bytes sequentially from the ROM area.

I've always found the Advanced User Guide a splendid reference work for 6502 machine code and BBC BASIC assembler. Here's a snippet (p.39) which describes this addressing mode:
AUG5-10.png
What I like particularly about this book is that it gives in the comments the "BASIC translation" of the opcodes which I find it much easier to relate to.
Image

AJW
Posts: 718
Joined: Sun Feb 15, 2004 2:01 pm
Contact:

Re: Indirection operations

Post by AJW » Thu May 21, 2020 3:35 pm

BeebMaster wrote:
Thu May 21, 2020 12:24 pm
By coincidence, I posted some code earlier in the week which uses this addressing mode, to fetch 16,384 bytes sequentially from the ROM area.

I've always found the Advanced User Guide a splendid reference work for 6502 machine code and BBC BASIC assembler. Here's a snippet (p.39) which describes this addressing mode:

AUG5-10.png

What I like particularly about this book is that it gives in the comments the "BASIC translation" of the opcodes which I find it much easier to relate to.
I'm using Bruce Smith's book but will reference the AUG, thanks.

AJW
Posts: 718
Joined: Sun Feb 15, 2004 2:01 pm
Contact:

Re: Indirection operations

Post by AJW » Thu May 21, 2020 3:39 pm

0xC0DE wrote:
Thu May 21, 2020 10:51 am
AJW wrote:
Thu May 21, 2020 10:41 am
!&77=&C00 should do that?
Yes, but please note that this also writes 0 to &79 and &7A. It writes 4 bytes at once!
That explains a couple of problems.

Here's my lookup which is supposed to print consecutive blocks 20 horizontally and 7 vertically (mode 1). Base address of &5800 is in &72-3 which is added to later in assembler and in assembler plot routine for 16x16 sprite.

1160t5%=0
1162DIM lksp3% 142
1165DIM lksp4% 142
1166REM lookup for sprite plotter offsets
1170FORf2%=0TO6
1171FORf%=0TO19
1180t8%=((f%*32)+(f2%*1280))
1190IFt5%<140 lksp3%?t5%=t8% MOD256
1191IFt5%<140 lksp3%?(t5%+1)=t8%MOD256
1193IFt5%>139 lksp4%?(t5%-140)=t8%DIV256
1194IFt5%>139 lksp4%?((t5%+1)-140)=t8%DIV256
1200t5%=t5%+2:REMP.t5%,t8%
1210NEXT,

User avatar
0xC0DE
Posts: 549
Joined: Tue Mar 19, 2019 7:52 pm
Location: The Netherlands
Contact:

Re: Indirection operations

Post by 0xC0DE » Thu May 21, 2020 4:16 pm

Shouldn't that be MOD, DIV, MOD, DIV instead of MOD, MOD, DIV, DIV?
0xC0DE
:idea: Follow me on Twitter :idea: Visit my YouTube channel featuring my demos for Acorn Electron and BBC Micro

AJW
Posts: 718
Joined: Sun Feb 15, 2004 2:01 pm
Contact:

Re: Indirection operations

Post by AJW » Thu May 21, 2020 4:48 pm

Yes.
Almost there:
Attachments
screen1.png

AJW
Posts: 718
Joined: Sun Feb 15, 2004 2:01 pm
Contact:

Re: Indirection operations

Post by AJW » Sat May 23, 2020 5:25 pm

Is there any way of accessing a lookup table with double byte size. This obviously does not yet work:

225LDX counter2 \low byte of index
230LDA lksp3%,X \low byte of offset
240STA &81:JSRctr2
245LDX counter2+1 \high byte of index
250LDA lksp3%,X \get high byte
260STA &82:JSR ctr2

312.ctr2 INCcounter2
313BNEend
314INCcounter2+1
317.end

it's trying to get the low and high bytes from a lookup table but the lookup is 280bytes in size so over 256 bytes X won't work.

User avatar
BigEd
Posts: 2997
Joined: Sun Jan 24, 2010 10:24 am
Location: West
Contact:

Re: Indirection operations

Post by BigEd » Sat May 23, 2020 5:33 pm

Often a table of byte pairs is implementing using two tables: using the same index, once to index into the table of low bytes and then to index into the table of high bytes.

AJW
Posts: 718
Joined: Sun Feb 15, 2004 2:01 pm
Contact:

Re: Indirection operations

Post by AJW » Sat May 23, 2020 5:37 pm

The index can only be 255 max though?

User avatar
BigEd
Posts: 2997
Joined: Sun Jan 24, 2010 10:24 am
Location: West
Contact:

Re: Indirection operations

Post by BigEd » Sat May 23, 2020 5:38 pm

But you only have 140 byte pairs, I think?

AJW
Posts: 718
Joined: Sun Feb 15, 2004 2:01 pm
Contact:

Re: Indirection operations

Post by AJW » Sat May 23, 2020 5:45 pm

So store the high bytes in another table? Ok, thanks, will try that.

AJW
Posts: 718
Joined: Sun Feb 15, 2004 2:01 pm
Contact:

Re: Indirection operations

Post by AJW » Sun May 24, 2020 7:45 pm

This will hopefully be the last one.

I have lookup tables containing the x and y position of sprites within a 38x18 map given a sprite block counter, X, which goes from 0-139 on screen (20across x 7 down). I then add in the offsets for the onscreen scroll, x% (&7E) and y%(&7F), but need to multiply y+y% by 38 to find the ascii code. for the screen block sprite within array m% of 684 bytes.

370LDA lksp5%,X:ADC&7C:STA&7E \adjust X to get onscreen, based on x and y of sprite block, ; x+x% in &7E
380LDA lksp6%,X:ADC&7D:STA&7F \y+y% in &7F;

multiply y+y% *38 , add to x+x%, find within m%? How is best to do this?

User avatar
BigEd
Posts: 2997
Joined: Sun Jan 24, 2010 10:24 am
Location: West
Contact:

Re: Indirection operations

Post by BigEd » Sun May 24, 2020 8:02 pm

(Note that those ADC most likely need a CLC before them.)

My feeling is that you need to do a number of two-byte operations here. To multiply by a constant, you'll probably hard-code the process, in this case as 38=32+4+2 that'll be three two-byte shifts and three two-byte additions. But it might be that some operations will fit into a single byte, which saves a little code and a few cycles.

It might also be that you'd be better off always holding your 38x value as a pre-multiplied value which you can use directly.

As the end result is a two-byte result, you're aiming to form a two-byte pointer which you can then indirect from, probably with (zp),Y mode and quite probably with a LDY #0. The ability to add the final byte with the indirection isn't likely to be crucial, but you might be able to save a little here.

AJW
Posts: 718
Joined: Sun Feb 15, 2004 2:01 pm
Contact:

Re: Indirection operations

Post by AJW » Sun May 24, 2020 11:01 pm

So I think I end up with the y-value 38x in &88-89 and the x-value in &7E.
Is it correct to add these:
CLC:LDA&88:ADC&7E:STA&88
LDA&89:ADC#0:STA&89



Then add to &1300 where hopefully I can store the ascii table.

User avatar
BigEd
Posts: 2997
Joined: Sun Jan 24, 2010 10:24 am
Location: West
Contact:

Re: Indirection operations

Post by BigEd » Mon May 25, 2020 11:44 am

Looks good to me. If you need to add &13 to the high byte, you can do that instead of adding zero.

AJW
Posts: 718
Joined: Sun Feb 15, 2004 2:01 pm
Contact:

Re: Indirection operations

Post by AJW » Mon May 25, 2020 5:14 pm

Here's the result so a few things to check.
Attachments
testmap.mp4
(1.46 MiB) Downloaded 7 times


AJW
Posts: 718
Joined: Sun Feb 15, 2004 2:01 pm
Contact:

Re: Indirection operations

Post by AJW » Mon May 25, 2020 6:43 pm

Thanks. Will update if I make more progress.

AJW
Posts: 718
Joined: Sun Feb 15, 2004 2:01 pm
Contact:

Re: Indirection operations

Post by AJW » Mon May 25, 2020 9:53 pm

Here's the code to obtain the ascii code of the sprite from a lookup stored at &1300 row of 38 consecutively.
The first row (see attached) is scrolling accurately but the other rows are nonsense (e.g.second row should be blank).
lksp5%?f3%=f3%MOD20 and lksp6%?f3%=f3%DIV20 going from 0-139 should be x and y of sprite block
&7C,&7D x and y offset (user controlled)
350.spr LDA#0:STA&77:LDA#12:STA&78:LDA &7B \reset sprites base address&C00, &7B onscreen sprite counter
360SEC:SBC#1:TAX \ correct index as incremented by 1 above
370LDA lksp5%,X:CLC:ADC&7C:STA&7E \get onscreen map x and y based on x and y of sprite block, x+x% in &7E
380LDA lksp6%,X:CLC:ADC&7D:STA&7F \y+y% in &7F;
381LDA&7F:ASL A:ASL A \ multiply y+y% *38, multiply by 4 first here
382STA&85:LDY#8:LDX#34:STX&87:LDA#0:STA&88:STA&89 \multiplicand, bit counter , multiplier; reset final address for lookup of ascii

383.rp1 LSR &87:BCC lp1 \routine to multiply by 34, check if multiplier bit 0
394CLC:ADC &85 \add multiplicand if 1
395.lp1 ROR A:ROR &88:DEY:BNE rp1. \rotate high byte, low byte, decrement bit counter
396STA&89
397 CLC:LDA&88:ADC&7E:STA&88:LDA&89:ADC#&13:STA&89:LDY#0 \now add
460LDA (&88),Y \get ascii of sprite at current plot pos
Attachments
testscreen1.png

Post Reply

Return to “programming”