It is currently Mon Oct 20, 2014 4:48 pm

All times are UTC [ DST ]




Post new topic Reply to topic  [ 73 posts ]  Go to page 1, 2, 3, 4  Next
Author Message
PostPosted: Wed May 07, 2008 9:35 am 
Offline
User avatar
 WWW  Profile

Joined: Fri Mar 28, 2008 10:47 am
Posts: 11
Hi Everyone,

I'm a decent programmer (C/C++/C#/Java) and a long time BBC devotee. I'd love to be able to join in here and do some 6502 coding, but I'm suffering from not having the right kind of resources. I've been through the programming docs on this site, and they don't seem to have the right focus.

I'll freely admit that I don't 'get' assembler at the moment. I played with 6502 a little bit back in the day, and I can do really basic stuff (adding two numbers together, testing conditions, jumping to a different location) but I can't find a decent resource which will help me understand basic things I want to do on the BBC. I can't find a good reference to show me how to put a sprite on screen, or even how do draw a specific colour at a specfic point on screen. I can't see how to get the BBC to play a sound in 6502. I've got tons of screen scrolling routines, but nothing to tell me how to do sprite collision.

Can we start to collect to examples of how to do these basic functions in 6502, and I'm sure there are many people like me who would like to take them either as building blocks or as a reference to do certain things in a game.

Thanks

_________________
Image


Top
 
PostPosted: Wed May 07, 2008 10:06 am 
Offline
User avatar
 WWW  Profile

Joined: Thu Apr 03, 2008 2:49 pm
Posts: 277
Location: Antarctica
Hello

If you get C/C++ you'll be OK with 6502.

Although you say you can do basic stuff like adding two numbers, testing conditions and so on, that's really all 6502 is! So at a very simple level you could do:

Code:
y register = 7
accumulator = pixel value

do
{
  Store accumulator to screen with an offset of the Y register
  Decrement y
} while ( y>=0 )


Mode 2 is a reasonable place to start, it has the most colours, and is memory mapped to 0x3000.

It also has 2 pixels per byte. Note these aren't stored in the upper and lower nibbles as perhaps you'd expect, but interleaved, so the left pixel is set by:

1010 1010

and the right pixel set by

0101 0101

So, to get 2 red pixels, your value would be:

1 OR 2 = 3.

So:

Code:
; Low byte of 0x3000
LDA #&00
STA &70
; High byte of 0x3000
LDA #&30
STA &71
; Loop counter and offset
LDY #7
; Pixel value
LDA #3
.loop
; Do the store
STA (&70),Y
; Decrement loop counter
DEY
; If >= 0, loop
BPL loop
;Return
RTS   


Assemble this code to 0x900, pop into mode2, and CALL &900. You should see a small red blob in the top left! All a sprite routine is really is an extension of this sort of stuff.

The real problem comes with the horrible memory layout of the BBC screen, you can see this explained in the advanced user guide on here somewhere.

Let us know how you get on with that and we can take it from there!



Dave


Last edited by DaveF on Wed May 07, 2008 2:20 pm, edited 1 time in total.

Top
 
PostPosted: Wed May 07, 2008 1:56 pm 
Offline
User avatar
 Profile

Joined: Wed Jan 09, 2008 7:30 am
Posts: 406
If you downlaod Swift it explains a little about how pixels are stored in a mode 2 screen in the attached documentation "Swift Sprite Data Formats". As Dave says The advanced user is essential to understand the screen layout though.


Top
 
PostPosted: Thu May 08, 2008 9:43 am 
Offline
User avatar
 WWW  Profile

Joined: Fri Mar 28, 2008 10:47 am
Posts: 11
Firstly, thanks Dave and Steve for helping me here.

Dave, your comments are very helpful. It is beginning to make sense.

Steve, I've tried to build this in Swift, but without success. When I try to build, I get the error 'Could not find assembler at C:\P65\p65.py' - I've triple checked, and this is the right location. I can execute p65.py from the command line however, so I know it works.

I've built it successfully in BeebASM (with minor modification) and I get the red blob, just as you describe. It was slightly different than I imagined; the pixels were arranged vertically when I was expecting them to arrange horizontally, but this is my error.

I've downloaded the New Advanced User Guide, and I'm beginning to trawl through that now. I guess that the next step is to define a sprite using EQUB and then get it to copy that data to screen memory.

Thanks again.

_________________
Image


Top
 
PostPosted: Thu May 08, 2008 10:00 am 
Offline
User avatar
 WWW  Profile

Joined: Thu Apr 03, 2008 2:49 pm
Posts: 277
Location: Antarctica
Glad to be of help.

The pixels going down is due to the way the video memory works on the BBC (I told you it was a pain!)

If you alter the code to do 9 iterations instead of 8 (ie change the LDY #7 to LDY #8), then you will see your vertical red line and another 2 pixels just to the right at the top.

This is because the video memory is based around (8x8) characters, so it's very easy to have a small loop to plot (for example) a sprite representing a letter 'A'.

So, to see an 8x8 red block, simply change the LDY #8 to LDY #31. This will give you a total of 64 pixels (remember there's 2 pixels per byte), in otherwords, 8x8!


Top
 
PostPosted: Thu May 08, 2008 10:06 am 
Offline
User avatar
 Profile

Joined: Wed Jan 09, 2008 7:30 am
Posts: 406
rival wrote:
Steve, I've tried to build this in Swift, but without success. When I try to build, I get the error 'Could not find assembler at C:\P65\p65.py' - I've triple checked, and this is the right location. I can execute p65.py from the command line however, so I know it works.


Just double checking but you should have two entries for the set up of P65. The "Executable location" should be set to your python executable (Python.exe). The "Script File Location" should be set to the p65 python script, so your entry "C:\P65\p65.py" should be set in the ""Script File Location" field.

Check these and get back to me :)

P.S. you can use BeebASM with Swift if you wish. There's a profile for it in the assemblers set up screen.


Top
 
PostPosted: Fri May 09, 2008 11:33 am 
Offline
User avatar
 WWW  Profile

Joined: Fri Mar 28, 2008 10:47 am
Posts: 11
Firstly Steve - I've changed the settings as you've suggested and everything is fine. I'm compiling in Swift. I seem to have a problem with Windows Media Player though, and I can't play your tutorial videos at the moment.

So, I've been working on the program a little bit.
Code:
.ORG $900
init:
 LDA #$00 ;the low byte of the initial address
 STA $70 ;store at &70
 LDA #$40 ;the high btye of the initial address
 STA $71 ;store at &71
 LDY #15 ;the amount of pixels to show / 2
 LDA #11 ;the byte value to enter into the address to show a yellow pixel and a red pixel
main:
 JMP plot ;draw the picture
 JMP move ; Move the picture on 2 pixels, 1 byte
 JMP main ;start the loop again
plot:
 STA ($70), Y
 DEY
 BPL plot
 RTS
move:
 LDA $70 ;read back the low-byte
 TAX ;move it to the X register
 INX ;increase it by one
 TXA ;move it back to A
 STA $70 ;save it back to where it came from
 RTS


I'm plotting a yellow and red pair of pixels towards the middle of the screen. I've tried to write a routine which will increase the lowbyte, and there is clearly stuff I don't understand. I've downloaded the New Advanced User Guide, but it isn't searchable and wading through the scans (whilst incredibly useful) is sending my eyes funny.

What I want it to do is to move the block I'm plotting across the screen. I've a routine 'move' which increase the value stored in the low byte by one. I then should loop back to the beginning of 'main' to execute it again with the new value. It seems that this infinate loop isn't looping at all, and execution ends after the first display. What am I missing? It seems that the line JMP main doesn't do anything.

Thanks

Sam

_________________
Image


Top
 
PostPosted: Fri May 09, 2008 12:22 pm 
Offline
User avatar
 WWW  Profile

Joined: Thu Apr 03, 2008 2:49 pm
Posts: 277
Location: Antarctica
Hello

It should perhaps read:
Code:
main:
JSR plot ;draw the picture
JSR move ; Move the picture on 2 pixels, 1 byte
JMP main ;start the loop again

So your subroutines are called then the main is looped back to. JMP is like a goto, while JSR is like a function call.

There is a good 6502 instruction reference here.

You might also find it useful to wait for the vertical sync, so:
Code:
main:
JSR plot ;draw the picture
JSR move ; Move the picture on 2 pixels, 1 byte
LDA #19
JSR &FFF4 ; OS_Byte 19 (wait for vsync)
JMP main ;start the loop again

Also, your entire 'move' routine could just compact to:
Code:
INC $70

As on the 6502 you can increment memory addresses.

You'll probably also want to setup your A and Y registers again on your plot function:
Code:
plot:
LDA #11
LDY #15
plotLoop:
STA ($70), Y
DEY
BPL plotLoop
RTS

Assemble that lot in and give it another whazz!


Dave


Top
 
PostPosted: Fri May 09, 2008 1:06 pm 
Offline
User avatar
 WWW  Profile

Joined: Fri Mar 28, 2008 10:47 am
Posts: 11
Thanks Dave - I really should get on with my real work. This is like learning a foreign (y'know, normal) language in that all my stupid mistakes are in public for anyone in earshot to laugh at. Never mind, I'm learning loads.

The 6502 reference is very useful, much handier than the NAUG for opcodes.

I've updated the program

Code:
.ORG $900
init:
 ;LDA #22 ; VDU 22 - set mode
 ;JMP $FFEE ;OSWRCH
 ;LDA #2 ; MODE 2
 ;JMP $FFEE ; OSWRCH
 LDA #$00 ;the low byte of the initial address
 STA $70 ;store at &70
 LDA #$40 ;the high btye of the initial address
 STA $71 ;store at &71
main:
 JSR plot ;draw the picture
 JSR move           
 LDA #19
 JSR $FFF4                 
 JMP main ;start the loop again
plot:
 LDY #8 ;the amount of pixels to show / 2
 LDA #11 ;the byte value to enter into the address to show a yellow pixel and a red pixel
plotloop:
 STA ($70), Y
 DEY
 BPL plotloop
 RTS
move:
 LDA $70
 ADC #8
 STA $70
 RTS


There are two areas I want to look at. Firstly, I'm trying to change to mode 2 in code:
Code:
 ;LDA #22 ; VDU 22 - set mode
 ;JMP $FFEE ;OSWRCH
 ;LDA #2 ; MODE 2
 ;JMP $FFEE ; OSWRCH


This is commented out, because it is obviously wrong. I appear to be going to mode 6. I've cribbed this from Christopher Dewhurst's analysis of siege, and clearly shows the dangers in cut and pasting code you don't understand. What have I done wrong here?

Secondly, the move routine.

Code:
move:
 LDA $70
 ADC #8
 STA $70
 RTS


I replaced it with a simple INC as you suggested, but it was very slow. I think that this was because I was over painting the same 'character block' several times. I've increased the value in &70 by 8, and it appears to work and is faster, but not as fast as I'd expect. Any advice?

Thanks

Sam

_________________
Image


Last edited by rival on Fri May 09, 2008 1:50 pm, edited 1 time in total.

Top
 
PostPosted: Fri May 09, 2008 1:16 pm 
Offline
User avatar
 WWW  Profile

Joined: Fri Mar 28, 2008 10:47 am
Posts: 11
OK - Got the first one!

I will learn the difference between JMP and JSR. I will learn the difference between JMP and JSR. I will learn the difference between JMP and JSR. I will learn the difference between JMP and JSR. I will learn the difference between JMP and JSR. I will learn the difference between JMP and JSR. I will learn the difference between JMP and JSR. I will learn the difference between JMP and JSR. I will learn the difference between JMP and JSR. I will learn the difference between JMP and JSR. I will learn the difference between JMP and JSR. I will learn the difference between JMP and JSR. I will learn the difference between JMP and JSR. I will learn the difference between JMP and JSR. I will learn the difference between JMP and JSR. I will learn the difference between JMP and JSR. I will learn the difference between JMP and JSR. I will learn the difference between JMP and JSR. I will learn the difference between JMP and JSR.

_________________
Image


Top
 
PostPosted: Fri May 09, 2008 1:42 pm 
Offline
User avatar
 WWW  Profile

Joined: Thu Apr 03, 2008 2:49 pm
Posts: 277
Location: Antarctica
rival wrote:
I replaced it with a simple INC as you suggested, but it was very slow. I think that this was because I was over painting the same 'character block' several times. I've increased the value in &70 by 8, and it appears to work and is faster, but not as fast as I'd expect. Any advice?


Did you put the call to OSByte 19 in? That will slow it down.

rival wrote:
Thanks Dave - I really should get on with my real work. This is like learning a foreign (y'know, normal) language in that all my stupid mistakes are in public for anyone in earshot to laugh at. Never mind, I'm learning loads.


Well, as they say, the only stupid question is the one that doesn't get asked :)


Top
 
PostPosted: Fri May 09, 2008 3:20 pm 
Offline
User avatar
 Profile

Joined: Wed Jan 09, 2008 7:30 am
Posts: 406
rival wrote:
Firstly Steve - I've changed the settings as you've suggested and everything is fine. I'm compiling in Swift. I seem to have a problem with Windows Media Player though, and I can't play your tutorial videos at the moment.


Are you Vista. Apparantly Microsoft removed a common codec stopping files being played. Should work ok in realplayer etc. Can't remember which one but was discussed on here I think

Also, I think the old "Advanced User Guide" is a PDF, so you can search it. Might be worth a download. I refer to that the most actually and use the "New" one for Master specific stuff, although I do have a paper copy of that so don't have to put up with scanned version.


Top
 
PostPosted: Fri May 09, 2008 3:25 pm 
Offline
User avatar
 WWW  Profile

Joined: Wed Jan 09, 2008 10:23 am
Posts: 359
Location: Glasgow, Scotland
SteveO wrote:
rival wrote:
Firstly Steve - I've changed the settings as you've suggested and everything is fine. I'm compiling in Swift. I seem to have a problem with Windows Media Player though, and I can't play your tutorial videos at the moment.


Are you Vista. Apparantly Microsoft removed a common codec stopping files being played. Should work ok in realplayer etc. Can't remember which one but was discussed on here I think

There were also codecs removed between the original release of XP and XP with service pack 1.

Kind regards,

Francis.


Top
 
PostPosted: Fri May 09, 2008 3:48 pm 
Offline
User avatar
 WWW  Profile

Joined: Fri Mar 28, 2008 10:47 am
Posts: 11
I've got Windows XPx64, but I'm having problems with Audible and other file formats. I need to kind of re-install WMP, but it doesn't seem easy to do. Which is a shame, because I don't really get on with other media players; I find WMP easily the best suited to me.

Also, I suspect that I've got a paper copy of the AUG in storage in London. I'll dig it out next time I'm in the UK.

_________________
Image


Top
 
PostPosted: Sun May 11, 2008 9:04 am 
Offline
User avatar
 WWW  Profile

Joined: Fri Mar 28, 2008 10:47 am
Posts: 11
Steve - I've a pile of suggestions for Swift. I'll sort them out into an email for you.
Dave - slowness was caused by waiting for VSync. I've taken it out.

OK, so I've been snatching 5 minutes here and there. This is my latest version

Code:
.ORG $900
init:
 LDA #22 ; VDU 22 - set mode
 JSR $FFEE ;OSWRCH
 LDA #2 ; MODE 2
 JSR $FFEE ; OSWRCH
 LDA #5
 JSR $FFEE
 JSR reset ; reset to top left
 LDA #1; default byte value
 STA $72
main:
 JSR plot ;draw the picture
 JSR move           
 JMP main ;start the loop again
plot:
 LDY #8 ;the amount of pixels to show / 2
 LDA $72 ;the byte value to enter into the address
plotloop:
 STA ($70), Y
 DEY
 BPL plotloop
 RTS
move:
 LDA $70
 ADC #8
 STA $70
 BVS movehi
 RTS
movehi:
 LDA #0
 STA $70
 INC $71 ;Add 1 to the hi byte
 LDA $71
 CMP #$7F
 BEQ reset ;move back to top left if we've moved the high byte to &80
 RTS
reset:
 LDA #$00 ;the low byte of the initial address
 STA $70 ;store at &70
 LDA #$40 ;the high btye of the initial address
 STA $71 ;store at &71
 INC $72 ;move the colour on
 RTS
end:
 NOP


So the idea is that it paints the byte in &72 to every byte on screen. When its done a full screen, it increases the value in &72 and starts again. It isn't working properly, and a picture paints a thousand words.
Image

The theory is that I'm doing this by adding 8 to the low byte after every plot routine, and then checking the overflow bit. If I've overflowed, I increase the high byte by one. When I increase the high byte, I test to see if I've got to the end of the screen memory. If so, I reset the start location back to &3000, increase the value in &72 and start again.

Can someone point out the obvious error I've made?

Thanks

_________________
Image


Top
 
PostPosted: Sun May 11, 2008 10:03 am 
Offline
 Profile

Joined: Thu Dec 27, 2007 3:57 pm
Posts: 20
You need to check the carry flag, not the overflow flag when doing additions.

You also need to clear the carry flag before doing the add as well.

Try changing your move routine to :

Code:
LDA $70
CLC
ADC #8
STA $70
BCS movehi
RTS


Jon.


Top
 
PostPosted: Sun May 11, 2008 12:54 pm 
Offline
User avatar
 WWW  Profile

Joined: Fri Mar 28, 2008 10:47 am
Posts: 11
Thanks Jon, that's magic. I've now got a full screen of flashing colours!

_________________
Image


Top
 
PostPosted: Sun May 11, 2008 1:03 pm 
Offline
User avatar
 Profile

Joined: Wed Jan 09, 2008 7:30 am
Posts: 406
As Jon said, but it still isn't quite right,

You need to make the following changes. Firstly your not starting at $3000 (you know you have to) but you've accidentally done a typo by putting in


Code:
LDA #$40 ;the high byte of the initial address


should be #$30

That will get it starting at the beginning of the screen. The the other issue is that it doesn't fill the screen. You've written

Code:
CMP #$7F

But by compring with this value means the last 256 bytes of screen memory won't get written to, just change to

Code:
CMP #$80


in fact these lines;

Code:
LDA $71
CMP #$7F
BEQ reset ;move back to top left if we've moved the high byte to &80



can be replaced with

Code:
BMI reset


several cycles saved. This works because You want to test when you get to $80, just luckily anything below this value does not have the top bit set (bit 7). When it hits $80 (via your inc $71) then bit 7 becomes set and therefore sets the negative flag.

also, not an error as such but the lines;

Code:
movehi:
LDA #0
STA $70


Need not be there at all, you can remove them and the code does the same. This is because the $70 value starts at 0 and you add 8 each time, therefore when the carry gets set the value in $70 will actually be 0 anyway, so you can save yourself some machine cycles :). i.e. you'll get to value 248 with no carry, add 8 to this creates 256 exactly, which will leave 0 in $70 and a carry.


So to put it together all these lines;

Code:
LDA #0
STA $70
INC $71 ;Add 1 to the hi byte
LDA $71
CMP #$7F
BEQ reset ;move back to top left if we've moved the high byte to &80


can be replaced by;

Code:
INC $71 ;Add 1 to the hi byte
BMI reset ;move back to top left if we've moved the high byte to &80


and that will save you quite a few cycles.

P.S. I look forward to your suggestions for Swift :)


Top
 
PostPosted: Sun May 11, 2008 1:39 pm 
Offline
User avatar
 WWW  Profile

Joined: Fri Mar 28, 2008 10:47 am
Posts: 11
Solid gold.

Quote:
LDA #$40 ;the high byte of the initial address

should be #$30

That will get it starting at the beginning of the screen. The the other issue is that it doesn't fill the screen. You've written

CMP #$7F

Yep, I'd picked these up. They were just values I was playing with.

Quote:
LDA #0
STA $70
INC $71 ;Add 1 to the hi byte
LDA $71
CMP #$7F
BEQ reset ;move back to top left if we've moved the high byte to &80

can be replaced by;

INC $71 ;Add 1 to the hi byte
BMI reset ;move back to top left if we've moved the high byte to &80


Magic, thank you. I'd never have thought to see what the decimal value of &80 was. As it is 128, then bit 7 is set and I can see if it would represent a negative number - fantastic.

Quote:
and lastly, not an error as such but the lines;

movehi:
LDA #0
STA $70

Need not be there at all,


I suspected that this was the case, but I've fallen foul of assumptions and impossible cases too many times in the past, so I stuck them in to be certain. I've stripped them out now.

I'll try to put something together soon about Swift.

_________________
Image


Top
 
PostPosted: Sun May 11, 2008 1:47 pm 
Offline
User avatar
 Profile

Joined: Wed Jan 09, 2008 7:30 am
Posts: 406
Quote:
Magic, thank you. I'd never have thought to see what the decimal value of &80 was. As it is 128, then bit 7 is set and I can see if it would represent a negative number - fantastic.


:) It's just one of those things I do in my head automatically with hex or decimal numbers, I'm always converting to the binary value (admittedly much easier to do when your using Hex). Sad I know, I should seriously get out more :lol:


Top
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 73 posts ]  Go to page 1, 2, 3, 4  Next

All times are UTC [ DST ]


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron