Hexapelago (working title)

developing/porting a new game or gaming framework? post in here!
SteveF
Posts: 1663
Joined: Fri Aug 28, 2015 9:34 pm
Contact:

Re: Hexapelago (working title)

Post by SteveF »

cola5pandex wrote: Wed Apr 24, 2024 11:45 pm I appreciate the feedback though. It's not like you can read my mind so from your point of view that's a perfectly reasonable suggestion and I'm not knocking it.
No problem, thanks for the explanation - it's interesting to hear how you see the game developing.
cola5pandex wrote: Thu Apr 25, 2024 5:54 pm I have a theory about borrowing from Peter to pay Paul. For example... How much RAM can I actually grab? How much RAM will it cost me to write routines that are already sitting in the ROM ready to do the job as long as I don't steal their workspace? How does that balance out? I don't really know so I'm playing it safe for now. That might change when things start to get tight though. That's when I might get ruthless. Does that make sense? Or am I playing it too safe?
I think if you're going to want to save and load files during gameplay, you really need to keep enough of the the OS+filing system code alive for that to work. Given the variety of filing systems around (there's floppy disc with DFS vs SD card alternatives like MMFS just for starters), writing your own code to do the job is asking for trouble.

I think you're on the right lines, do things by the book to start with and then if you start to run out of RAM or need more performance you can start considering the trade-offs of kicking the OS out, or half-way houses like (e.g.) lowering PAGE to &1100 and assuming that will work. Also, the more you can use the OS the more likely you are to end up with an Electron-compatible game - the OS hides quite a few hardware differences (e.g. in the keyboard handling) which you'd have to address separately for the Electron and BBC if you kick it out.
User avatar
Cybershark
Posts: 736
Joined: Wed Jun 14, 2006 11:16 pm
Contact:

Re: Hex Islands (working title)

Post by Cybershark »

cola5pandex wrote: Sat Apr 20, 2024 4:27 am It was a board game called Escape From Colditz that started it for me. Hexagons are certainly closer to circles for range of movement purposes. They are also just a bit more interesting to look at than squares for me.
Never played that one, but I have fond memories of Lost Valley of the Dinosaurs and its hexgrid :D

image_2024-04-25_234508874.png
User avatar
tricky
Posts: 7693
Joined: Tue Jun 21, 2011 9:25 am
Contact:

Re: Hexapelago (working title)

Post by tricky »

I love the look of the game, I really envy people who can do gfx, gameplay and code, still one out of three will have to do for me :(

How much memory can you get back? well pacman uses 32K of 32K - every byte - doesn't even enable interrupts ;)
Without looking, I guess my sound code doing sound+envelopes is 1/4 ot 1/2 the sound buffer and keyboard 1/4 the keyboard buffer.
Is it worth it? Almost certainly not unless you are looking for every last cycle, then the memory is also useful.
I've heard that BASIC workspace, can be stolen without getting into too much trouble :) but I don't know.
I've never met a simple BASIC + DFS/MMFS etc system that you couldn't push PAGE down to &1100 and still *LOAD (and maybe *SAVE).
I have no idea what Econet, a second filing system or any other ROMs might push page up to though.

I think I have "Lost Valley of the Dinosaurs" somewhere (amongst my 300+ board games) but have only played it once.
User avatar
cola5pandex
Posts: 55
Joined: Wed Apr 17, 2024 7:56 am
Location: West Midlands UK
Contact:

Re: Hexapelago (working title)

Post by cola5pandex »

SteveF wrote: Thu Apr 25, 2024 9:53 pm I think if you're going to want to save and load files during gameplay, you really need to keep enough of the the OS+filing system code alive for that to work. Given the variety of filing systems around (there's floppy disc with DFS vs SD card alternatives like MMFS just for starters), writing your own code to do the job is asking for trouble.
There is my lack of experience too. I don't want to get too technical before I'm even able to stand up straight for more than three seconds.
SteveF wrote: Thu Apr 25, 2024 9:53 pm I think you're on the right lines, do things by the book to start with and then if you start to run out of RAM or need more performance you can start considering the trade-offs of kicking the OS out, or half-way houses like (e.g.) lowering PAGE to &1100 and assuming that will work. Also, the more you can use the OS the more likely you are to end up with an Electron-compatible game - the OS hides quite a few hardware differences (e.g. in the keyboard handling) which you'd have to address separately for the Electron and BBC if you kick it out.
I'm glad you mentioned the Electron. I've already had to ditch my cursor in-joke because the Electron's cursor works differently. The only common ground appears to be VDU23,1 (to enable and disable). Changing the Cursor Display Mode (CRTC R10 bits 5-6) does have some effect on the Electron but it only works with certain modes and I think that's just an accident. All the more reason to K.I.S.S. and avoid anything too flashy (puns R us :lol:).

PAGE is another story. I'm coming to that.
User avatar
cola5pandex
Posts: 55
Joined: Wed Apr 17, 2024 7:56 am
Location: West Midlands UK
Contact:

Re: Hex Islands (working title)

Post by cola5pandex »

Cybershark wrote: Thu Apr 25, 2024 11:45 pm Never played that one, but I have fond memories of Lost Valley of the Dinosaurs and its hexgrid :D


image_2024-04-25_234508874.png
Looks interesting. Check out the board for Colditz though. The cells are actually circular, allowing hex, square and freeform sections of the grid. Super cool idea that I've never seen since.
User avatar
cola5pandex
Posts: 55
Joined: Wed Apr 17, 2024 7:56 am
Location: West Midlands UK
Contact:

Re: Hexapelago (working title)

Post by cola5pandex »

tricky wrote: Fri Apr 26, 2024 2:29 pm I love the look of the game, I really envy people who can do gfx, gameplay and code, still one out of three will have to do for me :(
Jack of all trades, master of none. :lol: Your coding is obviously far more advanced than mine so I guess it just depends how we invest our time. I was useless at graphics until I was forced to practice at work. I'm still not the best.
tricky wrote: Fri Apr 26, 2024 2:29 pm How much memory can you get back? well pacman uses 32K of 32K - every byte - doesn't even enable interrupts ;)
Without looking, I guess my sound code doing sound+envelopes is 1/4 ot 1/2 the sound buffer and keyboard 1/4 the keyboard buffer.
Is it worth it? Almost certainly not unless you are looking for every last cycle, then the memory is also useful.
I've heard that BASIC workspace, can be stolen without getting into too much trouble :) but I don't know.
I've never met a simple BASIC + DFS/MMFS etc system that you couldn't push PAGE down to &1100 and still *LOAD (and maybe *SAVE).
I have no idea what Econet, a second filing system or any other ROMs might push page up to though.
I did do a few experiments with various combinations of DFS, ADFS and ECONET to see how they affect PAGE. But did old school games make allowances for all of that? And is it unreasonable to say "Please disable A, B and C before launching this game"? This is something I've been pondering for a while but I never got round to seeking opinions.
tricky wrote: Fri Apr 26, 2024 2:29 pm I think I have "Lost Valley of the Dinosaurs" somewhere (amongst my 300+ board games) but have only played it once.
That sounds like one of my addictions. I have draws full of outfits that I've only worn once. Some are still in the wrappers after five years or more. :lol:
User avatar
cola5pandex
Posts: 55
Joined: Wed Apr 17, 2024 7:56 am
Location: West Midlands UK
Contact:

Re: Hexapelago (working title)

Post by cola5pandex »

Week Three

Added two more tables. One for fast conversion from cartesian coordinates to screen address. Another for fast conversion from cartesian coordinates to tile map index because (to save space) my tile map is a straight list with irregular row sizes rather than a sheared grid (ask Tricky :lol:).

Code: Select all

.tblColOffset ; 16 times table. Add tblRowStart to convert cartesian coords
EQUB $00,$10,$20,$30,$40,$50,$60,$70,$80,$90,$A0,$B0,$C0,$D0,$E0

.tblRowTotal ; tileMap index values for first column in each row of map
EQUB 161,152,142,131,119,106,92,77,63,50,38,27,17,8,0
Added a tile clearing mask (so I can redraw over existing tiles).

Code: Select all

.tileMask

EQUW %1111110000111111
EQUW %1111000000001111
EQUW %1100000000000011
EQUW %0000000000000000
EQUW %0000000000000000
EQUW %0000000000000000
EQUW %0000000000000000
EQUW %0000000000000000
EQUW %0000000000000000
EQUW %0000000000000000
EQUW %0000000000000000
EQUW %0000000000000000
EQUW %0000000000000000
EQUW %0000000000000000
EQUW %1100000000000011
EQUW %1111000000001111
Isolated the code that draws a single tile. Made it into a separate subroutine that accepts parameters to pass cartesian coordinates (X and Y) and a tile number (A). Added a few lines to incorporate the clearing mask.

Code: Select all

.redrawTile

; Store A as tile number
STA tileNumber

; Convert X and Y to screen address for drawing
TYA : ASL A : TAY : CLC
LDA tblRowStart,Y   : ADC tblColOffset,X : STA screenPointerL
LDA tblRowStart+1,Y : ADC #0             : STA screenPointerH

; Draw the first row of 16 pixels using bitwise OR to mask the corners of
; each tile because they overlap. No need to clear or store in the tilesheet
; because this row is always the same (3 green pixels).
LDA #%00000001 ; first byte in row
LDY #0 : ORA (screenPointerL),Y : STA (screenPointerL),Y
LDA #%11000000 ; second byte in row
LDY #8 : ORA (screenPointerL),Y : STA (screenPointerL),Y

; Increment screen address. No need to worry about carry or
; character block boundary as first row is always even
INC screenPointerL

; Initialise tile byte counter
LDA #32 : STA tileByteCount

; Get start address of tile sheet
LDA #LO(tileSheet) : STA tilePointerL
LDA #HI(tileSheet) : STA tilePointerH

; Load tile number and skip tile sheet offset arithmetic if this is 0
LDA tileNumber : BEQ nextTileRow

; Otherwise multiply by 32 (no. of bytes per tile) to give tile sheet offset
STA tileOffsetL : LDA #0 : STA tileOffsetH : LDX #5
.shiftTileOffset
ASL tileOffsetL : ROL tileOffsetH
DEX : BNE shiftTileOffset

; Add offset to start adddresss of tile sheet to get absolute address of tile
CLC
LDA tilePointerL : ADC tileOffsetL : STA tilePointerL
LDA tilePointerH : ADC tileOffsetH : STA tilePointerH

; Loop through each row of pixels (except the last)
.nextTileRow

; Draw current row of 16 pixels. Clear using bitwise AND and set using
; bitwise OR to mask the corners of each tile because they overlap.
DEC tileByteCount ; first byte in row
LDY tileByteCount : LDA tileMask,Y
LDY #0 : AND (screenPointerL),Y : STA (screenPointerL),Y
LDY tileByteCount : LDA (tilePointerL),Y
LDY #0 : ORA (screenPointerL),Y : STA (screenPointerL),Y
DEC tileByteCount ; second byte in row
LDY tileByteCount : LDA tileMask,Y
LDY #8 : AND (screenPointerL),Y : STA (screenPointerL),Y
LDY tileByteCount : LDA (tilePointerL),Y
LDY #8 : ORA (screenPointerL),Y : STA (screenPointerL),Y

; Skip screen address arithmetic if last row has been reached
LDA tileByteCount : BEQ endTile

; Increment low byte of screen address
INC screenPointerL

; Loop back to draw next row of pixels if new screen address is not
; a multiple of 8 (which means we've crossed a character block
; boundary and may also need to carry)
LDA #%111 : AND screenPointerL : BNE nextTileRow

; Increment high byte of screen address if low byte is now zero
CMP screenPointerL : BNE screenPointerNoCarry
INC screenPointerH
.screenPointerNoCarry

; Add 312 to screen pointer because we have crossed a character
; block boundary and want to move down not right
CLC
LDA #LO(312) : ADC screenPointerL : STA screenPointerL
LDA #HI(312) : ADC screenPointerH : STA screenPointerH

; Loop back to draw next row of pixels
JMP nextTileRow

.endTile

; The last row of pixels now draws itself because this row is always blank
; (1 black pixel) and so we can just end this subroutine here
RTS
Modified drawMap routine to use redrawTile. Slightly slower because of clearing mask (not required on a blank screen) and coordinate conversion but still fast enough. Also added a couple of "wait VSYNC" lines to stop tearing as the colours change. This is now simpler/easier to read.

Code: Select all

.drawMap

; Wait for vertical sync to avoid tearing
LDA #OSBYTE_WAIT_VSYNC : JSR OSBYTE

; Set foreground colour to black so we can't see
LDX #LO(lightsOff) : LDY #HI(lightsOff) : LDA #$C : JSR OSWORD

; Initialise row counter
LDA #14 : STA mapY

; Loop through each row of the map
.nextMapRow

; Initialise column counter
LDY mapY: LDX tblColCount,Y : DEX : STX mapX

; Loop through each column in the row
.nextMapCol

; Convert cartesian coordinates to tile map index
LDY mapY : CLC : LDA tblRowTotal,Y : ADC mapX : TAY

; Load parameters into registers
LDA tileMap,Y : LDX mapX : LDY mapY

; Draw Tile
JSR redrawTile

; Adjust loop counters and branch appropriately
DEC mapX : BPL nextMapCol
DEC mapY : BPL nextMapRow

; Wait for vertical sync to avoid tearing
LDA #OSBYTE_WAIT_VSYNC : JSR OSBYTE

; Reset foreground colour to green to reveal map
LDX #LO(lightsOn) : LDY #HI(lightsOn) : LDA #$C : JSR OSWORD

; Return
RTS
Modified my main loop to allow control of a single mob/sprite. As things stand this hides the underlying tile. Tried masking but in monochrome this doesn't work well. I have a different idea but I'll come back to that.

The other obvious imperfection is that as things stand you can only move in four directions along the cartesian axes. This is where things get interesting because I'm trying to avoid a six key system (which wouldn't work well with gamepads etc). All will be revealed. Hopefully quite soon now that I have a way to indicate mob/sprite positions.

Also added the option to press spacebar. This just forces a full redraw for testing purposes. Basically... It's just temporary.

There is also some code to stop the mob going off the edge but that is uncommented because that too is temporary.

Code: Select all

ORG $3000
.start

; Select screen mode 4
LDA #22 : JSR OSWRCH : LDA #4 : JSR OSWRCH

; Hide cursor
LDA #23 : JSR OSWRCH : LDA #1 : JSR OSWRCH : LDA #0 : JSR OSWRCH
LDX #7 : .zeros1 : LDA #0 : JSR OSWRCH : DEX : BNE zeros1

; Disable cursor editing
LDX #CURSOR_EDITING_OFF : LDA #OSBYTE_SET_CURSOR_EDITING : JSR OSBYTE

; Disable keyboard auto-repeat
LDX #0 : LDA #OSBYTE_SET_KEYBOARD_DELAY : JSR OSBYTE

; Draw map
JSR drawMap

; Draw mob
LDA mobImage : LDX mobX : LDY mobY
JSR redrawTile

.keyboardLoop

; Read keyboard with (almost) zero delay using OSBYTE 129 (aka INKEY)
LDX #0 : LDY #0 : LDA #129 : JSR OSBYTE

; If nothing pressed then keep listening
CPY #255 : BEQ keyboardLoop

.checkEscape ; If Escape pressed then GTFOH
CPY #27 : BNE checkLeft
JMP escape

.checkLeft ; If left arrow pressed then branch accordingly
CPX #136 : BNE checkRight
JMP keyLeft

.checkRight ; If right arrow pressed then branch accordingly
CPX #137 : BNE checkDown
JMP keyRight

.checkDown ; If down arrow pressed then branch accordingly
CPX #138 : BNE checkUp
JMP keyDown

.checkUp ; If up arrow pressed then branch accordingly
CPX #139 : BNE checkSpace
JMP keyUp

.checkSpace ; If spacebar pressed then branch accordingly
CPX #32 : BNE keyboardLoop
JMP keySpace

.keyLeft

LDA mobX : BNE safeLeft
.unsafeLeft
JMP keyboardLoop
.safeLeft
DEC mobX : JMP moved

.keyRight

LDY mobY
LDX mobX : INX
TXA : CMP tblColCount,Y : BCC safeRight
.unsafeRight
JMP keyboardLoop
.safeRight
INC mobX : JMP moved

.keyDown

LDY mobY : BEQ unsafeDown
CPY #8 : BCS safeDown
LDX mobX : INX
TXA : CMP tblColCount,Y : BCC safeDown
.unsafeDown
JMP keyboardLoop
.safeDown
DEC mobY : JMP moved

.keyUp

LDY mobY : CPY #14 : BEQ unsafeUp
CPY #7 : BCC safeUp
LDX mobX : INX
TXA : CMP tblColCount,Y : BCC safeUp
.unsafeUp
JMP keyboardLoop
.safeUp
INC mobY : JMP moved

.moved

; Convert cartesian coordinates to tile map index
LDY mobYold : CLC : LDA tblRowTotal,Y : ADC mobXold : TAY

; Load tile draw parameters for old position into registers
LDA tileMap,Y : LDX mobXold : LDY mobYold

; Draw map tile at old position
JSR redrawTile

; Load tile draw parameters for new position into registers
LDA mobImage : LDX mobX : LDY mobY

; Update old position
STX mobXold : STY mobYold

; Draw mob tile at new position
JSR redrawTile

JMP keyboardLoop

.keySpace

; Redraw all
JSR drawMap
LDA mobImage : LDX mobX : LDY mobY
JSR redrawTile

JMP keyboardLoop

.escape

; Acknowledge Escape condition
LDA #126 : JSR OSBYTE

; Enable cursor editing
LDX #CURSOR_EDITING_ON : LDA #OSBYTE_SET_CURSOR_EDITING : JSR OSBYTE

; Reset keyboard auto-repeat to defaults
LDX #0 : LDA #OSBYTE_SET_KEYBOARD_REPEAT : JSR OSBYTE

; Show cursor
LDA #23 : JSR OSWRCH : LDA #1 : JSR OSWRCH : LDA #1 : JSR OSWRCH
LDX #7 : .zeros2 : LDA #0 : JSR OSWRCH : DEX : BNE zeros2

; Back to BASIC (or whatever)
RTS
No screenshot because it doesn't look much different but here's the ssd for anyone who wants to see the effect of the changes...
hex.ssd
(2 KiB) Downloaded 1 time
User avatar
ChrisB
Posts: 547
Joined: Wed Oct 05, 2011 10:37 pm
Location: Surrey
Contact:

Re: Hexapelago (working title)

Post by ChrisB »

cola5pandex wrote: Wed May 01, 2024 6:18 pm I did do a few experiments with various combinations of DFS, ADFS and ECONET to see how they affect PAGE. But did old school games make allowances for all of that? And is it unreasonable to say "Please disable A, B and C before launching this game"? This is something I've been pondering for a while but I never got round to seeking opinions.
Most games - probably because of the need to be sold on cassette - didn't use any kind of multi load. In that case you can load over screen memory then select the Tape file system then move yourself down into the areas you want to use. Exceptions like Elite targeted DFS specifically (and don't work on ADFS, NFS etc.)

So - "Legally" if you don't use a Language you get &00 to &7f in zero page. &400 to &7ff the language workspace and then from page (&1900 with DFS) to the bottom of screen RAM - &5800. That gives 17152 bytes to play with + 128 bytes of zero page.
Standard DFS will cope with whole file loads if you trample over its RAM from &1100 (or &1200 with econet) - which gives another 2048 bytes.
If you only have 4 envelopes and don't use user defined characters or the soft keys you can get away with &900 - &CFF - Another 1024 bytes with &900 to &AFF being safer (&B00 and &C00 are used by Econet on the Master) So that gives 20224 bytes of memory + 128 of zero page. This still leaves the OS, VDU and Sound Drivers and whole file loads operational.

If you need a bit more it is unlikely that you will use 256 bytes of stack so - provided you're careful - some of page &01 can be used. Don't forget that you're unlikely to be returning back to the OS so you can reset the stack pointer to the top of the stack page (or wherever you like). There are some other areas of Zero page that you can stray into - provided you don't use the associated functionality.

All this assumes (a dangerous word) a standard configuration and any machine that varies from this will have varying levels of problems.
Castle Defender, Untitled Dungeon Game, Night Ninja, Wordle, Waffle, Acorn Island, Beebchase, Ghostbusters
SteveF
Posts: 1663
Joined: Fri Aug 28, 2015 9:34 pm
Contact:

Re: Hexapelago (working title)

Post by SteveF »

cola5pandex wrote: Wed May 01, 2024 6:18 pm I did do a few experiments with various combinations of DFS, ADFS and ECONET to see how they affect PAGE. But did old school games make allowances for all of that? And is it unreasonable to say "Please disable A, B and C before launching this game"? This is something I've been pondering for a while but I never got round to seeking opinions.
No, it's not unreasonable - it's just that it's nice if your game can work on as many systems as possible without having to compromise what you want it to be like. Users can turn off utility ROMs and multiple filing systems - albeit it's a bit fiddly - to get PAGE down, but they need at least one filing system and they will have their own preference for that, which creates a PAGE "floor" at which "just disable stuff" stops being an easy option.

I suspect most classic games which needed to use the disc after loading would assume PAGE<=&1900 and probably tended to assume the PAGE=&1100 trick would work. In some ways things are even easier now, because I suspect most retro-enthusiasts will have a filing system with PAGE=&E00 available (even if it isn't their default). That said, things are in some ways harder nowadays too, because with Econet's new wave of popularity among hobbyists, it would be nice if your game could run from Econet and it sounds like that typically has PAGE>&1900 on Electron/B/B+, albeit not by much.

I see you're using "org &3000" in the code snippets you're posting. My suggestion would be that you keep memory limits in the back of your mind but just keep developing your game and lowering that &3000 down as and when you have to. If you build something you consider finished and you haven't had to drop that down below (say) &1E00 you're probably golden, and if that isn't enough space you can start to consider the trade-offs.

Edit: I think the important thing is to build the game you want, even if turns out (for example) it only runs on a Master or equivalent spec because it's so big. Trying to write something that will run on smaller systems might well be part of the challenge/appeal for you, but if it's not then don't get too hung up on it. I find the squashing/multi-system aspect interesting, which is why I am writing posts like this, but I'd hate to be responsible for putting you off in any way. And within reason if you write something that's just slightly too big for a standard 32K machine, I'm sure you and the community here will be able to come up with some tricks to make it fit.
User avatar
cola5pandex
Posts: 55
Joined: Wed Apr 17, 2024 7:56 am
Location: West Midlands UK
Contact:

Re: Hexapelago (working title)

Post by cola5pandex »

Thanks guys. I will get back to you about all of that. Just wanted to give a quick update on the hidden tile problem for now.

Activate cloaking device. Deactivate cloaking device. And so on. :lol:

Here's the gist of it...

Code: Select all

...

LDX #LO(writeClock) : LDY #HI(writeClock)
LDA #OSWORD_WRITE_SYSTEM_CLOCK : JSR OSWORD

.keyboardLoop

LDX #LO(readClock) : LDY #HI(readClock)
LDA #OSWORD_READ_SYSTEM_CLOCK : JSR OSWORD

LDA readClock : CMP #49 : BCC readKeys

LDX #LO(writeClock) : LDY #HI(writeClock)
LDA #OSWORD_WRITE_SYSTEM_CLOCK : JSR OSWORD

LDA blinkPhase : EOR #%11111111 : STA blinkPhase : BNE blinkOn

.blinkOff
LDY mobY : CLC : LDA tblRowTotal,Y : ADC mobX : TAY
LDA tileMap,Y : LDX mobX : LDY mobY
JSR redrawTile
JMP readKeys

.blinkOn
LDA mobImage : LDX mobX : LDY mobY
JSR redrawTile

.readKeys

...
And here's the ssd...
hex.ssd
(2 KiB) Downloaded 7 times
SteveF
Posts: 1663
Joined: Fri Aug 28, 2015 9:34 pm
Contact:

Re: Hexapelago (working title)

Post by SteveF »

That looks good!
Post Reply

Return to “new projects in development: games”