Jump to content
IGNORED

New Project: Atari 8-bit Moria


Recommended Posts

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!)

Link to comment
Share on other sites

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 by Shawn Jefferson
  • Like 1
Link to comment
Share on other sites

  • 3 weeks later...
  • 2 months later...

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

post-2472-0-29392800-1308291497_thumb.jpg

post-2472-0-33566700-1308291503_thumb.jpg

moria.bin

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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 by Shawn Jefferson
Link to comment
Share on other sites

  • 9 months later...

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.

Link to comment
Share on other sites

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 by Shawn Jefferson
Link to comment
Share on other sites

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.

Link to comment
Share on other sites

  • 2 years later...

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 by Shawn Jefferson
  • Like 1
Link to comment
Share on other sites

  • 3 weeks later...

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 by Shawn Jefferson
Link to comment
Share on other sites

  • 4 weeks later...

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 - left
l - right
j - down
k - up
y - up left diagonal
u - up right diagonal
n - down left diagonal
m - 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 door
d - drop an item
e - equipment list
f - force/bash a door
i - inventory list
o - open a door
s - search
w - wear/wield
C - display character/change name
E - Eat
F - Fill lamp with oil
Q - quit the game
R - rest
S - spike a door
T - take off item
X - exchange item
< - go up a staircase
> - go down a staircase

# - Search mode

CTRL-P - previous message(s)

moria.bin

Edited by Shawn Jefferson
Link to comment
Share on other sites

  • 2 weeks later...

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

  • Like 2
Link to comment
Share on other sites

  • 2 months later...

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...