It is currently Mon Oct 20, 2014 5:50 pm

All times are UTC [ DST ]




Post new topic Reply to topic  [ 103 posts ]  Go to page Previous  1, 2, 3, 4, 5, 6  Next
Author Message
PostPosted: Sat Oct 10, 2009 10:41 am 
Offline
User avatar
 Profile

Joined: Mon Jan 07, 2008 7:02 pm
Posts: 273
Yeah - whoops! That'll teach me to _test_ code I post here...


Top
 
PostPosted: Sat Oct 10, 2009 10:46 am 
Offline
User avatar
 Profile

Joined: Fri Apr 25, 2008 7:55 pm
Posts: 147
Rich wrote:
If you like, I can post code to do this, or perhaps you'd prefer to have a go at implementing it yourself first?

If the 'you' is me then yes please Rich, that would be great. If the 'you' is Colin then yes please anyway - Col can look the other way if he wants to do it himself ;)

(I do have a well-on-the-way project btw and these basic but effective tricks are really helpful :D)

Martin


Top
 
PostPosted: Sat Oct 10, 2009 12:06 pm 
Offline
User avatar
 Profile

Joined: Mon Jan 07, 2008 6:46 pm
Posts: 380
Location: Málaga, Spain
OK, here it is. I guess this is a spoiler, so if you don't want to know how it's done, look away now!

Here is some skeleton code (and a disc image) presented in BeebAsm format. Essentially, it's more a tutorial in setting up the hardware and handling the interrupts than anything else. You'll notice that the configuration of the video hardware is very important, in particular explicitly setting the screen line where VSync should be generated, and setting the interlace mode. You can't necessarily guarantee either of these when selecting Mode 2 (because it depends on the *TV setting). Anyway, this code shows you how to set a timer to trigger just before the scanline of your choice starts to be rasterised.

Code:
vsynccount = 0              ; zero page address of the vsync counter

DEBUG_RASTERS = TRUE        ; conditionally assemble debug code
screenLine = 32             ; screen line (in pixels) on which timer should interrupt
vsyncPosition = 34          ; screen character row at which VSync is generated
vsyncWidth = 2              ; pulse width in scanlines of VSync signal (default is 2)

; number of screen lines (in pixels) between Vsync and line 0
numLinesAfterVsync = (39 - vsyncPosition) * 8 - vsyncWidth

; time spent rendering the border prior to our chosen line, in usecs
borderTime = (128 - 80) / 2

; time in usecs between the irq occurring and the service routine being reached
irqServiceLatency = 51

; calculate the timer value required to interrupt at the right place
timerLength = 64 * (screenLine + numLinesAfterVsync) - irqServiceLatency - borderTime

ORG &1900


\\-----------------------------------------------------------------
\\  The entry point of the code
\\-----------------------------------------------------------------
.start

    SEI
    LDX #&FF:TXS                    ; reset stack

    \\ Configure VIAs

    STX &FE44:STX &FE45
    LDA #&7F:STA &FE4E              ; disable all System VIA interrupts
    STA &FE6E                       ; disable all User VIA interrupts
    STA &FE43                       ; set keyboard data direction
    LDA #&C2:STA &FE4E              ; enable VSync and timer interrupt
    LDA #&0F:STA &FE42              ; set addressable latch for writing
    LDA #3:STA &FE40                ; keyboard write enable
    LDA #0:STA &FE4B                ; timer 1 one shot mode

    \\ Configure CRTC

    LDA #8:STA &FE00
    LDA #0:STA &FE01                ; turn off interlace
    LDA #10:STA &FE00
    LDA #32:STA &FE01               ; turn off cursor
    LDA #7:STA &FE00
    LDA #vsyncPosition:STA &FE01    ; explicitly set vsync position
    LDA #3:STA &FE00
    LDA #vsyncWidth * 16 + 8
    STA &FE01                       ; explicitly set vsync pulse width

    \\ Set interrupt handler

    LDA #LO(irq):STA &204
    LDA #HI(irq):STA &205           ; set interrupt handler
    CLI


\\-----------------------------------------------------------------
\\  This is the main loop - totally empty at the moment!
\\-----------------------------------------------------------------
.mainloop

    LDA #1:STA vsynccount

    \\ Do main loop here

    .waitforvsync
    LDA vsynccount:BNE waitforvsync

    JMP mainloop



\\-----------------------------------------------------------------
\\  The IRQ handler
\\-----------------------------------------------------------------
.irq

    LDA &FE4D
    AND #2                          ; test if it's a Vsync interrupt
    BNE irqvsync

    \\ If we got here, it's definitely a timer interrupt

.irqtimer
    IF DEBUG_RASTERS
        LDA #4:STA &FE21            ; debug change background to blue
    ENDIF
    LDA #&40:STA &FE4D              ; acknowledge timer interrupt
    LDA vsynccount
    BEQ skipdec
    DEC vsynccount                  ; decrement vsync count if not already zero
    .skipdec

    LDA &FC                         ; restore A
    RTI                             ; and exit

    \\ If we got here, it's a vsync

.irqvsync
    STA &FE4D                       ; acknowledge vsync interrupt
    LDA #LO(timerLength):STA &FE44  ; set timer interrupt period
    LDA #HI(timerLength):STA &FE45

    IF DEBUG_RASTERS
        LDA #7:STA &FE21            ; debug change background to black
    ENDIF

    LDA &FC                         ; restore A
    RTI                             ; and exit



.end

SAVE "Code", start, end

For some reason, the irqServiceLatency value seems to be rather large, but it has to be this big in order that the timer interrupts as soon as the right border begins on the line previous to the target line (in order to maximise our time as much as possible). Tom, you got any ideas where I've gone wrong here?


Attachments:
Raster.zip [2.69 KiB]
Downloaded 16 times


Last edited by RichTW on Sun Oct 11, 2009 12:18 pm, edited 1 time in total.
Top
 
PostPosted: Sat Oct 10, 2009 2:01 pm 
Offline
User avatar
 Profile

Joined: Mon Sep 14, 2009 7:50 pm
Posts: 91
Thats done the trick.. thanks guys... I can now see whats going on, when, and how fast too :D

Think I'll look at trying to optimise some of the code to try to speed things up...

Cheers, Colin


Top
 
PostPosted: Sat Oct 10, 2009 6:47 pm 
Offline
User avatar
 Profile

Joined: Mon Jan 07, 2008 6:46 pm
Posts: 380
Location: Málaga, Spain
RichTW wrote:
For some reason, the irqServiceLatency value seems to be rather large, but it has to be this big in order that the timer interrupts as soon as the right border begins on the line previous to the target line (in order to maximise our time as much as possible).

OK, I understand why it's that big now - it breaks down like this:

Upon VSync:
Code:
(jump to IRQ)    7
STA &FC          3
PLA              4
PHA              3
AND #&10         2
BNE (not taken)  2
JMP (&204)       5
...
LDA &FE4D        6 (worst case)
AND #2           2
BNE (taken)      3
STA &FE4D        5
LDA #            2
STA &FE44        6
LDA #            2
STA &FE45        5


Upon timer interrupt:
Code:
(jump to IRQ)    7
STA &FC          3
PLA              4
PHA              3
AND #&10         2
BNE (not taken)  2
JMP (&204)       5
...
LDA &FE4D        6 (worst case)
AND #2           2
BNE (not taken)  2
-------------------
    total       93

Of course, we have to take into account the IRQ handling overheads twice. On the VSync, we have to go through the whole process before we even get to set the timer, so we're already behind. And then when the timer interrupts, we repeat the whole preamble a second time, which gives us an additional delay of 47us. The additional few microseconds used by my code take into account the extra time it takes to load a value and store it to the palette (which are the first 'visible' moments of the interrupt), plus also to account for the latency if the IRQ happens in the middle of executing an instruction (could be as much as 3us more if a slow instruction is interrupted, e.g. a LDA (ind, X)).


Top
 
PostPosted: Sat Oct 10, 2009 7:18 pm 
Offline
User avatar
 Profile

Joined: Fri Apr 25, 2008 7:55 pm
Posts: 147
That's brilliant Rich - explains it all very nicely :D

One question - When you explicitly set the point where the vsync interrupt occurs, does this affect the actual physical behaviour of the raster or literally only the line at which the interrupt occurs? If the latter, why is it necessary to set the vsync position and then use that to set a timer to interrupt at a point before vsync - can you not just set vsync to occur at this earlier point? (I strongly suspect I'm missing something obvious :lol:)

Martin


Top
 
PostPosted: Sun Oct 11, 2009 11:22 am 
Offline
User avatar
 Profile

Joined: Mon Jan 07, 2008 6:46 pm
Posts: 380
Location: Málaga, Spain
When you set the VSync position, it is literally specifying the screen line at which the VSync pulse is sent to the VDU. At this point an interrupt is also generated. Since VSync triggers flyback, it will always denote which line will be the last one in the bottom border, so if you were to set it to the last line in your visible playing area, the whole screen would be moved physically downwards so that there was no bottom border at all (which would of course be far too low). That's why we need the timer to interrupt at the end of the displayed screen, before the bottom border is rasterised.

The VSync pulse width doesn't affect the display position at all, but it does delay the interrupt by the number of scanlines it specifies. It always defaults to 2 scanlines in Beeb modes, but I just set it explicitly to make a point.


Top
 
PostPosted: Sun Oct 11, 2009 12:56 pm 
Offline
User avatar
 Profile

Joined: Fri Apr 25, 2008 7:55 pm
Posts: 147
Got it. I thought perhaps we could signal a virtual vsync IRQ separate from the actual raster pulse but since not, that explains the need for a timer.

Thanks very much for all that Rich (and Tom), I now fully understand the techniques and can see all the benefits so I'll be adding this to my project forthwith :D

Martin


Top
 
PostPosted: Mon Oct 12, 2009 8:44 pm 
Offline
User avatar
 Profile

Joined: Mon Sep 14, 2009 7:50 pm
Posts: 91
OK.... I've been trying to muck about optimising code.....

I did manage to roll all the convert/colour/plot code into one loop.... But its not saved as much cpu time as I would have liked.... (Its nice neat code though, lol)... So.. forget that for now.....

OK.. I've done a screen sync.... and a delay to move stuff down the screen a litlle....

Green is converting the sprite from 64 bytes to BBC 128 bytes (and changing colour tables)

Blue is clearing old plot, Yellow is plotting new sprite.....

I've tried optimising (and it shaves a few cycles off) , but at the end of the day the code still has to shift a LOT of bytes around, so its not saving that much overall !!!

There are a couple of ways to shuffle memory round, so its faster to access in loops (or in mutiple byte numbers) - but it gets messy !! - So all the code is unoptimised for now....

So.... I've now got a fairly good idea, how fast stuff runs, and I'm unlikely to double the speed of the code, however much optimising I do.... (and I will try to optimise as fast as I can....eventually)

Dropped down to 4 sprites... so everthing runs at 50 FPS (inc conversion - which may well be off line - or a MIX - some online convertions but mostly offline !!)

Cheers, Colin

Ps... Here is a version of the new c64>beeb disply plot Code (that I'm not using.. but works, just to demonstrate how it works - I don't think it can be optimised very much !!! - I moved the tables down into zeropage, and it speeded up a little, but not that much overall !!) - I will probably use a variant of it to do the graphics convertion 'off line'.... ITS VERY BRUTE FORCE !!!

.alias SCREEN $70
.alias TEMP $72
.alias TEMP2 $73

LDA #$30
STA SCREEN+1
LDA #$00
STA SCREEN

Ldx #$00
STX TEMP2

LOOP1: LDY #$00

LOOP2: LDX TEMP2
INC TEMP2

lda $2000,x ; sprite starts here c64 format - 63 bytes of data... EACH BYTE is 4 PIXELS !! Unlike BBC mode 2 !!
sta TEMP

LDA #$00
ASL TEMP
ROL
ASL TEMP
ROL
TAX
LDA COLPALLET,X ; ( 0>3 - 0 = Background 1-3 = the 3 colours to use)
TAX
LDA BYTEPATTERN,X
ASL
STA FRIG1+1

LDA #$00
ASL TEMP
ROL
ASL TEMP
ROL
TAX
LDA COLPALLET,X
TAX
LDA BYTEPATTERN,X
FRIG1: ORA #$00
STA (SCREEN),Y ; 1ST BYTE SCREEN LOCATION

TYA
CLC
ADC #$08
TAY

LDA #$00
ASL TEMP
ROL
ASL TEMP
ROL
TAX
LDA COLPALLET,X ; ( 0>3 - 0 = Background 1-3 = the 3 colours to use)
TAX
LDA BYTEPATTERN,X
ASL
STA FRIG2+1

LDA #$00
ASL TEMP
ROL
ASL TEMP
ROL
TAX
LDA COLPALLET,X
TAX
LDA BYTEPATTERN,X
FRIG2: ORA #$00
STA (SCREEN),Y ; 2nd BYTE SCREEN LOCATION

TYA
CLC
ADC #$08
TAY
CPY #$30
BNE LOOP2

INC SCREEN
LDA SCREEN
AND #$07
BNE SKIP1

LDA SCREEN
SEC
SBC #$08
CLC
ADC #$80
STA SCREEN
LDA SCREEN+1
ADC #$02
STA SCREEN+1

SKIP1:

LDA TEMP2
CMP #63
BNE LOOP1

RTS


Attachments:
coltest2.zip [2.61 KiB]
Downloaded 14 times
Top
 
PostPosted: Tue Oct 13, 2009 7:25 pm 
Offline
User avatar
 Profile

Joined: Mon Sep 14, 2009 7:50 pm
Posts: 91
OK..... Heres a post to go a little 'off topic' but still kind of keep on track....

Having a quick muck about with PuCrunch ( I've used this before briefly on the c64).

Saved all my sprite data out... Its 8k worth... and crunches down to 3k... (mates game uses 12.5k of sprites and goes down to 4.6K)

Level data (50 game screens -256 bytes each) is 12.5K and crunches down to 4.25K...

so.. quick sums.. looks like its easily coming in under 40%....

If say I managed to optimise all my graphics/levels down to a 20K chunk (or a lot less with some optimising).... Say I end up with 4K of data packed.... I could then uncrunch this to the screen memory (as a scratch pad) - Pick out what I needed and copy it to a work area (say 2K ?) - So use 6K for whatever I have left overall...less a little for zero page, stack, etc.

.....then things could start to become quite intersting..(will be very tight though).. Either that or Multiload (which I want to try and avoid) !!

I'm going to be taking a break soon from this Scene for a short while (need to sort some c64 coding out for a music player - and other real life issues) - and then hopefully return one I have a game plan...

I'll be experimenting with some other c64 graphics formats too... Like Character sets/fonts (2k) and expanded xy c64 sprites (slow and messy, but might be fun !!)

Cheers, Colin


Top
 
PostPosted: Wed Oct 14, 2009 10:28 pm 
Offline
User avatar
 Profile

Joined: Mon Sep 14, 2009 7:50 pm
Posts: 91
Optimised my code above a little to ignore when the data is zero, so that it skips some of the indexing.... slows things though for very graphicy sprites...

Should also work with the other code I've done (which plots pre-converted 128 byte sprites)...

I'm quite happy with my progress.....

I'm going to start another thread about memory useage on the bbc !!

Cheers, Colin


Top
 
PostPosted: Fri Oct 16, 2009 8:41 pm 
Offline
User avatar
 Profile

Joined: Mon Sep 14, 2009 7:50 pm
Posts: 91
I'm now looking at c64 character font plotting.....

Heres a bbc screen shot, compared to the c64 version... You can ignore the colours for now... Very rough and ready code to copy the 'font' to the screen... The font is a Banner kind of thing.... Same kind of format as the sprites, so lots and lots of bit shifting of the 2k font to display on the beeb as 4k..... !!

At the moment the c64 version runs a hi-light through the banner, and changes colours from time to time..... But the bbc one just plots.... Got some spinning sprites below to test, but the memory is garbage for now..... On the c64 version I have some bubble sprites multiplexed floating up around the banner...(with more re-cycled hardware sprites below for the fishies etc) . Early days.... ;-)

Looks good to me !!

Attachment:
colaqua.JPG [74.73 KiB]
Downloaded 304 times


Last edited by ColinD on Fri Oct 16, 2009 8:58 pm, edited 1 time in total.

Top
 
PostPosted: Fri Oct 16, 2009 8:54 pm 
Offline
User avatar
 Profile

Joined: Wed Jan 09, 2008 7:30 am
Posts: 406
ColinD wrote:

Looks good to me !!



and me to ! :D


Top
 
PostPosted: Fri Oct 16, 2009 9:18 pm 
Offline
User avatar
 Profile

Joined: Mon Sep 14, 2009 7:50 pm
Posts: 91
SteveO wrote:
ColinD wrote:

Looks good to me !!


and me to ! :D


Ta very much ;)

The font graphics 'slab' is very memory inefficeint though.... its basically a 2k bitmap in 4 colours...(not sure how bitmaps are stored, but probably similar'ish) and there are lots of zero bytes scattered..... could probably be optimised to 1K but would be a LOT of HARD work !!! - Remember the c64 had much more memory to waste for trivial things like this.....

There is another 2k font used in my c64 game too... some for the font (in mono colour mode), and some for the character graphics in multicolour mode.... I'll have to bin the font and use native bbc fonts maybe if I can suss out how they are stored in the rom, and optimise the rest of the font too (and try to optimise level storage !!)..... Grrrr !!!!

##edit## As another 'test' next, I'll probably try to plot one of my game levels up on screen (minus the sprites of course) - I think things will need to be simplified, so that the sprites don't overlap the game screen graphics (or very little) - will be a bit of a shame and things will have to be redesigned somewhat, but otherwise things will run very slow compared to a c64....


Top
 
PostPosted: Fri Oct 16, 2009 9:49 pm 
Offline
User avatar
 Profile

Joined: Mon Sep 14, 2009 7:50 pm
Posts: 91
Here's the C64 'unfinished' game screen shot of one of the 50 levels (not all finished)... as seen at the Lass a few months ago at Console-Combat.. Sprite Priorities are mucked up (sprites should be infront of the background graphics)....

Attachment:
colaquashot.JPG [45.48 KiB]
Downloaded 285 times


Its a shame that the beeb only has the 8 colours to play with, so won't be able to do brown shades / grey shades etc.... so won't be able to show it all off in its intended glory !! (could possibly flicker the pallet of the 8-16 colours ? every screen under the sync interupt - would that work ??)

Not sure what to do yet... either make the enemy sprites 16(8)x16 instead of 24(12)x21... and make the screens native c64 sixe, or enlarge the screens a bit (to give the sprites free space to move around)... (multicolour halves the horizontal res)

The crab will be a bugger, as he likes to scurry about on the same level as the pearls/bubbles to collect (ovelapping)..... I could make all the other enemys move in free space...

You can see looking at the sprites that I've used the 2nd 'definable' colour to change the sprite main colour.. and used the 3rd and 4th 'fixed' multi-colours on the sprites as basic black and white... 1st colour is transparent..

I'm going to chill out now... too many 'bows'...

Cheers, Col


Top
 
PostPosted: Sat Oct 17, 2009 9:26 am 
Offline
User avatar
 Profile

Joined: Wed Jan 09, 2008 7:30 am
Posts: 406
I was at the Lass, missed this :( Looks good.


Top
 
PostPosted: Sun Oct 18, 2009 2:09 am 
Offline
User avatar
 Profile

Joined: Mon Sep 14, 2009 7:50 pm
Posts: 91
A little more progress... code is REALLY brute force, with lots of plotting sections repeated till I start breaking stuff into subroutines....
Attachment:
collevel1.JPG [63.06 KiB]
Downloaded 240 times
Attachment:
collevels.zip [10.8 KiB]
Downloaded 15 times


Top
 
PostPosted: Sun Oct 18, 2009 6:10 am 
Offline
User avatar
 WWW  Profile

Joined: Thu Jan 10, 2008 7:45 pm
Posts: 472
Location: Treddle's Wharf, Chigley
This is looking fantastic. If you want to see a good example of how get the most of the 8 colour palette you have to play with, then you may like to take a look at the Beeb version of Jamie Woodhouse's game "Qwak!". He uses several nifty tricks in his sprite designs to get around the limitations of the palette.

If getting good brown shades is important, I would suggest putting some of the C64 sprites through Francis Loch's BBC Image convertor and seeing what you can come up with.

Hope you don't mind my suggestions. The game is looking fabulous and I can't wait to play it.


Top
 
PostPosted: Sun Oct 18, 2009 7:47 am 
Offline
User avatar
 Profile

Joined: Wed Jan 09, 2008 7:30 am
Posts: 406
Yep, looking really good, are you re-using some of your C64 code ? or are you just really quick at knocking all this stuff up 8-)


Top
 
PostPosted: Sun Oct 18, 2009 2:48 pm 
Offline
User avatar
 Profile

Joined: Mon Sep 14, 2009 7:50 pm
Posts: 91
SteveO wrote:
Yep, looking really good, are you re-using some of your C64 code ? or are you just really quick at knocking all this stuff up 8-)


All the code is new, I'm just using the re-using graphics and the 1st levsls data - the c64 code is unsuitable due to the way it deals with character plotting.

Code is pretty clunky and oversized, and I'll have to optimise it - Knocked the level display up in a couple of hours after working out the format again... 19 x 10 Tiles (Each Tile is 4 characters from the font in increments of 4) - Think I've got 32 Tiles and the Hi-Res font below that.

Cheers, Colin


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

All times are UTC [ DST ]


Who is online

Users browsing this forum: No registered users and 0 guests


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