Jump to content
IGNORED

Scrolling (from memory buffer) and > 256 characters


mksmith

Recommended Posts

Hi all,

 

I been wanting to look into scrolling for quite a while to see how we can achieve having maps > 256 columns (horizontal).  In various guises across the forum (for 7800basic) there are quite a few examples generally using plotmap (drawing a left and right screen halves - there is a 32 column limit to drawing using plotmap) to do the job shifting the location to help simulate fine scrolling and it worked very well for me in my GnG sample (which just happened to fit nicely with the split level map). Anyway I did some research around some techniques used and starting with pure 7800basic got things moving but then converted the main routine to pure assembly (thanks to some learning doing PETSCII as well as assistance @RevEng has generously provided to myself and the community over the last few years).

 

The main goals were the following:

  • get a map larger than 256 characters wide (currently 512)
  • use the 'Under the Hood' TM method after drawing the initial screen to simulate fine scrolling - this method allows us to directly access the screen row zones of already drawn and saved objects rather than redrawing everything 
  • use hand-coded assembly for the best possible speed performance (even my low level of knowledge of 6502 has shown significant increases)

Stretch goals:

  • ideally make it multi-directional (left and right) - TBC
  • can we use double buffering of screen buffers to increase performance? (yes we can but currently at the expense of redrawing the background when switching buffers. Shifting sections of the back buffer each frame rather than at the end also spreads the load.) 

 

Map and buffer

  • Maps are designed for 512x17 in size
    • width can be customised (recommended 256 increments due to math)
    • height can be customised (adding or removing MAPSCREENBUFFERROWX entries)
    • changes will need to be made to the shift/copy routines to accommodate
  • Buffer is designed for 42x17 in size and scrolling from right to left
  • Columns 41/42 are used to load the next incoming characters
  • Scrolling based on 8 pixels (or 2 characters) for better performance

 

Process

  • Draw initial screen background (a left and right side) and save screen
  • Shift background using the 'Under the hood' method
  • At completion of the shift, restore the background zone(s) to their starting position, shift the buffer columns over 2 characters and copy in the next 2 characters


Notes

  • As the 'Under the Hood' TM method is used we don't need to continually draw the background
  • We need to add a drawwait call to ensure the restore/shift/copy routine doesn't tear the screen but this introduces a 1 frame delay (and potentially more??). To match this I've added a counter to simulate this during fine scroll
  • Overall the scroll shifts every 2nd (or could be more if required) frame then allowing time for other updates on the other frame(s)
  • On PAL there is frame variations (TBD) making the scrolling less smooth
  • If moving 8 pixels just call the CourseScroll routine directly
  • The routine could be changed to copy the map data out of ROM but larger maps might be difficult to access due to bank requirements

 

Src

20220704.scrolling.zip

 

Build

View on JS7800

scrolling.a78

 

Final thoughts

There are probably a few things that can be improved so please feel free to discuss! Hopefully some of you will find this useful for your projects!

 

The Uridium map was grabbed out of CharPad Pro by Subcrist Software (https://subchristsoftware.itch.io/charpad-pro) is highly recommended and is a fantastic map building tool even for the 7800! The characterset width was reduced to cater for our 7800 needs (tip!! multi-color on the c64 is essentially double-width and can be halved for 7800 needs).

 

  • Like 12
  • Thanks 1
Link to comment
Share on other sites

2 hours ago, Eagle said:

Hmm 7000 cycles, not great, not terrible :D 

There is definitely a lot of repetitive shifting of data - the double buffer version is nice as it allows that to be spread over multiple frames at the cost of redrawing to switch buffers.   There is a major cost on the final shift in this single buffer version but saving on the redrawing is a big win regardless. 

 

I'm sure someone with a better idea on 6502 could make a few savings somewhere. Also some of the loops could be unrolled and/or in-lined to save a few cycles.  Certainly very happy to take any feedback people might have to make it better!

  • Like 3
Link to comment
Share on other sites

Started expanding the scrolling to cater for left and right movement. Updated the buffer to 44 columns and repositioned the default positions.  I've inlined the main shift and copy routines which will save 6 cycles per column activity at the expense code space.

 

Next up will be getting the left -> right scrolling going (will do the coarse scrolling first). 

  • Like 3
Link to comment
Share on other sites

2 hours ago, Eagle said:

Why you redrawing screen instead of changing Display List screen address? 

 

The 'Under the Hood' method utilises the savescreen/restorescreen/drawscreen feature of 7800basic.  Normally moving objects (maps, sprites etc) are redrawn each loop as part of that process but what the 'Under the Hood' method allows us to do is directly access the zone objects to shift them within their zone without calling the 'plot' feature each time.   My next step in this would be shifting game sprites (ones staying within their zones) using this process without calling plotsprite each frame - probably not so easy depending on the actual game play.

 

It may not be as optimised as fully controlling the process yourself but that is definitely way above what the majority of us (including me!!) are currently capable of doing without 7800basic.  I guess this is a bit of a halfway mode but still allow the use of 7800basic.  

 

 

  • Like 1
Link to comment
Share on other sites

 

18 minutes ago, SlidellMan said:

Matt, Can this be used for vertical scrolling?

Unfortunately not in it current format. It would definitely be possible but the 'Under the Hood' savings will need to be removed as things would be crossing screen zones. 

  • Like 2
  • Thanks 1
Link to comment
Share on other sites

Hi @mksmith

Quick example scrolling Left/Right  Uridium in MADS

Use joystick

About 3500 cycles (not optimized) blue line showing CPU usage

 

 

Uridium scroll lef&right - Link to JS7800

 

 

Main code below (sorry for using MADS macros but code is much shorter)

https://mads.atari8.info/mads_eng.html

 

edit: ram usage for Uridum (42bytes*17line)+512bytes map lenght+1byte=1227bytes

You can use any map up to about 16000 bytes length :D 

screen equ $2400+1

NMI
	phr
	mva #$a6 BACKGRND   ;show CPU time
	jsr Joystick
	jsr CalculateOffset
	jsr UpdateDisplaylist
	jsr	CopyColumnRight
	jsr CopyColumnLeft
	mva #$00 BACKGRND
	plr 
	rti

CopyColumnRight 
	mwa #screen+40 Dest
	adw Dest Temp
	mwa #map Sour
	adw Sour Temp 

CopyColumn
	ldy #$00
	ldx #17
@
	lda (sour),y
	sta (dest),y
	inc sour+1
	inc sour+1			;2xINC MSB = +512
	adw dest #42 dest	;will be easier for 64 bytes wide screen 
	dex
	bne @-
	rts

CopyColumnLeft
	mwa #screen-1 Dest
	adw Dest Temp
	mwa #map-41 Sour
	adw Sour Temp 
	jmp CopyColumn

	
CalculateOffset 
	mwa Hscroll Temp
	clc
	ror Temp+1
	ror Temp
	clc
	ror Temp+1
	ror Temp
	lda Hscroll
	and	#$03
	eor #$FF
	sta H_x
	clc
	adc #128
	sta H_x_2
	rts

UpdateDisplaylist 
	mwa #Screen Sour
	adw Sour Temp
	mwa #line Dest

	ldx #17
@
	ldy #00		;LSB
	lda Sour
	sta (dest),y
	ldy #02		;MSB
	lda Sour+1
	sta (dest),y
	ldy #04		;X pos
	lda H_x
	sta (dest),y
	adw Sour #32	;dodaj 32 do adresu ekranu
	ldy #05		;LSB
	lda Sour
	sta (dest),y
	ldy #07		;MSB
	lda Sour+1	
	sta (dest),y
	ldy #09		;X pos
	lda H_x_2
	sta (dest),y
	adw Sour #10
	adw Dest #16
	dex
	bne @-
	rts

Joystick
	lda SWCHA
	and #$F0
	:4 lsr @
	eor #$0f
	cmp #$08	;right
	bne @+
	inw Hscroll	;incrase word
	rts
@	cmp #$04	;left
	bne @+
	dew Hscroll ;decrase word
@	rts

 

 

 

 

 

uridiumscroll.a78 UridiumScroll.rar

Edited by Eagle
  • Like 3
  • Thanks 1
Link to comment
Share on other sites

17 hours ago, mksmith said:

Thanks mate - that would be fantastic!

 

17 hours ago, Eagle said:

Yes. I will add vertical scroll later so you can have 4way scroll. 
No extra ram needed :) 

 

Honestly, all you need to do is with your background, change the heights of 2 DLL's (One on the top, the other on the bottom) in that when you want to go down one pixel, you add one to the top and subtract one from the bottom, and vice versa to go up (Shrink the top, enlarge the bottom) and when there is no more room, you reset it all and move all the background graphics pointers (Each row has it's own pointer) up one row, get rid of the top pointer and make a new one for the bottom.

 

  • Like 1
Link to comment
Share on other sites

????

OMG I just realized that in character mode, when scrolling the screen vertically, you need to change the value of the CHBASE register on the last line.

I was wondering when I was porting Robbo why I was having a problem with the last line.

 

  • Like 2
Link to comment
Share on other sites

VScroll in indirect mode

I will provide later full procedure for only Vertical Scroll in charmode

You have to update CHBASE on top of the screen 

;update just after VBlank
lda #>FNT
sta CHBASE
VScroll	.ds 2		;2bytes zero page	Vertical Scroll counter
ChbaseOffset .ds 1	;1byte zero page
FNT = $a000			;chars address

;DisplayListList
DLL
FirstLine	.byte $07,>FirstDlLine,<FirstDlLine
		.byte ..... next line
		.byte ..... next line
		.byte ..... next line
LastLine	.byte $87,>LastDlLine,<LastDlLine	;$8x Display List Interrupt

;Display List Interrupt
NMI
	pha
	lda ChbaseOffset
	sta WSYNC
	sta	CHBASE
	pla
	rti

UpdateDisplaListListVerticalScroll                                              
 	lda Vscroll		;LSB Vscroll
	and #$07
	ora #$80	;set bit 7 for Display List Interrupt (NMI)
	sta LastLine
	lda Vscroll		;LSB Vscroll
	and #$07
	eor #$07
	sta FirstLine
	clc                                              
	adc #>FNT		;calculate CHBASE for last line
  	sta ChbaseOffset
	rts

 

Edited by Eagle
  • Like 2
  • Thanks 1
Link to comment
Share on other sites

13 minutes ago, Eagle said:

@mksmith Commando vertical scroll with copy screen + source code (joystick up/down)

Next will be vertical wrapping scroll (soon)

 

Commando - emulator link

CommandoCopyScreen.a78 32.13 kB · 2 downloads CommandoVScrollCopy_SourceCode.zip 7.08 kB · 1 download

Jeez mate that's brilliant thank you! I now need to work out how I can fit this into the 7800basic structure - it's amazingly efficient and opens up plenty of doors for adding more scrolling games to the platform!

  • Like 5
Link to comment
Share on other sites

@mksmith wrapped version VScroll Up/Down. This is really fast! 

This version is drawing top and bottom row every VBlank to make program less complicated.

But really when you scrolling up you need update update only top row, when scrolling down update bottom row.

And only every 8th frame (if your zone is 8 height).

So if you are scrolling only in one direction (vertical shooter) you need update top row every 8 frame.

For 7 frames you need about 200 cycles and on 8th frame when you change zone about 1500-2000 cpu cycles.

You don't need any extra ram (640 bytes of RAM used in this example)

Source code included, feel free to ask :) 

 

Commando Wrapped VScroll - emulator link

CommandoWrapped.a78 CommandoWrappedVScroll_SourceCode.zip

  • Like 4
  • Thanks 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...