There are another questions for level conversion.
1. Where is the starting offset of level data in SNES rom file? (3940 bytes in sequence)
(I think that 0x20078 is the starting offset. Is that right?)
2. What is the algorithm for decoding/encoding level data block in SNES rom file? I think David can explain it. I use Delphi for development and found following related source codes of SNESLevelEditor for encoding and decoding level data, but I could not understand it. I think I have to convert this C++ codes to Delphi.
Code: Select all
void TSMC::decodelevel(TMemoryStream* ms_in,TMemoryStream* ms_out,int len){
int st=ms_out->Position,end=ms_out->Position+len,i,n;
unsigned char ch,*p; unsigned __int16 ad;
while(ms_out->Position<end){
ms_in->Read(&ch,1);
if(ch&0x80){
if(ch&0x7F) ms_out->CopyFrom(ms_in,ch&0x7F);
}else{
switch(ch){
case 1: ms_in->Read(&ch,1); n=ch?ch:256; ms_in->Read(&ch,1);
for(i=0;i<n;i++) ms_out->Write(&ch,1);
break;
case 2: ms_in->Read(&ch,1); n=ch?ch:256; ms_in->Read(&ch,1);
for(i=0;i<n;i++,ch++) ms_out->Write(&ch,1);
break;
case 3: ms_in->Read(&ch,1); n=ch?ch:256; ms_in->Read(&ch,1);
for(i=0;i<n;i++,ch--) ms_out->Write(&ch,1);
break;
case 4: ms_in->Read(&ch,1); n=ch?ch:256; ms_in->Read(&ch,1);
p=(unsigned char*)ms_out->Memory+st+ch;
for(i=0;i<n;i++,p++) ms_out->Write(p,1);
break;
case 5: ms_in->Read(&ch,1); n=ch?ch:256; ms_in->Read(&ad,2);
p=(unsigned char*)ms_out->Memory+st+ad;
for(i=0;i<n;i++,p++) ms_out->Write(p,1);
break;
default: return ShowMessage("error in decodelevel : "+IntToStr((int)ch));
}
}
}
}
void TSMC::encodelevel(TMemoryStream* ms_in,TMemoryStream* ms_out,int len){
int st=ms_in->Position,en=ms_in->Position+len;
unsigned char ch,*sp=(unsigned char*)ms_in->Memory+st;
unsigned char *p=sp,*ep=(unsigned char*)ms_in->Memory+en;
unsigned char *cp;
unsigned char dl=0,dt[128],tp;
unsigned __int16 l[5],sa,ln;
int i;
while(p<ep){
for(i=0;i<5;i++) l[i]=0;
for(ln=0;p+ln+1<ep&&ln<256;ln++) if(*(p+ln) !=*(p+ln+1)) break; if(ln>3) l[1]=ln;
for(ln=0;p+ln+1<ep&&ln<256;ln++) if(*(p+ln)+1!=*(p+ln+1)) break; if(ln>3) l[2]=ln;
for(ln=0;p+ln+1<ep&&ln<256;ln++) if(*(p+ln)-1!=*(p+ln+1)) break; if(ln>3) l[3]=ln;
l[4]=0;
for(cp=sp;cp<p;cp++){
for(ln=0;ln<256&&p+ln<ep;ln++){
if(*(p+ln)!=*(cp+ln)) break;
}
//ln++;
if(ln>l[4]&&(ln>4||cp-sp<0xFF&&ln>3)){ sa=cp-sp; l[4]=ln; }
}
ln=0; tp=0;
for(i=1;i<=4;i++) if(l[i]>ln){ ln=l[i]; tp=i; }
if(ln<2){
dt[dl++]=*(p++);
if(dl==0x7F){
dl+=0x80; ms_out->Write(&dl,1); dl-=0x80;
ms_out->Write(dt,dl); dl=0;
}
}else{
if(dl){
dl+=0x80; ms_out->Write(&dl,1); dl-=0x80;
ms_out->Write(dt,dl); dl=0;
}
if(tp==4){
if(sa>=0x100){
tp=5; ms_out->Write(&tp,1); ms_out->Write(&ln,1); ms_out->Write(&sa,2);
}else{
ms_out->Write(&tp,1); ms_out->Write(&ln,1); ms_out->Write(&sa,1);
}
}else{
ms_out->Write(&tp,1);
ms_out->Write(&ln,1);
ms_out->Write(p,1);
}
p+=ln;
}
}
if(dl){
dl+=0x80; ms_out->Write(&dl,1); dl-=0x80;
ms_out->Write(dt,dl); dl=0;
}
// ShowMessage(p-ep);
ms_in->Position=en;
}