by now it looks ALMOST normal, but it lacks some decent filling, i have no clue why "screen$" is Not Selected at all
Code: Select all
// RDcat040h
// zcc +zx -vn -lm -startup=31 -zorg0x7000 RDcat040h.c -oRDcat040h -lndos -create-app -Cz --noloader --list --c-code-in-asm //-a
// cat ramcatBAS.tap RDcat040h.tap > testRDcat040h.tap
// Catalogue for the contence off the early zx spectrum 128k 'toastrack' RamDrive
// http://www.users.globalnet.co.uk/~jg27paw4/type-ins/zx-comp/zx8605_intothe128.zip
// https://github.com/ZXSpectrumVault/rom-disassemblies/blob/master/Spectrum%20128K/Spectrum128_ROM0.asm
// BANK_M EQU $5B5C ; 1byte Copy of last byte output to I/O port $7FFD
// SFNEXT EQU $5B83 ; 2byte End of RAM disk catalogue marker. Pointer to first empty catalogue entry.
// SFSPACE EQU $5B85 ; 3byte Number of bytes free in RAM disk (3 bytes, 17 bit, LSB first).
// ------------------
// RAM Disk Catalogue
// ------------------
// The catalogue can occupy addresses $C000-$EBFF in physical RAM bank 7, starting at $EBFF and growing downwards.
//
// Each entry contains 20 bytes:
// Bytes $00-$09: Filename.
// Bytes $0A-$0C: Start address of file in RAM disk area.
// Bytes $0D-$0F: Length of file in RAM disk area.
// Bytes $10-$12: End address of file in RAM disk area (used as current position indicator when loading/saving).
// Byte $13 : Flags:
// Bit 0 : 1=Entry requires updating.
// Bits 1-7: Not used (always hold 0).
//
// A file consists of a 9 byte header followed by the data for the file. The header bytes
// have the following meaning:
// Byte $00 : File type - $00=Program, $01=Numeric array, $02=Character array, $03=Code/Screen$.
// Bytes $01-$02: Length of program/code block/screen$/array ($1B00 for screen$).
// Bytes $03-$04: Start of code block/screen$ ($4000 for screen$).
// Bytes $05-$06: Offset to the variables (i.e. length of program) if a program. For an array, $05 holds the variable name.
// Bytes $07-$08: Auto-run line number for a program ($80 in high byte if no auto-run).
// This is the information contained by the end-of-catalogue marker,
// assuming that IX points to the first byte. Note that this marker is indexed by (4)(SF_NEXT).
// IX+00 (ten bytes) : Not used
// IX+0A SF_START (three bytes): Page-coded address of first spare byte in RAMdisc
// IX+0D (seven bytes): Not used
//
// -----------------
// Throughout ROM 0, memory banks are accessed using a logical numbering scheme, which
// maps to physical RAM banks as follows:
// Logical Bank Physical Bank
// ------------ -------------
// $00 $01
// $01 $03
// $02 $04
// $03 $06
// $04 $07
// $05 $00
// This scheme makes the RAM disk code simpler than having to deal directly with physical RAM bank numbers.
// BASIC LOADER for testing
/*
1 CLEAR : SAVE "RDtestfile" LINE VAL "10"
10 CLEAR VAL "28671": LOAD ""CODE
11 GO TO VAL "150"
12 RANDOMIZE USR VAL "28672"
13 SAVE !"Ramdrive_1"CODE VAL "0",VAL "16384-9"
15 RANDOMIZE USR VAL "28672"
19 SAVE !"Ramdrive_2"CODE VAL "0",VAL "16384"
20 SAVE !"RamDrive_3"
22 SAVE !"RamDrive_4" LINE VAL "10"
24 LET n$="RamDrive_ ": LET c=VAL "512": DIM a(c): LET d=VAL "10"
25 LET n$(d)="5": SAVE !n$
26 DIM b$(c)
27 LET n$(d)="6": SAVE !n$ LINE VAL "10"
32 LET n$(d)="7": SAVE !n$ DATA a()
34 LET n$(d)="8": SAVE !n$ DATA b$()
36 LET n$(d)="9": SAVE !n$SCREEN$
100 RANDOMIZE USR VAL "28672"
150 CLS : CAT !: LET n$=" ": FOR x=VAL "1" TO VAL "10": LET n$(x)=SCREEN$ (0,x-1): NEXT x: PRINT AT 21,0;n$: IF n$<>" " THEN ERASE !n$: GO TO VAL "150"
200 GO TO VAL "12"
*/
//-------------------------------------------------
#include <stdio.h>
#include <string.h>
static __at(23429) unsigned long LEFTMEMORY ;
//-------------------------------------------------
void preskey( int cls)
{
char key;
printf("Press a key");
scanf("%c",&key ) ;
if (cls == 1) {printf("\xC");}
return ;
}
//-------------------------------------------------
// 32768(-1)?? 0-3 save area 16384-49151 49512-65535
// PAGE CODEING USED ( 4th , 3rd , 2nd , 1st ) ret
int __CALLEE__ fetchblock(unsigned int blocklength, unsigned char pagecode, unsigned int destiny, unsigned int source)__naked {
#asm // ALWAYS RETURN WITH RAM 0 SET !!!
di // disable interrupt for save RamBank switching
pop bc // fetch return addres
exx
pop hl // source cq headerstart adres
pop de // destiny adres HAS TO BE UNDER 49151-length , well, most off the times !!!
pop bc
ld a,c // logicbank aka pagecode 0,1,2,3,4,5: RamdriveCatalogue @ pagecode(4)=fysicbank(7)
pop bc // length
exx
push bc // reinstall return address on stack
exx
push bc // save length on stack
ld c,a
ex af,af // save for PAGECODE increase
ld a,c // both a hold pagecode
call PAGE_A // A must hold PAGE CODE
pop bc // BC=headerlength , HL=headerinfo, DE=destiny
fetch: ld a,(hl)
ld (de),a
inc de // ram UNDER 49152, hopefully it works, max range now 16384-49151, MIGHT overwrite THIS routine !!
inc hl // 0xffff top off RAM
ld a,h
or l
jr nz,nextbc
ex af,af // fetch pagecode again
inc a // raise to next page
push bc
call PAGE_A // A must hold PAGE CODE
pop bc
ld hl,0xC000 // ld h,0xC0 save 1 byte
nextbc:
dec bc
ld a,b
or c
jr nz,fetch
ld a,5
call PAGE_A
reit: ei
ret // ALWAYS RETURNS WITH RAM 0 SET !!!
// from 'SuperCAT' by Toni Baker from ZX Computing June 1987
PAGE_A: CP 5 // 0,1,2,3,4,5
jr z,a255 // jump on a=5
jr c,PAGE_A_2 // jump on a<5
ret // return if pagecode above a>5
a255: LD A,0xFF // A will contain 0 after increment
PAGE_A_2: INC A // 1,2,3,4,5,0
LD B,A // B= pagecode + 1
SRL B // 0,1,1,2,2,0 Divide B by two
ADD A,B // 1,3,4,6,7,0 A=absolute RAM page number
ld b,a
ld a,(23388)
and 248 // cut page info to 0
or b // set bank B
ld bc,32765
ld (23388),a
out (c),a // signal page
ret
// Thank you
#endasm // ROMS NOT CHANGED
} // ALWAYS RETURN WITH RAM 0 SET !!!
//-------------------------------------------------
main(){
unsigned long mem_count ; //*leftmemory at(23429)
unsigned int start, start1 ; // LET start=FN z(VAL "x+10")
unsigned int leng, leng1 ; // LET leng=FN z(VAL "x+13")
unsigned int end, end1 ; // LET end=FN z(VAL "x+16")
unsigned int *rd_counter=23427 ; // LET el=FN p(VAL "23427")
unsigned int rd_count, filecount, tempaddress ;
unsigned int rd_bottom=49512, rd_middle=56424, rd_top=60415 ; // rt=VAL "60415" rb=VAL "49512" rm=VAL "rb+6912"
unsigned int rd_headersize=20 ; // ram file header size or entry size @ram_7
unsigned int rd_fileheader=9 ; // small infile header to confirm big entry header @ram_x
unsigned int ram0=0, rdisc=4 ; // ramdisc at PAGE 4 = BANK 7
unsigned int x,y ;
unsigned char pagecodestr[]="134670" ; // pagecode 0,1,2,3,4,5 => fysic rambank 1,3,4,6,7,0
unsigned char pagecode, bank ; // LET pagecode=PEEK VAL "x+12"
unsigned char blocks_leng ; // LET blocks_leng=PEEK VAL "x+15":
unsigned char blocks_end ; // LET blocks_end=PEEK VAL "x+18"
unsigned char changed ; // LET ch=PEEK VAL "x+19"
rd_count=*rd_counter ;
mem_count=LEFTMEMORY & 0x0001FFFF ; // 3bytes > 17 bits
filecount = ( rd_top+1 -rd_headersize -rd_count ) /rd_headersize ; // LET fl=VAL "(rt-20-el+1)/20"
printf("\xCRamdrive %3u file found,%7lu bytes left\n",filecount,mem_count) ;
tempaddress = rd_top + 1 - rd_headersize ;
for (x=0;x<=filecount;x++){
unsigned char headerinfo[20+1];
unsigned char fileinfo[9+1] ;
// fetch catalogue
fetchblock(rd_headersize, rdisc, headerinfo, tempaddress) ; // catalogue=page 4 !!!
pagecode=headerinfo[12] ;
bank=pagecodestr[pagecode]-48 ; // ascii48='0': LET bank=VAL "134670"(pagecode+1)
start= (char)headerinfo[10] + ( (char)headerinfo[11] *256 );
// start1= start + (pagecode * 16384);
blocks_leng=headerinfo[15] ;
leng = (char)headerinfo[13] + ( (char)headerinfo[14] *256 );
leng1= leng + (blocks_leng * 16384);
blocks_end=headerinfo[18] ;
end = (char)headerinfo[16] + ( (char)headerinfo[17] *256 );
// end1 = end + (blocks_end * 16384);
changed=headerinfo[19] ; // internal flag if FILE needs update in CATalogue
unsigned char name[]="End_Of_Cat" ;
unsigned char type[]=" ", type2[]=" ", type3[]=" ", type4[]=" ",
lenstr[]=" ", startstr[]=" ", autostr[]=" ", varstr[]=" " ;
if ( x < filecount){
for (y=0;y<10;y++){name[y]=headerinfo[y]; } ;
name[10]='\0';
// fetch fileheader somewhere in RAM
fetchblock(rd_fileheader, pagecode, fileinfo, start ) ;
unsigned char filetype=fileinfo[0], datachr ;
unsigned int filelength, filestart, variables, autoline, basiclength ;
filelength = (char)fileinfo[1] + ( (char)fileinfo[2] *256 );
filestart = (char)fileinfo[3] + ( (char)fileinfo[4] *256 );
variables = (char)fileinfo[5] + ( (char)fileinfo[6] *256 );
autoline = (char)fileinfo[7] + ( (char)fileinfo[8] *256 );
datachr = fileinfo[5] ;
basiclength = filelength - variables ;
switch (filetype){
case 0: strcpy(type, "Prog");
if (autoline < 32768 ){
strcpy(type2, " LINE ");
sprintf(type3, "%5u", autoline);
};
if (variables>0){
sprintf(type4, "%5u", variables);
};
break;
case 1: strcpy(type, "Data");
strcpy(type2, " DATA ");
strcpy(type3, " () ");
type3[0]=datachr-32 ;
sprintf(type4, "%5u", filelength);
break;
case 2: strcpy(type, "Data");
strcpy(type2, " DATA ");
strcpy(type3, " $() ");
type3[0]=datachr-96 ;
sprintf(type4, "%5u", filelength);
break;
case 3: strcpy(type, "Byte");
sprintf(type3, "%5u", filestart);
sprintf(type4, "%5u", filelength);
strcpy(type2, " CODE ");
if (filelength==6912 && filestart==16384) {
strcpy(type2,"SCREEN$");
}
break;
}// end switch
}; // end IF x<filecount
printf("%s:%s %s %s %s " ,type ,name , type2 ,type3, type4 );
printf("%u/%5u %u/%5u %u/%5u",pagecode,start,blocks_leng,leng,blocks_end,end);
printf("\n");
tempaddress=tempaddress-rd_headersize ;
} // end 'for filecount'
preskey(1);
return 0;
}