Asbjorn emulator
This commit is contained in:
parent
c012f508d0
commit
d33ed6be9f
|
@ -0,0 +1,378 @@
|
|||
/** Z80: portable Z80 emulator *******************************/
|
||||
/** **/
|
||||
/** Codes.h **/
|
||||
/** **/
|
||||
/** This file contains implementation for the main table of **/
|
||||
/** Z80 commands. It is included from Z80.c. **/
|
||||
/** **/
|
||||
/** Copyright (C) Marat Fayzullin 1994,1995,1996,1997 **/
|
||||
/** You are not allowed to distribute this software **/
|
||||
/** commercially. Please, notify me, if you make any **/
|
||||
/** changes to this file. **/
|
||||
/*************************************************************/
|
||||
|
||||
case JR_NZ: if(R->AF.B.l&Z_FLAG) R->PC.W++; else { R->ICount-=5;M_JR; } break;
|
||||
case JR_NC: if(R->AF.B.l&C_FLAG) R->PC.W++; else { R->ICount-=5;M_JR; } break;
|
||||
case JR_Z: if(R->AF.B.l&Z_FLAG) { R->ICount-=5;M_JR; } else R->PC.W++; break;
|
||||
case JR_C: if(R->AF.B.l&C_FLAG) { R->ICount-=5;M_JR; } else R->PC.W++; break;
|
||||
|
||||
case JP_NZ: if(R->AF.B.l&Z_FLAG) R->PC.W+=2; else { M_JP; } break;
|
||||
case JP_NC: if(R->AF.B.l&C_FLAG) R->PC.W+=2; else { M_JP; } break;
|
||||
case JP_PO: if(R->AF.B.l&P_FLAG) R->PC.W+=2; else { M_JP; } break;
|
||||
case JP_P: if(R->AF.B.l&S_FLAG) R->PC.W+=2; else { M_JP; } break;
|
||||
case JP_Z: if(R->AF.B.l&Z_FLAG) { M_JP; } else R->PC.W+=2; break;
|
||||
case JP_C: if(R->AF.B.l&C_FLAG) { M_JP; } else R->PC.W+=2; break;
|
||||
case JP_PE: if(R->AF.B.l&P_FLAG) { M_JP; } else R->PC.W+=2; break;
|
||||
case JP_M: if(R->AF.B.l&S_FLAG) { M_JP; } else R->PC.W+=2; break;
|
||||
|
||||
case RET_NZ: if(!(R->AF.B.l&Z_FLAG)) { R->ICount-=6;M_RET; } break;
|
||||
case RET_NC: if(!(R->AF.B.l&C_FLAG)) { R->ICount-=6;M_RET; } break;
|
||||
case RET_PO: if(!(R->AF.B.l&P_FLAG)) { R->ICount-=6;M_RET; } break;
|
||||
case RET_P: if(!(R->AF.B.l&S_FLAG)) { R->ICount-=6;M_RET; } break;
|
||||
case RET_Z: if(R->AF.B.l&Z_FLAG) { R->ICount-=6;M_RET; } break;
|
||||
case RET_C: if(R->AF.B.l&C_FLAG) { R->ICount-=6;M_RET; } break;
|
||||
case RET_PE: if(R->AF.B.l&P_FLAG) { R->ICount-=6;M_RET; } break;
|
||||
case RET_M: if(R->AF.B.l&S_FLAG) { R->ICount-=6;M_RET; } break;
|
||||
|
||||
case CALL_NZ: if(R->AF.B.l&Z_FLAG) R->PC.W+=2; else { R->ICount-=7;M_CALL; } break;
|
||||
case CALL_NC: if(R->AF.B.l&C_FLAG) R->PC.W+=2; else { R->ICount-=7;M_CALL; } break;
|
||||
case CALL_PO: if(R->AF.B.l&P_FLAG) R->PC.W+=2; else { R->ICount-=7;M_CALL; } break;
|
||||
case CALL_P: if(R->AF.B.l&S_FLAG) R->PC.W+=2; else { R->ICount-=7;M_CALL; } break;
|
||||
case CALL_Z: if(R->AF.B.l&Z_FLAG) { R->ICount-=7;M_CALL; } else R->PC.W+=2; break;
|
||||
case CALL_C: if(R->AF.B.l&C_FLAG) { R->ICount-=7;M_CALL; } else R->PC.W+=2; break;
|
||||
case CALL_PE: if(R->AF.B.l&P_FLAG) { R->ICount-=7;M_CALL; } else R->PC.W+=2; break;
|
||||
case CALL_M: if(R->AF.B.l&S_FLAG) { R->ICount-=7;M_CALL; } else R->PC.W+=2; break;
|
||||
|
||||
case ADD_B: M_ADD(R->BC.B.h);break;
|
||||
case ADD_C: M_ADD(R->BC.B.l);break;
|
||||
case ADD_D: M_ADD(R->DE.B.h);break;
|
||||
case ADD_E: M_ADD(R->DE.B.l);break;
|
||||
case ADD_H: M_ADD(R->HL.B.h);break;
|
||||
case ADD_L: M_ADD(R->HL.B.l);break;
|
||||
case ADD_A: M_ADD(R->AF.B.h);break;
|
||||
case ADD_xHL: I=RdZ80(R->HL.W);M_ADD(I);break;
|
||||
case ADD_BYTE: I=RdZ80(R->PC.W++);M_ADD(I);break;
|
||||
|
||||
case SUB_B: M_SUB(R->BC.B.h);break;
|
||||
case SUB_C: M_SUB(R->BC.B.l);break;
|
||||
case SUB_D: M_SUB(R->DE.B.h);break;
|
||||
case SUB_E: M_SUB(R->DE.B.l);break;
|
||||
case SUB_H: M_SUB(R->HL.B.h);break;
|
||||
case SUB_L: M_SUB(R->HL.B.l);break;
|
||||
case SUB_A: R->AF.B.h=0;R->AF.B.l=N_FLAG|Z_FLAG;break;
|
||||
case SUB_xHL: I=RdZ80(R->HL.W);M_SUB(I);break;
|
||||
case SUB_BYTE: I=RdZ80(R->PC.W++);M_SUB(I);break;
|
||||
|
||||
case AND_B: M_AND(R->BC.B.h);break;
|
||||
case AND_C: M_AND(R->BC.B.l);break;
|
||||
case AND_D: M_AND(R->DE.B.h);break;
|
||||
case AND_E: M_AND(R->DE.B.l);break;
|
||||
case AND_H: M_AND(R->HL.B.h);break;
|
||||
case AND_L: M_AND(R->HL.B.l);break;
|
||||
case AND_A: M_AND(R->AF.B.h);break;
|
||||
case AND_xHL: I=RdZ80(R->HL.W);M_AND(I);break;
|
||||
case AND_BYTE: I=RdZ80(R->PC.W++);M_AND(I);break;
|
||||
|
||||
case OR_B: M_OR(R->BC.B.h);break;
|
||||
case OR_C: M_OR(R->BC.B.l);break;
|
||||
case OR_D: M_OR(R->DE.B.h);break;
|
||||
case OR_E: M_OR(R->DE.B.l);break;
|
||||
case OR_H: M_OR(R->HL.B.h);break;
|
||||
case OR_L: M_OR(R->HL.B.l);break;
|
||||
case OR_A: M_OR(R->AF.B.h);break;
|
||||
case OR_xHL: I=RdZ80(R->HL.W);M_OR(I);break;
|
||||
case OR_BYTE: I=RdZ80(R->PC.W++);M_OR(I);break;
|
||||
|
||||
case ADC_B: M_ADC(R->BC.B.h);break;
|
||||
case ADC_C: M_ADC(R->BC.B.l);break;
|
||||
case ADC_D: M_ADC(R->DE.B.h);break;
|
||||
case ADC_E: M_ADC(R->DE.B.l);break;
|
||||
case ADC_H: M_ADC(R->HL.B.h);break;
|
||||
case ADC_L: M_ADC(R->HL.B.l);break;
|
||||
case ADC_A: M_ADC(R->AF.B.h);break;
|
||||
case ADC_xHL: I=RdZ80(R->HL.W);M_ADC(I);break;
|
||||
case ADC_BYTE: I=RdZ80(R->PC.W++);M_ADC(I);break;
|
||||
|
||||
case SBC_B: M_SBC(R->BC.B.h);break;
|
||||
case SBC_C: M_SBC(R->BC.B.l);break;
|
||||
case SBC_D: M_SBC(R->DE.B.h);break;
|
||||
case SBC_E: M_SBC(R->DE.B.l);break;
|
||||
case SBC_H: M_SBC(R->HL.B.h);break;
|
||||
case SBC_L: M_SBC(R->HL.B.l);break;
|
||||
case SBC_A: M_SBC(R->AF.B.h);break;
|
||||
case SBC_xHL: I=RdZ80(R->HL.W);M_SBC(I);break;
|
||||
case SBC_BYTE: I=RdZ80(R->PC.W++);M_SBC(I);break;
|
||||
|
||||
case XOR_B: M_XOR(R->BC.B.h);break;
|
||||
case XOR_C: M_XOR(R->BC.B.l);break;
|
||||
case XOR_D: M_XOR(R->DE.B.h);break;
|
||||
case XOR_E: M_XOR(R->DE.B.l);break;
|
||||
case XOR_H: M_XOR(R->HL.B.h);break;
|
||||
case XOR_L: M_XOR(R->HL.B.l);break;
|
||||
case XOR_A: R->AF.B.h=0;R->AF.B.l=P_FLAG|Z_FLAG;break;
|
||||
case XOR_xHL: I=RdZ80(R->HL.W);M_XOR(I);break;
|
||||
case XOR_BYTE: I=RdZ80(R->PC.W++);M_XOR(I);break;
|
||||
|
||||
case CP_B: M_CP(R->BC.B.h);break;
|
||||
case CP_C: M_CP(R->BC.B.l);break;
|
||||
case CP_D: M_CP(R->DE.B.h);break;
|
||||
case CP_E: M_CP(R->DE.B.l);break;
|
||||
case CP_H: M_CP(R->HL.B.h);break;
|
||||
case CP_L: M_CP(R->HL.B.l);break;
|
||||
case CP_A: R->AF.B.l=N_FLAG|Z_FLAG;break;
|
||||
case CP_xHL: I=RdZ80(R->HL.W);M_CP(I);break;
|
||||
case CP_BYTE: I=RdZ80(R->PC.W++);M_CP(I);break;
|
||||
|
||||
case LD_BC_WORD: M_LDWORD(BC);break;
|
||||
case LD_DE_WORD: M_LDWORD(DE);break;
|
||||
case LD_HL_WORD: M_LDWORD(HL);break;
|
||||
case LD_SP_WORD: M_LDWORD(SP);break;
|
||||
|
||||
case LD_PC_HL: R->PC.W=R->HL.W;break;
|
||||
case LD_SP_HL: R->SP.W=R->HL.W;break;
|
||||
case LD_A_xBC: R->AF.B.h=RdZ80(R->BC.W);break;
|
||||
case LD_A_xDE: R->AF.B.h=RdZ80(R->DE.W);break;
|
||||
|
||||
case ADD_HL_BC: M_ADDW(HL,BC);break;
|
||||
case ADD_HL_DE: M_ADDW(HL,DE);break;
|
||||
case ADD_HL_HL: M_ADDW(HL,HL);break;
|
||||
case ADD_HL_SP: M_ADDW(HL,SP);break;
|
||||
|
||||
case DEC_BC: R->BC.W--;break;
|
||||
case DEC_DE: R->DE.W--;break;
|
||||
case DEC_HL: R->HL.W--;break;
|
||||
case DEC_SP: R->SP.W--;break;
|
||||
|
||||
case INC_BC: R->BC.W++;break;
|
||||
case INC_DE: R->DE.W++;break;
|
||||
case INC_HL: R->HL.W++;break;
|
||||
case INC_SP: R->SP.W++;break;
|
||||
|
||||
case DEC_B: M_DEC(R->BC.B.h);break;
|
||||
case DEC_C: M_DEC(R->BC.B.l);break;
|
||||
case DEC_D: M_DEC(R->DE.B.h);break;
|
||||
case DEC_E: M_DEC(R->DE.B.l);break;
|
||||
case DEC_H: M_DEC(R->HL.B.h);break;
|
||||
case DEC_L: M_DEC(R->HL.B.l);break;
|
||||
case DEC_A: M_DEC(R->AF.B.h);break;
|
||||
case DEC_xHL: I=RdZ80(R->HL.W);M_DEC(I);WrZ80(R->HL.W,I);break;
|
||||
|
||||
case INC_B: M_INC(R->BC.B.h);break;
|
||||
case INC_C: M_INC(R->BC.B.l);break;
|
||||
case INC_D: M_INC(R->DE.B.h);break;
|
||||
case INC_E: M_INC(R->DE.B.l);break;
|
||||
case INC_H: M_INC(R->HL.B.h);break;
|
||||
case INC_L: M_INC(R->HL.B.l);break;
|
||||
case INC_A: M_INC(R->AF.B.h);break;
|
||||
case INC_xHL: I=RdZ80(R->HL.W);M_INC(I);WrZ80(R->HL.W,I);break;
|
||||
|
||||
case RLCA:
|
||||
I=R->AF.B.h&0x80? C_FLAG:0;
|
||||
R->AF.B.h=(R->AF.B.h<<1)|I;
|
||||
R->AF.B.l=(R->AF.B.l&~(C_FLAG|N_FLAG|H_FLAG))|I;
|
||||
break;
|
||||
case RLA:
|
||||
I=R->AF.B.h&0x80? C_FLAG:0;
|
||||
R->AF.B.h=(R->AF.B.h<<1)|(R->AF.B.l&C_FLAG);
|
||||
R->AF.B.l=(R->AF.B.l&~(C_FLAG|N_FLAG|H_FLAG))|I;
|
||||
break;
|
||||
case RRCA:
|
||||
I=R->AF.B.h&0x01;
|
||||
R->AF.B.h=(R->AF.B.h>>1)|(I? 0x80:0);
|
||||
R->AF.B.l=(R->AF.B.l&~(C_FLAG|N_FLAG|H_FLAG))|I;
|
||||
break;
|
||||
case RRA:
|
||||
I=R->AF.B.h&0x01;
|
||||
R->AF.B.h=(R->AF.B.h>>1)|(R->AF.B.l&C_FLAG? 0x80:0);
|
||||
R->AF.B.l=(R->AF.B.l&~(C_FLAG|N_FLAG|H_FLAG))|I;
|
||||
break;
|
||||
|
||||
case RST00: M_RST(0x0000);break;
|
||||
case RST08: M_RST(0x0008);break;
|
||||
case RST10: M_RST(0x0010);break;
|
||||
case RST18: M_RST(0x0018);break;
|
||||
case RST20: M_RST(0x0020);break;
|
||||
case RST28: M_RST(0x0028);break;
|
||||
case RST30: M_RST(0x0030);break;
|
||||
case RST38: M_RST(0x0038);break;
|
||||
|
||||
case PUSH_BC: M_PUSH(BC);break;
|
||||
case PUSH_DE: M_PUSH(DE);break;
|
||||
case PUSH_HL: M_PUSH(HL);break;
|
||||
case PUSH_AF: M_PUSH(AF);break;
|
||||
|
||||
case POP_BC: M_POP(BC);break;
|
||||
case POP_DE: M_POP(DE);break;
|
||||
case POP_HL: M_POP(HL);break;
|
||||
case POP_AF: M_POP(AF);break;
|
||||
|
||||
case DJNZ: if(--R->BC.B.h) { M_JR; } else R->PC.W++;break;
|
||||
case JP: M_JP;break;
|
||||
case JR: M_JR;break;
|
||||
case CALL: M_CALL;break;
|
||||
case RET: M_RET;break;
|
||||
case SCF: S(C_FLAG);R(N_FLAG|H_FLAG);break;
|
||||
case CPL: R->AF.B.h=~R->AF.B.h;S(N_FLAG|H_FLAG);break;
|
||||
case NOP: break;
|
||||
case OUTA: OutZ80(RdZ80(R->PC.W++),R->AF.B.h);break;
|
||||
case INA: R->AF.B.h=InZ80(RdZ80(R->PC.W++));break;
|
||||
case HALT: R->PC.W--;R->IFF|=0x80;R->ICount=0;break;
|
||||
|
||||
case DI:
|
||||
R->IFF&=0xFE;
|
||||
break;
|
||||
case EI:
|
||||
R->IFF|=0x01;
|
||||
if(R->IRequest!=INT_NONE)
|
||||
{
|
||||
R->IFF|=0x20;
|
||||
R->IBackup=R->ICount;
|
||||
R->ICount=1;
|
||||
}
|
||||
break;
|
||||
|
||||
case CCF:
|
||||
R->AF.B.l^=C_FLAG;R(N_FLAG|H_FLAG);
|
||||
R->AF.B.l|=R->AF.B.l&C_FLAG? 0:H_FLAG;
|
||||
break;
|
||||
|
||||
case EXX:
|
||||
J.W=R->BC.W;R->BC.W=R->BC1.W;R->BC1.W=J.W;
|
||||
J.W=R->DE.W;R->DE.W=R->DE1.W;R->DE1.W=J.W;
|
||||
J.W=R->HL.W;R->HL.W=R->HL1.W;R->HL1.W=J.W;
|
||||
break;
|
||||
|
||||
case EX_DE_HL: J.W=R->DE.W;R->DE.W=R->HL.W;R->HL.W=J.W;break;
|
||||
case EX_AF_AF: J.W=R->AF.W;R->AF.W=R->AF1.W;R->AF1.W=J.W;break;
|
||||
|
||||
case LD_B_B: R->BC.B.h=R->BC.B.h;break;
|
||||
case LD_C_B: R->BC.B.l=R->BC.B.h;break;
|
||||
case LD_D_B: R->DE.B.h=R->BC.B.h;break;
|
||||
case LD_E_B: R->DE.B.l=R->BC.B.h;break;
|
||||
case LD_H_B: R->HL.B.h=R->BC.B.h;break;
|
||||
case LD_L_B: R->HL.B.l=R->BC.B.h;break;
|
||||
case LD_A_B: R->AF.B.h=R->BC.B.h;break;
|
||||
case LD_xHL_B: WrZ80(R->HL.W,R->BC.B.h);break;
|
||||
|
||||
case LD_B_C: R->BC.B.h=R->BC.B.l;break;
|
||||
case LD_C_C: R->BC.B.l=R->BC.B.l;break;
|
||||
case LD_D_C: R->DE.B.h=R->BC.B.l;break;
|
||||
case LD_E_C: R->DE.B.l=R->BC.B.l;break;
|
||||
case LD_H_C: R->HL.B.h=R->BC.B.l;break;
|
||||
case LD_L_C: R->HL.B.l=R->BC.B.l;break;
|
||||
case LD_A_C: R->AF.B.h=R->BC.B.l;break;
|
||||
case LD_xHL_C: WrZ80(R->HL.W,R->BC.B.l);break;
|
||||
|
||||
case LD_B_D: R->BC.B.h=R->DE.B.h;break;
|
||||
case LD_C_D: R->BC.B.l=R->DE.B.h;break;
|
||||
case LD_D_D: R->DE.B.h=R->DE.B.h;break;
|
||||
case LD_E_D: R->DE.B.l=R->DE.B.h;break;
|
||||
case LD_H_D: R->HL.B.h=R->DE.B.h;break;
|
||||
case LD_L_D: R->HL.B.l=R->DE.B.h;break;
|
||||
case LD_A_D: R->AF.B.h=R->DE.B.h;break;
|
||||
case LD_xHL_D: WrZ80(R->HL.W,R->DE.B.h);break;
|
||||
|
||||
case LD_B_E: R->BC.B.h=R->DE.B.l;break;
|
||||
case LD_C_E: R->BC.B.l=R->DE.B.l;break;
|
||||
case LD_D_E: R->DE.B.h=R->DE.B.l;break;
|
||||
case LD_E_E: R->DE.B.l=R->DE.B.l;break;
|
||||
case LD_H_E: R->HL.B.h=R->DE.B.l;break;
|
||||
case LD_L_E: R->HL.B.l=R->DE.B.l;break;
|
||||
case LD_A_E: R->AF.B.h=R->DE.B.l;break;
|
||||
case LD_xHL_E: WrZ80(R->HL.W,R->DE.B.l);break;
|
||||
|
||||
case LD_B_H: R->BC.B.h=R->HL.B.h;break;
|
||||
case LD_C_H: R->BC.B.l=R->HL.B.h;break;
|
||||
case LD_D_H: R->DE.B.h=R->HL.B.h;break;
|
||||
case LD_E_H: R->DE.B.l=R->HL.B.h;break;
|
||||
case LD_H_H: R->HL.B.h=R->HL.B.h;break;
|
||||
case LD_L_H: R->HL.B.l=R->HL.B.h;break;
|
||||
case LD_A_H: R->AF.B.h=R->HL.B.h;break;
|
||||
case LD_xHL_H: WrZ80(R->HL.W,R->HL.B.h);break;
|
||||
|
||||
case LD_B_L: R->BC.B.h=R->HL.B.l;break;
|
||||
case LD_C_L: R->BC.B.l=R->HL.B.l;break;
|
||||
case LD_D_L: R->DE.B.h=R->HL.B.l;break;
|
||||
case LD_E_L: R->DE.B.l=R->HL.B.l;break;
|
||||
case LD_H_L: R->HL.B.h=R->HL.B.l;break;
|
||||
case LD_L_L: R->HL.B.l=R->HL.B.l;break;
|
||||
case LD_A_L: R->AF.B.h=R->HL.B.l;break;
|
||||
case LD_xHL_L: WrZ80(R->HL.W,R->HL.B.l);break;
|
||||
|
||||
case LD_B_A: R->BC.B.h=R->AF.B.h;break;
|
||||
case LD_C_A: R->BC.B.l=R->AF.B.h;break;
|
||||
case LD_D_A: R->DE.B.h=R->AF.B.h;break;
|
||||
case LD_E_A: R->DE.B.l=R->AF.B.h;break;
|
||||
case LD_H_A: R->HL.B.h=R->AF.B.h;break;
|
||||
case LD_L_A: R->HL.B.l=R->AF.B.h;break;
|
||||
case LD_A_A: R->AF.B.h=R->AF.B.h;break;
|
||||
case LD_xHL_A: WrZ80(R->HL.W,R->AF.B.h);break;
|
||||
|
||||
case LD_xBC_A: WrZ80(R->BC.W,R->AF.B.h);break;
|
||||
case LD_xDE_A: WrZ80(R->DE.W,R->AF.B.h);break;
|
||||
|
||||
case LD_B_xHL: R->BC.B.h=RdZ80(R->HL.W);break;
|
||||
case LD_C_xHL: R->BC.B.l=RdZ80(R->HL.W);break;
|
||||
case LD_D_xHL: R->DE.B.h=RdZ80(R->HL.W);break;
|
||||
case LD_E_xHL: R->DE.B.l=RdZ80(R->HL.W);break;
|
||||
case LD_H_xHL: R->HL.B.h=RdZ80(R->HL.W);break;
|
||||
case LD_L_xHL: R->HL.B.l=RdZ80(R->HL.W);break;
|
||||
case LD_A_xHL: R->AF.B.h=RdZ80(R->HL.W);break;
|
||||
|
||||
case LD_B_BYTE: R->BC.B.h=RdZ80(R->PC.W++);break;
|
||||
case LD_C_BYTE: R->BC.B.l=RdZ80(R->PC.W++);break;
|
||||
case LD_D_BYTE: R->DE.B.h=RdZ80(R->PC.W++);break;
|
||||
case LD_E_BYTE: R->DE.B.l=RdZ80(R->PC.W++);break;
|
||||
case LD_H_BYTE: R->HL.B.h=RdZ80(R->PC.W++);break;
|
||||
case LD_L_BYTE: R->HL.B.l=RdZ80(R->PC.W++);break;
|
||||
case LD_A_BYTE: R->AF.B.h=RdZ80(R->PC.W++);break;
|
||||
case LD_xHL_BYTE: WrZ80(R->HL.W,RdZ80(R->PC.W++));break;
|
||||
|
||||
case LD_xWORD_HL:
|
||||
J.B.l=RdZ80(R->PC.W++);
|
||||
J.B.h=RdZ80(R->PC.W++);
|
||||
WrZ80(J.W++,R->HL.B.l);
|
||||
WrZ80(J.W,R->HL.B.h);
|
||||
break;
|
||||
|
||||
case LD_HL_xWORD:
|
||||
J.B.l=RdZ80(R->PC.W++);
|
||||
J.B.h=RdZ80(R->PC.W++);
|
||||
R->HL.B.l=RdZ80(J.W++);
|
||||
R->HL.B.h=RdZ80(J.W);
|
||||
break;
|
||||
|
||||
case LD_A_xWORD:
|
||||
J.B.l=RdZ80(R->PC.W++);
|
||||
J.B.h=RdZ80(R->PC.W++);
|
||||
R->AF.B.h=RdZ80(J.W);
|
||||
break;
|
||||
|
||||
case LD_xWORD_A:
|
||||
J.B.l=RdZ80(R->PC.W++);
|
||||
J.B.h=RdZ80(R->PC.W++);
|
||||
WrZ80(J.W,R->AF.B.h);
|
||||
break;
|
||||
|
||||
case EX_HL_xSP:
|
||||
J.B.l=RdZ80(R->SP.W);WrZ80(R->SP.W++,R->HL.B.l);
|
||||
J.B.h=RdZ80(R->SP.W);WrZ80(R->SP.W--,R->HL.B.h);
|
||||
R->HL.W=J.W;
|
||||
break;
|
||||
|
||||
case DAA:
|
||||
J.W=R->AF.B.h;
|
||||
if(R->AF.B.l&C_FLAG) J.W|=256;
|
||||
if(R->AF.B.l&H_FLAG) J.W|=512;
|
||||
if(R->AF.B.l&N_FLAG) J.W|=1024;
|
||||
R->AF.W=DAATable[J.W];
|
||||
break;
|
||||
|
||||
default:
|
||||
if(R->TrapBadOps)
|
||||
printf
|
||||
(
|
||||
"[Z80 %lX] Unrecognized instruction: %02X at PC=%04X\n",
|
||||
(long)R->User,RdZ80(R->PC.W-1),R->PC.W-1
|
||||
);
|
||||
break;
|
|
@ -0,0 +1,204 @@
|
|||
/** Z80: portable Z80 emulator *******************************/
|
||||
/** **/
|
||||
/** CodesCB.h **/
|
||||
/** **/
|
||||
/** This file contains implementation for the CB table of **/
|
||||
/** Z80 commands. It is included from Z80.c. **/
|
||||
/** **/
|
||||
/** Copyright (C) Marat Fayzullin 1994,1995,1996,1997 **/
|
||||
/** You are not allowed to distribute this software **/
|
||||
/** commercially. Please, notify me, if you make any **/
|
||||
/** changes to this file. **/
|
||||
/*************************************************************/
|
||||
|
||||
case RLC_B: M_RLC(R->BC.B.h);break; case RLC_C: M_RLC(R->BC.B.l);break;
|
||||
case RLC_D: M_RLC(R->DE.B.h);break; case RLC_E: M_RLC(R->DE.B.l);break;
|
||||
case RLC_H: M_RLC(R->HL.B.h);break; case RLC_L: M_RLC(R->HL.B.l);break;
|
||||
case RLC_xHL: I=RdZ80(R->HL.W);M_RLC(I);WrZ80(R->HL.W,I);break;
|
||||
case RLC_A: M_RLC(R->AF.B.h);break;
|
||||
|
||||
case RRC_B: M_RRC(R->BC.B.h);break; case RRC_C: M_RRC(R->BC.B.l);break;
|
||||
case RRC_D: M_RRC(R->DE.B.h);break; case RRC_E: M_RRC(R->DE.B.l);break;
|
||||
case RRC_H: M_RRC(R->HL.B.h);break; case RRC_L: M_RRC(R->HL.B.l);break;
|
||||
case RRC_xHL: I=RdZ80(R->HL.W);M_RRC(I);WrZ80(R->HL.W,I);break;
|
||||
case RRC_A: M_RRC(R->AF.B.h);break;
|
||||
|
||||
case RL_B: M_RL(R->BC.B.h);break; case RL_C: M_RL(R->BC.B.l);break;
|
||||
case RL_D: M_RL(R->DE.B.h);break; case RL_E: M_RL(R->DE.B.l);break;
|
||||
case RL_H: M_RL(R->HL.B.h);break; case RL_L: M_RL(R->HL.B.l);break;
|
||||
case RL_xHL: I=RdZ80(R->HL.W);M_RL(I);WrZ80(R->HL.W,I);break;
|
||||
case RL_A: M_RL(R->AF.B.h);break;
|
||||
|
||||
case RR_B: M_RR(R->BC.B.h);break; case RR_C: M_RR(R->BC.B.l);break;
|
||||
case RR_D: M_RR(R->DE.B.h);break; case RR_E: M_RR(R->DE.B.l);break;
|
||||
case RR_H: M_RR(R->HL.B.h);break; case RR_L: M_RR(R->HL.B.l);break;
|
||||
case RR_xHL: I=RdZ80(R->HL.W);M_RR(I);WrZ80(R->HL.W,I);break;
|
||||
case RR_A: M_RR(R->AF.B.h);break;
|
||||
|
||||
case SLA_B: M_SLA(R->BC.B.h);break; case SLA_C: M_SLA(R->BC.B.l);break;
|
||||
case SLA_D: M_SLA(R->DE.B.h);break; case SLA_E: M_SLA(R->DE.B.l);break;
|
||||
case SLA_H: M_SLA(R->HL.B.h);break; case SLA_L: M_SLA(R->HL.B.l);break;
|
||||
case SLA_xHL: I=RdZ80(R->HL.W);M_SLA(I);WrZ80(R->HL.W,I);break;
|
||||
case SLA_A: M_SLA(R->AF.B.h);break;
|
||||
|
||||
case SRA_B: M_SRA(R->BC.B.h);break; case SRA_C: M_SRA(R->BC.B.l);break;
|
||||
case SRA_D: M_SRA(R->DE.B.h);break; case SRA_E: M_SRA(R->DE.B.l);break;
|
||||
case SRA_H: M_SRA(R->HL.B.h);break; case SRA_L: M_SRA(R->HL.B.l);break;
|
||||
case SRA_xHL: I=RdZ80(R->HL.W);M_SRA(I);WrZ80(R->HL.W,I);break;
|
||||
case SRA_A: M_SRA(R->AF.B.h);break;
|
||||
|
||||
case SLL_B: M_SLL(R->BC.B.h);break; case SLL_C: M_SLL(R->BC.B.l);break;
|
||||
case SLL_D: M_SLL(R->DE.B.h);break; case SLL_E: M_SLL(R->DE.B.l);break;
|
||||
case SLL_H: M_SLL(R->HL.B.h);break; case SLL_L: M_SLL(R->HL.B.l);break;
|
||||
case SLL_xHL: I=RdZ80(R->HL.W);M_SLL(I);WrZ80(R->HL.W,I);break;
|
||||
case SLL_A: M_SLL(R->AF.B.h);break;
|
||||
|
||||
case SRL_B: M_SRL(R->BC.B.h);break; case SRL_C: M_SRL(R->BC.B.l);break;
|
||||
case SRL_D: M_SRL(R->DE.B.h);break; case SRL_E: M_SRL(R->DE.B.l);break;
|
||||
case SRL_H: M_SRL(R->HL.B.h);break; case SRL_L: M_SRL(R->HL.B.l);break;
|
||||
case SRL_xHL: I=RdZ80(R->HL.W);M_SRL(I);WrZ80(R->HL.W,I);break;
|
||||
case SRL_A: M_SRL(R->AF.B.h);break;
|
||||
|
||||
case BIT0_B: M_BIT(0,R->BC.B.h);break; case BIT0_C: M_BIT(0,R->BC.B.l);break;
|
||||
case BIT0_D: M_BIT(0,R->DE.B.h);break; case BIT0_E: M_BIT(0,R->DE.B.l);break;
|
||||
case BIT0_H: M_BIT(0,R->HL.B.h);break; case BIT0_L: M_BIT(0,R->HL.B.l);break;
|
||||
case BIT0_xHL: I=RdZ80(R->HL.W);M_BIT(0,I);break;
|
||||
case BIT0_A: M_BIT(0,R->AF.B.h);break;
|
||||
|
||||
case BIT1_B: M_BIT(1,R->BC.B.h);break; case BIT1_C: M_BIT(1,R->BC.B.l);break;
|
||||
case BIT1_D: M_BIT(1,R->DE.B.h);break; case BIT1_E: M_BIT(1,R->DE.B.l);break;
|
||||
case BIT1_H: M_BIT(1,R->HL.B.h);break; case BIT1_L: M_BIT(1,R->HL.B.l);break;
|
||||
case BIT1_xHL: I=RdZ80(R->HL.W);M_BIT(1,I);break;
|
||||
case BIT1_A: M_BIT(1,R->AF.B.h);break;
|
||||
|
||||
case BIT2_B: M_BIT(2,R->BC.B.h);break; case BIT2_C: M_BIT(2,R->BC.B.l);break;
|
||||
case BIT2_D: M_BIT(2,R->DE.B.h);break; case BIT2_E: M_BIT(2,R->DE.B.l);break;
|
||||
case BIT2_H: M_BIT(2,R->HL.B.h);break; case BIT2_L: M_BIT(2,R->HL.B.l);break;
|
||||
case BIT2_xHL: I=RdZ80(R->HL.W);M_BIT(2,I);break;
|
||||
case BIT2_A: M_BIT(2,R->AF.B.h);break;
|
||||
|
||||
case BIT3_B: M_BIT(3,R->BC.B.h);break; case BIT3_C: M_BIT(3,R->BC.B.l);break;
|
||||
case BIT3_D: M_BIT(3,R->DE.B.h);break; case BIT3_E: M_BIT(3,R->DE.B.l);break;
|
||||
case BIT3_H: M_BIT(3,R->HL.B.h);break; case BIT3_L: M_BIT(3,R->HL.B.l);break;
|
||||
case BIT3_xHL: I=RdZ80(R->HL.W);M_BIT(3,I);break;
|
||||
case BIT3_A: M_BIT(3,R->AF.B.h);break;
|
||||
|
||||
case BIT4_B: M_BIT(4,R->BC.B.h);break; case BIT4_C: M_BIT(4,R->BC.B.l);break;
|
||||
case BIT4_D: M_BIT(4,R->DE.B.h);break; case BIT4_E: M_BIT(4,R->DE.B.l);break;
|
||||
case BIT4_H: M_BIT(4,R->HL.B.h);break; case BIT4_L: M_BIT(4,R->HL.B.l);break;
|
||||
case BIT4_xHL: I=RdZ80(R->HL.W);M_BIT(4,I);break;
|
||||
case BIT4_A: M_BIT(4,R->AF.B.h);break;
|
||||
|
||||
case BIT5_B: M_BIT(5,R->BC.B.h);break; case BIT5_C: M_BIT(5,R->BC.B.l);break;
|
||||
case BIT5_D: M_BIT(5,R->DE.B.h);break; case BIT5_E: M_BIT(5,R->DE.B.l);break;
|
||||
case BIT5_H: M_BIT(5,R->HL.B.h);break; case BIT5_L: M_BIT(5,R->HL.B.l);break;
|
||||
case BIT5_xHL: I=RdZ80(R->HL.W);M_BIT(5,I);break;
|
||||
case BIT5_A: M_BIT(5,R->AF.B.h);break;
|
||||
|
||||
case BIT6_B: M_BIT(6,R->BC.B.h);break; case BIT6_C: M_BIT(6,R->BC.B.l);break;
|
||||
case BIT6_D: M_BIT(6,R->DE.B.h);break; case BIT6_E: M_BIT(6,R->DE.B.l);break;
|
||||
case BIT6_H: M_BIT(6,R->HL.B.h);break; case BIT6_L: M_BIT(6,R->HL.B.l);break;
|
||||
case BIT6_xHL: I=RdZ80(R->HL.W);M_BIT(6,I);break;
|
||||
case BIT6_A: M_BIT(6,R->AF.B.h);break;
|
||||
|
||||
case BIT7_B: M_BIT(7,R->BC.B.h);break; case BIT7_C: M_BIT(7,R->BC.B.l);break;
|
||||
case BIT7_D: M_BIT(7,R->DE.B.h);break; case BIT7_E: M_BIT(7,R->DE.B.l);break;
|
||||
case BIT7_H: M_BIT(7,R->HL.B.h);break; case BIT7_L: M_BIT(7,R->HL.B.l);break;
|
||||
case BIT7_xHL: I=RdZ80(R->HL.W);M_BIT(7,I);break;
|
||||
case BIT7_A: M_BIT(7,R->AF.B.h);break;
|
||||
|
||||
case RES0_B: M_RES(0,R->BC.B.h);break; case RES0_C: M_RES(0,R->BC.B.l);break;
|
||||
case RES0_D: M_RES(0,R->DE.B.h);break; case RES0_E: M_RES(0,R->DE.B.l);break;
|
||||
case RES0_H: M_RES(0,R->HL.B.h);break; case RES0_L: M_RES(0,R->HL.B.l);break;
|
||||
case RES0_xHL: I=RdZ80(R->HL.W);M_RES(0,I);WrZ80(R->HL.W,I);break;
|
||||
case RES0_A: M_RES(0,R->AF.B.h);break;
|
||||
|
||||
case RES1_B: M_RES(1,R->BC.B.h);break; case RES1_C: M_RES(1,R->BC.B.l);break;
|
||||
case RES1_D: M_RES(1,R->DE.B.h);break; case RES1_E: M_RES(1,R->DE.B.l);break;
|
||||
case RES1_H: M_RES(1,R->HL.B.h);break; case RES1_L: M_RES(1,R->HL.B.l);break;
|
||||
case RES1_xHL: I=RdZ80(R->HL.W);M_RES(1,I);WrZ80(R->HL.W,I);break;
|
||||
case RES1_A: M_RES(1,R->AF.B.h);break;
|
||||
|
||||
case RES2_B: M_RES(2,R->BC.B.h);break; case RES2_C: M_RES(2,R->BC.B.l);break;
|
||||
case RES2_D: M_RES(2,R->DE.B.h);break; case RES2_E: M_RES(2,R->DE.B.l);break;
|
||||
case RES2_H: M_RES(2,R->HL.B.h);break; case RES2_L: M_RES(2,R->HL.B.l);break;
|
||||
case RES2_xHL: I=RdZ80(R->HL.W);M_RES(2,I);WrZ80(R->HL.W,I);break;
|
||||
case RES2_A: M_RES(2,R->AF.B.h);break;
|
||||
|
||||
case RES3_B: M_RES(3,R->BC.B.h);break; case RES3_C: M_RES(3,R->BC.B.l);break;
|
||||
case RES3_D: M_RES(3,R->DE.B.h);break; case RES3_E: M_RES(3,R->DE.B.l);break;
|
||||
case RES3_H: M_RES(3,R->HL.B.h);break; case RES3_L: M_RES(3,R->HL.B.l);break;
|
||||
case RES3_xHL: I=RdZ80(R->HL.W);M_RES(3,I);WrZ80(R->HL.W,I);break;
|
||||
case RES3_A: M_RES(3,R->AF.B.h);break;
|
||||
|
||||
case RES4_B: M_RES(4,R->BC.B.h);break; case RES4_C: M_RES(4,R->BC.B.l);break;
|
||||
case RES4_D: M_RES(4,R->DE.B.h);break; case RES4_E: M_RES(4,R->DE.B.l);break;
|
||||
case RES4_H: M_RES(4,R->HL.B.h);break; case RES4_L: M_RES(4,R->HL.B.l);break;
|
||||
case RES4_xHL: I=RdZ80(R->HL.W);M_RES(4,I);WrZ80(R->HL.W,I);break;
|
||||
case RES4_A: M_RES(4,R->AF.B.h);break;
|
||||
|
||||
case RES5_B: M_RES(5,R->BC.B.h);break; case RES5_C: M_RES(5,R->BC.B.l);break;
|
||||
case RES5_D: M_RES(5,R->DE.B.h);break; case RES5_E: M_RES(5,R->DE.B.l);break;
|
||||
case RES5_H: M_RES(5,R->HL.B.h);break; case RES5_L: M_RES(5,R->HL.B.l);break;
|
||||
case RES5_xHL: I=RdZ80(R->HL.W);M_RES(5,I);WrZ80(R->HL.W,I);break;
|
||||
case RES5_A: M_RES(5,R->AF.B.h);break;
|
||||
|
||||
case RES6_B: M_RES(6,R->BC.B.h);break; case RES6_C: M_RES(6,R->BC.B.l);break;
|
||||
case RES6_D: M_RES(6,R->DE.B.h);break; case RES6_E: M_RES(6,R->DE.B.l);break;
|
||||
case RES6_H: M_RES(6,R->HL.B.h);break; case RES6_L: M_RES(6,R->HL.B.l);break;
|
||||
case RES6_xHL: I=RdZ80(R->HL.W);M_RES(6,I);WrZ80(R->HL.W,I);break;
|
||||
case RES6_A: M_RES(6,R->AF.B.h);break;
|
||||
|
||||
case RES7_B: M_RES(7,R->BC.B.h);break; case RES7_C: M_RES(7,R->BC.B.l);break;
|
||||
case RES7_D: M_RES(7,R->DE.B.h);break; case RES7_E: M_RES(7,R->DE.B.l);break;
|
||||
case RES7_H: M_RES(7,R->HL.B.h);break; case RES7_L: M_RES(7,R->HL.B.l);break;
|
||||
case RES7_xHL: I=RdZ80(R->HL.W);M_RES(7,I);WrZ80(R->HL.W,I);break;
|
||||
case RES7_A: M_RES(7,R->AF.B.h);break;
|
||||
|
||||
case SET0_B: M_SET(0,R->BC.B.h);break; case SET0_C: M_SET(0,R->BC.B.l);break;
|
||||
case SET0_D: M_SET(0,R->DE.B.h);break; case SET0_E: M_SET(0,R->DE.B.l);break;
|
||||
case SET0_H: M_SET(0,R->HL.B.h);break; case SET0_L: M_SET(0,R->HL.B.l);break;
|
||||
case SET0_xHL: I=RdZ80(R->HL.W);M_SET(0,I);WrZ80(R->HL.W,I);break;
|
||||
case SET0_A: M_SET(0,R->AF.B.h);break;
|
||||
|
||||
case SET1_B: M_SET(1,R->BC.B.h);break; case SET1_C: M_SET(1,R->BC.B.l);break;
|
||||
case SET1_D: M_SET(1,R->DE.B.h);break; case SET1_E: M_SET(1,R->DE.B.l);break;
|
||||
case SET1_H: M_SET(1,R->HL.B.h);break; case SET1_L: M_SET(1,R->HL.B.l);break;
|
||||
case SET1_xHL: I=RdZ80(R->HL.W);M_SET(1,I);WrZ80(R->HL.W,I);break;
|
||||
case SET1_A: M_SET(1,R->AF.B.h);break;
|
||||
|
||||
case SET2_B: M_SET(2,R->BC.B.h);break; case SET2_C: M_SET(2,R->BC.B.l);break;
|
||||
case SET2_D: M_SET(2,R->DE.B.h);break; case SET2_E: M_SET(2,R->DE.B.l);break;
|
||||
case SET2_H: M_SET(2,R->HL.B.h);break; case SET2_L: M_SET(2,R->HL.B.l);break;
|
||||
case SET2_xHL: I=RdZ80(R->HL.W);M_SET(2,I);WrZ80(R->HL.W,I);break;
|
||||
case SET2_A: M_SET(2,R->AF.B.h);break;
|
||||
|
||||
case SET3_B: M_SET(3,R->BC.B.h);break; case SET3_C: M_SET(3,R->BC.B.l);break;
|
||||
case SET3_D: M_SET(3,R->DE.B.h);break; case SET3_E: M_SET(3,R->DE.B.l);break;
|
||||
case SET3_H: M_SET(3,R->HL.B.h);break; case SET3_L: M_SET(3,R->HL.B.l);break;
|
||||
case SET3_xHL: I=RdZ80(R->HL.W);M_SET(3,I);WrZ80(R->HL.W,I);break;
|
||||
case SET3_A: M_SET(3,R->AF.B.h);break;
|
||||
|
||||
case SET4_B: M_SET(4,R->BC.B.h);break; case SET4_C: M_SET(4,R->BC.B.l);break;
|
||||
case SET4_D: M_SET(4,R->DE.B.h);break; case SET4_E: M_SET(4,R->DE.B.l);break;
|
||||
case SET4_H: M_SET(4,R->HL.B.h);break; case SET4_L: M_SET(4,R->HL.B.l);break;
|
||||
case SET4_xHL: I=RdZ80(R->HL.W);M_SET(4,I);WrZ80(R->HL.W,I);break;
|
||||
case SET4_A: M_SET(4,R->AF.B.h);break;
|
||||
|
||||
case SET5_B: M_SET(5,R->BC.B.h);break; case SET5_C: M_SET(5,R->BC.B.l);break;
|
||||
case SET5_D: M_SET(5,R->DE.B.h);break; case SET5_E: M_SET(5,R->DE.B.l);break;
|
||||
case SET5_H: M_SET(5,R->HL.B.h);break; case SET5_L: M_SET(5,R->HL.B.l);break;
|
||||
case SET5_xHL: I=RdZ80(R->HL.W);M_SET(5,I);WrZ80(R->HL.W,I);break;
|
||||
case SET5_A: M_SET(5,R->AF.B.h);break;
|
||||
|
||||
case SET6_B: M_SET(6,R->BC.B.h);break; case SET6_C: M_SET(6,R->BC.B.l);break;
|
||||
case SET6_D: M_SET(6,R->DE.B.h);break; case SET6_E: M_SET(6,R->DE.B.l);break;
|
||||
case SET6_H: M_SET(6,R->HL.B.h);break; case SET6_L: M_SET(6,R->HL.B.l);break;
|
||||
case SET6_xHL: I=RdZ80(R->HL.W);M_SET(6,I);WrZ80(R->HL.W,I);break;
|
||||
case SET6_A: M_SET(6,R->AF.B.h);break;
|
||||
|
||||
case SET7_B: M_SET(7,R->BC.B.h);break; case SET7_C: M_SET(7,R->BC.B.l);break;
|
||||
case SET7_D: M_SET(7,R->DE.B.h);break; case SET7_E: M_SET(7,R->DE.B.l);break;
|
||||
case SET7_H: M_SET(7,R->HL.B.h);break; case SET7_L: M_SET(7,R->HL.B.l);break;
|
||||
case SET7_xHL: I=RdZ80(R->HL.W);M_SET(7,I);WrZ80(R->HL.W,I);break;
|
||||
case SET7_A: M_SET(7,R->AF.B.h);break;
|
|
@ -0,0 +1,281 @@
|
|||
/** Z80: portable Z80 emulator *******************************/
|
||||
/** **/
|
||||
/** CodesED.h **/
|
||||
/** **/
|
||||
/** This file contains implementation for the ED table of **/
|
||||
/** Z80 commands. It is included from Z80.c. **/
|
||||
/** **/
|
||||
/** Copyright (C) Marat Fayzullin 1994,1995,1996,1997 **/
|
||||
/** You are not allowed to distribute this software **/
|
||||
/** commercially. Please, notify me, if you make any **/
|
||||
/** changes to this file. **/
|
||||
/*************************************************************/
|
||||
|
||||
/** This is a special patch for emulating BIOS calls: ********/
|
||||
case DB_FE: PatchZ80(R);break;
|
||||
/*************************************************************/
|
||||
|
||||
case ADC_HL_BC: M_ADCW(BC);break;
|
||||
case ADC_HL_DE: M_ADCW(DE);break;
|
||||
case ADC_HL_HL: M_ADCW(HL);break;
|
||||
case ADC_HL_SP: M_ADCW(SP);break;
|
||||
|
||||
case SBC_HL_BC: M_SBCW(BC);break;
|
||||
case SBC_HL_DE: M_SBCW(DE);break;
|
||||
case SBC_HL_HL: M_SBCW(HL);break;
|
||||
case SBC_HL_SP: M_SBCW(SP);break;
|
||||
|
||||
case LD_xWORDe_HL:
|
||||
J.B.l=RdZ80(R->PC.W++);
|
||||
J.B.h=RdZ80(R->PC.W++);
|
||||
WrZ80(J.W++,R->HL.B.l);
|
||||
WrZ80(J.W,R->HL.B.h);
|
||||
break;
|
||||
case LD_xWORDe_DE:
|
||||
J.B.l=RdZ80(R->PC.W++);
|
||||
J.B.h=RdZ80(R->PC.W++);
|
||||
WrZ80(J.W++,R->DE.B.l);
|
||||
WrZ80(J.W,R->DE.B.h);
|
||||
break;
|
||||
case LD_xWORDe_BC:
|
||||
J.B.l=RdZ80(R->PC.W++);
|
||||
J.B.h=RdZ80(R->PC.W++);
|
||||
WrZ80(J.W++,R->BC.B.l);
|
||||
WrZ80(J.W,R->BC.B.h);
|
||||
break;
|
||||
case LD_xWORDe_SP:
|
||||
J.B.l=RdZ80(R->PC.W++);
|
||||
J.B.h=RdZ80(R->PC.W++);
|
||||
WrZ80(J.W++,R->SP.B.l);
|
||||
WrZ80(J.W,R->SP.B.h);
|
||||
break;
|
||||
|
||||
case LD_HL_xWORDe:
|
||||
J.B.l=RdZ80(R->PC.W++);
|
||||
J.B.h=RdZ80(R->PC.W++);
|
||||
R->HL.B.l=RdZ80(J.W++);
|
||||
R->HL.B.h=RdZ80(J.W);
|
||||
break;
|
||||
case LD_DE_xWORDe:
|
||||
J.B.l=RdZ80(R->PC.W++);
|
||||
J.B.h=RdZ80(R->PC.W++);
|
||||
R->DE.B.l=RdZ80(J.W++);
|
||||
R->DE.B.h=RdZ80(J.W);
|
||||
break;
|
||||
case LD_BC_xWORDe:
|
||||
J.B.l=RdZ80(R->PC.W++);
|
||||
J.B.h=RdZ80(R->PC.W++);
|
||||
R->BC.B.l=RdZ80(J.W++);
|
||||
R->BC.B.h=RdZ80(J.W);
|
||||
break;
|
||||
case LD_SP_xWORDe:
|
||||
J.B.l=RdZ80(R->PC.W++);
|
||||
J.B.h=RdZ80(R->PC.W++);
|
||||
R->SP.B.l=RdZ80(J.W++);
|
||||
R->SP.B.h=RdZ80(J.W);
|
||||
break;
|
||||
|
||||
case RRD:
|
||||
I=RdZ80(R->HL.W);
|
||||
J.B.l=(I>>4)|(R->AF.B.h<<4);
|
||||
WrZ80(R->HL.W,J.B.l);
|
||||
R->AF.B.h=(I&0x0F)|(R->AF.B.h&0xF0);
|
||||
R->AF.B.l=PZSTable[R->AF.B.h]|(R->AF.B.l&C_FLAG);
|
||||
break;
|
||||
case RLD:
|
||||
I=RdZ80(R->HL.W);
|
||||
J.B.l=(I<<4)|(R->AF.B.h&0x0F);
|
||||
WrZ80(R->HL.W,J.B.l);
|
||||
R->AF.B.h=(I>>4)|(R->AF.B.h&0xF0);
|
||||
R->AF.B.l=PZSTable[R->AF.B.h]|(R->AF.B.l&C_FLAG);
|
||||
break;
|
||||
|
||||
case LD_A_I:
|
||||
R->AF.B.h=R->I;
|
||||
R->AF.B.l=(R->AF.B.l&C_FLAG)|(R->IFF&1? P_FLAG:0)|ZSTable[R->AF.B.h];
|
||||
break;
|
||||
|
||||
case LD_A_R:
|
||||
R->AF.B.h=(byte)(-R->ICount&0xFF);
|
||||
R->AF.B.l=(R->AF.B.l&C_FLAG)|(R->IFF&1? P_FLAG:0)|ZSTable[R->AF.B.h];
|
||||
break;
|
||||
|
||||
case LD_I_A: R->I=R->AF.B.h;break;
|
||||
case LD_R_A: break;
|
||||
|
||||
case IM_0: R->IFF&=0xF9;break;
|
||||
case IM_1: R->IFF=(R->IFF&0xF9)|2;break;
|
||||
case IM_2: R->IFF=(R->IFF&0xF9)|4;break;
|
||||
|
||||
case RETI: M_RET;break;
|
||||
case RETN: if(R->IFF&0x40) R->IFF|=0x01; else R->IFF&=0xFE;
|
||||
M_RET;break;
|
||||
|
||||
case NEG: I=R->AF.B.h;R->AF.B.h=0;M_SUB(I);break;
|
||||
|
||||
case IN_B_xC: M_IN(R->BC.B.h);break;
|
||||
case IN_C_xC: M_IN(R->BC.B.l);break;
|
||||
case IN_D_xC: M_IN(R->DE.B.h);break;
|
||||
case IN_E_xC: M_IN(R->DE.B.l);break;
|
||||
case IN_H_xC: M_IN(R->HL.B.h);break;
|
||||
case IN_L_xC: M_IN(R->HL.B.l);break;
|
||||
case IN_A_xC: M_IN(R->AF.B.h);break;
|
||||
case IN_F_xC: M_IN(J.B.l);break;
|
||||
|
||||
case OUT_xC_B: OutZ80(R->BC.B.l,R->BC.B.h);break;
|
||||
case OUT_xC_C: OutZ80(R->BC.B.l,R->BC.B.l);break;
|
||||
case OUT_xC_D: OutZ80(R->BC.B.l,R->DE.B.h);break;
|
||||
case OUT_xC_E: OutZ80(R->BC.B.l,R->DE.B.l);break;
|
||||
case OUT_xC_H: OutZ80(R->BC.B.l,R->HL.B.h);break;
|
||||
case OUT_xC_L: OutZ80(R->BC.B.l,R->HL.B.l);break;
|
||||
case OUT_xC_A: OutZ80(R->BC.B.l,R->AF.B.h);break;
|
||||
|
||||
case INI:
|
||||
WrZ80(R->HL.W++,InZ80(R->BC.B.l));
|
||||
R->BC.B.h--;
|
||||
R->AF.B.l=N_FLAG|(R->BC.B.h? 0:Z_FLAG);
|
||||
break;
|
||||
|
||||
case INIR:
|
||||
do
|
||||
{
|
||||
WrZ80(R->HL.W++,InZ80(R->BC.B.l));
|
||||
R->BC.B.h--;R->ICount-=21;
|
||||
}
|
||||
while(R->BC.B.h&&(R->ICount>0));
|
||||
if(R->BC.B.h) { R->AF.B.l=N_FLAG;R->PC.W-=2; }
|
||||
else { R->AF.B.l=Z_FLAG|N_FLAG;R->ICount+=5; }
|
||||
break;
|
||||
|
||||
case IND:
|
||||
WrZ80(R->HL.W--,InZ80(R->BC.B.l));
|
||||
R->BC.B.h--;
|
||||
R->AF.B.l=N_FLAG|(R->BC.B.h? 0:Z_FLAG);
|
||||
break;
|
||||
|
||||
case INDR:
|
||||
do
|
||||
{
|
||||
WrZ80(R->HL.W--,InZ80(R->BC.B.l));
|
||||
R->BC.B.h--;R->ICount-=21;
|
||||
}
|
||||
while(R->BC.B.h&&(R->ICount>0));
|
||||
if(R->BC.B.h) { R->AF.B.l=N_FLAG;R->PC.W-=2; }
|
||||
else { R->AF.B.l=Z_FLAG|N_FLAG;R->ICount+=5; }
|
||||
break;
|
||||
|
||||
case OUTI:
|
||||
OutZ80(R->BC.B.l,RdZ80(R->HL.W++));
|
||||
R->BC.B.h--;
|
||||
R->AF.B.l=N_FLAG|(R->BC.B.h? 0:Z_FLAG);
|
||||
break;
|
||||
|
||||
case OTIR:
|
||||
do
|
||||
{
|
||||
OutZ80(R->BC.B.l,RdZ80(R->HL.W++));
|
||||
R->BC.B.h--;R->ICount-=21;
|
||||
}
|
||||
while(R->BC.B.h&&(R->ICount>0));
|
||||
if(R->BC.B.h) { R->AF.B.l=N_FLAG;R->PC.W-=2; }
|
||||
else { R->AF.B.l=Z_FLAG|N_FLAG;R->ICount+=5; }
|
||||
break;
|
||||
|
||||
case OUTD:
|
||||
OutZ80(R->BC.B.l,RdZ80(R->HL.W--));
|
||||
R->BC.B.h--;
|
||||
R->AF.B.l=N_FLAG|(R->BC.B.h? 0:Z_FLAG);
|
||||
break;
|
||||
|
||||
case OTDR:
|
||||
do
|
||||
{
|
||||
OutZ80(R->BC.B.l,RdZ80(R->HL.W--));
|
||||
R->BC.B.h--;R->ICount-=21;
|
||||
}
|
||||
while(R->BC.B.h&&(R->ICount>0));
|
||||
if(R->BC.B.h) { R->AF.B.l=N_FLAG;R->PC.W-=2; }
|
||||
else { R->AF.B.l=Z_FLAG|N_FLAG;R->ICount+=5; }
|
||||
break;
|
||||
|
||||
case LDI:
|
||||
WrZ80(R->DE.W++,RdZ80(R->HL.W++));
|
||||
R->BC.W--;
|
||||
R->AF.B.l=(R->AF.B.l&~(N_FLAG|H_FLAG|P_FLAG))|(R->BC.W? P_FLAG:0);
|
||||
break;
|
||||
|
||||
case LDIR:
|
||||
do
|
||||
{
|
||||
WrZ80(R->DE.W++,RdZ80(R->HL.W++));
|
||||
R->BC.W--;R->ICount-=21;
|
||||
}
|
||||
while(R->BC.W&&(R->ICount>0));
|
||||
R->AF.B.l&=~(N_FLAG|H_FLAG|P_FLAG);
|
||||
if(R->BC.W) { R->AF.B.l|=N_FLAG;R->PC.W-=2; }
|
||||
else R->ICount+=5;
|
||||
break;
|
||||
|
||||
case LDD:
|
||||
WrZ80(R->DE.W--,RdZ80(R->HL.W--));
|
||||
R->BC.W--;
|
||||
R->AF.B.l=(R->AF.B.l&~(N_FLAG|H_FLAG|P_FLAG))|(R->BC.W? P_FLAG:0);
|
||||
break;
|
||||
|
||||
case LDDR:
|
||||
do
|
||||
{
|
||||
WrZ80(R->DE.W--,RdZ80(R->HL.W--));
|
||||
R->BC.W--;R->ICount-=21;
|
||||
}
|
||||
while(R->BC.W&&(R->ICount>0));
|
||||
R->AF.B.l&=~(N_FLAG|H_FLAG|P_FLAG);
|
||||
if(R->BC.W) { R->AF.B.l|=N_FLAG;R->PC.W-=2; }
|
||||
else R->ICount+=5;
|
||||
break;
|
||||
|
||||
case CPI:
|
||||
I=RdZ80(R->HL.W++);
|
||||
J.B.l=R->AF.B.h-I;
|
||||
R->BC.W--;
|
||||
R->AF.B.l =
|
||||
N_FLAG|(R->AF.B.l&C_FLAG)|ZSTable[J.B.l]|
|
||||
((R->AF.B.h^I^J.B.l)&H_FLAG)|(R->BC.W? P_FLAG:0);
|
||||
break;
|
||||
|
||||
case CPIR:
|
||||
do
|
||||
{
|
||||
I=RdZ80(R->HL.W++);
|
||||
J.B.l=R->AF.B.h-I;
|
||||
R->BC.W--;R->ICount-=21;
|
||||
}
|
||||
while(R->BC.W&&J.B.l&&(R->ICount>0));
|
||||
R->AF.B.l =
|
||||
N_FLAG|(R->AF.B.l&C_FLAG)|ZSTable[J.B.l]|
|
||||
((R->AF.B.h^I^J.B.l)&H_FLAG)|(R->BC.W? P_FLAG:0);
|
||||
if(R->BC.W&&J.B.l) R->PC.W-=2; else R->ICount+=5;
|
||||
break;
|
||||
|
||||
case CPD:
|
||||
I=RdZ80(R->HL.W--);
|
||||
J.B.l=R->AF.B.h-I;
|
||||
R->BC.W--;
|
||||
R->AF.B.l =
|
||||
N_FLAG|(R->AF.B.l&C_FLAG)|ZSTable[J.B.l]|
|
||||
((R->AF.B.h^I^J.B.l)&H_FLAG)|(R->BC.W? P_FLAG:0);
|
||||
break;
|
||||
|
||||
case CPDR:
|
||||
do
|
||||
{
|
||||
I=RdZ80(R->HL.W--);
|
||||
J.B.l=R->AF.B.h-I;
|
||||
R->BC.W--;R->ICount-=21;
|
||||
}
|
||||
while(R->BC.W&&J.B.l);
|
||||
R->AF.B.l =
|
||||
N_FLAG|(R->AF.B.l&C_FLAG)|ZSTable[J.B.l]|
|
||||
((R->AF.B.h^I^J.B.l)&H_FLAG)|(R->BC.W? P_FLAG:0);
|
||||
if(R->BC.W&&J.B.l) R->PC.W-=2; else R->ICount+=5;
|
||||
break;
|
|
@ -0,0 +1,64 @@
|
|||
/** Z80: portable Z80 emulator *******************************/
|
||||
/** **/
|
||||
/** CodesXCB.h **/
|
||||
/** **/
|
||||
/** This file contains implementation for FD/DD-CB tables **/
|
||||
/** of Z80 commands. It is included from Z80.c. **/
|
||||
/** **/
|
||||
/** Copyright (C) Marat Fayzullin 1994,1995,1996,1997 **/
|
||||
/** You are not allowed to distribute this software **/
|
||||
/** commercially. Please, notify me, if you make any **/
|
||||
/** changes to this file. **/
|
||||
/*************************************************************/
|
||||
|
||||
case RLC_xHL: I=RdZ80(J.W);M_RLC(I);WrZ80(J.W,I);break;
|
||||
case RRC_xHL: I=RdZ80(J.W);M_RRC(I);WrZ80(J.W,I);break;
|
||||
case RL_xHL: I=RdZ80(J.W);M_RL(I);WrZ80(J.W,I);break;
|
||||
case RR_xHL: I=RdZ80(J.W);M_RR(I);WrZ80(J.W,I);break;
|
||||
case SLA_xHL: I=RdZ80(J.W);M_SLA(I);WrZ80(J.W,I);break;
|
||||
case SRA_xHL: I=RdZ80(J.W);M_SRA(I);WrZ80(J.W,I);break;
|
||||
case SLL_xHL: I=RdZ80(J.W);M_SLL(I);WrZ80(J.W,I);break;
|
||||
case SRL_xHL: I=RdZ80(J.W);M_SRL(I);WrZ80(J.W,I);break;
|
||||
|
||||
case BIT0_B: case BIT0_C: case BIT0_D: case BIT0_E:
|
||||
case BIT0_H: case BIT0_L: case BIT0_A:
|
||||
case BIT0_xHL: I=RdZ80(J.W);M_BIT(0,I);break;
|
||||
case BIT1_B: case BIT1_C: case BIT1_D: case BIT1_E:
|
||||
case BIT1_H: case BIT1_L: case BIT1_A:
|
||||
case BIT1_xHL: I=RdZ80(J.W);M_BIT(1,I);break;
|
||||
case BIT2_B: case BIT2_C: case BIT2_D: case BIT2_E:
|
||||
case BIT2_H: case BIT2_L: case BIT2_A:
|
||||
case BIT2_xHL: I=RdZ80(J.W);M_BIT(2,I);break;
|
||||
case BIT3_B: case BIT3_C: case BIT3_D: case BIT3_E:
|
||||
case BIT3_H: case BIT3_L: case BIT3_A:
|
||||
case BIT3_xHL: I=RdZ80(J.W);M_BIT(3,I);break;
|
||||
case BIT4_B: case BIT4_C: case BIT4_D: case BIT4_E:
|
||||
case BIT4_H: case BIT4_L: case BIT4_A:
|
||||
case BIT4_xHL: I=RdZ80(J.W);M_BIT(4,I);break;
|
||||
case BIT5_B: case BIT5_C: case BIT5_D: case BIT5_E:
|
||||
case BIT5_H: case BIT5_L: case BIT5_A:
|
||||
case BIT5_xHL: I=RdZ80(J.W);M_BIT(5,I);break;
|
||||
case BIT6_B: case BIT6_C: case BIT6_D: case BIT6_E:
|
||||
case BIT6_H: case BIT6_L: case BIT6_A:
|
||||
case BIT6_xHL: I=RdZ80(J.W);M_BIT(6,I);break;
|
||||
case BIT7_B: case BIT7_C: case BIT7_D: case BIT7_E:
|
||||
case BIT7_H: case BIT7_L: case BIT7_A:
|
||||
case BIT7_xHL: I=RdZ80(J.W);M_BIT(7,I);break;
|
||||
|
||||
case RES0_xHL: I=RdZ80(J.W);M_RES(0,I);WrZ80(J.W,I);break;
|
||||
case RES1_xHL: I=RdZ80(J.W);M_RES(1,I);WrZ80(J.W,I);break;
|
||||
case RES2_xHL: I=RdZ80(J.W);M_RES(2,I);WrZ80(J.W,I);break;
|
||||
case RES3_xHL: I=RdZ80(J.W);M_RES(3,I);WrZ80(J.W,I);break;
|
||||
case RES4_xHL: I=RdZ80(J.W);M_RES(4,I);WrZ80(J.W,I);break;
|
||||
case RES5_xHL: I=RdZ80(J.W);M_RES(5,I);WrZ80(J.W,I);break;
|
||||
case RES6_xHL: I=RdZ80(J.W);M_RES(6,I);WrZ80(J.W,I);break;
|
||||
case RES7_xHL: I=RdZ80(J.W);M_RES(7,I);WrZ80(J.W,I);break;
|
||||
|
||||
case SET0_xHL: I=RdZ80(J.W);M_SET(0,I);WrZ80(J.W,I);break;
|
||||
case SET1_xHL: I=RdZ80(J.W);M_SET(1,I);WrZ80(J.W,I);break;
|
||||
case SET2_xHL: I=RdZ80(J.W);M_SET(2,I);WrZ80(J.W,I);break;
|
||||
case SET3_xHL: I=RdZ80(J.W);M_SET(3,I);WrZ80(J.W,I);break;
|
||||
case SET4_xHL: I=RdZ80(J.W);M_SET(4,I);WrZ80(J.W,I);break;
|
||||
case SET5_xHL: I=RdZ80(J.W);M_SET(5,I);WrZ80(J.W,I);break;
|
||||
case SET6_xHL: I=RdZ80(J.W);M_SET(6,I);WrZ80(J.W,I);break;
|
||||
case SET7_xHL: I=RdZ80(J.W);M_SET(7,I);WrZ80(J.W,I);break;
|
|
@ -0,0 +1,388 @@
|
|||
/** Z80: portable Z80 emulator *******************************/
|
||||
/** **/
|
||||
/** CodesXX.h **/
|
||||
/** **/
|
||||
/** This file contains implementation for FD/DD tables of **/
|
||||
/** Z80 commands. It is included from Z80.c. **/
|
||||
/** **/
|
||||
/** Copyright (C) Marat Fayzullin 1994,1995,1996,1997 **/
|
||||
/** You are not allowed to distribute this software **/
|
||||
/** commercially. Please, notify me, if you make any **/
|
||||
/** changes to this file. **/
|
||||
/*************************************************************/
|
||||
|
||||
case JR_NZ: if(R->AF.B.l&Z_FLAG) R->PC.W++; else { M_JR; } break;
|
||||
case JR_NC: if(R->AF.B.l&C_FLAG) R->PC.W++; else { M_JR; } break;
|
||||
case JR_Z: if(R->AF.B.l&Z_FLAG) { M_JR; } else R->PC.W++; break;
|
||||
case JR_C: if(R->AF.B.l&C_FLAG) { M_JR; } else R->PC.W++; break;
|
||||
|
||||
case JP_NZ: if(R->AF.B.l&Z_FLAG) R->PC.W+=2; else { M_JP; } break;
|
||||
case JP_NC: if(R->AF.B.l&C_FLAG) R->PC.W+=2; else { M_JP; } break;
|
||||
case JP_PO: if(R->AF.B.l&P_FLAG) R->PC.W+=2; else { M_JP; } break;
|
||||
case JP_P: if(R->AF.B.l&S_FLAG) R->PC.W+=2; else { M_JP; } break;
|
||||
case JP_Z: if(R->AF.B.l&Z_FLAG) { M_JP; } else R->PC.W+=2; break;
|
||||
case JP_C: if(R->AF.B.l&C_FLAG) { M_JP; } else R->PC.W+=2; break;
|
||||
case JP_PE: if(R->AF.B.l&P_FLAG) { M_JP; } else R->PC.W+=2; break;
|
||||
case JP_M: if(R->AF.B.l&S_FLAG) { M_JP; } else R->PC.W+=2; break;
|
||||
|
||||
case RET_NZ: if(!(R->AF.B.l&Z_FLAG)) { M_RET; } break;
|
||||
case RET_NC: if(!(R->AF.B.l&C_FLAG)) { M_RET; } break;
|
||||
case RET_PO: if(!(R->AF.B.l&P_FLAG)) { M_RET; } break;
|
||||
case RET_P: if(!(R->AF.B.l&S_FLAG)) { M_RET; } break;
|
||||
case RET_Z: if(R->AF.B.l&Z_FLAG) { M_RET; } break;
|
||||
case RET_C: if(R->AF.B.l&C_FLAG) { M_RET; } break;
|
||||
case RET_PE: if(R->AF.B.l&P_FLAG) { M_RET; } break;
|
||||
case RET_M: if(R->AF.B.l&S_FLAG) { M_RET; } break;
|
||||
|
||||
case CALL_NZ: if(R->AF.B.l&Z_FLAG) R->PC.W+=2; else { M_CALL; } break;
|
||||
case CALL_NC: if(R->AF.B.l&C_FLAG) R->PC.W+=2; else { M_CALL; } break;
|
||||
case CALL_PO: if(R->AF.B.l&P_FLAG) R->PC.W+=2; else { M_CALL; } break;
|
||||
case CALL_P: if(R->AF.B.l&S_FLAG) R->PC.W+=2; else { M_CALL; } break;
|
||||
case CALL_Z: if(R->AF.B.l&Z_FLAG) { M_CALL; } else R->PC.W+=2; break;
|
||||
case CALL_C: if(R->AF.B.l&C_FLAG) { M_CALL; } else R->PC.W+=2; break;
|
||||
case CALL_PE: if(R->AF.B.l&P_FLAG) { M_CALL; } else R->PC.W+=2; break;
|
||||
case CALL_M: if(R->AF.B.l&S_FLAG) { M_CALL; } else R->PC.W+=2; break;
|
||||
|
||||
case ADD_B: M_ADD(R->BC.B.h);break;
|
||||
case ADD_C: M_ADD(R->BC.B.l);break;
|
||||
case ADD_D: M_ADD(R->DE.B.h);break;
|
||||
case ADD_E: M_ADD(R->DE.B.l);break;
|
||||
case ADD_H: M_ADD(R->XX.B.h);break;
|
||||
case ADD_L: M_ADD(R->XX.B.l);break;
|
||||
case ADD_A: M_ADD(R->AF.B.h);break;
|
||||
case ADD_xHL: I=RdZ80(R->XX.W+(offset)RdZ80(R->PC.W++));
|
||||
M_ADD(I);break;
|
||||
case ADD_BYTE: I=RdZ80(R->PC.W++);M_ADD(I);break;
|
||||
|
||||
case SUB_B: M_SUB(R->BC.B.h);break;
|
||||
case SUB_C: M_SUB(R->BC.B.l);break;
|
||||
case SUB_D: M_SUB(R->DE.B.h);break;
|
||||
case SUB_E: M_SUB(R->DE.B.l);break;
|
||||
case SUB_H: M_SUB(R->XX.B.h);break;
|
||||
case SUB_L: M_SUB(R->XX.B.l);break;
|
||||
case SUB_A: R->AF.B.h=0;R->AF.B.l=N_FLAG|Z_FLAG;break;
|
||||
case SUB_xHL: I=RdZ80(R->XX.W+(offset)RdZ80(R->PC.W++));
|
||||
M_SUB(I);break;
|
||||
case SUB_BYTE: I=RdZ80(R->PC.W++);M_SUB(I);break;
|
||||
|
||||
case AND_B: M_AND(R->BC.B.h);break;
|
||||
case AND_C: M_AND(R->BC.B.l);break;
|
||||
case AND_D: M_AND(R->DE.B.h);break;
|
||||
case AND_E: M_AND(R->DE.B.l);break;
|
||||
case AND_H: M_AND(R->XX.B.h);break;
|
||||
case AND_L: M_AND(R->XX.B.l);break;
|
||||
case AND_A: M_AND(R->AF.B.h);break;
|
||||
case AND_xHL: I=RdZ80(R->XX.W+(offset)RdZ80(R->PC.W++));
|
||||
M_AND(I);break;
|
||||
case AND_BYTE: I=RdZ80(R->PC.W++);M_AND(I);break;
|
||||
|
||||
case OR_B: M_OR(R->BC.B.h);break;
|
||||
case OR_C: M_OR(R->BC.B.l);break;
|
||||
case OR_D: M_OR(R->DE.B.h);break;
|
||||
case OR_E: M_OR(R->DE.B.l);break;
|
||||
case OR_H: M_OR(R->XX.B.h);break;
|
||||
case OR_L: M_OR(R->XX.B.l);break;
|
||||
case OR_A: M_OR(R->AF.B.h);break;
|
||||
case OR_xHL: I=RdZ80(R->XX.W+(offset)RdZ80(R->PC.W++));
|
||||
M_OR(I);break;
|
||||
case OR_BYTE: I=RdZ80(R->PC.W++);M_OR(I);break;
|
||||
|
||||
case ADC_B: M_ADC(R->BC.B.h);break;
|
||||
case ADC_C: M_ADC(R->BC.B.l);break;
|
||||
case ADC_D: M_ADC(R->DE.B.h);break;
|
||||
case ADC_E: M_ADC(R->DE.B.l);break;
|
||||
case ADC_H: M_ADC(R->XX.B.h);break;
|
||||
case ADC_L: M_ADC(R->XX.B.l);break;
|
||||
case ADC_A: M_ADC(R->AF.B.h);break;
|
||||
case ADC_xHL: I=RdZ80(R->XX.W+(offset)RdZ80(R->PC.W++));
|
||||
M_ADC(I);break;
|
||||
case ADC_BYTE: I=RdZ80(R->PC.W++);M_ADC(I);break;
|
||||
|
||||
case SBC_B: M_SBC(R->BC.B.h);break;
|
||||
case SBC_C: M_SBC(R->BC.B.l);break;
|
||||
case SBC_D: M_SBC(R->DE.B.h);break;
|
||||
case SBC_E: M_SBC(R->DE.B.l);break;
|
||||
case SBC_H: M_SBC(R->XX.B.h);break;
|
||||
case SBC_L: M_SBC(R->XX.B.l);break;
|
||||
case SBC_A: M_SBC(R->AF.B.h);break;
|
||||
case SBC_xHL: I=RdZ80(R->XX.W+(offset)RdZ80(R->PC.W++));
|
||||
M_SBC(I);break;
|
||||
case SBC_BYTE: I=RdZ80(R->PC.W++);M_SBC(I);break;
|
||||
|
||||
case XOR_B: M_XOR(R->BC.B.h);break;
|
||||
case XOR_C: M_XOR(R->BC.B.l);break;
|
||||
case XOR_D: M_XOR(R->DE.B.h);break;
|
||||
case XOR_E: M_XOR(R->DE.B.l);break;
|
||||
case XOR_H: M_XOR(R->XX.B.h);break;
|
||||
case XOR_L: M_XOR(R->XX.B.l);break;
|
||||
case XOR_A: R->AF.B.h=0;R->AF.B.l=P_FLAG|Z_FLAG;break;
|
||||
case XOR_xHL: I=RdZ80(R->XX.W+(offset)RdZ80(R->PC.W++));
|
||||
M_XOR(I);break;
|
||||
case XOR_BYTE: I=RdZ80(R->PC.W++);M_XOR(I);break;
|
||||
|
||||
case CP_B: M_CP(R->BC.B.h);break;
|
||||
case CP_C: M_CP(R->BC.B.l);break;
|
||||
case CP_D: M_CP(R->DE.B.h);break;
|
||||
case CP_E: M_CP(R->DE.B.l);break;
|
||||
case CP_H: M_CP(R->XX.B.h);break;
|
||||
case CP_L: M_CP(R->XX.B.l);break;
|
||||
case CP_A: R->AF.B.l=N_FLAG|Z_FLAG;break;
|
||||
case CP_xHL: I=RdZ80(R->XX.W+(offset)RdZ80(R->PC.W++));
|
||||
M_CP(I);break;
|
||||
case CP_BYTE: I=RdZ80(R->PC.W++);M_CP(I);break;
|
||||
|
||||
case LD_BC_WORD: M_LDWORD(BC);break;
|
||||
case LD_DE_WORD: M_LDWORD(DE);break;
|
||||
case LD_HL_WORD: M_LDWORD(XX);break;
|
||||
case LD_SP_WORD: M_LDWORD(SP);break;
|
||||
|
||||
case LD_PC_HL: R->PC.W=R->XX.W;break;
|
||||
case LD_SP_HL: R->SP.W=R->XX.W;break;
|
||||
case LD_A_xBC: R->AF.B.h=RdZ80(R->BC.W);break;
|
||||
case LD_A_xDE: R->AF.B.h=RdZ80(R->DE.W);break;
|
||||
|
||||
case ADD_HL_BC: M_ADDW(XX,BC);break;
|
||||
case ADD_HL_DE: M_ADDW(XX,DE);break;
|
||||
case ADD_HL_HL: M_ADDW(XX,XX);break;
|
||||
case ADD_HL_SP: M_ADDW(XX,SP);break;
|
||||
|
||||
case DEC_BC: R->BC.W--;break;
|
||||
case DEC_DE: R->DE.W--;break;
|
||||
case DEC_HL: R->XX.W--;break;
|
||||
case DEC_SP: R->SP.W--;break;
|
||||
|
||||
case INC_BC: R->BC.W++;break;
|
||||
case INC_DE: R->DE.W++;break;
|
||||
case INC_HL: R->XX.W++;break;
|
||||
case INC_SP: R->SP.W++;break;
|
||||
|
||||
case DEC_B: M_DEC(R->BC.B.h);break;
|
||||
case DEC_C: M_DEC(R->BC.B.l);break;
|
||||
case DEC_D: M_DEC(R->DE.B.h);break;
|
||||
case DEC_E: M_DEC(R->DE.B.l);break;
|
||||
case DEC_H: M_DEC(R->XX.B.h);break;
|
||||
case DEC_L: M_DEC(R->XX.B.l);break;
|
||||
case DEC_A: M_DEC(R->AF.B.h);break;
|
||||
case DEC_xHL: I=RdZ80(R->XX.W+(offset)RdZ80(R->PC.W));M_DEC(I);
|
||||
WrZ80(R->XX.W+(offset)RdZ80(R->PC.W++),I);
|
||||
break;
|
||||
|
||||
case INC_B: M_INC(R->BC.B.h);break;
|
||||
case INC_C: M_INC(R->BC.B.l);break;
|
||||
case INC_D: M_INC(R->DE.B.h);break;
|
||||
case INC_E: M_INC(R->DE.B.l);break;
|
||||
case INC_H: M_INC(R->XX.B.h);break;
|
||||
case INC_L: M_INC(R->XX.B.l);break;
|
||||
case INC_A: M_INC(R->AF.B.h);break;
|
||||
case INC_xHL: I=RdZ80(R->XX.W+(offset)RdZ80(R->PC.W));M_INC(I);
|
||||
WrZ80(R->XX.W+(offset)RdZ80(R->PC.W++),I);
|
||||
break;
|
||||
|
||||
case RLCA:
|
||||
I=(R->AF.B.h&0x80? C_FLAG:0);
|
||||
R->AF.B.h=(R->AF.B.h<<1)|I;
|
||||
R->AF.B.l=(R->AF.B.l&~(C_FLAG|N_FLAG|H_FLAG))|I;
|
||||
break;
|
||||
case RLA:
|
||||
I=(R->AF.B.h&0x80? C_FLAG:0);
|
||||
R->AF.B.h=(R->AF.B.h<<1)|(R->AF.B.l&C_FLAG);
|
||||
R->AF.B.l=(R->AF.B.l&~(C_FLAG|N_FLAG|H_FLAG))|I;
|
||||
break;
|
||||
case RRCA:
|
||||
I=R->AF.B.h&0x01;
|
||||
R->AF.B.h=(R->AF.B.h>>1)|(I? 0x80:0);
|
||||
R->AF.B.l=(R->AF.B.l&~(C_FLAG|N_FLAG|H_FLAG))|I;
|
||||
break;
|
||||
case RRA:
|
||||
I=R->AF.B.h&0x01;
|
||||
R->AF.B.h=(R->AF.B.h>>1)|(R->AF.B.l&C_FLAG? 0x80:0);
|
||||
R->AF.B.l=(R->AF.B.l&~(C_FLAG|N_FLAG|H_FLAG))|I;
|
||||
break;
|
||||
|
||||
case RST00: M_RST(0x0000);break;
|
||||
case RST08: M_RST(0x0008);break;
|
||||
case RST10: M_RST(0x0010);break;
|
||||
case RST18: M_RST(0x0018);break;
|
||||
case RST20: M_RST(0x0020);break;
|
||||
case RST28: M_RST(0x0028);break;
|
||||
case RST30: M_RST(0x0030);break;
|
||||
case RST38: M_RST(0x0038);break;
|
||||
|
||||
case PUSH_BC: M_PUSH(BC);break;
|
||||
case PUSH_DE: M_PUSH(DE);break;
|
||||
case PUSH_HL: M_PUSH(XX);break;
|
||||
case PUSH_AF: M_PUSH(AF);break;
|
||||
|
||||
case POP_BC: M_POP(BC);break;
|
||||
case POP_DE: M_POP(DE);break;
|
||||
case POP_HL: M_POP(XX);break;
|
||||
case POP_AF: M_POP(AF);break;
|
||||
|
||||
case DJNZ: if(--R->BC.B.h) { M_JR; } else R->PC.W++;break;
|
||||
case JP: M_JP;break;
|
||||
case JR: M_JR;break;
|
||||
case CALL: M_CALL;break;
|
||||
case RET: M_RET;break;
|
||||
case SCF: S(C_FLAG);R(N_FLAG|H_FLAG);break;
|
||||
case CPL: R->AF.B.h=~R->AF.B.h;S(N_FLAG|H_FLAG);break;
|
||||
case NOP: break;
|
||||
case OUTA: OutZ80(RdZ80(R->PC.W++),R->AF.B.h);break;
|
||||
case INA: R->AF.B.h=InZ80(RdZ80(R->PC.W++));break;
|
||||
|
||||
case DI:
|
||||
R->IFF&=0xFE;
|
||||
break;
|
||||
case EI:
|
||||
R->IFF|=0x01;
|
||||
if(R->IRequest!=INT_NONE)
|
||||
{
|
||||
R->IFF|=0x20;
|
||||
R->IBackup=R->ICount;
|
||||
R->ICount=1;
|
||||
}
|
||||
break;
|
||||
|
||||
case CCF:
|
||||
R->AF.B.l^=C_FLAG;R(N_FLAG|H_FLAG);
|
||||
R->AF.B.l|=R->AF.B.l&C_FLAG? 0:H_FLAG;
|
||||
break;
|
||||
|
||||
case EXX:
|
||||
J.W=R->BC.W;R->BC.W=R->BC1.W;R->BC1.W=J.W;
|
||||
J.W=R->DE.W;R->DE.W=R->DE1.W;R->DE1.W=J.W;
|
||||
J.W=R->HL.W;R->HL.W=R->HL1.W;R->HL1.W=J.W;
|
||||
break;
|
||||
|
||||
case EX_DE_HL: J.W=R->DE.W;R->DE.W=R->HL.W;R->HL.W=J.W;break;
|
||||
case EX_AF_AF: J.W=R->AF.W;R->AF.W=R->AF1.W;R->AF1.W=J.W;break;
|
||||
|
||||
case LD_B_B: R->BC.B.h=R->BC.B.h;break;
|
||||
case LD_C_B: R->BC.B.l=R->BC.B.h;break;
|
||||
case LD_D_B: R->DE.B.h=R->BC.B.h;break;
|
||||
case LD_E_B: R->DE.B.l=R->BC.B.h;break;
|
||||
case LD_H_B: R->XX.B.h=R->BC.B.h;break;
|
||||
case LD_L_B: R->XX.B.l=R->BC.B.h;break;
|
||||
case LD_A_B: R->AF.B.h=R->BC.B.h;break;
|
||||
case LD_xHL_B: J.W=R->XX.W+(offset)RdZ80(R->PC.W++);
|
||||
WrZ80(J.W,R->BC.B.h);break;
|
||||
|
||||
case LD_B_C: R->BC.B.h=R->BC.B.l;break;
|
||||
case LD_C_C: R->BC.B.l=R->BC.B.l;break;
|
||||
case LD_D_C: R->DE.B.h=R->BC.B.l;break;
|
||||
case LD_E_C: R->DE.B.l=R->BC.B.l;break;
|
||||
case LD_H_C: R->XX.B.h=R->BC.B.l;break;
|
||||
case LD_L_C: R->XX.B.l=R->BC.B.l;break;
|
||||
case LD_A_C: R->AF.B.h=R->BC.B.l;break;
|
||||
case LD_xHL_C: J.W=R->XX.W+(offset)RdZ80(R->PC.W++);
|
||||
WrZ80(J.W,R->BC.B.l);break;
|
||||
|
||||
case LD_B_D: R->BC.B.h=R->DE.B.h;break;
|
||||
case LD_C_D: R->BC.B.l=R->DE.B.h;break;
|
||||
case LD_D_D: R->DE.B.h=R->DE.B.h;break;
|
||||
case LD_E_D: R->DE.B.l=R->DE.B.h;break;
|
||||
case LD_H_D: R->XX.B.h=R->DE.B.h;break;
|
||||
case LD_L_D: R->XX.B.l=R->DE.B.h;break;
|
||||
case LD_A_D: R->AF.B.h=R->DE.B.h;break;
|
||||
case LD_xHL_D: J.W=R->XX.W+(offset)RdZ80(R->PC.W++);
|
||||
WrZ80(J.W,R->DE.B.h);break;
|
||||
|
||||
case LD_B_E: R->BC.B.h=R->DE.B.l;break;
|
||||
case LD_C_E: R->BC.B.l=R->DE.B.l;break;
|
||||
case LD_D_E: R->DE.B.h=R->DE.B.l;break;
|
||||
case LD_E_E: R->DE.B.l=R->DE.B.l;break;
|
||||
case LD_H_E: R->XX.B.h=R->DE.B.l;break;
|
||||
case LD_L_E: R->XX.B.l=R->DE.B.l;break;
|
||||
case LD_A_E: R->AF.B.h=R->DE.B.l;break;
|
||||
case LD_xHL_E: J.W=R->XX.W+(offset)RdZ80(R->PC.W++);
|
||||
WrZ80(J.W,R->DE.B.l);break;
|
||||
|
||||
case LD_B_H: R->BC.B.h=R->XX.B.h;break;
|
||||
case LD_C_H: R->BC.B.l=R->XX.B.h;break;
|
||||
case LD_D_H: R->DE.B.h=R->XX.B.h;break;
|
||||
case LD_E_H: R->DE.B.l=R->XX.B.h;break;
|
||||
case LD_H_H: R->XX.B.h=R->XX.B.h;break;
|
||||
case LD_L_H: R->XX.B.l=R->XX.B.h;break;
|
||||
case LD_A_H: R->AF.B.h=R->XX.B.h;break;
|
||||
case LD_xHL_H: J.W=R->XX.W+(offset)RdZ80(R->PC.W++);
|
||||
WrZ80(J.W,R->HL.B.h);break;
|
||||
|
||||
case LD_B_L: R->BC.B.h=R->XX.B.l;break;
|
||||
case LD_C_L: R->BC.B.l=R->XX.B.l;break;
|
||||
case LD_D_L: R->DE.B.h=R->XX.B.l;break;
|
||||
case LD_E_L: R->DE.B.l=R->XX.B.l;break;
|
||||
case LD_H_L: R->XX.B.h=R->XX.B.l;break;
|
||||
case LD_L_L: R->XX.B.l=R->XX.B.l;break;
|
||||
case LD_A_L: R->AF.B.h=R->XX.B.l;break;
|
||||
case LD_xHL_L: J.W=R->XX.W+(offset)RdZ80(R->PC.W++);
|
||||
WrZ80(J.W,R->HL.B.l);break;
|
||||
|
||||
case LD_B_A: R->BC.B.h=R->AF.B.h;break;
|
||||
case LD_C_A: R->BC.B.l=R->AF.B.h;break;
|
||||
case LD_D_A: R->DE.B.h=R->AF.B.h;break;
|
||||
case LD_E_A: R->DE.B.l=R->AF.B.h;break;
|
||||
case LD_H_A: R->XX.B.h=R->AF.B.h;break;
|
||||
case LD_L_A: R->XX.B.l=R->AF.B.h;break;
|
||||
case LD_A_A: R->AF.B.h=R->AF.B.h;break;
|
||||
case LD_xHL_A: J.W=R->XX.W+(offset)RdZ80(R->PC.W++);
|
||||
WrZ80(J.W,R->AF.B.h);break;
|
||||
|
||||
case LD_xBC_A: WrZ80(R->BC.W,R->AF.B.h);break;
|
||||
case LD_xDE_A: WrZ80(R->DE.W,R->AF.B.h);break;
|
||||
|
||||
case LD_B_xHL: R->BC.B.h=RdZ80(R->XX.W+(offset)RdZ80(R->PC.W++));break;
|
||||
case LD_C_xHL: R->BC.B.l=RdZ80(R->XX.W+(offset)RdZ80(R->PC.W++));break;
|
||||
case LD_D_xHL: R->DE.B.h=RdZ80(R->XX.W+(offset)RdZ80(R->PC.W++));break;
|
||||
case LD_E_xHL: R->DE.B.l=RdZ80(R->XX.W+(offset)RdZ80(R->PC.W++));break;
|
||||
case LD_H_xHL: R->HL.B.h=RdZ80(R->XX.W+(offset)RdZ80(R->PC.W++));break;
|
||||
case LD_L_xHL: R->HL.B.l=RdZ80(R->XX.W+(offset)RdZ80(R->PC.W++));break;
|
||||
case LD_A_xHL: R->AF.B.h=RdZ80(R->XX.W+(offset)RdZ80(R->PC.W++));break;
|
||||
|
||||
case LD_B_BYTE: R->BC.B.h=RdZ80(R->PC.W++);break;
|
||||
case LD_C_BYTE: R->BC.B.l=RdZ80(R->PC.W++);break;
|
||||
case LD_D_BYTE: R->DE.B.h=RdZ80(R->PC.W++);break;
|
||||
case LD_E_BYTE: R->DE.B.l=RdZ80(R->PC.W++);break;
|
||||
case LD_H_BYTE: R->XX.B.h=RdZ80(R->PC.W++);break;
|
||||
case LD_L_BYTE: R->XX.B.l=RdZ80(R->PC.W++);break;
|
||||
case LD_A_BYTE: R->AF.B.h=RdZ80(R->PC.W++);break;
|
||||
case LD_xHL_BYTE: J.W=R->XX.W+(offset)RdZ80(R->PC.W++);
|
||||
WrZ80(J.W,RdZ80(R->PC.W++));break;
|
||||
|
||||
case LD_xWORD_HL:
|
||||
J.B.l=RdZ80(R->PC.W++);
|
||||
J.B.h=RdZ80(R->PC.W++);
|
||||
WrZ80(J.W++,R->XX.B.l);
|
||||
WrZ80(J.W,R->XX.B.h);
|
||||
break;
|
||||
|
||||
case LD_HL_xWORD:
|
||||
J.B.l=RdZ80(R->PC.W++);
|
||||
J.B.h=RdZ80(R->PC.W++);
|
||||
R->XX.B.l=RdZ80(J.W++);
|
||||
R->XX.B.h=RdZ80(J.W);
|
||||
break;
|
||||
|
||||
case LD_A_xWORD:
|
||||
J.B.l=RdZ80(R->PC.W++);
|
||||
J.B.h=RdZ80(R->PC.W++);
|
||||
R->AF.B.h=RdZ80(J.W);
|
||||
break;
|
||||
|
||||
case LD_xWORD_A:
|
||||
J.B.l=RdZ80(R->PC.W++);
|
||||
J.B.h=RdZ80(R->PC.W++);
|
||||
WrZ80(J.W,R->AF.B.h);
|
||||
break;
|
||||
|
||||
case EX_HL_xSP:
|
||||
J.B.l=RdZ80(R->SP.W);WrZ80(R->SP.W++,R->XX.B.l);
|
||||
J.B.h=RdZ80(R->SP.W);WrZ80(R->SP.W--,R->XX.B.h);
|
||||
R->XX.W=J.W;
|
||||
break;
|
||||
|
||||
case DAA:
|
||||
J.W=R->AF.B.h;
|
||||
if(R->AF.B.l&C_FLAG) J.W|=256;
|
||||
if(R->AF.B.l&H_FLAG) J.W|=512;
|
||||
if(R->AF.B.l&N_FLAG) J.W|=1024;
|
||||
R->AF.W=DAATable[J.W];
|
||||
break;
|
|
@ -0,0 +1,411 @@
|
|||
/** Z80: portable Z80 emulator *******************************/
|
||||
/** **/
|
||||
/** Debug.c **/
|
||||
/** **/
|
||||
/** This file contains the built-in debugging routine for **/
|
||||
/** the Z80 emulator which is called on each Z80 step when **/
|
||||
/** Trap!=0. **/
|
||||
/** **/
|
||||
/** Copyright (C) Marat Fayzullin 1995,1996,1997 **/
|
||||
/** You are not allowed to distribute this software **/
|
||||
/** commercially. Please, notify me, if you make any **/
|
||||
/** changes to this file. **/
|
||||
/*************************************************************/
|
||||
#include "Z80.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
static char *Mnemonics[256] =
|
||||
{
|
||||
"NOP","LD BC,#h","LD (BC),A","INC BC","INC B","DEC B","LD B,*h","RLCA",
|
||||
"EX AF,AF'","ADD HL,BC","LD A,(BC)","DEC BC","INC C","DEC C","LD C,*h","RRCA",
|
||||
"DJNZ @h","LD DE,#h","LD (DE),A","INC DE","INC D","DEC D","LD D,*h","RLA",
|
||||
"JR @h","ADD HL,DE","LD A,(DE)","DEC DE","INC E","DEC E","LD E,*h","RRA",
|
||||
"JR NZ,@h","LD HL,#h","LD (#h),HL","INC HL","INC H","DEC H","LD H,*h","DAA",
|
||||
"JR Z,@h","ADD HL,HL","LD HL,(#h)","DEC HL","INC L","DEC L","LD L,*h","CPL",
|
||||
"JR NC,@h","LD SP,#h","LD (#h),A","INC SP","INC (HL)","DEC (HL)","LD (HL),*h","SCF",
|
||||
"JR C,@h","ADD HL,SP","LD A,(#h)","DEC SP","INC A","DEC A","LD A,*h","CCF",
|
||||
"LD B,B","LD B,C","LD B,D","LD B,E","LD B,H","LD B,L","LD B,(HL)","LD B,A",
|
||||
"LD C,B","LD C,C","LD C,D","LD C,E","LD C,H","LD C,L","LD C,(HL)","LD C,A",
|
||||
"LD D,B","LD D,C","LD D,D","LD D,E","LD D,H","LD D,L","LD D,(HL)","LD D,A",
|
||||
"LD E,B","LD E,C","LD E,D","LD E,E","LD E,H","LD E,L","LD E,(HL)","LD E,A",
|
||||
"LD H,B","LD H,C","LD H,D","LD H,E","LD H,H","LD H,L","LD H,(HL)","LD H,A",
|
||||
"LD L,B","LD L,C","LD L,D","LD L,E","LD L,H","LD L,L","LD L,(HL)","LD L,A",
|
||||
"LD (HL),B","LD (HL),C","LD (HL),D","LD (HL),E","LD (HL),H","LD (HL),L","HALT","LD (HL),A",
|
||||
"LD A,B","LD A,C","LD A,D","LD A,E","LD A,H","LD A,L","LD A,(HL)","LD A,A",
|
||||
"ADD B","ADD C","ADD D","ADD E","ADD H","ADD L","ADD (HL)","ADD A",
|
||||
"ADC B","ADC C","ADC D","ADC E","ADC H","ADC L","ADC (HL)","ADC A",
|
||||
"SUB B","SUB C","SUB D","SUB E","SUB H","SUB L","SUB (HL)","SUB A",
|
||||
"SBC B","SBC C","SBC D","SBC E","SBC H","SBC L","SBC (HL)","SBC A",
|
||||
"AND B","AND C","AND D","AND E","AND H","AND L","AND (HL)","AND A",
|
||||
"XOR B","XOR C","XOR D","XOR E","XOR H","XOR L","XOR (HL)","XOR A",
|
||||
"OR B","OR C","OR D","OR E","OR H","OR L","OR (HL)","OR A",
|
||||
"CP B","CP C","CP D","CP E","CP H","CP L","CP (HL)","CP A",
|
||||
"RET NZ","POP BC","JP NZ,#h","JP #h","CALL NZ,#h","PUSH BC","ADD *h","RST 00h",
|
||||
"RET Z","RET","JP Z,#h","PFX_CB","CALL Z,#h","CALL #h","ADC *h","RST 08h",
|
||||
"RET NC","POP DE","JP NC,#h","OUTA (*h)","CALL NC,#h","PUSH DE","SUB *h","RST 10h",
|
||||
"RET C","EXX","JP C,#h","INA (*h)","CALL C,#h","PFX_DD","SBC *h","RST 18h",
|
||||
"RET PO","POP HL","JP PO,#h","EX HL,(SP)","CALL PO,#h","PUSH HL","AND *h","RST 20h",
|
||||
"RET PE","LD PC,HL","JP PE,#h","EX DE,HL","CALL PE,#h","PFX_ED","XOR *h","RST 28h",
|
||||
"RET P","POP AF","JP P,#h","DI","CALL P,#h","PUSH AF","OR *h","RST 30h",
|
||||
"RET M","LD SP,HL","JP M,#h","EI","CALL M,#h","PFX_FD","CP *h","RST 38h"
|
||||
};
|
||||
|
||||
static char *MnemonicsCB[256] =
|
||||
{
|
||||
"RLC B","RLC C","RLC D","RLC E","RLC H","RLC L","RLC (HL)","RLC A",
|
||||
"RRC B","RRC C","RRC D","RRC E","RRC H","RRC L","RRC (HL)","RRC A",
|
||||
"RL B","RL C","RL D","RL E","RL H","RL L","RL (HL)","RL A",
|
||||
"RR B","RR C","RR D","RR E","RR H","RR L","RR (HL)","RR A",
|
||||
"SLA B","SLA C","SLA D","SLA E","SLA H","SLA L","SLA (HL)","SLA A",
|
||||
"SRA B","SRA C","SRA D","SRA E","SRA H","SRA L","SRA (HL)","SRA A",
|
||||
"SLL B","SLL C","SLL D","SLL E","SLL H","SLL L","SLL (HL)","SLL A",
|
||||
"SRL B","SRL C","SRL D","SRL E","SRL H","SRL L","SRL (HL)","SRL A",
|
||||
"BIT 0,B","BIT 0,C","BIT 0,D","BIT 0,E","BIT 0,H","BIT 0,L","BIT 0,(HL)","BIT 0,A",
|
||||
"BIT 1,B","BIT 1,C","BIT 1,D","BIT 1,E","BIT 1,H","BIT 1,L","BIT 1,(HL)","BIT 1,A",
|
||||
"BIT 2,B","BIT 2,C","BIT 2,D","BIT 2,E","BIT 2,H","BIT 2,L","BIT 2,(HL)","BIT 2,A",
|
||||
"BIT 3,B","BIT 3,C","BIT 3,D","BIT 3,E","BIT 3,H","BIT 3,L","BIT 3,(HL)","BIT 3,A",
|
||||
"BIT 4,B","BIT 4,C","BIT 4,D","BIT 4,E","BIT 4,H","BIT 4,L","BIT 4,(HL)","BIT 4,A",
|
||||
"BIT 5,B","BIT 5,C","BIT 5,D","BIT 5,E","BIT 5,H","BIT 5,L","BIT 5,(HL)","BIT 5,A",
|
||||
"BIT 6,B","BIT 6,C","BIT 6,D","BIT 6,E","BIT 6,H","BIT 6,L","BIT 6,(HL)","BIT 6,A",
|
||||
"BIT 7,B","BIT 7,C","BIT 7,D","BIT 7,E","BIT 7,H","BIT 7,L","BIT 7,(HL)","BIT 7,A",
|
||||
"RES 0,B","RES 0,C","RES 0,D","RES 0,E","RES 0,H","RES 0,L","RES 0,(HL)","RES 0,A",
|
||||
"RES 1,B","RES 1,C","RES 1,D","RES 1,E","RES 1,H","RES 1,L","RES 1,(HL)","RES 1,A",
|
||||
"RES 2,B","RES 2,C","RES 2,D","RES 2,E","RES 2,H","RES 2,L","RES 2,(HL)","RES 2,A",
|
||||
"RES 3,B","RES 3,C","RES 3,D","RES 3,E","RES 3,H","RES 3,L","RES 3,(HL)","RES 3,A",
|
||||
"RES 4,B","RES 4,C","RES 4,D","RES 4,E","RES 4,H","RES 4,L","RES 4,(HL)","RES 4,A",
|
||||
"RES 5,B","RES 5,C","RES 5,D","RES 5,E","RES 5,H","RES 5,L","RES 5,(HL)","RES 5,A",
|
||||
"RES 6,B","RES 6,C","RES 6,D","RES 6,E","RES 6,H","RES 6,L","RES 6,(HL)","RES 6,A",
|
||||
"RES 7,B","RES 7,C","RES 7,D","RES 7,E","RES 7,H","RES 7,L","RES 7,(HL)","RES 7,A",
|
||||
"SET 0,B","SET 0,C","SET 0,D","SET 0,E","SET 0,H","SET 0,L","SET 0,(HL)","SET 0,A",
|
||||
"SET 1,B","SET 1,C","SET 1,D","SET 1,E","SET 1,H","SET 1,L","SET 1,(HL)","SET 1,A",
|
||||
"SET 2,B","SET 2,C","SET 2,D","SET 2,E","SET 2,H","SET 2,L","SET 2,(HL)","SET 2,A",
|
||||
"SET 3,B","SET 3,C","SET 3,D","SET 3,E","SET 3,H","SET 3,L","SET 3,(HL)","SET 3,A",
|
||||
"SET 4,B","SET 4,C","SET 4,D","SET 4,E","SET 4,H","SET 4,L","SET 4,(HL)","SET 4,A",
|
||||
"SET 5,B","SET 5,C","SET 5,D","SET 5,E","SET 5,H","SET 5,L","SET 5,(HL)","SET 5,A",
|
||||
"SET 6,B","SET 6,C","SET 6,D","SET 6,E","SET 6,H","SET 6,L","SET 6,(HL)","SET 6,A",
|
||||
"SET 7,B","SET 7,C","SET 7,D","SET 7,E","SET 7,H","SET 7,L","SET 7,(HL)","SET 7,A"
|
||||
};
|
||||
|
||||
static char *MnemonicsED[256] =
|
||||
{
|
||||
"DB EDh,00h","DB EDh,01h","DB EDh,02h","DB EDh,03h",
|
||||
"DB EDh,04h","DB EDh,05h","DB EDh,06h","DB EDh,07h",
|
||||
"DB EDh,08h","DB EDh,09h","DB EDh,0Ah","DB EDh,0Bh",
|
||||
"DB EDh,0Ch","DB EDh,0Dh","DB EDh,0Eh","DB EDh,0Fh",
|
||||
"DB EDh,10h","DB EDh,11h","DB EDh,12h","DB EDh,13h",
|
||||
"DB EDh,14h","DB EDh,15h","DB EDh,16h","DB EDh,17h",
|
||||
"DB EDh,18h","DB EDh,19h","DB EDh,1Ah","DB EDh,1Bh",
|
||||
"DB EDh,1Ch","DB EDh,1Dh","DB EDh,1Eh","DB EDh,1Fh",
|
||||
"DB EDh,20h","DB EDh,21h","DB EDh,22h","DB EDh,23h",
|
||||
"DB EDh,24h","DB EDh,25h","DB EDh,26h","DB EDh,27h",
|
||||
"DB EDh,28h","DB EDh,29h","DB EDh,2Ah","DB EDh,2Bh",
|
||||
"DB EDh,2Ch","DB EDh,2Dh","DB EDh,2Eh","DB EDh,2Fh",
|
||||
"DB EDh,30h","DB EDh,31h","DB EDh,32h","DB EDh,33h",
|
||||
"DB EDh,34h","DB EDh,35h","DB EDh,36h","DB EDh,37h",
|
||||
"DB EDh,38h","DB EDh,39h","DB EDh,3Ah","DB EDh,3Bh",
|
||||
"DB EDh,3Ch","DB EDh,3Dh","DB EDh,3Eh","DB EDh,3Fh",
|
||||
"IN B,(C)","OUT (C),B","SBC HL,BC","LD (#h),BC",
|
||||
"NEG","RETN","IM 0","LD I,A",
|
||||
"IN C,(C)","OUT (C),C","ADC HL,BC","LD BC,(#h)",
|
||||
"DB EDh,4Ch","RETI","DB EDh,4Eh","LD R,A",
|
||||
"IN D,(C)","OUT (C),D","SBC HL,DE","LD (#h),DE",
|
||||
"DB EDh,54h","DB EDh,55h","IM 1","LD A,I",
|
||||
"IN E,(C)","OUT (C),E","ADC HL,DE","LD DE,(#h)",
|
||||
"DB EDh,5Ch","DB EDh,5Dh","IM 2","LD A,R",
|
||||
"IN H,(C)","OUT (C),H","SBC HL,HL","LD (#h),HL",
|
||||
"DB EDh,64h","DB EDh,65h","DB EDh,66h","RRD",
|
||||
"IN L,(C)","OUT (C),L","ADC HL,HL","LD HL,(#h)",
|
||||
"DB EDh,6Ch","DB EDh,6Dh","DB EDh,6Eh","RLD",
|
||||
"IN F,(C)","DB EDh,71h","SBC HL,SP","LD (#h),SP",
|
||||
"DB EDh,74h","DB EDh,75h","DB EDh,76h","DB EDh,77h",
|
||||
"IN A,(C)","OUT (C),A","ADC HL,SP","LD SP,(#h)",
|
||||
"DB EDh,7Ch","DB EDh,7Dh","DB EDh,7Eh","DB EDh,7Fh",
|
||||
"DB EDh,80h","DB EDh,81h","DB EDh,82h","DB EDh,83h",
|
||||
"DB EDh,84h","DB EDh,85h","DB EDh,86h","DB EDh,87h",
|
||||
"DB EDh,88h","DB EDh,89h","DB EDh,8Ah","DB EDh,8Bh",
|
||||
"DB EDh,8Ch","DB EDh,8Dh","DB EDh,8Eh","DB EDh,8Fh",
|
||||
"DB EDh,90h","DB EDh,91h","DB EDh,92h","DB EDh,93h",
|
||||
"DB EDh,94h","DB EDh,95h","DB EDh,96h","DB EDh,97h",
|
||||
"DB EDh,98h","DB EDh,99h","DB EDh,9Ah","DB EDh,9Bh",
|
||||
"DB EDh,9Ch","DB EDh,9Dh","DB EDh,9Eh","DB EDh,9Fh",
|
||||
"LDI","CPI","INI","OUTI",
|
||||
"DB EDh,A4h","DB EDh,A5h","DB EDh,A6h","DB EDh,A7h",
|
||||
"LDD","CPD","IND","OUTD",
|
||||
"DB EDh,ACh","DB EDh,ADh","DB EDh,AEh","DB EDh,AFh",
|
||||
"LDIR","CPIR","INIR","OTIR",
|
||||
"DB EDh,B4h","DB EDh,B5h","DB EDh,B6h","DB EDh,B7h",
|
||||
"LDDR","CPDR","INDR","OTDR",
|
||||
"DB EDh,BCh","DB EDh,BDh","DB EDh,BEh","DB EDh,BFh",
|
||||
"DB EDh,C0h","DB EDh,C1h","DB EDh,C2h","DB EDh,C3h",
|
||||
"DB EDh,C4h","DB EDh,C5h","DB EDh,C6h","DB EDh,C7h",
|
||||
"DB EDh,C8h","DB EDh,C9h","DB EDh,CAh","DB EDh,CBh",
|
||||
"DB EDh,CCh","DB EDh,CDh","DB EDh,CEh","DB EDh,CFh",
|
||||
"DB EDh,D0h","DB EDh,D1h","DB EDh,D2h","DB EDh,D3h",
|
||||
"DB EDh,D4h","DB EDh,D5h","DB EDh,D6h","DB EDh,D7h",
|
||||
"DB EDh,D8h","DB EDh,D9h","DB EDh,DAh","DB EDh,DBh",
|
||||
"DB EDh,DCh","DB EDh,DDh","DB EDh,DEh","DB EDh,DFh",
|
||||
"DB EDh,E0h","DB EDh,E1h","DB EDh,E2h","DB EDh,E3h",
|
||||
"DB EDh,E4h","DB EDh,E5h","DB EDh,E6h","DB EDh,E7h",
|
||||
"DB EDh,E8h","DB EDh,E9h","DB EDh,EAh","DB EDh,EBh",
|
||||
"DB EDh,ECh","DB EDh,EDh","DB EDh,EEh","DB EDh,EFh",
|
||||
"DB EDh,F0h","DB EDh,F1h","DB EDh,F2h","DB EDh,F3h",
|
||||
"DB EDh,F4h","DB EDh,F5h","DB EDh,F6h","DB EDh,F7h",
|
||||
"DB EDh,F8h","DB EDh,F9h","DB EDh,FAh","DB EDh,FBh",
|
||||
"DB EDh,FCh","DB EDh,FDh","DB EDh,FEh","DB EDh,FFh"
|
||||
};
|
||||
|
||||
static char *MnemonicsXX[256] =
|
||||
{
|
||||
"NOP","LD BC,#h","LD (BC),A","INC BC","INC B","DEC B","LD B,*h","RLCA",
|
||||
"EX AF,AF'","ADD I%,BC","LD A,(BC)","DEC BC","INC C","DEC C","LD C,*h","RRCA",
|
||||
"DJNZ @h","LD DE,#h","LD (DE),A","INC DE","INC D","DEC D","LD D,*h","RLA",
|
||||
"JR @h","ADD I%,DE","LD A,(DE)","DEC DE","INC E","DEC E","LD E,*h","RRA",
|
||||
"JR NZ,@h","LD I%,#h","LD (#h),I%","INC I%","INC I%h","DEC I%h","LD I%h,*h","DAA",
|
||||
"JR Z,@h","ADD I%,I%","LD I%,(#h)","DEC I%","INC I%l","DEC I%l","LD I%l,*h","CPL",
|
||||
"JR NC,@h","LD SP,#h","LD (#h),A","INC SP","INC (I%+^h)","DEC (I%+^h)","LD (I%+^h),*h","SCF",
|
||||
"JR C,@h","ADD I%,SP","LD A,(#h)","DEC SP","INC A","DEC A","LD A,*h","CCF",
|
||||
"LD B,B","LD B,C","LD B,D","LD B,E","LD B,I%h","LD B,I%l","LD B,(I%+^h)","LD B,A",
|
||||
"LD C,B","LD C,C","LD C,D","LD C,E","LD C,I%h","LD C,I%l","LD C,(I%+^h)","LD C,A",
|
||||
"LD D,B","LD D,C","LD D,D","LD D,E","LD D,I%h","LD D,I%l","LD D,(I%+^h)","LD D,A",
|
||||
"LD E,B","LD E,C","LD E,D","LD E,E","LD E,I%h","LD E,I%l","LD E,(I%+^h)","LD E,A",
|
||||
"LD I%h,B","LD I%h,C","LD I%h,D","LD I%h,E","LD I%h,I%h","LD I%h,I%l","LD H,(I%+^h)","LD I%h,A",
|
||||
"LD I%l,B","LD I%l,C","LD I%l,D","LD I%l,E","LD I%l,I%h","LD I%l,I%l","LD L,(I%+^h)","LD I%l,A",
|
||||
"LD (I%+^h),B","LD (I%+^h),C","LD (I%+^h),D","LD (I%+^h),E","LD (I%+^h),H","LD (I%+^h),L","HALT","LD (I%+^h),A",
|
||||
"LD A,B","LD A,C","LD A,D","LD A,E","LD A,I%h","LD A,I%l","LD A,(I%+^h)","LD A,A",
|
||||
"ADD B","ADD C","ADD D","ADD E","ADD I%h","ADD I%l","ADD (I%+^h)","ADD A",
|
||||
"ADC B","ADC C","ADC D","ADC E","ADC I%h","ADC I%l","ADC (I%+^h)","ADC,A",
|
||||
"SUB B","SUB C","SUB D","SUB E","SUB I%h","SUB I%l","SUB (I%+^h)","SUB A",
|
||||
"SBC B","SBC C","SBC D","SBC E","SBC I%h","SBC I%l","SBC (I%+^h)","SBC A",
|
||||
"AND B","AND C","AND D","AND E","AND I%h","AND I%l","AND (I%+^h)","AND A",
|
||||
"XOR B","XOR C","XOR D","XOR E","XOR I%h","XOR I%l","XOR (I%+^h)","XOR A",
|
||||
"OR B","OR C","OR D","OR E","OR I%h","OR I%l","OR (I%+^h)","OR A",
|
||||
"CP B","CP C","CP D","CP E","CP I%h","CP I%l","CP (I%+^h)","CP A",
|
||||
"RET NZ","POP BC","JP NZ,#h","JP #h","CALL NZ,#h","PUSH BC","ADD *h","RST 00h",
|
||||
"RET Z","RET","JP Z,#h","PFX_CB","CALL Z,#h","CALL #h","ADC *h","RST 08h",
|
||||
"RET NC","POP DE","JP NC,#h","OUTA (*h)","CALL NC,#h","PUSH DE","SUB *h","RST 10h",
|
||||
"RET C","EXX","JP C,#h","INA (*h)","CALL C,#h","PFX_DD","SBC *h","RST 18h",
|
||||
"RET PO","POP I%","JP PO,#h","EX I%,(SP)","CALL PO,#h","PUSH I%","AND *h","RST 20h",
|
||||
"RET PE","LD PC,I%","JP PE,#h","EX DE,I%","CALL PE,#h","PFX_ED","XOR *h","RST 28h",
|
||||
"RET P","POP AF","JP P,#h","DI","CALL P,#h","PUSH AF","OR *h","RST 30h",
|
||||
"RET M","LD SP,I%","JP M,#h","EI","CALL M,#h","PFX_FD","CP *h","RST 38h"
|
||||
};
|
||||
|
||||
static char *MnemonicsXCB[256] =
|
||||
{
|
||||
"RLC B","RLC C","RLC D","RLC E","RLC H","RLC L","RLC (I%@h)","RLC A",
|
||||
"RRC B","RRC C","RRC D","RRC E","RRC H","RRC L","RRC (I%@h)","RRC A",
|
||||
"RL B","RL C","RL D","RL E","RL H","RL L","RL (I%@h)","RL A",
|
||||
"RR B","RR C","RR D","RR E","RR H","RR L","RR (I%@h)","RR A",
|
||||
"SLA B","SLA C","SLA D","SLA E","SLA H","SLA L","SLA (I%@h)","SLA A",
|
||||
"SRA B","SRA C","SRA D","SRA E","SRA H","SRA L","SRA (I%@h)","SRA A",
|
||||
"SLL B","SLL C","SLL D","SLL E","SLL H","SLL L","SLL (I%@h)","SLL A",
|
||||
"SRL B","SRL C","SRL D","SRL E","SRL H","SRL L","SRL (I%@h)","SRL A",
|
||||
"BIT 0,B","BIT 0,C","BIT 0,D","BIT 0,E","BIT 0,H","BIT 0,L","BIT 0,(I%@h)","BIT 0,A",
|
||||
"BIT 1,B","BIT 1,C","BIT 1,D","BIT 1,E","BIT 1,H","BIT 1,L","BIT 1,(I%@h)","BIT 1,A",
|
||||
"BIT 2,B","BIT 2,C","BIT 2,D","BIT 2,E","BIT 2,H","BIT 2,L","BIT 2,(I%@h)","BIT 2,A",
|
||||
"BIT 3,B","BIT 3,C","BIT 3,D","BIT 3,E","BIT 3,H","BIT 3,L","BIT 3,(I%@h)","BIT 3,A",
|
||||
"BIT 4,B","BIT 4,C","BIT 4,D","BIT 4,E","BIT 4,H","BIT 4,L","BIT 4,(I%@h)","BIT 4,A",
|
||||
"BIT 5,B","BIT 5,C","BIT 5,D","BIT 5,E","BIT 5,H","BIT 5,L","BIT 5,(I%@h)","BIT 5,A",
|
||||
"BIT 6,B","BIT 6,C","BIT 6,D","BIT 6,E","BIT 6,H","BIT 6,L","BIT 6,(I%@h)","BIT 6,A",
|
||||
"BIT 7,B","BIT 7,C","BIT 7,D","BIT 7,E","BIT 7,H","BIT 7,L","BIT 7,(I%@h)","BIT 7,A",
|
||||
"RES 0,B","RES 0,C","RES 0,D","RES 0,E","RES 0,H","RES 0,L","RES 0,(I%@h)","RES 0,A",
|
||||
"RES 1,B","RES 1,C","RES 1,D","RES 1,E","RES 1,H","RES 1,L","RES 1,(I%@h)","RES 1,A",
|
||||
"RES 2,B","RES 2,C","RES 2,D","RES 2,E","RES 2,H","RES 2,L","RES 2,(I%@h)","RES 2,A",
|
||||
"RES 3,B","RES 3,C","RES 3,D","RES 3,E","RES 3,H","RES 3,L","RES 3,(I%@h)","RES 3,A",
|
||||
"RES 4,B","RES 4,C","RES 4,D","RES 4,E","RES 4,H","RES 4,L","RES 4,(I%@h)","RES 4,A",
|
||||
"RES 5,B","RES 5,C","RES 5,D","RES 5,E","RES 5,H","RES 5,L","RES 5,(I%@h)","RES 5,A",
|
||||
"RES 6,B","RES 6,C","RES 6,D","RES 6,E","RES 6,H","RES 6,L","RES 6,(I%@h)","RES 6,A",
|
||||
"RES 7,B","RES 7,C","RES 7,D","RES 7,E","RES 7,H","RES 7,L","RES 7,(I%@h)","RES 7,A",
|
||||
"SET 0,B","SET 0,C","SET 0,D","SET 0,E","SET 0,H","SET 0,L","SET 0,(I%@h)","SET 0,A",
|
||||
"SET 1,B","SET 1,C","SET 1,D","SET 1,E","SET 1,H","SET 1,L","SET 1,(I%@h)","SET 1,A",
|
||||
"SET 2,B","SET 2,C","SET 2,D","SET 2,E","SET 2,H","SET 2,L","SET 2,(I%@h)","SET 2,A",
|
||||
"SET 3,B","SET 3,C","SET 3,D","SET 3,E","SET 3,H","SET 3,L","SET 3,(I%@h)","SET 3,A",
|
||||
"SET 4,B","SET 4,C","SET 4,D","SET 4,E","SET 4,H","SET 4,L","SET 4,(I%@h)","SET 4,A",
|
||||
"SET 5,B","SET 5,C","SET 5,D","SET 5,E","SET 5,H","SET 5,L","SET 5,(I%@h)","SET 5,A",
|
||||
"SET 6,B","SET 6,C","SET 6,D","SET 6,E","SET 6,H","SET 6,L","SET 6,(I%@h)","SET 6,A",
|
||||
"SET 7,B","SET 7,C","SET 7,D","SET 7,E","SET 7,H","SET 7,L","SET 7,(I%@h)","SET 7,A"
|
||||
};
|
||||
#if 1
|
||||
/** DAsm() ***************************************************/
|
||||
/** DAsm() will disassemble the code at adress A and put **/
|
||||
/** the output text into S. It will return the number of **/
|
||||
/** bytes disassembled. **/
|
||||
/*************************************************************/
|
||||
static int DAsm(char *S,word A)
|
||||
{
|
||||
char R[128],H[10],C,*T,*P;
|
||||
byte J,Offset=0;
|
||||
word B;
|
||||
|
||||
B=A;C='\0';J=0;
|
||||
|
||||
switch(RdZ80(B))
|
||||
{
|
||||
case 0xCB: B++;T=MnemonicsCB[RdZ80(B++)];break;
|
||||
case 0xED: B++;T=MnemonicsED[RdZ80(B++)];break;
|
||||
case 0xDD: B++;C='X';
|
||||
if(RdZ80(B)!=0xCB) T=MnemonicsXX[RdZ80(B++)];
|
||||
else
|
||||
{ B++;Offset=RdZ80(B++);J=1;T=MnemonicsXCB[RdZ80(B++)]; }
|
||||
break;
|
||||
case 0xFD: B++;C='Y';
|
||||
if(RdZ80(B)!=0xCB) T=MnemonicsXX[RdZ80(B++)];
|
||||
else
|
||||
{ B++;Offset=RdZ80(B++);J=1;T=MnemonicsXCB[RdZ80(B++)]; }
|
||||
break;
|
||||
default: T=Mnemonics[RdZ80(B++)];
|
||||
}
|
||||
|
||||
if((P=strchr(T,'^')))
|
||||
{
|
||||
strncpy(R,T,P-T);R[P-T]='\0';
|
||||
sprintf(H,"%02X",RdZ80(B++));
|
||||
strcat(R,H);strcat(R,P+1);
|
||||
}
|
||||
else strcpy(R,T);
|
||||
if((P=strchr(R,'%'))) *P=C;
|
||||
|
||||
if((P=strchr(R,'*')))
|
||||
{
|
||||
strncpy(S,R,P-R);S[P-R]='\0';
|
||||
sprintf(H,"%02X",RdZ80(B++));
|
||||
strcat(S,H);strcat(S,P+1);
|
||||
}
|
||||
else
|
||||
if((P=strchr(R,'@')))
|
||||
{
|
||||
strncpy(S,R,P-R);S[P-R]='\0';
|
||||
if(!J) Offset=RdZ80(B++);
|
||||
strcat(S,Offset&0x80? "-":"+");
|
||||
J=Offset&0x80? 256-Offset:Offset;
|
||||
sprintf(H,"%02X",J);
|
||||
strcat(S,H);strcat(S,P+1);
|
||||
}
|
||||
else
|
||||
if((P=strchr(R,'#')))
|
||||
{
|
||||
strncpy(S,R,P-R);S[P-R]='\0';
|
||||
sprintf(H,"%04X",RdZ80(B)+256*RdZ80(B+1));
|
||||
strcat(S,H);strcat(S,P+1);
|
||||
B+=2;
|
||||
}
|
||||
else strcpy(S,R);
|
||||
|
||||
return(B-A);
|
||||
}
|
||||
|
||||
/** DebugZ80() ***********************************************/
|
||||
/** This function should exist if DEBUG is #defined. When **/
|
||||
/** Trace!=0, it is called after each command executed by **/
|
||||
/** the CPU, and given the Z80 registers. **/
|
||||
/*************************************************************/
|
||||
byte DebugZ80(Z80 *R)
|
||||
{
|
||||
static char Flags[8] = "SZ.H.PNC";
|
||||
char S[128],T[10];
|
||||
byte J,I;
|
||||
|
||||
DAsm(S,R->PC.W);
|
||||
for(J=0,I=R->AF.B.l;J<8;J++,I<<=1) T[J]=I&0x80? Flags[J]:'.';
|
||||
T[8]='\0';
|
||||
|
||||
printf
|
||||
(
|
||||
"AF:%04X HL:%04X DE:%04X BC:%04X PC:%04X SP:%04X IX:%04X IY:%04X\n",
|
||||
R->AF.W,R->HL.W,R->DE.W,R->BC.W,R->PC.W,R->SP.W,R->IX.W,R->IY.W
|
||||
);
|
||||
printf
|
||||
(
|
||||
"AT PC: [%02X - %s] AT SP: [%04X] FLAGS: [%s]\n\n",
|
||||
RdZ80(R->PC.W),S,RdZ80(R->SP.W)+RdZ80(R->SP.W+1)*256,T
|
||||
);
|
||||
|
||||
while(1)
|
||||
{
|
||||
printf("\n[Command,'?']-> ");
|
||||
fflush(stdout);fflush(stdin);
|
||||
|
||||
fgets(S,50,stdin);
|
||||
for(J=0;S[J]>=' ';J++)
|
||||
S[J]=toupper(S[J]);
|
||||
S[J]='\0';
|
||||
|
||||
switch(S[0])
|
||||
{
|
||||
case 'H':
|
||||
case '?':
|
||||
puts("\n***** Built-in Z80 Debugger Commands *****");
|
||||
puts("<CR> : Break at next instruction");
|
||||
puts("= <addr> : Break at addr");
|
||||
puts("+ <offset> : Break at PC + offset");
|
||||
puts("c : Continue without break");
|
||||
puts("j <addr> : Continue from addr");
|
||||
puts("m <addr> : Memory dump at addr");
|
||||
puts("d <addr> : Disassembly at addr");
|
||||
puts("?,h : Show this help text");
|
||||
puts("q : Exit Z80 emulation");
|
||||
break;
|
||||
|
||||
case '\0': return(1);
|
||||
case '=': if(strlen(S)>=2)
|
||||
{ sscanf(S+1,"%hX",&(R->Trap));R->Trace=0;return(1); }
|
||||
break;
|
||||
case '+': if(strlen(S)>=2)
|
||||
{
|
||||
sscanf(S+1,"%hX",&(R->Trap));
|
||||
R->Trap+=R->PC.W;R->Trace=0;
|
||||
return(1);
|
||||
}
|
||||
break;
|
||||
case 'J': if(strlen(S)>=2)
|
||||
{ sscanf(S+1,"%hX",&(R->PC.W));R->Trace=0;return(1); }
|
||||
break;
|
||||
case 'C': R->Trap=0xFFFF;R->Trace=0;return(1);
|
||||
case 'Q': return(0);
|
||||
|
||||
case 'M':
|
||||
{
|
||||
word Addr;
|
||||
|
||||
if(strlen(S)>1) sscanf(S+1,"%hX",&Addr); else Addr=R->PC.W;
|
||||
puts("");
|
||||
for(J=0;J<16;J++)
|
||||
{
|
||||
printf("%04X: ",Addr);
|
||||
for(I=0;I<16;I++,Addr++)
|
||||
printf("%02X ",RdZ80(Addr));
|
||||
printf(" | ");Addr-=16;
|
||||
for(I=0;I<16;I++,Addr++)
|
||||
putchar(isprint(RdZ80(Addr))? RdZ80(Addr):'.');
|
||||
puts("");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
{
|
||||
word Addr;
|
||||
|
||||
if(strlen(S)>1) sscanf(S+1,"%hX",&Addr); else Addr=R->PC.W;
|
||||
puts("");
|
||||
for(J=0;J<16;J++)
|
||||
{
|
||||
printf("%04X: ",Addr);
|
||||
Addr+=DAsm(S,Addr);
|
||||
puts(S);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Continue emulation */
|
||||
return(1);
|
||||
}
|
||||
#endif
|
||||
#endif /* DEBUG */
|
|
@ -0,0 +1,140 @@
|
|||
TIKI-100_emul V1.1.1, 25 august 2001
|
||||
------------------------------------
|
||||
|
||||
Dette er kildefilene til TIKI-100_emul. Denne fila gir en oppskrift på
|
||||
hvordan kompilere. Den gir også en generell beskrivelse av
|
||||
kildefilene dersom du skulle være interessert i det, men det er ikke
|
||||
nødvendig dersom du bare vil kompilere og få en kjørbar emulator. For
|
||||
mer informasjon om bruk av emulatoren, se TIKI-100_emul.txt.
|
||||
|
||||
Bortsett fra filene til Z80-emulatoren, er alle kildefilene mine. Jeg
|
||||
gir tillatelse til å bruke og spre disse fritt. Men ønsker du å gjøre
|
||||
forandringer vil jeg at du tar kontakt med meg. Dette fordi jeg ikke
|
||||
anser meg for ferdig med emulatoren enda. På den måten unngår vi at
|
||||
flere forskjellige personer jobber på de samme tingene. Men kom gjerne
|
||||
med forslag til hvordan ting kan gjøres bedre.
|
||||
|
||||
Disse kildefilene skal ikke brukes til kommersielle formål på noen som
|
||||
helst måte, hverken i original eller modifisert form.
|
||||
|
||||
Kompilering:
|
||||
------------
|
||||
|
||||
Kompilering skal være temmelig enkelt. Kildefilene er skrevet i
|
||||
ansi-c og skal kompilere med de aller fleste c-kompilatorer. Makefile
|
||||
er skrevet for GCC og GNU make. For unix vil du ofte ha det som trengs
|
||||
allerede. For win32 må du skaffe deg cygwin, som finnes gratis på
|
||||
http://www.cygwin.com. En full installasjon anbefales. Amigaversjonen
|
||||
kan kompileres med verktøyene fra Geek Gadgets som finnes gratis på
|
||||
http://www.ninemoons.com. Dessuten trenger du NDK fra Amiga
|
||||
International, inc. Disse finner du bl.a på Amiga Developer CD.
|
||||
|
||||
Før kompilering må filen Makefile justeres til å passe ditt
|
||||
system. For Amiga og win32 vil dette bare bestå i å velge rett
|
||||
system. For unix må du i tillegg sette en del andre ting. Alt dette
|
||||
skal være forklart i Makefile.
|
||||
|
||||
Etter dette er det bare å skrive "make" i katalogen du har kildefilene
|
||||
i. Resultatet blir en kjørbar fil tikiemul eller tikiemul.exe. Kopier
|
||||
(minimum) denne fila og tiki.rom dit du ønsker å ha programmet. I
|
||||
tillegg anbefaler jeg at du kopierer plater-katalogen og
|
||||
TIKI-100_emul.txt til samme plass. Så skulle alt være klart til bruk.
|
||||
|
||||
Har du problemer, så ta kontakt med meg.
|
||||
|
||||
Generell beskrivelse av kildefiler:
|
||||
-----------------------------------
|
||||
|
||||
Skal du forstå hvordan denne emulatoren virker, bør du kjenne til
|
||||
hvordan en TIKI-100 fungerer. Se på min TIKI-100 hjemmeside for mer
|
||||
informasjon om det.
|
||||
|
||||
Disse filene skal være med:
|
||||
|
||||
Systemuavhengige filer (selve emulatorkoden):
|
||||
- TIKI-100_emul.c Hovedmodul, inneholder toppnivå
|
||||
emulatorrutiner
|
||||
- TIKI-100_emul.h Inneholder alle prototyper, konstanter
|
||||
etc. som er nødvendig for den
|
||||
systemspesifikke koden.
|
||||
- ctc.c Z80-CTC emulering
|
||||
- disk.c FD17xx emulering
|
||||
- keyboard.c Tastaturhåndtering
|
||||
- mem.c RAM og I/O-port håndtering
|
||||
- parallel.c Z80-PIO emulering
|
||||
- protos.h Prototyper for funksjoner internt i den
|
||||
systemuavhengige koden.
|
||||
- serial.c Z80-DART emulering
|
||||
- sound.c AY-3-8912 emulering
|
||||
- video.c Videoemulering
|
||||
|
||||
Z80-emulator av Marat Fayzullin. Disse filene er inkludert med
|
||||
tillatelse men tilhører ikke meg. Les egen copyrightnotis i filene og
|
||||
se på http://www.komkon.org/fms/EMUL8 for mer informasjon:
|
||||
- Z80.c
|
||||
- Z80.h
|
||||
- Codes.h
|
||||
- CodesCB.h
|
||||
- CodesED.h
|
||||
- CodesXCB.h
|
||||
- CodesXX.h
|
||||
- Debug.c
|
||||
- Tables.h
|
||||
|
||||
Systemkode for Amiga:
|
||||
- amiga.c
|
||||
- amiga.cd Katalogdeskriptor (locale)
|
||||
- amiga_icons/* Diverse ikoner
|
||||
- amiga_translations/* Oversettelser til andre språk
|
||||
|
||||
Systemkode for win32:
|
||||
- win32.c
|
||||
- win32.ico Ikoner
|
||||
- win32_res.h Konstanter brukt av resources
|
||||
- win32_res.rc Resources
|
||||
|
||||
Systemkode for unix:
|
||||
- unix.c
|
||||
|
||||
Andre filer:
|
||||
- Makefile GNU make kompatibel Makefile
|
||||
- plater/t90.dsk Tom 90k diskfil
|
||||
- plater/t200.dsk Tom 200k diskfil
|
||||
- plater/t400.dsk Tom 400k diskfil
|
||||
- plater/t800.dsk Tom 800k diskfil
|
||||
- plater/tiko_kjerne_v4.01.dsk TIKO-systemdiskett
|
||||
- tiki.rom TIKI-100 rombilde
|
||||
- TIKI-100_emul.txt Beskrivelse av emulatoren
|
||||
- LESMEG Filen du leser på nå
|
||||
|
||||
Som du ser kan kildefilene deles inn i 2 grupper. Den systemuavhengige
|
||||
koden som inneholder alt som kan programmeres uten bruk av annet enn
|
||||
standard c-bibliotek, og systemkoden som inneholder de tingene som må
|
||||
programmeres for et spesielt system (bl.a GUI). Dette vil si at all
|
||||
emulatorlogikk er adskilt fra systemkoden.
|
||||
|
||||
Grensesnittet mellom disse to delene er laget så enkelt som mulig og
|
||||
er definert i TIKI-100_emul.h (i form av prototyper for funksjoner som
|
||||
må implementeres og funksjoner som kan kalles). Dette er den eneste
|
||||
fila man trenger kjennskap til dersom man ønsker å lage en versjon for
|
||||
et nytt system. Har du lyst til dette, så ta kontakt med meg.
|
||||
|
||||
Emulatorens main() funksjon (eller tilsvarende) befinner seg i
|
||||
systemkoden. Når systemkoden er klar til å starte emulatorkoden kaller
|
||||
den runEmul() som tar over kontrollen (går i en uendelig loop). Hver
|
||||
80.000 cycle (skal tilsvare 20 ms) kalles funksjonen loopEmul() i
|
||||
systemkoden. Dette gjør systemkoden i stand til å måle og senke
|
||||
hastighet samt sjekke brukeraktivitet. Resten av funksjonene som
|
||||
systemkoden må implementere (definert i TIKI-100_emul.h) kalles
|
||||
etterhvert som emulatoren har bruk for de.
|
||||
|
||||
Etter noe initialisering vil runEmul() starte Z80 emulator. Z80
|
||||
emulator trenger funksjoner for å lese/skrive til/fra
|
||||
RAM/ROM/IO. Disse (sammen med emulert RAM/ROM) er implementert i
|
||||
mem.c. Disse funksjonene vil, hver gang Z80 emulator benytter I/O,
|
||||
kalle en funksjon i en av de andre c-filene. F.eks dersom Z80 leser
|
||||
fra I/O-port 0x03 (tastatur-register) vil funksjonen readKeyboard() i
|
||||
keyboard.c kalles. Tilsvarende for alle andre I/O-porter.
|
||||
|
||||
---
|
||||
Asbjørn Djupdal, djupdal@stud.ntnu.no
|
|
@ -0,0 +1,148 @@
|
|||
# Makefile for TIKI-100_emul V1.1
|
||||
# Asbjørn Djupdal 2001
|
||||
#
|
||||
# make - Bygger emulator
|
||||
# make clean - Sletter alle automatisk genererte filer
|
||||
# make amiga_translations - kompilerer catalog-filer for Amiga-versjon
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Generelle innstillinger
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
# Velg system du skal kompilere for:
|
||||
#SYSTEM = amiga
|
||||
#SYSTEM = win32
|
||||
SYSTEM = unix
|
||||
|
||||
# Ta med denne dersom Z80-debugger ønskes inkludert:
|
||||
#Z80_DEBUGGER = -DDEBUG
|
||||
|
||||
# Velg C-kompilator du ønsker å bruke:
|
||||
CC = gcc
|
||||
|
||||
# Generelle kompilatoropsjoner:
|
||||
CFLAGS = -Wall -O
|
||||
|
||||
# Generelle linkeropsjoner:
|
||||
LDFLAGS = -s
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Dersom SYSTEM=unix må følgende settes:
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
# Velg CPU-type - big-endian eller little-endian:
|
||||
#ENDIAN = -DMSB_FIRST # big-endian CPU, bl.a: M68k, Sun-maskiner
|
||||
ENDIAN = -DLSB_FIRST # little-endian CPU, bl.a: intel-x86
|
||||
|
||||
# Skriv inn stien til X11-includefiler:
|
||||
X11_INCLUDE_PATH = -I/usr/X11R6/include
|
||||
|
||||
# Skriv inn stien til X11-linkbibliotek:
|
||||
X11_LIB_PATH = -L/usr/X11R6/lib
|
||||
|
||||
# Skriv inn hvilke bibliotek som må linkes:
|
||||
X11_LINK_LIBS = -lX11
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Det skal ikke være nødvendig å forandre på resten av denne filen!
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Systemspesifikke innstillinger
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
# amiga
|
||||
CFLAGS_amiga = -DMSB_FIRST $(CFLAGS) $(Z80_DEBUGGER)
|
||||
LDFLAGS_amiga = -lm -noixemul $(LDFLAGS)
|
||||
SYS_OBJECTS_amiga = amiga.o
|
||||
|
||||
# win32
|
||||
NO_CONSOLE_ = -mno-cygwin -Wl,--subsystem,windows
|
||||
CFLAGS_win32 = -DLSB_FIRST $(CFLAGS) $(Z80_DEBUGGER)
|
||||
LDFLAGS_win32 = $(NO_CONSOLE_$(Z80_DEBUGGER)) -e _mainCRTStartup -lgdi32 -lcomdlg32 -lcomctl32 $(LDFLAGS)
|
||||
SYS_OBJECTS_win32 = win32.o win32_res.res
|
||||
|
||||
# unix
|
||||
CFLAGS_unix = $(ENDIAN) $(X11_INCLUDE_PATH) $(CFLAGS) $(Z80_DEBUGGER)
|
||||
LDFLAGS_unix = $(LDFLAGS) $(X11_LIB_PATH) $(X11_LINK_LIBS)
|
||||
SYS_OBJECTS_unix = unix.o
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Regler
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
# Alle objektfiler som skal linkes
|
||||
OBJECTS = TIKI-100_emul.o mem.o video.o sound.o ctc.o keyboard.o disk.o serial.o parallel.o Z80.o Debug.o $(SYS_OBJECTS_$(SYSTEM))
|
||||
|
||||
tikiemul : $(OBJECTS) Makefile
|
||||
$(CC) -o $@ $(OBJECTS) $(LDFLAGS_$(SYSTEM))
|
||||
|
||||
TIKI-100_emul.o : TIKI-100_emul.c TIKI-100_emul.h protos.h Z80.h Makefile
|
||||
$(CC) -c $< $(CFLAGS_$(SYSTEM))
|
||||
|
||||
mem.o : mem.c TIKI-100_emul.h protos.h Z80.h Makefile
|
||||
$(CC) -c $< $(CFLAGS_$(SYSTEM))
|
||||
|
||||
video.o : video.c TIKI-100_emul.h protos.h Z80.h Makefile
|
||||
$(CC) -c $< $(CFLAGS_$(SYSTEM))
|
||||
|
||||
sound.o : sound.c TIKI-100_emul.h protos.h Z80.h Makefile
|
||||
$(CC) -c $< $(CFLAGS_$(SYSTEM))
|
||||
|
||||
ctc.o : ctc.c TIKI-100_emul.h protos.h Z80.h Makefile
|
||||
$(CC) -c $< $(CFLAGS_$(SYSTEM))
|
||||
|
||||
keyboard.o : keyboard.c TIKI-100_emul.h protos.h Z80.h Makefile
|
||||
$(CC) -c $< $(CFLAGS_$(SYSTEM))
|
||||
|
||||
disk.o : disk.c TIKI-100_emul.h protos.h Z80.h Makefile
|
||||
$(CC) -c $< $(CFLAGS_$(SYSTEM))
|
||||
|
||||
serial.o : serial.c TIKI-100_emul.h protos.h Z80.h Makefile
|
||||
$(CC) -c $< $(CFLAGS_$(SYSTEM))
|
||||
|
||||
parallel.o : parallel.c TIKI-100_emul.h protos.h Z80.h Makefile
|
||||
$(CC) -c $< $(CFLAGS_$(SYSTEM))
|
||||
|
||||
Z80.o : Z80.c Z80.h Codes.h CodesED.h CodesCB.h CodesXX.h Tables.h CodesXCB.h Makefile
|
||||
$(CC) -c $< $(CFLAGS_$(SYSTEM))
|
||||
|
||||
Debug.o : Debug.c Z80.h Makefile
|
||||
$(CC) -c $< $(CFLAGS_$(SYSTEM))
|
||||
|
||||
.PHONY : clean
|
||||
clean :
|
||||
rm -rf tikiemul tikiemul.exe amiga_strings.h *.res *.o *~ catalogs
|
||||
|
||||
#------
|
||||
# amiga
|
||||
#------
|
||||
|
||||
amiga.o : amiga.c amiga_strings.h TIKI-100_emul.h Z80.h Makefile
|
||||
$(CC) -c $< $(CFLAGS_$(SYSTEM))
|
||||
|
||||
amiga_strings.h : amiga.cd Makefile
|
||||
catcomp DESCRIPTOR amiga.cd CFILE amiga_strings.h
|
||||
|
||||
.PHONY : amiga_translations
|
||||
amiga_translations :
|
||||
mkdir -p catalogs/norsk
|
||||
catcomp DESCRIPTOR amiga.cd TRANSLATION amiga_translations/norsk.ct CATALOG catalogs/norsk/tikiemul.catalog VB 0
|
||||
|
||||
#------
|
||||
# win32
|
||||
#------
|
||||
|
||||
win32.o : win32.c win32_res.h TIKI-100_emul.h Z80.h Makefile
|
||||
$(CC) -c $< $(CFLAGS_$(SYSTEM))
|
||||
|
||||
win32_res.res : win32_res.rc win32_res.h TIKI-100_emul.h Z80.h Makefile
|
||||
windres $< $(Z80_DEBUGGER) -O coff -o $@
|
||||
|
||||
#------
|
||||
# unix
|
||||
#------
|
||||
|
||||
unix.o : unix.c TIKI-100_emul.h Z80.h Makefile
|
||||
$(CC) -c $< $(CFLAGS_$(SYSTEM))
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
TIKI-100_emul V1.1.1, 25-aug-2001
|
||||
|
||||
A freeware TIKI-100 Rev. C emulator
|
||||
|
||||
Z80 emulation copyright (C) Marat Fayzullin
|
||||
The rest is copyright (C) Asbjørn Djupdal
|
||||
|
||||
I permit redistribution and free use of this emulator. It is not legal
|
||||
to use it for commersial purposes.
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
This emulator emulates the TIKI-100 computer, a norwegian
|
||||
home computer released in 1984. It uses a norwegian operating system,
|
||||
TIKO, compatible with CP/M-2.2.
|
||||
|
||||
It should be quite easy to understand how to use the emulator if you
|
||||
are familiar with how emulators in general works. If you have any
|
||||
problems at all, contact me (email-address below).
|
||||
|
||||
I'm sorry this text doesn't describe the emulator in more detail, but
|
||||
because of it's norwegian operating system I guess most people that is
|
||||
interested can read norwegian. See the norwegian text for more detail.
|
||||
|
||||
My TIKI-100 homepage, with TIKI programs, information and
|
||||
emulator-source/binaries is located here (norwegian only):
|
||||
|
||||
http://www.stud.ntnu.no/~djupdal/tiki/
|
||||
|
||||
Send comments and questions to:
|
||||
|
||||
djupdal@stud.ntnu.no
|
|
@ -0,0 +1,58 @@
|
|||
/* TIKI-100_emul.c V1.1.0
|
||||
*
|
||||
* Hovedmodul for TIKI-100_emul
|
||||
* Copyright (C) Asbjørn Djupdal 2000-2001
|
||||
*/
|
||||
|
||||
#include "TIKI-100_emul.h"
|
||||
#include "protos.h"
|
||||
|
||||
/* variabler */
|
||||
|
||||
Z80 cpu;
|
||||
static boolean done = FALSE;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* starter emulering, returnerer når emulering avslutter */
|
||||
boolean runEmul (void) {
|
||||
#ifdef DEBUG
|
||||
cpu.Trap = 0xffff;
|
||||
#endif
|
||||
cpu.IPeriod = 4000;
|
||||
if (initMem()) {
|
||||
ResetZ80 (&cpu);
|
||||
RunZ80 (&cpu);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
/* ikke i bruk */
|
||||
void PatchZ80 (register Z80 *R) {
|
||||
}
|
||||
/* kalles regelmessig av z80-emulator */
|
||||
word LoopZ80 (register Z80 *R) {
|
||||
static int guiCount = 20;
|
||||
if (done) return INT_QUIT;
|
||||
updateCTC (cpu.IPeriod);
|
||||
if (--guiCount == 0) {
|
||||
loopEmul (20);
|
||||
guiCount = 20;
|
||||
}
|
||||
return INT_NONE;
|
||||
}
|
||||
/* reset emulator */
|
||||
void resetEmul (void) {
|
||||
OutZ80 (0x1c, 0x00);
|
||||
ResetZ80 (&cpu);
|
||||
}
|
||||
/* avslutt emulator */
|
||||
void quitEmul (void) {
|
||||
done = TRUE;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
/* start z80-debugger */
|
||||
void trace (void) {
|
||||
cpu.Trace = 1;
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,200 @@
|
|||
/* TIKI-100_emul.h V1.1.0
|
||||
*
|
||||
* Definisjoner og konstanter nyttige for alle TIKI-100_emul moduler
|
||||
* Copyright (C) Asbjørn Djupdal 2000-2001
|
||||
*/
|
||||
|
||||
#ifndef TIKI_EMUL_H
|
||||
#define TIKI_EMUL_H
|
||||
|
||||
#include "Z80.h"
|
||||
|
||||
/* byte og word definert i Z80.h */
|
||||
typedef short boolean;
|
||||
|
||||
#define TRUE ~0
|
||||
#define FALSE 0
|
||||
|
||||
/* video */
|
||||
|
||||
#define HIGHRES 16 /* 1024 * 256 * 2 */
|
||||
#define MEDRES 32 /* 512 * 256 * 4 */
|
||||
#define LOWRES 48 /* 256 * 256 * 16 */
|
||||
|
||||
/* serie */
|
||||
|
||||
enum parity {
|
||||
PAR_NONE, PAR_EVEN, PAR_ODD
|
||||
};
|
||||
enum stopBits {
|
||||
ONE_SB, ONE_PT_FIVE_SB, TWO_SB
|
||||
};
|
||||
struct serParams {
|
||||
int receiveBits; /* antall bits i innkommende tegn */
|
||||
int sendBits; /* antall bits i tegn som sendes */
|
||||
int parity; /* paritet, en av de angitt over */
|
||||
int stopBits; /* antall stopbits, en av de angitt over */
|
||||
int baud; /* baud */
|
||||
/* følgende er kun for bruk i serial.c: */
|
||||
int regPtr;
|
||||
int clkDiv;
|
||||
boolean exi;
|
||||
boolean txi;
|
||||
boolean sav;
|
||||
int rxi;
|
||||
boolean rxe;
|
||||
boolean ae;
|
||||
boolean txe;
|
||||
boolean rxa;
|
||||
boolean newChar;
|
||||
};
|
||||
|
||||
/* tastatur - ikke-alfanumeriske taster */
|
||||
|
||||
#define KEY_NONE 0x80
|
||||
#define KEY_CTRL 0x81
|
||||
#define KEY_SHIFT 0x82
|
||||
#define KEY_BRYT 0x03
|
||||
#define KEY_CR 0x0d
|
||||
#define KEY_SPACE 0x20
|
||||
#define KEY_SLETT 0x7f
|
||||
#define KEY_GRAFIKK 0x84
|
||||
#define KEY_ANGRE 0x1a
|
||||
#define KEY_LOCK 0x83
|
||||
#define KEY_HJELP 0x0a
|
||||
#define KEY_LEFT 0x08
|
||||
#define KEY_UTVID 0x05
|
||||
#define KEY_F1 0x01
|
||||
#define KEY_F4 0x07
|
||||
#define KEY_RIGHT 0x0c
|
||||
#define KEY_F2 0x02
|
||||
#define KEY_F3 0x06
|
||||
#define KEY_F5 0x0e
|
||||
#define KEY_F6 0x0f
|
||||
#define KEY_DOWN 0x1c
|
||||
#define KEY_PGUP 0x17
|
||||
#define KEY_PGDOWN 0x1f
|
||||
#define KEY_UP 0x0b
|
||||
#define KEY_HOME 0x09
|
||||
#define KEY_TABLEFT 0x1d
|
||||
#define KEY_TABRIGHT 0x18
|
||||
#define KEY_NUMDIV 0x80 | 0x2f
|
||||
#define KEY_NUMPLUS 0x80 | 0x2b
|
||||
#define KEY_NUMMINUS 0x80 | 0x2d
|
||||
#define KEY_NUMMULT 0x80 | 0x2a
|
||||
#define KEY_NUMPERCENT 0x80 | 0x25
|
||||
#define KEY_NUMEQU 0x80 | 0x3d
|
||||
#define KEY_ENTER 0x80 | 0x0d
|
||||
#define KEY_NUM0 0x80 | 0x30
|
||||
#define KEY_NUM1 0x80 | 0x31
|
||||
#define KEY_NUM2 0x80 | 0x32
|
||||
#define KEY_NUM3 0x80 | 0x33
|
||||
#define KEY_NUM4 0x80 | 0x34
|
||||
#define KEY_NUM5 0x80 | 0x35
|
||||
#define KEY_NUM6 0x80 | 0x36
|
||||
#define KEY_NUM7 0x80 | 0x37
|
||||
#define KEY_NUM8 0x80 | 0x38
|
||||
#define KEY_NUM9 0x80 | 0x39
|
||||
#define KEY_NUMDOT 0x80 | 0x2e
|
||||
|
||||
/* Må implementeres av system-koden
|
||||
**********************************/
|
||||
|
||||
/* Forandre oppløsning.
|
||||
* Må samtidig fylle alle pixler med farge 0
|
||||
*/
|
||||
void changeRes (int newRes);
|
||||
|
||||
/* Plott en pixel med farge tatt fra pallett */
|
||||
void plotPixel (int x, int y, int color);
|
||||
|
||||
/* Scroll skjerm 'distance' linjer oppover
|
||||
* 'distance' kan være både positiv og negativ
|
||||
*/
|
||||
void scrollScreen (int distance);
|
||||
|
||||
/* Ny farge, gitt pallettnummer og intensitet 0-255.
|
||||
* Må oppdatere alle pixler med dette pallettnummeret til ny farge
|
||||
*/
|
||||
void changePalette (int colornumber, byte red, byte green, byte blue);
|
||||
|
||||
/* Kalles periodisk. Lar system kode måle / senke emuleringshastighet
|
||||
* Kan også brukes til sjekk av brukeraktivitet / serieporter
|
||||
* ms er antall "emulerte" millisekunder siden forrige gang loopEmul ble kalt
|
||||
*/
|
||||
void loopEmul (int ms);
|
||||
|
||||
/* Tenn/slukk lock lys */
|
||||
void lockLight (boolean status);
|
||||
|
||||
/* Tenn/slukk grafikk lys */
|
||||
void grafikkLight (boolean status);
|
||||
|
||||
/* Tenn/slukk disk lys for gitt stasjon */
|
||||
void diskLight (int drive, boolean status);
|
||||
|
||||
/* Sjekk status til hver av de gitte tastene
|
||||
* Sett bit n i returkode hvis tast n IKKE er nedtrykt
|
||||
* Taster er enten ascii-kode eller en av konstantene over
|
||||
*/
|
||||
byte testKey (byte keys[8]);
|
||||
|
||||
/* Setter seriekanalparametre */
|
||||
void setParams (struct serParams *p1Params, struct serParams *p2Params);
|
||||
|
||||
/* Send tegn til seriekanal
|
||||
* port = 0: port 1
|
||||
* port = 1: port 2
|
||||
*/
|
||||
void sendChar (int port, byte value);
|
||||
|
||||
/* Hent tegn fra seriekanal
|
||||
* port = 0: port 1
|
||||
* port = 1: port 2
|
||||
*/
|
||||
byte getChar (int port);
|
||||
|
||||
/* Send tegn til skriver (port 3) */
|
||||
void printChar (byte value);
|
||||
|
||||
/* Kan kalles av system-koden
|
||||
****************************/
|
||||
|
||||
/* Starter emulering, returnerer når emulering avsluttes
|
||||
* Returverdi ved feil: FALSE
|
||||
* Ellers returneres TRUE (etter at quitEmul() er kalt)
|
||||
*/
|
||||
boolean runEmul (void);
|
||||
|
||||
/* Ny diskett i stasjon
|
||||
* disk: Hvilken stasjon (0 eller 1)
|
||||
* diskImage: Peker til diskettbilde-data
|
||||
* Resten er diskparametre
|
||||
*/
|
||||
void insertDisk (int drive, byte *diskImage, int tracks,
|
||||
int sides, int sectors, int sectSize);
|
||||
|
||||
/* Fjern diskett fra stasjon (0 eller 1) */
|
||||
void removeDisk (int drive);
|
||||
|
||||
/* Resetter TIKI-100 */
|
||||
void resetEmul (void);
|
||||
|
||||
/* Avslutter emulator */
|
||||
void quitEmul (void);
|
||||
|
||||
#ifdef DEBUG
|
||||
/* Åpner avlusnings monitor */
|
||||
void trace (void);
|
||||
#endif
|
||||
|
||||
/* Setter bøyle ST 28 b */
|
||||
void setST28b (boolean status);
|
||||
|
||||
/* Nytt serietegn mottatt
|
||||
* port = 0: port 1
|
||||
* port = 1: port 2
|
||||
*/
|
||||
void charAvailable (int port);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,339 @@
|
|||
TIKI-100_emul V1.1.1, 25 august 2001
|
||||
|
||||
En freeware TIKI-100 Rev. C emulator
|
||||
|
||||
Z80 emulering copyright (C) Marat Fayzullin.
|
||||
Resten copyright (C) Asbjørn Djupdal.
|
||||
|
||||
Jeg gir tillatelse til å bruke og spre denne emulatoren fritt bortsett
|
||||
fra til kommersielle formål. Det skal aldri tjenes penger på denne
|
||||
emulatoren.
|
||||
|
||||
|
||||
Introduksjon
|
||||
------------
|
||||
|
||||
TIKI-100 er en norskbygd maskin lansert i 1984. Den kjører et norsk
|
||||
operativsystem, TIKO, som er kompatibelt med CP/M-2.2. Maskina har en
|
||||
Z80A på 4MHz, fargegrafikk og 3 kanalers lyd. Den ble mye brukt i norske
|
||||
skoler.
|
||||
|
||||
Programmet du nå leser om er en TIKI-100 emulator, dvs et program som
|
||||
lar deg kjøre all programvare som finnes til TIKI-100 på en mer
|
||||
moderne datamaskin.
|
||||
|
||||
Emulatoren er skrevet i C. Kildefilene er tilgjengelig på emulatorens
|
||||
hjemmeside: http://www.stud.ntnu.no/~djupdal/tiki/emulator/
|
||||
|
||||
Hva som emuleres
|
||||
----------------
|
||||
|
||||
- Z80 CPU
|
||||
- CTC klokkekrets
|
||||
- DART rs-232 serieporter (begrenset)
|
||||
- PIO parallellporter (svært begrenset)
|
||||
- Videokrets
|
||||
- FD17xx diskettkontroller
|
||||
- Div andre småting som minnehåndtering, tastatur, etc.
|
||||
|
||||
Hva som mangler
|
||||
---------------
|
||||
|
||||
- AY-3-8912 lydgenerator
|
||||
- Modemsignaler (DART). Emulering av serieporter skjer uten noen
|
||||
kontroll på modemsignaler.
|
||||
- Skikkelig emulering av parallellporter (PIO). Nå emuleres bare
|
||||
det aller mest nødvendige for å kunne bruke skriver.
|
||||
- Emulering av diverse tilleggsutstyr (harddisk, 8088-kort, etc.)
|
||||
|
||||
Bruk av emulatoren
|
||||
------------------
|
||||
|
||||
Denne emulatoren er en såkalt maskinvareemulator, dvs den etterligner
|
||||
maskinvaren i en TIKI-100. Det gjør at alle operativsystemer som
|
||||
finnes til TIKI-100 vil kjøre på denne emulatoren, såfremt de ikke
|
||||
forutsetter tilleggsutstyr som ikke støttes.
|
||||
|
||||
Når emulatoren starter opp prøver den å laste inn fila
|
||||
"tiki.rom". Denne inneholder en kopi av ROM'en i en ekte
|
||||
TIKI-100. Ønsker du å bruke en annen ROM kan du bare bytte ut denne
|
||||
fila. Emulatoren støtter alle ROM-filer opp til 16kB, akkurat som en
|
||||
ekte TIKI-100. OBS: En slik fil MÅ være tilstede!
|
||||
|
||||
Emulatoren bruker diskettfiler. En diskettfil er en TIKI-100 diskett
|
||||
som i sin helhet har blitt kopiert inn på en enkelt fil. Det som er
|
||||
viktig å vite om diskettfilene i denne emulatoren er at forandringer
|
||||
som gjøres på en diskett i emulatoren ikke blir lagret før du
|
||||
eksplisitt ber emulatoren om det.
|
||||
|
||||
Etter at emulatoren har startet opp vil du få det velkjente TIKI-100
|
||||
oppstartsbildet på skjermen: "Sett inn en TIKI diskett og trykk B"
|
||||
|
||||
Bruk av emulatoren utenom dette avhenger av hvilken versjon du bruker.
|
||||
|
||||
Amiga-versjonen
|
||||
---------------
|
||||
|
||||
Merk at serieporter og parallellport foreløpig ikke støttes av
|
||||
Amigaversjonen.
|
||||
|
||||
Nederst i emulatorvinduet ser du 4 "lysdioder". Disse tilsvarer
|
||||
lysdiodene på lock-tasten, grafikk-tasten, diskettstasjon a og
|
||||
diskettstasjon b.
|
||||
|
||||
Amigaversjonen har disse menyene som burde være selvforklarende:
|
||||
|
||||
- Emulator
|
||||
- Reset
|
||||
- Om...
|
||||
- Avslutt
|
||||
- Diskettstasjon
|
||||
- Hent plate A...
|
||||
- Hent plate B...
|
||||
- Lagre plate A...
|
||||
- Lagre plate B...
|
||||
- Fjern plate A...
|
||||
- Fjern plate B...
|
||||
- Innstillinger
|
||||
- Begrens hastighet (foreløpig ikke i bruk)
|
||||
- Bevar forhold
|
||||
- 40-modus størrelse
|
||||
- Standard
|
||||
- Fordoblet
|
||||
- Firedoblet
|
||||
- 80-modus størrelse
|
||||
- Standard
|
||||
- Fordoblet
|
||||
|
||||
Plassering av TIKI taster på tastaturet:
|
||||
|
||||
GRAFIKK: ` (til venstre for tasten 1)
|
||||
BRYT: Tab
|
||||
ANGRE: Esc
|
||||
LOCK: Venstre Alt
|
||||
UTVID: \ (til venstre for slettetasten)
|
||||
HJEM: Del
|
||||
Side opp: F7
|
||||
Side ned: F8
|
||||
Venstre tab: F9
|
||||
Høyre tab: F10
|
||||
%: [ (på numerisk tastatur)
|
||||
=: ] (på numerisk tastatur)
|
||||
|
||||
Resten av tastene er plassert på de tilsvarende Amiga-tastene.
|
||||
|
||||
Win32-versjonen
|
||||
---------------
|
||||
|
||||
Nederst i emulatorvinduet ser du 4 "lysdioder". Disse tilsvarer
|
||||
lysdiodene på lock-tasten, grafikk-tasten, diskettstasjon a og
|
||||
diskettstasjon b.
|
||||
|
||||
Win32-versjonen har disse menyene som burde være selvforklarende:
|
||||
|
||||
- Emulator
|
||||
- Reset
|
||||
- Innstillinger...
|
||||
- Om...
|
||||
- Avslutt
|
||||
- diskettstasjon
|
||||
- Hent plate A...
|
||||
- Hent plate B...
|
||||
- Lagre plate A...
|
||||
- Lagre plate B...
|
||||
- Fjern plate A
|
||||
- Fjern plate B
|
||||
|
||||
Menyvalget "Innstillinger" bringer fram en dialogboks der du kan
|
||||
stille inn diverse:
|
||||
|
||||
- Merk "Senk hastighet" dersom du vil at emulatoren skal kjøre på
|
||||
samme hastighet som en ekte TIKI-100. Denne har bare virkning
|
||||
dersom din datamaskin er for rask.
|
||||
- Alt innenfor boksen "Skjermforstørring" styrer forstørring av
|
||||
TIKI-skjermbilde. "Bevar forhold" gir samme forhold på
|
||||
emulatorvinduet som på en ekte TIKI-skjerm.
|
||||
- Det innenfor boksen "Porter" bestemmer hvordan de emulerte
|
||||
TIKI-portene skal brukes. Skriv inn navnet på PC-portene du vil
|
||||
skal benyttes til de forskjellige TIKI-portene. Skriver du inn et
|
||||
filnavn i stedet vil alt som skulle blitt sendt til en port i
|
||||
stedet bli lagret til den fila.
|
||||
Merker du av "Sett ST 28 b" vil du få samme effekt som om du satte
|
||||
den tilsvarende bøylen ("jumper'en") i en ekte TIKI-100. Du vil
|
||||
neppe få bruk for denne.
|
||||
|
||||
Plassering av TIKI taster på tastaturet:
|
||||
|
||||
GRAFIKK: | (til venstre for tasten 1)
|
||||
BRYT: Tab
|
||||
ANGRE: Esc
|
||||
UTVID: Insert
|
||||
Venstre tab: Delete
|
||||
Høyre tab: End
|
||||
HJELP: F8
|
||||
ENTER (num): F9
|
||||
%: F11
|
||||
=: F12
|
||||
|
||||
Resten av tastene er plassert på de tilsvarende PC-tastene.
|
||||
|
||||
Unix-versjonen
|
||||
--------------
|
||||
|
||||
Nederst i emulatorvinduet ser du 4 "lysdioder". Disse tilsvarer
|
||||
lysdiodene på lock-tasten, grafikk-tasten, diskettstasjon a og
|
||||
diskettstasjon b.
|
||||
|
||||
Trykk Escape-tasten i emulatorvinduet for å gå inn i kommandomodus. Da
|
||||
vil en prompt komme fram i xtermen du startet emulatoren fra. Følgende
|
||||
kommandoer kan da skrives inn:
|
||||
|
||||
hjelp : Vis hjelpetekst
|
||||
h : Forkortelse for 'hjelp'
|
||||
|
||||
disk <stasjon> <filnavn> : Hent inn diskettfil
|
||||
d <stasjon> <filnavn> : Forkortelse for 'disk ...'
|
||||
|
||||
lagre <stasjon> <filnavn> : Lagre diskettfil
|
||||
l <stasjon> <filnavn> : Forkortelse for 'lagre...'
|
||||
|
||||
fjern <stasjon> : Fjern diskettfil
|
||||
f <stasjon> : Forkortelse for 'fjern...'
|
||||
|
||||
pk [kommandonavn] : Send utskrift til print-kommando
|
||||
|
||||
pf [filnavn] : Send utskrift til fil
|
||||
|
||||
reset : Reset emulator
|
||||
|
||||
fortsett : Fortsett emulering
|
||||
c : Forkortelse for 'fortsett'
|
||||
|
||||
om : Om emulator (bl.a versjonsnummer)
|
||||
|
||||
avslutt : Avslutt emulator
|
||||
q : Forkortelse for 'avslutt'
|
||||
|
||||
Alle diskettkommandoene tar et stasjonsargument. Det er enten a eller
|
||||
b, avhengig av hvilken diskettstasjon du ønsker å benytte kommandoen
|
||||
på. Stasjon a er oppstartsdiskettstasjonen i en TIKI-100.
|
||||
|
||||
Eksempel: For å hente inn diskettfil 'plater/tiko_kjerne_v4.01.dsk'
|
||||
til stasjon a skriver du: 'disk a plater/tiko_kjerne_v4.01.dsk'.
|
||||
|
||||
Kommandoene pk og pf spesifiserer hhv en printkommando eller en fil
|
||||
som utskrift fra TIKI-programmer skal sendes til. Dersom du ønsker å
|
||||
skru av utskriftsmulighetene igjen så gi kommandoen uten argument. Du
|
||||
kan skrive til både kommando og fil samtidig. Vær oppmerksom på at
|
||||
utskrift til en printkommando som oftest ikke sendes til skriver før
|
||||
forbindelsen til den avsluttes. Så selv om TIKI-programmet er ferdig
|
||||
med utskriften må du avslutte printkommando med "pk" for å sende
|
||||
utskrift til skriver.
|
||||
|
||||
Eksempel: For å sende utskrift til kommandoen 'lpr' skriver du:
|
||||
'pk lpr'. For å sende utskrift til fila 'utskrift' skriver du:
|
||||
'pf utskrift'.
|
||||
|
||||
Plassering av TIKI taster på tastaturet:
|
||||
|
||||
BRYT: Break, F10
|
||||
SLETT: BackSpace, Delete
|
||||
GRAFIKK: F8
|
||||
ANGRE: Redo, F9
|
||||
LOCK: Caps_Lock, Shift_Lock, F7
|
||||
HJELP: Help, F11
|
||||
UTVID: Insert, F12
|
||||
Venstre TAB: Prior
|
||||
Høyre TAB: Tab, Next
|
||||
|
||||
Navnet på TIKI-tasten er til venstre og navnet på den (eller de)
|
||||
tilsvarende X11-keysym tasten(e) er til høyre. For mer informasjon om
|
||||
keysyms, les man-siden til 'xmodmap'.
|
||||
|
||||
Resten av tastene er mappet til tilsvarende keysyms. Merk at TIKI-100
|
||||
bare har 6 F-taster, så dersom et program ber deg trykke på F7, er det
|
||||
antakelig ute etter shift-F1 i stedet.
|
||||
|
||||
Følgende kommandolinjeargumenter kan benyttes ved oppstart:
|
||||
|
||||
-display <display> Angi display
|
||||
-d <display> Samme som over
|
||||
|
||||
-geometry <geometry> Angi vindusplassering (størrelse ignoreres)
|
||||
-g <geometry> Samme som over
|
||||
|
||||
-diska <diskettfil> Angi diskettfil til stasjon A
|
||||
-diskb <diskettfil> Angi diskettfil til stasjon B
|
||||
|
||||
-bevarforhold Emulatorvindu har samme forhold som en ekte
|
||||
TIKI-skjerm
|
||||
-ikkebevarforhold Negasjonen av den over
|
||||
|
||||
-40x <forstørrelse> Angi forstørring av 40-modus skjerm (1-4)
|
||||
-80x <forstørrelse> Angi forstørring av 80-modus skjerm (1-2)
|
||||
|
||||
-begrens Dersom datamaskin er for rask, sett ned
|
||||
hastigheten til "normal" TIKI-100
|
||||
hastighet
|
||||
-ikkebegrens Negasjonen av den over
|
||||
|
||||
-port1 <device> Angi hvilken device du vil skal benyttes til
|
||||
TIKI-serieport P1 (f.eks /dev/tty00)
|
||||
-port2 <device> Samme som -port1 men for TIKI-serieport P2.
|
||||
|
||||
-pk <utskriftskommando> Angi hvilken kommando utskrift skal sendes til.
|
||||
-pf <utskriftsfil> Angi hvilken fil utskrift skal sendes til.
|
||||
|
||||
-st28b Tilsvarende å sette bøyle ('jumper') ST 28 b i en
|
||||
ekte TIKI-100. Du vil neppe få bruk for denne.
|
||||
-ikkest28b Negasjonen av den over
|
||||
|
||||
Disse kan også settes i .Xresources filen:
|
||||
|
||||
Tikiemul.geometry (geometry)
|
||||
Tikiemul.diska (filnavn)
|
||||
Tikiemul.diskb (filnavn)
|
||||
Tikiemul.bevarforhold (on eller off)
|
||||
Tikiemul.40x (1-4)
|
||||
Tikiemul.80x (1-2)
|
||||
Tikiemul.begrens (on eller off)
|
||||
Tikiemul.port1 (device)
|
||||
Tikiemul.port2 (device)
|
||||
Tikiemul.pk (utskriftskommando)
|
||||
Tikiemul.pf (utskriftsfil)
|
||||
Tikiemul.st28b (on eller off)
|
||||
|
||||
Dersom du ikke gir noen kommandolinjeargumenter, og ingen verdier er
|
||||
satt i .Xresources, vil følgende standardverdier benyttes:
|
||||
'-begrens -ikkest28b -ikkebevarforhold -40x 1 -80x 1', ingen
|
||||
diskettfiler i stasjonen, og ingen printkommando/fil.
|
||||
|
||||
Annet
|
||||
-----
|
||||
|
||||
På min TIKI-100 hjemmeside finner du mer informasjon om TIKI-100. Der
|
||||
finner du også mange kjente TIKI-100 programmer som kan benyttes i
|
||||
denne emulatoren. Her finner du også emulatorens hjemmeside.
|
||||
|
||||
http://www.stud.ntnu.no/~djupdal/tiki/
|
||||
|
||||
Send spørsmål, forslag til forbedringer og andre kommentarer til:
|
||||
|
||||
djupdal@stud.ntnu.no
|
||||
|
||||
Historie
|
||||
--------
|
||||
|
||||
* 25 aug 2001 Versjon 1.1.1
|
||||
- Fikset feil i diskettkontrolleremulering
|
||||
* 24 aug 2001 Versjon 1.1.0 for Amiga, win32, unix.
|
||||
- Generell opprenskning i alle kildefiler.
|
||||
- Fikset feil i diskkontrolleremulering
|
||||
- Fikset feil i videoemulering
|
||||
- Laget (begrenset) serie og parallellport emulering
|
||||
- Laget unix-versjon
|
||||
- Laget helt ny Amiga-versjon
|
||||
- Forbedret win32-versjon
|
||||
- Kildefiler tilgjengelig
|
||||
* 21 sep 2000 Versjon 1.0.1 for win32
|
||||
* 26 aug 2000 Versjon 1.0.0 for Amiga
|
|
@ -0,0 +1,447 @@
|
|||
/** Z80: portable Z80 emulator *******************************/
|
||||
/** **/
|
||||
/** Tables.h **/
|
||||
/** **/
|
||||
/** This file contains tables of used by Z80 emulation to **/
|
||||
/** compute SIGN,ZERO, PARITY flags, and decimal correction **/
|
||||
/** There are also timing tables for Z80 opcodes. This file **/
|
||||
/** is included from Z80.c. **/
|
||||
/** **/
|
||||
/** Copyright (C) Marat Fayzullin 1994,1995,1996,1997 **/
|
||||
/** You are not allowed to distribute this software **/
|
||||
/** commercially. Please, notify me, if you make any **/
|
||||
/** changes to this file. **/
|
||||
/*************************************************************/
|
||||
|
||||
static byte Cycles[256] =
|
||||
{
|
||||
4,10, 7, 6, 4, 4, 7, 4, 4,11, 7, 6, 4, 4, 7, 4,
|
||||
8,10, 7, 6, 4, 4, 7, 4,12,11, 7, 6, 4, 4, 7, 4,
|
||||
7,10,16, 6, 4, 4, 7, 4, 7,11,16, 6, 4, 4, 7, 4,
|
||||
7,10,13, 6,11,11,10, 4, 7,11,13, 6, 4, 4, 7, 4,
|
||||
4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
|
||||
4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
|
||||
4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
|
||||
7, 7, 7, 7, 7, 7, 4, 7, 4, 4, 4, 4, 4, 4, 7, 4,
|
||||
4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
|
||||
4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
|
||||
4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
|
||||
4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
|
||||
5,10,10,10,10,11, 7,11, 5,10,10, 0,10,17, 7,11,
|
||||
5,10,10,11,10,11, 7,11, 5, 4,10,11,10, 0, 7,11,
|
||||
5,10,10,19,10,11, 7,11, 5, 4,10, 4,10, 0, 7,11,
|
||||
5,10,10, 4,10,11, 7,11, 5, 6,10, 4,10, 0, 7,11
|
||||
};
|
||||
|
||||
static byte CyclesCB[256] =
|
||||
{
|
||||
8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
|
||||
8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
|
||||
8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
|
||||
8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
|
||||
8, 8, 8, 8, 8, 8,12, 8, 8, 8, 8, 8, 8, 8,12, 8,
|
||||
8, 8, 8, 8, 8, 8,12, 8, 8, 8, 8, 8, 8, 8,12, 8,
|
||||
8, 8, 8, 8, 8, 8,12, 8, 8, 8, 8, 8, 8, 8,12, 8,
|
||||
8, 8, 8, 8, 8, 8,12, 8, 8, 8, 8, 8, 8, 8,12, 8,
|
||||
8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
|
||||
8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
|
||||
8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
|
||||
8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
|
||||
8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
|
||||
8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
|
||||
8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
|
||||
8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8
|
||||
};
|
||||
|
||||
static byte CyclesED[256] =
|
||||
{
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
12,12,15,20, 8,14, 8, 9,12,12,15,20, 0,14, 0, 9,
|
||||
12,12,15,20, 0, 0, 8, 9,12,12,15,20, 0, 0, 8, 9,
|
||||
12,12,15,20, 0, 0, 0,18,12,12,15,20, 0, 0, 0,18,
|
||||
12, 0,15,20, 0, 0, 0, 0,12,12,15,20, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
16,16,16,16, 0, 0, 0, 0,16,16,16,16, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
static byte CyclesXX[256] =
|
||||
{
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0,15, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0,15, 0, 0, 0, 0, 0, 0,
|
||||
0,14,20,10, 9, 9, 9, 0, 0,15,20,10, 9, 9, 9, 0,
|
||||
0, 0, 0, 0,23,23,19, 0, 0,15, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 9, 9,19, 0, 0, 0, 0, 0, 9, 9,19, 0,
|
||||
0, 0, 0, 0, 9, 9,19, 0, 0, 0, 0, 0, 9, 9,19, 0,
|
||||
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||
19,19,19,19,19,19,19,19, 0, 0, 0, 0, 9, 9,19, 0,
|
||||
0, 0, 0, 0, 9, 9,19, 0, 0, 0, 0, 0, 9, 9,19, 0,
|
||||
0, 0, 0, 0, 9, 9,19, 0, 0, 0, 0, 0, 9, 9,19, 0,
|
||||
0, 0, 0, 0, 9, 9,19, 0, 0, 0, 0, 0, 9, 9,19, 0,
|
||||
0, 0, 0, 0, 9, 9,19, 0, 0, 0, 0, 0, 9, 9,19, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0,14, 0,23, 0,15, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0,10, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
static byte CyclesXXCB[256] =
|
||||
{
|
||||
0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,
|
||||
0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,
|
||||
0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,
|
||||
0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,
|
||||
20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
|
||||
20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
|
||||
20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
|
||||
20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
|
||||
0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,
|
||||
0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,
|
||||
0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,
|
||||
0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,
|
||||
0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,
|
||||
0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,
|
||||
0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,
|
||||
0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0
|
||||
};
|
||||
|
||||
static byte ZSTable[256] =
|
||||
{
|
||||
Z_FLAG,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG
|
||||
};
|
||||
|
||||
static byte PZSTable[256] =
|
||||
{
|
||||
Z_FLAG|P_FLAG,0,0,P_FLAG,0,P_FLAG,P_FLAG,0,
|
||||
0,P_FLAG,P_FLAG,0,P_FLAG,0,0,P_FLAG,
|
||||
0,P_FLAG,P_FLAG,0,P_FLAG,0,0,P_FLAG,P_FLAG,0,0,P_FLAG,0,P_FLAG,P_FLAG,0,
|
||||
0,P_FLAG,P_FLAG,0,P_FLAG,0,0,P_FLAG,P_FLAG,0,0,P_FLAG,0,P_FLAG,P_FLAG,0,
|
||||
P_FLAG,0,0,P_FLAG,0,P_FLAG,P_FLAG,0,0,P_FLAG,P_FLAG,0,P_FLAG,0,0,P_FLAG,
|
||||
0,P_FLAG,P_FLAG,0,P_FLAG,0,0,P_FLAG,P_FLAG,0,0,P_FLAG,0,P_FLAG,P_FLAG,0,
|
||||
P_FLAG,0,0,P_FLAG,0,P_FLAG,P_FLAG,0,0,P_FLAG,P_FLAG,0,P_FLAG,0,0,P_FLAG,
|
||||
P_FLAG,0,0,P_FLAG,0,P_FLAG,P_FLAG,0,0,P_FLAG,P_FLAG,0,P_FLAG,0,0,P_FLAG,
|
||||
0,P_FLAG,P_FLAG,0,P_FLAG,0,0,P_FLAG,P_FLAG,0,0,P_FLAG,0,P_FLAG,P_FLAG,0,
|
||||
S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,
|
||||
S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,
|
||||
S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,
|
||||
S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,
|
||||
S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,
|
||||
S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,
|
||||
S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,
|
||||
S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,
|
||||
S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,
|
||||
S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,
|
||||
S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,
|
||||
S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,
|
||||
S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,
|
||||
S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,
|
||||
S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,
|
||||
S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,
|
||||
S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,
|
||||
S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,
|
||||
S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,
|
||||
S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,
|
||||
S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,
|
||||
S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,
|
||||
S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,
|
||||
S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,
|
||||
S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,
|
||||
S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,
|
||||
S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG
|
||||
};
|
||||
|
||||
static word DAATable[2048] =
|
||||
{
|
||||
0x0044,0x0100,0x0200,0x0304,0x0400,0x0504,0x0604,0x0700,
|
||||
0x0808,0x090C,0x1010,0x1114,0x1214,0x1310,0x1414,0x1510,
|
||||
0x1000,0x1104,0x1204,0x1300,0x1404,0x1500,0x1600,0x1704,
|
||||
0x180C,0x1908,0x2030,0x2134,0x2234,0x2330,0x2434,0x2530,
|
||||
0x2020,0x2124,0x2224,0x2320,0x2424,0x2520,0x2620,0x2724,
|
||||
0x282C,0x2928,0x3034,0x3130,0x3230,0x3334,0x3430,0x3534,
|
||||
0x3024,0x3120,0x3220,0x3324,0x3420,0x3524,0x3624,0x3720,
|
||||
0x3828,0x392C,0x4010,0x4114,0x4214,0x4310,0x4414,0x4510,
|
||||
0x4000,0x4104,0x4204,0x4300,0x4404,0x4500,0x4600,0x4704,
|
||||
0x480C,0x4908,0x5014,0x5110,0x5210,0x5314,0x5410,0x5514,
|
||||
0x5004,0x5100,0x5200,0x5304,0x5400,0x5504,0x5604,0x5700,
|
||||
0x5808,0x590C,0x6034,0x6130,0x6230,0x6334,0x6430,0x6534,
|
||||
0x6024,0x6120,0x6220,0x6324,0x6420,0x6524,0x6624,0x6720,
|
||||
0x6828,0x692C,0x7030,0x7134,0x7234,0x7330,0x7434,0x7530,
|
||||
0x7020,0x7124,0x7224,0x7320,0x7424,0x7520,0x7620,0x7724,
|
||||
0x782C,0x7928,0x8090,0x8194,0x8294,0x8390,0x8494,0x8590,
|
||||
0x8080,0x8184,0x8284,0x8380,0x8484,0x8580,0x8680,0x8784,
|
||||
0x888C,0x8988,0x9094,0x9190,0x9290,0x9394,0x9490,0x9594,
|
||||
0x9084,0x9180,0x9280,0x9384,0x9480,0x9584,0x9684,0x9780,
|
||||
0x9888,0x998C,0x0055,0x0111,0x0211,0x0315,0x0411,0x0515,
|
||||
0x0045,0x0101,0x0201,0x0305,0x0401,0x0505,0x0605,0x0701,
|
||||
0x0809,0x090D,0x1011,0x1115,0x1215,0x1311,0x1415,0x1511,
|
||||
0x1001,0x1105,0x1205,0x1301,0x1405,0x1501,0x1601,0x1705,
|
||||
0x180D,0x1909,0x2031,0x2135,0x2235,0x2331,0x2435,0x2531,
|
||||
0x2021,0x2125,0x2225,0x2321,0x2425,0x2521,0x2621,0x2725,
|
||||
0x282D,0x2929,0x3035,0x3131,0x3231,0x3335,0x3431,0x3535,
|
||||
0x3025,0x3121,0x3221,0x3325,0x3421,0x3525,0x3625,0x3721,
|
||||
0x3829,0x392D,0x4011,0x4115,0x4215,0x4311,0x4415,0x4511,
|
||||
0x4001,0x4105,0x4205,0x4301,0x4405,0x4501,0x4601,0x4705,
|
||||
0x480D,0x4909,0x5015,0x5111,0x5211,0x5315,0x5411,0x5515,
|
||||
0x5005,0x5101,0x5201,0x5305,0x5401,0x5505,0x5605,0x5701,
|
||||
0x5809,0x590D,0x6035,0x6131,0x6231,0x6335,0x6431,0x6535,
|
||||
0x6025,0x6121,0x6221,0x6325,0x6421,0x6525,0x6625,0x6721,
|
||||
0x6829,0x692D,0x7031,0x7135,0x7235,0x7331,0x7435,0x7531,
|
||||
0x7021,0x7125,0x7225,0x7321,0x7425,0x7521,0x7621,0x7725,
|
||||
0x782D,0x7929,0x8091,0x8195,0x8295,0x8391,0x8495,0x8591,
|
||||
0x8081,0x8185,0x8285,0x8381,0x8485,0x8581,0x8681,0x8785,
|
||||
0x888D,0x8989,0x9095,0x9191,0x9291,0x9395,0x9491,0x9595,
|
||||
0x9085,0x9181,0x9281,0x9385,0x9481,0x9585,0x9685,0x9781,
|
||||
0x9889,0x998D,0xA0B5,0xA1B1,0xA2B1,0xA3B5,0xA4B1,0xA5B5,
|
||||
0xA0A5,0xA1A1,0xA2A1,0xA3A5,0xA4A1,0xA5A5,0xA6A5,0xA7A1,
|
||||
0xA8A9,0xA9AD,0xB0B1,0xB1B5,0xB2B5,0xB3B1,0xB4B5,0xB5B1,
|
||||
0xB0A1,0xB1A5,0xB2A5,0xB3A1,0xB4A5,0xB5A1,0xB6A1,0xB7A5,
|
||||
0xB8AD,0xB9A9,0xC095,0xC191,0xC291,0xC395,0xC491,0xC595,
|
||||
0xC085,0xC181,0xC281,0xC385,0xC481,0xC585,0xC685,0xC781,
|
||||
0xC889,0xC98D,0xD091,0xD195,0xD295,0xD391,0xD495,0xD591,
|
||||
0xD081,0xD185,0xD285,0xD381,0xD485,0xD581,0xD681,0xD785,
|
||||
0xD88D,0xD989,0xE0B1,0xE1B5,0xE2B5,0xE3B1,0xE4B5,0xE5B1,
|
||||
0xE0A1,0xE1A5,0xE2A5,0xE3A1,0xE4A5,0xE5A1,0xE6A1,0xE7A5,
|
||||
0xE8AD,0xE9A9,0xF0B5,0xF1B1,0xF2B1,0xF3B5,0xF4B1,0xF5B5,
|
||||
0xF0A5,0xF1A1,0xF2A1,0xF3A5,0xF4A1,0xF5A5,0xF6A5,0xF7A1,
|
||||
0xF8A9,0xF9AD,0x0055,0x0111,0x0211,0x0315,0x0411,0x0515,
|
||||
0x0045,0x0101,0x0201,0x0305,0x0401,0x0505,0x0605,0x0701,
|
||||
0x0809,0x090D,0x1011,0x1115,0x1215,0x1311,0x1415,0x1511,
|
||||
0x1001,0x1105,0x1205,0x1301,0x1405,0x1501,0x1601,0x1705,
|
||||
0x180D,0x1909,0x2031,0x2135,0x2235,0x2331,0x2435,0x2531,
|
||||
0x2021,0x2125,0x2225,0x2321,0x2425,0x2521,0x2621,0x2725,
|
||||
0x282D,0x2929,0x3035,0x3131,0x3231,0x3335,0x3431,0x3535,
|
||||
0x3025,0x3121,0x3221,0x3325,0x3421,0x3525,0x3625,0x3721,
|
||||
0x3829,0x392D,0x4011,0x4115,0x4215,0x4311,0x4415,0x4511,
|
||||
0x4001,0x4105,0x4205,0x4301,0x4405,0x4501,0x4601,0x4705,
|
||||
0x480D,0x4909,0x5015,0x5111,0x5211,0x5315,0x5411,0x5515,
|
||||
0x5005,0x5101,0x5201,0x5305,0x5401,0x5505,0x5605,0x5701,
|
||||
0x5809,0x590D,0x6035,0x6131,0x6231,0x6335,0x6431,0x6535,
|
||||
0x0604,0x0700,0x0808,0x090C,0x0A0C,0x0B08,0x0C0C,0x0D08,
|
||||
0x0E08,0x0F0C,0x1010,0x1114,0x1214,0x1310,0x1414,0x1510,
|
||||
0x1600,0x1704,0x180C,0x1908,0x1A08,0x1B0C,0x1C08,0x1D0C,
|
||||
0x1E0C,0x1F08,0x2030,0x2134,0x2234,0x2330,0x2434,0x2530,
|
||||
0x2620,0x2724,0x282C,0x2928,0x2A28,0x2B2C,0x2C28,0x2D2C,
|
||||
0x2E2C,0x2F28,0x3034,0x3130,0x3230,0x3334,0x3430,0x3534,
|
||||
0x3624,0x3720,0x3828,0x392C,0x3A2C,0x3B28,0x3C2C,0x3D28,
|
||||
0x3E28,0x3F2C,0x4010,0x4114,0x4214,0x4310,0x4414,0x4510,
|
||||
0x4600,0x4704,0x480C,0x4908,0x4A08,0x4B0C,0x4C08,0x4D0C,
|
||||
0x4E0C,0x4F08,0x5014,0x5110,0x5210,0x5314,0x5410,0x5514,
|
||||
0x5604,0x5700,0x5808,0x590C,0x5A0C,0x5B08,0x5C0C,0x5D08,
|
||||
0x5E08,0x5F0C,0x6034,0x6130,0x6230,0x6334,0x6430,0x6534,
|
||||
0x6624,0x6720,0x6828,0x692C,0x6A2C,0x6B28,0x6C2C,0x6D28,
|
||||
0x6E28,0x6F2C,0x7030,0x7134,0x7234,0x7330,0x7434,0x7530,
|
||||
0x7620,0x7724,0x782C,0x7928,0x7A28,0x7B2C,0x7C28,0x7D2C,
|
||||
0x7E2C,0x7F28,0x8090,0x8194,0x8294,0x8390,0x8494,0x8590,
|
||||
0x8680,0x8784,0x888C,0x8988,0x8A88,0x8B8C,0x8C88,0x8D8C,
|
||||
0x8E8C,0x8F88,0x9094,0x9190,0x9290,0x9394,0x9490,0x9594,
|
||||
0x9684,0x9780,0x9888,0x998C,0x9A8C,0x9B88,0x9C8C,0x9D88,
|
||||
0x9E88,0x9F8C,0x0055,0x0111,0x0211,0x0315,0x0411,0x0515,
|
||||
0x0605,0x0701,0x0809,0x090D,0x0A0D,0x0B09,0x0C0D,0x0D09,
|
||||
0x0E09,0x0F0D,0x1011,0x1115,0x1215,0x1311,0x1415,0x1511,
|
||||
0x1601,0x1705,0x180D,0x1909,0x1A09,0x1B0D,0x1C09,0x1D0D,
|
||||
0x1E0D,0x1F09,0x2031,0x2135,0x2235,0x2331,0x2435,0x2531,
|
||||
0x2621,0x2725,0x282D,0x2929,0x2A29,0x2B2D,0x2C29,0x2D2D,
|
||||
0x2E2D,0x2F29,0x3035,0x3131,0x3231,0x3335,0x3431,0x3535,
|
||||
0x3625,0x3721,0x3829,0x392D,0x3A2D,0x3B29,0x3C2D,0x3D29,
|
||||
0x3E29,0x3F2D,0x4011,0x4115,0x4215,0x4311,0x4415,0x4511,
|
||||
0x4601,0x4705,0x480D,0x4909,0x4A09,0x4B0D,0x4C09,0x4D0D,
|
||||
0x4E0D,0x4F09,0x5015,0x5111,0x5211,0x5315,0x5411,0x5515,
|
||||
0x5605,0x5701,0x5809,0x590D,0x5A0D,0x5B09,0x5C0D,0x5D09,
|
||||
0x5E09,0x5F0D,0x6035,0x6131,0x6231,0x6335,0x6431,0x6535,
|
||||
0x6625,0x6721,0x6829,0x692D,0x6A2D,0x6B29,0x6C2D,0x6D29,
|
||||
0x6E29,0x6F2D,0x7031,0x7135,0x7235,0x7331,0x7435,0x7531,
|
||||
0x7621,0x7725,0x782D,0x7929,0x7A29,0x7B2D,0x7C29,0x7D2D,
|
||||
0x7E2D,0x7F29,0x8091,0x8195,0x8295,0x8391,0x8495,0x8591,
|
||||
0x8681,0x8785,0x888D,0x8989,0x8A89,0x8B8D,0x8C89,0x8D8D,
|
||||
0x8E8D,0x8F89,0x9095,0x9191,0x9291,0x9395,0x9491,0x9595,
|
||||
0x9685,0x9781,0x9889,0x998D,0x9A8D,0x9B89,0x9C8D,0x9D89,
|
||||
0x9E89,0x9F8D,0xA0B5,0xA1B1,0xA2B1,0xA3B5,0xA4B1,0xA5B5,
|
||||
0xA6A5,0xA7A1,0xA8A9,0xA9AD,0xAAAD,0xABA9,0xACAD,0xADA9,
|
||||
0xAEA9,0xAFAD,0xB0B1,0xB1B5,0xB2B5,0xB3B1,0xB4B5,0xB5B1,
|
||||
0xB6A1,0xB7A5,0xB8AD,0xB9A9,0xBAA9,0xBBAD,0xBCA9,0xBDAD,
|
||||
0xBEAD,0xBFA9,0xC095,0xC191,0xC291,0xC395,0xC491,0xC595,
|
||||
0xC685,0xC781,0xC889,0xC98D,0xCA8D,0xCB89,0xCC8D,0xCD89,
|
||||
0xCE89,0xCF8D,0xD091,0xD195,0xD295,0xD391,0xD495,0xD591,
|
||||
0xD681,0xD785,0xD88D,0xD989,0xDA89,0xDB8D,0xDC89,0xDD8D,
|
||||
0xDE8D,0xDF89,0xE0B1,0xE1B5,0xE2B5,0xE3B1,0xE4B5,0xE5B1,
|
||||
0xE6A1,0xE7A5,0xE8AD,0xE9A9,0xEAA9,0xEBAD,0xECA9,0xEDAD,
|
||||
0xEEAD,0xEFA9,0xF0B5,0xF1B1,0xF2B1,0xF3B5,0xF4B1,0xF5B5,
|
||||
0xF6A5,0xF7A1,0xF8A9,0xF9AD,0xFAAD,0xFBA9,0xFCAD,0xFDA9,
|
||||
0xFEA9,0xFFAD,0x0055,0x0111,0x0211,0x0315,0x0411,0x0515,
|
||||
0x0605,0x0701,0x0809,0x090D,0x0A0D,0x0B09,0x0C0D,0x0D09,
|
||||
0x0E09,0x0F0D,0x1011,0x1115,0x1215,0x1311,0x1415,0x1511,
|
||||
0x1601,0x1705,0x180D,0x1909,0x1A09,0x1B0D,0x1C09,0x1D0D,
|
||||
0x1E0D,0x1F09,0x2031,0x2135,0x2235,0x2331,0x2435,0x2531,
|
||||
0x2621,0x2725,0x282D,0x2929,0x2A29,0x2B2D,0x2C29,0x2D2D,
|
||||
0x2E2D,0x2F29,0x3035,0x3131,0x3231,0x3335,0x3431,0x3535,
|
||||
0x3625,0x3721,0x3829,0x392D,0x3A2D,0x3B29,0x3C2D,0x3D29,
|
||||
0x3E29,0x3F2D,0x4011,0x4115,0x4215,0x4311,0x4415,0x4511,
|
||||
0x4601,0x4705,0x480D,0x4909,0x4A09,0x4B0D,0x4C09,0x4D0D,
|
||||
0x4E0D,0x4F09,0x5015,0x5111,0x5211,0x5315,0x5411,0x5515,
|
||||
0x5605,0x5701,0x5809,0x590D,0x5A0D,0x5B09,0x5C0D,0x5D09,
|
||||
0x5E09,0x5F0D,0x6035,0x6131,0x6231,0x6335,0x6431,0x6535,
|
||||
0x0046,0x0102,0x0202,0x0306,0x0402,0x0506,0x0606,0x0702,
|
||||
0x080A,0x090E,0x0402,0x0506,0x0606,0x0702,0x080A,0x090E,
|
||||
0x1002,0x1106,0x1206,0x1302,0x1406,0x1502,0x1602,0x1706,
|
||||
0x180E,0x190A,0x1406,0x1502,0x1602,0x1706,0x180E,0x190A,
|
||||
0x2022,0x2126,0x2226,0x2322,0x2426,0x2522,0x2622,0x2726,
|
||||
0x282E,0x292A,0x2426,0x2522,0x2622,0x2726,0x282E,0x292A,
|
||||
0x3026,0x3122,0x3222,0x3326,0x3422,0x3526,0x3626,0x3722,
|
||||
0x382A,0x392E,0x3422,0x3526,0x3626,0x3722,0x382A,0x392E,
|
||||
0x4002,0x4106,0x4206,0x4302,0x4406,0x4502,0x4602,0x4706,
|
||||
0x480E,0x490A,0x4406,0x4502,0x4602,0x4706,0x480E,0x490A,
|
||||
0x5006,0x5102,0x5202,0x5306,0x5402,0x5506,0x5606,0x5702,
|
||||
0x580A,0x590E,0x5402,0x5506,0x5606,0x5702,0x580A,0x590E,
|
||||
0x6026,0x6122,0x6222,0x6326,0x6422,0x6526,0x6626,0x6722,
|
||||
0x682A,0x692E,0x6422,0x6526,0x6626,0x6722,0x682A,0x692E,
|
||||
0x7022,0x7126,0x7226,0x7322,0x7426,0x7522,0x7622,0x7726,
|
||||
0x782E,0x792A,0x7426,0x7522,0x7622,0x7726,0x782E,0x792A,
|
||||
0x8082,0x8186,0x8286,0x8382,0x8486,0x8582,0x8682,0x8786,
|
||||
0x888E,0x898A,0x8486,0x8582,0x8682,0x8786,0x888E,0x898A,
|
||||
0x9086,0x9182,0x9282,0x9386,0x9482,0x9586,0x9686,0x9782,
|
||||
0x988A,0x998E,0x3423,0x3527,0x3627,0x3723,0x382B,0x392F,
|
||||
0x4003,0x4107,0x4207,0x4303,0x4407,0x4503,0x4603,0x4707,
|
||||
0x480F,0x490B,0x4407,0x4503,0x4603,0x4707,0x480F,0x490B,
|
||||
0x5007,0x5103,0x5203,0x5307,0x5403,0x5507,0x5607,0x5703,
|
||||
0x580B,0x590F,0x5403,0x5507,0x5607,0x5703,0x580B,0x590F,
|
||||
0x6027,0x6123,0x6223,0x6327,0x6423,0x6527,0x6627,0x6723,
|
||||
0x682B,0x692F,0x6423,0x6527,0x6627,0x6723,0x682B,0x692F,
|
||||
0x7023,0x7127,0x7227,0x7323,0x7427,0x7523,0x7623,0x7727,
|
||||
0x782F,0x792B,0x7427,0x7523,0x7623,0x7727,0x782F,0x792B,
|
||||
0x8083,0x8187,0x8287,0x8383,0x8487,0x8583,0x8683,0x8787,
|
||||
0x888F,0x898B,0x8487,0x8583,0x8683,0x8787,0x888F,0x898B,
|
||||
0x9087,0x9183,0x9283,0x9387,0x9483,0x9587,0x9687,0x9783,
|
||||
0x988B,0x998F,0x9483,0x9587,0x9687,0x9783,0x988B,0x998F,
|
||||
0xA0A7,0xA1A3,0xA2A3,0xA3A7,0xA4A3,0xA5A7,0xA6A7,0xA7A3,
|
||||
0xA8AB,0xA9AF,0xA4A3,0xA5A7,0xA6A7,0xA7A3,0xA8AB,0xA9AF,
|
||||
0xB0A3,0xB1A7,0xB2A7,0xB3A3,0xB4A7,0xB5A3,0xB6A3,0xB7A7,
|
||||
0xB8AF,0xB9AB,0xB4A7,0xB5A3,0xB6A3,0xB7A7,0xB8AF,0xB9AB,
|
||||
0xC087,0xC183,0xC283,0xC387,0xC483,0xC587,0xC687,0xC783,
|
||||
0xC88B,0xC98F,0xC483,0xC587,0xC687,0xC783,0xC88B,0xC98F,
|
||||
0xD083,0xD187,0xD287,0xD383,0xD487,0xD583,0xD683,0xD787,
|
||||
0xD88F,0xD98B,0xD487,0xD583,0xD683,0xD787,0xD88F,0xD98B,
|
||||
0xE0A3,0xE1A7,0xE2A7,0xE3A3,0xE4A7,0xE5A3,0xE6A3,0xE7A7,
|
||||
0xE8AF,0xE9AB,0xE4A7,0xE5A3,0xE6A3,0xE7A7,0xE8AF,0xE9AB,
|
||||
0xF0A7,0xF1A3,0xF2A3,0xF3A7,0xF4A3,0xF5A7,0xF6A7,0xF7A3,
|
||||
0xF8AB,0xF9AF,0xF4A3,0xF5A7,0xF6A7,0xF7A3,0xF8AB,0xF9AF,
|
||||
0x0047,0x0103,0x0203,0x0307,0x0403,0x0507,0x0607,0x0703,
|
||||
0x080B,0x090F,0x0403,0x0507,0x0607,0x0703,0x080B,0x090F,
|
||||
0x1003,0x1107,0x1207,0x1303,0x1407,0x1503,0x1603,0x1707,
|
||||
0x180F,0x190B,0x1407,0x1503,0x1603,0x1707,0x180F,0x190B,
|
||||
0x2023,0x2127,0x2227,0x2323,0x2427,0x2523,0x2623,0x2727,
|
||||
0x282F,0x292B,0x2427,0x2523,0x2623,0x2727,0x282F,0x292B,
|
||||
0x3027,0x3123,0x3223,0x3327,0x3423,0x3527,0x3627,0x3723,
|
||||
0x382B,0x392F,0x3423,0x3527,0x3627,0x3723,0x382B,0x392F,
|
||||
0x4003,0x4107,0x4207,0x4303,0x4407,0x4503,0x4603,0x4707,
|
||||
0x480F,0x490B,0x4407,0x4503,0x4603,0x4707,0x480F,0x490B,
|
||||
0x5007,0x5103,0x5203,0x5307,0x5403,0x5507,0x5607,0x5703,
|
||||
0x580B,0x590F,0x5403,0x5507,0x5607,0x5703,0x580B,0x590F,
|
||||
0x6027,0x6123,0x6223,0x6327,0x6423,0x6527,0x6627,0x6723,
|
||||
0x682B,0x692F,0x6423,0x6527,0x6627,0x6723,0x682B,0x692F,
|
||||
0x7023,0x7127,0x7227,0x7323,0x7427,0x7523,0x7623,0x7727,
|
||||
0x782F,0x792B,0x7427,0x7523,0x7623,0x7727,0x782F,0x792B,
|
||||
0x8083,0x8187,0x8287,0x8383,0x8487,0x8583,0x8683,0x8787,
|
||||
0x888F,0x898B,0x8487,0x8583,0x8683,0x8787,0x888F,0x898B,
|
||||
0x9087,0x9183,0x9283,0x9387,0x9483,0x9587,0x9687,0x9783,
|
||||
0x988B,0x998F,0x9483,0x9587,0x9687,0x9783,0x988B,0x998F,
|
||||
0xFABE,0xFBBA,0xFCBE,0xFDBA,0xFEBA,0xFFBE,0x0046,0x0102,
|
||||
0x0202,0x0306,0x0402,0x0506,0x0606,0x0702,0x080A,0x090E,
|
||||
0x0A1E,0x0B1A,0x0C1E,0x0D1A,0x0E1A,0x0F1E,0x1002,0x1106,
|
||||
0x1206,0x1302,0x1406,0x1502,0x1602,0x1706,0x180E,0x190A,
|
||||
0x1A1A,0x1B1E,0x1C1A,0x1D1E,0x1E1E,0x1F1A,0x2022,0x2126,
|
||||
0x2226,0x2322,0x2426,0x2522,0x2622,0x2726,0x282E,0x292A,
|
||||
0x2A3A,0x2B3E,0x2C3A,0x2D3E,0x2E3E,0x2F3A,0x3026,0x3122,
|
||||
0x3222,0x3326,0x3422,0x3526,0x3626,0x3722,0x382A,0x392E,
|
||||
0x3A3E,0x3B3A,0x3C3E,0x3D3A,0x3E3A,0x3F3E,0x4002,0x4106,
|
||||
0x4206,0x4302,0x4406,0x4502,0x4602,0x4706,0x480E,0x490A,
|
||||
0x4A1A,0x4B1E,0x4C1A,0x4D1E,0x4E1E,0x4F1A,0x5006,0x5102,
|
||||
0x5202,0x5306,0x5402,0x5506,0x5606,0x5702,0x580A,0x590E,
|
||||
0x5A1E,0x5B1A,0x5C1E,0x5D1A,0x5E1A,0x5F1E,0x6026,0x6122,
|
||||
0x6222,0x6326,0x6422,0x6526,0x6626,0x6722,0x682A,0x692E,
|
||||
0x6A3E,0x6B3A,0x6C3E,0x6D3A,0x6E3A,0x6F3E,0x7022,0x7126,
|
||||
0x7226,0x7322,0x7426,0x7522,0x7622,0x7726,0x782E,0x792A,
|
||||
0x7A3A,0x7B3E,0x7C3A,0x7D3E,0x7E3E,0x7F3A,0x8082,0x8186,
|
||||
0x8286,0x8382,0x8486,0x8582,0x8682,0x8786,0x888E,0x898A,
|
||||
0x8A9A,0x8B9E,0x8C9A,0x8D9E,0x8E9E,0x8F9A,0x9086,0x9182,
|
||||
0x9282,0x9386,0x3423,0x3527,0x3627,0x3723,0x382B,0x392F,
|
||||
0x3A3F,0x3B3B,0x3C3F,0x3D3B,0x3E3B,0x3F3F,0x4003,0x4107,
|
||||
0x4207,0x4303,0x4407,0x4503,0x4603,0x4707,0x480F,0x490B,
|
||||
0x4A1B,0x4B1F,0x4C1B,0x4D1F,0x4E1F,0x4F1B,0x5007,0x5103,
|
||||
0x5203,0x5307,0x5403,0x5507,0x5607,0x5703,0x580B,0x590F,
|
||||
0x5A1F,0x5B1B,0x5C1F,0x5D1B,0x5E1B,0x5F1F,0x6027,0x6123,
|
||||
0x6223,0x6327,0x6423,0x6527,0x6627,0x6723,0x682B,0x692F,
|
||||
0x6A3F,0x6B3B,0x6C3F,0x6D3B,0x6E3B,0x6F3F,0x7023,0x7127,
|
||||
0x7227,0x7323,0x7427,0x7523,0x7623,0x7727,0x782F,0x792B,
|
||||
0x7A3B,0x7B3F,0x7C3B,0x7D3F,0x7E3F,0x7F3B,0x8083,0x8187,
|
||||
0x8287,0x8383,0x8487,0x8583,0x8683,0x8787,0x888F,0x898B,
|
||||
0x8A9B,0x8B9F,0x8C9B,0x8D9F,0x8E9F,0x8F9B,0x9087,0x9183,
|
||||
0x9283,0x9387,0x9483,0x9587,0x9687,0x9783,0x988B,0x998F,
|
||||
0x9A9F,0x9B9B,0x9C9F,0x9D9B,0x9E9B,0x9F9F,0xA0A7,0xA1A3,
|
||||
0xA2A3,0xA3A7,0xA4A3,0xA5A7,0xA6A7,0xA7A3,0xA8AB,0xA9AF,
|
||||
0xAABF,0xABBB,0xACBF,0xADBB,0xAEBB,0xAFBF,0xB0A3,0xB1A7,
|
||||
0xB2A7,0xB3A3,0xB4A7,0xB5A3,0xB6A3,0xB7A7,0xB8AF,0xB9AB,
|
||||
0xBABB,0xBBBF,0xBCBB,0xBDBF,0xBEBF,0xBFBB,0xC087,0xC183,
|
||||
0xC283,0xC387,0xC483,0xC587,0xC687,0xC783,0xC88B,0xC98F,
|
||||
0xCA9F,0xCB9B,0xCC9F,0xCD9B,0xCE9B,0xCF9F,0xD083,0xD187,
|
||||
0xD287,0xD383,0xD487,0xD583,0xD683,0xD787,0xD88F,0xD98B,
|
||||
0xDA9B,0xDB9F,0xDC9B,0xDD9F,0xDE9F,0xDF9B,0xE0A3,0xE1A7,
|
||||
0xE2A7,0xE3A3,0xE4A7,0xE5A3,0xE6A3,0xE7A7,0xE8AF,0xE9AB,
|
||||
0xEABB,0xEBBF,0xECBB,0xEDBF,0xEEBF,0xEFBB,0xF0A7,0xF1A3,
|
||||
0xF2A3,0xF3A7,0xF4A3,0xF5A7,0xF6A7,0xF7A3,0xF8AB,0xF9AF,
|
||||
0xFABF,0xFBBB,0xFCBF,0xFDBB,0xFEBB,0xFFBF,0x0047,0x0103,
|
||||
0x0203,0x0307,0x0403,0x0507,0x0607,0x0703,0x080B,0x090F,
|
||||
0x0A1F,0x0B1B,0x0C1F,0x0D1B,0x0E1B,0x0F1F,0x1003,0x1107,
|
||||
0x1207,0x1303,0x1407,0x1503,0x1603,0x1707,0x180F,0x190B,
|
||||
0x1A1B,0x1B1F,0x1C1B,0x1D1F,0x1E1F,0x1F1B,0x2023,0x2127,
|
||||
0x2227,0x2323,0x2427,0x2523,0x2623,0x2727,0x282F,0x292B,
|
||||
0x2A3B,0x2B3F,0x2C3B,0x2D3F,0x2E3F,0x2F3B,0x3027,0x3123,
|
||||
0x3223,0x3327,0x3423,0x3527,0x3627,0x3723,0x382B,0x392F,
|
||||
0x3A3F,0x3B3B,0x3C3F,0x3D3B,0x3E3B,0x3F3F,0x4003,0x4107,
|
||||
0x4207,0x4303,0x4407,0x4503,0x4603,0x4707,0x480F,0x490B,
|
||||
0x4A1B,0x4B1F,0x4C1B,0x4D1F,0x4E1F,0x4F1B,0x5007,0x5103,
|
||||
0x5203,0x5307,0x5403,0x5507,0x5607,0x5703,0x580B,0x590F,
|
||||
0x5A1F,0x5B1B,0x5C1F,0x5D1B,0x5E1B,0x5F1F,0x6027,0x6123,
|
||||
0x6223,0x6327,0x6423,0x6527,0x6627,0x6723,0x682B,0x692F,
|
||||
0x6A3F,0x6B3B,0x6C3F,0x6D3B,0x6E3B,0x6F3F,0x7023,0x7127,
|
||||
0x7227,0x7323,0x7427,0x7523,0x7623,0x7727,0x782F,0x792B,
|
||||
0x7A3B,0x7B3F,0x7C3B,0x7D3F,0x7E3F,0x7F3B,0x8083,0x8187,
|
||||
0x8287,0x8383,0x8487,0x8583,0x8683,0x8787,0x888F,0x898B,
|
||||
0x8A9B,0x8B9F,0x8C9B,0x8D9F,0x8E9F,0x8F9B,0x9087,0x9183,
|
||||
0x9283,0x9387,0x9483,0x9587,0x9687,0x9783,0x988B,0x998F
|
||||
};
|
|
@ -0,0 +1,573 @@
|
|||
/** Z80: portable Z80 emulator *******************************/
|
||||
/** **/
|
||||
/** Z80.c **/
|
||||
/** **/
|
||||
/** This file contains implementation for Z80 CPU. Don't **/
|
||||
/** forget to provide RdZ80(), WrZ80(), InZ80(), OutZ80(), **/
|
||||
/** LoopZ80(), and PatchZ80() functions to accomodate the **/
|
||||
/** emulated machine's architecture. **/
|
||||
/** **/
|
||||
/** Copyright (C) Marat Fayzullin 1994,1995,1996,1997 **/
|
||||
/** You are not allowed to distribute this software **/
|
||||
/** commercially. Please, notify me, if you make any **/
|
||||
/** changes to this file. **/
|
||||
/*************************************************************/
|
||||
|
||||
#include "Z80.h"
|
||||
#include "Tables.h"
|
||||
#include <stdio.h>
|
||||
|
||||
/** INLINE ***************************************************/
|
||||
/** Different compilers inline C functions differently. **/
|
||||
/*************************************************************/
|
||||
#ifdef __GNUC__
|
||||
#define INLINE inline
|
||||
#else
|
||||
#define INLINE static
|
||||
#endif
|
||||
|
||||
/** System-Dependent Stuff ***********************************/
|
||||
/** This is system-dependent code put here to speed things **/
|
||||
/** up. It has to stay inlined to be fast. **/
|
||||
/*************************************************************/
|
||||
#ifdef COLEM
|
||||
extern byte *RAM;
|
||||
INLINE byte RdZ80(word A) { return(RAM[A]); }
|
||||
#endif
|
||||
#ifdef MG
|
||||
extern byte *Page[];
|
||||
INLINE byte RdZ80(word A) { return(Page[A>>13][A&0x1FFF]); }
|
||||
#endif
|
||||
#ifdef FMSX
|
||||
extern byte *RAM[],PSL[],SSLReg;
|
||||
INLINE byte RdZ80(word A)
|
||||
{
|
||||
if(A!=0xFFFF) return(RAM[A>>13][A&0x1FFF]);
|
||||
else return((PSL[3]==3)? ~SSLReg:RAM[7][0x1FFF]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#define S(Fl) R->AF.B.l|=Fl
|
||||
#define R(Fl) R->AF.B.l&=~(Fl)
|
||||
#define FLAGS(Rg,Fl) R->AF.B.l=Fl|ZSTable[Rg]
|
||||
|
||||
#define M_RLC(Rg) \
|
||||
R->AF.B.l=Rg>>7;Rg=(Rg<<1)|R->AF.B.l;R->AF.B.l|=PZSTable[Rg]
|
||||
#define M_RRC(Rg) \
|
||||
R->AF.B.l=Rg&0x01;Rg=(Rg>>1)|(R->AF.B.l<<7);R->AF.B.l|=PZSTable[Rg]
|
||||
#define M_RL(Rg) \
|
||||
if(Rg&0x80) \
|
||||
{ \
|
||||
Rg=(Rg<<1)|(R->AF.B.l&C_FLAG); \
|
||||
R->AF.B.l=PZSTable[Rg]|C_FLAG; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
Rg=(Rg<<1)|(R->AF.B.l&C_FLAG); \
|
||||
R->AF.B.l=PZSTable[Rg]; \
|
||||
}
|
||||
#define M_RR(Rg) \
|
||||
if(Rg&0x01) \
|
||||
{ \
|
||||
Rg=(Rg>>1)|(R->AF.B.l<<7); \
|
||||
R->AF.B.l=PZSTable[Rg]|C_FLAG; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
Rg=(Rg>>1)|(R->AF.B.l<<7); \
|
||||
R->AF.B.l=PZSTable[Rg]; \
|
||||
}
|
||||
|
||||
#define M_SLA(Rg) \
|
||||
R->AF.B.l=Rg>>7;Rg<<=1;R->AF.B.l|=PZSTable[Rg]
|
||||
#define M_SRA(Rg) \
|
||||
R->AF.B.l=Rg&C_FLAG;Rg=(Rg>>1)|(Rg&0x80);R->AF.B.l|=PZSTable[Rg]
|
||||
|
||||
#define M_SLL(Rg) \
|
||||
R->AF.B.l=Rg>>7;Rg=(Rg<<1)|0x01;R->AF.B.l|=PZSTable[Rg]
|
||||
#define M_SRL(Rg) \
|
||||
R->AF.B.l=Rg&0x01;Rg>>=1;R->AF.B.l|=PZSTable[Rg]
|
||||
|
||||
#define M_BIT(Bit,Rg) \
|
||||
R->AF.B.l=(R->AF.B.l&~(N_FLAG|Z_FLAG))|H_FLAG|(Rg&(1<<Bit)? 0:Z_FLAG)
|
||||
|
||||
#define M_SET(Bit,Rg) Rg|=1<<Bit
|
||||
#define M_RES(Bit,Rg) Rg&=~(1<<Bit)
|
||||
|
||||
#define M_POP(Rg) \
|
||||
R->Rg.B.l=RdZ80(R->SP.W++);R->Rg.B.h=RdZ80(R->SP.W++)
|
||||
#define M_PUSH(Rg) \
|
||||
WrZ80(--R->SP.W,R->Rg.B.h);WrZ80(--R->SP.W,R->Rg.B.l)
|
||||
|
||||
#define M_CALL \
|
||||
J.B.l=RdZ80(R->PC.W++);J.B.h=RdZ80(R->PC.W++); \
|
||||
WrZ80(--R->SP.W,R->PC.B.h);WrZ80(--R->SP.W,R->PC.B.l); \
|
||||
R->PC.W=J.W
|
||||
|
||||
#define M_JP J.B.l=RdZ80(R->PC.W++);J.B.h=RdZ80(R->PC.W);R->PC.W=J.W
|
||||
#define M_JR R->PC.W+=(offset)RdZ80(R->PC.W)+1
|
||||
#define M_RET R->PC.B.l=RdZ80(R->SP.W++);R->PC.B.h=RdZ80(R->SP.W++)
|
||||
|
||||
#define M_RST(Ad) \
|
||||
WrZ80(--R->SP.W,R->PC.B.h);WrZ80(--R->SP.W,R->PC.B.l);R->PC.W=Ad
|
||||
|
||||
#define M_LDWORD(Rg) \
|
||||
R->Rg.B.l=RdZ80(R->PC.W++);R->Rg.B.h=RdZ80(R->PC.W++)
|
||||
|
||||
#define M_ADD(Rg) \
|
||||
J.W=R->AF.B.h+Rg; \
|
||||
R->AF.B.l= \
|
||||
(~(R->AF.B.h^Rg)&(Rg^J.B.l)&0x80? V_FLAG:0)| \
|
||||
J.B.h|ZSTable[J.B.l]| \
|
||||
((R->AF.B.h^Rg^J.B.l)&H_FLAG); \
|
||||
R->AF.B.h=J.B.l
|
||||
|
||||
#define M_SUB(Rg) \
|
||||
J.W=R->AF.B.h-Rg; \
|
||||
R->AF.B.l= \
|
||||
((R->AF.B.h^Rg)&(R->AF.B.h^J.B.l)&0x80? V_FLAG:0)| \
|
||||
N_FLAG|-J.B.h|ZSTable[J.B.l]| \
|
||||
((R->AF.B.h^Rg^J.B.l)&H_FLAG); \
|
||||
R->AF.B.h=J.B.l
|
||||
|
||||
#define M_ADC(Rg) \
|
||||
J.W=R->AF.B.h+Rg+(R->AF.B.l&C_FLAG); \
|
||||
R->AF.B.l= \
|
||||
(~(R->AF.B.h^Rg)&(Rg^J.B.l)&0x80? V_FLAG:0)| \
|
||||
J.B.h|ZSTable[J.B.l]| \
|
||||
((R->AF.B.h^Rg^J.B.l)&H_FLAG); \
|
||||
R->AF.B.h=J.B.l
|
||||
|
||||
#define M_SBC(Rg) \
|
||||
J.W=R->AF.B.h-Rg-(R->AF.B.l&C_FLAG); \
|
||||
R->AF.B.l= \
|
||||
((R->AF.B.h^Rg)&(R->AF.B.h^J.B.l)&0x80? V_FLAG:0)| \
|
||||
N_FLAG|-J.B.h|ZSTable[J.B.l]| \
|
||||
((R->AF.B.h^Rg^J.B.l)&H_FLAG); \
|
||||
R->AF.B.h=J.B.l
|
||||
|
||||
#define M_CP(Rg) \
|
||||
J.W=R->AF.B.h-Rg; \
|
||||
R->AF.B.l= \
|
||||
((R->AF.B.h^Rg)&(R->AF.B.h^J.B.l)&0x80? V_FLAG:0)| \
|
||||
N_FLAG|-J.B.h|ZSTable[J.B.l]| \
|
||||
((R->AF.B.h^Rg^J.B.l)&H_FLAG)
|
||||
|
||||
#define M_AND(Rg) R->AF.B.h&=Rg;R->AF.B.l=H_FLAG|PZSTable[R->AF.B.h]
|
||||
#define M_OR(Rg) R->AF.B.h|=Rg;R->AF.B.l=PZSTable[R->AF.B.h]
|
||||
#define M_XOR(Rg) R->AF.B.h^=Rg;R->AF.B.l=PZSTable[R->AF.B.h]
|
||||
#define M_IN(Rg) Rg=InZ80(R->BC.B.l);R->AF.B.l=PZSTable[Rg]|(R->AF.B.l&C_FLAG)
|
||||
|
||||
#define M_INC(Rg) \
|
||||
Rg++; \
|
||||
R->AF.B.l= \
|
||||
(R->AF.B.l&C_FLAG)|ZSTable[Rg]| \
|
||||
(Rg==0x80? V_FLAG:0)|(Rg&0x0F? 0:H_FLAG)
|
||||
|
||||
#define M_DEC(Rg) \
|
||||
Rg--; \
|
||||
R->AF.B.l= \
|
||||
N_FLAG|(R->AF.B.l&C_FLAG)|ZSTable[Rg]| \
|
||||
(Rg==0x7F? V_FLAG:0)|((Rg&0x0F)==0x0F? H_FLAG:0)
|
||||
|
||||
#define M_ADDW(Rg1,Rg2) \
|
||||
J.W=(R->Rg1.W+R->Rg2.W)&0xFFFF; \
|
||||
R->AF.B.l= \
|
||||
(R->AF.B.l&~(H_FLAG|N_FLAG|C_FLAG))| \
|
||||
((R->Rg1.W^R->Rg2.W^J.W)&0x1000? H_FLAG:0)| \
|
||||
(((long)R->Rg1.W+(long)R->Rg2.W)&0x10000? C_FLAG:0); \
|
||||
R->Rg1.W=J.W
|
||||
|
||||
#define M_ADCW(Rg) \
|
||||
I=R->AF.B.l&C_FLAG;J.W=(R->HL.W+R->Rg.W+I)&0xFFFF; \
|
||||
R->AF.B.l= \
|
||||
(((long)R->HL.W+(long)R->Rg.W+(long)I)&0x10000? C_FLAG:0)| \
|
||||
(~(R->HL.W^R->Rg.W)&(R->Rg.W^J.W)&0x8000? V_FLAG:0)| \
|
||||
((R->HL.W^R->Rg.W^J.W)&0x1000? H_FLAG:0)| \
|
||||
(J.W? 0:Z_FLAG)|(J.B.h&S_FLAG); \
|
||||
R->HL.W=J.W
|
||||
|
||||
#define M_SBCW(Rg) \
|
||||
I=R->AF.B.l&C_FLAG;J.W=(R->HL.W-R->Rg.W-I)&0xFFFF; \
|
||||
R->AF.B.l= \
|
||||
N_FLAG| \
|
||||
(((long)R->HL.W-(long)R->Rg.W-(long)I)&0x10000? C_FLAG:0)| \
|
||||
((R->HL.W^R->Rg.W)&(R->HL.W^J.W)&0x8000? V_FLAG:0)| \
|
||||
((R->HL.W^R->Rg.W^J.W)&0x1000? H_FLAG:0)| \
|
||||
(J.W? 0:Z_FLAG)|(J.B.h&S_FLAG); \
|
||||
R->HL.W=J.W
|
||||
|
||||
enum Codes
|
||||
{
|
||||
NOP,LD_BC_WORD,LD_xBC_A,INC_BC,INC_B,DEC_B,LD_B_BYTE,RLCA,
|
||||
EX_AF_AF,ADD_HL_BC,LD_A_xBC,DEC_BC,INC_C,DEC_C,LD_C_BYTE,RRCA,
|
||||
DJNZ,LD_DE_WORD,LD_xDE_A,INC_DE,INC_D,DEC_D,LD_D_BYTE,RLA,
|
||||
JR,ADD_HL_DE,LD_A_xDE,DEC_DE,INC_E,DEC_E,LD_E_BYTE,RRA,
|
||||
JR_NZ,LD_HL_WORD,LD_xWORD_HL,INC_HL,INC_H,DEC_H,LD_H_BYTE,DAA,
|
||||
JR_Z,ADD_HL_HL,LD_HL_xWORD,DEC_HL,INC_L,DEC_L,LD_L_BYTE,CPL,
|
||||
JR_NC,LD_SP_WORD,LD_xWORD_A,INC_SP,INC_xHL,DEC_xHL,LD_xHL_BYTE,SCF,
|
||||
JR_C,ADD_HL_SP,LD_A_xWORD,DEC_SP,INC_A,DEC_A,LD_A_BYTE,CCF,
|
||||
LD_B_B,LD_B_C,LD_B_D,LD_B_E,LD_B_H,LD_B_L,LD_B_xHL,LD_B_A,
|
||||
LD_C_B,LD_C_C,LD_C_D,LD_C_E,LD_C_H,LD_C_L,LD_C_xHL,LD_C_A,
|
||||
LD_D_B,LD_D_C,LD_D_D,LD_D_E,LD_D_H,LD_D_L,LD_D_xHL,LD_D_A,
|
||||
LD_E_B,LD_E_C,LD_E_D,LD_E_E,LD_E_H,LD_E_L,LD_E_xHL,LD_E_A,
|
||||
LD_H_B,LD_H_C,LD_H_D,LD_H_E,LD_H_H,LD_H_L,LD_H_xHL,LD_H_A,
|
||||
LD_L_B,LD_L_C,LD_L_D,LD_L_E,LD_L_H,LD_L_L,LD_L_xHL,LD_L_A,
|
||||
LD_xHL_B,LD_xHL_C,LD_xHL_D,LD_xHL_E,LD_xHL_H,LD_xHL_L,HALT,LD_xHL_A,
|
||||
LD_A_B,LD_A_C,LD_A_D,LD_A_E,LD_A_H,LD_A_L,LD_A_xHL,LD_A_A,
|
||||
ADD_B,ADD_C,ADD_D,ADD_E,ADD_H,ADD_L,ADD_xHL,ADD_A,
|
||||
ADC_B,ADC_C,ADC_D,ADC_E,ADC_H,ADC_L,ADC_xHL,ADC_A,
|
||||
SUB_B,SUB_C,SUB_D,SUB_E,SUB_H,SUB_L,SUB_xHL,SUB_A,
|
||||
SBC_B,SBC_C,SBC_D,SBC_E,SBC_H,SBC_L,SBC_xHL,SBC_A,
|
||||
AND_B,AND_C,AND_D,AND_E,AND_H,AND_L,AND_xHL,AND_A,
|
||||
XOR_B,XOR_C,XOR_D,XOR_E,XOR_H,XOR_L,XOR_xHL,XOR_A,
|
||||
OR_B,OR_C,OR_D,OR_E,OR_H,OR_L,OR_xHL,OR_A,
|
||||
CP_B,CP_C,CP_D,CP_E,CP_H,CP_L,CP_xHL,CP_A,
|
||||
RET_NZ,POP_BC,JP_NZ,JP,CALL_NZ,PUSH_BC,ADD_BYTE,RST00,
|
||||
RET_Z,RET,JP_Z,PFX_CB,CALL_Z,CALL,ADC_BYTE,RST08,
|
||||
RET_NC,POP_DE,JP_NC,OUTA,CALL_NC,PUSH_DE,SUB_BYTE,RST10,
|
||||
RET_C,EXX,JP_C,INA,CALL_C,PFX_DD,SBC_BYTE,RST18,
|
||||
RET_PO,POP_HL,JP_PO,EX_HL_xSP,CALL_PO,PUSH_HL,AND_BYTE,RST20,
|
||||
RET_PE,LD_PC_HL,JP_PE,EX_DE_HL,CALL_PE,PFX_ED,XOR_BYTE,RST28,
|
||||
RET_P,POP_AF,JP_P,DI,CALL_P,PUSH_AF,OR_BYTE,RST30,
|
||||
RET_M,LD_SP_HL,JP_M,EI,CALL_M,PFX_FD,CP_BYTE,RST38
|
||||
};
|
||||
|
||||
enum CodesCB
|
||||
{
|
||||
RLC_B,RLC_C,RLC_D,RLC_E,RLC_H,RLC_L,RLC_xHL,RLC_A,
|
||||
RRC_B,RRC_C,RRC_D,RRC_E,RRC_H,RRC_L,RRC_xHL,RRC_A,
|
||||
RL_B,RL_C,RL_D,RL_E,RL_H,RL_L,RL_xHL,RL_A,
|
||||
RR_B,RR_C,RR_D,RR_E,RR_H,RR_L,RR_xHL,RR_A,
|
||||
SLA_B,SLA_C,SLA_D,SLA_E,SLA_H,SLA_L,SLA_xHL,SLA_A,
|
||||
SRA_B,SRA_C,SRA_D,SRA_E,SRA_H,SRA_L,SRA_xHL,SRA_A,
|
||||
SLL_B,SLL_C,SLL_D,SLL_E,SLL_H,SLL_L,SLL_xHL,SLL_A,
|
||||
SRL_B,SRL_C,SRL_D,SRL_E,SRL_H,SRL_L,SRL_xHL,SRL_A,
|
||||
BIT0_B,BIT0_C,BIT0_D,BIT0_E,BIT0_H,BIT0_L,BIT0_xHL,BIT0_A,
|
||||
BIT1_B,BIT1_C,BIT1_D,BIT1_E,BIT1_H,BIT1_L,BIT1_xHL,BIT1_A,
|
||||
BIT2_B,BIT2_C,BIT2_D,BIT2_E,BIT2_H,BIT2_L,BIT2_xHL,BIT2_A,
|
||||
BIT3_B,BIT3_C,BIT3_D,BIT3_E,BIT3_H,BIT3_L,BIT3_xHL,BIT3_A,
|
||||
BIT4_B,BIT4_C,BIT4_D,BIT4_E,BIT4_H,BIT4_L,BIT4_xHL,BIT4_A,
|
||||
BIT5_B,BIT5_C,BIT5_D,BIT5_E,BIT5_H,BIT5_L,BIT5_xHL,BIT5_A,
|
||||
BIT6_B,BIT6_C,BIT6_D,BIT6_E,BIT6_H,BIT6_L,BIT6_xHL,BIT6_A,
|
||||
BIT7_B,BIT7_C,BIT7_D,BIT7_E,BIT7_H,BIT7_L,BIT7_xHL,BIT7_A,
|
||||
RES0_B,RES0_C,RES0_D,RES0_E,RES0_H,RES0_L,RES0_xHL,RES0_A,
|
||||
RES1_B,RES1_C,RES1_D,RES1_E,RES1_H,RES1_L,RES1_xHL,RES1_A,
|
||||
RES2_B,RES2_C,RES2_D,RES2_E,RES2_H,RES2_L,RES2_xHL,RES2_A,
|
||||
RES3_B,RES3_C,RES3_D,RES3_E,RES3_H,RES3_L,RES3_xHL,RES3_A,
|
||||
RES4_B,RES4_C,RES4_D,RES4_E,RES4_H,RES4_L,RES4_xHL,RES4_A,
|
||||
RES5_B,RES5_C,RES5_D,RES5_E,RES5_H,RES5_L,RES5_xHL,RES5_A,
|
||||
RES6_B,RES6_C,RES6_D,RES6_E,RES6_H,RES6_L,RES6_xHL,RES6_A,
|
||||
RES7_B,RES7_C,RES7_D,RES7_E,RES7_H,RES7_L,RES7_xHL,RES7_A,
|
||||
SET0_B,SET0_C,SET0_D,SET0_E,SET0_H,SET0_L,SET0_xHL,SET0_A,
|
||||
SET1_B,SET1_C,SET1_D,SET1_E,SET1_H,SET1_L,SET1_xHL,SET1_A,
|
||||
SET2_B,SET2_C,SET2_D,SET2_E,SET2_H,SET2_L,SET2_xHL,SET2_A,
|
||||
SET3_B,SET3_C,SET3_D,SET3_E,SET3_H,SET3_L,SET3_xHL,SET3_A,
|
||||
SET4_B,SET4_C,SET4_D,SET4_E,SET4_H,SET4_L,SET4_xHL,SET4_A,
|
||||
SET5_B,SET5_C,SET5_D,SET5_E,SET5_H,SET5_L,SET5_xHL,SET5_A,
|
||||
SET6_B,SET6_C,SET6_D,SET6_E,SET6_H,SET6_L,SET6_xHL,SET6_A,
|
||||
SET7_B,SET7_C,SET7_D,SET7_E,SET7_H,SET7_L,SET7_xHL,SET7_A
|
||||
};
|
||||
|
||||
enum CodesED
|
||||
{
|
||||
DB_00,DB_01,DB_02,DB_03,DB_04,DB_05,DB_06,DB_07,
|
||||
DB_08,DB_09,DB_0A,DB_0B,DB_0C,DB_0D,DB_0E,DB_0F,
|
||||
DB_10,DB_11,DB_12,DB_13,DB_14,DB_15,DB_16,DB_17,
|
||||
DB_18,DB_19,DB_1A,DB_1B,DB_1C,DB_1D,DB_1E,DB_1F,
|
||||
DB_20,DB_21,DB_22,DB_23,DB_24,DB_25,DB_26,DB_27,
|
||||
DB_28,DB_29,DB_2A,DB_2B,DB_2C,DB_2D,DB_2E,DB_2F,
|
||||
DB_30,DB_31,DB_32,DB_33,DB_34,DB_35,DB_36,DB_37,
|
||||
DB_38,DB_39,DB_3A,DB_3B,DB_3C,DB_3D,DB_3E,DB_3F,
|
||||
IN_B_xC,OUT_xC_B,SBC_HL_BC,LD_xWORDe_BC,NEG,RETN,IM_0,LD_I_A,
|
||||
IN_C_xC,OUT_xC_C,ADC_HL_BC,LD_BC_xWORDe,DB_4C,RETI,DB_,LD_R_A,
|
||||
IN_D_xC,OUT_xC_D,SBC_HL_DE,LD_xWORDe_DE,DB_54,DB_55,IM_1,LD_A_I,
|
||||
IN_E_xC,OUT_xC_E,ADC_HL_DE,LD_DE_xWORDe,DB_5C,DB_5D,IM_2,LD_A_R,
|
||||
IN_H_xC,OUT_xC_H,SBC_HL_HL,LD_xWORDe_HL,DB_64,DB_65,DB_66,RRD,
|
||||
IN_L_xC,OUT_xC_L,ADC_HL_HL,LD_HL_xWORDe,DB_6C,DB_6D,DB_6E,RLD,
|
||||
IN_F_xC,DB_71,SBC_HL_SP,LD_xWORDe_SP,DB_74,DB_75,DB_76,DB_77,
|
||||
IN_A_xC,OUT_xC_A,ADC_HL_SP,LD_SP_xWORDe,DB_7C,DB_7D,DB_7E,DB_7F,
|
||||
DB_80,DB_81,DB_82,DB_83,DB_84,DB_85,DB_86,DB_87,
|
||||
DB_88,DB_89,DB_8A,DB_8B,DB_8C,DB_8D,DB_8E,DB_8F,
|
||||
DB_90,DB_91,DB_92,DB_93,DB_94,DB_95,DB_96,DB_97,
|
||||
DB_98,DB_99,DB_9A,DB_9B,DB_9C,DB_9D,DB_9E,DB_9F,
|
||||
LDI,CPI,INI,OUTI,DB_A4,DB_A5,DB_A6,DB_A7,
|
||||
LDD,CPD,IND,OUTD,DB_AC,DB_AD,DB_AE,DB_AF,
|
||||
LDIR,CPIR,INIR,OTIR,DB_B4,DB_B5,DB_B6,DB_B7,
|
||||
LDDR,CPDR,INDR,OTDR,DB_BC,DB_BD,DB_BE,DB_BF,
|
||||
DB_C0,DB_C1,DB_C2,DB_C3,DB_C4,DB_C5,DB_C6,DB_C7,
|
||||
DB_C8,DB_C9,DB_CA,DB_CB,DB_CC,DB_CD,DB_CE,DB_CF,
|
||||
DB_D0,DB_D1,DB_D2,DB_D3,DB_D4,DB_D5,DB_D6,DB_D7,
|
||||
DB_D8,DB_D9,DB_DA,DB_DB,DB_DC,DB_DD,DB_DE,DB_DF,
|
||||
DB_E0,DB_E1,DB_E2,DB_E3,DB_E4,DB_E5,DB_E6,DB_E7,
|
||||
DB_E8,DB_E9,DB_EA,DB_EB,DB_EC,DB_ED,DB_EE,DB_EF,
|
||||
DB_F0,DB_F1,DB_F2,DB_F3,DB_F4,DB_F5,DB_F6,DB_F7,
|
||||
DB_F8,DB_F9,DB_FA,DB_FB,DB_FC,DB_FD,DB_FE,DB_FF
|
||||
};
|
||||
|
||||
static void CodesCB(register Z80 *R)
|
||||
{
|
||||
register byte I;
|
||||
|
||||
I=RdZ80(R->PC.W++);
|
||||
R->ICount-=CyclesCB[I];
|
||||
switch(I)
|
||||
{
|
||||
#include "CodesCB.h"
|
||||
default:
|
||||
if(R->TrapBadOps)
|
||||
printf
|
||||
(
|
||||
"[Z80 %lX] Unrecognized instruction: CB %02X at PC=%04X\n",
|
||||
(long)(R->User),RdZ80(R->PC.W-1),R->PC.W-2
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static void CodesDDCB(register Z80 *R)
|
||||
{
|
||||
register pair J;
|
||||
register byte I;
|
||||
|
||||
#define XX IX
|
||||
J.W=R->XX.W+(offset)RdZ80(R->PC.W++);
|
||||
I=RdZ80(R->PC.W++);
|
||||
R->ICount-=CyclesXXCB[I];
|
||||
switch(I)
|
||||
{
|
||||
#include "CodesXCB.h"
|
||||
default:
|
||||
if(R->TrapBadOps)
|
||||
printf
|
||||
(
|
||||
"[Z80 %lX] Unrecognized instruction: DD CB %02X %02X at PC=%04X\n",
|
||||
(long)(R->User),RdZ80(R->PC.W-2),RdZ80(R->PC.W-1),R->PC.W-4
|
||||
);
|
||||
}
|
||||
#undef XX
|
||||
}
|
||||
|
||||
static void CodesFDCB(register Z80 *R)
|
||||
{
|
||||
register pair J;
|
||||
register byte I;
|
||||
|
||||
#define XX IY
|
||||
J.W=R->XX.W+(offset)RdZ80(R->PC.W++);
|
||||
I=RdZ80(R->PC.W++);
|
||||
R->ICount-=CyclesXXCB[I];
|
||||
switch(I)
|
||||
{
|
||||
#include "CodesXCB.h"
|
||||
default:
|
||||
if(R->TrapBadOps)
|
||||
printf
|
||||
(
|
||||
"[Z80 %lX] Unrecognized instruction: FD CB %02X %02X at PC=%04X\n",
|
||||
(long)R->User,RdZ80(R->PC.W-2),RdZ80(R->PC.W-1),R->PC.W-4
|
||||
);
|
||||
}
|
||||
#undef XX
|
||||
}
|
||||
|
||||
static void CodesED(register Z80 *R)
|
||||
{
|
||||
register byte I;
|
||||
register pair J;
|
||||
|
||||
I=RdZ80(R->PC.W++);
|
||||
R->ICount-=CyclesED[I];
|
||||
switch(I)
|
||||
{
|
||||
#include "CodesED.h"
|
||||
case PFX_ED:
|
||||
R->PC.W--;break;
|
||||
default:
|
||||
if(R->TrapBadOps)
|
||||
printf
|
||||
(
|
||||
"[Z80 %lX] Unrecognized instruction: ED %02X at PC=%04X\n",
|
||||
(long)R->User,RdZ80(R->PC.W-1),R->PC.W-2
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static void CodesDD(register Z80 *R)
|
||||
{
|
||||
register byte I;
|
||||
register pair J;
|
||||
|
||||
#define XX IX
|
||||
I=RdZ80(R->PC.W++);
|
||||
R->ICount-=CyclesXX[I];
|
||||
switch(I)
|
||||
{
|
||||
#include "CodesXX.h"
|
||||
case PFX_FD:
|
||||
case PFX_DD:
|
||||
R->PC.W--;break;
|
||||
case PFX_CB:
|
||||
CodesDDCB(R);break;
|
||||
case HALT:
|
||||
R->PC.W--;R->IFF|=0x80;R->ICount=0;break;
|
||||
default:
|
||||
if(R->TrapBadOps)
|
||||
printf
|
||||
(
|
||||
"[Z80 %lX] Unrecognized instruction: DD %02X at PC=%04X\n",
|
||||
(long)R->User,RdZ80(R->PC.W-1),R->PC.W-2
|
||||
);
|
||||
}
|
||||
#undef XX
|
||||
}
|
||||
|
||||
static void CodesFD(register Z80 *R)
|
||||
{
|
||||
register byte I;
|
||||
register pair J;
|
||||
|
||||
#define XX IY
|
||||
I=RdZ80(R->PC.W++);
|
||||
R->ICount-=CyclesXX[I];
|
||||
switch(I)
|
||||
{
|
||||
#include "CodesXX.h"
|
||||
case PFX_FD:
|
||||
case PFX_DD:
|
||||
R->PC.W--;break;
|
||||
case PFX_CB:
|
||||
CodesFDCB(R);break;
|
||||
case HALT:
|
||||
R->PC.W--;R->IFF|=0x80;R->ICount=0;break;
|
||||
default:
|
||||
printf
|
||||
(
|
||||
"Unrecognized instruction: FD %02X at PC=%04X\n",
|
||||
RdZ80(R->PC.W-1),R->PC.W-2
|
||||
);
|
||||
}
|
||||
#undef XX
|
||||
}
|
||||
|
||||
/** ResetZ80() ***********************************************/
|
||||
/** This function can be used to reset the register struct **/
|
||||
/** before starting execution with Z80(). It sets the **/
|
||||
/** registers to their supposed initial values. **/
|
||||
/*************************************************************/
|
||||
void ResetZ80(Z80 *R)
|
||||
{
|
||||
R->PC.W=0x0000;R->SP.W=0xF000;
|
||||
R->AF.W=R->BC.W=R->DE.W=R->HL.W=0x0000;
|
||||
R->AF1.W=R->BC1.W=R->DE1.W=R->HL1.W=0x0000;
|
||||
R->IX.W=R->IY.W=0x0000;
|
||||
R->I=0x00;R->IFF=0x00;
|
||||
R->ICount=R->IPeriod;
|
||||
R->IRequest=INT_NONE;
|
||||
}
|
||||
|
||||
/** ExecZ80() ************************************************/
|
||||
/** This function will execute a single Z80 opcode. It will **/
|
||||
/** then return next PC, and current register values in R. **/
|
||||
/*************************************************************/
|
||||
word ExecZ80(Z80 *R)
|
||||
{
|
||||
register byte I;
|
||||
register pair J;
|
||||
|
||||
I=RdZ80(R->PC.W++);
|
||||
R->ICount-=Cycles[I];
|
||||
switch(I)
|
||||
{
|
||||
#include "Codes.h"
|
||||
case PFX_CB: CodesCB(R);break;
|
||||
case PFX_ED: CodesED(R);break;
|
||||
case PFX_FD: CodesFD(R);break;
|
||||
case PFX_DD: CodesDD(R);break;
|
||||
}
|
||||
|
||||
/* We are done */
|
||||
return(R->PC.W);
|
||||
}
|
||||
|
||||
/** IntZ80() *************************************************/
|
||||
/** This function will generate interrupt of given vector. **/
|
||||
/*************************************************************/
|
||||
void IntZ80(Z80 *R,word Vector)
|
||||
{
|
||||
if((R->IFF&0x01)||(Vector==INT_NMI))
|
||||
{
|
||||
/* Experimental V Shouldn't disable all interrupts? */
|
||||
R->IFF=(R->IFF&0x9E)|((R->IFF&0x01)<<6);
|
||||
if(R->IFF&0x80) { R->PC.W++;R->IFF&=0x7F; }
|
||||
M_PUSH(PC);
|
||||
|
||||
if(Vector==INT_NMI) R->PC.W=INT_NMI;
|
||||
else
|
||||
if(R->IFF&0x04)
|
||||
{
|
||||
Vector=(Vector&0xFF)|((word)(R->I)<<8);
|
||||
R->PC.B.l=RdZ80(Vector++);
|
||||
R->PC.B.h=RdZ80(Vector);
|
||||
}
|
||||
else
|
||||
if(R->IFF&0x02) R->PC.W=INT_IRQ;
|
||||
else R->PC.W=Vector;
|
||||
}
|
||||
}
|
||||
|
||||
/** RunZ80() *************************************************/
|
||||
/** This function will run Z80 code until an LoopZ80() call **/
|
||||
/** returns INT_QUIT. It will return the PC at which **/
|
||||
/** emulation stopped, and current register values in R. **/
|
||||
/*************************************************************/
|
||||
word RunZ80(Z80 *R)
|
||||
{
|
||||
register byte I;
|
||||
register pair J;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
/* Turn tracing on when reached trap address */
|
||||
if(R->PC.W==R->Trap) R->Trace=1;
|
||||
/* Call single-step debugger, exit if requested */
|
||||
if(R->Trace)
|
||||
if(!DebugZ80(R)) return(R->PC.W);
|
||||
#endif
|
||||
|
||||
I=RdZ80(R->PC.W++);
|
||||
R->ICount-=Cycles[I];
|
||||
switch(I)
|
||||
{
|
||||
#include "Codes.h"
|
||||
case PFX_CB: CodesCB(R);break;
|
||||
case PFX_ED: CodesED(R);break;
|
||||
case PFX_FD: CodesFD(R);break;
|
||||
case PFX_DD: CodesDD(R);break;
|
||||
}
|
||||
|
||||
/* If cycle counter expired... */
|
||||
if(R->ICount<=0)
|
||||
{
|
||||
/* If we have come after EI, get address from IRequest */
|
||||
/* Otherwise, get it from the loop handler */
|
||||
if(R->IFF&0x20)
|
||||
{
|
||||
J.W=R->IRequest; /* Get pending interrupt */
|
||||
R->ICount+=R->IBackup-1; /* Restore the ICount */
|
||||
R->IFF&=0xDF; /* Done with AfterEI state */
|
||||
}
|
||||
else
|
||||
{
|
||||
J.W=LoopZ80(R); /* Call periodic handler */
|
||||
R->ICount=R->IPeriod; /* Reset the cycle counter */
|
||||
}
|
||||
|
||||
if(J.W==INT_QUIT) return(R->PC.W); /* Exit if INT_QUIT */
|
||||
if(J.W!=INT_NONE) IntZ80(R,J.W); /* Int-pt if needed */
|
||||
}
|
||||
}
|
||||
|
||||
/* Execution stopped */
|
||||
return(R->PC.W);
|
||||
}
|
|
@ -0,0 +1,139 @@
|
|||
/** Z80: portable Z80 emulator *******************************/
|
||||
/** **/
|
||||
/** Z80.h **/
|
||||
/** **/
|
||||
/** This file contains declarations relevant to emulation **/
|
||||
/** of Z80 CPU. **/
|
||||
/** **/
|
||||
/** Copyright (C) Marat Fayzullin 1994,1995,1996,1997 **/
|
||||
/** You are not allowed to distribute this software **/
|
||||
/** commercially. Please, notify me, if you make any **/
|
||||
/** changes to this file. **/
|
||||
/*************************************************************/
|
||||
#ifndef Z80_H
|
||||
#define Z80_H
|
||||
|
||||
/* Compilation options: */
|
||||
/* #define DEBUG */ /* Compile debugging version */
|
||||
/* #define LSB_FIRST */ /* Compile for low-endian CPU */
|
||||
/* #define MSB_FIRST */ /* Compile for hi-endian CPU */
|
||||
|
||||
/* LoopZ80() may return: */
|
||||
#define INT_IRQ 0x0038 /* Standard RST 38h interrupt */
|
||||
#define INT_NMI 0x0066 /* Non-maskable interrupt */
|
||||
#define INT_NONE 0xFFFF /* No interrupt required */
|
||||
#define INT_QUIT 0xFFFE /* Exit the emulation */
|
||||
|
||||
/* Bits in Z80 F register: */
|
||||
#define S_FLAG 0x80 /* 1: Result negative */
|
||||
#define Z_FLAG 0x40 /* 1: Result is zero */
|
||||
#define H_FLAG 0x10 /* 1: Halfcarry/Halfborrow */
|
||||
#define P_FLAG 0x04 /* 1: Result is even */
|
||||
#define V_FLAG 0x04 /* 1: Overflow occured */
|
||||
#define N_FLAG 0x02 /* 1: Subtraction occured */
|
||||
#define C_FLAG 0x01 /* 1: Carry/Borrow occured */
|
||||
|
||||
/** Simple Datatypes *****************************************/
|
||||
/** NOTICE: sizeof(byte)=1 and sizeof(word)=2 **/
|
||||
/*************************************************************/
|
||||
typedef unsigned char byte;
|
||||
typedef unsigned short word;
|
||||
typedef signed char offset;
|
||||
|
||||
/** Structured Datatypes *************************************/
|
||||
/** NOTICE: #define LSB_FIRST for machines where least **/
|
||||
/** signifcant byte goes first. **/
|
||||
/*************************************************************/
|
||||
typedef union
|
||||
{
|
||||
#ifdef LSB_FIRST
|
||||
struct { byte l,h; } B;
|
||||
#else
|
||||
struct { byte h,l; } B;
|
||||
#endif
|
||||
word W;
|
||||
} pair;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
pair AF,BC,DE,HL,IX,IY,PC,SP; /* Main registers */
|
||||
pair AF1,BC1,DE1,HL1; /* Shadow registers */
|
||||
byte IFF,I; /* Interrupt registers */
|
||||
|
||||
int IPeriod,ICount; /* Set IPeriod to number of CPU cycles */
|
||||
/* between calls to LoopZ80() */
|
||||
int IBackup; /* Private, don't touch */
|
||||
word IRequest; /* Set to address of pending IRQ */
|
||||
void *User; /* Arbitrary user data (ID,RAM*,etc.) */
|
||||
byte TrapBadOps; /* Set to 1 to warn of illegal opcodes */
|
||||
word Trap; /* Set Trap to address to trace from */
|
||||
byte Trace; /* Set Trace=1 to start tracing */
|
||||
} Z80;
|
||||
|
||||
/** ResetZ80() ***********************************************/
|
||||
/** This function can be used to reset the registers before **/
|
||||
/** starting execution with RunZ80(). It sets registers to **/
|
||||
/** their initial values. **/
|
||||
/*************************************************************/
|
||||
void ResetZ80(register Z80 *R);
|
||||
|
||||
/** ExecZ80() ************************************************/
|
||||
/** This function will execute a single Z80 opcode. It will **/
|
||||
/** then return next PC, and current register values in R. **/
|
||||
/*************************************************************/
|
||||
word ExecZ80(register Z80 *R);
|
||||
|
||||
/** IntZ80() *************************************************/
|
||||
/** This function will generate interrupt of given vector. **/
|
||||
/*************************************************************/
|
||||
void IntZ80(register Z80 *R,register word Vector);
|
||||
|
||||
/** RunZ80() *************************************************/
|
||||
/** This function will run Z80 code until an LoopZ80() call **/
|
||||
/** returns INT_QUIT. It will return the PC at which **/
|
||||
/** emulation stopped, and current register values in R. **/
|
||||
/*************************************************************/
|
||||
word RunZ80(register Z80 *R);
|
||||
|
||||
/** RdZ80()/WrZ80() ******************************************/
|
||||
/** These functions are called when access to RAM occurs. **/
|
||||
/** They allow to control memory access. **/
|
||||
/************************************ TO BE WRITTEN BY USER **/
|
||||
void WrZ80(register word Addr,register byte Value);
|
||||
byte RdZ80(register word Addr);
|
||||
|
||||
/** InZ80()/OutZ80() *****************************************/
|
||||
/** Z80 emulation calls these functions to read/write from **/
|
||||
/** I/O ports. There can be 65536 I/O ports, but only first **/
|
||||
/** 256 are usually used **/
|
||||
/************************************ TO BE WRITTEN BY USER **/
|
||||
void OutZ80(register word Port,register byte Value);
|
||||
byte InZ80(register word Port);
|
||||
|
||||
/** PatchZ80() ***********************************************/
|
||||
/** Z80 emulation calls this function when it encounters a **/
|
||||
/** special patch command (ED FE) provided for user needs. **/
|
||||
/** For example, it can be called to emulate BIOS calls, **/
|
||||
/** such as disk and tape access. Replace it with an empty **/
|
||||
/** macro for no patching. **/
|
||||
/************************************ TO BE WRITTEN BY USER **/
|
||||
void PatchZ80(register Z80 *R);
|
||||
|
||||
/** DebugZ80() ***********************************************/
|
||||
/** This function should exist if DEBUG is #defined. When **/
|
||||
/** Trace!=0, it is called after each command executed by **/
|
||||
/** the CPU, and given the Z80 registers. Emulation exits **/
|
||||
/** if DebugZ80() returns 0. **/
|
||||
/*************************************************************/
|
||||
byte DebugZ80(register Z80 *R);
|
||||
|
||||
/** LoopZ80() ************************************************/
|
||||
/** Z80 emulation calls this function periodically to check **/
|
||||
/** if the system hardware requires any interrupts. This **/
|
||||
/** function must return an address of the interrupt vector **/
|
||||
/** (0x0038, 0x0066, etc.) or INT_NONE for no interrupt. **/
|
||||
/** Return INT_QUIT to exit the emulation loop. **/
|
||||
/************************************ TO BE WRITTEN BY USER **/
|
||||
word LoopZ80(register Z80 *R);
|
||||
|
||||
#endif /* Z80_H */
|
|
@ -0,0 +1,636 @@
|
|||
/* amiga.c V1.1.0
|
||||
*
|
||||
* Amiga systemspesifikk kode for TIKI-100_emul
|
||||
* Copyright (C) Asbjørn Djupdal 2000-2001
|
||||
*/
|
||||
|
||||
#include "TIKI-100_emul.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <graphics/gfxbase.h>
|
||||
#include <clib/intuition_protos.h>
|
||||
#include <clib/asl_protos.h>
|
||||
#include <clib/gadtools_protos.h>
|
||||
#include <clib/graphics_protos.h>
|
||||
#include <clib/dos_protos.h>
|
||||
#include <clib/alib_protos.h>
|
||||
#include <clib/exec_protos.h>
|
||||
#include <clib/locale_protos.h>
|
||||
|
||||
#define CATCOMP_NUMBERS
|
||||
#define CATCOMP_STRINGS
|
||||
#define CATCOMP_BLOCK
|
||||
#define CATCOMP_CODE
|
||||
#include "amiga_strings.h"
|
||||
|
||||
#define DEFAULT_DIR "PROGDIR:plater"
|
||||
#define STATUSBAR_HEIGHT 15
|
||||
|
||||
/* protos */
|
||||
|
||||
int main (int argc, char *argv[]);
|
||||
static struct Menu *CreateLocMenus(struct NewMenu *newMenus, ULONG tag, ...);
|
||||
static void createStatusBar (void);
|
||||
static void draw3dBox (int x, int y, int w, int h, boolean raise);
|
||||
static void doIDCMP (void);
|
||||
static void loadDiskImage (int drive);
|
||||
static void saveDiskImage (int drive);
|
||||
|
||||
/* variabler */
|
||||
|
||||
static byte keyTable[0x80] = {
|
||||
KEY_GRAFIKK, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
|
||||
0x38, 0x39, 0x30, 0x2b, 0x40, KEY_UTVID, KEY_NONE, KEY_NUM0,
|
||||
0x71, 0x77, 0x65, 0x72, 0x74, 0x79, 0x75, 0x69,
|
||||
0x6f, 0x70, 0xe5, 0x5e, KEY_NONE, KEY_NUM1, KEY_NUM2, KEY_NUM3,
|
||||
0x61, 0x73, 0x64, 0x66, 0x67, 0x68, 0x6a, 0x6b,
|
||||
0x6c, 0xf8, 0xe6, 0x27, KEY_NONE, KEY_NUM4, KEY_NUM5, KEY_NUM6,
|
||||
0x3c, 0x7a, 0x78, 0x63, 0x76, 0x62, 0x6e, 0x6d,
|
||||
0x2c, 0x2e, 0x2d, KEY_NONE, KEY_NUMDOT, KEY_NUM7, KEY_NUM8, KEY_NUM9,
|
||||
KEY_SPACE, KEY_SLETT, KEY_BRYT, KEY_ENTER, KEY_CR, KEY_ANGRE, KEY_HOME, KEY_NONE,
|
||||
KEY_NONE, KEY_NONE, KEY_NUMMINUS, KEY_NONE, KEY_UP, KEY_DOWN, KEY_RIGHT, KEY_LEFT,
|
||||
KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_PGUP, KEY_PGDOWN,
|
||||
KEY_TABLEFT, KEY_TABRIGHT, KEY_NUMPERCENT, KEY_NUMEQU, KEY_NUMDIV, KEY_NUMMULT, KEY_NUMPLUS, KEY_HJELP,
|
||||
KEY_SHIFT, KEY_SHIFT, KEY_NONE, KEY_CTRL, KEY_LOCK, KEY_NONE, KEY_NONE, KEY_NONE,
|
||||
KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
|
||||
KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
|
||||
KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE
|
||||
};
|
||||
|
||||
static struct NewMenu mn[] = {
|
||||
{NM_TITLE, (char *)MSG_EMULATOR_MENU, 0, 0, 0, 0, },
|
||||
{NM_ITEM, (char *)MSG_EMULATOR_RESET, 0, 0, 0, 0, },
|
||||
{NM_ITEM, (char *)MSG_EMULATOR_ABOUT, 0, 0, 0, 0, },
|
||||
{NM_ITEM, (char *)MSG_EMULATOR_QUIT, 0, 0, 0, 0, },
|
||||
|
||||
{NM_TITLE, (char *)MSG_DISKDRIVE_MENU, 0, 0, 0, 0, },
|
||||
{NM_ITEM, (char *)MSG_DISKDRIVE_LOADA, 0, 0, 0, 0, },
|
||||
{NM_ITEM, (char *)MSG_DISKDRIVE_LOADB, 0, 0, 0, 0, },
|
||||
{NM_ITEM, (char *)MSG_DISKDRIVE_SAVEA, 0, NM_ITEMDISABLED, 0, 0, },
|
||||
{NM_ITEM, (char *)MSG_DISKDRIVE_SAVEB, 0, NM_ITEMDISABLED, 0, 0, },
|
||||
{NM_ITEM, (char *)MSG_DISKDRIVE_REMOVEA, 0, 0, 0, 0, },
|
||||
{NM_ITEM, (char *)MSG_DISKDRIVE_REMOVEB, 0, 0, 0, 0, },
|
||||
|
||||
{NM_TITLE, (char *)MSG_OPTIONS_MENU, 0, 0, 0, 0, },
|
||||
{NM_ITEM, (char *)MSG_OPTIONS_SLOWDOWN, 0, NM_ITEMDISABLED | CHECKIT | MENUTOGGLE, 0, 0, },
|
||||
{NM_ITEM, (char *)MSG_OPTIONS_SCANLINES, 0, CHECKIT | MENUTOGGLE, 0, 0, },
|
||||
{NM_ITEM, (char *)MSG_OPTIONS_SIZE40, 0, 0, 0, 0, },
|
||||
{NM_SUB, (char *)MSG_OPTIONS_SIZE40_ONE, 0, CHECKIT | CHECKED, ~1, 0, },
|
||||
{NM_SUB, (char *)MSG_OPTIONS_SIZE40_TWO, 0, CHECKIT, ~2, 0, },
|
||||
{NM_SUB, (char *)MSG_OPTIONS_SIZE40_FOUR, 0, CHECKIT, ~4, 0, },
|
||||
{NM_ITEM, (char *)MSG_OPTIONS_SIZE80, 0, 0, 0, 0, },
|
||||
{NM_SUB, (char *)MSG_OPTIONS_SIZE80_ONE, 0, CHECKIT | CHECKED, ~1, 0, },
|
||||
{NM_SUB, (char *)MSG_OPTIONS_SIZE80_TWO, 0, CHECKIT, ~2, 0, },
|
||||
|
||||
#ifdef DEBUG
|
||||
{NM_TITLE, (char *)MSG_DEBUG_MENU, 0, 0, 0, 0, },
|
||||
{NM_ITEM, (char *)MSG_DEBUG_MONITOR, 0, 0, 0, 0, },
|
||||
#endif
|
||||
|
||||
{NM_END, NULL, 0, 0, 0, 0, },
|
||||
};
|
||||
|
||||
static byte pressedKeys[0x100];
|
||||
static struct Screen *pubScreen;
|
||||
static struct Window *window;
|
||||
static struct Menu *menuStrip;
|
||||
static long pens[16];
|
||||
static struct LocaleInfo localeInfo;
|
||||
struct Library *IntuitionBase;
|
||||
struct Library *GfxBase;
|
||||
struct Library *GadToolsBase;
|
||||
struct Library *AslBase;
|
||||
struct Library *LocaleBase;
|
||||
static int topOffset, leftOffset;
|
||||
static int borderX, borderY;
|
||||
static int resolution = MEDRES;
|
||||
static BOOL scanlines = FALSE;
|
||||
static int times40 = 1;
|
||||
static int times80 = 1;
|
||||
static byte *dsk[2];
|
||||
static ULONG fileSize[2];
|
||||
static int width;
|
||||
static int height;
|
||||
static boolean changingWinSize;
|
||||
static boolean lock = FALSE;
|
||||
static boolean grafikk = FALSE;
|
||||
static boolean disk[2] = {FALSE, FALSE};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int main (int argc, char *argv[]) {
|
||||
memset (pressedKeys, 1, 0x100);
|
||||
|
||||
/* åpne bibliotek */
|
||||
if ((AslBase = (struct Library *)OpenLibrary ("asl.library", 37L))) {
|
||||
if ((IntuitionBase = (struct Library *)OpenLibrary ("intuition.library", 39L))) {
|
||||
if ((GfxBase = (struct Library *)OpenLibrary ("graphics.library", 39L))) {
|
||||
if ((GadToolsBase = (struct Library *)OpenLibrary ("gadtools.library", 39L))) {
|
||||
if ((LocaleBase = (struct Library *)OpenLibrary ("locale.library", 38L))) {
|
||||
|
||||
/* finn katalog */
|
||||
localeInfo.li_LocaleBase = LocaleBase;
|
||||
localeInfo.li_Catalog = OpenCatalog (NULL, "tikiemul.catalog",
|
||||
OC_BuiltInLanguage, "english", TAG_DONE);
|
||||
|
||||
/* skaff public screen */
|
||||
if ((pubScreen = LockPubScreen (NULL))) {
|
||||
|
||||
/* finn vindusrammetykkelse */
|
||||
topOffset = pubScreen->WBorTop + pubScreen->Font->ta_YSize + 1;
|
||||
leftOffset = pubScreen->WBorLeft;
|
||||
borderX = leftOffset + pubScreen->WBorRight;
|
||||
borderY = topOffset + pubScreen->WBorBottom + STATUSBAR_HEIGHT;
|
||||
|
||||
/* finn vindusstørrelse */
|
||||
width = 512 * times80;
|
||||
height = 256 * times80 * (scanlines ? 2 : 1);
|
||||
|
||||
/* åpne vindu */
|
||||
if ((window = (struct Window *)OpenWindowTags (NULL, WA_Left, 0, WA_Top, 0,
|
||||
WA_Width, width + borderX,
|
||||
WA_Height, height + borderY,
|
||||
WA_Activate, TRUE, WA_SmartRefresh, TRUE,
|
||||
WA_Title, "TIKI-100_emul",
|
||||
WA_PubScreen, pubScreen,
|
||||
WA_NewLookMenus, TRUE, WA_DepthGadget, TRUE,
|
||||
WA_CloseGadget, TRUE, WA_DragBar, TRUE,
|
||||
WA_IDCMP, IDCMP_RAWKEY | IDCMP_MENUPICK |
|
||||
IDCMP_CLOSEWINDOW | IDCMP_NEWSIZE,
|
||||
TAG_DONE))) {
|
||||
|
||||
/* skaff 16 pens */
|
||||
{
|
||||
BOOL cont = TRUE;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
if ((pens[i] = ObtainPen (pubScreen->ViewPort.ColorMap, -1, 0, 0, 0, PEN_EXCLUSIVE))
|
||||
== -1) {
|
||||
cont = FALSE;
|
||||
}
|
||||
}
|
||||
if (cont) {
|
||||
|
||||
/* sett bakgrunnsfarge til farge 0 */
|
||||
SetAPen (window->RPort, pens[0]);
|
||||
SetBPen (window->RPort, pens[0]);
|
||||
RectFill (window->RPort, leftOffset,
|
||||
topOffset, width - 1 + leftOffset,
|
||||
height - 1 + topOffset);
|
||||
|
||||
createStatusBar();
|
||||
|
||||
/* lag menystripe */
|
||||
{
|
||||
APTR *visInfo;
|
||||
if ((visInfo = (APTR)GetVisualInfo (window->WScreen, TAG_END))) {
|
||||
if ((menuStrip = (struct Menu *)CreateLocMenus (mn, TAG_END))) {
|
||||
if (LayoutMenus (menuStrip, visInfo, GTMN_NewLookMenus, TRUE, TAG_END)) {
|
||||
if (SetMenuStrip (window, menuStrip)) {
|
||||
|
||||
/* kjør emulator */
|
||||
runEmul();
|
||||
|
||||
/* avlutt */
|
||||
ClearMenuStrip (window);
|
||||
}
|
||||
FreeMenus (menuStrip);
|
||||
}
|
||||
}
|
||||
FreeVisualInfo (visInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i = 0; i < 16; i++) {
|
||||
ReleasePen (pubScreen->ViewPort.ColorMap, pens[i]);
|
||||
}
|
||||
}
|
||||
CloseWindow (window);
|
||||
}
|
||||
UnlockPubScreen (NULL, pubScreen);
|
||||
}
|
||||
CloseCatalog (localeInfo.li_Catalog);
|
||||
CloseLibrary (LocaleBase);
|
||||
}
|
||||
CloseLibrary (GadToolsBase);
|
||||
}
|
||||
CloseLibrary (GfxBase);
|
||||
}
|
||||
CloseLibrary (IntuitionBase);
|
||||
}
|
||||
CloseLibrary (AslBase);
|
||||
}
|
||||
free (dsk[0]);
|
||||
free (dsk[1]);
|
||||
return 0;
|
||||
}
|
||||
/* Tatt (nesten) direkte fra NDK
|
||||
* Lokalisert CreateMenus()
|
||||
*/
|
||||
static struct Menu *CreateLocMenus(struct NewMenu *newMenus, ULONG tag, ...) {
|
||||
UWORD i = 0;
|
||||
struct NewMenu *nm;
|
||||
struct Menu *menus;
|
||||
|
||||
/* gå til slutten */
|
||||
while (newMenus[i++].nm_Type != NM_END) {}
|
||||
|
||||
/* alloker minne til menystruktur */
|
||||
if (!(nm = AllocVec (sizeof (struct NewMenu) * i, MEMF_CLEAR | MEMF_PUBLIC)))
|
||||
return NULL;
|
||||
|
||||
/* sett alle strenger i menystruktur */
|
||||
while (i--) {
|
||||
nm[i] = newMenus[i];
|
||||
|
||||
if (nm[i].nm_Label != NM_BARLABEL) {
|
||||
nm[i].nm_CommKey = GetString (&localeInfo, (LONG)nm[i].nm_Label);
|
||||
|
||||
nm[i].nm_Label = nm[i].nm_CommKey + 2;
|
||||
|
||||
if (nm[i].nm_CommKey[0] == ' ')
|
||||
nm[i].nm_CommKey = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* lag meny */
|
||||
menus = CreateMenusA (nm, (struct TagItem *)&tag);
|
||||
|
||||
FreeVec (nm);
|
||||
|
||||
return (menus);
|
||||
}
|
||||
/* lager statusbar */
|
||||
static void createStatusBar (void) {
|
||||
SetAPen (window->RPort, 0);
|
||||
RectFill (window->RPort, leftOffset, height + topOffset,
|
||||
width - 1 + leftOffset, height - 1 + STATUSBAR_HEIGHT + topOffset);
|
||||
|
||||
draw3dBox (0, height, width, STATUSBAR_HEIGHT, TRUE);
|
||||
|
||||
draw3dBox (20, height + 3, 9, 9, FALSE);
|
||||
draw3dBox (40, height + 3, 9, 9, FALSE);
|
||||
draw3dBox (60, height + 3, 9, 9, FALSE);
|
||||
draw3dBox (80, height + 3, 9, 9, FALSE);
|
||||
|
||||
lockLight (lock);
|
||||
grafikkLight (grafikk);
|
||||
diskLight (0, disk[0]);
|
||||
diskLight (1, disk[1]);
|
||||
}
|
||||
/* lager en 3d-boks */
|
||||
static void draw3dBox (int x, int y, int w, int h, boolean raise) {
|
||||
long pen1 = (raise ? 2 : 1);
|
||||
long pen2 = (raise ? 1 : 2);
|
||||
|
||||
SetAPen (window->RPort, pen1);
|
||||
Move (window->RPort, x + leftOffset, y + h - 1 + topOffset);
|
||||
Draw (window->RPort, x + leftOffset, y + topOffset);
|
||||
Draw (window->RPort, x + w - 1 + leftOffset, y + topOffset);
|
||||
SetAPen (window->RPort, pen2);
|
||||
Draw (window->RPort, x + w - 1 + leftOffset, y + h - 1 + topOffset);
|
||||
Draw (window->RPort, x + leftOffset, y + h - 1 + topOffset);
|
||||
}
|
||||
|
||||
/* Forandre oppløsning */
|
||||
void changeRes (int newRes) {
|
||||
resolution = newRes;
|
||||
switch (resolution) {
|
||||
case LOWRES:
|
||||
width = 256 * times40;
|
||||
height = 256 * times40;
|
||||
break;
|
||||
case MEDRES:
|
||||
width = 512 * times80;
|
||||
height = 256 * times80 * (scanlines ? 2 : 1);
|
||||
break;
|
||||
case HIGHRES:
|
||||
width = 1024;
|
||||
height = 256 * (scanlines ? 4 : 1);
|
||||
break;
|
||||
}
|
||||
ChangeWindowBox (window, 0, 0, width + borderX, height + borderY);
|
||||
/* må vente til vindu har fått ny størrelse */
|
||||
changingWinSize = TRUE;
|
||||
while (changingWinSize) {
|
||||
Wait (1L << window->UserPort->mp_SigBit);
|
||||
doIDCMP();
|
||||
}
|
||||
/* rensk vindu */
|
||||
SetAPen (window->RPort, pens[0]);
|
||||
RectFill (window->RPort, leftOffset, topOffset, width - 1 + leftOffset, height - 1 + topOffset);
|
||||
|
||||
createStatusBar();
|
||||
}
|
||||
/* Plotter en pixel med farge tatt fra pallett */
|
||||
void plotPixel (int x, int y, int color) {
|
||||
SetAPen (window->RPort, pens[color]);
|
||||
switch (resolution) {
|
||||
case LOWRES:
|
||||
x *= times40;
|
||||
y *= times40;
|
||||
break;
|
||||
case MEDRES:
|
||||
x *= times80;
|
||||
y *= times80 * (scanlines ? 2 : 1);
|
||||
break;
|
||||
case HIGHRES:
|
||||
y *= scanlines ? 4 : 1;
|
||||
break;
|
||||
}
|
||||
WritePixel (window->RPort, x + leftOffset, y + topOffset);
|
||||
}
|
||||
/* Scroller skjerm 'distance' linjer oppover */
|
||||
void scrollScreen (int distance) {
|
||||
switch (resolution) {
|
||||
case LOWRES:
|
||||
distance *= times40;
|
||||
break;
|
||||
case MEDRES:
|
||||
distance *= times80 * (scanlines ? 2 : 1);
|
||||
break;
|
||||
case HIGHRES:
|
||||
distance *= scanlines ? 4 : 1;
|
||||
break;
|
||||
}
|
||||
ScrollRaster (window->RPort, 0, distance, leftOffset, topOffset,
|
||||
width - 1 + leftOffset, height - 1 + topOffset);
|
||||
}
|
||||
/* Ny farge, gitt pallett nummer og intensitet 0-255 */
|
||||
void changePalette (int colornumber, byte red, byte green, byte blue) {
|
||||
SetRGB32 (&(pubScreen->ViewPort), pens[colornumber], red << 24, green << 24, blue << 24);
|
||||
}
|
||||
/* Kalles periodisk. Lar system kode måle / senke emuleringshastighet
|
||||
* Kan også brukes til sjekk av brukeraktivitet
|
||||
* ms er antall "emulerte" millisekunder siden forrige gang loopEmul ble kalt
|
||||
*/
|
||||
void loopEmul (int ms) {
|
||||
doIDCMP();
|
||||
}
|
||||
/* Prosesserer alle nye IDCMP-events */
|
||||
static void doIDCMP (void) {
|
||||
struct IntuiMessage *msg;
|
||||
|
||||
while ((msg = (struct IntuiMessage *)GetMsg (window->UserPort))) {
|
||||
struct MenuItem *item;
|
||||
UWORD menuNumber;
|
||||
|
||||
switch (msg->Class) {
|
||||
case IDCMP_MENUPICK:
|
||||
menuNumber = msg->Code;
|
||||
while (menuNumber != MENUNULL) {
|
||||
item = (struct MenuItem *)ItemAddress (menuStrip, menuNumber);
|
||||
switch (MENUNUM (menuNumber)) {
|
||||
case 0: /* emulator */
|
||||
switch (ITEMNUM (menuNumber)) {
|
||||
case 0: /* reset */
|
||||
resetEmul();
|
||||
break;
|
||||
case 1: { /* om */
|
||||
struct EasyStruct omReq = {
|
||||
sizeof (struct EasyStruct), 0,
|
||||
GetString (&localeInfo, MSG_ABOUTBOX_TITLE),
|
||||
GetString (&localeInfo, MSG_ABOUTBOX_TEXT),
|
||||
GetString (&localeInfo, MSG_ABOUTBOX_BUTTON)
|
||||
};
|
||||
EasyRequest (NULL, &omReq, NULL);
|
||||
break;
|
||||
}
|
||||
case 2: /* avslutt */
|
||||
quitEmul();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 1: /* diskettstasjon */
|
||||
switch (ITEMNUM (menuNumber)) {
|
||||
case 0: /* hent plate a */
|
||||
loadDiskImage (0);
|
||||
break;
|
||||
case 1: /* hent plate b */
|
||||
loadDiskImage (1);
|
||||
break;
|
||||
case 2: /* lagre plate a */
|
||||
saveDiskImage (0);
|
||||
break;
|
||||
case 3: /* lagre plate b */
|
||||
saveDiskImage (1);
|
||||
break;
|
||||
case 4: /* fjern plate a */
|
||||
removeDisk (0);
|
||||
OffMenu (window, FULLMENUNUM (1, 2, 0));
|
||||
break;
|
||||
case 5: /* fjern plate b */
|
||||
removeDisk (1);
|
||||
OffMenu (window, FULLMENUNUM (1, 3, 0));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 2: /* innstillinger */
|
||||
switch (ITEMNUM (menuNumber)) {
|
||||
case 0: /* reduser hastighet */
|
||||
/* ikke implementert, har for treg maskin :-/ */
|
||||
break;
|
||||
case 1: /* bevar forhold */
|
||||
scanlines = item->Flags & CHECKED;
|
||||
changeRes (resolution);
|
||||
resetEmul();
|
||||
break;
|
||||
case 2: /* forstørr 40 modus */
|
||||
switch (SUBNUM (menuNumber)) {
|
||||
case 0: /* 1 */
|
||||
times40 = 1;
|
||||
break;
|
||||
case 1: /* 2 */
|
||||
times40 = 2;
|
||||
break;
|
||||
case 2: /* 4 */
|
||||
times40 = 4;
|
||||
break;
|
||||
}
|
||||
changeRes (resolution);
|
||||
resetEmul();
|
||||
break;
|
||||
case 3: /* forstærr 80 modus */
|
||||
switch (SUBNUM (menuNumber)) {
|
||||
case 0: /* 1 */
|
||||
times80 = 1;
|
||||
break;
|
||||
case 1: /* 2 */
|
||||
times80 = 2;
|
||||
break;
|
||||
}
|
||||
changeRes (resolution);
|
||||
resetEmul();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
#ifdef DEBUG
|
||||
case 3: /* debug */
|
||||
switch (ITEMNUM (menuNumber)) {
|
||||
case 0: /* monitor */
|
||||
trace();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
menuNumber = item->NextSelect;
|
||||
}
|
||||
break;
|
||||
case IDCMP_RAWKEY:
|
||||
if (msg->Code < 0x80) {
|
||||
pressedKeys[keyTable[msg->Code]] = 0;
|
||||
} else {
|
||||
pressedKeys[keyTable[msg->Code - 0x80]] = 1;
|
||||
}
|
||||
break;
|
||||
case IDCMP_CLOSEWINDOW:
|
||||
quitEmul();
|
||||
break;
|
||||
case IDCMP_NEWSIZE:
|
||||
changingWinSize = FALSE;
|
||||
break;
|
||||
}
|
||||
ReplyMsg ((struct Message *)msg);
|
||||
}
|
||||
}
|
||||
/* Hent inn diskbilde fra fil */
|
||||
static void loadDiskImage (int drive) {
|
||||
struct FileRequester *fr;
|
||||
static char drawer[256] = DEFAULT_DIR; /* hvilken skuffe filreq. skal åpne i */
|
||||
|
||||
if ((fr = (struct FileRequester *)AllocAslRequestTags (ASL_FileRequest, ASLFR_DoPatterns,
|
||||
TRUE, ASLFR_InitialPattern, "~(#?.info)",
|
||||
ASLFR_InitialDrawer, drawer, TAG_DONE))) {
|
||||
if (AslRequest (fr, NULL)) {
|
||||
char fileName[256];
|
||||
strcpy (fileName, fr->rf_Dir);
|
||||
strcpy (drawer, fr->rf_Dir);
|
||||
if (AddPart (fileName, fr->rf_File, 256)) {
|
||||
BPTR fp;
|
||||
if ((fp = Open ((STRPTR)&fileName, MODE_OLDFILE))) {
|
||||
struct FileInfoBlock *fileInfo = 0L;
|
||||
if ((fileInfo = (struct FileInfoBlock *)AllocDosObject (DOS_FIB, TAG_DONE))) {
|
||||
if (ExamineFH (fp, fileInfo)) {
|
||||
FILE *f;
|
||||
fileSize[drive] = fileInfo->fib_Size;
|
||||
free (dsk[drive]);
|
||||
OnMenu (window, FULLMENUNUM (1, (drive + 2), 0));
|
||||
if ((dsk[drive] = (byte *)malloc (fileSize[drive]))) {
|
||||
if ((f = fopen (fileName, "r"))) {
|
||||
if (fread (dsk[drive], 1, fileSize[drive], f)) {
|
||||
switch (fileSize[drive]) {
|
||||
case 40*1*18*128:
|
||||
insertDisk (drive, dsk[drive], 40, 1, 18, 128);
|
||||
break;
|
||||
case 40*1*10*512:
|
||||
insertDisk (drive, dsk[drive], 40, 1, 10, 512);
|
||||
break;
|
||||
case 40*2*10*512:
|
||||
insertDisk (drive, dsk[drive], 40, 2, 10, 512);
|
||||
break;
|
||||
case 80*2*10*512:
|
||||
insertDisk (drive, dsk[drive], 80, 2, 10, 512);
|
||||
break;
|
||||
default:
|
||||
removeDisk (drive);
|
||||
OffMenu (window, FULLMENUNUM (1, (drive + 2), 0));
|
||||
}
|
||||
} else {
|
||||
removeDisk (drive);
|
||||
OffMenu (window, FULLMENUNUM (1, (drive + 2), 0));
|
||||
}
|
||||
fclose (f);
|
||||
} else {
|
||||
removeDisk (drive);
|
||||
OffMenu (window, FULLMENUNUM (1, (drive + 2), 0));
|
||||
}
|
||||
} else {
|
||||
removeDisk (drive);
|
||||
OffMenu (window, FULLMENUNUM (1, (drive + 2), 0));
|
||||
}
|
||||
}
|
||||
FreeDosObject (DOS_FIB, fileInfo);
|
||||
}
|
||||
Close (fp);
|
||||
}
|
||||
}
|
||||
}
|
||||
FreeAslRequest (fr);
|
||||
}
|
||||
}
|
||||
/* Lagre diskbilde til fil */
|
||||
static void saveDiskImage (int drive) {
|
||||
struct FileRequester *fr;
|
||||
FILE *fp;
|
||||
static char drawer[256] = DEFAULT_DIR; /* hvilken skuffe filreq. skal åpne i */
|
||||
|
||||
if ((fr = (struct FileRequester *)AllocAslRequestTags (ASL_FileRequest, ASL_FuncFlags, FILF_SAVE,
|
||||
ASLFR_DoPatterns, TRUE, ASLFR_InitialPattern,
|
||||
"~(#?.info)", ASLFR_InitialDrawer, drawer,
|
||||
TAG_DONE))) {
|
||||
if (AslRequest (fr, NULL)) {
|
||||
char fileName[256];
|
||||
strcpy (fileName, fr->rf_Dir);
|
||||
strcpy (drawer, fr->rf_Dir);
|
||||
if (AddPart (fileName, fr->rf_File, 256)) {
|
||||
if ((fp = fopen (fileName, "w"))) {
|
||||
fwrite (dsk[drive], 1, fileSize[drive], fp);
|
||||
fclose (fp);
|
||||
}
|
||||
}
|
||||
}
|
||||
FreeAslRequest (fr);
|
||||
}
|
||||
}
|
||||
/* Tenn/slukk lock lys */
|
||||
void lockLight (boolean status) {
|
||||
lock = status;
|
||||
SetAPen (window->RPort, status ? 3 : 0);
|
||||
RectFill (window->RPort, 21 + leftOffset, height + 4 + topOffset,
|
||||
27 + leftOffset, height + 10 + topOffset);
|
||||
}
|
||||
/* Tenn/slukk grafikk lys */
|
||||
void grafikkLight (boolean status) {
|
||||
grafikk = status;
|
||||
SetAPen (window->RPort, status ? 3 : 0);
|
||||
RectFill (window->RPort, 41 + leftOffset, height + 4 + topOffset,
|
||||
47 + leftOffset, height + 10 + topOffset);
|
||||
}
|
||||
/* Tenn/slukk disk lys for gitt stasjon */
|
||||
void diskLight (int drive, boolean status) {
|
||||
int x = (drive ? 80 : 60);
|
||||
disk[drive] = status;
|
||||
SetAPen (window->RPort, status ? 3 : 0);
|
||||
RectFill (window->RPort, x + 1 + leftOffset, height + 4 + topOffset,
|
||||
x + 7 + leftOffset, height + 10 + topOffset);
|
||||
}
|
||||
/* Sjekk status til hver av de gitte tastene
|
||||
* Sett bit n i returkode hvis tast n IKKE er nedtrykt
|
||||
* Taster er enten ascii-kode eller en av konstantene over
|
||||
*/
|
||||
byte testKey (byte keys[8]) {
|
||||
return pressedKeys[keys[0]] | (pressedKeys[keys[1]] << 1) | (pressedKeys[keys[2]] << 2) |
|
||||
(pressedKeys[keys[3]] << 3) | (pressedKeys[keys[4]] << 4) | (pressedKeys[keys[5]] << 5) |
|
||||
(pressedKeys[keys[6]] << 6) | (pressedKeys[keys[7]] << 7);
|
||||
}
|
||||
/* Setter seriekanalparametre */
|
||||
void setParams (struct serParams *p1Params, struct serParams *p2Params) {
|
||||
/* ikke implementert */
|
||||
}
|
||||
/* Send tegn til seriekanal */
|
||||
void sendChar (int port, byte value) {
|
||||
/* ikke implementert */
|
||||
}
|
||||
/* Hent tegn fra seriekanal */
|
||||
byte getChar (int port) {
|
||||
/* ikke implementert */
|
||||
return 0;
|
||||
}
|
||||
/* Send tegn til skriver */
|
||||
void printChar (byte value) {
|
||||
/* ikke implementert */
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
; amiga.cd V1.1.0
|
||||
;
|
||||
; Katalogdeskriptor for TIKI-100_emul (amiga)
|
||||
; Copyright (C) Asbjørn Djupdal 2001
|
||||
;
|
||||
MSG_EMULATOR_MENU (//)
|
||||
\0Emulator
|
||||
;
|
||||
MSG_EMULATOR_RESET (//)
|
||||
R\0Reset
|
||||
;
|
||||
MSG_EMULATOR_ABOUT (//)
|
||||
\0About...
|
||||
;
|
||||
MSG_EMULATOR_QUIT (//)
|
||||
Q\0Quit
|
||||
;
|
||||
MSG_DISKDRIVE_MENU (//)
|
||||
\0Diskdrive
|
||||
;
|
||||
MSG_DISKDRIVE_LOADA (//)
|
||||
A\0Load disk A...
|
||||
;
|
||||
MSG_DISKDRIVE_LOADB (//)
|
||||
B\0Load disk B...
|
||||
;
|
||||
MSG_DISKDRIVE_SAVEA (//)
|
||||
\0Save disk A...
|
||||
;
|
||||
MSG_DISKDRIVE_SAVEB (//)
|
||||
\0Save disk B...
|
||||
;
|
||||
MSG_DISKDRIVE_REMOVEA (//)
|
||||
\0Remove disk A
|
||||
;
|
||||
MSG_DISKDRIVE_REMOVEB (//)
|
||||
\0Remove disk B
|
||||
;
|
||||
MSG_OPTIONS_MENU (//)
|
||||
\0Options
|
||||
;
|
||||
MSG_OPTIONS_SLOWDOWN (//)
|
||||
\0Slow down
|
||||
;
|
||||
MSG_OPTIONS_SCANLINES (//)
|
||||
\0Scanlines
|
||||
;
|
||||
MSG_OPTIONS_SIZE40 (//)
|
||||
\000Lowres size
|
||||
;
|
||||
MSG_OPTIONS_SIZE40_ONE (//)
|
||||
\0Standard
|
||||
;
|
||||
MSG_OPTIONS_SIZE40_TWO (//)
|
||||
\0Double
|
||||
;
|
||||
MSG_OPTIONS_SIZE40_FOUR (//)
|
||||
\0Quadruple
|
||||
;
|
||||
MSG_OPTIONS_SIZE80 (//)
|
||||
\0Medres size
|
||||
;
|
||||
MSG_OPTIONS_SIZE80_ONE (//)
|
||||
\0Standard
|
||||
;
|
||||
MSG_OPTIONS_SIZE80_TWO (//)
|
||||
\0Double
|
||||
; brukes bare av debugversjon
|
||||
MSG_DEBUG_MENU (//)
|
||||
\0Debug
|
||||
;
|
||||
MSG_DEBUG_MONITOR (//)
|
||||
M\0Monitor
|
||||
;
|
||||
MSG_ABOUTBOX_TITLE (//)
|
||||
About TIKI-100_emul
|
||||
;
|
||||
MSG_ABOUTBOX_TEXT (//)
|
||||
TIKI-100_emul V1.1.1 - a freeware TIKI 100 Rev. C emulator.\n\
|
||||
Z80 emulation copyright (C) Marat Fayzullin 1994,1995,1996,1997.\n\
|
||||
The rest is copyright (C) Asbjørn Djupdal 2000-2001.
|
||||
;
|
||||
MSG_ABOUTBOX_BUTTON (//)
|
||||
Ok
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,108 @@
|
|||
## version $VER: tikiemul.catalog 1.1 (02.06.01)
|
||||
## codeset 0
|
||||
## language X
|
||||
;
|
||||
MSG_EMULATOR_MENU
|
||||
|
||||
; \0Emulator
|
||||
;
|
||||
MSG_EMULATOR_RESET
|
||||
|
||||
; R\0Reset
|
||||
;
|
||||
MSG_EMULATOR_ABOUT
|
||||
|
||||
; \0About...
|
||||
;
|
||||
MSG_EMULATOR_QUIT
|
||||
|
||||
; Q\0Quit
|
||||
;
|
||||
MSG_DISKDRIVE_MENU
|
||||
|
||||
; \0Diskdrive
|
||||
;
|
||||
MSG_DISKDRIVE_LOADA
|
||||
|
||||
; A\0Load disk A...
|
||||
;
|
||||
MSG_DISKDRIVE_LOADB
|
||||
|
||||
; B\0Load disk B...
|
||||
;
|
||||
MSG_DISKDRIVE_SAVEA
|
||||
|
||||
; \0Save disk A...
|
||||
;
|
||||
MSG_DISKDRIVE_SAVEB
|
||||
|
||||
; \0Save disk B...
|
||||
;
|
||||
MSG_DISKDRIVE_REMOVEA
|
||||
|
||||
; \0Remove disk A
|
||||
;
|
||||
MSG_DISKDRIVE_REMOVEB
|
||||
|
||||
; \0Remove disk B
|
||||
;
|
||||
MSG_OPTIONS_MENU
|
||||
|
||||
; \0Options
|
||||
;
|
||||
MSG_OPTIONS_SLOWDOWN
|
||||
|
||||
; \0Slow down
|
||||
;
|
||||
MSG_OPTIONS_SCANLINES
|
||||
|
||||
; \0Scanlines
|
||||
;
|
||||
MSG_OPTIONS_SIZE40
|
||||
|
||||
; \000Lowres size
|
||||
;
|
||||
MSG_OPTIONS_SIZE40_ONE
|
||||
|
||||
; \0Standard
|
||||
;
|
||||
MSG_OPTIONS_SIZE40_TWO
|
||||
|
||||
; \0Double
|
||||
;
|
||||
MSG_OPTIONS_SIZE40_FOUR
|
||||
|
||||
; \0Quadruple
|
||||
;
|
||||
MSG_OPTIONS_SIZE80
|
||||
|
||||
; \0Medres size
|
||||
;
|
||||
MSG_OPTIONS_SIZE80_ONE
|
||||
|
||||
; \0Standard
|
||||
;
|
||||
MSG_OPTIONS_SIZE80_TWO
|
||||
|
||||
; \0Double
|
||||
;
|
||||
MSG_DEBUG_MENU
|
||||
|
||||
; \0Debug
|
||||
;
|
||||
MSG_DEBUG_MONITOR
|
||||
|
||||
; M\0Monitor
|
||||
;
|
||||
MSG_ABOUTBOX_TITLE
|
||||
|
||||
; About TIKI-100_emul
|
||||
;
|
||||
MSG_ABOUTBOX_TEXT
|
||||
|
||||
; TIKI-100_emul V1.1.1 - a freeware TIKI 100 Rev. C emulator.\nZ80 emulation copyright (C) Marat Fayzullin 1994,1995,1996,1997.\nThe rest is copyright (C) Asbjørn Djupdal 2000-2001.
|
||||
;
|
||||
MSG_ABOUTBOX_BUTTON
|
||||
|
||||
; Ok
|
||||
;
|
|
@ -0,0 +1,83 @@
|
|||
## version $VER: tikiemul.catalog 1.1 (02.06.01)
|
||||
## codeset 0
|
||||
## language norsk
|
||||
;
|
||||
MSG_EMULATOR_MENU
|
||||
\0Emulator
|
||||
;
|
||||
MSG_EMULATOR_RESET
|
||||
R\0Reset
|
||||
;
|
||||
MSG_EMULATOR_ABOUT
|
||||
\0Om...
|
||||
;
|
||||
MSG_EMULATOR_QUIT
|
||||
Q\0Avslutt
|
||||
;
|
||||
MSG_DISKDRIVE_MENU
|
||||
\0Diskettstasjon
|
||||
;
|
||||
MSG_DISKDRIVE_LOADA
|
||||
A\0Hent plate A...
|
||||
;
|
||||
MSG_DISKDRIVE_LOADB
|
||||
B\0Hent plate B...
|
||||
;
|
||||
MSG_DISKDRIVE_SAVEA
|
||||
\0Lagre plate A...
|
||||
;
|
||||
MSG_DISKDRIVE_SAVEB
|
||||
\0Lagre plate B...
|
||||
;
|
||||
MSG_DISKDRIVE_REMOVEA
|
||||
\0Fjern plate A
|
||||
;
|
||||
MSG_DISKDRIVE_REMOVEB
|
||||
\0Fjern plate B
|
||||
;
|
||||
MSG_OPTIONS_MENU
|
||||
\0Innstillinger
|
||||
;
|
||||
MSG_OPTIONS_SLOWDOWN
|
||||
\0Begrens hastighet
|
||||
;
|
||||
MSG_OPTIONS_SCANLINES
|
||||
\0Bevar forhold
|
||||
;
|
||||
MSG_OPTIONS_SIZE40
|
||||
\00040-modus størrelse
|
||||
;
|
||||
MSG_OPTIONS_SIZE40_ONE
|
||||
\0Standard
|
||||
;
|
||||
MSG_OPTIONS_SIZE40_TWO
|
||||
\0Fordoblet
|
||||
;
|
||||
MSG_OPTIONS_SIZE40_FOUR
|
||||
\0Firedoblet
|
||||
;
|
||||
MSG_OPTIONS_SIZE80
|
||||
\00080-modus størrelse
|
||||
;
|
||||
MSG_OPTIONS_SIZE80_ONE
|
||||
\0Standard
|
||||
;
|
||||
MSG_OPTIONS_SIZE80_TWO
|
||||
\0Fordoblet
|
||||
;
|
||||
MSG_DEBUG_MENU
|
||||
\0Debug
|
||||
;
|
||||
MSG_DEBUG_MONITOR
|
||||
M\0Monitor
|
||||
;
|
||||
MSG_ABOUTBOX_TITLE
|
||||
Om TIKI-100_emul
|
||||
;
|
||||
MSG_ABOUTBOX_TEXT
|
||||
TIKI-100_emul V1.1.1 - en freeware TIKI 100 Rev. C emulator.\n\
|
||||
Z80 emulering copyright (C) Marat Fayzullin 1994,1995,1996,1997.\n\
|
||||
Resten copyright (C) Asbjørn Djupdal 2000-2001.
|
||||
;
|
||||
MSG_ABOUTBOX_BUTTON
|
||||
Ok
|
|
@ -0,0 +1,149 @@
|
|||
/* ctc.c V1.1.0
|
||||
*
|
||||
* Z80 CTC emulering for TIKI-100_emul
|
||||
* Copyright (C) Asbjørn Djupdal 2000-2001
|
||||
*/
|
||||
|
||||
#include "TIKI-100_emul.h"
|
||||
#include "protos.h"
|
||||
|
||||
/* data for en seriekanal */
|
||||
struct ctcParams {
|
||||
boolean interrupt; /* om interrupt skal genereres */
|
||||
boolean enable; /* om teller av på eller av */
|
||||
int in; /* inngang - ant. sykler mellom hver inn-puls */
|
||||
int out; /* utgang - ant. sykler mellom hver ut-puls */
|
||||
boolean use4MHz; /* om klokke skal brukes i stedet for inngang */
|
||||
int count; /* sykler igjen til neste ut-puls */
|
||||
boolean writeTk; /* skriv tidskonstant neste gang */
|
||||
byte timeConst; /* tidskonstant */
|
||||
int scale; /* skaleringsfaktor */
|
||||
};
|
||||
|
||||
/* protos */
|
||||
|
||||
static void writeCtc (byte value, struct ctcParams *params);
|
||||
static void recalcCtc (void);
|
||||
|
||||
/* variabler */
|
||||
|
||||
extern Z80 cpu;
|
||||
static struct ctcParams params0 = {FALSE, FALSE, 2, FALSE, 0, FALSE, 0, 0};
|
||||
static struct ctcParams params1 = {FALSE, FALSE, 2, FALSE, 0, FALSE, 0, 0};
|
||||
static struct ctcParams params2 = {FALSE, FALSE, 1, FALSE, 0, FALSE, 0, 0};
|
||||
static struct ctcParams params3 = {FALSE, FALSE, 1, FALSE, 0, FALSE, 0, 0};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* skriv til ctc0-register */
|
||||
void writeCtc0 (byte value) {
|
||||
writeCtc (value, ¶ms0);
|
||||
}
|
||||
/* skriv til ctc1-register */
|
||||
void writeCtc1 (byte value) {
|
||||
writeCtc (value, ¶ms1);
|
||||
}
|
||||
/* skriv til ctc2-register */
|
||||
void writeCtc2 (byte value) {
|
||||
writeCtc (value, ¶ms2);
|
||||
}
|
||||
/* skriv til ctc3-register */
|
||||
void writeCtc3 (byte value) {
|
||||
writeCtc (value, ¶ms3);
|
||||
}
|
||||
/* setter data til gitt seriekanal */
|
||||
static void writeCtc (byte value, struct ctcParams *params) {
|
||||
if (params->writeTk) {
|
||||
params->writeTk = FALSE;
|
||||
params->timeConst = value;
|
||||
params->enable = TRUE;
|
||||
} else {
|
||||
params->interrupt = value & 128;
|
||||
if (value & 64) {
|
||||
params->use4MHz = FALSE;
|
||||
params->scale = 1;
|
||||
} else {
|
||||
params->use4MHz = TRUE;
|
||||
params->scale = value & 32 ? 256 : 16;
|
||||
}
|
||||
params->writeTk = value & 4;
|
||||
params->enable = !(value & 2);
|
||||
}
|
||||
recalcCtc();
|
||||
}
|
||||
/* rekalkulerer frekvenser for tellerkanalene */
|
||||
static void recalcCtc (void) {
|
||||
params2.in = params0.out;
|
||||
params3.in = params2.out;
|
||||
|
||||
params0.out = params0.timeConst * params0.scale * (params0.use4MHz ? 1 : params0.in);
|
||||
params1.out = params1.timeConst * params1.scale * (params1.use4MHz ? 1 : params1.in);
|
||||
params2.out = params2.timeConst * params2.scale * (params2.use4MHz ? 1 : params2.in);
|
||||
params3.out = params3.timeConst * params3.scale * (params3.use4MHz ? 1 : params3.in);
|
||||
|
||||
params0.count = params0.out; /* dette er ikke helt riktig, men bra nok */
|
||||
params1.count = params1.out;
|
||||
params2.count = params2.out;
|
||||
params3.count = params3.out;
|
||||
|
||||
recalcBaud();
|
||||
}
|
||||
/* les ctc0-register */
|
||||
byte readCtc0 (void) {
|
||||
return params0.count / params0.in;
|
||||
}
|
||||
/* les ctc1-register */
|
||||
byte readCtc1 (void) {
|
||||
return params1.count / params1.in;
|
||||
}
|
||||
/* les ctc2-register */
|
||||
byte readCtc2 (void) {
|
||||
return params2.count / params2.in;
|
||||
}
|
||||
/* les ctc3-register */
|
||||
byte readCtc3 (void) {
|
||||
return params3.count / params3.in;
|
||||
}
|
||||
/* må kalles regelmessig for å oppdatere tellere og sjekke om interrupt skal genereres */
|
||||
void updateCTC (int cycles) {
|
||||
if (params0.enable) params0.count -= cycles;
|
||||
if (params1.enable) params1.count -= cycles;
|
||||
if (params2.enable) params2.count -= cycles;
|
||||
if (params3.enable) params3.count -= cycles;
|
||||
|
||||
if (params0.count <= 0) {
|
||||
params0.count += params0.out;
|
||||
if (params0.interrupt) {
|
||||
IntZ80 (&cpu, 0x10);
|
||||
}
|
||||
}
|
||||
if (params1.count <= 0) {
|
||||
params1.count += params1.out;
|
||||
if (params1.interrupt) {
|
||||
IntZ80 (&cpu, 0x12);
|
||||
}
|
||||
}
|
||||
if (params2.count <= 0) {
|
||||
params2.count += params2.out;
|
||||
if (params2.interrupt) {
|
||||
IntZ80 (&cpu, 0x14);
|
||||
}
|
||||
}
|
||||
if (params3.count <= 0) {
|
||||
params3.count += params3.out;
|
||||
if (params3.interrupt) {
|
||||
IntZ80 (&cpu, 0x16);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* returnerer antall sykler mellom hver ut puls på gitt ctc-kanal */
|
||||
int getCtc (int c) {
|
||||
switch (c) {
|
||||
case 0: return params0.out;
|
||||
case 1: return params1.out;
|
||||
case 2: return params2.out;
|
||||
case 3: return params3.out;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,339 @@
|
|||
/* disk.c V1.1.1
|
||||
*
|
||||
* FD17xx emulering for TIKI-100_emul
|
||||
* Copyright (C) Asbjørn Djupdal 2000-2001
|
||||
*/
|
||||
|
||||
#include "TIKI-100_emul.h"
|
||||
#include "protos.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
enum diskCommands {
|
||||
NO_COMMAND, READ_SECT, READ_ADDR, WRITE_SECT, READ_TRACK, WRITE_TRACK
|
||||
};
|
||||
|
||||
#define STEPIN 1
|
||||
#define STEPOUT -1
|
||||
|
||||
/* data for en diskettstasjon */
|
||||
struct diskParams {
|
||||
byte *diskImage; /* diskettbilde */
|
||||
boolean active; /* om det er diskett i stasjonen */
|
||||
int tracks; /* antall spor */
|
||||
int sides; /* antall sider - 1 */
|
||||
int sectors; /* sektorer pr spor */
|
||||
int sectSize; /* bytes pr sektor */
|
||||
int realTrack; /* hvilken spor r/w-hode står over */
|
||||
};
|
||||
|
||||
/* protos */
|
||||
|
||||
static void setLights (void);
|
||||
static void setLight (int drive, boolean status);
|
||||
|
||||
/* variabler */
|
||||
|
||||
static struct diskParams params0; /* data for stasjon 0 */
|
||||
static struct diskParams params1; /* data for stasjon 1 */
|
||||
static struct diskParams *params; /* data for aktiv plate */
|
||||
|
||||
static int side = 0; /* gjeldende side (0 eller 1) */
|
||||
static boolean motOn = FALSE; /* om motor er på */
|
||||
|
||||
static byte track = 0; /* sporregister */
|
||||
static byte sector = 1; /* sektorregister */
|
||||
static byte data = 0; /* dataregister */
|
||||
static byte status = 0x20; /* statusregister */
|
||||
|
||||
static byte stepDir = STEPIN; /* verdi som legges til realTrack ved STEP */
|
||||
static byte command = NO_COMMAND; /* kommando som pågår */
|
||||
static long imageOffset = 0; /* offset inn i diskImage, ved r/w */
|
||||
static long endOffset = 0; /* hvor en r/w kommando skal avslutte */
|
||||
static int byteCount = 0; /* antall behandlede bytes ved READ_ADDR, WRITE_TRACK */
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* skriv til kontrollregister */
|
||||
void diskControl (byte value) {
|
||||
/* restore */
|
||||
if ((value & 0xf0) == 0x00) {
|
||||
track = 0;
|
||||
params->realTrack = 0;
|
||||
status = 0x24;
|
||||
}
|
||||
/* søk */
|
||||
else if ((value & 0xf0) == 0x10) {
|
||||
if (data >= params->tracks)
|
||||
status = 0x30 | (params->realTrack == 0 ? 0x04 : 0x00);
|
||||
else {
|
||||
params->realTrack = data;
|
||||
track = params->realTrack;
|
||||
status = 0x20 | (params->realTrack == 0 ? 0x04 : 0x00);
|
||||
}
|
||||
}
|
||||
/* step */
|
||||
else if ((value & 0xe0) == 0x20) {
|
||||
params->realTrack += stepDir;
|
||||
if (params->realTrack >= params->tracks) params->realTrack = params->tracks - 1;
|
||||
if (params->realTrack < 0) params->realTrack = 0;
|
||||
status = 0x20 | (params->realTrack == 0 ? 0x04 : 0x00);
|
||||
if (value & 0x10)
|
||||
track = params->realTrack;
|
||||
}
|
||||
/* step inn */
|
||||
else if ((value & 0xe0) == 0x40) {
|
||||
params->realTrack += STEPIN;
|
||||
if (params->realTrack >= params->tracks) params->realTrack = params->tracks - 1;
|
||||
stepDir = STEPIN;
|
||||
status = 0x20;
|
||||
if (value & 0x10)
|
||||
track = params->realTrack;
|
||||
}
|
||||
/* step ut */
|
||||
else if ((value & 0xe0) == 0x60) {
|
||||
params->realTrack += STEPOUT;
|
||||
if (params->realTrack < 0) params->realTrack = 0;
|
||||
stepDir = STEPOUT;
|
||||
status = 0x20 | (params->realTrack == 0 ? 0x04 : 0x00);
|
||||
if (value & 0x10)
|
||||
track = params->realTrack;
|
||||
}
|
||||
/* les sektor */
|
||||
else if ((value & 0xe0) == 0x80) {
|
||||
if (params->active) {
|
||||
side = (value & 0x02) ? 1 : 0;
|
||||
if ((sector > params->sectors) || (side > params->sides)) {
|
||||
status = 0x10;
|
||||
}
|
||||
else {
|
||||
if (value & 0x10) /* les resten av sektor i spor */
|
||||
endOffset = (((params->realTrack+1) << params->sides) + side) * /* BUG ?? */
|
||||
params->sectors * params->sectSize;
|
||||
else /* les kun 1 sektor */
|
||||
endOffset = ((params->realTrack << params->sides) + side) * params->sectors *
|
||||
params->sectSize + sector * params->sectSize;
|
||||
imageOffset = ((params->realTrack << params->sides) + side) * params->sectors *
|
||||
params->sectSize + (sector-1) * params->sectSize;
|
||||
command = READ_SECT;
|
||||
status = 0x02;
|
||||
}
|
||||
} else {
|
||||
status = 0x80;
|
||||
}
|
||||
}
|
||||
/* skriv sektor */
|
||||
else if ((value & 0xe0) == 0xa0) {
|
||||
if (params->active) {
|
||||
side = (value & 0x02) ? 1 : 0;
|
||||
if ((sector > params->sectors) || (side > params->sides)) {
|
||||
status = 0x10;
|
||||
}
|
||||
else {
|
||||
if (value & 0x10) /* skriv resten av sektor i spor */
|
||||
endOffset = (((params->realTrack+1) << params->sides) + side) * /* BUG ?? */
|
||||
params->sectors * params->sectSize;
|
||||
else /* skriv kun 1 sektor */
|
||||
endOffset = ((params->realTrack << params->sides) + side) * params->sectors *
|
||||
params->sectSize + sector * params->sectSize;
|
||||
imageOffset = ((params->realTrack << params->sides) + side) * params->sectors *
|
||||
params->sectSize + (sector-1) * params->sectSize;
|
||||
command = WRITE_SECT;
|
||||
status = 0x02;
|
||||
}
|
||||
} else {
|
||||
status = 0x80;
|
||||
}
|
||||
}
|
||||
/* les adresse */
|
||||
else if ((value & 0xf8) == 0xc0) {
|
||||
if (params->active) {
|
||||
side = (value & 0x02) ? 1 : 0;
|
||||
if (side > params->sides) {
|
||||
status = 0x10;
|
||||
}
|
||||
else {
|
||||
command = READ_ADDR;
|
||||
byteCount = 0;
|
||||
status = 0x02;
|
||||
}
|
||||
} else {
|
||||
status = 0x80;
|
||||
}
|
||||
}
|
||||
/* les spor -- ikke implementert */
|
||||
else if ((value & 0xf8) == 0xe0) {
|
||||
status = 0x80;
|
||||
}
|
||||
/* skriv spor -- kun delvis implementert */
|
||||
else if ((value & 0xf8) == 0xf0) {
|
||||
if (params->active) {
|
||||
side = (value & 0x02) ? 1 : 0;
|
||||
if (side > params->sides) {
|
||||
status = 0x10;
|
||||
}
|
||||
else {
|
||||
command = WRITE_TRACK;
|
||||
byteCount = 0;
|
||||
status = 0x02;
|
||||
}
|
||||
} else {
|
||||
status = 0x80;
|
||||
}
|
||||
}
|
||||
/* avbryt */
|
||||
else if ((value & 0xf0) == 0xd0) {
|
||||
command = NO_COMMAND;
|
||||
if (status & 0x01) {
|
||||
status = status & 0xfe;
|
||||
} else {
|
||||
status = 0x20 | (params->realTrack == 0 ? 0x04 : 0x00);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* skriv til sporregister */
|
||||
void newTrack (byte value) {
|
||||
track = value;
|
||||
}
|
||||
/* skriv til sektorregister */
|
||||
void newSector (byte value) {
|
||||
sector = value;
|
||||
}
|
||||
/* skriv til dataregister */
|
||||
void newDiskData (byte value) {
|
||||
data = value;
|
||||
switch (command) {
|
||||
case WRITE_SECT:
|
||||
params->diskImage[imageOffset++] = data;
|
||||
if (imageOffset == endOffset) {
|
||||
command = NO_COMMAND;
|
||||
status = 0x00;
|
||||
}
|
||||
break;
|
||||
case WRITE_TRACK:
|
||||
/* kun delvis implementert */
|
||||
if (++byteCount > 6200) {
|
||||
memset (¶ms->diskImage[((params->realTrack << params->sides) + side) * params->sectors *
|
||||
params->sectSize],
|
||||
0xe5, params->sectors * params->sectSize);
|
||||
command = NO_COMMAND;
|
||||
status = 0x00;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* les statusregister */
|
||||
byte diskStatus (void) {
|
||||
return status;
|
||||
}
|
||||
/* les sporregister */
|
||||
byte getTrack (void) {
|
||||
return track;
|
||||
}
|
||||
/* les sektorregister */
|
||||
byte getSector (void) {
|
||||
return sector;
|
||||
}
|
||||
/* les dataregister */
|
||||
byte getDiskData (void) {
|
||||
switch (command) {
|
||||
case READ_SECT:
|
||||
data = params->diskImage[imageOffset++];
|
||||
if (imageOffset == endOffset) {
|
||||
command = NO_COMMAND;
|
||||
status = 0x00;
|
||||
}
|
||||
break;
|
||||
case READ_ADDR:
|
||||
switch (byteCount++) {
|
||||
case 0: data = params->realTrack; break;
|
||||
case 1: data = side; break;
|
||||
case 2: data = 1; break;
|
||||
case 3: switch (params->sectSize) {
|
||||
case 128: data = 0; break;
|
||||
case 256: data = 1; break;
|
||||
case 512: data = 2; break;
|
||||
case 1024: data = 3; break;
|
||||
}
|
||||
break;
|
||||
case 4: data = 0; break;
|
||||
case 5: data = 0;
|
||||
command = NO_COMMAND;
|
||||
status = 0x00;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case READ_TRACK:
|
||||
/* ikke implementert */
|
||||
break;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
/* sett disk 0 aktiv / inaktiv */
|
||||
void disk0 (boolean status) {
|
||||
if (status) {
|
||||
params = ¶ms0;
|
||||
} else {
|
||||
params = ¶ms1;
|
||||
}
|
||||
setLights();
|
||||
}
|
||||
/* sett disk 1 aktiv / inaktiv */
|
||||
void disk1 (boolean status) {
|
||||
if (status) {
|
||||
params = ¶ms1;
|
||||
} else {
|
||||
params = ¶ms0;
|
||||
}
|
||||
setLights();
|
||||
}
|
||||
/* skru motor på / av */
|
||||
void diskMotor (boolean status) {
|
||||
motOn = status;
|
||||
setLights();
|
||||
}
|
||||
/* sett alle disklys */
|
||||
static void setLights (void) {
|
||||
int disk = params == ¶ms0 ? 0 : 1;
|
||||
int otherDisk = disk == 1 ? 0 : 1;
|
||||
|
||||
if (motOn) {
|
||||
setLight (disk, 1);
|
||||
setLight (otherDisk, 0);
|
||||
} else {
|
||||
setLight (0, 0);
|
||||
setLight (1, 0);
|
||||
}
|
||||
}
|
||||
/* sett disk lys til gitt stasjon og status */
|
||||
static void setLight (int drive, boolean status) {
|
||||
static int l[2] = {0, 0};
|
||||
|
||||
if (l[drive] != status) {
|
||||
l[drive] = status;
|
||||
diskLight (drive, status);
|
||||
}
|
||||
}
|
||||
/* ny diskett i stasjon
|
||||
* disk: Hvilken stasjon
|
||||
* diskImage: Peker til diskettbilde-data
|
||||
* resten er diskparametre
|
||||
*/
|
||||
void insertDisk (int drive, byte *dskImg, int trcks, int sds,
|
||||
int sctrs, int sctSize) {
|
||||
struct diskParams *dp = drive ? ¶ms1 : ¶ms0;
|
||||
|
||||
dp->active = TRUE;
|
||||
dp->diskImage = dskImg;
|
||||
dp->tracks = trcks;
|
||||
dp->sides = sds - 1;
|
||||
dp->sectors = sctrs;
|
||||
dp->sectSize = sctSize;
|
||||
}
|
||||
/* fjern diskett fra stasjon */
|
||||
void removeDisk (int drive) {
|
||||
struct diskParams *dp = drive ? ¶ms1 :¶ms0;
|
||||
|
||||
dp->active = FALSE;
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/* keyboard.c V1.1.0
|
||||
*
|
||||
* Tastatur emulering for TIKI-100_emul
|
||||
* Copyright (C) Asbjřrn Djupdal 2000-2001
|
||||
*/
|
||||
|
||||
#include "TIKI-100_emul.h"
|
||||
#include "protos.h"
|
||||
|
||||
/* variabler */
|
||||
|
||||
static byte keyMatrix[12][8] = {
|
||||
{KEY_CTRL, KEY_SHIFT, KEY_BRYT, KEY_CR, KEY_SPACE, KEY_NUMDIV, KEY_SLETT, KEY_NONE},
|
||||
{KEY_GRAFIKK, '1', KEY_ANGRE, 'a', '<', 'z', 'q', KEY_LOCK},
|
||||
{'2', 'w', 's', 'x', '3', 'e', 'd', 'c'},
|
||||
{'4', 'r', 'f', 'v', '5', 't', 'g', 'b'},
|
||||
{'6', 'y', 'h', 'n', '7', 'u', 'j', 'm'},
|
||||
{'8', 'i', 'k', ',', '9', 'o', 'l', '.'},
|
||||
{'0', 'p', (byte)'ř', '-', '+', (byte)'ĺ', (byte)'ć', KEY_HJELP},
|
||||
{'@', '^', '\'', KEY_LEFT, KEY_UTVID, KEY_F1, KEY_F4, KEY_PGUP},
|
||||
{KEY_F2, KEY_F3, KEY_F5, KEY_F6, KEY_UP, KEY_PGDOWN, KEY_TABLEFT, KEY_DOWN},
|
||||
{KEY_NUMPLUS, KEY_NUMMINUS, KEY_NUMMULT, KEY_NUM7, KEY_NUM8, KEY_NUM9, KEY_NUMPERCENT, KEY_NUMEQU},
|
||||
{KEY_NUM4, KEY_NUM5, KEY_NUM6, KEY_TABRIGHT, KEY_NUM1, KEY_NUM0, KEY_NUMDOT, KEY_NONE},
|
||||
{KEY_HOME, KEY_RIGHT, KEY_NUM2, KEY_NUM3, KEY_ENTER, KEY_NONE, KEY_NONE, KEY_NONE},
|
||||
};
|
||||
|
||||
static int column = 0;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* skriv til tastatur-register */
|
||||
void resetKeyboard (void) {
|
||||
column = 0;
|
||||
}
|
||||
/* les tastatur-register */
|
||||
byte readKeyboard (void) {
|
||||
return testKey (keyMatrix[column++]);
|
||||
}
|
||||
|
|
@ -0,0 +1,203 @@
|
|||
/* mem.c V1.1.0
|
||||
*
|
||||
* Tar seg av minne-håndtering for TIKI-100_emul
|
||||
* Copyright (C) Asbjørn Djupdal 2000-2001
|
||||
*/
|
||||
|
||||
#include "TIKI-100_emul.h"
|
||||
#include "protos.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#define ROM_FILENAME "tiki.rom"
|
||||
|
||||
/* variabler */
|
||||
|
||||
byte ram[64 * 1024]; /* hoved minne */
|
||||
extern byte gfxRam[]; /* grafikk minne */
|
||||
byte rom[16 * 1024]; /* monitor eprom, vanligvis bare 8k men støtter 16k */
|
||||
|
||||
static boolean gfxIn; /* TRUE hvis grafikkram er synlig for prosessor */
|
||||
static boolean romIn; /* TRUE hvis rom er synlig for prosessor */
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* må kalles før emulering starter */
|
||||
int initMem() {
|
||||
FILE *fp;
|
||||
|
||||
/* hent ROM */
|
||||
if ((fp = fopen (ROM_FILENAME, "rb"))) {
|
||||
fread (rom, 1, 16 * 1024, fp);
|
||||
fclose (fp);
|
||||
OutZ80 (0x1c, 0x00);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
/* skriv til minnet */
|
||||
void WrZ80 (register word addr, register byte value) {
|
||||
if (gfxIn && !(addr & 0x8000)) {
|
||||
if (gfxRam[addr] != value) {
|
||||
gfxRam[addr] = value;
|
||||
drawByte (addr);
|
||||
}
|
||||
}
|
||||
else if (romIn && !(addr & 0xc000)) {
|
||||
return;
|
||||
}
|
||||
else {
|
||||
ram[addr] = value;
|
||||
}
|
||||
}
|
||||
/* les fra minnet */
|
||||
byte RdZ80 (register word addr) {
|
||||
if (gfxIn && !(addr & 0x8000)) {
|
||||
return gfxRam[addr];
|
||||
}
|
||||
if (romIn && !(addr & 0xc000)) {
|
||||
return rom[addr];
|
||||
}
|
||||
return ram[addr];
|
||||
}
|
||||
/* skriv til i/o-port */
|
||||
void OutZ80 (register word port, register byte value) {
|
||||
static int lock = 0;
|
||||
static int gfx = 0;
|
||||
|
||||
switch (port) {
|
||||
case 0x00: /* tastatur */
|
||||
case 0x01:
|
||||
case 0x02:
|
||||
case 0x03:
|
||||
resetKeyboard();
|
||||
break;
|
||||
case 0x04: /* serie A data */
|
||||
newSerAData (value);
|
||||
break;
|
||||
case 0x05: /* serie B data */
|
||||
newSerBData (value);
|
||||
break;
|
||||
case 0x06: /* serie A styreord */
|
||||
serAControl (value);
|
||||
break;
|
||||
case 0x07: /* serie B styreord */
|
||||
serBControl (value);
|
||||
break;
|
||||
case 0x08: /* parallell A data */
|
||||
newParAData (value);
|
||||
break;
|
||||
case 0x09: /* parallell B data */
|
||||
newParBData (value);
|
||||
break;
|
||||
case 0x0a: /* parallell A styreord */
|
||||
parAControl (value);
|
||||
break;
|
||||
case 0x0b: /* parallell B styreord */
|
||||
parBControl (value);
|
||||
break;
|
||||
case 0x0c: /* grafikk-modus */
|
||||
case 0x0d:
|
||||
case 0x0e:
|
||||
case 0x0f:
|
||||
newMode (value);
|
||||
break;
|
||||
case 0x10: /* disk styreord */
|
||||
diskControl (value);
|
||||
break;
|
||||
case 0x11: /* disk spornummer */
|
||||
newTrack (value);
|
||||
break;
|
||||
case 0x12: /* disk sektorregister */
|
||||
newSector (value);
|
||||
break;
|
||||
case 0x13: /* disk dataregister */
|
||||
newDiskData (value);
|
||||
break;
|
||||
case 0x14: /* farge-register */
|
||||
case 0x15:
|
||||
newColor (value);
|
||||
break;
|
||||
case 0x16: /* lyd-scroll peker */
|
||||
soundReg (value);
|
||||
break;
|
||||
case 0x17: /* lyd-scroll data */
|
||||
soundData (value);
|
||||
break;
|
||||
case 0x18: /* ctc kanal 0 */
|
||||
writeCtc0 (value);
|
||||
break;
|
||||
case 0x19: /* ctc kanal 1 */
|
||||
writeCtc1 (value);
|
||||
break;
|
||||
case 0x1a: /* ctc kanal 2 */
|
||||
writeCtc2 (value);
|
||||
break;
|
||||
case 0x1b: /* ctc kanal 3 */
|
||||
writeCtc3 (value);
|
||||
break;
|
||||
case 0x1c: /* system-register */
|
||||
case 0x1d:
|
||||
case 0x1e:
|
||||
case 0x1f:
|
||||
disk0 (value & 1);
|
||||
disk1 (value & 2);
|
||||
romIn = !(value & 4);
|
||||
gfxIn = value & 8;
|
||||
if (gfx != !(value & 32)) {
|
||||
grafikkLight (!(value & 32));
|
||||
gfx = !(value & 32);
|
||||
}
|
||||
diskMotor (value & 64);
|
||||
if (lock != !(value & 128)) {
|
||||
lockLight (!(value & 128));
|
||||
lock = !(value & 128);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* les fra i/o-port */
|
||||
byte InZ80 (register word port) {
|
||||
switch (port) {
|
||||
case 0x00: /* tastatur */
|
||||
case 0x01:
|
||||
case 0x02:
|
||||
case 0x03:
|
||||
return readKeyboard();
|
||||
case 0x04: /* serie A data */
|
||||
return serAData();
|
||||
case 0x05: /* serie B data */
|
||||
return serBData();
|
||||
case 0x06: /* serie A status */
|
||||
return serAStatus();
|
||||
case 0x07: /* serie B status */
|
||||
return serBStatus();
|
||||
case 0x08: /* parallell A data */
|
||||
return parAData();
|
||||
case 0x09: /* parallell B data */
|
||||
return parBData();
|
||||
case 0x0a: /* parallell A status */
|
||||
return parAStatus();
|
||||
case 0x0b: /* parallell B status */
|
||||
return parBStatus();
|
||||
case 0x10: /* disk status */
|
||||
return diskStatus();
|
||||
case 0x11: /* disk spornummer */
|
||||
return getTrack();
|
||||
case 0x12: /* disk sektorregister */
|
||||
return getSector();
|
||||
case 0x13: /* disk dataregister */
|
||||
return getDiskData();
|
||||
case 0x17: /* lyd-scroll data */
|
||||
return getSoundData();
|
||||
case 0x18: /* ctc kanal 0 */
|
||||
return readCtc0();
|
||||
case 0x19: /* ctc kanal 1 */
|
||||
return readCtc1();
|
||||
case 0x1a: /* ctc kanal 2 */
|
||||
return readCtc2();
|
||||
case 0x1b: /* ctc kanal 3 */
|
||||
return readCtc3();
|
||||
default:
|
||||
return 0xff;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/* parallel.c V1.1.0
|
||||
*
|
||||
* Z80 PIO emulering for TIKI-100_emul
|
||||
* Copyright (C) Asbjørn Djupdal 2001
|
||||
*/
|
||||
|
||||
#include "TIKI-100_emul.h"
|
||||
#include "protos.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* skriv til dataregister A */
|
||||
void newParAData (byte value) {
|
||||
printChar (value);
|
||||
}
|
||||
/* skriv til dataregister B */
|
||||
void newParBData (byte value) {
|
||||
}
|
||||
/* skriv til kontrollregister A */
|
||||
void parAControl (byte value) {
|
||||
}
|
||||
/* skriv til kontrollregister B */
|
||||
void parBControl (byte value) {
|
||||
}
|
||||
/* les dataregister A */
|
||||
byte parAData (void) {
|
||||
return 0;
|
||||
}
|
||||
/* les dataregister B */
|
||||
byte parBData (void) {
|
||||
return 0x10; /* Ack på, busy og no-paper av */
|
||||
}
|
||||
/* les statusregister A */
|
||||
byte parAStatus (void) {
|
||||
return 0;
|
||||
}
|
||||
/* les statusregister B */
|
||||
byte parBStatus (void) {
|
||||
return 0;
|
||||
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,124 @@
|
|||
/* protos.h V1.1.0
|
||||
*
|
||||
* Prototyper for funksjoner som kun skal brukes av den systemuavhengige koden.
|
||||
* Resten av prototypene er i TIKI-100_emul.h
|
||||
* Copyright (C) Asbjørn Djupdal 2000-2001
|
||||
*/
|
||||
|
||||
#ifndef PROTOS_H
|
||||
#define PROTOS_H
|
||||
|
||||
/*****************************************************************************/
|
||||
/* ctc.c */
|
||||
/*****************************************************************************/
|
||||
|
||||
/* skriv til ctc-kontrollregister */
|
||||
void writeCtc0 (byte value);
|
||||
void writeCtc1 (byte value);
|
||||
void writeCtc2 (byte value);
|
||||
void writeCtc3 (byte value);
|
||||
/* les ctc-register */
|
||||
byte readCtc0 (void);
|
||||
byte readCtc1 (void);
|
||||
byte readCtc2 (void);
|
||||
byte readCtc3 (void);
|
||||
/* må kalles regelmessig for å oppdatere tellere og sjekke om interrupt skal genereres */
|
||||
void updateCTC (int cycles);
|
||||
/* returnerer antall sykler mellom hver ut puls på gitt ctc-kanal */
|
||||
int getCtc (int c);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* disk.c */
|
||||
/*****************************************************************************/
|
||||
|
||||
/* skriv til disk-register */
|
||||
void diskControl (byte value);
|
||||
void newTrack (byte value);
|
||||
void newSector (byte value);
|
||||
void newDiskData (byte value);
|
||||
/* les disk-register */
|
||||
byte diskStatus (void);
|
||||
byte getTrack (void);
|
||||
byte getSector (void);
|
||||
byte getDiskData (void);
|
||||
/* sett stasjon aktiv / inaktiv */
|
||||
void disk0 (boolean status);
|
||||
void disk1 (boolean status);
|
||||
/* skru motor på / av */
|
||||
void diskMotor (boolean status);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* keyboard.c */
|
||||
/*****************************************************************************/
|
||||
|
||||
/* skriv til tastatur-register */
|
||||
void resetKeyboard (void);
|
||||
/* les tastatur-register */
|
||||
byte readKeyboard (void);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* mem.c */
|
||||
/*****************************************************************************/
|
||||
|
||||
/* må kalles før emulering starter */
|
||||
int initMem();
|
||||
|
||||
/*****************************************************************************/
|
||||
/* sound.c */
|
||||
/*****************************************************************************/
|
||||
|
||||
/* skriv til lyd-register */
|
||||
void soundReg (byte value);
|
||||
void soundData (byte value);
|
||||
/* les lyd-register */
|
||||
byte getSoundData (void);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* video.c */
|
||||
/*****************************************************************************/
|
||||
|
||||
/* tegn gitt byte i grafikkminne til skjerm */
|
||||
void drawByte (word addr);
|
||||
/* skriv til grafikk-sregister */
|
||||
void newMode (byte mode);
|
||||
void newColor (byte color);
|
||||
/* ny offset (dvs scroll) */
|
||||
void newOffset (byte newOffset);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* serial.c */
|
||||
/*****************************************************************************/
|
||||
|
||||
/* skriv til data-register */
|
||||
void newSerAData (byte value);
|
||||
void newSerBData (byte value);
|
||||
/* skriv til kontroll-register */
|
||||
void serAControl (byte value);
|
||||
void serBControl (byte value);
|
||||
/* les data-register */
|
||||
byte serAData (void);
|
||||
byte serBData (void);
|
||||
/* les status-register */
|
||||
byte serAStatus (void);
|
||||
byte serBStatus (void);
|
||||
/* rekalkuler buad-rate (nye ctc-verdier) */
|
||||
void recalcBaud (void);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* parallel.c */
|
||||
/*****************************************************************************/
|
||||
|
||||
/* skriv til data-register */
|
||||
void newParAData (byte value);
|
||||
void newParBData (byte value);
|
||||
/* skriv til kontroll-register */
|
||||
void parAControl (byte value);
|
||||
void parBControl (byte value);
|
||||
/* les data-register */
|
||||
byte parAData (void);
|
||||
byte parBData (void);
|
||||
/* les status-register */
|
||||
byte parAStatus (void);
|
||||
byte parBStatus (void);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,206 @@
|
|||
/* serial.c V1.1.0
|
||||
*
|
||||
* Z80 DART emulering for TIKI-100_emul
|
||||
* Copyright (C) Asbjørn Djupdal 2001
|
||||
*/
|
||||
|
||||
#include "TIKI-100_emul.h"
|
||||
#include "protos.h"
|
||||
|
||||
enum rxiType {
|
||||
RXI_NONE, RXI_FIRST, RXI_ALL_PAR_CHANGE_VEC, RXI_ALL_PAR_DONT_CHANGE_VEC
|
||||
};
|
||||
|
||||
/* protos */
|
||||
|
||||
static void serControl (byte value, struct serParams *sParams);
|
||||
static byte serStatus (struct serParams *sParams);
|
||||
|
||||
/* variabler */
|
||||
|
||||
extern Z80 cpu; /* må ha tilgang til cpu for å gjøre interrupt */
|
||||
|
||||
static boolean st28b = FALSE; /* jumper i TIKI-100 */
|
||||
|
||||
/* parametre for de to seriekanalene */
|
||||
static struct serParams serAParams;
|
||||
static struct serParams serBParams;
|
||||
|
||||
static byte intVector = 0; /* interrupt vektor, delt mellom kanalene */
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* skriv til dataregister A */
|
||||
void newSerAData (byte value) {
|
||||
if (serAParams.txe) {
|
||||
sendChar (1, value);
|
||||
}
|
||||
}
|
||||
/* skriv til dataregister B */
|
||||
void newSerBData (byte value) {
|
||||
if (serBParams.txe) {
|
||||
sendChar (0, value);
|
||||
}
|
||||
}
|
||||
/* skriv til kontrollregister A */
|
||||
void serAControl (byte value) {
|
||||
serControl (value, &serAParams);
|
||||
}
|
||||
/* skriv til kontrollregister B */
|
||||
void serBControl (byte value) {
|
||||
serControl (value, &serBParams);
|
||||
}
|
||||
static void serControl (byte value, struct serParams *sParams) {
|
||||
switch (sParams->regPtr) {
|
||||
case 0: /* Command Register */
|
||||
sParams->regPtr = value & 7;
|
||||
/* nullstill status interrupt */
|
||||
/* nullstill hele kanalen */
|
||||
if ((value & 0x38) == 0x18) {
|
||||
sParams->newChar = FALSE;
|
||||
}
|
||||
/* Sett interrupt når neste tegn mottas */
|
||||
if ((value & 0x38) == 0x20) {
|
||||
sParams->newChar = FALSE;
|
||||
}
|
||||
/* nullstill senderinterrupt */
|
||||
/* nullstill feilmelding */
|
||||
/* retur fra interrupt */
|
||||
break;
|
||||
case 1: /* Transmit/Receive Interrupt */
|
||||
sParams->regPtr = 0;
|
||||
sParams->exi = value & 0x01;
|
||||
sParams->txi = value & 0x02;
|
||||
sParams->sav = value & 0x04;
|
||||
switch (value & 0x18) {
|
||||
case 0x00: sParams->rxi = RXI_NONE; break;
|
||||
case 0x08: sParams->rxi = RXI_FIRST; break;
|
||||
case 0x10: sParams->rxi = RXI_ALL_PAR_CHANGE_VEC; break;
|
||||
case 0x18: sParams->rxi = RXI_ALL_PAR_DONT_CHANGE_VEC; break;
|
||||
}
|
||||
break;
|
||||
case 2: /* Interrupt Vector */
|
||||
sParams->regPtr = 0;
|
||||
intVector = value;
|
||||
break;
|
||||
case 3: /* Receive Parameters */
|
||||
sParams->regPtr = 0;
|
||||
sParams->rxe = value & 0x01;
|
||||
sParams->ae = value & 0x20;
|
||||
switch (value & 0xc0) {
|
||||
case 0x00: sParams->receiveBits = 5; break;
|
||||
case 0x40: sParams->receiveBits = 7; break;
|
||||
case 0x80: sParams->receiveBits = 6; break;
|
||||
case 0xc0: sParams->receiveBits = 8; break;
|
||||
}
|
||||
break;
|
||||
case 4: /* Transmit/Receive Misc Parameters */
|
||||
sParams->regPtr = 0;
|
||||
if (!(value & 0x01)) {
|
||||
sParams->parity = PAR_NONE;
|
||||
} else {
|
||||
sParams->parity = value & 0x02 ? PAR_EVEN : PAR_ODD;
|
||||
}
|
||||
switch (value & 0x0c) {
|
||||
case 0x00: /* ugyldig */
|
||||
case 0x04: sParams->stopBits = ONE_SB; break;
|
||||
case 0x08: sParams->stopBits = ONE_PT_FIVE_SB; break;
|
||||
case 0x0c: sParams->stopBits = TWO_SB; break;
|
||||
}
|
||||
switch (value & 0xc0) {
|
||||
case 0x00: sParams->clkDiv = 1; break;
|
||||
case 0x40: sParams->clkDiv = 16; break;
|
||||
case 0x80: sParams->clkDiv = 32; break;
|
||||
case 0xc0: sParams->clkDiv = 64; break;
|
||||
}
|
||||
break;
|
||||
case 5: /* Transmit Parameters */
|
||||
sParams->regPtr = 0;
|
||||
/* rts */
|
||||
sParams->txe = value & 0x08;
|
||||
/* break */
|
||||
switch (value & 0xc0) {
|
||||
case 0x00: sParams->sendBits = 5; break;
|
||||
case 0x40: sParams->sendBits = 7; break;
|
||||
case 0x80: sParams->sendBits = 6; break;
|
||||
case 0xc0: sParams->sendBits = 8; break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
recalcBaud();
|
||||
}
|
||||
/* rekalkuler baud-rate (nye ctc-verdier) */
|
||||
void recalcBaud (void) {
|
||||
int ctc0 = getCtc (0);
|
||||
int ctc1 = getCtc (1);
|
||||
int ctc2 = getCtc (2);
|
||||
|
||||
if ((ctc0 != 0) && ((st28b ? ctc2 : ctc1) != 0) && (serAParams.clkDiv != 0) && (serBParams.clkDiv != 0)) {
|
||||
serAParams.baud = 4000000/ctc0/serAParams.clkDiv;
|
||||
serBParams.baud = 4000000/(st28b ? ctc2 : ctc1)/serBParams.clkDiv;
|
||||
setParams (&serBParams, &serAParams);
|
||||
}
|
||||
}
|
||||
/* les dataregister A */
|
||||
byte serAData (void) {
|
||||
if (serAParams.rxa) {
|
||||
serAParams.rxa = FALSE;
|
||||
return getChar (1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/* les dataregister B */
|
||||
byte serBData (void) {
|
||||
if (serBParams.rxa) {
|
||||
serBParams.rxa = FALSE;
|
||||
return getChar (0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/* les statusregister A */
|
||||
byte serAStatus (void) {
|
||||
return serStatus (&serAParams);
|
||||
}
|
||||
/* les statusregister B */
|
||||
byte serBStatus (void) {
|
||||
return serStatus (&serBParams);
|
||||
}
|
||||
static byte serStatus (struct serParams *sParams) {
|
||||
byte returnValue = 0;
|
||||
|
||||
switch (sParams->regPtr) {
|
||||
case 0: returnValue = 0x34 | (sParams->rxa ? 1 : 0);
|
||||
break;
|
||||
case 1: returnValue = 0x01;
|
||||
break;
|
||||
case 2: returnValue = intVector;
|
||||
break;
|
||||
}
|
||||
sParams->regPtr = 0;
|
||||
return returnValue;
|
||||
}
|
||||
/* sett jumper ST28b */
|
||||
void setST28b (boolean status) {
|
||||
st28b = status;
|
||||
recalcBaud();
|
||||
}
|
||||
/* nytt tegn tilgjengelig */
|
||||
void charAvailable (int port) {
|
||||
struct serParams *sParams = port ? &serAParams : &serBParams;
|
||||
int channel = port ? 0 : 1;
|
||||
|
||||
sParams->rxa = TRUE;
|
||||
sParams->newChar = TRUE;
|
||||
|
||||
if (sParams->sav) {
|
||||
intVector = (intVector & 0xf1) | (channel ? 0 : 8) | 4;
|
||||
}
|
||||
switch (sParams->rxi) {
|
||||
case RXI_FIRST: if (!(sParams->newChar)) IntZ80 (&cpu, intVector);
|
||||
break;
|
||||
case RXI_ALL_PAR_CHANGE_VEC:
|
||||
case RXI_ALL_PAR_DONT_CHANGE_VEC:
|
||||
IntZ80 (&cpu, intVector);
|
||||
break;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/* sound.c V1.1.0
|
||||
*
|
||||
* AY-3-8912 emulering for TIKI-100_emul
|
||||
* Copyright (C) Asbjørn Djupdal 2000-2001
|
||||
*/
|
||||
|
||||
#include "TIKI-100_emul.h"
|
||||
#include "protos.h"
|
||||
|
||||
/* variabler */
|
||||
|
||||
static byte reg = 0;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* skriv til kontrollregister */
|
||||
void soundReg (byte value) {
|
||||
reg = value;
|
||||
}
|
||||
/* skriv til dataregister */
|
||||
void soundData (byte value) {
|
||||
switch (reg) {
|
||||
case 14: newOffset (value); break;
|
||||
}
|
||||
}
|
||||
/* les dataregister */
|
||||
byte getSoundData (void) {
|
||||
return 0xff;
|
||||
}
|
||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,123 @@
|
|||
/* video.c V1.1.0
|
||||
*
|
||||
* Grafikk emulering for TIKI-100_emul
|
||||
* Copyright (C) Asbjørn Djupdal 2000-2001
|
||||
*/
|
||||
|
||||
#include "TIKI-100_emul.h"
|
||||
#include "protos.h"
|
||||
#include <string.h>
|
||||
|
||||
/* variabler */
|
||||
|
||||
/* konverteringstabeller */
|
||||
static const byte redGreenTable[8] = {0, 36, 73, 109, 146, 182, 219, 255};
|
||||
static const byte blueTable[4] = {0, 85, 170, 255};
|
||||
|
||||
byte gfxRam[32 * 1024];
|
||||
|
||||
static byte red = 0, green = 0, blue = 0; /* farge-register */
|
||||
static int res = MEDRES; /* gjeldende oppløsning */
|
||||
static boolean changeColor = FALSE; /* forandre farge hver gang fargeregister forandres */
|
||||
static int colornumber = 0;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Tegn alle pixler representert i gitt byte */
|
||||
void drawByte (word addr) {
|
||||
int x;
|
||||
byte y = addr >> 7;
|
||||
|
||||
switch (res) {
|
||||
case HIGHRES: x = (addr & 0x7f) << 3;
|
||||
plotPixel (x, y, gfxRam[addr] & 0x01);
|
||||
plotPixel (++x, y, (gfxRam[addr] & 0x02) >> 1);
|
||||
plotPixel (++x, y, (gfxRam[addr] & 0x04) >> 2);
|
||||
plotPixel (++x, y, (gfxRam[addr] & 0x08) >> 3);
|
||||
plotPixel (++x, y, (gfxRam[addr] & 0x10) >> 4);
|
||||
plotPixel (++x, y, (gfxRam[addr] & 0x20) >> 5);
|
||||
plotPixel (++x, y, (gfxRam[addr] & 0x40) >> 6);
|
||||
plotPixel (++x, y, (gfxRam[addr] & 0x80) >> 7);
|
||||
break;
|
||||
case MEDRES: x = (addr & 0x7f) << 2;
|
||||
plotPixel (x, y, gfxRam[addr] & 0x03);
|
||||
plotPixel (++x, y, (gfxRam[addr] & 0x0c) >> 2);
|
||||
plotPixel (++x, y, (gfxRam[addr] & 0x30) >> 4);
|
||||
plotPixel (++x, y, (gfxRam[addr] & 0xc0) >> 6);
|
||||
break;
|
||||
case LOWRES: x = (addr & 0x7f) << 1;
|
||||
plotPixel (x, y, gfxRam[addr] & 0x0f);
|
||||
plotPixel (++x, y, (gfxRam[addr] & 0xf0) >> 4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Ny verdi til modusregister */
|
||||
void newMode (byte mode) {
|
||||
colornumber = mode & 0x0f;
|
||||
if (mode & 128) { /* sett farge */
|
||||
changeColor = TRUE;
|
||||
changePalette (colornumber, red, green, blue);
|
||||
} else {
|
||||
changeColor = FALSE;
|
||||
}
|
||||
if (res != (mode & 48)) {
|
||||
res = (mode & 48); /* ny oppløsning */
|
||||
changeRes (res);
|
||||
{ /* oppdater skjerm */
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 32768; i++) {
|
||||
if (gfxRam[i]) drawByte (i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Ny verdi i fargeregister */
|
||||
void newColor (byte color) {
|
||||
red = redGreenTable[(~color & 224) >> 5];
|
||||
green = redGreenTable[(~color & 28) >> 2];
|
||||
blue = blueTable[~color & 3];
|
||||
if (changeColor) {
|
||||
changePalette (colornumber, red, green, blue);
|
||||
}
|
||||
}
|
||||
/* Ny verdi i scrollregister fra AY-3-8912 */
|
||||
void newOffset (byte newOffset) {
|
||||
static byte vOffset = 0; /* scrollregister */
|
||||
|
||||
/* ignorer hvis ikke noen forskjell */
|
||||
if (newOffset != vOffset) {
|
||||
int distance = (signed char)(newOffset - vOffset);
|
||||
byte buffer[128 * 128]; /* skroller aldri mer enn halve skjermen */
|
||||
word addr;
|
||||
|
||||
/* flytt på skjerm */
|
||||
scrollScreen (distance);
|
||||
|
||||
if (distance > 0) {
|
||||
/* flytt i ram */
|
||||
memmove (buffer, gfxRam, distance * 128); /* øverst -> buffer */
|
||||
memmove (gfxRam, gfxRam + distance * 128, (256 - distance) * 128); /* nederst -> øverst */
|
||||
memmove (gfxRam + (256 - distance) * 128, buffer, distance * 128); /* buffer -> nederst */
|
||||
|
||||
/* oppdater nederste del av skjerm */
|
||||
for (addr = 32768 - (distance * 128); addr < 32768; addr++) {
|
||||
if (gfxRam[addr]) drawByte (addr);
|
||||
}
|
||||
} else {
|
||||
/* flytt i ram */
|
||||
memmove (buffer, gfxRam + (byte)distance * 128, -distance * 128); /* nederst -> buffer */
|
||||
memmove (gfxRam + (-distance * 128), gfxRam, (byte)distance * 128); /* øverst -> nederst */
|
||||
memmove (gfxRam, buffer, -distance * 128); /* buffer -> øverst */
|
||||
|
||||
/* oppdater øverste del av skjerm */
|
||||
for (addr = 0; addr < -distance * 128; addr++) {
|
||||
if (gfxRam[addr]) drawByte (addr);
|
||||
}
|
||||
}
|
||||
|
||||
/* oppdater scrollregister */
|
||||
vOffset = newOffset;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,792 @@
|
|||
/* win32.c V1.1.1
|
||||
*
|
||||
* Win32 systemspesifikk kode for TIKI-100_emul
|
||||
* Copyright (C) Asbjørn Djupdal 2000-2001
|
||||
*/
|
||||
|
||||
#include "TIKI-100_emul.h"
|
||||
#include "win32_res.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <windows.h>
|
||||
#include <commctrl.h>
|
||||
|
||||
#define ERROR_CAPTION "TIKI-100_emul feilmelding"
|
||||
#define STATUSBAR_HEIGHT 19
|
||||
|
||||
/* protos */
|
||||
int WINAPI WinMain (HINSTANCE hThisInst, HINSTANCE hPrevInst, LPSTR lpszArgs, int nWinMode);
|
||||
static LRESULT CALLBACK WindowFunc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
static BOOL CALLBACK DialogFunc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
static void update (int x, int y, int w, int h);
|
||||
static void draw3dBox (int x, int y, int w, int h);
|
||||
static void getDiskImage (int drive);
|
||||
static void saveDiskImage (int drive);
|
||||
static void setParam (HANDLE portHandle, struct serParams *params);
|
||||
|
||||
/* variabler */
|
||||
|
||||
static byte keyTable[256] = {
|
||||
KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
|
||||
KEY_SLETT, KEY_BRYT, KEY_NONE, KEY_NONE, KEY_NONE, KEY_CR, KEY_NONE, KEY_NONE,
|
||||
KEY_SHIFT, KEY_CTRL, KEY_NONE, KEY_NONE, KEY_LOCK, KEY_NONE, KEY_NONE, KEY_NONE,
|
||||
KEY_NONE, KEY_NONE, KEY_NONE, KEY_ANGRE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
|
||||
KEY_SPACE, KEY_PGUP, KEY_PGDOWN, KEY_TABRIGHT, KEY_HOME, KEY_LEFT, KEY_UP, KEY_RIGHT,
|
||||
KEY_DOWN, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_UTVID, KEY_TABLEFT, KEY_NONE,
|
||||
'0', '1', '2', '3', '4', '5', '6', '7',
|
||||
'8', '9', KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
|
||||
KEY_NONE, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
|
||||
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
|
||||
'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
|
||||
'x', 'y', 'z', KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
|
||||
KEY_NUM0, KEY_NUM1, KEY_NUM2, KEY_NUM3, KEY_NUM4, KEY_NUM5, KEY_NUM6, KEY_NUM7,
|
||||
KEY_NUM8, KEY_NUM9, KEY_NUMMULT, KEY_NUMPLUS, KEY_NONE, KEY_NUMMINUS, KEY_NUMDOT, KEY_NUMDIV,
|
||||
KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_NONE, KEY_HJELP,
|
||||
KEY_ENTER, KEY_NONE, KEY_NUMPERCENT, KEY_NUMEQU, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
|
||||
KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
|
||||
KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
|
||||
KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
|
||||
KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
|
||||
KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
|
||||
KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
|
||||
KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
|
||||
KEY_NONE, KEY_NONE, '^', '+', ',', '-', '.', '\'',
|
||||
'ø', KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
|
||||
KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
|
||||
KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
|
||||
KEY_NONE, KEY_NONE, KEY_NONE, '@', KEY_GRAFIKK, 'å', 'æ', KEY_NONE,
|
||||
KEY_NONE, KEY_NONE, '<', KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
|
||||
KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
|
||||
KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
|
||||
KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE
|
||||
};
|
||||
|
||||
static HWND hwnd;
|
||||
static HINSTANCE appInst;
|
||||
static HDC memdc;
|
||||
static HBITMAP hbit;
|
||||
static byte screen[1024*256];
|
||||
static COLORREF colors[16];
|
||||
static char defaultDir[256];
|
||||
static byte pressedKeys[256];
|
||||
static byte *dsk[2];
|
||||
static DWORD fileSize[2];
|
||||
static int resolution;
|
||||
static boolean slowDown = TRUE;
|
||||
static boolean scanlines = FALSE;
|
||||
static boolean st28b = FALSE;
|
||||
static int width, height;
|
||||
static int size40x = 1, size80x = 1;
|
||||
static unsigned int xmin = (unsigned)~0;
|
||||
static unsigned int ymin = (unsigned)~0;
|
||||
static unsigned int xmax = 0;
|
||||
static unsigned int ymax = 0;
|
||||
static boolean updateWindow = FALSE;
|
||||
static boolean lock = FALSE;
|
||||
static boolean grafikk = FALSE;
|
||||
static boolean disk[2] = {FALSE, FALSE};
|
||||
static HANDLE port1;
|
||||
static HANDLE port2;
|
||||
static HANDLE port3;
|
||||
static char port1Name[256] = "COM1";
|
||||
static char port2Name[256] = "COM2";
|
||||
static char port3Name[256] = "LPT1";
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int WINAPI WinMain (HINSTANCE hThisInst, HINSTANCE hPrevInst, LPSTR lpszArgs, int nWinMode) {
|
||||
char szWinName[] = "TIKIWin";
|
||||
MSG msg;
|
||||
WNDCLASSEX wcl;
|
||||
|
||||
appInst = hThisInst;
|
||||
|
||||
InitCommonControls();
|
||||
|
||||
/* lag og registrer vindusklasse */
|
||||
wcl.cbSize = sizeof (WNDCLASSEX);
|
||||
wcl.hInstance = hThisInst;
|
||||
wcl.lpszClassName = szWinName;
|
||||
wcl.lpfnWndProc = WindowFunc;
|
||||
wcl.style = 0;
|
||||
wcl.hIcon = LoadIcon (appInst, "icon");
|
||||
wcl.hIconSm = NULL;
|
||||
wcl.hCursor = LoadCursor (NULL, IDC_ARROW);
|
||||
wcl.lpszMenuName = "menu";
|
||||
wcl.cbClsExtra = 0;
|
||||
wcl.cbWndExtra = 0;
|
||||
wcl.hbrBackground = (HBRUSH)GetStockObject (BLACK_BRUSH);
|
||||
if (!RegisterClassEx (&wcl)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* lag vindu */
|
||||
hwnd = CreateWindow (szWinName, "TIKI-100_emul", WS_OVERLAPPEDWINDOW & ~WS_SIZEBOX & ~WS_MAXIMIZEBOX, CW_USEDEFAULT,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, HWND_DESKTOP, NULL, hThisInst, NULL);
|
||||
changeRes (MEDRES);
|
||||
ShowWindow (hwnd, nWinMode);
|
||||
|
||||
/* initialiser arrays */
|
||||
memset (pressedKeys, 1, 256);
|
||||
memset (screen, 0, 1024*256);
|
||||
|
||||
/* finn katalog */
|
||||
GetCurrentDirectory (256, defaultDir);
|
||||
|
||||
/* kjør emulator */
|
||||
if (!runEmul()) {
|
||||
MessageBox (hwnd, "Finner ikke ROM-fil!", ERROR_CAPTION, MB_OK);
|
||||
}
|
||||
|
||||
/* avslutt */
|
||||
free (dsk[0]);
|
||||
free (dsk[1]);
|
||||
if (port1) CloseHandle (port1);
|
||||
if (port2) CloseHandle (port2);
|
||||
if (port3) CloseHandle (port3);
|
||||
|
||||
return msg.wParam;
|
||||
}
|
||||
|
||||
static LRESULT CALLBACK WindowFunc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
|
||||
switch (msg) {
|
||||
case WM_CREATE:
|
||||
{ /* sett opp memdc */
|
||||
HDC hdc = GetDC (hwnd);
|
||||
memdc = CreateCompatibleDC (hdc);
|
||||
hbit = CreateCompatibleBitmap (hdc, 1024, 1024 + STATUSBAR_HEIGHT);
|
||||
SelectObject (memdc, hbit);
|
||||
SelectObject (memdc, GetStockObject (BLACK_BRUSH));
|
||||
PatBlt (memdc, 0, 0, 1024, 1024 + STATUSBAR_HEIGHT, PATCOPY);
|
||||
ReleaseDC (hwnd, hdc);
|
||||
}
|
||||
break;
|
||||
case WM_PAINT:
|
||||
{ /* kopier fra memdc til hdc */
|
||||
PAINTSTRUCT ps;
|
||||
HDC hdc = BeginPaint (hwnd, &ps);
|
||||
BitBlt (hdc, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right - ps.rcPaint.left,
|
||||
ps.rcPaint.bottom - ps.rcPaint.top, memdc, ps.rcPaint.left, ps.rcPaint.top, SRCCOPY);
|
||||
EndPaint (hwnd, &ps);
|
||||
}
|
||||
break;
|
||||
case WM_SIZE:
|
||||
/* statusbar */
|
||||
SelectObject (memdc, GetSysColorBrush (COLOR_3DFACE));
|
||||
PatBlt (memdc, 0, height, width, STATUSBAR_HEIGHT, PATCOPY);
|
||||
|
||||
/* tegn småbokser */
|
||||
draw3dBox (20, height + 5, 9, 9);
|
||||
draw3dBox (40, height + 5, 9, 9);
|
||||
draw3dBox (60, height + 5, 9, 9);
|
||||
draw3dBox (80, height + 5, 9, 9);
|
||||
|
||||
/* oppdater diodelys */
|
||||
lockLight (lock);
|
||||
grafikkLight (grafikk);
|
||||
diskLight (0, disk[0]);
|
||||
diskLight (1, disk[1]);
|
||||
break;
|
||||
case WM_DESTROY:
|
||||
PostQuitMessage (0);
|
||||
break;
|
||||
case WM_KEYDOWN:
|
||||
pressedKeys[keyTable[(byte)wParam]] = 0;
|
||||
break;
|
||||
case WM_KEYUP:
|
||||
pressedKeys[keyTable[(byte)wParam]] = 1;
|
||||
break;
|
||||
case WM_COMMAND:
|
||||
switch (LOWORD (wParam)) {
|
||||
case IDM_RESET:
|
||||
resetEmul();
|
||||
break;
|
||||
case IDM_INNSTILLINGER:
|
||||
DialogBox (appInst, "dialog", hwnd, (DLGPROC)DialogFunc);
|
||||
break;
|
||||
case IDM_OM:
|
||||
MessageBox (hwnd,
|
||||
"TIKI-100_emul V1.1.1 - en freeware TIKI 100 Rev. C emulator.\n"
|
||||
"Z80 emulering copyright (C) Marat Fayzullin 1994,1995,1996,1997.\n"
|
||||
"Resten copyright (C) Asbjørn Djupdal 2000-2001.",
|
||||
"Om TIKI-100_emul",
|
||||
MB_OK);
|
||||
break;
|
||||
case IDM_AVSLUTT:
|
||||
PostQuitMessage (0);
|
||||
break;
|
||||
case IDM_HENT_A:
|
||||
getDiskImage (0);
|
||||
break;
|
||||
case IDM_HENT_B:
|
||||
getDiskImage (1);
|
||||
break;
|
||||
case IDM_LAGRE_A:
|
||||
saveDiskImage (0);
|
||||
break;
|
||||
case IDM_LAGRE_B:
|
||||
saveDiskImage (1);
|
||||
break;
|
||||
case IDM_FJERN_A:
|
||||
EnableMenuItem (GetSubMenu (GetMenu (hwnd), 1), IDM_LAGRE_A, MF_BYCOMMAND | MF_GRAYED);
|
||||
removeDisk (0);
|
||||
break;
|
||||
case IDM_FJERN_B:
|
||||
EnableMenuItem (GetSubMenu (GetMenu (hwnd), 1), IDM_LAGRE_B, MF_BYCOMMAND | MF_GRAYED);
|
||||
removeDisk (1);
|
||||
break;
|
||||
#ifdef DEBUG
|
||||
case IDM_MONITOR:
|
||||
trace();
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
default:
|
||||
return DefWindowProc (hwnd, msg, wParam, lParam);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/* tegner en 3d-boks */
|
||||
static void draw3dBox (int x, int y, int w, int h) {
|
||||
HGDIOBJ obj;
|
||||
HPEN pen1 = CreatePen (PS_SOLID, 0, GetSysColor (COLOR_3DDKSHADOW));
|
||||
HPEN pen2 = CreatePen (PS_SOLID, 0, GetSysColor (COLOR_3DHILIGHT));
|
||||
|
||||
MoveToEx (memdc, x, y + h - 1, NULL);
|
||||
obj = SelectObject (memdc, pen1);
|
||||
LineTo (memdc, x, y);
|
||||
LineTo (memdc, x + w - 1, y);
|
||||
SelectObject (memdc, pen2);
|
||||
LineTo (memdc, x + w - 1, y + h - 1);
|
||||
LineTo (memdc, x, y + h - 1);
|
||||
|
||||
SelectObject (memdc, obj);
|
||||
DeleteObject (pen2);
|
||||
DeleteObject (pen1);
|
||||
}
|
||||
static BOOL CALLBACK DialogFunc (HWND hdwnd, UINT message, WPARAM wParam, LPARAM lParam) {
|
||||
static HWND ud40Wnd, ud80Wnd;
|
||||
|
||||
switch (message) {
|
||||
case WM_INITDIALOG:
|
||||
/* oppdater alle felter */
|
||||
ud40Wnd = CreateUpDownControl (WS_CHILD | WS_BORDER | WS_VISIBLE | UDS_SETBUDDYINT | UDS_ALIGNRIGHT,
|
||||
48, 52, 11, 14, hdwnd, IDD_40SPIN, appInst, GetDlgItem (hdwnd, IDD_40EDIT),
|
||||
4, 1, size40x);
|
||||
ud80Wnd = CreateUpDownControl (WS_CHILD | WS_BORDER | WS_VISIBLE | UDS_SETBUDDYINT | UDS_ALIGNRIGHT,
|
||||
48, 71, 11, 14, hdwnd, IDD_80SPIN, appInst, GetDlgItem (hdwnd, IDD_80EDIT),
|
||||
2, 1, size80x);
|
||||
if (slowDown) SendDlgItemMessage (hdwnd, IDD_HASTIGHET, BM_SETCHECK, 1, 0);
|
||||
if (scanlines) SendDlgItemMessage (hdwnd, IDD_BEVARFORHOLD, BM_SETCHECK, 1, 0);
|
||||
if (st28b) SendDlgItemMessage (hdwnd, IDD_ST28B, BM_SETCHECK, 1, 0);
|
||||
if (port1) SendDlgItemMessage (hdwnd, IDD_P1, BM_SETCHECK, 1, 0);
|
||||
if (port2) SendDlgItemMessage (hdwnd, IDD_P2, BM_SETCHECK, 1, 0);
|
||||
if (port3) SendDlgItemMessage (hdwnd, IDD_P3, BM_SETCHECK, 1, 0);
|
||||
SendDlgItemMessage (hdwnd, IDD_P1EDIT, WM_SETTEXT, 0, (LPARAM)port1Name);
|
||||
SendDlgItemMessage (hdwnd, IDD_P2EDIT, WM_SETTEXT, 0, (LPARAM)port2Name);
|
||||
SendDlgItemMessage (hdwnd, IDD_P3EDIT, WM_SETTEXT, 0, (LPARAM)port3Name);
|
||||
break;
|
||||
case WM_COMMAND:
|
||||
switch (LOWORD(wParam)) {
|
||||
case IDD_OK: {
|
||||
int s40x, s80x;
|
||||
boolean sl;
|
||||
boolean st;
|
||||
char p1[256];
|
||||
char p2[256];
|
||||
char p3[256];
|
||||
|
||||
/* begrense hastighet */
|
||||
slowDown = SendDlgItemMessage (hdwnd, IDD_HASTIGHET, BM_GETCHECK, 0, 0);
|
||||
|
||||
/* forandre vindus-størrelse */
|
||||
s40x = SendMessage (ud40Wnd, UDM_GETPOS, 0, 0);
|
||||
s80x = SendMessage (ud80Wnd, UDM_GETPOS, 0, 0);
|
||||
sl = SendDlgItemMessage (hdwnd, IDD_BEVARFORHOLD, BM_GETCHECK, 0, 0);
|
||||
if (s40x != size40x || s80x != size80x || sl != scanlines) {
|
||||
size40x = s40x; size80x = s80x; scanlines = sl;
|
||||
changeRes (resolution);
|
||||
resetEmul();
|
||||
}
|
||||
|
||||
/* sett ST 28 b */
|
||||
st = SendDlgItemMessage (hdwnd, IDD_ST28B, BM_GETCHECK, 0, 0);
|
||||
if (st != st28b) {
|
||||
st28b = st;
|
||||
setST28b (st28b);
|
||||
}
|
||||
|
||||
/* skaff nye portnavn */
|
||||
SendDlgItemMessage (hdwnd, IDD_P1EDIT, WM_GETTEXT, 256, (LPARAM)p1);
|
||||
SendDlgItemMessage (hdwnd, IDD_P2EDIT, WM_GETTEXT, 256, (LPARAM)p2);
|
||||
SendDlgItemMessage (hdwnd, IDD_P3EDIT, WM_GETTEXT, 256, (LPARAM)p3);
|
||||
|
||||
/* åpne/lukke porter */
|
||||
if (SendDlgItemMessage (hdwnd, IDD_P1, BM_GETCHECK, 0, 0)) {
|
||||
/* port 1 */
|
||||
if (!port1 || strcmp (p1, port1Name)) {
|
||||
if (port1) CloseHandle (port1);
|
||||
SetCurrentDirectory (defaultDir);
|
||||
if ((port1 = CreateFile(p1, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, 0, NULL)) ==
|
||||
INVALID_HANDLE_VALUE) {
|
||||
MessageBox (hwnd, "Angitt navn på P1 ikke tilgjengelig!", ERROR_CAPTION, MB_OK);
|
||||
port1 = 0;
|
||||
}
|
||||
}
|
||||
} else if (port1) {
|
||||
CloseHandle (port1);
|
||||
port1 = 0;
|
||||
}
|
||||
if (SendDlgItemMessage (hdwnd, IDD_P2, BM_GETCHECK, 0, 0)) {
|
||||
/* port 2 */
|
||||
if (!port2 || strcmp (p2, port2Name)) {
|
||||
if (port2) CloseHandle (port2);
|
||||
SetCurrentDirectory (defaultDir);
|
||||
if ((port2 = CreateFile(p2, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, 0, NULL)) ==
|
||||
INVALID_HANDLE_VALUE) {
|
||||
MessageBox (hwnd, "Angitt navn på P2 ikke tilgjengelig!", ERROR_CAPTION, MB_OK);
|
||||
port1 = 0;
|
||||
}
|
||||
}
|
||||
} else if (port2) {
|
||||
CloseHandle (port2);
|
||||
port2 = 0;
|
||||
}
|
||||
if (SendDlgItemMessage (hdwnd, IDD_P3, BM_GETCHECK, 0, 0)) {
|
||||
/* port 3 */
|
||||
if (!port3 || strcmp (p3, port3Name)) {
|
||||
if (port3) CloseHandle (port3);
|
||||
SetCurrentDirectory (defaultDir);
|
||||
if ((port3 = CreateFile(p3, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, 0, NULL)) ==
|
||||
INVALID_HANDLE_VALUE) {
|
||||
MessageBox (hwnd, "Angitt navn på P3 ikke tilgjengelig!", ERROR_CAPTION, MB_OK);
|
||||
port1 = 0;
|
||||
}
|
||||
}
|
||||
} else if (port3) {
|
||||
CloseHandle (port3);
|
||||
port3 = 0;
|
||||
}
|
||||
|
||||
/* ta vare på portnavn */
|
||||
strcpy (port1Name, p1);
|
||||
strcpy (port2Name, p2);
|
||||
strcpy (port3Name, p3);
|
||||
}
|
||||
case 2: /* lukkeknapp for dialogboks, vet ikke makronavnet for den */
|
||||
case IDD_AVBRYT:
|
||||
EndDialog (hdwnd, 0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/* hent inn diskbilde fra fil */
|
||||
static void getDiskImage (int drive) {
|
||||
OPENFILENAME fname;
|
||||
char fn[256] = "\0";
|
||||
HANDLE hFile;
|
||||
|
||||
memset (&fname, 0, sizeof (OPENFILENAME));
|
||||
fname.lStructSize = sizeof (OPENFILENAME);
|
||||
fname.hwndOwner = hwnd;
|
||||
fname.lpstrFile = fn;
|
||||
fname.nMaxFile = sizeof (fn);
|
||||
fname.Flags = OFN_FILEMUSTEXIST;
|
||||
|
||||
if (GetOpenFileName (&fname)) {
|
||||
if ((hFile = CreateFile (fn, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL)) != INVALID_HANDLE_VALUE) {
|
||||
fileSize[drive] = GetFileSize (hFile, NULL);
|
||||
free (dsk[drive]);
|
||||
if ((dsk[drive] = (byte *)malloc (fileSize[drive]))) {
|
||||
DWORD dwRead;
|
||||
if (ReadFile (hFile, dsk[drive], fileSize[drive], &dwRead, NULL)) {
|
||||
switch (fileSize[drive]) {
|
||||
case 40*1*18*128:
|
||||
EnableMenuItem (GetSubMenu (GetMenu (hwnd), 1), drive == 0 ? IDM_LAGRE_A : IDM_LAGRE_B,
|
||||
MF_BYCOMMAND | MF_ENABLED);
|
||||
insertDisk (drive, dsk[drive], 40, 1, 18, 128);
|
||||
break;
|
||||
case 40*1*10*512:
|
||||
EnableMenuItem (GetSubMenu (GetMenu (hwnd), 1), drive == 0 ? IDM_LAGRE_A : IDM_LAGRE_B,
|
||||
MF_BYCOMMAND | MF_ENABLED);
|
||||
insertDisk (drive, dsk[drive], 40, 1, 10, 512);
|
||||
break;
|
||||
case 40*2*10*512:
|
||||
EnableMenuItem (GetSubMenu (GetMenu (hwnd), 1), drive == 0 ? IDM_LAGRE_A : IDM_LAGRE_B,
|
||||
MF_BYCOMMAND | MF_ENABLED);
|
||||
insertDisk (drive, dsk[drive], 40, 2, 10, 512);
|
||||
break;
|
||||
case 80*2*10*512:
|
||||
EnableMenuItem (GetSubMenu (GetMenu (hwnd), 1), drive == 0 ? IDM_LAGRE_A : IDM_LAGRE_B,
|
||||
MF_BYCOMMAND | MF_ENABLED);
|
||||
insertDisk (drive, dsk[drive], 80, 2, 10, 512);
|
||||
break;
|
||||
default:
|
||||
removeDisk (drive);
|
||||
fileSize[drive] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
CloseHandle (hFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* lagre diskbilde til fil */
|
||||
static void saveDiskImage (int drive) {
|
||||
OPENFILENAME fname;
|
||||
char fn[256] = "\0";
|
||||
HANDLE hFile;
|
||||
|
||||
memset (&fname, 0, sizeof (OPENFILENAME));
|
||||
fname.lStructSize = sizeof (OPENFILENAME);
|
||||
fname.hwndOwner = hwnd;
|
||||
fname.lpstrFile = fn;
|
||||
fname.nMaxFile = sizeof (fn);
|
||||
fname.Flags = OFN_HIDEREADONLY;
|
||||
|
||||
if (GetSaveFileName (&fname)) {
|
||||
if ((hFile = CreateFile (fn, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL))
|
||||
!= INVALID_HANDLE_VALUE) {
|
||||
DWORD dwWritten;
|
||||
WriteFile (hFile, dsk[drive], fileSize[drive], &dwWritten, NULL);
|
||||
CloseHandle (hFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Forandre oppløsning */
|
||||
void changeRes (int newRes) {
|
||||
RECT windowRect;
|
||||
|
||||
switch (newRes) {
|
||||
case HIGHRES:
|
||||
width = 1024;
|
||||
height = 256 * (scanlines ? 4 : 1);
|
||||
break;
|
||||
case MEDRES:
|
||||
width = 512 * size80x;
|
||||
height = 256 * size80x * (scanlines ? 2 : 1);
|
||||
break;
|
||||
case LOWRES:
|
||||
default:
|
||||
width = 256 * size40x;
|
||||
height = 256 * size40x;
|
||||
break;
|
||||
}
|
||||
GetWindowRect (hwnd, &windowRect);
|
||||
MoveWindow (hwnd, windowRect.left, windowRect.top, width + 2 * GetSystemMetrics (SM_CXFIXEDFRAME),
|
||||
height + 2 * GetSystemMetrics (SM_CYFIXEDFRAME) + GetSystemMetrics (SM_CYCAPTION) +
|
||||
GetSystemMetrics (SM_CYMENU) + STATUSBAR_HEIGHT, 1);
|
||||
/* slett bakgrunn */
|
||||
SelectObject (memdc, GetStockObject (BLACK_BRUSH));
|
||||
PatBlt (memdc, 0, 0, width, height, PATCOPY);
|
||||
if (newRes != resolution) {
|
||||
memset (screen, 0, 1024*256);
|
||||
resolution = newRes;
|
||||
}
|
||||
/* oppdater vindu */
|
||||
InvalidateRect (hwnd, NULL, FALSE);
|
||||
}
|
||||
/* Plotter en pixel med farge tatt fra pallett */
|
||||
void plotPixel (int x, int y, int color) {
|
||||
screen[x+y*1024] = color;
|
||||
switch (resolution) {
|
||||
case HIGHRES:
|
||||
y *= scanlines ? 4 : 1;
|
||||
break;
|
||||
case MEDRES:
|
||||
x *= size80x;
|
||||
y *= size80x * (scanlines ? 2 : 1);
|
||||
break;
|
||||
case LOWRES:
|
||||
x *= size40x;
|
||||
y *= size40x;
|
||||
break;
|
||||
}
|
||||
SetPixelV (memdc, x, y, colors[color]);
|
||||
update (x, y, 1, 1);
|
||||
}
|
||||
/* Scroller skjerm 'distance' linjer oppover */
|
||||
void scrollScreen (int distance) {
|
||||
/* scroll screen */
|
||||
if (distance > 0) {
|
||||
memmove (screen, screen + distance * 1024, (256 - distance) * 1024);
|
||||
memset (screen + distance * 1024, 0, (256 - distance) * 1024);
|
||||
} else {
|
||||
memmove (screen + -(distance * 1024), screen, (byte)distance * 1024);
|
||||
memset (screen, 0, -distance * 1024);
|
||||
}
|
||||
/* finn avstand */
|
||||
switch (resolution) {
|
||||
case HIGHRES:
|
||||
distance *= scanlines ? 4 : 1;
|
||||
break;
|
||||
case MEDRES:
|
||||
distance *= size80x * (scanlines ? 2 : 1);
|
||||
break;
|
||||
case LOWRES:
|
||||
default:
|
||||
distance *= size40x;
|
||||
break;
|
||||
}
|
||||
/* scroll memdc */
|
||||
BitBlt (memdc, 0, -distance, width, height + distance, memdc, 0, 0, SRCCOPY);
|
||||
SelectObject (memdc, GetStockObject (BLACK_BRUSH));
|
||||
/* slett resten */
|
||||
if (distance > 0) {
|
||||
PatBlt (memdc, 0, height - distance, width, distance, PATCOPY);
|
||||
} else {
|
||||
PatBlt (memdc, 0, 0, width, -distance, PATCOPY);
|
||||
}
|
||||
/* oppdater vindu */
|
||||
InvalidateRect (hwnd, NULL, FALSE);
|
||||
}
|
||||
/* Ny farge, gitt pallett nummer og intensitet 0-255 */
|
||||
void changePalette (int colornumber, byte red, byte green, byte blue) {
|
||||
if (colors[colornumber] != RGB (red, green, blue)) {
|
||||
int x, y;
|
||||
|
||||
colors[colornumber] = RGB (red, green, blue);
|
||||
|
||||
/* oppdater pixler med denne fargen */
|
||||
for (y = 0; y < 256; y++) {
|
||||
for (x = 0; x < 1024; x++) {
|
||||
if (screen[x+y*1024] == colornumber) {
|
||||
plotPixel (x, y, colornumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Kalles periodisk. Lar system kode måle / senke emuleringshastighet
|
||||
* Kan også brukes til sjekk av brukeraktivitet
|
||||
* ms er antall "emulerte" millisekunder siden forrige gang loopEmul ble kalt
|
||||
*/
|
||||
void loopEmul (int ms) {
|
||||
/* senk hastigheten */
|
||||
if (slowDown) {
|
||||
static boolean firstTime = TRUE;
|
||||
static LARGE_INTEGER lastTime;
|
||||
LARGE_INTEGER currentTime;
|
||||
static LARGE_INTEGER freq;
|
||||
|
||||
if (QueryPerformanceCounter (¤tTime)) {
|
||||
if (firstTime) {
|
||||
QueryPerformanceFrequency (&freq);
|
||||
lastTime = currentTime;
|
||||
firstTime = FALSE;
|
||||
} else {
|
||||
long sleepPeriod = ms - ((currentTime.QuadPart - lastTime.QuadPart) * 1000 / freq.QuadPart);
|
||||
|
||||
lastTime = currentTime;
|
||||
|
||||
if (sleepPeriod > 0) {
|
||||
Sleep (sleepPeriod);
|
||||
QueryPerformanceCounter (&lastTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* oppdater skjerm */
|
||||
if (updateWindow) {
|
||||
RECT rect = {xmin, ymin, xmax, ymax};
|
||||
InvalidateRect (hwnd, &rect, FALSE);
|
||||
xmin = (unsigned)~0, ymin = (unsigned)~0, xmax = 0, ymax = 0;
|
||||
updateWindow = FALSE;
|
||||
}
|
||||
/* sjekk seriekanaler */
|
||||
{
|
||||
DWORD error;
|
||||
COMSTAT comstat;
|
||||
|
||||
if (port1) {
|
||||
if (ClearCommError (port1, &error, &comstat)) {
|
||||
if (comstat.cbInQue != 0) {
|
||||
charAvailable (0);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (port2) {
|
||||
if (ClearCommError (port2, &error, &comstat)) {
|
||||
if (comstat.cbInQue != 0) {
|
||||
charAvailable (1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* sjekk om der er events som venter */
|
||||
{
|
||||
MSG msg;
|
||||
|
||||
while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) {
|
||||
if (msg.message == WM_QUIT) {
|
||||
DeleteDC (memdc);
|
||||
DeleteObject (hbit);
|
||||
quitEmul();
|
||||
} else {
|
||||
DispatchMessage (&msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Tenn/slukk lock lys */
|
||||
void lockLight (boolean status) {
|
||||
HBRUSH brush = (status ?
|
||||
GetSysColorBrush (COLOR_HIGHLIGHT) :
|
||||
GetSysColorBrush (COLOR_3DFACE));
|
||||
SelectObject (memdc, brush);
|
||||
PatBlt (memdc, 21, height + 6, 7, 7, PATCOPY);
|
||||
update (21, height + 6, 7, 7);
|
||||
lock = status;
|
||||
}
|
||||
/* Tenn/slukk grafikk lys */
|
||||
void grafikkLight (boolean status) {
|
||||
HBRUSH brush = (status ?
|
||||
GetSysColorBrush (COLOR_HIGHLIGHT) :
|
||||
GetSysColorBrush (COLOR_3DFACE));
|
||||
SelectObject (memdc, brush);
|
||||
PatBlt (memdc, 41, height + 6, 7, 7, PATCOPY);
|
||||
update (41, height + 6, 7, 7);
|
||||
grafikk = status;
|
||||
}
|
||||
/* Tenn/slukk disk lys for gitt stasjon */
|
||||
void diskLight (int drive, boolean status) {
|
||||
int x = (drive ? 81 : 61);
|
||||
HBRUSH brush = (status ?
|
||||
GetSysColorBrush (COLOR_HIGHLIGHT) :
|
||||
GetSysColorBrush (COLOR_3DFACE));
|
||||
SelectObject (memdc, brush);
|
||||
PatBlt (memdc, x, height + 6, 7, 7, PATCOPY);
|
||||
update (61, height + 6, 7, 7);
|
||||
disk[drive] = status;
|
||||
}
|
||||
static void update (int x, int y, int w, int h) {
|
||||
if (xmin > x) xmin = x;
|
||||
if (ymin > y) ymin = y;
|
||||
if (xmax < (x + w)) xmax = x + w;
|
||||
if (ymax < (y + h)) ymax = y + h;
|
||||
updateWindow = TRUE;
|
||||
}
|
||||
/* Sjekk status til hver av de gitte tastene
|
||||
* Sett bit n i returkode hvis tast n IKKE er nedtrykt
|
||||
* Taster er enten ascii-kode eller en av konstantene over
|
||||
*/
|
||||
byte testKey (byte keys[8]) {
|
||||
return pressedKeys[keys[0]] | (pressedKeys[keys[1]] << 1) | (pressedKeys[keys[2]] << 2) |
|
||||
(pressedKeys[keys[3]] << 3) | (pressedKeys[keys[4]] << 4) | (pressedKeys[keys[5]] << 5) |
|
||||
(pressedKeys[keys[6]] << 6) | (pressedKeys[keys[7]] << 7);
|
||||
}
|
||||
/* setter seriekanalparametre */
|
||||
void setParams (struct serParams *p1Params, struct serParams *p2Params) {
|
||||
if (port1) setParam (port1, p1Params);
|
||||
if (port2) setParam (port2, p2Params);
|
||||
}
|
||||
static void setParam (HANDLE portHandle, struct serParams *params) {
|
||||
DCB dcb = {sizeof (DCB),
|
||||
0, /* BaudRate */
|
||||
TRUE, /* fBinary */
|
||||
0, /* fParity */
|
||||
FALSE, /* fOutxCtsFlow */
|
||||
FALSE, /* fOutxDsrFlow */
|
||||
DTR_CONTROL_ENABLE, /* fDtrControl */
|
||||
FALSE, /* fDsrSensitivity */
|
||||
TRUE, /* fTXContinueOnXoff */
|
||||
FALSE, /* fOutX */
|
||||
FALSE, /* fInX */
|
||||
FALSE, /* fErrorChar */
|
||||
FALSE, /* fNull */
|
||||
RTS_CONTROL_ENABLE, /* fRtsControl */
|
||||
FALSE, /* fAbortOnError */
|
||||
17, /* fDummy2 */
|
||||
0, /* wReserved */
|
||||
0, /* XonLim */
|
||||
0, /* XoffLim */
|
||||
0, /* ByteSize */
|
||||
0, /* Parity */
|
||||
0, /* StopBits */
|
||||
0, /* XonChar */
|
||||
0, /* XoffChar */
|
||||
0, /* ErrorChar */
|
||||
-1, /* EofChar */
|
||||
0, /* EvtChar */
|
||||
0}; /* wReservedl */
|
||||
|
||||
dcb.BaudRate = params->baud;
|
||||
dcb.BaudRate = dcb.BaudRate - dcb.BaudRate % 100;
|
||||
|
||||
dcb.ByteSize = params->sendBits; /* obs: receiveBits blir ikke tatt hensyn til */
|
||||
switch (params->parity) {
|
||||
case PAR_NONE:
|
||||
dcb.Parity = NOPARITY;
|
||||
dcb.fParity = FALSE;
|
||||
break;
|
||||
case PAR_EVEN:
|
||||
dcb.Parity = EVENPARITY;
|
||||
dcb.fParity = TRUE;
|
||||
break;
|
||||
case PAR_ODD:
|
||||
dcb.Parity = ODDPARITY;
|
||||
dcb.fParity = TRUE;
|
||||
break;
|
||||
}
|
||||
switch (params->stopBits) {
|
||||
case ONE_SB: dcb.StopBits = ONESTOPBIT; break;
|
||||
case ONE_PT_FIVE_SB: dcb.StopBits = ONE5STOPBITS; break;
|
||||
case TWO_SB: dcb.StopBits = TWOSTOPBITS; break;
|
||||
}
|
||||
|
||||
if (!SetCommState(portHandle, &dcb)) {
|
||||
/* ingen aksjon */
|
||||
}
|
||||
return;
|
||||
}
|
||||
/* send tegn til seriekanal */
|
||||
void sendChar (int port, byte value) {
|
||||
DWORD bytesWritten;
|
||||
HANDLE portHandle = port ? port2 : port1;
|
||||
|
||||
if (portHandle) {
|
||||
if (!WriteFile (portHandle, &value, 1, &bytesWritten, NULL)) {
|
||||
/* kan ikke skrive til port */
|
||||
}
|
||||
}
|
||||
}
|
||||
/* hent tegn fra seriekanal */
|
||||
byte getChar (int port) {
|
||||
HANDLE portHandle = port ? port2 : port1;
|
||||
byte value = 0;
|
||||
DWORD bytesRead;
|
||||
|
||||
if (portHandle) {
|
||||
if (!ReadFile (portHandle, &value, 1, &bytesRead, NULL)) {
|
||||
/* kan ikke lese fra port */
|
||||
}
|
||||
|
||||
/* flere tegn i buffer? */
|
||||
{
|
||||
DWORD error;
|
||||
COMSTAT comstat;
|
||||
|
||||
if (ClearCommError (portHandle, &error, &comstat)) {
|
||||
if (comstat.cbInQue != 0) {
|
||||
charAvailable (port);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
/* send tegn til skriver */
|
||||
void printChar (byte value) {
|
||||
DWORD bytesWritten;
|
||||
|
||||
if (port3) {
|
||||
if (!WriteFile (port3, &value, 1, &bytesWritten, NULL)) {
|
||||
/* kan ikke skrive til port */
|
||||
}
|
||||
}
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
|
@ -0,0 +1,39 @@
|
|||
/* win32_res.h V1.1.0
|
||||
*
|
||||
* Konstanter for win32 ressurser
|
||||
* Copyright (C) Asbjørn Djupdal 2000-2001
|
||||
*/
|
||||
|
||||
#include "TIKI-100_emul.h"
|
||||
|
||||
#define IDM_RESET 0
|
||||
#define IDM_INNSTILLINGER 1
|
||||
#define IDM_OM 2
|
||||
#define IDM_AVSLUTT 3
|
||||
#define IDM_HENT_A 4
|
||||
#define IDM_HENT_B 5
|
||||
#define IDM_LAGRE_A 6
|
||||
#define IDM_LAGRE_B 7
|
||||
#define IDM_FJERN_A 8
|
||||
#define IDM_FJERN_B 9
|
||||
|
||||
#ifdef DEBUG
|
||||
#define IDM_MONITOR 10
|
||||
#endif
|
||||
|
||||
#define IDD_HASTIGHET 11
|
||||
#define IDD_BEVARFORHOLD 12
|
||||
#define IDD_SOLID 13
|
||||
#define IDD_40SPIN 14
|
||||
#define IDD_80SPIN 15
|
||||
#define IDD_40EDIT 16
|
||||
#define IDD_80EDIT 17
|
||||
#define IDD_OK 18
|
||||
#define IDD_AVBRYT 19
|
||||
#define IDD_P1EDIT 20
|
||||
#define IDD_P2EDIT 21
|
||||
#define IDD_P3EDIT 22
|
||||
#define IDD_P1 23
|
||||
#define IDD_P2 24
|
||||
#define IDD_P3 25
|
||||
#define IDD_ST28B 26
|
|
@ -0,0 +1,59 @@
|
|||
/* win32_res.rc V1.1.0
|
||||
*
|
||||
* Win32 resources for TIKI-100_emul
|
||||
* Copyright (C) Asbjørn Djupdal 2000-2001
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
#include "win32_res.h"
|
||||
#include "TIKI-100_emul.h"
|
||||
|
||||
menu MENU {
|
||||
POPUP "&Emulator" {
|
||||
MENUITEM "&Reset", IDM_RESET
|
||||
MENUITEM "&Innstillinger...", IDM_INNSTILLINGER
|
||||
MENUITEM "&Om...", IDM_OM
|
||||
MENUITEM "&Avslutt", IDM_AVSLUTT
|
||||
}
|
||||
POPUP "&Diskettstasjon" {
|
||||
MENUITEM "Hent plate &A...", IDM_HENT_A
|
||||
MENUITEM "Hent plate &B...", IDM_HENT_B
|
||||
MENUITEM "Lagre plate A...", IDM_LAGRE_A, GRAYED
|
||||
MENUITEM "Lagre plate B...", IDM_LAGRE_B, GRAYED
|
||||
MENUITEM "Fjern plate A", IDM_FJERN_A
|
||||
MENUITEM "Fjern plate B", IDM_FJERN_B
|
||||
}
|
||||
#ifdef DEBUG
|
||||
POPUP "&Debug" {
|
||||
MENUITEM "&Monitor...", IDM_MONITOR
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
dialog DIALOG DISCARDABLE 30, 30, 269, 137
|
||||
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "TIKI-100_emul innstillinger"
|
||||
{
|
||||
DEFPUSHBUTTON "OK", IDD_OK, 155, 114, 50, 14
|
||||
PUSHBUTTON "Avbryt", IDD_AVBRYT, 211, 114, 50, 14
|
||||
|
||||
AUTOCHECKBOX "Senk hastighet", IDD_HASTIGHET, 7, 7, 63, 10
|
||||
|
||||
GROUPBOX "Skjermforstørring", -1, 7, 26, 121, 78
|
||||
EDITTEXT IDD_40EDIT, 21, 42, 25, 14, ES_LEFT | WS_CHILD | WS_VISIBLE | WS_BORDER
|
||||
EDITTEXT IDD_80EDIT, 21, 61, 25, 14, ES_LEFT | WS_CHILD | WS_VISIBLE | WS_BORDER
|
||||
LTEXT "40 tegns skjerm", -1, 55, 45, 60, 8
|
||||
LTEXT "80 tegns skjerm", -1, 55, 64, 60, 8
|
||||
AUTOCHECKBOX "Bevar forhold", IDD_BEVARFORHOLD, 21, 80, 58, 10
|
||||
|
||||
GROUPBOX "Porter", -1, 133, 9, 128, 95
|
||||
AUTOCHECKBOX "Sett ST 28 b", IDD_ST28B, 145, 23, 56, 10
|
||||
EDITTEXT IDD_P1EDIT, 145, 42, 42, 14, ES_AUTOHSCROLL
|
||||
EDITTEXT IDD_P2EDIT, 145, 61, 42, 14, ES_AUTOHSCROLL
|
||||
EDITTEXT IDD_P3EDIT, 145, 80, 42, 14, ES_AUTOHSCROLL
|
||||
AUTOCHECKBOX "Serieport P1", IDD_P1, 193, 45, 63, 8
|
||||
AUTOCHECKBOX "Serieport P2", IDD_P2, 193, 64, 63, 8
|
||||
AUTOCHECKBOX "Parallellport P3", IDD_P3, 193, 83, 63, 8
|
||||
}
|
||||
|
||||
icon ICON win32.ico
|
Reference in New Issue