Beispiel #1
0
void dumpMem1(Cpu_t *cpu)
{
  SYSTEMOUT("dump mem1:");
  uint16_t n;
  for(n=0; n<0x50;n++)SYSTEMOUTHEX(" ",cpu->M[0][n]);
  SYSTEMOUT(" ");
}
Beispiel #2
0
char getCharFromStream()
{
	char c;

#ifdef WITHFILESYSTEM

	if(InputStreamState==GETKEY)c=SYSTEMGETCHAR();
	if(InputStreamState==OPENFILE)
	{
		//InputFile = fopen("test.fs", "r");
		InputFile = fopen(WordBuffer, "r");
		if (InputFile == NULL) {
		    SYSTEMOUT_("file not found: ");
		    SYSTEMOUT_(WordBuffer);
		    InputStreamState=GETKEY;
		}else InputStreamState=READFROMFILE;
	}
	if(InputStreamState==READFROMFILE)
	{
		c=fgetc(InputFile);
		if(c==EOF)
		{
			fclose(InputFile);
			InputStreamState=GETKEY; // switch to keyboard
			SYSTEMOUT("\nok>");
			c=' ';
		}
	}
#else
	c=SYSTEMGETCHAR();
#endif

	return c;
}
Beispiel #3
0
void cpuExternalCall(Cpu_t *cpu)
{
	int32_t command=pop(cpu);
	uint16_t value;

	switch(command)
	{
		case EXTERNAL_C_GETMSTIME:
		{
			push(cpu,updateSysCounter()&0xFFFF); // low counts
			push(cpu,updateSysCounter()>>16); // high counts
		}break;

		case EXTERNAL_C_GETKEY:
		{
			push(cpu,SYSTEMGETCHAR());
			push(cpu,0xFFFF); // true flag for char received
		}break;

		case EXTERNAL_C_PRINTCHAR:
		{
			value=pop(cpu);
			SYSTEMOUTCHAR(value);
		}break;
		case EXTERNAL_C_PRINTNUMBER:
		{
			value=pop(cpu);
			if(Base==10)
			{
				value=(value>0x8000L)? value-(int32_t) 0x10000L:value;
				SYSTEMOUTPRINTNUMBER(value);
			}
			else SYSTEMOUTPRINTHEXNUMBER(value);
		}break;
		case EXTERNAL_C_SETBASE: // set the calculation base
		{
			value=pop(cpu);
			Base=value;
		}break;
		default: SYSTEMOUT("external command not found");break;
	}
}
Beispiel #4
0
void executeVm(Cpu_t *cpu)
{
	uint8_t temp;
	uint8_t command;
	//SYSTEMOUTHEX("adr",cpu->Pc);
	//SYSTEMOUTHEX("flag",cpu->flag);
	command=cpu->M[cpu->Pc];
	cpu->Pc++;
	switch(command)
	{
		// KA 	K->Ar 	 0, 1 	The pressed key from the hex keypad is saved to the A register.
		// If a key is not pressed, the Flag is set to 1, otherwise it is 0.
		case KA:{
		  DISASM("KA   ");
		  if(KEYHIT())
          {
            cpu->M[AR]=GETKEY();
            cpu->flag=0;
            SYSTEMOUTHEX("Key:",cpu->M[AR]);
          }else {
            SYSTEMOUT("nokey");
            cpu->flag=1;
          }
		}break;
		// AO 	Ar->Op 		1 	The 7-segment readout displays the value currently contained in the A register.
		case AO:{
			DISASM("AO   ");
			//show7Segment(cpu->M[AR]);
			DISPLAYOUTHEX(cpu->M[AR]);
			 //PRINT7SEGMENT(x);
			cpu->flag=1;
		}break;
		// CH 	Ar<=>Br
        // Yr<=>Zr 	1 	Exchange the contents of the A and B registers, and the Y and Z registers.
		case CH:{
			DISASM("CH   ");

			temp=cpu->M[AR];
			cpu->M[AR]=cpu->M[BR];
			cpu->M[BR]=temp;
			temp=cpu->M[YR];
			cpu->M[YR]=cpu->M[ZR];
			cpu->M[ZR]=temp;
			cpu->flag=1;
		}break;
		// CY 	Ar<=>Yr 	1 	Exchange the contents of the A and Y registers.
		case CY:{
			DISASM("CY   ");

			temp=cpu->M[AR];
			cpu->M[AR]=cpu->M[YR];
			cpu->M[YR]=temp;
			cpu->flag=1;
		}break;
		// AM 	Ar->M 		1 	Write the contents of the A register to data memory (memory address is 50 + Y register).
		case AM:{
			DISASM("AM   ");

			cpu->M[((cpu->M[YR])&0xF)+M_OFFSET]=cpu->M[AR];
			cpu->flag=1;
		}break;
		// MA 	M->Ar 		1 	Write the contents of data memory (50 + Y register) to the A register.
		case MA:{
			DISASM("MA   ");

			cpu->M[AR]=cpu->M[((cpu->M[YR])&0xF)+M_OFFSET];
			cpu->flag=1;
		}break;
		// M+ 	M+Ar->Ar 	0, 1 	Add the contents of data memory (50 + Y register) to the A register. If there is overflow, the Flag is set to 1, otherwise 0.
		case MPLUS:{
			DISASM("M+   ");

			cpu->M[AR]+=cpu->M[((cpu->M[YR])&0xF)+M_OFFSET];
			if(((cpu->M[AR])&0x10)!=0)cpu->flag=1;
			else cpu->flag=0;
			cpu->M[AR]&=0x0F;
		}break;
		// M- 	M-Ar->Ar 	0, 1 	Subtract the contents of data memory (50 + Y register) from the A register. If the result is negative, the Flag is set to 1, otherwise 0.
		case MMINUS:{
			DISASM("M-   ");

			cpu->M[AR]-=cpu->M[((cpu->M[YR])&0xF)+M_OFFSET];
			if(((cpu->M[AR])&0x10)!=0)cpu->flag=1;
			else cpu->flag=0;
			cpu->M[AR]&=0x0F;
		}break;
		// TIA [ ] 	[ ] -> Ar 	1 	Transfer immediate to the A register.
		case TIA:{
			DISASM("TIA  ");

			cpu->M[AR]=cpu->M[cpu->Pc];
			cpu->Pc++;
			cpu->flag=1;
		}break;
		// AIA [ ] 	Ar + [ ] -> Ar 	0, 1 	Add immediate to the A register. If there is overflow, the Flag is set to 1, otherwise 0.
		case AIA:{
			DISASM("AIA  ");

			cpu->M[AR]+=cpu->M[cpu->Pc];
			if(((cpu->M[AR])&0x10)!=0)cpu->flag=1;
			else cpu->flag=0;
			cpu->M[AR]&=0x0F;
			cpu->Pc++;
		}break;
		// TIY [ ] 	[ ] -> Yr 	1 	Transfer immediate to the Y register.
		case TIY:{
			DISASM("TIA  ");

			cpu->M[YR]=cpu->M[cpu->Pc];
			cpu->Pc++;
			cpu->flag=1;
		}break;
		// AIY [ ] 	Yr + [ ] -> Yr 	0, 1 	Add immediate to the Y register. If there is overflow, the Flag is set to 1, otherwise 0.
		case AIY:{
			DISASM("AIY  ");

			cpu->M[YR]+=cpu->M[cpu->Pc];
			if(((cpu->M[YR])&0x10)!=0)cpu->flag=1;
			else cpu->flag=0;
			cpu->M[YR]&=0x0F;
			cpu->Pc++;
		}break;
		// CIA [ ] 	Ar != [ ] ? 	0, 1 	Compare immediate to the A register. If equal, Flag reset to 0, otherwise set to 1.
		case CIA:{
			DISASM("CIA  ");

			if(cpu->M[AR]!=cpu->M[cpu->Pc])cpu->flag=0;
			else cpu->flag=1;
			cpu->Pc++;
		}break;
		// CIY [ ] 	Yr != [ ] ? 	0, 1 	Compare immediate to the Y register. If equal, Flag reset to 0, otherwise set to 1.
		case CIY:{
			DISASM("CIY  ");

			if(cpu->M[YR]!=cpu->M[cpu->Pc])cpu->flag=0;
			else cpu->flag=1;
			cpu->Pc++;
		}break;
		//JUMP [ ] [ ] 		1 	Jump to the immediate address if the Flag is 1, otherwise just increment the program counter.
		//The Flag is then set to 1. Note that this is an absolute address. That is, JUMP [0] [2] will change the address pointer to hex address 0x02.
		//You can jump both forward and backward in program space.
		case JUMP:{
			DISASM("JUMP ");

			if((cpu->flag)==1)
			{
				temp=cpu->M[cpu->Pc]<<4;
				cpu->Pc++;
				temp+=cpu->M[cpu->Pc]<<4;
				cpu->Pc=temp;
			}else{
				cpu->Pc++;
				cpu->flag=1;
			}
		}break;
		//      --- 	--- 	--- 	Extended code. See table below.
		case EXTENDED:{
			command=(cpu->M[cpu->Pc])|0xE0;
			SYSTEMOUTHEX("com:",command);
			cpu->Pc++;
			if(cpu->flag==1)switch(command)
			{
				case CAL_RSTO:{
					DISASM("CAL_RSTO  ");
					SYSTEMOUTCHAR(' ');
					//SYSTEMOUT("clear 7 seg");
				}break;
				case CAL_SETR:{
					DISASM("CAL_SETR  ");
					cpu->leds|=(1<<(cpu->M[YR]));
					SHOWLEDS(cpu->leds);
					//SYSTEMOUT("led on");
				}break;
				case CAL_RSTR:{
					DISASM("CAL_RSTR  ");
                    cpu->leds&=~(1<<(cpu->M[YR]));
                    SHOWLEDS(cpu->leds);
					//SYSTEMOUT("led off");
				}break;
				// 0xE4 // 	CAL CMPL 	1 	Complement the A register (1 <=> 0).
				case CAL_CMPL:{
					DISASM("CAL_CMPL  ");

					cpu->M[AR]=(~cpu->M[AR])&0x0F;
					cpu->flag=1;
				}break;
				//0xE5 // 	CAL CHNG 	1 	Swap the A/B/Y/Z registers with A'/B'/Y'/Z'
				case CAL_CHNG:{
					DISASM("CAL_CHNG  ");

					temp=cpu->M[AR];
					cpu->M[AR]=cpu->M[AR_];
					cpu->M[AR_]=temp;

					temp=cpu->M[BR];
					cpu->M[BR]=cpu->M[BR_];
					cpu->M[BR_]=temp;

					temp=cpu->M[YR];
					cpu->M[YR]=cpu->M[YR_];
					cpu->M[YR_]=temp;

					temp=cpu->M[ZR];
					cpu->M[ZR]=cpu->M[ZR_];
					cpu->M[ZR_]=temp;

					cpu->flag=1;

				}break;
				// 0xE6 //	CAL SIFT 	0, 1 	Shift the A register right 1 bit. If the starting value is even (bit 0 = 0), set the Flag to 1, otherwise 0.
				case CAL_SIFT:{
					DISASM("CAL_SIFT  ");

					if((cpu->M[AR])&1)cpu->flag=1;
					else cpu->flag=0;
					cpu->M[AR]=(~cpu->M[AR])>>1;
				}break;
				//0xE7 //	CAL ENDS 	1 	Play the End sound.
				case CAL_ENDS:{
					DISASM("CAL_ENDS  ");
					SOUND(NOTE_D6,80);
					SOUND(NOTE_E6,80);
					SOUND(NOTE_F6,80);
					SOUND(NOTE_G6,80);
					SOUND(NOTE_A6,80);
					SOUND(NOTE_B6,80);
				    //soundf(0);
					//SOUND(440,500);
					SYSTEMOUT("end sound");
					cpu->flag=1;
				}break;
				//0xE8 //	CAL ERRS 	1 	Play the Error sound.
				case CAL_ERRS:{
					DISASM("CAL_ERRS  ");
				    for(int n = 0; n < 6; n++)
				    {
				        SOUND(NOTE_G5,20);
				        SOUND(NOTE_A5,20);
				        SOUND(NOTE_B5,20);
				        SOUND(NOTE_C6,20);
				        SOUND(NOTE_D6,20);
				        SOUND(NOTE_E6,20);
				    }
					//SOUND(200,500);
					SYSTEMOUT("play error sound");
					cpu->flag=1;
				}break;
				//0xE9 //	CAL SHTS 	1 	Play a short "pi" sound.
				case CAL_SHTS:{
					DISASM("CAL_SHTS  ");
					SOUND(NOTE_C5,150);
					SYSTEMOUT("play short peep sound");
					cpu->flag=1;
				}break;
				//0xEA //	CAL LONS 	1 	Play a longer "pi-" sound.
				case CAL_LONS:{
					DISASM("CAL_LONS  ");
					SOUND(NOTE_C5,450);
					SYSTEMOUT("play longer peep sound");
					cpu->flag=1;
				}break;
				//0xEB //	CAL SUND 	1 	Play a note based on the value of the A register
				//(allowed values are 1 - E).
				case CAL_SUND:{

					DISASM("CAL_SUND  ");
					//SOUND(cpu->M[AR],500);
					gmcSound(cpu->M[AR],300);

					SYSTEMOUT("play A reg");
					cpu->flag=1;
				}break;
				//0xEC // 	CAL TIMR 	1
				//Pause for the time calculated by (value of A register +1) * 0.1 seconds.
				case CAL_TIMR:{
					DISASM("CAL_TIMR  ");

					showMatrix(((cpu->M[AR])*100+1));

					cpu->flag=1;
				}break;

				//0xED //	CAL DSPR 	1 	Set the 2-pin LEDs with the value from data memory. The data to display is as follows: the upper three bits come from memory address 5F (bits 0-2), and the lower four from memory address 5E (bits 0-3).
				case CAL_DSPR:{
					DISASM("CAL_DSPR  ");

					SYSTEMOUT("set LED");
					cpu->flag=1;
				}break;
				//0xEE // 	CAL DEM- 	1
				//Subtract the value of the A register from the value in data memory.
				//The new value is stored in data memory as a decimal.
				//Afterwards, the Y register is decremented by 1.
				case CAL_DEMMINUS:{
					DISASM("CAL_DEM-  ");

					//SYSTEMOUT("dem-");
					cpu->M[YR]=cpu->M[YR]-cpu->M[AR];
					cpu->M[YR]++;
					cpu->M[YR]&=0xF;
					cpu->flag=1;
				}break;

				//0xEF //	CAL DEM+ 	1
				//Add the value of the A register to the value in data memory.
				//The new value is stored in memory as a decimal.
				//If the result is overflow, data memory will be automatically adjusted.
				//Afterwards, the Y register is decremented.
				case CAL_DEMPLUS:{
					DISASM("CAL_DEM+  ");

					cpu->M[YR]=cpu->M[YR]+cpu->M[AR];
					cpu->M[YR]--;
					cpu->M[YR]&=0xF;
					cpu->flag=1;
				}break;
			}
		}break;

	}
}