Login
Back to forumReply to this topicGo to last reply

Posted By

Harry Potter
on 2022-12-03
17:04:01
 AdvSkel65/128k Plus4/cc65: Hannes memory not loaded properly

Hi! I am working on a new version of AdvSkel65. New to this release are 128k Plus4, Apple2 enhanced and limited text compression support. I'm currently having an issue with the 128k Plus4 version: it seems that the text data is not being loaded into Hannes memory properly. sad It uses CBMSimpleIO, AltInput and MemBankP4. I attached the code that loads to Hannes memory:

----------------------------
unsigned int bank1_cbm_load(const char* name, unsigned char device, void* data)
{
/* LFN is set to 0 but it's not needed for loading.
* (BASIC V2 sets it to the value of the SA for LOAD) */
static unsigned int i;
cbm_k_setlfs(14, device, CBM_READ);
cbm_k_setnam(name);
i=cbm_k_open(); //if (i) return -1;
i=bank1_cbm_read (14, data, 0xFC00-(unsigned) data);
cbm_close (14);
return i;
}

unsigned __fastcall__ bank1_cbm_read (unsigned char lfn, void* buffer, unsigned size)
/* Reads up to "size" bytes from a file to "buffer".
* Returns the number of actually read bytes, 0 if there are no bytes left
* (EOF) or -1 in case of an error. _oserror contains an errorcode then (see
* table below).
*/
{
static unsigned int bytesread;
unsigned char tmp, *a=buffer;

/* if we can't change to the inputchannel #lfn then return an error */
if (_oserror = cbm_k_chkin(lfn)) return -1;

bytesread = 0;
while (bytesread<size && !cbm_k_readst()) {
tmp = cbm_k_basin();
/* the kernal routine BASIN sets ST to EOF if the end of file
* is reached the first time, then we have store tmp.
* every subsequent call returns EOF and READ ERROR in ST, then
* we have to exit the loop here immidiatly. */
if (cbm_k_readst() & 0xBF) break;
bank1_writebyte (a, tmp);
if (bank1_readbyte(a)&255!=tmp)
{cbm_k_clrch(); printscr ("Error loading Hannes mem."); printu(bytesread); getkey(); break;}
++bytesread; ++a;
}
cbm_k_clrch();
return bytesread;
}
-----------------------------

Any help would be appreciated.

Posted By

Harry Potter
on 2022-12-07
10:56:16
 Re: AdvSkel65/128k Plus4/cc65: Hannes memory not loaded properly

I really want this to work. I'm attaching the config file:
----------------------
FEATURES {
STARTADDRESS: default = $1001;
}
SYMBOLS {
__LOADADDR__: type = import;
__EXEHDR__: type = import;
__STACKSIZE__: type = weak, value = $0800; # 2k stack
__HIMEM__: type = weak, value = $FC00;
}
MEMORY {
ZP: file = "", define = yes, start = $0002, size = $0036;
LOADADDR: file = %O, start = %S - 2, size = $0002;
HEADER: file = %O, define = yes, start = %S, size = $000D;
MAIN: file = %O, define = yes, start = __HEADER_LAST__, size = __HIMEM__ - __MAIN_START__ - __STACKSIZE__;
ZP2: file = "adv-low4.prg", start = $36, size = $90-$36;# 88 BYTES

BASBUF: file = "adv-low2.prg",
start = $01FE, size = $5A; # 90 bytes
TAPE: file = "adv-low1.prg",
start = $330, size = $0494-$0330; #356 bytes
BSTACK: file = "",
start = $06EC, size = $07AF-$06EC; #180 bytes
GRAPHIC1: file = "adv-low3.prg",
start = $02AB, size = $0300-$02AB; # 85 bytes

BANK1: file = "bank1.seq", define = yes, start = $1000, size = $EC00;
}
SEGMENTS {
ZEROPAGE: load = ZP, type = zp;
LOADADDR: load = LOADADDR, type = ro;
EXEHDR: load = HEADER, type = ro;
STARTUP: load = MAIN, type = ro;
LOWCODE: load = MAIN, type = ro, optional = yes;
CODE: load = MAIN, type = ro;
MEMBANK: load = MAIN, run = BSTACK,
optional = yes, define = yes;
ONCE: load = MAIN, type = ro, optional = yes;
RODATA: load = MAIN, type = ro;
DATA: load = MAIN, type = rw;
INIT: load = MAIN, type = bss;
BSS: load = MAIN, type = bss, define = yes;

#BASBSTART:load = BASBUF, type = ro, optional = yes;
BASBCODE: load = MAIN, type = ro, optional = yes;
#BASBCONST:load = BASBUF, type = ro, optional = yes;
#BASBDATA: load = BASBUF, type = rw, optional = yes;
GRSTART: load = GRAPHIC1, type = ro, optional = yes;
GRCODE: load = GRAPHIC1, type = ro, optional = yes;
GRCONST: load = GRAPHIC1, type = ro, optional = yes;
GRDATA: load = GRAPHIC1, type = rw, optional = yes;
BASISTART:load = BASBUF, type = ro, optional = yes;
BASICODE: load = BASBUF, type = ro, optional = yes;
BASICONST:load = BASBUF, type = ro, optional = yes;
BASIDATA: load = BASBUF, type = rw, optional = yes;
TAPESTART:load = TAPE, type = ro, optional = yes;
TAPECODE: load = TAPE, type = ro, optional = yes;
TAPECONST:load = TAPE, type = ro, optional = yes;
TAPEDATA: load = TAPE, type = rw, optional = yes;
TAPEBSS: load = TAPE, type = bss, optional = yes;
ZP2START: load = ZP2, type = ro, optional = yes;
ZP2CODE: load = ZP2, type = ro, optional = yes;

B1CODDE: load = BANK1, type = ro, optional = yes;
B1RODATA: load = BANK1, type = ro, optional = yes;
B1DATA: load = BANK1, type = rw, optional = yes;
B1BSS: load = BANK1, type = bss, optional = yes;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
segment = RODATA;
CONDES: type = interruptor,
label = __INTERRUPTOR_TABLE__,
count = __INTERRUPTOR_COUNT__,
segment = RODATA,
import = __CALLIRQ__;
}
---------------
and the crt0.s file:
-----------------------------------
;
; Startup code for cc65 (C128 version)
;
; This must be the *first* file on the linker command line
;

.export _exit
.export __STARTUP__ : absolute = 1 ; Mark as startup
.import callirq, initlib, donelib
.import zerobss
.import push0, pushax, callmain, _puts, _cgetc, _printf
.import _main
.import RESTOR, BSOUT, CLRCH
;.import __INTERRUPTOR_COUNT__
.import __RAM_START__, __RAM_SIZE__
.import __BANK1C_LOAD__, __BANK1C_RUN__, __BANK1C_SIZE__

.importzp ST
.include "zeropage.inc"
.include "c128.inc"


; ------------------------------------------------------------------------
; Constants

;IRQInd = $2FD ; JMP $0000 - used as indirect IRQ vector

; ------------------------------------------------------------------------
; Place the startup code in a special segment to cope with the quirks of
; c128 banking.

.segment "STARTUP"

; BASIC header with a SYS call

.org $1BFF
.word Head ; Load address
Head: .word @Next
.word .version ; Line number
;<---Changed by Harry Potter--->
.byte $FE,$02 ; BANK 15:
.byte '1','5',':'
.byte $9E,"7186" ; SYS 7186
;<---End changed by Harry Potter--->
.byte $00 ; End of BASIC line
@Next: .word 0 ; BASIC end marker
.reloc

; ------------------------------------------------------------------------
; Actual code

; Close open files
;<---Changed by Harry Potter--->
;lda #$00
;sta $FF00
jsr CLRCH

; Switch to the second charset

lda #14
jsr BSOUT
;lda #%00111111
;sta $FF00
lda #$00
sta $D503

sta $FF01
;<---End changed by Harry Potter--->
; Before doing anything else, we have to setup our banking configuration.
; Otherwise just the lowest 16K are actually RAM. Writing through the ROM
; to the underlying RAM works, but it is bad style.
;lda MMU_CR ; Get current memory configuration...
;pha ; ...and save it for later
;<---Changed by Harry Potter--->
;lda #MMU_CFG_CC65 ; Bank0 with kernal ROM
;lda #$00
;sta MMU_CR
;<---End changed by Harry Potter--->

; Save the zero page locations we need

ldx #zpspace-1
L1: ;lda sp,x
lda $0C,x
sta zpsave,x
dex
bpl L1

; Clear the BSS data

jsr zerobss

; Save system stuff and setup the stack

;pla ; Get MMU setting
;sta mmusave
tsx
stx spsave ; Save the system stack pointer

lda #<(__RAM_START__ + __RAM_SIZE__)
sta sp
lda #>(__RAM_START__ + __RAM_SIZE__)
sta sp+1 ; Set argument stack ptr

;Copy Bank 1 access routines to the memory visible to both Bank 0 and
;Bank 1.
ldx #<__BANK1C_SIZE__
@CopyB1Code:
dex
lda __BANK1C_LOAD__,x
sta __BANK1C_RUN__,x
cpx #0
bne @CopyB1Code
; Call module constructors

;lda #$3F
;sta $FF00
lda #0
sta FNAM_BANK
sta $FF01
jsr initlib
;pla
;sta $FF00

; Set the bank for the file name to our execution bank. We must do this,
; *after* calling constructors, because some of them may depend on the
; original value of this register.


; If we have IRQ functions, chain our stub into the IRQ vector

; lda #<__INTERRUPTOR_COUNT__
; beq NoIRQ1
; lda IRQVec
; ldx IRQVec+1
; sta IRQInd+1
; stx IRQInd+2
; lda #; ldx #>IRQStub
; sei
; sta IRQVec
; stx IRQVec+1
; cli
; Push arguments and call main()

NoIRQ1:
sta $FF01
jsr callmain

; Back from main (this is also the _exit entry). Reset the IRQ vector if we
; chained it.

_exit: pha ; Save the return code on stack
;lda # ;ldx #>M
;jsr _puts
;jsr _cgetc ;Wait for keypress.
; lda #<__INTERRUPTOR_COUNT__
; beq NoIRQ2
; lda IRQInd+1
; ldx IRQInd+2
; sei
; sta IRQVec
; stx IRQVec+1
; cli
; Run module destructors

NoIRQ2: jsr donelib

; Copy back the zero page stuff

ldx #zpspace-1
L2: lda zpsave,x
sta sp,x
dex
bpl L2

; Place the program return code into ST

pla
sta ST

; Reset the stack and the memory configuration

ldx spsave
txs
;<---Changed by Harry Potter--->
;ldx mmusave
;stx MMU_CR
;<---End changed by Harry Potter--->

; Done, restore kernal vectors in an attempt to cleanup
;lda #$00
sta $FF03
;jsr RESTOR
;jmp ($FFFC) ;Call C128 kernal reset routine
jmp RESTOR

; ------------------------------------------------------------------------
; The C128 has ROM parallel to the RAM starting from $4000. The startup code
; above will change this setting so that we have RAM from $0000-$BFFF. This
; works quite well with the exception of interrupts: The interrupt handler
; is in ROM, and the ROM switches back to the ROM configuration, which means
; that parts of our program may not be accessible. To solve this, we place
; the following code into a special segment called "LOWCODE" which will be
; placed just above the startup code, so it goes into a RAM area that is
; not banked.

.segment "LOWCODE"

;IRQStub:
; cld ; Just to be sure
; lda MMU_CR ; Get old register value
; pha ; And save on stack
; lda #MMU_CFG_CC65 ; Bank 0 with kernal ROM
; sta MMU_CR
; jsr callirq ; Call the functions
; pla ; Get old register value
; sta MMU_CR
; jmp IRQInd ; Jump to the saved IRQ vector
;

; ------------------------------------------------------------------------
; Data

.rodata
;M: .byte "Your program has finished. Press any",13
; .byte "key to continue...",13,0

.data
zpsave: .res zpspace

.bss
spsave: .res 1
mmusave:.res 1

.segment "APPSTART"
.word $1300

.segment "B1START"
.word $0400
-------------------------------


Posted By

Harry Potter
on 2022-12-08
08:39:49
 Re: AdvSkel65/128k Plus4/cc65: Hannes memory not loaded properly

I got the strings to display properly. happy I was loading a pointer from Hannes memory instead of directly. Now, in the first room, I'm getting garbage for all items but the first. sad Following are the code for the vLook verb:
void vLook (void)//char Itm1)
{
static unsigned char i;
static void (*func)();
//If an item is specified:
if (Itm1!=0xFF) {
//If it is available in the player inventory,
#ifdef __USEFARMEM__
if (SearchInvPlayer () || SearchInvRoom ())
{
//get string address and print help text.
if ((s=hidereadw((void*)&ItemPtr->Info))==0) {
printscr ("No help available for that item.");
return;
}
printtok (s); printcr ();
#else
if (SearchInvPlayer () || SearchInvRoom ())
{
//get string address and print help text.
if ((s=ItemPtr->Info)==0) {
printscr ("No help available for that item.");
return;
}
printscr (s);
#endif
} else {
printnoitem ();
}
return;
}
//Otherwise,
//get room information
CurRoomInv=Player.RoomInv[CRoom];
CRm=&Room[CRoom];
//print it,
#ifdef __USEFARMEM__
printtok ((char*)hidereadw((void*)&CRm->Desc));
//printc ('a');
//call the room handler
func=hidereadw((void*)&CRm->RoomHandler);
//printc ('b');
#else
printtok (CRm->Desc);
//call the room handler
func=(CRm->RoomHandler);
#endif
(*func) ();
printcr();
//and list room items.
for (i=0; i<8 && (Itm1=CurRoomInv<i>)!=0xFF;++i) {
#ifdef __USEFARMEM__
prints ("There is a ");
printitmname ();
printscr (" here.");
#else
prints ("There is a ");
printitmname ();
printscr (" here.");
#endif
}
//if (i) printcr();
}
[/code]and to print the item name:
[code]static void __fastcall__ printitmname (void)
{
//printu (Itm1); printc (' ');
#ifdef __USEFARMEM__
#ifdef __C128__
//bank1_print (bank1_readword((void*)&Item[Itm1].Name));
printtok (Item[Itm1].Name);
#elif defined __C64__
printtok (hidereadw((void*)&Item[/*CurRoomInv*/Itm1].Name));
#elif defined __PLUS4__ || defined __C128__
printtok (bank1_readword((void*)&Item[Itm1].Name));
#elif defined __ATARI__ || defined __APPLE2ENH__
printtok (aux_readword((void*)&Item[Itm1].Name));
#endif
#else
prints (Item[Itm1].Name);
#endif
}


Posted By

SVS
on 2022-12-09
08:43:10
 Re: AdvSkel65/128k Plus4/cc65: Hannes memory not loaded properly

@Harry Potter: Cause missing time I haven't studied your listings yet. But I remember my work in 256K Mega Assembler, maybe some into can be useful to you. The default bank with Hannes expansion is #3. You can switch it by writing the new bank # on $FD16 register. While the bank is different than #3 you must disable the IRQ routine.

Posted By

Harry Potter
on 2022-12-09
10:14:57
 Re: AdvSkel65/128k Plus4/cc65: Hannes memory not loaded properly

SVS, I thank you for your info. I am writing $30+bank # to $FD16. I am also disabling IRQ's while accessing the RAM. I plan to post here the read/write code later today, as I am currently in the middle of something else right now.

Posted By

Harry Potter
on 2022-12-10
08:31:33
 Re: AdvSkel65/128k Plus4/cc65: Hannes memory not loaded properly

I fixed a bug in the code--I forgot what the bug was--and now, the room description prints properly, but the items in the room after the first print garbage. Also, the C64 versions currently don't work: they give me a blue screen with no text. sad Following are some code snippets that might be causing the problem:
-------------------------------
.segment "MEMBANK"

_bank1_readbyte:
ldy #0
bank1_readbyteoffs:
sta ptr1
stx ptr1+1
bank1_readbyteoffs2:
;sta $FF02
sei
lda #$32
sta $FD16
lda (ptr1),y
;sta $FF01
ldx #$33
stx $FD16
cli
ldx #0
rts

.segment "LOWCODE"

_bank1_writebyte:
;jsr popa
pha
jsr popax
sta ptr1
stx ptr1+1
pla
ldy #0
jmp bank1_writebytedirect

.segment "MEMBANK"

bank1_writebytedirect:
;sta $FF02
sei
pha
lda #$32
sta $FD16
pla
sta (ptr1),y
lda #$33
sta $FD16
cli
rts
-------------------------
//Prints the name of the current item indicated by Itm1.
static void __fastcall__ printitmname (void)
{
//printu (Itm1); printc (' ');
#ifdef __USEFARMEM__
#ifdef __C128__
//bank1_print (bank1_readword((void*)&Item[Itm1].Name));
printtok (Item[Itm1].Name);
#elif defined __C64__
printtok (hidereadw((void*)&Item[/*CurRoomInv<i>*/Itm1].Name));
#elif defined __PLUS4__ || defined __C128__
printtok (bank1_readword((void*)&Item[Itm1].Name));
#elif defined __ATARI__ || defined __APPLE2ENH__
printtok (aux_readword((void*)&Item[Itm1].Name));
#endif
#else
prints (Item[Itm1].Name);
#endif
}

//Verb to describe the current item or scene.
void vLook (void)//char Itm1)
{
//static unsigned char i;
static void (*func)(void);
//If an item is specified:
if (Itm1!=0xFF) {
//If it is available in the player inventory,
#ifdef __USEFARMEM__
if (SearchInvPlayer () || SearchInvRoom ())
{
//get string address and print help text.
if ((s=hidereadw((void*)&ItemPtr->Info))==0) {
printscr ("No help available for that item.");
return;
}
printtok (s); printcr ();
#else
if (SearchInvPlayer () || SearchInvRoom ())
{
//get string address and print help text.
if ((s=ItemPtr->Info)==0) {
printscr ("No help available for that item.");
return;
}
printscr (s);
#endif
} else {
printnoitem ();
}
return;
}
//Otherwise,
//get room information
memcpy (0xC00, Player.RoomInv[CRoom], 8); getkey();
CurRoomInv=&Player.RoomInv[CRoom];
CRm=&Room[CRoom];
//print it,
#ifdef __USEFARMEM__
printtok ((char*)hidereadw((void*)&CRm->Desc));
//printc ('a');
//call the room handler
func=hidereadw((void*)&CRm->RoomHandler);
//printc ('b');
#else
printtok (CRm->Desc);
//call the room handler
func=(CRm->RoomHandler);
#endif
(*func) ();
printcr();
//and list room items.
for (i=0; i<8 && (Itm1=CurRoomInv<i>)!=0xFF;++i) {
//printu (CurRoomInv+i);
#ifdef __USEFARMEM__
prints ("There is a ");
printitmname ();
printscr (" here.");
#else
prints ("There is a ");
printitmname ();
printscr (" here.");
#endif
}
//if (i) printcr();
}


Posted By

SVS
on 2022-12-13
04:25:47
 Re: AdvSkel65/128k Plus4/cc65: Hannes memory not loaded properly

@Harry Potter: remember that by setting $FF16 with #$30+bank# as you does, the TED is enabled to always access Bank#3. If you want TED do access to another bank, you have to set (on) bit 6 of $FF16 that i #$70+bank#.

Posted By

Harry Potter
on 2022-12-13
06:38:49
 Re: AdvSkel65/128k Plus4/cc65: Hannes memory not loaded properly

SVS: I thank you for your response, but I want the TED to always use Bank 3. I just want the CPU to read and write Bank 2, that's all.

Posted By

Harry Potter
on 2023-03-04
13:36:49
 Re: AdvSkel65/128k Plus4/cc65: Hannes memory not loaded properly

I gained a lot of ground with debugging AdvSkel65 but still have problems. However, AdvSkelVic65 was updated recently. The main updates are some bug fixes and support for text compression. If you don't use a lot of text, you can disable the compression, but there is a bug where such support is not complete. sad An update is available that explains the extra step needed. It is at https://sourceforge.net/projects/cc65extra/files/game/. Try it out!



Back to topReply to this topic


Copyright © Plus/4 World Team, 2001-2024. Support Plus/4 World on Patreon