📄 st20.c
字号:
/* * Softcam plugin to VDR (C++) * * This code is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Or, point your browser to http://www.gnu.org/copyleft/gpl.html */#include <stdlib.h>#include <stdio.h>#include <unistd.h>#include <string.h>#include <vdr/tools.h>#include "log-viaccess.h"#include "st20.h"#include "helper.h"#include "misc.h"//#define SAVE_DEBUG // add some (slow) failsafe checks and stricter emulation#define INVALID_VALUE 0xCCCCCCCC#define ERRORVAL 0xDEADBEEF#define MININT 0x7FFFFFFF#define MOSTPOS 0x7FFFFFFF#define MOSTNEG 0x80000000#ifndef SAVE_DEBUG#define POP() stack[(sptr++)&STACKMASK]#else#define POP() ({ int __t=stack[sptr&STACKMASK]; stack[(sptr++)&STACKMASK]=INVALID_VALUE; __t; })#endif#define PUSH(v) do { int __v=(v); stack[(--sptr)&STACKMASK]=__v; } while(0)#define DROP(n) sptr+=n#define AAA stack[sptr&STACKMASK]#define BBB stack[(sptr+1)&STACKMASK]#define CCC stack[(sptr+2)&STACKMASK]#define GET_OP() operand|=op1&0x0F#define CLEAR_OP() operand=0#define JUMP(x) Iptr+=(x)#define POP64() ({ unsigned int __b=POP(); ((unsigned long long)POP()<<32)|__b; })#define PUSHPOP(op,val) do { int __a=val; AAA op##= (__a); } while(0)#ifndef SAVE_DEBUG#define RB(off) UINT8_LE(Addr(off))#define RW(off) UINT32_LE(Addr(off))#define WW(off,val) BYTE4_LE(Addr(off),val)#else#define RB(off) ReadByte(off)#define RW(off) ReadWord(off)#define WW(off,val) WriteWord(off,val)#endif#define LOG_OP(op) do { if(v) LogOp(op); } while(0)// -- cST20 --------------------------------------------------------------------cST20::cST20(void){ flash=ram=0; loglb=new cLineBuff(128);}cST20::~cST20(){ free(flash); free(ram); delete loglb;}void cST20::SetFlash(unsigned char *m, int len){ free(flash); flash=MALLOC(unsigned char,len); if(flash && m) memcpy(flash,m,len); else memset(flash,0,len); flashSize=len;}void cST20::SetRam(unsigned char *m, int len){ free(ram); ram=MALLOC(unsigned char,len); if(ram && m) memcpy(ram,m,len); else memset(ram,0,len); ramSize=len;}void cST20::Init(unsigned int IPtr, unsigned int WPtr){ Wptr=WPtr; Iptr=IPtr; memset(stack,INVALID_VALUE,sizeof(stack)); sptr=STACKMAX-3; memset(iram,0,sizeof(iram)); verbose=LOG(L_SYS_DISASM);}void cST20::SetCallFrame(unsigned int raddr, int p1, int p2, int p3){ Wptr-=16; WriteWord(Wptr,raddr); // RET WriteWord(Wptr+4,0); WriteWord(Wptr+8,0); WriteWord(Wptr+12,p1); WriteWord(Wptr+16,p2); WriteWord(Wptr+20,p3); SetReg(AREG,raddr); // RET}unsigned int cST20::GetReg(int reg) const{ switch(reg) { case IPTR: return Iptr; case WPTR: return Wptr; case AREG: return AAA; case BREG: return BBB; case CREG: return CCC; default: PRINTF(L_SYS_ST20,"getreg: unknown reg"); return ERRORVAL; }}void cST20::SetReg(int reg, unsigned int val){ switch(reg) { case IPTR: Iptr=val; return; case WPTR: Wptr=val; return; case AREG: AAA=val; return; case BREG: BBB=val; return; case CREG: CCC=val; return; default: PRINTF(L_SYS_ST20,"setreg: unknown reg"); return; }}unsigned char *cST20::Addr(unsigned int off){ switch(off) { case FLASHS ... FLASHE:#ifndef SAVE_DEBUG return &flash[off-FLASHS];#else off-=FLASHS; if(off<flashSize && flash) return &flash[off]; break;#endif case RAMS ... RAME:#ifndef SAVE_DEBUG return &ram[off-RAMS];#else off-=RAMS; if(off<ramSize && ram) return &ram[off]; break;#endif case IRAMS ... IRAME: return &iram[off-IRAMS]; }#ifndef SAVE_DEBUG invalid=ERRORVAL; return (unsigned char *)&invalid;#else return 0;#endif}unsigned int cST20::ReadWord(unsigned int off){#ifndef SAVE_DEBUG return UINT32_LE(Addr(off));#else unsigned char *addr=Addr(off); return addr ? UINT32_LE(addr) : ERRORVAL;#endif}unsigned short cST20::ReadShort(unsigned int off){#ifndef SAVE_DEBUG return UINT16_LE(Addr(off));#else unsigned char *addr=Addr(off); return addr ? UINT16_LE(addr) : ERRORVAL>>16;#endif}unsigned char cST20::ReadByte(unsigned int off){#ifndef SAVE_DEBUG return UINT8_LE(Addr(off));#else unsigned char *addr=Addr(off); return addr ? UINT8_LE(addr) : ERRORVAL>>24;#endif}void cST20::WriteWord(unsigned int off, unsigned int val){#ifndef SAVE_DEBUG BYTE4_LE(Addr(off),val);#else unsigned char *addr=Addr(off); if(addr) BYTE4_LE(addr,val);#endif}void cST20::WriteShort(unsigned int off, unsigned short val){#ifndef SAVE_DEBUG BYTE2_LE(Addr(off),val);#else unsigned char *addr=Addr(off); if(addr) BYTE2_LE(addr,val);#endif}void cST20::WriteByte(unsigned int off, unsigned char val){#ifndef SAVE_DEBUG BYTE1_LE(Addr(off),val);#else unsigned char *addr=Addr(off); if(addr) BYTE1_LE(addr,val);#endif}#define OP_COL 20void cST20::LogOpOper(int op, int oper){ const static char *cmds[] = { "j","ldlp",0,"ldnl","ldc","ldnlp",0,"ldl","adc","call","cj","ajw","eqc","stl","stnl",0 }; const static char flags[] = { 3, 0, 0, 0, 1, 0, 0, 0, 1, 3, 3, 0, 1, 0, 0, 0 }; if(oper==0) loglb->Printf("%08X %02X",Iptr-1,op); else loglb->Printf("%02X",op); oper|=op&0xF; op>>=4; if(!cmds[op]) return; int n=loglb->Length(); if(flags[op]&2) oper+=Iptr; if(flags[op]&1) loglb->Printf("%*s%-5s $%-8X ",max(OP_COL-n,1)," ",cmds[op],oper); else loglb->Printf("%*s%-5s %-8d ",max(OP_COL-n,1)," ",cmds[op],oper);}void cST20::LogOp(char *op){ int n=loglb->Length(); loglb->Printf("%*s%-15s ",max(OP_COL-n,1)," ",op);}int cST20::Decode(int count){ int operand; bool v=verbose; CLEAR_OP(); while(Iptr!=0) { int a, op1=RB(Iptr++); if(v) LogOpOper(op1,operand); GET_OP(); switch(op1>>4) { case 0x0: // j / jump#ifdef SAVE_DEBUG POP(); POP(); POP();#endif JUMP(operand); CLEAR_OP(); break; case 0x1: // ldlp PUSH(Wptr+(operand*4)); CLEAR_OP(); break; case 0x2: // positive prefix operand<<=4; break; case 0x3: // ldnl AAA=RW(AAA+(operand*4)); CLEAR_OP(); break; case 0x4: // ldc PUSH(operand); CLEAR_OP(); break; case 0x5: // ldnlp PUSHPOP(+,operand*4); CLEAR_OP(); break; case 0x6: // negative prefix operand=(~operand)<<4; break; case 0x7: // ldl PUSH(RW(Wptr+(operand*4))); CLEAR_OP(); break; case 0x8: // adc PUSHPOP(+,operand); CLEAR_OP(); break; case 0x9: // call Wptr-=16; WW(Wptr,Iptr); WW(Wptr+4,POP()); WW(Wptr+8,POP()); WW(Wptr+12,POP()); PUSH(Iptr); JUMP(operand); CLEAR_OP(); break; case 0xA: // cj / conditional jump if(AAA) DROP(1); else JUMP(operand); CLEAR_OP(); break; case 0xB: // ajw / adjust workspace Wptr+=operand*4; CLEAR_OP(); break; case 0xC: // eqc / equals constant AAA=(operand==AAA ? 1 : 0); CLEAR_OP(); break; case 0xD: // stl WW(Wptr+(operand*4),POP()); CLEAR_OP(); break; case 0xE: // stnl a=POP(); WW(a+(operand*4),POP()); CLEAR_OP(); break; case 0xF: // opr (secondary ins) switch(operand) { case 0x00: LOG_OP("rev"); a=AAA; AAA=BBB; BBB=a; break; case 0x01: LOG_OP("lb"); AAA=RB(AAA); break; case 0x02: LOG_OP("bsub"); PUSHPOP(+,POP()); break; case 0x04: LOG_OP("diff"); PUSHPOP(-,POP()); break; case 0x05: LOG_OP("add"); PUSHPOP(+,POP()); break; case 0x06: LOG_OP("gcall"); a=AAA; AAA=Iptr; Iptr=a; break; case 0x08: LOG_OP("prod"); PUSHPOP(*,POP()); break; case 0x09: LOG_OP("gt"); a=POP(); AAA=(AAA>a); break; case 0x0A: LOG_OP("wsub"); a=POP(); AAA=a+(AAA*4); break; case 0x0C: LOG_OP("sub"); PUSHPOP(-,POP()); break; case 0x1B: LOG_OP("ldpi"); PUSHPOP(+,Iptr); break; case 0x20: LOG_OP("ret"); Iptr=RW(Wptr); Wptr=Wptr+16; break; case 0x2C: LOG_OP("div"); PUSHPOP(/,POP()); break; case 0x32: LOG_OP("not"); AAA=~AAA; break; case 0x33: LOG_OP("xor"); PUSHPOP(^,POP()); break; case 0x34: LOG_OP("bcnt"); PUSHPOP(*,4); break; case 0x3B: LOG_OP("sb"); a=POP(); WriteByte(a,POP()); break; case 0x3F: LOG_OP("wcnt"); a=POP(); PUSH(a&3); PUSH((unsigned int)a>>2); break; case 0x40: LOG_OP("shr"); a=POP(); AAA=(unsigned int)AAA>>a; break; case 0x41: LOG_OP("shl"); a=POP(); AAA=(unsigned int)AAA<<a; break; case 0x42: LOG_OP("mint"); PUSH(MOSTNEG); break; case 0x46: LOG_OP("and"); PUSHPOP(&,POP()); break; case 0x4A: LOG_OP("move"); { a=POP(); int b=POP(); int c=POP(); while(a--) WriteByte(b++,ReadByte(c++)); } break; case 0x4B: LOG_OP("or"); PUSHPOP(|,POP()); break; case 0x53: LOG_OP("mul"); PUSHPOP(*,POP()); break; case 0x5A: LOG_OP("dup"); PUSH(AAA); break; case 0x5F: LOG_OP("gtu"); a=POP(); AAA=((unsigned int)AAA>(unsigned int)a); break; case 0x1D: LOG_OP("xdble"); CCC=BBB; BBB=(AAA>=0 ? 0:-1); break; case 0x1A: LOG_OP("ldiv"); { a=POP(); unsigned long long ll=POP64(); PUSH(ll%(unsigned int)a); PUSH(ll/(unsigned int)a); } break; case 0x1F: LOG_OP("rem"); PUSHPOP(%,POP()); break; case 0x35: LOG_OP("lshr"); { a=POP(); unsigned long long ll=POP64()>>a; PUSH((ll>>32)&0xFFFFFFFF); PUSH(ll&0xFFFFFFFF); } break; case 0xCA: LOG_OP("ls"); AAA=ReadShort(AAA); break; case 0xCD: LOG_OP("gintdis"); break; case 0xCE: LOG_OP("gintenb"); break; case -0x40: LOG_OP("nop"); break; default: if(verbose) PUTLB(L_SYS_DISASM,loglb); PRINTF(L_SYS_ST20,"unknown opcode %X",operand); return ERR_ILL_OP; } CLEAR_OP(); break; } if(v && operand==0) { loglb->Printf("%08X %08X %08X W:%08X",AAA,BBB,CCC,Wptr); PUTLB(L_SYS_DISASM,loglb); } if(--count<=0 && operand==0) { PRINTF(L_SYS_ST20,"instruction counter exceeded"); return ERR_CNT; } } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -