Asbjorn emulator

This commit is contained in:
Einar Johan Trøan Sømåen 2008-09-01 10:30:26 +00:00
parent c012f508d0
commit d33ed6be9f
43 changed files with 7991 additions and 0 deletions

378
TIKI-100_emul-src/Codes.h Normal file
View File

@ -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;

204
TIKI-100_emul-src/CodesCB.h Normal file
View File

@ -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;

281
TIKI-100_emul-src/CodesED.h Normal file
View File

@ -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;

View File

@ -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;

388
TIKI-100_emul-src/CodesXX.h Normal file
View File

@ -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;

411
TIKI-100_emul-src/Debug.c Normal file
View File

@ -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 */

140
TIKI-100_emul-src/LESMEG Normal file
View File

@ -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

148
TIKI-100_emul-src/Makefile Normal file
View File

@ -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))

View File

@ -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

View File

@ -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

View File

@ -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.
* 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.
* 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

View File

@ -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

447
TIKI-100_emul-src/Tables.h Normal file
View File

@ -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
};

573
TIKI-100_emul-src/Z80.c Normal file
View File

@ -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);
}

139
TIKI-100_emul-src/Z80.h Normal file
View File

@ -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 */

636
TIKI-100_emul-src/amiga.c Normal file
View File

@ -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 */
}

View File

@ -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.

View File

@ -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
;

View File

@ -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

149
TIKI-100_emul-src/ctc.c Normal file
View File

@ -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, &params0);
}
/* skriv til ctc1-register */
void writeCtc1 (byte value) {
writeCtc (value, &params1);
}
/* skriv til ctc2-register */
void writeCtc2 (byte value) {
writeCtc (value, &params2);
}
/* skriv til ctc3-register */
void writeCtc3 (byte value) {
writeCtc (value, &params3);
}
/* 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;
}

339
TIKI-100_emul-src/disk.c Normal file
View File

@ -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 (&params->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 = &params0;
} else {
params = &params1;
}
setLights();
}
/* sett disk 1 aktiv / inaktiv */
void disk1 (boolean status) {
if (status) {
params = &params1;
} else {
params = &params0;
}
setLights();
}
/* skru motor på / av */
void diskMotor (boolean status) {
motOn = status;
setLights();
}
/* sett alle disklys */
static void setLights (void) {
int disk = params == &params0 ? 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 ? &params1 : &params0;
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 ? &params1 :&params0;
dp->active = FALSE;
}

View File

@ -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++]);
}

203
TIKI-100_emul-src/mem.c Normal file
View File

@ -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;
}
}

View File

@ -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.

124
TIKI-100_emul-src/protos.h Normal file
View File

@ -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

206
TIKI-100_emul-src/serial.c Normal file
View File

@ -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;
}
}

30
TIKI-100_emul-src/sound.c Normal file
View File

@ -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;
}

BIN
TIKI-100_emul-src/tiki.rom Normal file

Binary file not shown.

1135
TIKI-100_emul-src/unix.c Normal file

File diff suppressed because it is too large Load Diff

123
TIKI-100_emul-src/video.c Normal file
View File

@ -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;
}
}

792
TIKI-100_emul-src/win32.c Normal file
View File

@ -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 (&currentTime)) {
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 */
}
}
}

BIN
TIKI-100_emul-src/win32.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -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

View File

@ -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