Created
November 14, 2020 08:45
-
-
Save Manna5/c70eca1b15c9d87ab5c44db296a48217 to your computer and use it in GitHub Desktop.
Mikro Basic Emulator for Modern PCs - version Alpha 14 by Jan Mleczko "Manna5" (CC-BY-SA license)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <string.h> | |
#include <dos.h> | |
unsigned int variables[25]; | |
int for_loop_begin[25]; | |
int for_loop_max_value[25]; | |
int program_counter; | |
char program_memory[20][256]; | |
char ready_msg=1; | |
char continue_running=0; | |
char additional_newline=1; | |
void basic_save(){ | |
FILE* fp; | |
fp=fopen("CASSETTE.DAT","wb"); | |
fwrite(program_memory,256,20,fp); | |
fclose(fp); | |
} | |
void basic_load(){ | |
FILE* fp; | |
fp=fopen("CASSETTE.DAT","rb"); | |
fread(program_memory,256,20,fp); | |
fclose(fp); | |
} | |
void basic_new(){ | |
int i,j; | |
for(i=0;i<20;i++){ | |
for(j=0;j<256;j++){ | |
program_memory[i][j]=0; | |
} | |
} | |
} | |
unsigned int basic_eval(char* expr){ | |
if(!strlen(expr)){ | |
return 0; | |
}if(*expr>='0' && *expr<='9'){ | |
return atoi(expr); | |
}else if(*expr>='A' && *expr<='Z'){ | |
if(strlen(expr)<2){ | |
return variables[*expr-65]; | |
}else{ | |
if(*(expr+1)=='+'){ | |
return variables[*expr-65]+basic_eval(expr+2); | |
}else if(*(expr+1)=='-'){ | |
return variables[*expr-65]-basic_eval(expr+2); | |
}else if(*(expr+1)=='*'){ | |
return variables[*expr-65]*basic_eval(expr+2); | |
}else if(*(expr+1)=='/'){ | |
return variables[*expr-65]/basic_eval(expr+2); | |
} | |
} | |
} | |
} | |
void basic_execute(char* command){ | |
if(*command==' '){ | |
basic_execute(command+1); | |
}else if(!strlen(command)){ | |
}else{ | |
int i; | |
char input_buffer[256]={0}; | |
if(!strncmp(command,"PRINT ",6) && strlen(command)>6){ | |
printf(" %d\n",basic_eval(command+6)); | |
}else if(!strncmp(command,"LET ",4) && *(command+5)=='=' && strlen(command)>6){ | |
variables[*(command+4)-65]=basic_eval(command+6); | |
}else if(!strcmp(command,"CLS")){ | |
system("CLS"); | |
}else if(!strncmp(command,"IF ",3)){ | |
int enable_if=0; | |
if(*(command+4)=='='){ | |
enable_if=variables[*(command+3)-65]==basic_eval(command+5); | |
}else if(*(command+4)=='<'){ | |
enable_if=variables[*(command+3)-65]<basic_eval(command+5); | |
}else if(*(command+4)=='>'){ | |
enable_if=variables[*(command+3)-65]>basic_eval(command+5); | |
} | |
if(enable_if){ | |
basic_execute(strchr(command+4,' ')); | |
} | |
}else if(!strcmp(command,"LIST")){ | |
for(i=0;i<20;i++){ | |
if(strlen(program_memory[i])){ | |
printf(" %d0 %s\n",i+1,program_memory[i]); | |
} | |
} | |
additional_newline=0; | |
}else if(!strcmp(command,"NEW")){ | |
basic_new(); | |
}else if(*(command+1)=='0' && *(command+2)==' ' && *command>='1' && *command<='9'){ | |
strcpy(program_memory[*command-49],command+3); | |
ready_msg=0; | |
}else if(*(command+2)=='0' && *(command+3)==' ' && *command>='1' && *command<='9' && *(command+1)>='0' && *(command+1)<='9'){ | |
strcpy(program_memory[atoi(command)/10-1],command+4); | |
ready_msg=0; | |
}else if(!strncmp(command,"GOTO ",5) && strlen(command)>6){ | |
continue_running=1; | |
for(program_counter=(atoi(command+5)/10)-1;program_counter<20&&continue_running;program_counter++){ | |
basic_execute(program_memory[program_counter]); | |
} | |
continue_running=0; | |
}else if(!strcmp(command,"RUN")){ | |
basic_execute("GOTO 10"); | |
}else if(!strncmp(command,"INPUT ",6) && strlen(command)==7){ | |
printf("%c:",*(command+6)); | |
gets(input_buffer); | |
variables[*(command+6)-65]=atoi(input_buffer); | |
}else if(!strncmp(command,"FOR ",4) && *(command+5)=='='){ | |
variables[*(command+4)-65]=basic_eval(command+6); | |
variables[1]=for_loop_max_value[*(command+4)-65]=basic_eval(strchr(command+5,' ')+4); | |
for_loop_begin[*(command+4)-65]=program_counter+1; | |
}else if(!strncmp(command,"NEXT ",5) && strlen(command)==6){ | |
char simulated_goto[]="GOTO ?00"; | |
if(for_loop_begin[*(command+5)-65]<10){ | |
simulated_goto[5]=49+for_loop_begin[*(command+5)-65]; | |
simulated_goto[7]=0; | |
}else{ | |
simulated_goto[6]=48+((for_loop_begin[*(command+5)-65]+1)%10); | |
simulated_goto[5]=48+((for_loop_begin[*(command+5)-65]+1)/10); | |
} | |
if(variables[*(command+5)-65]<for_loop_max_value[*(command+5)-65]){ | |
variables[*(command+5)-65]++; | |
basic_execute(simulated_goto); | |
} | |
}else if(!strcmp(command,"EXIT")){ | |
exit(0); | |
}else if(!strcmp(command,"SAVE")){ | |
basic_save(); | |
}else if(!strcmp(command,"LOAD")){ | |
basic_load(); | |
}else{ | |
puts("WHAT?\a"); | |
continue_running=0; | |
} | |
} | |
} | |
int main(){ | |
puts("MIKRO BASIC"); | |
additional_newline=0; | |
char command[256]={0}; | |
basic_new(); | |
while(1){ | |
if(ready_msg){ | |
if(additional_newline){ | |
putchar('\n'); | |
}else additional_newline=1; | |
puts("READY"); | |
}else ready_msg=1; | |
putchar('>'); | |
gets(command); | |
if(strlen(command)){ | |
basic_execute(command); | |
} | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment