︙ | | | ︙ | |
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
|
#define AddInstF(x,y) (cl->codes[ptr++]=(x),prflag=(y))
#define ChangeInst(x) (cl->codes[ptr-1]x,prflag=0)
#define InstFlag(x) (peep<ptr && (prflag&(x)))
#define Inst7bit() (peep<ptr && cl->codes[ptr-1]<0x0080)
#define Inst8bit() (peep<ptr && cl->codes[ptr-1]<0x0100)
#define AbbrevOp(x,y) case x: if(Inst7bit()) ChangeInst(+=0x1000|((y)<<4)); else AddInstF(x,tokent); break
#define FlowPush(x) do{ if(flowdepth==64) ParseError("Too much flow control nesting\n"); flowop[flowdepth]=x; flowptr[flowdepth++]=ptr; }while(0)
#define FlowPop(x) do{ if(!flowdepth || flowop[--flowdepth]!=(x)) ParseError("Flow control mismatch\n"); }while(0)
static int parse_instructions(int cla,int ptr,Hash*hash,int compat) {
int peep=ptr;
int prflag=0;
Class*cl=classes[cla];
int flowdepth=0;
Uint16 flowop[64];
Uint16 flowptr[64];
|
|
|
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
|
#define AddInstF(x,y) (cl->codes[ptr++]=(x),prflag=(y))
#define ChangeInst(x) (cl->codes[ptr-1]x,prflag=0)
#define InstFlag(x) (peep<ptr && (prflag&(x)))
#define Inst7bit() (peep<ptr && cl->codes[ptr-1]<0x0080)
#define Inst8bit() (peep<ptr && cl->codes[ptr-1]<0x0100)
#define AbbrevOp(x,y) case x: if(Inst7bit()) ChangeInst(+=0x1000|((y)<<4)); else AddInstF(x,tokent); break
#define FlowPush(x) do{ if(flowdepth==64) ParseError("Too much flow control nesting\n"); flowop[flowdepth]=x; flowptr[flowdepth++]=ptr; }while(0)
#define FlowPop(x) do{ if(!flowdepth || flowop[--flowdepth]!=(x)) ParseError("Flow control mismatch\n"); prflag=0; }while(0)
static int parse_instructions(int cla,int ptr,Hash*hash,int compat) {
int peep=ptr;
int prflag=0;
Class*cl=classes[cla];
int flowdepth=0;
Uint16 flowop[64];
Uint16 flowptr[64];
|
︙ | | | ︙ | |
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
|
AddInst(y+0x0800);
AddInst(0x1F00|(x&0x1F));
} else {
AddInst(y);
AddInst(0x1F00|(x&0x1F));
}
break;
default:
if(Tokenf(TF_ABNORMAL)) ParseError("Invalid instruction token\n");
if(compat && Tokenf(TF_COMPAT) && Tokenf(TF_EQUAL)) ++tokenv;
AddInstF(tokenv,tokent);
}
} else if(Tokenf(TF_FUNCTION)) {
AddInst2(OP_FUNCTION,tokenv&0x3FFF);
|
>
>
>
>
>
|
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
|
AddInst(y+0x0800);
AddInst(0x1F00|(x&0x1F));
} else {
AddInst(y);
AddInst(0x1F00|(x&0x1F));
}
break;
case OP_SUPER:
case OP_SUPER_C:
if(!ptr || cl->codes[0]!=OP_SUPER) ParseError("Use of Super in a class with no parent class\n");
AddInst(tokenv);
break;
default:
if(Tokenf(TF_ABNORMAL)) ParseError("Invalid instruction token\n");
if(compat && Tokenf(TF_COMPAT) && Tokenf(TF_EQUAL)) ++tokenv;
AddInstF(tokenv,tokent);
}
} else if(Tokenf(TF_FUNCTION)) {
AddInst2(OP_FUNCTION,tokenv&0x3FFF);
|
︙ | | | ︙ | |
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
|
} else {
ParseError("Invalid instruction token\n");
}
if(ptr>=0xFFEF) ParseError("Out of code space\n");
}
if(flowdepth) ParseError("Unterminated flow control blocks (%d levels)\n",flowdepth);
cl->codes=realloc(cl->codes,ptr*sizeof(Uint16))?:cl->codes;
return ptr;
}
static void dump_class(int cla,int endptr,const Hash*hash) {
const Class*cl=classes[cla];
int i,j;
if(!cl) return;
|
>
|
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
|
} else {
ParseError("Invalid instruction token\n");
}
if(ptr>=0xFFEF) ParseError("Out of code space\n");
}
if(flowdepth) ParseError("Unterminated flow control blocks (%d levels)\n",flowdepth);
cl->codes=realloc(cl->codes,ptr*sizeof(Uint16))?:cl->codes;
if(!ptr) cl->codes=0;
return ptr;
}
static void dump_class(int cla,int endptr,const Hash*hash) {
const Class*cl=classes[cla];
int i,j;
if(!cl) return;
|
︙ | | | ︙ | |
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
|
if(!x) ParseError("User flag ^%s not defined\n",tokenstr);
if(x<0x1020) cl->misc4|=1L<<(x&0x1F);
else if(x<0x1040) cl->misc5|=1L<<(x&0x1F);
else if(x<0x1060) cl->misc6|=1L<<(x&0x1F);
else if(x<0x1080) cl->misc7|=1L<<(x&0x1F);
else cl->collisionLayers|=1<<(x&0x1F);
}
static void class_definition(int cla,sqlite3_stmt*vst) {
Hash*hash=calloc(LOCAL_HASH_SIZE,sizeof(Hash));
Class*cl=classes[cla];
int ptr=0;
int compat=0;
int i;
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
|
if(!x) ParseError("User flag ^%s not defined\n",tokenstr);
if(x<0x1020) cl->misc4|=1L<<(x&0x1F);
else if(x<0x1040) cl->misc5|=1L<<(x&0x1F);
else if(x<0x1060) cl->misc6|=1L<<(x&0x1F);
else if(x<0x1080) cl->misc7|=1L<<(x&0x1F);
else cl->collisionLayers|=1<<(x&0x1F);
}
static void set_super_class(Class*cl,int ptr) {
Class*su=classes[tokenv&0x3FFF];
int i;
if(ptr || cl->nmsg) ParseError("Cannot specify superclasses before program blocks\n");
if(!su || !(su->cflags&CF_GROUP)) ParseError("Cannot inherit from non-abstract class\n");
cl->codes=malloc(8);
if(!cl->codes) fatal("Allocation failed\n");
cl->codes[0]=OP_SUPER;
cl->codes[1]=tokenv&0x3FFF;
cl->height=su->height;
cl->weight=su->weight;
cl->climb=su->climb;
cl->density=su->density;
cl->volume=su->volume;
cl->strength=su->strength;
cl->arrivals|=su->arrivals;
cl->departures|=su->departures;
cl->temperature=su->temperature;
cl->misc4|=su->misc4;
cl->misc5|=su->misc5;
cl->misc6|=su->misc6;
cl->misc7|=su->misc7;
cl->uservars+=su->uservars;
cl->oflags|=su->oflags;
for(i=0;i<4;i++) {
cl->sharp[i]=su->sharp[i];
cl->hard[i]=su->hard[i];
}
cl->cflags|=su->cflags&(CF_PLAYER|CF_INPUT|CF_COMPATIBLE|CF_QUIZ);
cl->shape=su->shape;
cl->shovable=su->shovable;
cl->collisionLayers|=su->collisionLayers;
if(cl->nmsg=su->nmsg) {
cl->messages=malloc(cl->nmsg*sizeof(Uint16));
if(!cl->messages) fatal("Allocation failed\n");
for(i=0;i<cl->nmsg;i++) cl->messages[i]=(su->messages[i]==0xFFFF)?0xFFFF:0x0000;
}
}
static void class_definition(int cla,sqlite3_stmt*vst) {
Hash*hash=calloc(LOCAL_HASH_SIZE,sizeof(Hash));
Class*cl=classes[cla];
int ptr=0;
int compat=0;
int i;
|
︙ | | | ︙ | |
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
|
case OP_QUIZ: cl->cflags|=CF_QUIZ; break;
case OP_INVISIBLE: cl->oflags|=OF_INVISIBLE; break;
case OP_VISUALONLY: cl->oflags|=OF_VISUALONLY; break;
case OP_STEALTHY: cl->oflags|=OF_STEALTHY; break;
case OP_USERSTATE: cl->oflags|=OF_USERSTATE; break;
case OP_SHOVABLE: cl->shovable=0x55; break;
case OP_USERFLAG: class_user_flag(cl); break;
default: ParseError("Invalid directly inside of a class definition\n");
}
} else if(Tokenf(TF_CLOSE)) {
break;
} else {
ParseError("Invalid directly inside of a class definition\n");
}
}
end_label_stack(cl->codes,hash);
if(!cl->nimages) cl->oflags|=OF_INVISIBLE;
if(main_options['C']) dump_class(cla,ptr,hash);
if(main_options['H']) {
for(i=0;i<LOCAL_HASH_SIZE;i++) if(hash[i].id) printf(" \"%s\": %04X\n",hash[i].txt,hash[i].id);
}
for(i=0;i<LOCAL_HASH_SIZE;i++) {
if(vst && hash[i].id>=0x2000 && hash[i].id<0x2800) {
sqlite3_reset(vst);
sqlite3_bind_int(vst,1,(hash[i].id&0x07FF)|(cla<<16));
sqlite3_bind_text(vst,2,hash[i].txt,-1,free);
while(sqlite3_step(vst)==SQLITE_ROW);
} else {
free(hash[i].txt);
}
}
free(hash);
}
static void load_class_numbers(void) {
int i,n;
long size=0;
unsigned char*data=read_lump(FIL_LEVEL,LUMP_CLASS_DEF,&size);
unsigned char*p;
|
>
>
|
>
>
>
|
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
|
case OP_QUIZ: cl->cflags|=CF_QUIZ; break;
case OP_INVISIBLE: cl->oflags|=OF_INVISIBLE; break;
case OP_VISUALONLY: cl->oflags|=OF_VISUALONLY; break;
case OP_STEALTHY: cl->oflags|=OF_STEALTHY; break;
case OP_USERSTATE: cl->oflags|=OF_USERSTATE; break;
case OP_SHOVABLE: cl->shovable=0x55; break;
case OP_USERFLAG: class_user_flag(cl); break;
case OP_ABSTRACT: cl->cflags|=CF_GROUP; break;
case 0x4000 ... 0x7FFF: set_super_class(cl,ptr); ptr=2; break;
default: ParseError("Invalid directly inside of a class definition\n");
}
} else if(Tokenf(TF_CLOSE)) {
break;
} else {
ParseError("Invalid directly inside of a class definition\n");
}
}
end_label_stack(cl->codes,hash);
if(!cl->nimages && !(cl->cflags&CF_GROUP)) cl->oflags|=OF_INVISIBLE;
if(main_options['C']) dump_class(cla,ptr,hash);
if(main_options['H']) {
for(i=0;i<LOCAL_HASH_SIZE;i++) if(hash[i].id) printf(" \"%s\": %04X\n",hash[i].txt,hash[i].id);
}
for(i=0;i<LOCAL_HASH_SIZE;i++) {
if(vst && hash[i].id>=0x2000 && hash[i].id<0x2800) {
sqlite3_reset(vst);
sqlite3_bind_int(vst,1,(hash[i].id&0x07FF)|(cla<<16));
sqlite3_bind_text(vst,2,hash[i].txt,-1,free);
while(sqlite3_step(vst)==SQLITE_ROW);
} else {
free(hash[i].txt);
}
}
free(hash);
if(cl->cflags&CF_GROUP) {
if(cl->edithelp || cl->gamehelp || cl->nimages) ParseError("Invalid in abstract classes");
}
}
static void load_class_numbers(void) {
int i,n;
long size=0;
unsigned char*data=read_lump(FIL_LEVEL,LUMP_CLASS_DEF,&size);
unsigned char*p;
|
︙ | | | ︙ | |