Shawn Jefferson Posted March 1, 2011 Share Posted March 1, 2011 The project I've been working on lately: http://www.atariage.com/forums/blog/18-shawn-jeffersons-blog/ Quote Link to comment Share on other sites More sharing options...
danwinslow Posted March 1, 2011 Share Posted March 1, 2011 Cool! I liked that game a lot myself. Shawn I'd be interested to know how code gets run from the flashcart...some kind of bank switching? Quote Link to comment Share on other sites More sharing options...
ilmenit Posted March 1, 2011 Share Posted March 1, 2011 Btw, a little demo of one of my unfinished projects. WSAD - control. i - inventory g - get item r - rest roguelike.xex Quote Link to comment Share on other sites More sharing options...
Shawn Jefferson Posted March 2, 2011 Author Share Posted March 2, 2011 Cool! I liked that game a lot myself. Shawn I'd be interested to know how code gets run from the flashcart...some kind of bank switching? A lot of bank switching. Code is switched in and out of cartridge banks (library code, some minimal set of Moria code, and banking code is in low ram). VBXE RAM is banked in at $4000-BFFF as well. I'm using about 4 different VBXE banks to store data/structures. The "cave" structure itself is 44x132x4 (24k!) Quote Link to comment Share on other sites More sharing options...
Shawn Jefferson Posted March 2, 2011 Author Share Posted March 2, 2011 (edited) Dan (or anyone who cares), here's the linker config file from the Atarimax 1Mbit version (I've since moved to the 8Mbit cart, very similiar config file though), and the custom crt0.s file to make cc65 programs run from a cart. You just manage where your code and data goes with a lot of #pragma code-name, #pragma rodata-name, etc... One tricky thing to keep in mind is that it seems you can only have one rodata segment per source file, I guess due to the optimization of RO strings that cc65 does. FEATURES { STARTADDRESS: default = $0400; } SYMBOLS { #__STACKSIZE__ = $400; # 1K stack #__RESERVED_MEMORY__: value = $1, weak = yes; __STACKSIZE__: type = weak, value $0400; # 1K stack __RESERVED_MEMORY__: type = weak, value = $0000; } MEMORY { ZP: start = $0082, size = $007E, type = rw, define = yes; LIBRAM: start = %S, size = $3800, define = yes; STACK: start = $3C00, size = __STACKSIZE__, define = yes; #ENGRAM: start = $3000, size = $5010, define = yes; MONSTERS: start = $4000, size = $6000, type = rw, define = yes; OBJECTS: start = $4000, size = $6000, type = rw, define = yes; SPELLS: start = $4000, size = $6000, type = rw, define = yes; MAGIC: start = $4000, size = $6000, type = rw, define = yes; CAVE: start = $4000, size = $6000, type = rw, define = yes; GEN: start = $4000, size = $6000, type = rw, define = yes; CART0: start = $A000, size = $1FFA, type = ro, fill = yes, fillval = $00, file = %O; VECTORS: start = $BFFA, size = 6, type = ro, file = %O; CART1: start = $A000, size = $4000, type = ro, fill = yes, fillval = $11, file = %O; #CART2: start = $A000, size = $2000, type = ro, fill = yes, fillval = $22, file = %O; CART3: start = $A000, size = $6000, type = ro, fill = yes, fillval = $33, file = %O; #CART4: start = $A000, size = $2000, type = ro, fill = yes, fillval = $44, file = %O; #CART5: start = $A000, size = $2000, type = ro, fill = yes, fillval = $55, file = %O; CART6: start = $A000, size = $6000, type = ro, fill = yes, fillval = $66, file = %O; #CART7: start = $A000, size = $2000, type = ro, fill = yes, fillval = $77, file = %O; #CART8: start = $A000, size = $2000, type = ro, fill = yes, fillval = $88, file = %O; CART9: start = $A000, size = $2000, type = ro, fill = yes, fillval = $99, file = %O; CARTA: start = $A000, size = $2000, type = ro, fill = yes, fillval = $AA, file = %O; CARTB: start = $A000, size = $2000, type = ro, fill = yes, fillval = $BB, file = %O; CARTC: start = $A000, size = $2000, type = ro, fill = yes, fillval = $CC, file = %O; CARTD: start = $A000, size = $2000, type = ro, fill = yes, fillval = $DD, file = %O; CARTE: start = $A000, size = $2000, type = ro, fill = yes, fillval = $EE, file = %O; CARTF: start = $A000, size = $2000, type = ro, fill = yes, fillval = $FF, file = %O; } SEGMENTS { INIT: load = CART0, type = ro, define = yes, optional = yes; STARTUP: load = CART0, type = ro, define = yes; LOWCODE: load = CART0, type = ro, define = yes, optional = yes; CODE: load = CART0, run = LIBRAM, type = ro, define = yes; RODATA: load = CART0, run = LIBRAM, type = ro, define = yes; DATA: load = CART0, run = LIBRAM, type = rw, define = yes; BSS: load = LIBRAM, type = bss, define = yes; HEAP: load = LIBRAM, type = bss, optional = yes; # must sit just below stack CAVERAM: load = CAVE, type = bss, define = yes; # Main CAVE structures GENRAM: load = GEN, type = bss, define = yes; # structures used in Generate.c functions BANK0: load = CART0, run = CART0, type = ro, define = yes; # BANK0 $00000 Setup Code, library code MONSTERBANK: load = CART1, run = MONSTERS, type = ro, define = yes; # BANK1-2 $02000 Monster list/structures OBJECTBANK: load = CART3, run = OBJECTS, type = ro, define = yes; # BANK3-5 $06000 Object list/structures SPELLBANK: load = CART6, run = SPELLS, type = ro, define = yes; # BANK6-8 $0C000 Spell data/structures, player data/structures MAGICBANK: load = CART9, run = MAGIC, type = ro, define = yes; # BANK9 $10000 Potions/Wands/Staff stuff INITBANK: load = CARTA, run = CARTA, type = ro, define = yes; # BANKA $12000 Init code/rodata CREATE1BANK: load = CARTB, run = CARTB, type = ro, define = yes; # BANKB $14000 Create1 code/rodata CREATE2BANK: load = CARTC, run = CARTC, type = ro, define = yes; # BANKC $16000 Create 2 code/rodata (modify_stats, calc_stuff) PRINTBANK: load = CARTD, run = CARTD, type = ro, define = yes; # BANKD $18000 Print (VBXE/IO bank. put_misc3 character print) CHPRINT1BANK:load = CARTE, run = CARTE, type = ro, define = yes; # BANKE $1A000 Print1 (Character Print stuff) GENBANK: load = CARTF, run = CARTF, type = ro, define = yes; # BANKF $1C000 Generate code/rodata VECTORS: load = VECTORS, type = ro, define = yes; #ZPSAVE: load = LIBRAM, type = bss, define = yes; ZEROPAGE: load = ZP, type = zp; EXTZP: load = ZP, type = zp, optional = yes; } FEATURES { CONDES: segment = INIT, type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__; CONDES: segment = RODATA, type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__; CONDES: type = interruptor, segment = RODATA, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__; } ; ; Startup code for cc65 (ATARI version) ; Modifed for cartridge, Shawn Jefferson 08/15/2008 ; ; Contributing authors: ; Mark Keates ; Freddy Offenga ; Christian Groessler ; ; This must be the *first* file on the linker command line ; .export _exit .export __STARTUP__ : absolute = 1 ; mark as startup .constructor initsp, 26 .import initlib, donelib, callmain .import zerobss, pushax .import copysegs .import _main .import __STARTUP_LOAD__, __BSS_LOAD__ .import __CODE_LOAD__ .import __RESERVED_MEMORY__ .import __STACK_START__, __STACK_SIZE__ .ifdef DYNAMIC_DD .import __getdefdev .endif .include "zeropage.inc" .include "atari.inc" .include "_file.inc" ; ------------------------------------------------------------------------ ; EXE header ; Not needed for cartridge ; .segment "EXEHDR" ; .word $FFFF ; .word __LOWCODE_LOAD__ ; .word __BSS_LOAD__ - 1 ; ------------------------------------------------------------------------ ; Actual code .segment "STARTUP" rts ; fix for SpartaDOS / OS/A+ ; they first call the entry point from AUTOSTRT and ; then the load addess (this rts here). ; We point AUTOSTRT directly after the rts. ; Real entry point: ; Copy the library segements to RAM jsr copysegs ; Clear the BSS data jsr zerobss ; Call module constructors jsr initlib ; set left margin to 0 lda #0 sta LMARGN ; set keyb to upper/lowercase mode sta SHFLOK ; Initialize conio stuff lda #$FF sta CH ; Push arguments and call main jsr callmain ; Call module destructors. This is also the _exit entry. _exit: jsr donelib ; Run module destructors END: jmp END ; loop forever ; *** end of main startup code ; setup sp .segment "INIT" initsp: lda #<(__STACK_START__ + __STACK_SIZE__ - 1) sta sp lda #>(__STACK_START__ + __STACK_SIZE__ - 1) sta sp+1 rts ; Cartridge vectors at $BFFA ; .segment "VECTORS" ; Start Address .word __STARTUP_LOAD__+1 ; Cart present .byte $00 ; Init & Start .byte $04 ; Init Address .word __STARTUP_LOAD__ and copysegs.s (modified version of copyseg.s from cc65 package) ; ; Ullrich von Bassewitz, 1998-12-07, 2004-12-01 ; ; Copy the data segment from the LOAD to the RUN location ; ; modified to be a generic segment copy function ; just set ptr1, ptr2 and set seg size in x reg and a reg ; before calling. ; ; ptr1 is source (load address) ; ptr2 is dest (run address) ; ax is size .export copyseg, copysegs .import __CODE_LOAD__, __CODE_RUN__, __CODE_SIZE__ .import __RODATA_LOAD__, __RODATA_RUN__, __RODATA_SIZE__ .import __DATA_LOAD__, __DATA_RUN__, __DATA_SIZE__ .importzp ptr1, ptr2, tmp1 .segment "INIT" copysegs: lda #<__CODE_LOAD__ ; Source pointer sta ptr1 lda #>__CODE_LOAD__ sta ptr1+1 lda #<__CODE_RUN__ ; Target pointer sta ptr2 lda #>__CODE_RUN__ sta ptr2+1 ldx #<~__CODE_SIZE__ lda #>~__CODE_SIZE__ ; Use -(__DATASIZE__+1) jsr copyseg lda #<__RODATA_LOAD__ ; Source pointer sta ptr1 lda #>__RODATA_LOAD__ sta ptr1+1 lda #<__RODATA_RUN__ ; Target pointer sta ptr2 lda #>__RODATA_RUN__ sta ptr2+1 ldx #<~__RODATA_SIZE__ lda #>~__RODATA_SIZE__ ; Use -(__DATASIZE__+1) jsr copyseg lda #<__DATA_LOAD__ ; Source pointer sta ptr1 lda #>__DATA_LOAD__ sta ptr1+1 lda #<__DATA_RUN__ ; Target pointer sta ptr2 lda #>__DATA_RUN__ sta ptr2+1 ldx #<~__DATA_SIZE__ lda #>~__DATA_SIZE__ ; Use -(__DATASIZE__+1) jsr copyseg rts copyseg: sta tmp1 ldy #$00 ; Copy loop @L1: inx beq @L3 @L2: lda (ptr1),y sta (ptr2),y iny bne @L1 inc ptr1+1 inc ptr2+1 ; Bump pointers bne @L1 ; Branch always (hopefully) ; Bump the high counter byte @L3: inc tmp1 bne @L2 ; Done rts Edited March 2, 2011 by Shawn Jefferson 1 Quote Link to comment Share on other sites More sharing options...
Shawn Jefferson Posted March 23, 2011 Author Share Posted March 23, 2011 Update: http://www.atariage....effersons-blog/ Cave Generation code is coming along... almost done. Quote Link to comment Share on other sites More sharing options...
Shawn Jefferson Posted June 17, 2011 Author Share Posted June 17, 2011 Not much progress, since RL has been so busy, but I have completed character creation and cave generation. Attached is an Atarimax 8Mb cartridge image. Requires VBXE, since it uses 80 column mode, and the RAM of the VBXE. You can roll up a character, and then it will create a random dungeon. Pressing any key creates another dungeon. This is a straight across port from the Moria 5.5 source code, with minor changes to make it more cc65 friendly. No optimization has been done yet. You will notice that the object placement is very slow, this is because it is randomly grabbing locations from the map, checking if they are floor or not, and then placing the object-this can be sped up considerably I think. Still to do/port: store code in-game (dungeon) code character saving/loading code moria.bin Quote Link to comment Share on other sites More sharing options...
danwinslow Posted June 17, 2011 Share Posted June 17, 2011 Dan (or anyone who cares), here's the linker config file from the Atarimax 1Mbit version (I've since moved to the 8Mbit cart, very similiar config file though), and the custom crt0.s file to make cc65 programs run from a cart. You just manage where your code and data goes with a lot of #pragma code-name, #pragma rodata-name, etc... One tricky thing to keep in mind is that it seems you can only have one rodata segment per source file, I guess due to the optimization of RO strings that cc65 does. FEATURES { STARTADDRESS: default = $0400; } SYMBOLS { #__STACKSIZE__ = $400; # 1K stack #__RESERVED_MEMORY__: value = $1, weak = yes; __STACKSIZE__: type = weak, value $0400; # 1K stack __RESERVED_MEMORY__: type = weak, value = $0000; } MEMORY { ZP: start = $0082, size = $007E, type = rw, define = yes; LIBRAM: start = %S, size = $3800, define = yes; STACK: start = $3C00, size = __STACKSIZE__, define = yes; #ENGRAM: start = $3000, size = $5010, define = yes; MONSTERS: start = $4000, size = $6000, type = rw, define = yes; OBJECTS: start = $4000, size = $6000, type = rw, define = yes; SPELLS: start = $4000, size = $6000, type = rw, define = yes; MAGIC: start = $4000, size = $6000, type = rw, define = yes; CAVE: start = $4000, size = $6000, type = rw, define = yes; GEN: start = $4000, size = $6000, type = rw, define = yes; CART0: start = $A000, size = $1FFA, type = ro, fill = yes, fillval = $00, file = %O; VECTORS: start = $BFFA, size = 6, type = ro, file = %O; CART1: start = $A000, size = $4000, type = ro, fill = yes, fillval = $11, file = %O; #CART2: start = $A000, size = $2000, type = ro, fill = yes, fillval = $22, file = %O; CART3: start = $A000, size = $6000, type = ro, fill = yes, fillval = $33, file = %O; #CART4: start = $A000, size = $2000, type = ro, fill = yes, fillval = $44, file = %O; #CART5: start = $A000, size = $2000, type = ro, fill = yes, fillval = $55, file = %O; CART6: start = $A000, size = $6000, type = ro, fill = yes, fillval = $66, file = %O; #CART7: start = $A000, size = $2000, type = ro, fill = yes, fillval = $77, file = %O; #CART8: start = $A000, size = $2000, type = ro, fill = yes, fillval = $88, file = %O; CART9: start = $A000, size = $2000, type = ro, fill = yes, fillval = $99, file = %O; CARTA: start = $A000, size = $2000, type = ro, fill = yes, fillval = $AA, file = %O; CARTB: start = $A000, size = $2000, type = ro, fill = yes, fillval = $BB, file = %O; CARTC: start = $A000, size = $2000, type = ro, fill = yes, fillval = $CC, file = %O; CARTD: start = $A000, size = $2000, type = ro, fill = yes, fillval = $DD, file = %O; CARTE: start = $A000, size = $2000, type = ro, fill = yes, fillval = $EE, file = %O; CARTF: start = $A000, size = $2000, type = ro, fill = yes, fillval = $FF, file = %O; } SEGMENTS { INIT: load = CART0, type = ro, define = yes, optional = yes; STARTUP: load = CART0, type = ro, define = yes; LOWCODE: load = CART0, type = ro, define = yes, optional = yes; CODE: load = CART0, run = LIBRAM, type = ro, define = yes; RODATA: load = CART0, run = LIBRAM, type = ro, define = yes; DATA: load = CART0, run = LIBRAM, type = rw, define = yes; BSS: load = LIBRAM, type = bss, define = yes; HEAP: load = LIBRAM, type = bss, optional = yes; # must sit just below stack CAVERAM: load = CAVE, type = bss, define = yes; # Main CAVE structures GENRAM: load = GEN, type = bss, define = yes; # structures used in Generate.c functions BANK0: load = CART0, run = CART0, type = ro, define = yes; # BANK0 $00000 Setup Code, library code MONSTERBANK: load = CART1, run = MONSTERS, type = ro, define = yes; # BANK1-2 $02000 Monster list/structures OBJECTBANK: load = CART3, run = OBJECTS, type = ro, define = yes; # BANK3-5 $06000 Object list/structures SPELLBANK: load = CART6, run = SPELLS, type = ro, define = yes; # BANK6-8 $0C000 Spell data/structures, player data/structures MAGICBANK: load = CART9, run = MAGIC, type = ro, define = yes; # BANK9 $10000 Potions/Wands/Staff stuff INITBANK: load = CARTA, run = CARTA, type = ro, define = yes; # BANKA $12000 Init code/rodata CREATE1BANK: load = CARTB, run = CARTB, type = ro, define = yes; # BANKB $14000 Create1 code/rodata CREATE2BANK: load = CARTC, run = CARTC, type = ro, define = yes; # BANKC $16000 Create 2 code/rodata (modify_stats, calc_stuff) PRINTBANK: load = CARTD, run = CARTD, type = ro, define = yes; # BANKD $18000 Print (VBXE/IO bank. put_misc3 character print) CHPRINT1BANK:load = CARTE, run = CARTE, type = ro, define = yes; # BANKE $1A000 Print1 (Character Print stuff) GENBANK: load = CARTF, run = CARTF, type = ro, define = yes; # BANKF $1C000 Generate code/rodata VECTORS: load = VECTORS, type = ro, define = yes; #ZPSAVE: load = LIBRAM, type = bss, define = yes; ZEROPAGE: load = ZP, type = zp; EXTZP: load = ZP, type = zp, optional = yes; } FEATURES { CONDES: segment = INIT, type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__; CONDES: segment = RODATA, type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__; CONDES: type = interruptor, segment = RODATA, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__; } ; ; Startup code for cc65 (ATARI version) ; Modifed for cartridge, Shawn Jefferson 08/15/2008 ; ; Contributing authors: ; Mark Keates ; Freddy Offenga ; Christian Groessler ; ; This must be the *first* file on the linker command line ; .export _exit .export __STARTUP__ : absolute = 1 ; mark as startup .constructor initsp, 26 .import initlib, donelib, callmain .import zerobss, pushax .import copysegs .import _main .import __STARTUP_LOAD__, __BSS_LOAD__ .import __CODE_LOAD__ .import __RESERVED_MEMORY__ .import __STACK_START__, __STACK_SIZE__ .ifdef DYNAMIC_DD .import __getdefdev .endif .include "zeropage.inc" .include "atari.inc" .include "_file.inc" ; ------------------------------------------------------------------------ ; EXE header ; Not needed for cartridge ; .segment "EXEHDR" ; .word $FFFF ; .word __LOWCODE_LOAD__ ; .word __BSS_LOAD__ - 1 ; ------------------------------------------------------------------------ ; Actual code .segment "STARTUP" rts ; fix for SpartaDOS / OS/A+ ; they first call the entry point from AUTOSTRT and ; then the load addess (this rts here). ; We point AUTOSTRT directly after the rts. ; Real entry point: ; Copy the library segements to RAM jsr copysegs ; Clear the BSS data jsr zerobss ; Call module constructors jsr initlib ; set left margin to 0 lda #0 sta LMARGN ; set keyb to upper/lowercase mode sta SHFLOK ; Initialize conio stuff lda #$FF sta CH ; Push arguments and call main jsr callmain ; Call module destructors. This is also the _exit entry. _exit: jsr donelib ; Run module destructors END: jmp END ; loop forever ; *** end of main startup code ; setup sp .segment "INIT" initsp: lda #<(__STACK_START__ + __STACK_SIZE__ - 1) sta sp lda #>(__STACK_START__ + __STACK_SIZE__ - 1) sta sp+1 rts ; Cartridge vectors at $BFFA ; .segment "VECTORS" ; Start Address .word __STARTUP_LOAD__+1 ; Cart present .byte $00 ; Init & Start .byte $04 ; Init Address .word __STARTUP_LOAD__ and copysegs.s (modified version of copyseg.s from cc65 package) ; ; Ullrich von Bassewitz, 1998-12-07, 2004-12-01 ; ; Copy the data segment from the LOAD to the RUN location ; ; modified to be a generic segment copy function ; just set ptr1, ptr2 and set seg size in x reg and a reg ; before calling. ; ; ptr1 is source (load address) ; ptr2 is dest (run address) ; ax is size .export copyseg, copysegs .import __CODE_LOAD__, __CODE_RUN__, __CODE_SIZE__ .import __RODATA_LOAD__, __RODATA_RUN__, __RODATA_SIZE__ .import __DATA_LOAD__, __DATA_RUN__, __DATA_SIZE__ .importzp ptr1, ptr2, tmp1 .segment "INIT" copysegs: lda #<__CODE_LOAD__ ; Source pointer sta ptr1 lda #>__CODE_LOAD__ sta ptr1+1 lda #<__CODE_RUN__ ; Target pointer sta ptr2 lda #>__CODE_RUN__ sta ptr2+1 ldx #<~__CODE_SIZE__ lda #>~__CODE_SIZE__ ; Use -(__DATASIZE__+1) jsr copyseg lda #<__RODATA_LOAD__ ; Source pointer sta ptr1 lda #>__RODATA_LOAD__ sta ptr1+1 lda #<__RODATA_RUN__ ; Target pointer sta ptr2 lda #>__RODATA_RUN__ sta ptr2+1 ldx #<~__RODATA_SIZE__ lda #>~__RODATA_SIZE__ ; Use -(__DATASIZE__+1) jsr copyseg lda #<__DATA_LOAD__ ; Source pointer sta ptr1 lda #>__DATA_LOAD__ sta ptr1+1 lda #<__DATA_RUN__ ; Target pointer sta ptr2 lda #>__DATA_RUN__ sta ptr2+1 ldx #<~__DATA_SIZE__ lda #>~__DATA_SIZE__ ; Use -(__DATASIZE__+1) jsr copyseg rts copyseg: sta tmp1 ldy #$00 ; Copy loop @L1: inx beq @L3 @L2: lda (ptr1),y sta (ptr2),y iny bne @L1 inc ptr1+1 inc ptr2+1 ; Bump pointers bne @L1 ; Branch always (hopefully) ; Bump the high counter byte @L3: inc tmp1 bne @L2 ; Done rts Nice stuff, Shawn! Isn't there an option now to change the way CC65 handles the RO string data? IIRC, you can tell it to leave the data local. Quote Link to comment Share on other sites More sharing options...
Shawn Jefferson Posted June 18, 2011 Author Share Posted June 18, 2011 (edited) Nice stuff, Shawn! Isn't there an option now to change the way CC65 handles the RO string data? IIRC, you can tell it to leave the data local. Maybe... I'm specifying where to put RODATA though. For the most part, it's being put in the cartridge bank with the code that uses it, or VBXE RAM, depending on what it is within the game. I think there's about a half meg of data and code for Moria... so heavy bank switching of both cart and VBXE ram. Here's what the segment config looks like now (cart segments only): BANK0: load = CART0, run = CART0, type = ro, define = yes; # BANK0 MONSTERBANK: load = CART1, run = MONSTERS, type = ro, define = yes; # BANK1-2 $02000 Monster list/structures OBJECTBANK: load = CART3, run = OBJECTS, type = ro, define = yes; # BANK3-5 $06000 Object list/structures SPELLBANK: load = CART6, run = SPELLS, type = ro, define = yes; # BANK6-8 $0C000 Spell data/structures, player data/structures MAGICBANK: load = CART9, run = MAGIC, type = ro, define = yes; # BANK9 $10000 Potions/Wands/Staff stuff INITBANK: load = CARTA, run = CARTA, type = ro, define = yes; # BANKA $12000 Init code/rodata CREATE1BANK: load = CARTB, run = CARTB, type = ro, define = yes; # BANKB $14000 Create1 code/rodata CREATE2BANK: load = CARTC, run = CARTC, type = ro, define = yes; # BANKC $16000 Create 2 code/rodata (modify_stats, calc_stuff) PRINTBANK: load = CARTD, run = CARTD, type = ro, define = yes; # BANKD $18000 Print (VBXE/IO bank. put_misc3 character print) CHPRINT1BANK:load = CARTE, run = CARTE, type = ro, define = yes; # BANKE $1A000 Print1 (Character Print stuff) GEN1BANK: load = CARTF, run = CARTF, type = ro, define = yes; # BANKF $1C000 Generate1 code/rodata GEN2BANK: load = CART10, run = CART10, type = ro, define = yes; # BANK10 $1E000 Generate2 code/rodata (init, town_gen) GEN3BANK: load = CART11, run = CART11, type = ro, define = yes; # BANK11 $20000 Generate3 code/rodata (build_type2 & 3) MON1BANK: load = CART12, run = CART12, type = ro, define = yes; # BANK12 $22000 Monster code/rodata (alloc_monster) BANK13: load = CART13, run = CART13, type = ro, define = yes; # BANK13 $24000 MAGICT1BANK: load = CART14, run = CART14, type = ro, define = yes; # BANK14 $26000 magic_treasure1 function MAGICT2BANK: load = CART15, run = CART15, type = ro, define = yes; # BANK15 $28000 magic_treasure2 function PLACE1BANK: load = CART16, run = CART16, type = ro, define = yes; # BANK16 $2A000 cave place_xxxx functions Edited June 18, 2011 by Shawn Jefferson Quote Link to comment Share on other sites More sharing options...
Shawn Jefferson Posted March 25, 2012 Author Share Posted March 25, 2012 It's been about a year since I updated the blog (link below-WIP cartridge image available for download there), but I'm still working on this (slowly). I had the store_maint stuff (creating and populating the stores and items in the stores), but there was some nasty bugs due to all the bank switching needed to bring a 512+k game to a 64k computer. Finally sat down and fixed those bugs and now the generate cave portion of the code is completely ported over. Quote Link to comment Share on other sites More sharing options...
phaeron Posted March 26, 2012 Share Posted March 26, 2012 You might want to clear VBXE memory before initing the display. Quote Link to comment Share on other sites More sharing options...
Shawn Jefferson Posted March 26, 2012 Author Share Posted March 26, 2012 (edited) Yes, I just noticed that with the latest version of Altirra. Older versions had it already cleared I guess. Thanks! Does the real thing (VBXE) have random garbage in memory? I didn't notice this garbage on the real thing when I tested long ago (it was long ago though!) Hmm, just noticed when I turn on Randomize memory at cold start, it crashes after generating the map... I must be relying on some memory being clear I guess-another bug to hunt down. Speaking of that, can you load debugging information or symbols from cc65 into Altirra? Edited March 26, 2012 by Shawn Jefferson Quote Link to comment Share on other sites More sharing options...
phaeron Posted March 26, 2012 Share Posted March 26, 2012 There's a bug in current versions of Altirra where VBXE memory isn't getting cleared on cold reset, but I'm fixing that. The screenshot above is with the randomize function enabled. And yes, you can get garbage on real hardware -- someone posted a vidcap of this when I wrote a rotation demo that didn't clear its framebuffer. Altirra can read cc65 symbols, but it can't associate symbols by banks. I haven't tried a banked program but I'm guessing you'll get a bit of a mess. Quote Link to comment Share on other sites More sharing options...
Shawn Jefferson Posted March 27, 2012 Author Share Posted March 27, 2012 (edited) Hmmm, I'll have to try it. This is heavily bank-switched, so that could prove fatal. Do you use the .loadsym command to load them? Edited March 27, 2012 by Shawn Jefferson Quote Link to comment Share on other sites More sharing options...
phaeron Posted March 27, 2012 Share Posted March 27, 2012 For a cart, you'd have to load them manually with .loadsym, yes. I don't even know if Altirra will parse the symbol file, though -- it may blow up if there are bank indicators in the listing addresses. Quote Link to comment Share on other sites More sharing options...
Nateo Posted March 29, 2012 Share Posted March 29, 2012 You know, I was just wondering about what RPGs/RPG-like games there are for the Atari 8-bit. And now I have a new one to look forward to! I love Rogue-likes, and I'm really excited for this! Quote Link to comment Share on other sites More sharing options...
Shawn Jefferson Posted September 6, 2014 Author Share Posted September 6, 2014 (edited) I picked this up again and did some more work on it, including finding some really stupid bugs. I think I have a better grip on all the bank switching now so hopefully things will go faster. I have the store display code done (by done I mean ported) and debugged, and also have ported purchase haggling, so you can actually do something in the store. Latest cartridge image is here: http://atariage.com/forums/blog/18-atari-8-bit-moria-port/ Try it in Altirra with Warp speed, no optimization done yet. Requires VBXE2. The segment listing from my cc65 map file: Segment list: ------------- Name Start End Size Align ---------------------------------------------------- ZEROPAGE 000082 0000A4 000023 00001 CODE 000400 001EBB 001ABC 00001 RODATA 001EBC 002005 00014A 00001 DATA 002006 002111 00010C 00001 BSS 002112 002F52 000E41 00001 CAVERAM 004000 009BEF 005BF0 00001 GENRAM 004000 005387 001388 00001 MAGICBANK 004000 005002 001003 00001 MONSTERBANK 004000 00766C 00366D 00001 OBJECTBANK 004000 009FEA 005FEB 00001 SPELLBANK 004000 008A3C 004A3D 00001 CHPRINT1BANK 00A000 00B516 001517 00001 CREATE1BANK 00A000 00B716 001717 00001 CREATE2BANK 00A000 00BB5C 001B5D 00001 GEN1BANK 00A000 00BE9C 001E9D 00001 GEN2BANK 00A000 00ABB3 000BB4 00001 GEN3BANK 00A000 00BD5A 001D5B 00001 INIT 00A000 00A113 000114 00001 INITBANK 00A000 00B010 001011 00001 MAGICT1BANK 00A000 00BE56 001E57 00001 MAGICT2BANK 00A000 00BE83 001E84 00001 MISC1BANK 00A000 00AC0B 000C0C 00001 MON1BANK 00A000 00B29E 00129F 00001 OBJDESBANK 00A000 00B32C 00132D 00001 PLACE1BANK 00A000 00BBD4 001BD5 00001 PRINTBANK 00A000 00B6ED 0016EE 00001 STORE1BANK 00A000 00B4C6 0014C7 00001 STORE2BANK 00A000 00BC1A 001C1B 00001 STORE3BANK 00A000 00BA52 001A53 00001 STARTUP 00A114 00A132 00001F 00001 BANK7F 00BE45 00BF01 0000BD 00001 VECTORS 00BFFA 00BFFF 000006 00001 Edited September 6, 2014 by Shawn Jefferson 1 Quote Link to comment Share on other sites More sharing options...
Shawn Jefferson Posted September 25, 2014 Author Share Posted September 25, 2014 (edited) I've been generally posting any updates in my blog, but figured I should update this thread if anyone is following/cares. I have the first "demo". Character creation, Store interaction, Inventory and town/dungeon generation are ported and generally speaking work. It's interesting trying to port a program that expects a computer with 640k to run on a 64k computer with two small banked memory areas. $4000-9FFF is used for various of the large data structures that Moria uses: treasure/item list, monster list, cave structure and assorted spell and prayer data. $A000-BFFF is where pretty much all the code from Moria is going. There's a lot of banking going on, so low memory is the C runtime, some in memory variables (player struct, game variables) and all the banking code to make the inter-bank function calls work. I'm also duplicating some code in various banks to avoid banking where possible. Attached a cartridge image, Atarimax 8Mb old style bank 127. Run in Altirra with VBXE and Warp Speed. This is still un-optimized. I'm focusing on getting it ported and then I'll work on those parts that are slow (there's a lot!) After creating your character, press 1 for Town (and Stores) and 2 for Dungeon. The stores are interactive, and all options work (except Ctrl-R for redraw). There are six stores, and pressing ESC in the last one will exit the Town back to the 1 or 2 selection screen (it runs store maintenance, turning over items in the store, so next time you enter the stores items will have changed slightly.) The dungeon option will display a random dungeon and scroll around-pressing any key stops it and goes back to the 1 for Town, 2 for Dungeon screen. I was also thinking that once I get the game ported to work with VBXE, it's very possible that I can port the game to work on a non-VBXE computer using expanded memory (probably 256k at least). I will have to slim down the treasure list, and tweak the cave structure, and of course, re-write the display code to work with 40-columns... I'll think about that once the whole thing is ported and working on the Atari with VBXE though! PS. there are some display glitches still... I'll work those out. moria.bin Edited September 25, 2014 by Shawn Jefferson Quote Link to comment Share on other sites More sharing options...
Shawn Jefferson Posted October 17, 2014 Author Share Posted October 17, 2014 (edited) Here's a second demo, same Atarimax 8mb cartridge, old style 127 banking. This one you can create your character and walk around the town and dungeon. You can pick up, wear/wield/equip, and drop items. It's possible to die by stepping on traps or starving. If you are familiar with the original, I'm using rogue-like commands. Cave generation is still pretty slow, you may want to use Warp Speed in Altirra (no optimization of the cave generation has been attempted yet.) Movement commands:h - leftl - rightj - downk - upy - up left diagonalu - up right diagonaln - down left diagonalm - down right diagonal Use Shift with those commands to Run.Use Ctrl with those commands to Tunnel. PS. you can also use the Ctrl-Arrows to move your character up/down/left/right (but not run or tunnel at the moment.) Other commands:c - close a doord - drop an iteme - equipment listf - force/bash a doori - inventory listo - open a doors - searchw - wear/wieldC - display character/change nameE - EatF - Fill lamp with oilQ - quit the gameR - restS - spike a doorT - take off itemX - exchange item< - go up a staircase> - go down a staircase # - Search mode CTRL-P - previous message(s) moria.bin Edited October 17, 2014 by Shawn Jefferson Quote Link to comment Share on other sites More sharing options...
Wrathchild Posted October 17, 2014 Share Posted October 17, 2014 If you've space in the ROM, would it possible to store a pre-build cave and have the option to run that instead? Quote Link to comment Share on other sites More sharing options...
Shawn Jefferson Posted October 18, 2014 Author Share Posted October 18, 2014 Yes, I think there will be, but I will first try to optimize the cave generation so that it is more reasonable. The random cave generation is one of the fundamental things that makes Moria what it is I think. Quote Link to comment Share on other sites More sharing options...
Shawn Jefferson Posted November 2, 2014 Author Share Posted November 2, 2014 I've done some optimization with lookup tables and some zeropage use... gameplay is more bearable and cave generation is on average around 30 seconds now. Also found and fixed some porting bugs. This version I'm attaching will calculate (based on NTSC) the time it is taking to generate the cave. I also realized that I'll have to fix the palette for PAL/NTSC depending. Wrathchild's comment about pre-generated caves had me thinking about that as well. I'm thinking there will be enough space to pack some pre-generated caves into the cartridge space and provide that as an option for folks who can't stand the delay between levels... moria.bin 2 Quote Link to comment Share on other sites More sharing options...
Wrathchild Posted November 3, 2014 Share Posted November 3, 2014 (edited) I was thinking too that the pre-gen'd caves could be a useful for tournaments etc in a multi-player setting. E.g. first to reach a set character level or amount of riches to descend to a cave level and return time limited challenges etc. Edited November 3, 2014 by Wrathchild Quote Link to comment Share on other sites More sharing options...
Shawn Jefferson Posted January 17, 2015 Author Share Posted January 17, 2015 Basic monster code ported over now... monsters can move and attack, and you can attack them. update: http://atariage.com/forums/blog/18/entry-11652-here-be-dragons/ 1 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.