Good documented source code examples on viewing selected part of bigger game map

Here you can ask questions or provide insights about how to use efficiently 6502 assembly code on the Oric.
Post Reply
xahmol
Pilot Officer
Posts: 114
Joined: Sun Jun 28, 2020 7:32 pm
Location: Utrecht, The Netherlands
Contact:

Good documented source code examples on viewing selected part of bigger game map

Post by xahmol »

Started a new project converting an old board game program I wrote decades ago on the Commodore 128 and quickly decided that to have any meaningful representation of the game board on screen is not possible viewing the whole board at the same time using only 25*40 characters.
My original game used 25*80, and also that one looking back had 'meh' overview of the board.

So I really want to use a much larger virtual screen of which only a selected viewport at a time is copied to screen memory.

I will use text mode only. Also do not need smooth scrolling as I see no way doable for me to do so without getting into a color attribute nightmare, and I do not want to loose color also.
Present game board layout uses 9 rows times 9 colums of board tiles of 10 characters width and 8 characters height, including 1 character in both height and weight being black and blank. Already have a raw binary game map for the board game design that copes with having the space for color change attributes (on each line every tile again starts with set ink set paper attribute) while still giving room for text elements I need.
Virtual game map resulting is 89 characters in width (9 times 10 minus the last black character I do not need) and 71 characters height (9 times 8 minus again the last black line not needed).

So what I now basically need is code top copy say a 20 high, 40 width character viewport from the bigger virtual screen in memory to the visible TEXT screen memory. BASIC is way to slow to do this,
As I copy only 40 characters of 89 width every time I can not use a normal memcopy, but need a strided memcopy of sorts.

I also know that many games use such a viewport from a larger game map (for example the Treasure game I see elsewhere on the forum, or the Gulp game from Twilighte), so there must be examples around.
But maybe my searching skills, did not find an example yet providing well documented assembly source.

Any suggestions for code examples to get inspiration from or reuse with credit?
And yes, I can of course use tools to disassemble existing games that use a similar mechanism, but as I am a complete starter in 6502 assembly languague, a documented source would be much more helpful to actually understand what the code does.

Also other tips are appreciated, like if 89 times 71 characters is a convenient dimension, or if it would be much more practical to have some characters more to make it easier to handle by code. Preferably not less as that would take major redesign of the board again.

Thanks for any input!

User avatar
Dbug
Site Admin
Posts: 3456
Joined: Fri Jan 06, 2006 10:00 pm
Location: Oslo, Norway
Contact:

Re: Good documented source code examples on viewing selected part of bigger game map

Post by Dbug »

So basically you have a map which is 89x71 (6319 bytes) and you want to copy some arbitrary rectangle part of it on a 40x25 screen, correct?

xahmol
Pilot Officer
Posts: 114
Joined: Sun Jun 28, 2020 7:32 pm
Location: Utrecht, The Netherlands
Contact:

Re: Good documented source code examples on viewing selected part of bigger game map

Post by xahmol »

Dbug wrote:
Thu Nov 12, 2020 4:00 pm
So basically you have a map which is 89x71 (6319 bytes) and you want to copy some arbitrary rectangle part of it on a 40x25 screen, correct?
Correct.

User avatar
Dbug
Site Admin
Posts: 3456
Joined: Fri Jan 06, 2006 10:00 pm
Location: Oslo, Norway
Contact:

Re: Good documented source code examples on viewing selected part of bigger game map

Post by Dbug »

I guess the implementation depends of the performance you want, the problem on the 6502 is the very limited index registers and addressing modes in general. I assume that you want your map to be in a standard layout, not convoluted, even if that would help with the performance?

A possibility would be to do a variant of the fast copy:

Code: Select all

 ldy starting_position_in_the_map_plus_25
 ldx #40-1
loop
 lda map+89*0,y
 sta screen+40*0,x
 lda map+89*1,y
 sta screen+40*1,x
 (...)
 lda map+89*24,y
 sta screen+40*24,x
 dey
 dex
 bpl loop
the problem of course is that this only works to copy a 89x25 buffer to the screen, so to support the vertical offset, it's necessary to patch all the 25 lda instructions to compensate for the difference.

Else the alternative, as usual, is to use indirect addressing

Code: Select all

  lda #<map
  sta ptr_src+0
  lda #>map
  sta ptr_src+1
  ; Add X/Y computations for the start of the map

  lda #<screen
  sta ptr_dst+0
  lda #>screen
  sta ptr_dst+1

 ldy #25
loop_y
 ldx #40
loop_x
 lda (ptr_src),y
 sta (ptr_dst),y
 bne loop_x
 
  ; add 89 to src
 ; add 40 to dst
 bne loop_y
The bottom line is, on the Oric - and 6502 in general -, there's is rarely an optimal generic code you can just reuse from somewhere else, pretty much all the code is adapted variants of patterns, but the routines can rarely be reused as such.

xahmol
Pilot Officer
Posts: 114
Joined: Sun Jun 28, 2020 7:32 pm
Location: Utrecht, The Netherlands
Contact:

Re: Good documented source code examples on viewing selected part of bigger game map

Post by xahmol »

Thanks, that already helps.... also confirms that what I could come up with is not so crazy after all...

Was hoping for some hyper efficient standard routine. But your explanation makes sense.

User avatar
ibisum
Wing Commander
Posts: 1355
Joined: Fri Apr 03, 2009 8:56 am
Location: Vienna, Austria
Contact:

Re: Good documented source code examples on viewing selected part of bigger game map

Post by ibisum »

> it's necessary to patch all the 25 lda instructions to compensate for the difference.

With self-modifying code, right? Or .. what about a STA generator?

User avatar
Dbug
Site Admin
Posts: 3456
Joined: Fri Jan 06, 2006 10:00 pm
Location: Oslo, Norway
Contact:

Re: Good documented source code examples on viewing selected part of bigger game map

Post by Dbug »

ibisum wrote:
Fri Nov 13, 2020 3:55 pm
> it's necessary to patch all the 25 lda instructions to compensate for the difference.

With self-modifying code, right? Or .. what about a STA generator?
Well, it has to be done at run time (at least if you don't want to have 50 different variants of the copy code), so yeah SMC: pointer on the code, and change the addresses in the code.

xahmol
Pilot Officer
Posts: 114
Joined: Sun Jun 28, 2020 7:32 pm
Location: Utrecht, The Netherlands
Contact:

Re: Good documented source code examples on viewing selected part of bigger game map

Post by xahmol »

Thanks all.

Now have this code:

Code: Select all

	.zero

	*=$50
_GameBoardZP		.dsb 2		    ; Gameboard address zero page
_ScreenZP	    	.dsb 2		    ; Screen address zero page

	.text

    *=$6500 

#define BoarddataStart  $9800       ; Game board data base address
#define Screenstart     $bcc0       ; Screen position X=0 and Y=7

StartCopygameboard
; Obtain game board copy adress via Y and X registers
    clc                             ; Clear carry
    lda YpointersLowbyte,y          ; Obtain low byte of vertical index
    adc Xpointers,x                 ; Add x index
    sta _GameBoardZP                ; Store low byte in zero page
    lda YpointersHighbyte,y         ; Obtain high byte of vertical index
    adc #0                          ; Add zero to add carry if needed
    sta _GameBoardZP+1              ; Store high byte in zero page

; Load screen base address at X=1 and Y=7
    lda #<Screenstart               ; Load low byte of screen base address
    sta _ScreenZP                   ; Store low byte in zero page
    lda #>Screenstart               ; Load high byte of screen base address
    sta _ScreenZP+1                 ; Store low byte in zero page

; Main routine
    ldx #20                         ; Counter for 20 lines
loop_x
    ldy #0                          ; Reset at char 0 of line
    lda #0                          ; Value for black ink
    sta (_ScreenZP),y               ; Store black ink at start of each line

; Loop for copying a single line
loop_y
    lda (_GameBoardZP),y            ; Load char at x index
    iny                             ; Increase y
    sta (_ScreenZP),y               ; Store char at x index
    cpy #39                         ; Did we reach char 39?
    bne loop_y                      ; Continue loop if not equal
 
 ; Add 89 to source address pointer
    clc                             ; Clear carry
    lda _GameBoardZP                ; Load low byte
    adc #89                         ; Add 89
    sta _GameBoardZP                ; Store updated address
    lda _GameBoardZP+1              ; Load high byte
    adc #0                          ; Add zero to add carry if needed
    sta _GameBoardZP+1              ; Store high byte

 ; Add 40 to screen address pointer
    clc                             ; Clear carry
    lda _ScreenZP                   ; Load low byte
    adc #40                         ; Add 40
    sta _ScreenZP                   ; Store updated address
    lda _ScreenZP+1                 ; Load high byte
    adc #0                          ; Add zero to add carry if needed
    sta _ScreenZP+1                 ; Store high byte

; Next line
    dex                             ; Decrease x
    bne loop_x                      ; Continue loop if not zero                 

    rts                             ; Finished and return

; Pointers for the start adresses of the half tile lines

YpointersHighbyte
    .byt >BoarddataStart
    .byt >BoarddataStart+356
    .byt >BoarddataStart+712
    .byt >BoarddataStart+1068
    .byt >BoarddataStart+1424
    .byt >BoarddataStart+1780
    .byt >BoarddataStart+2136
    .byt >BoarddataStart+2492
    .byt >BoarddataStart+2848
    .byt >BoarddataStart+3204
    .byt >BoarddataStart+3560
    .byt >BoarddataStart+3916
    .byt >BoarddataStart+4272
    .byt >BoarddataStart+4539

YpointersLowbyte
    .byt <BoarddataStart
    .byt <BoarddataStart+356
    .byt <BoarddataStart+712
    .byt <BoarddataStart+1068
    .byt <BoarddataStart+1424
    .byt <BoarddataStart+1780
    .byt <BoarddataStart+2136
    .byt <BoarddataStart+2492
    .byt <BoarddataStart+2848
    .byt <BoarddataStart+3204
    .byt <BoarddataStart+3560
    .byt <BoarddataStart+3916
    .byt <BoarddataStart+4272
    .byt <BoarddataStart+4539

; Horizontal offsett per tile

Xpointers
    .byt 0
    .byt 10
    .byt 20
    .byt 30
    .byt 40
    .byt 50
    .byt 60
It takes the X and Y registers as input for the vertical and horizontal tile number. Tiles are 8 high, 10 width, but divided the tiles horizontally in two.

Routine is called from basic by the SEDORIC command USER, which enables to call machine code while passing register values.

I have a simple BASIC program now testing the code and game board data by scrolling with the cursor keys:

Code: Select all

#labels
#optimize

Start:+1:0
    X=5: Y=13
    REPEAT
        USER 1, DEF #6500
        USER 1, X X, Y Y
        GET K$
        IF K$=CHR$(8) AND X>0 THEN X=X-1
        IF K$=CHR$(9) AND X<5 THEN X=X+1
        IF K$=CHR$(11) AND Y>0 THEN Y=Y-1
        IF K$=CHR$(10) AND Y<13 THEN Y=Y+1
    UNTIL K$=CHR$(13)
    INK 7
    END
Works great! So happy with 'My first ORIC assembler code'!

Probably it can be done much more efficiently and faster, but it already works almost instantly so quick enough.

User avatar
Dbug
Site Admin
Posts: 3456
Joined: Fri Jan 06, 2006 10:00 pm
Location: Oslo, Norway
Contact:

Re: Good documented source code examples on viewing selected part of bigger game map

Post by Dbug »

Cool, glad that it works, congratz for your first Oric assembler code :)
(I'm also happy you play with my extensions to BAS2TAP, it was done for my own needs and I'm not sure anyone else tried them)

Performance wise, I guess the only simple improvement would be to revert the Y copy and decrement and test instead of comparing to #39.
Other optimizations would be the speed up of the adc #40 and adc #89, but that would only be moderately faster since the core of the cost is in the inner loop.

What is the reason for setting black ink at the start of each line?

xahmol
Pilot Officer
Posts: 114
Joined: Sun Jun 28, 2020 7:32 pm
Location: Utrecht, The Netherlands
Contact:

Re: Good documented source code examples on viewing selected part of bigger game map

Post by xahmol »

Hi, tried decreasing instead of increasing first, for some reason with that the colour attributes did not work correctly. Do not understand why as it should work, maybe something in the board data that I have wrong or something else I missed in the code in the order of decreasing y and the store instructions, but with increasing it now works.
Might figure out later why decreasing does not work, but for now I settle with what does work 😉

On the black ink, might delete that later, but as I start to plot on column 1 instead of 0 the black ink at each line start is not in my board game data. Did so to avoid the need of setting the black ink for every tile again (and loosing another character) as otherwise scrolling would not work as the black ink attribute disappears.
In final stage I might just once set the background correctly first.

And the BAS2TAP extensions are excellent, it gives really maintainable and clean code on the editor side. Linenumbers in VSCode are a big nuisance, so glad to get rid of it. So thanks!
Last edited by xahmol on Sat Nov 14, 2020 8:55 am, edited 1 time in total.

User avatar
jbperin
Flying Officer
Posts: 164
Joined: Wed Nov 06, 2019 11:00 am
Location: Valence, France

Re: Good documented source code examples on viewing selected part of bigger game map

Post by jbperin »

xahmol wrote:
Sat Nov 14, 2020 1:33 am

Works great! So happy with 'My first ORIC assembler code'!
Congratulations ! I've been developing on Oric for one year now and I never managed to mix assembly and basic.

Your progress are surprising .. and interesting.

How many other C128 games have you produced ?

xahmol
Pilot Officer
Posts: 114
Joined: Sun Jun 28, 2020 7:32 pm
Location: Utrecht, The Netherlands
Contact:

Re: Good documented source code examples on viewing selected part of bigger game map

Post by xahmol »

jbperin wrote:
Sat Nov 14, 2020 8:51 am
How many other C128 games have you produced ?
Not that many more that are originally written by me and are worthwhile to port.

Have many that are blatant rip-offs of type-ins for ZX Spectrum and C64 that I redid on the 128. But as copyright was a somewhat unknown term to me at that age :lol: I of course did not include any credit of the original author in the code.
And do not want to pose a program as my own without at least crediting the original author.
(I have some feeling that I am not the only one that grew up with 8 bits that literally did not own any software for decades I actually paid for apart from the paid type in magazines. Basically started to pay for software when a) I had the income at which I could no longer justify to myself not paying and b) basically every crack I download made the virusscanner go crazy).

Others are just not interesting apart for sentimental reasons for myselves or were intended for my school work, like plotting Keynesian economic graphs and a demo of an animated dancing sprite with a characteriture of my math teacher at that time.....

So maybe one or two that are still worth converting that I can at least mostly call my own code. Or do know the original author to do proper credits.

Did one game that I really did from scratch (not an existing board game), and honestly, if I play it now it is of course a warm sentimental feeling, but also have to say the game is not that good and rather boring. So might port that at some time but that will be a bigger project as I only want to release it publicly after improving the actual game a lot.

Basically I could code and improve upon game ideas of others, but never was very good at original game ideas. There is a reason I made a career in IT auditing, and not in creating 😉
Nice job by the way in a big financial institution, as in one audit you have to delve into IBM zSeries mainframe security, sysprogramming and COBOL, where in another one you are assessing Amazon Web Services Infra as a Code and Kunernetes security, again another learning Python for data science for fraud analysis to also penetration testing, red teaming and ethical hacking.
Like to hobby both in the 8 bit old stuff as well as experimenting with my website with serverless Amazon Web Services components and a website build in the React framework.
Downside of course that if you want to try all, you are a master at nothing..... so happy to continue to learn from the experts in all these fields.

xahmol
Pilot Officer
Posts: 114
Joined: Sun Jun 28, 2020 7:32 pm
Location: Utrecht, The Netherlands
Contact:

Re: Good documented source code examples on viewing selected part of bigger game map

Post by xahmol »

Small update: got sidetracked by doing another project first, which is a project on the Commodore 128 that I want to do in C with CC65.

Will come back to this project, just will take longer 😉 And wanted to learn C in CC65 anyway also for Oric Atmos projects.

(If anyone is interested: plan is to build my own little boot program for the C128 with a menu with several boot options and the option to start a file browser. Especially for the file browser part, BASIC is too slow and my assembler skills way to limited. Found a nice C source that I think I am able to work with as base, that is why I want to do it in C.
And want to build my own program as there are surprisingly not that many existing options for the C128 as there are a lot less C128s out there, and the people that had a C128 almost all only used the C64 mode of it. And the C64 can not boot from a disk, the C128 can. So there is a plethora of file browsers, one of which I will lend large part of the source code from, but not integrated in a boot menu. And also not optimised for 80 column screen and modern SD storage devices).

Post Reply