FlashGBX-GameBoy和GBA卡带烧录软件

读取和写入 Game Boy 和 Game Boy Advance 卡带数据。支持的硬件:GBxCart RW、GBFlash、Joey Jr

官方链接:

https://github.com/lesserkuma/FlashGBX

对应的硬件:

https://github.com/insidegadgets/GBxCart-RW

https://www.gbxcart.com/

淘宝可以买对应的硬件:

搜索 GBA 烧录器

介绍

FlashGBX,由Lesserkuma倾力打造,是一款跨平台的强大工具,专为复古游戏爱好者设计。

AT32读写通过软件SPI读写W25Q128存储芯片

SPI简介

SPI(Serial Peripheral Interface)是由Motorola公司开发的一种通用数据总线

四根通信线:SCK(Serial Clock)、MOSI(Master Output Slave Input)、MISO(Master Input Slave Output)、SS(Slave Select)同步, 全双工支持总线挂载多设备(一主多从) SPI较IIC传输更快,最大传输速度取决于芯片厂商的设计需求,但硬件开销较IIC大,通信线个数较多

NSI安装包脚本

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
; Script generated by the HM NIS Edit Script Wizard.

; HM NIS Edit Wizard helper defines
!define PRODUCT_NAME "mdblog"
!define PRODUCT_VERSION "v0.0.1"
!define PRODUCT_PUBLISHER "GrabByte"
!define PRODUCT_WEB_SITE "https://www.grabbyte.com/product/${PRODUCT_NAME}"
!define PRODUCT_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\${PRODUCT_NAME}.exe"
!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
!define PRODUCT_UNINST_ROOT_KEY "HKCU"

SetCompressor lzma

; MUI 1.67 compatible ------
!include "MUI2.nsh"
!include "x64.nsh"

; MUI Settings
!define MUI_ABORTWARNING
!define MUI_ICON "../resources/icons/app_icon.ico"
!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\modern-uninstall.ico"

; Language Selection Dialog Settings
!define MUI_LANGDLL_REGISTRY_ROOT "${PRODUCT_UNINST_ROOT_KEY}"
!define MUI_LANGDLL_REGISTRY_KEY "${PRODUCT_UNINST_KEY}"
!define MUI_LANGDLL_REGISTRY_VALUENAME "NSIS:Language"

; Welcome page
!insertmacro MUI_PAGE_WELCOME
; License page
!insertmacro MUI_PAGE_LICENSE "../LICENSE.md"
; Components page
!insertmacro MUI_PAGE_COMPONENTS
; Directory page
!insertmacro MUI_PAGE_DIRECTORY
; Instfiles page
!insertmacro MUI_PAGE_INSTFILES
; Finish page
!define MUI_FINISHPAGE_RUN "$INSTDIR\${PRODUCT_NAME}.exe"
!define MUI_FINISHPAGE_SHOWREADME
!define MUI_FINISHPAGE_SHOWREADME_Function OpenReadme
!insertmacro MUI_PAGE_FINISH

; Uninstaller pages
!insertmacro MUI_UNPAGE_INSTFILES

; Language files
!insertmacro MUI_LANGUAGE "English"
!insertmacro MUI_LANGUAGE "SimpChinese"

LangString LANG_PRODUCT_NAME ${LANG_ENGLISH} "mdblog"
LangString LANG_PRODUCT_NAME ${LANG_SIMPCHINESE} "MD博客"

LangString LANG_UNINSTALL_CONFIRM ${LANG_ENGLISH} "Thank you very much! $(^Name) has been successfully removed."
LangString LANG_UNINSTALL_CONFIRM ${LANG_SIMPCHINESE} "非常感谢您的使用! $(^Name) 已成功地从您的计算机中移除。"

LangString LANG_REMOVE_COMPONENT ${LANG_ENGLISH} "You sure you want to completely remove $ (^ Name), and all of its components?"
LangString LANG_REMOVE_COMPONENT ${LANG_SIMPCHINESE} "你确实要完全移除 $(^Name) ,其及所有的组件?"

; MUI end ------

Name "$(LANG_PRODUCT_NAME) ${PRODUCT_VERSION}"
Caption "$(LANG_PRODUCT_NAME) ${PRODUCT_VERSION}"
OutFile "${PRODUCT_NAME}_Setup_${PRODUCT_VERSION}.exe"
InstallDir "$LOCALAPPDATA\${PRODUCT_NAME}"
;InstallDirRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_DIR_REGKEY}" ""

ShowInstDetails show
ShowUnInstDetails show
#RequestExecutionLevel user

; Install vc runtime
Function InstallVC
   Push $R0
   ClearErrors
   ReadRegDword $R0 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{FF66E9F6-83E7-3A3E-AF14-8DE9A809A6A4}" "Version"

   ; check register
   IfErrors 0 VSRedistInstalled
   Exec "$INSTDIR\bin\vcredist_x86.exe /q /norestart"
   StrCpy $R0 "-1"

VSRedistInstalled:
  ;MessageBox MB_OK  "Installed"
  Exch $R0
  Delete "$INSTDIR\bin\vcredist_x86.exe"
FunctionEnd

Function InstallVC64
    Push $R0
    ClearErrors
    ReadRegDword $R0 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{FF66E9F6-83E7-3A3E-AF14-8DE9A809A6A4}" "Version"
    
    ; check register
    IfErrors 0 VSRedistInstalled
    Exec "$INSTDIR\bin\vcredist_x64.exe /q /norestart"
    StrCpy $R0 "-1"
    
    VSRedistInstalled:
    ;MessageBox MB_OK  "Installed"
    Exch $R0
    Delete "$INSTDIR\bin\vcredist_x64.exe"
FunctionEnd

Function InstallRuntime
    IfFileExists "$INSTDIR\bin\vcredist_x64.exe" 0 +2
    call InstallVC64
    IfFileExists "$INSTDIR\bin\vcredist_x86.exe" 0 +2
    call InstallVC
FunctionEnd

Function DirectoryPermissionErrorBox
 StrCpy $1 "${LANG_DIRECTORY_PERMISSION}"
     MessageBox MB_ICONSTOP $1 
       Abort
FunctionEnd

Var UNINSTALL_PROG
Var OLD_PATH
Function .onInit  
  !insertmacro MUI_LANGDLL_DISPLAY
  ClearErrors
  ReadRegStr $UNINSTALL_PROG ${PRODUCT_UNINST_ROOT_KEY} ${PRODUCT_UNINST_KEY} "UninstallString"
  IfErrors  done

  ;https://blog.csdn.net/u012896330/article/details/55517461
  CopyFiles $UNINSTALL_PROG $TEMP
  StrCpy $OLD_PATH $UNINSTALL_PROG -10
  ExecWait '"$TEMP/uninst.exe" /S _?=$OLD_PATH' $0
  DetailPrint "uninst.exe returned $0"
  Delete "$TEMP/uninst.exe"

done:
FunctionEnd

Section "${PRODUCT_NAME}" SEC01
  SetOutPath "$INSTDIR"
  IfFileExists "$INSTDIR\*.*" +2 0
  call DirectoryPermissionErrorBox
  SetOverwrite ifnewer
  File /r "../../bin\*"
  ;SetShellVarContext all
  ;SetShellVarContext current
  call InstallRuntime
SectionEnd

Section -AdditionalIcons
  CreateDirectory "$SMPROGRAMS\${PRODUCT_NAME}"
  CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\$(LANG_PRODUCT_NAME).lnk" "$INSTDIR\${PRODUCT_NAME}.exe"
  CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\Uninstall.lnk" "$INSTDIR\uninst.exe"
  CreateShortCut "$DESKTOP\$(LANG_PRODUCT_NAME).lnk" "$INSTDIR\${PRODUCT_NAME}.exe"
 
  WriteIniStr "$INSTDIR\${PRODUCT_NAME}.url" "InternetShortcut" "URL" "${PRODUCT_WEB_SITE}"
  ;SetShellVarContext all
  CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\Website.lnk" "$INSTDIR\${PRODUCT_NAME}.url"
  ;SetShellVarContext current
SectionEnd

Section -Post
  WriteUninstaller "$INSTDIR\uninst.exe"
  ;WriteRegStr HKLM "${PRODUCT_DIR_REGKEY}" "" "$INSTDIR\${PRODUCT_APP_NAME}.exe"
  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_DIR_REGKEY}" "" "$INSTDIR\${PRODUCT_NAME}.exe"
  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_DIR_REGKEY}" "Path" "$INSTDIR\"
  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)"
  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninst.exe"
  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\${PRODUCT_NAME}.exe"
  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}"
  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "URLInfoAbout" "${PRODUCT_WEB_SITE}"
  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}"
SectionEnd

; Section descriptions
!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
  !insertmacro MUI_DESCRIPTION_TEXT ${SEC01} "$(LANG_PRODUCT_NAME)"
!insertmacro MUI_FUNCTION_DESCRIPTION_END

Function un.onUninstSuccess
  HideWindow
  MessageBox MB_ICONINFORMATION|MB_OK "$(LANG_UNINSTALL_CONFIRM)"
FunctionEnd

Function un.onInit
!insertmacro MUI_UNGETLANGUAGE
  MessageBox MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2 "$(LANG_REMOVE_COMPONENT)" IDYES +2
  Abort
FunctionEnd

Function OpenReadme
    ExecShell "open" "https://www.grabbyte.com/product/mdblog/" 
FunctionEnd

Section Uninstall
  ;SetShellVarContext all
  RMDir /r "$SMPROGRAMS\${PRODUCT_NAME}"
  Delete "$DESKTOP\$(LANG_PRODUCT_NAME).lnk"
  SetOutPath "$SMPROGRAMS"
  ;SetShellVarContext current
  RMDir /r "$INSTDIR"

  DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
  ;DeleteRegKey HKLM "${PRODUCT_DIR_REGKEY}"
  DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_DIR_REGKEY}"
  
  SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment"
  SetAutoClose true
SectionEnd

基于C++的多任务应用代码框架

项目结构

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
project/
├── arch/
   ├── arch_stm32.cpp      // STM32 的上下文切换实现
   ├── arch_stm32.hpp      // STM32 的硬件抽象层接口
   ├── arch_pc.cpp         // PC 的上下文切换实现
   ├── arch_pc.hpp         // PC 的硬件抽象层接口
   └── arch.hpp            // 硬件抽象层通用接口
├── hal/
   ├── hal_stm32.cpp       // STM32 的 HAL 实现
   ├── hal_stm32.hpp       // STM32 的 HAL 接口
   ├── hal_pc.cpp          // PC 的 HAL 实现
   ├── hal_pc.hpp          // PC 的 HAL 接口
   └── hal.hpp             // HAL 通用接口
├── drivers/
   ├── uart/               // 串口驱动
      ├── uart_stm32.cpp  // STM32 串口驱动
      ├── uart_pc.cpp     // PC 串口驱动
      └── uart.hpp        // 串口驱动接口
   ├── display/            // 显示驱动
      ├── display_8080.cpp // 8080 接口显示驱动
      ├── display_rgb.cpp  // RGB 接口显示驱动
      ├── display_mipi.cpp // MIPI 接口显示驱动
      ├── display_vbe.cpp  // BIOS VBE3.0 显示驱动
      ├── display_uefi.cpp // UEFI 图形显示驱动
      └── display.hpp      // 显示驱动接口
   ├── audio/              // 声音驱动
      ├── audio_stm32.cpp // STM32 声音驱动
      ├── audio_pc.cpp    // PC 声音驱动
      └── audio.hpp       // 声音驱动接口
   ├── input/              // 输入设备驱动
      ├── keyboard.cpp    // 键盘驱动
      ├── mouse.cpp       // 鼠标驱动
      └── input.hpp       // 输入设备驱动接口
   └── drivers.hpp         // 驱动模块通用接口
├── scheduler/
   ├── scheduler.cpp       // 任务调度器实现
   └── scheduler.hpp       // 任务调度器接口
├── tasks/
   ├── task_led.cpp        // LED 任务实现
   ├── task_button.cpp     // 按钮任务实现
   └── tasks.hpp           // 任务函数声明
├── task_manager/
   ├── task_manager.cpp    // 任务管理器实现
   └── task_manager.hpp    // 任务管理器接口
├── task_base/
   ├── task_base.cpp       // 任务基类实现
   └── task_base.hpp       // 任务基类接口
└── main.cpp                // 主程序
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
#include "arch.h"
#include "stm32f1xx_hal.h"

// 保存和恢复上下文的汇编代码
__asm void arch_context_switch(uint32_t** current_stack, uint32_t* next_stack) {
    // 保存当前任务的上下文
    PUSH {R4-R11}          // 保存寄存器
    STR SP, [R0]           // 保存当前堆栈指针

    // 切换到下一个任务的上下文
    LDR SP, [R1]           // 加载下一个任务的堆栈指针
    POP {R4-R11}           // 恢复寄存器
    BX LR                  // 返回
}

arch.hpp(硬件抽象层接口)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16

#ifndef ARCH_HPP
#define ARCH_HPP

#include <cstdint>

class Arch {
public:
    // 上下文切换函数
    static void contextSwitch(uint32_t** currentStack, uint32_t* nextStack);

    // 初始化硬件相关功能
    static void init();
};

#endif // ARCH_HPP

arch_stm32.cpp(STM32 的上下文切换实现)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15

#include "arch.hpp"
#include "stm32f1xx_hal.h"

// 保存和恢复上下文的汇编代码
extern "C" void arch_context_switch(uint32_t** currentStack, uint32_t* nextStack);

void Arch::contextSwitch(uint32_t** currentStack, uint32_t* nextStack) {
    arch_context_switch(currentStack, nextStack);
}

void Arch::init() {
    HAL_Init();
    SystemClock_Config();
}

hal.hpp(HAL 接口)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14

#ifndef HAL_HPP
#define HAL_HPP

class HAL {
public:
    // 初始化 GPIO
    static void init();

    // 切换 GPIO 状态
    static void togglePin(int pin);
};

#endif // HAL_HPP

hal_stm32.cpp(STM32 的 HAL 实现)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

#include "hal.hpp"
#include "stm32f1xx_hal.h"

void HAL::init() {
    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();

    GPIO_InitTypeDef GPIO_InitStruct = {0};
    GPIO_InitStruct.Pin = GPIO_PIN_5 | GPIO_PIN_0;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}

void HAL::togglePin(int pin) {
    if (pin == 5) {
        HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
    } else if (pin == 0) {
        HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0);
    }
}

scheduler.hpp(任务调度器接口)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#ifndef SCHEDULER_HPP
#define SCHEDULER_HPP

#include <cstdint>
#include <functional>

class Scheduler {
public:
    // 任务函数类型
    using TaskFunction = std::function<void()>;

    // 添加任务
    static void addTask(TaskFunction taskFunc);

    // 启动调度器
    static void start();

private:
    // 任务结构体
    struct Task {
        TaskFunction taskFunction; // 任务函数
        uint32_t* stackPointer;    // 任务堆栈指针
        uint32_t stack[64];        // 任务堆栈
    };

    static const int MAX_TASKS = 3;
    static Task taskQueue[MAX_TASKS];
    static int currentTaskIndex;
};

#endif // SCHEDULER_HPP

scheduler.cpp(任务调度器实现)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

#include "scheduler.hpp"
#include "arch.hpp"

Scheduler::Task Scheduler::taskQueue[Scheduler::MAX_TASKS];
int Scheduler::currentTaskIndex = -1;

void Scheduler::addTask(TaskFunction taskFunc) {
    static int taskCount = 0;
    if (taskCount < MAX_TASKS) {
        taskQueue[taskCount].taskFunction = taskFunc;
        taskQueue[taskCount].stackPointer = taskQueue[taskCount].stack + 63; // 初始化堆栈指针
        taskCount++;
    }
}

void Scheduler::start() {
    if (currentTaskIndex == -1) {
        currentTaskIndex = 0;
        taskQueue[currentTaskIndex].taskFunction();
    }
}

extern "C" void SysTick_Handler(void) {
    HAL_IncTick(); // 更新 HAL 库的 tick

    // 任务切换
    if (Scheduler::currentTaskIndex != -1) {
        int nextTaskIndex = (Scheduler::currentTaskIndex + 1) % Scheduler::MAX_TASKS;
        Arch::contextSwitch(&Scheduler::taskQueue[Scheduler::currentTaskIndex].stackPointer,
                            Scheduler::taskQueue[nextTaskIndex].stackPointer);
        Scheduler::currentTaskIndex = nextTaskIndex;
    }
}

上下文切换(PC 版)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18

// arch_pc.hpp
#ifndef ARCH_PC_HPP
#define ARCH_PC_HPP

#include <cstdint>
#include <csetjmp>

class Arch {
public:
    // 上下文切换函数
    static void contextSwitch(uint32_t** currentStack, uint32_t* nextStack);

    // 初始化硬件相关功能
    static void init();
};

#endif // ARCH_PC_HPP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19

// arch_pc.cpp
#include "arch_pc.hpp"
#include <iostream>

void Arch::contextSwitch(uint32_t** currentStack, uint32_t* nextStack) {
    // 使用 setjmp/longjmp 实现上下文切换
    static jmp_buf env;
    if (setjmp(env) == 0) {
        // 保存当前上下文
        *currentStack = reinterpret_cast<uint32_t*>(&env);
        // 切换到下一个上下文
        longjmp(env, 1);
    }
}

void Arch::init() {
    std::cout << "Arch initialized for PC." << std::endl;
}

定时器(PC 版)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21

// hal_pc.hpp
#ifndef HAL_PC_HPP
#define HAL_PC_HPP

#include <chrono>
#include <thread>

class HAL {
public:
    // 初始化 GPIO
    static void init();

    // 切换 GPIO 状态
    static void togglePin(int pin);

    // 延时函数
    static void delay(uint32_t ms);
};

#endif // HAL_PC_HPP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16

// hal_pc.cpp
#include "hal_pc.hpp"
#include <iostream>

void HAL::init() {
    std::cout << "HAL initialized for PC." << std::endl;
}

void HAL::togglePin(int pin) {
    std::cout << "Toggling pin " << pin << std::endl;
}

void HAL::delay(uint32_t ms) {
    std::this_thread::sleep_for(std::chrono::milliseconds(ms));
}

任务实现(PC 版)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20

// task_led.cpp
#include "task_base.hpp"
#include "hal_pc.hpp"

class TaskLed : public TaskBase {
public:
    TaskLed() : TaskBase(taskFunction, 128, 1) {}

private:
    static void taskFunction() {
        while (true) {
            HAL::togglePin(5); // 切换 LED 状态
            HAL::delay(500);   // 延时 500ms
        }
    }
};

// 静态对象,自动注册任务
static TaskLed taskLed;
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20

// task_button.cpp
#include "task_base.hpp"
#include "hal_pc.hpp"

class TaskButton : public TaskBase {
public:
    TaskButton() : TaskBase(taskFunction, 128, 2) {}

private:
    static void taskFunction() {
        while (true) {
            HAL::togglePin(0); // 切换另一个 LED 状态
            HAL::delay(100);   // 延时 100ms
        }
    }
};

// 静态对象,自动注册任务
static TaskButton taskButton;

调度器(PC 版)

调度器的实现与之前相同,直接从任务管理器中获取任务并调度。

做自己的通达信指标公式

在股票K线图的左上角显示一个黄色的文字: 获利比例 Ctrl+F 打开公式管理器,创建一个指标公式

编辑公式

Image

指标公式代码:

1
2
DRAWTEXT_FIX(1,0.005,0.17,0,'莸利比例:'),COLORYELLOW;
{在左上角(0.005,0.17)的位置用黄色显示:“获利比例”四个字};

运行截图

Image Image

Image

如何使用C++编程编写自己的通达信选股插件

通达信插件选股

通达信插件选股功能可能大家都有听说过,有很多牛X的炒股选手,将自己的选股经验,做成程序,以插件的方式集成在炒股软件中使用. 这样子每次选股,复盘,就不用那么麻烦,而且更加有数据依据,不会因为自己的错误判断导致买错股票.