【遊戯王真DM】チートリモコンを作ってみた~ソースコード一覧~【封印されし記憶】

遊戯王真デュエルモンスターズ~封印されし記憶~のポケットステーションで強力なカードを入手するためのツール:チートリモコンを製作した。
この記事では、チートリモコンのソースコード一覧を載せる。



<チートリモコン作ってみたシリーズ>
封印されし記憶を語る
概要編
ハードウェア編
ソフトウェア編①:動作確認
ソフトウェア編②:キー操作
ソフトウェア編③:チャタリング対策
ソフトウェア編④:NECフォーマット
ソースコード一覧 ←いまここ
入手カード一覧




LCDlib.hは外部で入手した汎用ライブラリのため、仕様にあったものを自分で入手してください。


pic18f25k22_config.h

// PIC18F25K22 Configuration Bit Settings

// 'C' source line config statements

// CONFIG1H
#pragma config FOSC = HSMP      // Oscillator Selection bits (HS oscillator (medium power 4-16 MHz))
#pragma config PLLCFG = ON      // 4X PLL Enable (Oscillator multiplied by 4)
#pragma config PRICLKEN = ON    // Primary clock enable bit (Primary clock enabled)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
#pragma config IESO = OFF       // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)

// CONFIG2L
#pragma config PWRTEN = ON      // Power-up Timer Enable bit (Power up timer enabled)
#pragma config BOREN = OFF      // Brown-out Reset Enable bits (Brown-out Reset disabled in hardware and software)
#pragma config BORV = 190       // Brown Out Reset Voltage bits (VBOR set to 1.90 V nominal)

// CONFIG2H
#pragma config WDTEN = OFF      // Watchdog Timer Enable bits (Watch dog timer is always disabled. SWDTEN has no effect.)
#pragma config WDTPS = 32768    // Watchdog Timer Postscale Select bits (1:32768)

// CONFIG3H
#pragma config CCP2MX = PORTC1  // CCP2 MUX bit (CCP2 input/output is multiplexed with RC1)
#pragma config PBADEN = OFF     // PORTB A/D Enable bit (PORTB<5:0> pins are configured as digital I/O on Reset)
#pragma config CCP3MX = PORTB5  // P3A/CCP3 Mux bit (P3A/CCP3 input/output is multiplexed with RB5)
#pragma config HFOFST = ON      // HFINTOSC Fast Start-up (HFINTOSC output and ready status are not delayed by the oscillator stable status)
#pragma config T3CMX = PORTC0   // Timer3 Clock input mux bit (T3CKI is on RC0)
#pragma config P2BMX = PORTB5   // ECCP2 B output mux bit (P2B is on RB5)
#pragma config MCLRE = EXTMCLR  // MCLR Pin Enable bit (MCLR pin enabled, RE3 input pin disabled)

// CONFIG4L
#pragma config STVREN = ON      // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
#pragma config LVP = OFF        // Single-Supply ICSP Enable bit (Single-Supply ICSP disabled)
#pragma config XINST = OFF      // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))

// CONFIG5L
#pragma config CP0 = OFF        // Code Protection Block 0 (Block 0 (000800-001FFFh) not code-protected)
#pragma config CP1 = OFF        // Code Protection Block 1 (Block 1 (002000-003FFFh) not code-protected)
#pragma config CP2 = OFF        // Code Protection Block 2 (Block 2 (004000-005FFFh) not code-protected)
#pragma config CP3 = OFF        // Code Protection Block 3 (Block 3 (006000-007FFFh) not code-protected)

// CONFIG5H
#pragma config CPB = OFF        // Boot Block Code Protection bit (Boot block (000000-0007FFh) not code-protected)
#pragma config CPD = OFF        // Data EEPROM Code Protection bit (Data EEPROM not code-protected)

// CONFIG6L
#pragma config WRT0 = OFF       // Write Protection Block 0 (Block 0 (000800-001FFFh) not write-protected)
#pragma config WRT1 = OFF       // Write Protection Block 1 (Block 1 (002000-003FFFh) not write-protected)
#pragma config WRT2 = OFF       // Write Protection Block 2 (Block 2 (004000-005FFFh) not write-protected)
#pragma config WRT3 = OFF       // Write Protection Block 3 (Block 3 (006000-007FFFh) not write-protected)

// CONFIG6H
#pragma config WRTC = OFF       // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) not write-protected)
#pragma config WRTB = OFF       // Boot Block Write Protection bit (Boot Block (000000-0007FFh) not write-protected)
#pragma config WRTD = OFF       // Data EEPROM Write Protection bit (Data EEPROM not write-protected)

// CONFIG7L
#pragma config EBTR0 = OFF      // Table Read Protection Block 0 (Block 0 (000800-001FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR1 = OFF      // Table Read Protection Block 1 (Block 1 (002000-003FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR2 = OFF      // Table Read Protection Block 2 (Block 2 (004000-005FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR3 = OFF      // Table Read Protection Block 3 (Block 3 (006000-007FFFh) not protected from table reads executed in other blocks)

// CONFIG7H
#pragma config EBTRB = OFF      // Boot Block Table Read Protection bit (Boot Block (000000-0007FFh) not protected from table reads executed in other blocks)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

#include <xc.h>


main.c

// ヘッダーファイルの読み込み
#include <stdio.h>
#include "xc.h"
#include "LCDlib.h"
#include "pic18f25k22_config.h"
#include "keys.h"
//#include "IrREMlib.h"

#define _XTAL_FREQ 40000000

// 文字列の置き換え
#define RST_SW  PORTAbits.RA0
#define CUST_A  PORTAbits.RA1
#define CUST_B  PORTAbits.RA2
#define CUST_SW PORTAbits.RA3
#define DATA_A  PORTCbits.RC0
#define DATA_B  PORTCbits.RC1
#define DATA_SW PORTCbits.RC2
#define SEND_SW PORTCbits.RC3
#define LED_ON  LATB1 = 1
#define LED_OFF LATB1 = 0

int main() {
  // 変数定義
  int nec_cust_cur = 0; // Customコードの桁設定、0:一桁、1:十桁
  int nec_data_cur = 0; // Dataコードの桁設定、0:一桁、1:十桁

  unsigned char nec_custom = 0; // Customコード
  unsigned char nec_data   = 0; // Dataコード

  int lcd_status = 0; // コード変化フラグ、bit1:Data、bit0:Custom

  char NEC_CUSTOMT[2]; // Customコード用テキストデータ、2文字分
  char NEC_DATAT[2];   // Dataコード用テキストデータ、2文字分

  // I/Oポート初期化
  ANSELA = 0x00; // 全てデジタル
  ANSELB = 0x00; // 全てデジタル
  ANSELC = 0x00; // 全てデジタル
  TRISA  = 0xCF; // RA0-3,6-7が入力
  TRISB  = 0x00; // RB0-7が出力
  TRISC  = 0x0F; // RC0-3が入力
  LED_OFF;

  // LCD初期化
  lcd_init();
  lcd_str(1, 1, "NEC  Custom Data");
  lcd_str(2, 1, "       0x00 0x00");

  // Main Loop
  while(1){
    // Keys
    if(RST_SW == 0){
      lcd_status = NecDataRst(&nec_custom, &nec_data);
    }
    else if((CUST_A == 0) && (CUST_B == 1)){
      lcd_status = NecCustCw(nec_cust_cur, &nec_custom);
    }
    else if((CUST_A == 1) && (CUST_B == 0)){
      lcd_status = NecCustCcw(nec_cust_cur, &nec_custom);
    }
    else if(CUST_SW == 0){
      NecCustSw(&nec_cust_cur);
    }
    else if((DATA_A == 0) && (DATA_B == 1)){
      lcd_status = NecDataCw(nec_data_cur, &nec_data);
    }
    else if((DATA_A == 1) && (DATA_B == 0)){
      lcd_status = NecDataCcw(nec_data_cur, &nec_data);
    }
    else if(DATA_SW == 0){
      NecDataSw(&nec_data_cur);
    }
    else if(SEND_SW == 0){
      lcd_str(2, 1, "Send");
      NecDataSend(nec_custom, nec_data);
      lcd_str(2, 1, "    ");
    }

    // LCD
    if(lcd_status & 1){
      sprintf(NEC_CUSTOMT, "%02X", nec_custom);
      lcd_str(2, 10, NEC_CUSTOMT);
    }
    if(lcd_status & 2){
      sprintf(NEC_DATAT, "%02X", nec_data);
      lcd_str(2, 15, NEC_DATAT);
    }
    lcd_status = 0;
  }

  return (EXIT_SUCCESS);
}


keys.h

#ifndef KEYS_H
#define	KEYS_H

// NEC Format
// RESETスイッチ
int  NecDataRst(unsigned char *custom, unsigned char *data);
// CUSTOMエンコーダー時計回り
int  NecCustCw(int cursor, unsigned char *custom);
// CUSTOMエンコーダー時計回り
int  NecCustCcw(int cursor, unsigned char *custom);
// CUSTOMエンコーダースイッチ
void NecCustSw(int *cursor);
// DATAエンコーダー時計回り
int  NecDataCw(int cursor, unsigned char *data);
// DATAエンコーダー反時計回り
int  NecDataCcw(int cursor, unsigned char *data);
// DATAエンコーダースイッチ
void NecDataSw(int *cursor);
// SENDスイッチ
void NecDataSend(unsigned char custom, unsigned char data);

#endif	/* KEYS_H */


keys.c

#include "xc.h"
#include "IrREMlib.h"

#define RST_SW  PORTAbits.RA0
#define CUST_A  PORTAbits.RA1
#define CUST_B  PORTAbits.RA2
#define CUST_SW PORTAbits.RA3
#define DATA_A  PORTCbits.RC0
#define DATA_B  PORTCbits.RC1
#define DATA_SW PORTCbits.RC2
#define SEND_SW PORTCbits.RC3

#define chata_sw_delay_ms     10
#define chata_start_cnt_max   10
#define chata_end_cnt_max     30

#define _XTAL_FREQ 40000000



int  NecDataRst(unsigned char *custom, unsigned char *data){
  // チャタリング対策
  __delay_ms(chata_sw_delay_ms);
  if(RST_SW == 1) return 0;

  // 値の変更
  *custom = 0;
  *data   = 0;

  // スイッチがOFFになるまで待ち
  while(RST_SW == 0);
  __delay_ms(chata_sw_delay_ms);

  // 終了処理
  return 3;
}

int  NecCustCw(int cursor, unsigned char *custom){
  unsigned int chata_start_cnt = 0;
  unsigned int chata_end_cnt   = 0;
  unsigned int timeout_cnt     = 0;

  // チャタリング対策
  while(chata_start_cnt < chata_start_cnt_max){
    if(CUST_A == 0 && CUST_B == 0){
      chata_start_cnt++;
    }
    else{
      chata_start_cnt = 0;
    }
    if(timeout_cnt < 65535){
      timeout_cnt++;
    }
    else{
      return 0;
    }
  }

  // 値の変更
  switch(cursor){
    case 0  : *custom = *custom + 0x01; break;
    case 1  : *custom = *custom + 0x10; break;
    defoult : *custom = *custom + 0x01; break;
  }

  // スイッチがOFFになるまで待ち
  while(chata_end_cnt < chata_end_cnt_max){
    if(CUST_A == 1 && CUST_B == 1){
      chata_end_cnt++;
    }
    else{
      chata_end_cnt = 0;
    }
  }

  // 終了処理
  return 1;
}

int  NecCustCcw(int cursor, unsigned char *custom){
  unsigned int chata_start_cnt = 0;
  unsigned int chata_end_cnt   = 0;
  unsigned int timeout_cnt     = 0;

  // チャタリング対策
  while(chata_start_cnt < chata_start_cnt_max){
    if(CUST_A == 0 && CUST_B == 0){
      chata_start_cnt++;
    }
    else{
      chata_start_cnt = 0;
    }
    if(timeout_cnt < 65535){
      timeout_cnt++;
    }
    else{
      return 0;
    }
  }

  // 値の変更
  switch(cursor){
    case 0  : *custom = *custom - 0x01; break;
    case 1  : *custom = *custom - 0x10; break;
    defoult : *custom = *custom - 0x01; break;
  }

  // スイッチがOFFになるまで待ち
  while(chata_end_cnt < chata_end_cnt_max){
    if(CUST_A == 1 && CUST_B == 1){
      chata_end_cnt++;
    }
    else{
      chata_end_cnt = 0;
    }
  }

  // 終了処理
  return 1;
}

void NecCustSw(int *cursor){
  // チャタリング対策
  __delay_ms(chata_sw_delay_ms);
  if(CUST_SW == 1) return;

  // 値の変更
  *cursor = *cursor + 1;
  if(*cursor >= 2) *cursor = 0;

  // スイッチがOFFになるまで待ち
  while(CUST_SW == 0);
  __delay_ms(chata_sw_delay_ms);
}

int  NecDataCw(int cursor, unsigned char *data){
  unsigned int chata_start_cnt = 0;
  unsigned int chata_end_cnt   = 0;
  unsigned int timeout_cnt     = 0;

  // チャタリング対策
  while(chata_start_cnt < chata_start_cnt_max){
    if(DATA_A == 0 && DATA_B == 0){
      chata_start_cnt++;
    }
    else{
      chata_start_cnt = 0;
    }
    if(timeout_cnt < 65535){
      timeout_cnt++;
    }
    else{
      return 0;
    }
  }

  // 値の変更
  switch(cursor){
    case 0  : *data = *data + 0x01; break;
    case 1  : *data = *data + 0x10; break;
    defoult : *data = *data + 0x01; break;
  }

  // スイッチがOFFになるまで待ち
  while(chata_end_cnt < chata_end_cnt_max){
    if(DATA_A == 1 && DATA_B == 1){
      chata_end_cnt++;
    }
    else{
      chata_end_cnt = 0;
    }
  }

  // 終了処理
  return 2;
}

int  NecDataCcw(int cursor, unsigned char *data){
  unsigned int chata_start_cnt = 0;
  unsigned int chata_end_cnt   = 0;
  unsigned int timeout_cnt     = 0;

  // チャタリング対策
  while(chata_start_cnt < chata_start_cnt_max){
    if(DATA_A == 0 && DATA_B == 0){
      chata_start_cnt++;
    }
    else{
      chata_start_cnt = 0;
    }
    if(timeout_cnt < 65535){
      timeout_cnt++;
    }
    else{
      return 0;
    }
  }

  // 値の変更
  switch(cursor){
    case 0  : *data = *data - 0x01; break;
    case 1  : *data = *data - 0x10; break;
    defoult : *data = *data - 0x01; break;
  }

  // スイッチがOFFになるまで待ち
  while(chata_end_cnt < chata_end_cnt_max){
    if(DATA_A == 1 && DATA_B == 1){
      chata_end_cnt++;
    }
    else{
      chata_end_cnt = 0;
    }
  }

  // 終了処理
  return 2;
}

void NecDataSw(int *cursor){
  // チャタリング対策
  __delay_ms(chata_sw_delay_ms);
  if(DATA_SW == 1) return;

  // 値の変更
  *cursor = *cursor + 1;
  if(*cursor >= 2) *cursor = 0;

  // スイッチがOFFになるまで待ち
  while(DATA_SW == 0);
  __delay_ms(chata_sw_delay_ms);
}

void NecDataSend(unsigned char custom, unsigned char data){
  while(SEND_SW == 0){
    NecSend(custom, data);
    __delay_ms(40);
  }
}


IrREMlib.h

#ifndef IRREMLIB_H
#define	IRREMLIB_H

// NEC Format
void NecSend(unsigned char custom, unsigned char data);

#endif


IrREMlib.c

#include "xc.h"

#define _XTAL_FREQ 40000000

#define LED_ON  LATB1 = 1
#define LED_OFF LATB1 = 0

void NecGenLedTon(void){
//// 調整前
//  for(int i=0; i<21; i++){
//    LED_ON;
//    __delay_us(9);
//    LED_OFF;
//    __delay_us(17);
//  }
//  __delay_us(12);

  // 調整後
  for(int i=0; i<21; i++){
    LED_ON;
    __delay_us(8);
    _delay(7);
    LED_OFF;
    __delay_us(16);
  }
  __delay_us(8);
}

void NecGenLedToff(void){
  LED_OFF;
  __delay_us(562);
}

void NecGenBitHigh(void){
  NecGenLedTon();
  NecGenLedToff();
  NecGenLedToff();
  NecGenLedToff();
}

void NecGenBitLow(void){
  NecGenLedTon();
  NecGenLedToff();
}

void NecSend(unsigned char custom, unsigned char data){
  int i;
  // Leader Code
  for(i=0; i<16; i++){
    NecGenLedTon();
  }
  for(i=0; i<8; i++){
    NecGenLedToff();
  }
  // Custom Code
  for(i=0; i<8; i++){
    if(custom>>i & 1){
      NecGenBitHigh();
    }
    else{
      NecGenBitLow();
    }
  }
  // Custom Code(invert)
  for(i=0; i<8; i++){
    if(custom>>i & 1){
      NecGenBitLow();
    }
    else{
      NecGenBitHigh();
    }
  }
  // Data Code
  for(i=0; i<8; i++){
    if(data>>i & 1){
      NecGenBitHigh();
    }
    else{
      NecGenBitLow();
    }
  }
  // Data Code(invert)
  for(i=0; i<8; i++){
    if(data>>i & 1){
      NecGenBitLow();
    }
    else{
      NecGenBitHigh();
    }
  }
  // Stop Bit
  NecGenLedTon();
}