遊戯王真デュエルモンスターズ~封印されし記憶~のポケットステーションで強力なカードを入手するためのツール:チートリモコンを製作した。
この記事では、チートリモコンのソースコード一覧を載せる。
<チートリモコン作ってみたシリーズ>
・封印されし記憶を語る
・概要編
・ハードウェア編
・ソフトウェア編①:動作確認
・ソフトウェア編②:キー操作
・ソフトウェア編③:チャタリング対策
・ソフトウェア編④: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(); }