What software do i need to make Computer software
I might be jumping ahead of my self.
But i'm on a mission.
And one of my friends already has some computer savy skills.
What do I need?
http://25.media.tumblr.com/f68dbf9272b310721ec008e6b5dd6a51/tumblr_mg0u1lBSlg1r55j58o1_1280.png
Additional bonus question, what program do I need to make video games?
Re: What software do i need to make Computer software
Quote:
What software do i need to make Computer software
That mostly depends on the programming language(s) you've opted to use.
Picture's unrelated, I guess... :blink:
Re: What software do i need to make Computer software
Either way, bookmark the New Boston. It was my home away from home when I was at uni.
http://thenewboston.org/tutorials.php
Re: What software do i need to make Computer software
start with windows apllications. you need visual studio and C#
Quote:
Originally Posted by
fuzzy_mcnut
Re: What software do i need to make Computer software
Might want to start with qbasic. You can make some pretty awesome games.
Re: What software do i need to make Computer software
Depends on what kind of coding you plan on doing.
Re: What software do i need to make Computer software
This sounds interesting and can be fun, but it will take a lot of hard work to make anything nearly as interesting as professional software. My suggestion is start with visual basic,very easy to understand for noobs. From there it all depends what you want to do. Be prepared to read a lot and practice all the time.
Re: What software do i need to make Computer software
Notepad ++ or Sublime Text 2 are my 2 "go to" code editing apps, call me old fashioned I guess
Re: What software do i need to make Computer software
I second Visual Basic. Easier to learn than C++, Java etc. Get your feet wet before trying harder languages.
Re: What software do i need to make Computer software
I can mirror some of these comments - VB is easy to code in, but it'll probably ruin you if you want to get into actual coding as a career.
If you fancy trying it out - there is an amazing course just about to start - it's totally free and online - ran my a university - and will guide you through building a mobile phone game in java
https://www.futurelearn.com/courses/...ogramming-2014
These courses are amazing, I can't recommend them enough
Re: What software do i need to make Computer software
Quote:
Originally Posted by
byrnesc1
Notepad ++ or Sublime Text 2 are my 2 "go to" code editing apps, call me old fashioned I guess
I would suggest doing a bit of research before jumping straight into a language. You should think about what you want to make and what for platform. C++ is a very good language to learn in which there's a high chance you will actually use it in a major project.
Re: What software do i need to make Computer software
Re: What software do i need to make Computer software
C with gcc compiler, notepad as an editor and debug the hard way. Don't mess with that Visual stuff :D
Or Devpac assembler if you want to develop on an Amiga :S.... ok not very likely that one but it was just as much fun.
For Intel\PC then I use PowerBasic as it compiles to standalone without a whole bunch of "framework" crap, little bit harder to debug that visual stuff but certain satisfaction in tracing issues with debug outputs. You don`t need automatic trash collection if you code proper like :)
Oh the good old days....
Code:
/*********************************************************************
File: GoM V3.5.4 (Based all on FoM-FunSECA)
Author: Gribley
Dates: Nov2001 - May 2002
Purpose: SECA emulation :p
Compiler: AVR-GCC + Make2
Hardware: FunCard 8515 or, with mod to Makefile, 8535
**********************************************************************/
#include <io.h>
#include "types.h"
// Using intelli byte we can add additional space
// to any calls to the upper end of the eeprom
// this therefore allows us to have a single
// version that supports Funcard 2, 3 and 4... this value
// is added to the upper limit of the eeprom
u16 Extra_Funcard_Space = 0x0000;
// Default serial number
//u08 DefaultSerial[3] = {0xF2, 0xF1, 0xF0};
#include "funseca.h"
#include "funio.h"
#include "decrip.h"
#include "ee_ext.h"
#include "ee_int.h"
#define MODO_LOG = 0x01
u08 ECM_Count_High = 0x00;
u08 ECM_Count_Low = 0x00;
u08 ECM_LastECMInst = 0x00;
u08 ECM_LastProviderChecked = 0x00;
//u08 EVENT_Display[16] = {0xD3,0xC7,0xAE,0xFD,0x2B,0x8E,0x91,0x35,
// 0xC4,0x81,0xC0,0xE4,0xB3,0x09,0xD4,0x0B};
u08 EVENT_Display[12] = {'C','W','P',':','0','0',' ','E',
'V','N','T',':'};
//u08 ECM_Display[16] = {0x6A,0x81,0x60,0x2A,0x12,0xA7,0x38,0x8E,
// 0x66,0xD1,0xCB,0x82,0x6C,0xAC,0xB9,0x09};
u08 ECM_Display[12] = {'I','N','S',':','0','0',' ','E',
'C','M','s',':'};
// Display LOG ON in provider 4 when logging is enabled.
u08 LOG_Method = 0x00;
u08 LOG_ON[6] = {'L','o','g',' ','O','N'};
u08 LOG_Mode_0[4] = {'L','o','o','p'};
u08 LOG_Mode_1[4] = {'S','t','o','p'};
#define MAX_COMMAND_LENGHT 0x5F // (+5 de la cabecera = 0x5f)
// Buffer of entrance and exit
u08 buffer[MAX_COMMAND_LENGHT];
// This is just an experiement!
u08 ProviderCount = 0x00;
// current Provider, currentKey & current Channel for info mode
u08 currentProvider = 0x01;
u08 currentKey = 0x00;
// PPV auto - with CapturePPVEvent now watching for lack of 3c\3a receipt
// i.e. Porn, this should then default to using SelectSelect mode.
//u08 CapturePPVEvent = 0x00;
u08 EventUpdatedin3C = FALSE;
u08 OldStylePPV = FALSE;
// Data for the Inst 0x0A: Operating system of the card
#define TOTAL_VERSION 68
u08 version[TOTAL_VERSION]= {
0x61,0x19,0xad,0xca,0x15,0x2f,0x10,0x03,
0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x9E,
0xB9,0xDF,0x34,0x94,0xEF,0x3E,0x00,0x13,
0x3A,0x57,0x12,0x53,0x84,0x1A,0xD5,0x90,
0x14,0x10,0x31,0x2C,0xDA,0xC8,0xAD, '5',
'4' ,'=' ,'-' ,0x00 };
//u08 gribomatic[16] = {'G','-','o','-','M',' ','V','3',
// 'x','x',' ','(','N','A',')',' '};
u08 gribomatic[16] = {0x9B,0x65,0xBB,0x32,0x07,0x10,0xF2,0x32,
0x36,0xB4,0xD4,0xCC,0x86,0x2B,0xB5,0x1D};
// Encrypted strings you easy use :)
// If nothing else it should stop Mr PurpleHaze
// Standard version 3 -> 0x9B,0x65,0xBB,0x32,0x07,0x10,0xF2,0x32,
// Beta\private version 3 -> 0x8E,0xDA,0xB3,0xFC,0xB0,0x6E,0x98,0x13,
// 353 string -> 0x14,0xCC,0x61,0xF4,0xE6,0x84,0x07,0xC9};
// 354 string -> 0x36,0xB4,0xD4,0xCC,0x86,0x2B,0xB5,0x1D};
// PPV BX record, generate event and session details on the fly....
u08 ppv_record[14] = {0xB1,0x00,0xFF,0xFF,0x01,0xFE,0x05,0x00,0x00,0xFF,0xFF,0x00,0x00,0x04};
// Record last requested in 0x34,0x32 pair
//u08 ppv_request[2] = {0x00,0x00};
#define EVENT_ID1 2
#define EVENT_ID2 3
#define SESSION_ID 4
#define SESSION_DATE1 9
#define SESSION_DATE2 10
// Punteros a las funciones de comunicación
void (*ptrSend)(u08);
u08 (*ptrReceive) (void);
// stores the last processed instruction
u08 lastInst = 0x00;
// Only show my info if last command was not a 3c or 3a request
u08 LastNonProviderInst = 0x00;
// Allows to use phoenix to make operations of external I/O eeprom.
u08 support_phoenix = TRUE;
// PAra the cloqueo of ticket offices
u08 decodeX = FALSE;
u08 needPin = TRUE;
u08 pinChecked = FALSE;
// Answer to Reset
// It indicates that the card is a version 4,1 (original FoM 4.0)
u08 ATR[16]={0x3B,0xF7,0x11,0x00,0x01,0x40,0x96,0x58,
0x42,0x14,0x0E,0x6C,0xB6,0xD6,0x90,0x00};
// key in use (PK + SK)
u08 Key[8+8];
// hash-buffers for the verification of the signature
u08 hash[8];
u08 initial_hash[8];
// ControlWords desencriptadas para la 0x3A
u08 CW[8+8];
// command sent by 0x34 and 0x38
u08 Comando34[5];
// status bytes
u08 sw1=0x90,sw2=0x00;
// PPV Cache vars
u08 NextEvent=0;
u08 lLastProvider=0;
u08 CommandCountDown=60;
u08 EventInCache(u08 evnt1, u08 evnt2)
{
u08 i;
for (i=0; i<32; i=i+2){
if (evnt1==version[i] && evnt2==version[i+1]){
// Event is known :)
return 1;
}
}
return 0;
}
void AddPPVEvent(u08 evnt1, u08 evnt2)
{
if (!EventInCache(evnt1,evnt2)){
// Move the event marker onwards
version[NextEvent++]=evnt1;
version[NextEvent++]=evnt2;
// Start to overwrite from the start once again
if (NextEvent>31){
// Back to the start
NextEvent=0;
}
}
}
void IncrementECMCount(u08 inst)
{
// Only increment ECM count when card has been initalised in the STB
if (!support_phoenix){
ECM_LastECMInst = inst;
if (ECM_Count_Low==0xff){
if (ECM_Count_High<0xff){ECM_Count_High++;}
ECM_Count_Low=0x00;
} else
ECM_Count_Low++;
}
}
void sendString(u08 *str, u08 len)
{
do { (*ptrSend)(*str++); } while (--len);
}
void receiveString(u08 len)
{
u08 *dst=buffer;
do { *dst++ = (*ptrReceive)(); } while (--len);
}
void fillBuffer(u08 begin_idx ,u08 end_idx, u08 fillByte)
{
u08 cnt;
for (cnt=begin_idx; cnt<end_idx; cnt++)
buffer[cnt]=fillByte;
}
void _memcpy(u08 *dst,u08 *src,u08 n)
{
while(n){
*dst=*src;
dst++;
src++;
n--;
}
}
u16 getProvAddr(u08 p1)
{
u16 res;
p1 &= 0x0f;
for (res = EE_ENTETY_0; p1; p1--)
res += EE_ENTETY_SIZE;
return res;
}
u16 getPKAddr(u08 p1, u08 p2)
{
u16 key_offset = getProvAddr(p1) + EE_ENT_KEY_0;
//key_index*=8, at908515 opt, lose the bit 7 (superencription)
p2 <<= 1; p2 <<= 1; p2 <<= 1;
return (key_offset + p2);
}
void decode(u08 p2, u08 len)
{
u08 *src=buffer;
if (p2&0x80){
while (len>8){
decrip(Key,src);
len-=8;
src+=8;
}
}
}
void getKey(u08 p1, u08 p2)
{
u16 key_offset=getPKAddr(p1,p2);
ee_readString(Key,key_offset,8);
ee_readString(Key+8,(p1&0x10)?key_offset+(16*8):key_offset,8);
}
u08 xor_hash(u08 len, u08 r)
{
u08 cnt;
decrip(Key,hash);
len-=r;
for (cnt=0; cnt<r; cnt++)
hash[cnt]^=buffer[len+cnt];
return len;
}
u08 signaturePresent(u08 siglen)
{
// Grib - Length has to be at least 9 (82 plus sig)
if (siglen>0x08){
if (buffer[siglen-0x09]==0x82){
// Signature is present
return 1;
}
}
// Too short of signature missing
return 0;
}
u08 signatureCheck(u08 p1, u08 len)
{
u08 cnt;
u08 resto=len&7;
u16 addr;
// Grib - Length has to be at least 9 (82 plus sig)
if (!signaturePresent(len)){
return 0;
}
//if (len<9)
// return 0;
len-=8; // indice al nano 0x82
//if (buffer[len-1]!=0x82)
// return 0;
_memcpy(hash,buffer+len,8);
// I calculate inverse of the company/signature
if (resto){
len=xor_hash(len,resto);
}
while (len>0){
len=xor_hash(len,8);
}
// To calculate initial hashbuffer
for (cnt=0; cnt<8; cnt++){
initial_hash[cnt]=0;
}
addr=getProvAddr(p1) + EE_ENT_PPUA;
p1&=0xE0;
if (p1==0x20){
// UA + 00 00
ee_readString(initial_hash, EE_NUM_TARJETA,6);
} else if (p1==0x40){
// PPUA + 00 00 00 00
ee_readString(initial_hash,addr,4);
} else if (p1==0x60){
// SA + 00 00 00 00 00
ee_readString(initial_hash,addr,3);
}
// If hash signs correct - > calculated buffer = hash initial buffer
for (cnt=0; cnt<8; cnt++){
if (initial_hash[cnt]!=hash[cnt])
return 0;
}
return 1;
}
void updateKey(u08 idx, u08 p1, u08 sk)
{
u16 addr;
// to desencriptar the key
_memcpy(CW,&buffer[idx+2],8);
decrip(Key,CW);
// to calculate direction
addr=getPKAddr(p1,(buffer[idx+1]&0x0F));
addr=sk?(addr+(16*8)):addr;
// to update if it is different from the stored one
ee_updateString(addr,CW,8);
}
u08 keyExist(u08 p1, u08 p2)
{
// 0x00 if the key does not exist
// 0x50 if only PK
// 0xf0 if also SK (note: the PK can be 8*0x00)
u08 cnt,res=0x00;
// Cargar Pk&Sk
getKey(p1|0x10,p2);
for (cnt=0; cnt<16; cnt++){
if (Key[cnt]){
if (cnt<8)
res=0x50;
else res=0xf0;
}
}
return res;
}
u08 nibble2ascii(u08 nibble)
{
// Changed to go lower case for the 'keylog' stuff later on
return (nibble<0x0a)?(nibble+'0'):(nibble+('a'-0x0a));
}
void byte2ascii(u08 value, u08 idx)
{
u08 *dst=&buffer[idx];
*dst++=nibble2ascii(value>>4);
*dst=nibble2ascii(value&0x0f);
}
void antipurple(u08 offset, u08 repeat)
{
u08 i;
// Antipurple decrypts the contents in the buffer
// at a given offset x the number of 8byte blocks
for (i=0; i<16; i++){
Key[i]=i%0x0d;
}
for (i=0; i<repeat; i++){
decrip(Key,buffer+(offset+(8*i)));
}
}
#ifdef MODO_LOG
#include "log.h"
#endif
void setupInfo(u08 p1, u08 p3)
{
u16 addr;
u08 i; //j,n;
if (p1!=++ECM_LastProviderChecked){
// Not in sequence!
LastNonProviderInst=0x12;
}
// Check provider index ANTI-ECM method
if ((p1 & 0x0F)>=ProviderCount && currentKey && (LastNonProviderInst!=0x3a || p3!=0x18)){
// We are faking the number of providers.
LastNonProviderInst=0x12;
sw2=0x04;
return;
}
// Stick in the real provider details
addr = getProvAddr(p1);
// Ident
ee_readString(buffer,addr,2);
// To fill up with spaces field names
fillBuffer(2,(2+16),0x20);
//addr = getProvAddr(CurrentProvider);
// PPUA + Date
ee_readString(buffer+(2+16),addr + EE_ENT_PPUA, 4+2);
// Grib - adding region to the return
ee_readString(buffer+(23+1),addr + EE_ENT_REGION,1);
p1&=0x0f;
if (p1==0x00 || LastNonProviderInst!=0x3a || p3!=0x18){
LastNonProviderInst=0x12;
// Provider name in buffer[2..18]
ee_readString(buffer + 2, addr + EE_ENT_NAME, 16);
// PPUA + Date
// done above -> ee_readString(buffer+(2+16),addr + EE_ENT_PPUA,4+2);
if (!p1){
// Just clear the seca date....
_memcpy(buffer+(2+16+4+1),0x00,1);
}
} else
if (p1==0x01){
_memcpy(buffer+(2),gribomatic,16);
// Need to decrypt the my key now.... waster mr PurpleHaze
antipurple(2,2);
// Display the current Opkey
byte2ascii(currentKey,14);
// And the method of PPV
buffer[17]=(OldStylePPV)?'M':'A';
} else
if (p1==0x02){
// Use provider 2 for event and custWP :)
_memcpy(buffer+(2),EVENT_Display,12);
//antipurple(2,2);
byte2ascii(ee_read(getProvAddr(currentProvider)+(EE_ENT_PPUA + 3)),6);
byte2ascii(ppv_record[EVENT_ID1],14);
byte2ascii(ppv_record[EVENT_ID2],16);
} else
if (p1==0x03){
// Use provider 3 as a general ECM display :)
_memcpy(buffer+(2),ECM_Display,12);
//antipurple(2,2);
byte2ascii(ECM_LastECMInst,6);
byte2ascii(ECM_Count_High,14);
byte2ascii(ECM_Count_Low,16);
} else
if (p1==0x04){
// Bit of a KeyLog rip off, show only the opkey
// that is not in use :p
if (modo_log){
_memcpy(buffer+(2),LOG_ON,6);
if (LOG_Method){
// Loop at end of eeprom
_memcpy(buffer+(9),LOG_Mode_1,4);
} else {
// Stop at end of eeprom
_memcpy(buffer+(9),LOG_Mode_0,4);
}
} else {
if (currentKey==0x0c){
addr=getPKAddr(currentProvider, 0x0d);
} else {
addr=getPKAddr(currentProvider, 0x0c);
}
for(i=0; i<8; i++){
byte2ascii(ee_read(addr + i),2+2*i);
}
}
} else {
// Provider name in buffer[2..18]
ee_readString(buffer + 2, addr + EE_ENT_NAME, 16);
}
}
u08 cardHasExpired(u08 p1, u08 nano_idx, u08 TestDate)
{
u08 expdate_h,expdate_l;
u08 actdate_h,actdate_l;
u08 *ptr;
u16 addr;
// get card expiration date
addr=getProvAddr(p1) + EE_ENT_SUBS_DATE;
expdate_h=ee_read(addr);
expdate_l=ee_read(addr+1);
// get ECM or EMM command date
ptr=&buffer[nano_idx];
actdate_h=*(ptr+1);
actdate_l=*(ptr+2);
// Do we want to check the boundery of the date?... ECM check
if (TestDate){
if (!(actdate_h<expdate_h)){
// Check out the difference between the dates
addr=((actdate_h-expdate_h)*0xff)+(actdate_l-expdate_l);
if (addr>=0x00){
return 1;
}
}
return 0;
}
// else we just see if the card has expired
return (actdate_h>expdate_h || (actdate_h==expdate_h && actdate_l>expdate_l));
}
u08 isCustWPActive(u08 nanof0_idx, u08 custwp)
{
return rightShift(buffer[(nanof0_idx + 32) - rightShift(custwp,3)],custwp&7)&1;
}
u08 TestKey(u08 idx, u08 p1, u08 sk)
{
u16 addr;
u08 res;
// Not the current OpKey so ignore..
// default to bad update until we know better
res=0;
if ((buffer[idx+1]&0x0F)==currentKey){
// to decypt the key
_memcpy(CW,&buffer[idx+2],8);
decrip(Key,CW);
// to calculate base address of the key
addr=getPKAddr(p1,(buffer[idx+1]&0x0F));
addr=sk?(addr+(16*8)):addr;
// Return 1 if already set (this is the "good" result)
res = mem2eeprom_cmp(addr, CW, 8);
//res=ee_TestString(addr,CW,8);
}
return res;
}
u08 processNanos(u08 p1,u08 ECMorEMM, u08 TestOnly)
{
// Current Nano command
u08 nano;
// Position with "buffer"
u08 idx=0;
// Preview PPV or PBM check will activate
u08 rightsAdquired = 0;
// Does more or less the same as rights Aquired!
u08 nanos_13_31 = 2;
// Nbr of nanos processed, returned as part of error in 3c if required
u08 pnanos = 0;
// Store address of target provider
u16 addr;
// Disable porn channels, going via the parental warning nano
u08 nano_2c = 1;
// Flag checks if a d1 nano was present in an ECM
u08 invalid_ECM=0;
// Reused var... various
u08 cnt;
u08 aux1;
u08 aux2;
// Set initial value for 3c check to 1 for ECM
if (ECMorEMM==kECM){
invalid_ECM=1;
//EventUpdatedin3C=FALSE;
}
// Get provider address once outside loop :)
addr = getProvAddr(p1) ;
while (1){
nano = buffer[idx];
// Less flash space to load here instead of references later.
aux1 = buffer[idx+1];
aux2 = buffer[idx+2];
if (nano==0x82){
// ECM 3-Mar-2002
// They are sending through signed 3c instructions
// that do not contain valid nanos
if (TestOnly){
if (!invalid_ECM){
sw2=0x09;
}
return invalid_ECM;
}
if (invalid_ECM){
sw1 = 0x96; sw2 = pnanos;
return 0;
}
pnanos++;
return pnanos;
} else
// ECM nanos - - - - - - - - - - - - - - - - - - - - - - - - - - -
if (ECMorEMM){
// nano 04 : give dw for output OK
// nano 12 : parental control protection ADDED
// nano 13 : verify channel id with provider bitmap package OK
// nano 15 : PPV special management ADDED
// nano 19 : PPV preview control OK
// nano 27 : delete old PPV preview records OK
// nano 2C : PPV tokens management OK
// nano 2D : delete old PPV event records ADDED
// nano 31 : verify PPV event id, diffusion number and vision number OK
// nano 82 : signature OK
// nano D1 : control word to decrypt OK
// nano F1 : bitmap regional code OK
if ((nano==0x04 || nano==0x19) && !rightsAdquired){
// free the channel
if (nano==0x19){sw2=0x27;}
rightsAdquired = 1;
pnanos++;
} else
if (nano==0x13 && !rightsAdquired && nanos_13_31){
// test channel boundle identifier
u08 pbm,bid;
if ((bid=aux1)<64){
//addr=getProvAddr(p1) + (EE_ENT_PBM + 7) - rightShift(bid,3);
//pbm=ee_read(addr);
pbm=ee_read(addr + (EE_ENT_PBM + 7) - rightShift(bid,3));
if (rightShift(pbm,bid&7)&1){
RED_INFO_LED_OFF;
rightsAdquired=1;
}
}
pnanos++;
} else
if (nano==0x12 || nano==0x2d){
pnanos++;
} else
if (nano==0x15){
if (nanos_13_31>0x01){
sw1=0x96; sw2=0;
return 0;
}
pnanos++;
} else
if (nano==0x27 && !rightsAdquired){
// test card expiration date
pnanos++;
// Check for not a Null value in the 0x27
if (aux1|aux2){
if (cardHasExpired(p1,idx,FALSE)){
sw1=0x93; sw2=0x01;
return 0;
}
ppv_record[SESSION_DATE1] = aux1;
ppv_record[SESSION_DATE2] = aux2;
}
} else
if (nano==0x2c && !rightsAdquired){
// x channel
// No pin of perv channels,
if ((aux1|aux2)==0){ // (buffer[idx+1]==0 && buffer[idx+2]==0){
// Null event!
sw1=0x96; sw2=0;
return 0;
}
nano_2c = decodeX;
nanos_13_31--;
} else
if (nano==0x31 && !rightsAdquired && nanos_13_31){
// Check that the PPV event matches the last PPV record
// request offered in the 32/34
if ((aux1|aux2)==0){ // (buffer[idx+1]==0 && buffer[idx+2]==0){
// Null event!
sw1=0x96; sw2=0;
return 0;
}
// Now if the event is in the cache it is bad!
if (CommandCountDown || EventInCache(aux1,aux2)){ // ((ppv_request[0]!=buffer[idx+1] || ppv_request[1]!=buffer[idx+2]) && (!EventInCache(buffer[idx+1],buffer[idx+2]))){
sw2=0x1a;
} else {
ppv_record[SESSION_ID] = buffer[idx+3];
// Add the captured event ID... need to test further!
ppv_record[EVENT_ID1] = aux1;
ppv_record[EVENT_ID2] = aux2;
// Flag for the 34 to determine if an event was received
// EventUpdatedin3C=TRUE;
}
// No longer it is necessary to verify 0x13, 0x31
nanos_13_31--;
pnanos++;
} else
if (nano==0xD1){
pnanos++;
if ((rightsAdquired || !nanos_13_31) && (nano_2c)){
u08 *ptr;
ptr=&buffer[idx+1];
decrip(Key,ptr);
decrip(Key,ptr+8);
_memcpy(CW,ptr,16);
// Contains control word :)
invalid_ECM=0;
} else{
// rights no adquired
sw1=0x93; sw2=0x02;
return 0;
}
} else
if (nano==0xf1){
// Region nano, purpose not really understood... at least by me....
pnanos++;
//addr=getProvAddr(p1) + EE_ENT_REGION;
// Can reuse the custWP check for region check, they
// perform the same actual bit check
if (!isCustWPActive(idx, ee_read(addr + EE_ENT_REGION))){
//IncrementECMCount(0xf1);
sw1=0x93; sw2=0x05;
return 0;
}
}
} // end of ECM nanos
// EMM nanos - - - - - - - - - - - - - - - - - - - - - - - - - - -
else {
// nano 01 : set nano 24 flag to FF
// nano 02 : set nano 24 flag to 00
// nano 03 : delete pin code
// nano 10 : delete given key (primary and secondary)
// nano 11 : delete seca record of a given type
// nano 17 : write regional bitmap
// nano 18 : delete service preview record
// nano 1D : set 8022 eeprom location
// nano 1E : set 8020 eeprom location
// nano 1F : set 8021 eeprom location
// nano 21 : set expiration date
// nano 22 : verify expiration date
// nano 23 : add new provider
// nano 24 : apply next nanos to given provider
// nano 25 : delete given provider
// nano 26 : modify provider space for records and flags
// nano 28 : delete a ppv preview record
// nano 30 : store special credits in ppv credits record
// nano 32 : seek or create record for a given event-id
// nano 33 : create or modify service preview record
// nano 40 : delete ppv event record with event-id between min-max
// nano 41 : set PPUA
// nano 42 : store data and new credits in ppv credits record
// nano 43 : update data and add credits in ppv credits record
// nano 80 : set provider bitmap package
// nano 82 : signature
// nano 87 : set provider data for ins 44
// nano 90 : write primary key
// nano 91 : write secondary key
// nano B0 : store seca record of a given type
// nano D0 : change provider name
// nano F0 : verify CUSTWP
if (nano==0x17 && !TestOnly){
// Grib - Region code update
// addr=getProvAddr(p1) + EE_ENT_REGION;
// Store the region code.
ee_write(addr + EE_ENT_REGION,aux1);
} else
if (nano==0x21){
// Check to see if we are just checking out the EMM instruction
if (TestOnly){
if (!cardHasExpired(p1,idx,TRUE)){
sw2=0x09;
return 0;
}
} else {
// update expiration date
//addr=getProvAddr(p1) + EE_ENT_SUBS_DATE;
ee_updateString(addr + EE_ENT_SUBS_DATE,&buffer[idx+1],2);
pnanos++;
}
} else
if (nano==0x22 && !TestOnly){
// test card expiration date
if (cardHasExpired(p1,idx,FALSE)){
sw1=0x93; sw2=0x01;
return 0;
}
} else
if (nano==0x41 && !TestOnly){
// update PPUA
//addr=getProvAddr(p1)+ EE_ENT_PPUA;
if (ee_updateString(addr + EE_ENT_PPUA,&buffer[idx+1],4)){
sw2 = 0x19; // 90 19
}
} else
// nano 80 : set provider bitmap package
if (nano==0x80 && TestOnly){
// update PBM 8 bytes
pnanos=0;
for(cnt=0; cnt<8; cnt++){
if (buffer[idx+1+cnt]){
pnanos++;
}
}
// If PBM is being reset then ignore packet
if (!pnanos){
sw2=0x09;
return 0;
}
} else
if (nano==0x90 || nano==0x91){
// update primary or secondary key
if (TestOnly){
if (TestKey(idx,p1,nano&0x01))
invalid_ECM=1;
} else {
updateKey(idx,p1,nano&0x01);
}
} else
if (nano==0xF0 && !TestOnly){
// CustWP-Bitmap
//u08 custwp;
//addr=getProvAddr(p1)+(EE_ENT_PPUA + 3);
//custwp = ee_read(addr+(EE_ENT_PPUA + 3));
// Should reuse vars like this but want the extra space
pnanos = ee_read(addr+(EE_ENT_PPUA + 3));
if (!isCustWPActive(idx, pnanos)){ // if (!isCustWPActive(idx, custwp)){
// If this assets and are not different from zero -> 90 09
cnt = 0x00;
//custwp = 0xff;
pnanos = 0xff;
do{
cnt++;
if (isCustWPActive(idx,cnt)){
// Found an Active CustWP! Updating Ppua!
ee_write(addr+(EE_ENT_PPUA + 3),cnt);
// it ignites red LED, was extinguished in proxima 0x3c
RED_INFO_LED_ON;
//custwp=cnt;
pnanos=cnt;
}
} while (cnt!=pnanos); //(cnt!=custwp);
}
} // end of nano f0
} // end of EMM nanos
// next nano
nano>>=4;
if (nano>0xC) nano=(nano-0x0b)<<3;
idx+=(nano+1);
}
}
// Combined the sign prepares from 38, 3c and 40 Instructions
// saves around 50 odd bytes :)
u08 PrepareSigCheck(u08 p1, u08 p2, u08 p3, u08 checkMK)
{
u08 tmp;
// 13-Apr-2002,
// If not super encrypted then need to check a signature is supplied first!
if (!(p2&0x80)){
// Not encrypted, check signature presence
if (!signaturePresent(p3)){
sw2=0x02;
goto PrepFailed;
}
}
// 17-Apr-2002, to verify that it uses MK
if (checkMK && (p2&0x0f)>0x0b){
sw2=0x13;
goto PrepFailed;
}
// it verifies existence of keys
tmp = keyExist(p1, p2&0x0f);
if (tmp==0x00){
// It does not exist key primary 90 1D
sw2=0x1D;
goto PrepFailed;
} else
if (tmp==0x50 && (p1&0x10)){
// It does not exist key secondary 90 1F
sw2=0x1F;
goto PrepFailed;
}
// decrypt buffer before continueing
getKey(p1,p2);
decode(p2,p3);
// Return 0 for OK... caller will jmp to TX_Data on anything else
return 0;
PrepFailed:
return 1;
}
// Secoms construction of 06 record returns.... how complicated!
// Append Key Index and trailer for Primary\Secondary keys
u08 *ConstructKeyRegistry(u08 tipo,u08 Prov,u08 *lista){
if ((tipo&0xf0)==0xf0){ // Si tenemos la primaria y secundaria
*lista++=tipo;
*lista++=0x80|Prov;
*lista++=0x50|(tipo&0x0f);
*lista++=0xc0|Prov;
} else if ((tipo&0x50)==0x50) {// Si tenemos solo la primaria
*lista++=tipo;
*lista++=0x80|Prov;
}
return lista;
}
// Build a list (using log buffer) of all the records on the card
void ConstructEEpromList(u08 ndrProviders){
// It is used to store the list, the table that contendra the instruction to do log (to save space)
// The list this structured of the following form:
// A registry is of two bytes reason why to correctly cross it habra that to jump of two in two
// The first field contains the type of registry and the second is the descriptive Byte
// Each registry of this table identifies to one virtual one in eeprom.
// The order of the registries is not accidental, this fact asi despues to analyze a pile of original cards
u08 *punt1=&log_buffer[2], ind1, ind2;
// REGISTRIES RECORDS
*punt1++=0x01; // First type of record STARTUP
*punt1++=0xe0;
*punt1++=0; // Second type of record PPV
*punt1++=0xe0;
punt1=ConstructKeyRegistry(keyExist(0,0),0,punt1); // Registries of mks 00
*punt1++=0x02; // Date of Activation of card
*punt1++=0xe0;
// Extract the PBM and Keys for all the providers
for (ind1=0;ind1<=ndrProviders;ind1++){
// PBM of the supplier, single if it is not empty
if (ind1){
*punt1++=0;
*punt1++=0x90|ind1;
}
// Loop through for current provider build list of keys in use!
for (ind2=(ind1)?0:1;ind2<16;ind2++){
punt1=ConstructKeyRegistry((keyExist(ind1,ind2)|ind2),ind1,punt1);
}
/* For the moment don`t want to support the PPV returns :)
if (ind1) { // Registries PPV, Single if not empty
*punt1++=0x0; // Registry of Credit PPV of the Supplier
*punt1++=0xd0|ind1;
*punt1++=0x0; // A registry of Event PPV anyone
*punt1++=0xb0|ind1;
}
*/
}
*++punt1=0xff; // End of list
}
// End of Secom 06 record construction!
// info en KeyLeds
void LED_Display(void)
{
// keyleds:
// - 0: always off (low power supply decos) (PIN:9999)
// - 1: show operation key in use (PIN:9998)
// - 2: show current provider index (PIN:9997)
u08 keyleds = 0x00;
keyleds = ee_read(EE_KEYLEDS + Extra_Funcard_Space);
if (keyleds==0){
outp(0x0F,PORTD);
} else if (keyleds==1){
outp(~(currentKey),PORTD);
} else if (keyleds==2){
outp(~(currentProvider),PORTD);
}
}
int main(void)
{
u08 *ptrAux; // Pointer used by secom code
u16 addr_prov; // Store the address of the current provider
u08 inst=0,p1=0,p2=0,p3=0;
u08 numProviders;
// Don`t really need a dedicate var for this
//u08 cla=0;
u08 lastprovider=0;
u08 ind=0;
u08 aux1=0;
u08 aux2=0;
// Number of complete registry inst 32 interations
u08 RegActual=0;
// Desactiva el comparador analogico :P
sbi(ACSR,7);
// Configura Puertos B y D
// El puerto B :
// - leds de colores (pins 2,3,4)
// - i/o (pin 6)
outp(0x1C,DDRB); // 0b00011100
outp(0x1C,PORTB); // 0b01011100
// El puerto D :
// - KeyLeds (pins 0,1,2,3)
outp(0x0F,DDRD); // 0b00001111
outp(0x0F,PORTD); // 0b00001111
// init eeprom externa
/*-----------------------------------------------------------------------------
| Detección modo Apollo:
|
| The state of bit 7 is verified and bit 5 of port B. If the 7 are to 0 and
| the 5 to 1, somebody to them has changed (FunStudio) - > Apollo way
|
+------------------------------------------------------------------------------------*/
if(0x80 == (inp(PINB) & 0xA0))
{
sbi(DDRB,6);
sbi(PORTB,6);
RED_INFO_LED_ON;
ptrSend = &SendA;
ptrReceive = &ReceiveA;
cbi(PORTB,6);
}
else
{
// Modo Phoenix
ptrSend = &Send;
ptrReceive = &Receive;
// Enviamos ATR
ORANGE_INFO_LED_ON;
sendString(ATR,16);
ORANGE_INFO_LED_OFF;
// Send(0x90);
// Send(0x00);
}
extee_init();
// Populate the offset value depending on the type of eeprom we have in use.
ee_SetEEPromSize();
// Load the number of providers from the eeprom
numProviders = ee_read(EE_NUM_ENTETIES) - 1;
// Now loading OldStyle PPV setting from ext eeprom config
OldStylePPV = !ee_read(EE_FULLAUTO);
// Load the log style they want to use
LOG_Method = ee_read(EE_LOGMETHOD);
// Load up the number of providers to return when asked
ProviderCount = ee_read(EE_PROVIDER_CNT);
// Put an upper limit on the provider count to stop
// users setting to higher than available!
if (ProviderCount>numProviders){ProviderCount=numProviders + 1;}
// For the decos without PIN It allows to block channels X
decodeX = (ee_read(EE_FLAGS) & FLG_BLOQUEAR_TX);
#ifdef MODO_LOG
// Is AutoLog enabled?... hate it myself but.....
modo_log = ee_read(EE_FLAGS) & FLG_AUTOLOG;
// Set the start point in the ee_ to start the log
leer_config_log(numProviders);
#endif
while (1){
// Decrement the command counter (bad PPV enent cache)
if (CommandCountDown){CommandCountDown--;}
// status word by default
sw1=0x90;
sw2=0x00;
GREEN_INFO_LED_OFF; // 'busy' led
// Using a temp var for class... no need to retain
ind=(*ptrReceive)(); // C1 en SECA
GREEN_INFO_LED_ON; // 'busy' led
inst=(*ptrReceive)(); // Instruction
p1=(*ptrReceive)(); // parameter 1
p2=(*ptrReceive)(); // parameter 2
p3=(*ptrReceive)(); // Length of command
// Check class in temp var
if (ind!=0xC1){
// Class not supported: 6E 00
//lastInst=0;
sw1=0x6E;
goto TX_Data;
}
if (inst&1){
// The first bit of inst must be zero
sw1=0x6D;
lastInst=0;
goto TX_Date_MPSkip;
}
if ((!p3 && inst&2) || p3>MAX_COMMAND_LENGHT){
// Length of incorrect entrance: 67 00
sw1=0x67;
lastInst=0;
// Do not send back data for invalid length
p3=0;
goto TX_Date_MPSkip;
}
// Check p3, we do not send an ack for anything without length!
if (p3)
// Return ACK
(*ptrSend)(inst);
if (inst&2){
// CARD->CAM
fillBuffer(0,MAX_COMMAND_LENGHT,0xFF);
} else {
// CAM->CARD
if (p3)
receiveString(p3);
#ifdef MODO_LOG
// alvamos the buffer for log
_memcpy(&log_buffer[5],buffer,p3);
#endif
}
/*-----------------------------------------------------------------------------
| In principle, treating this possibility does not have here to produce problems
| With !support_phoenix we made sure to be able to send all the directions
| it stops INS 20 y 22
+-----------------------------------------------------------------------------*/
// Check provider index, not applicable to serial request.
if (((p1 & 0x0F) > numProviders && inst!=0x0e) && (!support_phoenix)){
// supported supplier not 90 04
sw2=0x04;
goto TX_Data;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// INSTRUCTION 0x34: Specification of the Request of Data
if (inst==0x34){
// Sólo soportamos dos peticiones:
// 00 00 00 : Provider Package Bitmap Records
// 04 00 01 : SECA Startup Records
// The request is stored in Comando34
// Check that provider is within the limit
if ((p1&0x0F)>ProviderCount){
// Need to validate supplier index
sw2=0x04;
goto TX_Data;
}
if (p3!=3){
// Incorrect length of the entrance: 67 00
sw1=0x67;
goto TX_Data;
}
_memcpy(Comando34,buffer,3);
//lastInst=inst;
} else
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// INSTRUCTION 0x32: Request of Data
// INSTRUCTION 0x36: As per 0x32 but with additional options
// 2Fh=d4 30h=d5 87-8Eh=a1..a8
if (inst==0x32 || inst==0x36){
/*
; Ins 32 : output data requested
; data from ins 34 d1 = 29h d2 = 2Dh d3 = 2Eh
; d1 d2 d3
; 0 0 0 Provider package bitmap record C1 32 xx 00 0A 83 data 04
; 1 0 0 Provider PPV credits record C1 32 xx 00 0A 84 data 04
' 2 ....... a check on something??
; 3 x x Provider PPV event record C1 32 xx 00 0D B1 data 04
; 4 0 x Seca record C1 32 00 00 0D B1 data 04
; 6 x x Given record (number) C1 32 xx 00 12 D2 data 03
*/
// Store the command 34 stuff into vars, takes a little less
// space than references in the code
ind = Comando34[0];
aux1 = Comando34[1];
aux2 = Comando34[2];
if (p2){
// incorrect value of p2 (p2!=0) 94 02
sw1=0x94;
sw2=0x02;
goto TX_Data;
// Check last instruction was a 36 or 38
} else if (lastInst!=inst && lastInst!=0x38 && lastInst!=0x34){
sw2=0x14;
goto TX_Data;
} else if (inst==0x36){
// ins 36 error in parameter P1
if (lastprovider!=p1){
sw1=0x94; sw2=0x01;
goto TX_Data;
}
} else {
// Works on a MOSC but not documented...
if (ind==0x02 && (lastprovider)){
sw2=0x15;
goto TX_Data;
}
}
// Default for returned records is 0x04
buffer[0]=0x04;
// Command 00 - - - - - - - - - - - - - - - - - - - -
if (ind==0x00){
// Command 00
// Data: 00 00 -> Provider Package Bitmap Records
if (p3<0x0A){
// It does not fit, to send 0x03
buffer[0]=0x03;
} else if (p1){
// ok, all except SECA
buffer[0]=0x83;
ee_readString(buffer + 1, getProvAddr(p1) + EE_ENT_PBM, 8);
buffer[0x0A-1]=0x04;
}
} else if (ind==0x01){
if (p3<0x0A){
// It does not fit, to send 0x03
buffer[0]=0x03;
}
} else if (ind==0x03){
// Command 03
// Data: xx xx -> Provider PPV Records (xx xx = EventID)
if(p3<0x0e){
buffer[0] = 0x03;
} else {
// buffer[0]=0x04;
if (EventInCache(aux1, aux2) || CommandCountDown || p3!=0x20){
// Bad record
AddPPVEvent(aux1,aux2);
IncrementECMCount(inst);
} else {
// Store last PPV request, need to check the 31 nano in 3c
// to ensure they match
// Hoping for an auto purchase
//if (OldStylePPV || CapturePPVEvent>1 || EventUpdatedin3C){// || (ppv_record[EVENT_ID1]==Comando34[1] && ppv_record[EVENT_ID2]==Comando34[2])){
//if ((OldStylePPV || EventUpdatedin3C) && (ppv_request[0]==aux1 && ppv_request[0]==aux2)){
needPin = FALSE;
if (OldStylePPV || EventUpdatedin3C){
// needPin = FALSE;
ppv_record[EVENT_ID1] = aux1;
ppv_record[EVENT_ID2] = aux2;
// Return the BX record requested
_memcpy(buffer,ppv_record,14);
EventUpdatedin3C = FALSE;
} else {
EventUpdatedin3C=TRUE;
}
}
}
} else if (ind==0x04){
// Data: 00 00 -> SECA PPV Records
// 00 01 -> SECA Startup Records
// 00 02 -> SECA Records de Activación
// This one will not get caught by main increment
IncrementECMCount(inst);
// 12-Apr-2002, we have move the size check outside
// the check on record number
if (p3<0x0d){
// Not enough space for result! 0x03
buffer[0]=0x03;
// SECA Startup Records
} else {
// Only information on Seca p1=0 can be requested
if (aux2<=0x02 && !p1){
// Build the output record
buffer[0]=0xb2;
if (aux2==0x00){
ee_readString(buffer + 1, EE_SECA_PPVSTARTUP, 11);
} else {
if (aux2==0x01){
ee_readString(buffer + 1, EE_STARTUP_STR, 11);
} else {
ee_readString(buffer + 1, EE_SECA_ACTIVATE, 11);
}
}
buffer[0x0D-1]=0x04;
}
}
} else if (ind==0x06){
// If it is the first request to initialize the registry
// to the first item to send
if (lastInst==0x34) RegActual=aux2;
// We constructed the Virtual List of eeprom records (only need
// to build upto the current provider each time - required for
// record position information :()
ConstructEEpromList(p1);
// We initialized leader of construction of answer
aux2=0;
// Loop for construction of answer
while (1) {
// Memorizamos type of registry (RegActual*2)
ind = log_buffer[RegActual<<1];
// Description Memorizamos of Registry
aux1= log_buffer[(RegActual<<1)+1];
// If to the registries or the Supplier of the present
// Registry finished it is greater than the requested supplier
if ((aux1==0xff)||((aux1&0x0f)>(p1&0x0f))){
buffer[aux2]=0x04;
goto TX_Data;
}
// If the Supplier of the Present Registry is minor who the asked for supplier
if ((aux1&0x0f)<(p1&0x0f)){
RegActual++; // We increased I number of registry
continue; // We return to verify
}
// If the following registry does not fit in the answer message
if ((aux2+18)>p3){
buffer[aux2]=0x03;
goto TX_Data;
}
// First part of the answer
buffer[aux2] = 0xd2;
buffer[aux2+1]= 0;
buffer[aux2+2]= RegActual;
// We initialized this part of the answer to 0
fillBuffer(aux2+12,aux2+17,0x00);
// We assigned leader for saving of space
ptrAux = &buffer[aux2+3];
addr_prov = getProvAddr(p1);
// Following Part of the Answer depending on the type of registry to send
// SECA - PPV
if ((ind==0x00)&&(p1==0)) {
ee_readString(ptrAux, EE_SECA_PPVSTARTUP, 11);
// SECA - Start-up
} else if (ind==0x01) {
// We read startup record of eeprom
ee_readString(ptrAux, EE_STARTUP_STR, 11);
// SECA - Registry of activation of the card
} else if (ind==0x02) {
ee_readString(ptrAux, EE_SECA_ACTIVATE, 11);
// Registry of suppliers - Package BitMap (PBM)
} else if (((aux1&0xf0)==0x90)&&(p1)) {
*ptrAux=0x00;
// We read PBM of the supplier
ee_readString(&buffer[aux2+4],addr_prov + EE_ENT_PBM ,8);
// Registry of suppliers - Key
} else if (((ind&0xf0)==0xf0)||((ind&0xf0)==0x50)) {
*ptrAux=ind;
if (!currentKey){
addr_prov = getPKAddr(p1,ind&0x0f);
addr_prov = ((aux1&0xf0)==0xC0)?addr_prov+(16*8):addr_prov;
//if ((aux1&0xf0)==0xC0){addr_prov=addr_prov+8;}
// If no key in use then populate the key details too
ee_readString(&buffer[aux2+4],addr_prov,8);
}
/* For the moment don`t want to support the PPV returns :)
// Registry of suppliers - Credit PPV
} else if ((aux1&0xf0)==0xd0) {
// We initialized answer with 0x00
fillBuffer(aux2+3,aux2+13,0x00);
// PPV Credit handler not available in GoM!
//buffer[aux2+7]=fichasppv;
//buffer[aux2+8]=FechaRec[0];
//buffer[aux2+9]=FechaRec[1]-1;
// Registry of Suppliers - a Registry of Event PPV anyone
} else if ((aux1&0xf0)==0xb0) {
ee_readString(ptrAux, EE_SECA_PPVSTARTUP, 11);
// So that the events are not always equal
// PPV Credit handler not available in GoM!
//buffer[aux2+4]=FechaRec[0];
*/
}
buffer[aux2+14]=aux1; // Descriptive byte
aux2+=17; // We increased leader of construction of message in 1 registry
RegActual++; // We increased I number of registry by which we go
}
} else {
// A invalid record request always returns 0x03....
buffer[0]=0x03;
}
} else
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// INSTRUCTION 0x0E: Serial number of the card
if (inst==0x0E){
fillBuffer(0,2,0x00);
// I number of series this in SECA.UA
ee_readString(buffer + 2, EE_NUM_TARJETA, 6);
// Turn off the pheonix interface when the serial is requested
support_phoenix=0x00;
} else
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// INSTRUCTION 0x16: Enumeration of Suppliers
if (inst==0x16){
fillBuffer(0,6,0x00);
if (currentKey){
// This is for the euro boys :p
aux1=ProviderCount;
// This one will not get caught by main increment
IncrementECMCount(inst);
} else {
aux1=numProviders + 1; //number of suppliers + seca
}
buffer[2]=rightShift(0xff,16-aux1);
buffer[3]=rightShift(0xff,(aux1<8?(8-aux1):0));
} else
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// INSTRUCTION 0x12: ProviderID (Ident)
if (inst==0x12){
// Dont want to include this in the history!
setupInfo(p1,p3);
} else
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// INSTRUCTION 0x3C: ECM ControlWords encrypted
if (inst==0x3C){
// p1 = provider number & pk-sk
// p2 = key index & superencription
// AntiECM - need to clear CW incase 3c fails
//_memcpy(CW,version+(16),16);
needPin = TRUE;
pinChecked = FALSE;
currentKey=p2&0x0F;
// Grib, moved sigcheck prep to sub
if (PrepareSigCheck(p1,p2,p3,FALSE)){
goto TX_Data;
}
// Do the LED display if necessary
LED_Display();
if (signatureCheck(p1,p3)){
RED_INFO_LED_OFF;
processNanos(p1,kECM,FALSE);
// Store the current provider... if the key
// in use is a normal operational one
if (currentKey==0x0c || currentKey==0x0d){
currentProvider=p1&0x0F;
/*
if (currentProvider!=lLastProvider){
lLastProvider=currentProvider;
// Re-capture PPV events for this new provider
CommandCountDown=60;
}
*/
}
} else {
// 90 02: Signature fails
sw2=02;
RED_INFO_LED_ON;
}
} else
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// INSTRUCTION 0x3A: ECM ControlWords decrypted
if (inst==0x3A){
// Invalid command sequence
if (lastInst!=0x3C){
sw2=0x14;
goto TX_Data;
}
// enviar CW desencriptadas
_memcpy(buffer,CW,16);
// Clear the Provider info flag
ECM_LastProviderChecked=0x00;
} else
// INSTRUCTION 0x30: Transactions protected by PIN
if (inst==0x30){
/*
; C1 30 00 00 10 (old pin)(new pin) : insert/modify pin
; C1 30 00 01 09 (pin)(protection status 0/1) : modify pin protection status
; C1 30 00 02 09 (pin)(flags) : modify flags (6 bit)
; bit 0 - addressable bit 01 (20.1 not used)
; bit 1 - addressable bit 06 (20.6 override parental control protection)
; bit 2 - addressable bit 07 (20.7 ppv management)
; bit 3 - addressable bit 03 (20.3 ppv special management)
; bit 6 - addressable bit 00 (20.0 ppv management)
; bit 7 - addressable bit 08 (21.0 instruction protected flag)
;-------------------------------------------------------------------------------
*/
if (p1!=0x00 || p2>0x02){
sw2=0x10; // Invalid pin number.....
goto TX_Data;
} else if ((p2==0x00 && p3!=0x10) || ((p2==0x01 || p2==0x02) && p3!=0x09)){
// There is an incorrect len check on PIN change
sw1=0x67;
goto TX_Data;
}
/*
// Introduccion/modificacion de PIN
// - El PIN se almacena en eeprom externa.
// - Utilizo los dos ultimos bytes de la UA
// del proveedor con indice 1 (sigue a SECA).
if (buffer[14]==0x27){
// Apagar Keyleds?
if (buffer[15]==0x0f){
ee_write(EE_KEYLEDS + Extra_Funcard_Space,0);
}
// Keyleds muestran indice de la clave en uso
if (buffer[15]==0x0e){
ee_write(EE_KEYLEDS + Extra_Funcard_Space,1);
}
// Keyleds muestran indice del proveedor actual
if (buffer[15]==0x0d){
ee_write(EE_KEYLEDS + Extra_Funcard_Space,2);
}
} else
//if ((buffer[14]==PIN_INFO_H) && (buffer[15]==PIN_INFO_L))
//infoMode=!(infoMode);
*/
#ifdef MODO_LOG
// No need to supply provider anymore, reuses first call
// tratar_PINS_log( buffer[14], buffer[15], numProviders );
tratar_PINS_log(buffer[14], buffer[15]);
#endif
/*-----------------------------------------------------------------------------
| Bloqueo de taquillas oficial:
| Una vez que se bloquea una taquiila, el deco pedirá PIN a la hora de la
| compra aún cuando esa taquilla no esté bloqueada. En una taquilla bloqueada,
| lo pide 2 veces: a la hora de entrar en la taquilla y a la hora de la compra.
|
| Lo que intentamos es simular el bloqueo de taquillas evitando la petición del
| PIN, a la hora de la compra, si esa taquilla no está bloqueada. En una bloqueada
| lo seguirá pidiendo 2 veces.
|
| A la hora de realizar la compra o volver a una taquilla ya comprada, el deco no
| nos da datos suficientes para poder saber en que situación estamos. El sistema
| que hemos adoptado garantiza, al menos, una petición de PIN cuando se entre en
| una taquilla bloqueada, ya sea para el proceso de compra o si cambiamos a una
| taquilla bloqueada con un evento de compra ya activado. En contra partida, en alguna
| situación, puede darse el caso de que se pida PIN en el proceso de compra de una
| taquilla sin bloquear :-)
|
| Variables que controlan la situación:
| needPin : Se activa al inicio, en cada INS 3C, si se introduce in PIN correcto
| o si en la comprobación del PIN se encontraba sin activar needPIN o
| pinChecked.
| Se desactiva con la INS 32, comando 4 (compra PPV)
|
| pinChecked : Se activa si se introduce un PIN correcto o si en la comprobación
| del PIN se encontraba sin activar needPIN o pinChecked.
| Se desactiva al inicio y en cada INS 3C.
|
| Se comprueba el PIN si cualquiera de las dos variables se encuentran
| activas en el momento de la petición del mismo.
+------------------------------------------------------------------------------------*/
if ((pinChecked) || (needPin)){
if (mem2eeprom_cmp(EE_PIN + Extra_Funcard_Space,&buffer[14],2)==0){
// ultimo PIN validado = PIN almacenado ?
if (mem2eeprom_cmp(EE_PIN + Extra_Funcard_Space,&buffer[6],2)==1){
// modificación del PIN
ee_writeString(EE_PIN + Extra_Funcard_Space,&buffer[14],2);
}
else {
sw2=0x10; // no validar PIN: 9010
}
} else {
needPin = pinChecked = TRUE;
}
} else { // Aunque parezca mentira
needPin = pinChecked = TRUE; // esta línea ocupa -2 bytes !!??
} // fin comprobación pin
} else
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// INSTRUCTION 0x02: give 8 bytes of data as result from IN THE 0x04
if (inst==0x02){
if (lastInst!=inst && lastInst!=0x04){
// Last instruction had to be a 0x04 ... return 9014
sw2=0x14;
goto TX_Data;
}
// Return the encoded 8 bytes
_memcpy(buffer,hash,8);
} else
// INSTRUCTION 0x04: Supply 8 bytes for encryption using 0x0f key
if (inst==0x04){
// Return result of 04 request to encrypt using 0f (in p2) key
if (p3!=8){
// Length of incorrect entrance: 67 00
sw1=0x67;
goto TX_Data;
}
if (p2!=0x0f){
// Requesting using key other than 0x0f ... return 9021
sw2=0x21;
goto TX_Data;
}
getKey(p1,p2);
// To prepare 16*0xff
encript(Key,buffer);
// Encode the contents of the buffer from 0 -> 7
_memcpy(hash,buffer,8);
} else
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// INSTRUCTION 0x48: set flags 20.2 and 20.5 ?
// INSTRUCTION 0x4A: associated 4c can be used but 4a retrieve still valid
// but returns just FF * p3
if (inst==0x48 || inst==0x4A){
// No action, just need to support the call
IncrementECMCount(inst);
} else
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// INSTRUCTION 0x4C: Puts down bitmap of the allowed IN THE 0x44-Nanos and Protection Flags
// INSTRUCTION 0x50: Add new provider...
// INSTRUCTION 0x54: LP Mode something...
// INSTRUCTION 0x56: LP Mode something...
if (inst==0x4c || inst==0x50 || inst==0x54 || inst==0x56){
// High or Low programming mode required.... therefore not available here!
// 90 11 Test-bit put not down, therefore instruction doesn't support
// but maybe 90 22 Card in the wrong mode ???
// maybe 9017 from the Rom dump????
sw2=0x11;
} else
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// INSTRUCTION 0x7c --------------------------------------------------------------
// result just taken from Secom (301)
if (inst==0x7c){
// Have no information on what this indicates.... not a return
// code in the SecaFAQ!
sw1=0x98; sw2=0x01;
} else
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// INSTRUCTION 0x42: Edition of the data from IN THE 0x44
// result just taken from Secom (301)
if (inst==0x42){
// 90 14: Gone ahead instruction wrong
sw2=0x14;
} else
// INSTRUCTION 0x38: Some bollocks to do with PPV
if (inst==0x38){
/*
; Ins 38 : data request and PPV event recording request
; C1 38 xx yy 1A 16 (d1) 2A (d2 d3) 2B (d4 d5) 86 (8 bytes) 82 (signature)
; Superencryption may be active
; on exit : 29h=d1 2Dh=d2 2Eh=d3 2Fh=d4 30h=d5 87-8Eh=(8 bytes for security)
; d1 d2 d3 as in ins 34 d4-d5 : PPV event spot
*/
// Grib, moved sigcheck prep to sub
if (PrepareSigCheck(p1,p2,p3,TRUE)){
goto TX_Data;
}
// Should check p1 for super encryption....
if (signatureCheck(p1,p3)==0){
// 90 02: Signature fails
sw2=0x02;
goto TX_Data;
}
// Store the copy security word in the 86 if supplied
if (buffer[p3-18]==0x86){
_memcpy(hash,&buffer[p3-17],8);
}
_memcpy(Comando34+1,buffer+1,1);
_memcpy(Comando34+2,buffer+3,2);
// Store d4 and d5 PPV Event ID too
_memcpy(Comando34+4,buffer+6,2);
} else
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// INSTRUCTION 0x40: EMM - pass to nano processing....
if (inst==0x40){
// Grib, moved sigcheck prep to sub
if (PrepareSigCheck(p1,p2,p3,TRUE)){
goto TX_Data;
}
// we ignored SECA ( C1 40 00 81 17 )
if (p1&0x0f){
if (signatureCheck(p1,p3)){
if (processNanos(p1,kEMM,TRUE)){
processNanos(p1,kEMM,FALSE);
} // PPUA does not exist
} else {sw2=0x02;}
}
} else
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// INSTRUCTION 0x1A: Reading of the Indices of keys
if (inst==0x1A){
// FF FF 0B 40 00
ee_readString(buffer, EE_AVAIL_KEYS, 5);
for (p2=0, aux1=5; p2<16; p2++){
ind=keyExist(p1,p2)|p2;
if (ind&0xf0){
// Nota: it considers space in SECA
//if(p1 | (p2 < 8)){
buffer[aux1++]=ind;
//}
}
}
} else
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// INSTRUCTION 0x5C: Lay down word to be encrypted
if (inst==0x5C){
if (p3!=0x08){
sw1=0x67;
}
} else
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// INSTRUCTION 0x5A: Lectura de claves encriptadas
if (inst==0x5A){
//lastInst=inst;
// Reading of encrypted keys
// Nota: it considers space in SECA
// aux1 = (p1 | (p2 < 8))? keyExist(p1,p2&0x0f) : 0x00;
aux1 = keyExist(p1,p2&0x0f);
if (aux1==0x00){
// It does not exist key primary 90 1D
sw2=0x1d;
goto TX_Data;
} else if (aux1==0x50 && (p1&0x10)){
// It does not exist key secondary 90 1F
sw2=0x1F;
goto TX_Data;
}
getKey(p1,p2);
// To prepare 8*0x00
fillBuffer(0,16,0x00);
encript(Key,buffer);
} else
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// INSTRUCTION 0x0A: System of Operation of the Card
if (inst==0x0A){
_memcpy(buffer,version,TOTAL_VERSION);
// Need to decrypt buffer + 39
// Decrypt the firmware result
antipurple(39,3);
} else
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// INSTRUCTION 0x22: Reading of eeprom
// C1 22 P1 P2 P3
// P1 Low Addr
// P2 High Addr
// P3 Bytes to read
if ( (inst==0x22) && support_phoenix){
ee_readString(buffer,(((u16)p1)<<8)+p2,p3);
} else
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// INSTRUCTION 0x20: writing of eeprom
// C1 20 P1 P2 P3
// P1 Low Addr
// P2 High Addr
// P3 Bytes to write
if ( (inst==0x20) && support_phoenix){
//RED_INFO_LED_ON;
ee_writeString((((u16)p1)<<8)+p2,buffer,p3);
//RED_INFO_LED_OFF;
} else {
// UNKNOWN INSTRUCTION
sw1=0x6D;
}
TX_Data:
// Check if the result was valid :)
lastInst=inst;
// Need for the associate 32/36 instruction, must be the same
// for some record requests
lastprovider = p1;
if (sw1!=0x90 || sw2){
IncrementECMCount(inst);
// Check if it exceeded visible provider count
if ((p1&0x0F)>=ProviderCount && inst!=0x40){
sw1=0x90; sw2=0x04;
if (inst&2){
// CARD->CAM
fillBuffer(0,MAX_COMMAND_LENGHT,0xFF);
}
}
if (inst!=0x3c || (sw1==0x90 && sw2==0x02)){
lastInst=0;
}
}
// Transmit without the hidden provider checks
TX_Date_MPSkip:
// Store the last command used global for the SetupInfo function...
if (inst!=0x12){LastNonProviderInst = inst;}
#ifdef MODO_LOG
if (modo_log && !support_phoenix){
// Log the current instruction to the eeprom
capturar_inst(0xc1,inst,p1,p2,p3);
}
#endif
// Grib - Bug fix :)
if(p3 && inst&2){
// CARD->CAM
sendString(buffer,p3);
}
(*ptrSend)(sw1);
(*ptrSend)(sw2);
/*
#ifdef MODO_LOG
if (ins_capturadas){
ORANGE_INFO_LED_ON;
}
#endif
*/
} // end of while(1){}
return 0;
} // end of main()
Re: What software do i need to make Computer software
Notepad++ and Sublime text are the best code editing softwares...
Re: What software do i need to make Computer software
An editor is any program that allows you to write computer code. They range from simple, like a basic text editor, to advanced software, such as Adobe Dreamweaver, Eclipse, JDeveloper, or Microsoft Visual Studio. Fortunately, any program can be written in a text editor, which means you can get started for free.
Re: What software do i need to make Computer software
Try Visual Studio Community Edition, full featured and free
Re: What software do i need to make Computer software
Well, you can use Visual Studio Code as a free IDE (editor for your code). With that you can write programs in most languages.
To get started you could look into Python or Javascript.
To get serious and code games, you'll need to be looking at C or C#