Skip to content

Instantly share code, notes, and snippets.

@Manna5
Created November 14, 2020 08:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Manna5/c70eca1b15c9d87ab5c44db296a48217 to your computer and use it in GitHub Desktop.
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)
#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