【开坑】【告别】在fx-9860系列上用C语言编程(翻译转载)
本帖最后由 Myth 于 2021-7-21 16:06 编辑Written by Zezombye@planet-casio.
Original post
#此教程由法语翻译而来,并非本人成果。感谢原作者Zezombye!
好久没上cnCalc了。
遥想刚入坑时,cnCalc一日十几新帖,各种挖黑胶、爆机操作层出不穷,diameter、Mike等大神(大神过多,恕不一一列举)各显神通。再看如今,真是令人唏嘘。
入坑以来,未能给cnCalc做什么贡献,不过是写了几篇9750升级教程而已。今日退坑,决定再翻译一个planet-casio上的9860SDK教程,算是个留念,也算是致敬@diameter当年写的教程。
原教程法语,再加上我个人C语言水平过低,如有错误,还请包涵。
最后,感谢原作者@Zezombye,也感谢这个圈子内的所有人,这个圈子一直以来给我带来的快乐,我不会忘记。
原贴:https://www.planet-casio.com/Fr/forums/lecture_sujet.php?id=14992
fx-9860 SDK及官方文档:https://myth.akashic.cc/ 点击 DOWNLOAD -> 计算器 下载
本帖最后由 Myth 于 2019-10-9 22:48 编辑
Written by Zezombye@planet-casio.
Original post
#此教程由法语翻译而来,并非本人成果。感谢原作者Zezombye!
为了更好地编写游戏,我们可以在fx-9860系列上使用C语言编程。用C语言编写的程序格式为*.g1a(与*.g1m不兼容),被称为Add-in。可以将这些程序传输到fx-9860中运行。
在本教程中,我假设您已经了解C语言,这意味着您熟悉结构、指针、变量等概念。
如果您对C语言没有足够了解,建议您查看Openclassroom教程。
本帖最后由 Myth 于 2020-3-22 11:15 编辑
第一部分:安装SDK
如果您的操作系统是Linux,请查看Gint的有关内容。如果您的操作系统是Windows,您需要安装fx-9860 SDK(提取码:a4px)。如果您的电脑是Mac,请在Windows上使用fx-9860 SDK。
在Windows上安装时,请勿将安装在如Program Files(x86)等带括号的文件夹中!!!
Linux(使用Gint)无此限制。 本帖最后由 Myth 于 2019-10-13 14:25 编辑
第二部分:使用SDK
安装SDK后,将其打开。我们首先来创建一个新的项目。
单击Project<<New,然后依次填写项目路径、文件夹名称、项目名称、版本号。
此后会弹出错误消息显示无项目文件,这是正常的。
您会发现,SDK为您自动预置了代码,您可以先编译一下。
要编译,请单击Project<<Rebuild all
如果您的路径不含括号的话,此时编译应该会顺利完成。若您的编译器报错,请检查路径是否含有括号。
然后单击Run<<Run开始在模拟器中运行程序。稍稍拉大Display窗口,使模拟器屏幕更大。然后在Menu内找到您的Add-in(图标为Debug),点击EXE打开。您会得到以下结果:
本帖最后由 Myth 于 2020-3-22 11:16 编辑
第三部分:关于代码的基本介绍
首先,我们打开项目文件夹,您应该看到以下文件:
MainIcon.bmp是要在Menu中显示的图标(单色位图),更改此文件可更改程序的图标。
使用您喜欢的代码编辑器打开*.c文件(如Vscode)。您可以从SDK中直接编辑代码,但编辑体验极差,没有突出显示和代码缩进功能。
这里,主函数是此函数:
int AddIn_main(int isAppli, unsigned short OptionNum)
{
unsigned int key;
Bdisp_AllClr_DDVRAM();
locate(1,4);
Print((unsigned char*)"This application is");
locate(1,5);
Print((unsigned char*)" sample Add-In.");
while(1){
GetKey(&key);
}
return 1;
}
程序将从这里的主函数开始。当然,您不用考虑int AddIn_main()中的参数。事实上,Add-in可以在Menu或E-act中被启动,但由于在绝大多数情况下程序是从Menu启动的,您可以忽略这些参数。
首先要注意的是,尽管fx9860 SDK有C标准库,但它却不支持printf()函数和scanf()函数。事实上,计算器没有PC那样输入流和输出流的概念。像在CASIO BASIC中一样,有必要在输出时进行定位。例如:
locate(int x, int y); //将光标放在x,y处
Print(char* str); //显示字符串
没有scanf()函数令人恼火,但其实您不太需要它。毕竟大多数人想要制作游戏,而大多数游戏不要求输入文本。
如果确实有输入文本的需要,请自己编写函数或使用EasyInput库。
如果要在屏幕上输出数字,则有两种选择:
要么使用sprintf()函数,例如:
int a = 30, u = 40;
char* str = malloc(u);
sprintf(str, " %d", a);
locate(1,1);
Print(str);
您也可以使用不在C标准库中的itoa函数:
void itoa(int n, char s[])
{
int i, j, sign;
char c;
if ((sign = n) < 0)
n = -n;
i = 0;
do {
s = n % 10 + '0';
} while ((n /= 10) > 0);
if (sign < 0)
s = '-';
s = '\0';
for (i = 0, j = strlen(s)-1; i<j; i++, j--) {
c = s;
s = s;
s = c;
}
}
考虑到使用sprintf()会使加载项增加30 KB,建议使用第二种方式。若要使用sprintf(),请务必记得#include<stdio.h>。
另外,请注意该编译器不支持C99标准,因此,请注意变量声明的位置与for循环的使用。
[*]函数Bdisp_AllClr_DDVRAM()用于清空DD和VRAM。
要了解DD与VRAM的区别,请设想现在要绘制一个图案。首先,图案在VRAM上绘制,然后发送给DD,后者将其显示出来。
由VRAM向DD的发送并不是自动的,需要通过Bdisp_PutDisp_DD()函数来实现。需要注意的是,某些函数会自动进行此操作,例如GetKey()函数。
[*]函数GetKey(int *key)用于按键检测。
请注意,若没有按下任何键,该函数将暂停程序的执行,直到一个键按下为止。我们稍后将介绍一些不会使程序暂停的函数。要特别注意的是,GetKey()将刷新DD。 (未完待续) 支持你,感谢分享和翻译 本帖最后由 Myth 于 2019-10-11 08:39 编辑
第四部分:使用MonochromeLib
MonochromeLib是使用fx-9860 SDK时必不可少的库:它极大地提高了绘图速度(帧率)。
您可以从这里下载.
您将得到MonochromeLib.c和MonochromeLib.h两个文件,请将它们移动到您的项目文件夹中,并添加到您的项目中。
在SDK的左侧,右键单击Source Files,然后点击Add,把您项目文件夹中的MonochromeLib.c文件选中;同样地,右键单击Header Files,然后点击Add,把您项目文件夹中的MonochromeLib.h文件选中。
注意:打开MonochromeLib.h文件,您会注意到一些#define被注释掉了,这是为了避免占用太多空间。您可以根据需要进行更改。
最后,在原先创建的*.c文件中,添加#include “MonochromeLib.h”,最后用ML_clear_vram()函数代替Bdisp_AllClr_DDVRAM()函数。
在SDK中,单击Project<<Rebuild all(如为灰色,先单击Run<<Stop)。程序应该可以正常编译,并且运行结果与之前相同——但要快一点。
在以后的编程中,尽可能使用MonochromeLib中的绘图功能,而非fxlib中的函数。 感谢! 希望继续更新! cctvgm 发表于 2019-10-13 16:41
希望继续更新!
这个教程很短的,剩的也不多了
其实真说要编程的话,看到这儿再结合diameter的帖子,我觉得已经够了
这两天比较忙,不过以后应该会更完的 竟然咕到了现在。。。考试周结束再说吧 十分感谢楼主的入门帖子,11月份的时候参加了学校组织的一个小型的设计比赛,脑洞大开想在casio上写个小游戏(2048小游戏),然而网上相关资料特别少,还好看到了楼主的入门帖,结合着diameter的教程,总算是成功了,十分感谢!!!
现在又把当时做的小游戏想传到真正的计算器上,不太知道咋搞 1282708293 发表于 2020-1-5 19:35
十分感谢楼主的入门帖子,11月份的时候参加了学校组织的一个小型的设计比赛,脑洞大开想在casio上写个小游 ...
很高兴能帮助到你!
编译生成的*.g1a文件,需要通过FA-124软件传入fx9860运行。如果是fx9750的话,需要先刷机刷成9860的系统。
https://www.cncalc.org/data/attachment/forum/201912/27/192901e11i4a1jkaejaiir.jpg
如图,当计算器连上电脑后,计算器调至连接模式,在FA-124左边点击connect连接计算器。点击圈出的部分,这时候就可以传g1a了。(右边copy,左边paste)
本帖最后由 Myth 于 2020-4-29 15:57 编辑
# 感谢 @wan帮忙翻译了以下所有内容
第五部分:按键和显示管理
有2个功能用来管理按键。
- GetKey()会暂停程序,并自动在屏幕上显示VRAM。- IsKeyDown()不暂停程序,不在屏幕上显示VRAM。
用哪一种?这一切都取决于你的游戏是否是实时的。如果不是实时的(如选择菜单),使用GetKey()。如果是实时的,使用IsKeyDown()。
按键值可以在SDK安装文件夹中的PDF文件中找到("KeyCode List.pdf "文件)。
注意上档键(shift和alpha)可能会返回不同的值(所以如果用户按shift+down,会返回KEY_CTRL_PAGEDOWN而不是KEY_CTRL_DOWN)。
例如,这里是一个游戏中的循环,可以用来移动一个方块(伪代码)。
while (1)
{
ML_clear_vram();
ML_pixel(x, y);
ML_display_vram();
if (IsKeyDown(KEY_CTRL_UP))
{
y--;
}
else if (isKeyDown(KEY_CTRL_DOWN))
{
y++;
} ...
}
至于显示功能方面,有以下语句:
- ML_pixel() 显示一个像素点- ML_line() 显示一行- ML_rectangle()来显示一个矩形等。
所有的函数参见MonochromeLib.h,名字很明确。
要显示文字,有以下语句:
- Print(char *str),在Locate(intx, int y)函数之后使用,以类似于basic中的Locate函数的方式显示。- PrintRev,其工作原理与Print类似,但颜色反转(黑底白字)。- PrintXY(int x, int y, char* str, int type),在坐标x, y处显示str,如果type = 0,则以黑色显示,如果type = 1,则以白色显示- PrintMini,其工作原理与PrintXY类似,但使用小字体显示(类似basic中的Text功能)。- BetterFont,一个可以显示带有自定义字符的字体库
请注意,这些功能使用卡西欧编码,部分兼容ASCII编码。
例如,我们要显示"agréable "。如果你使用Print("agréable"),你会注意到它显示的是这个:
如果你将文件保存为ANSI而不是UTF-8,则 "agr able"。
所以必须要符合卡西欧的编码。要知道怎么做,请到SDK安装文件夹里去看,里面有5个pdf文件。我们感兴趣的是 "字符集"。
在PDF的第6页,我们看到"é"的编码是0xE60A。
要在字符串中插入这些字节,不需要使用十六进制编辑器来修改.c文件(可能会导致编译错误):你必须使用十六进制转义符\x,通常只需要2位数作为参数。因此我们的代码行将是Print("agr\xE6\x0Aable")。如果我们执行它,它是这样显示的:
问题出在哪里?显然,编译器考虑到\x最多需要3位数,因此翻译成0xE6和0x0Aa→0xAA,而0xE6AA在卡西欧编码中就是中间那个点。并排的字符串是自动关联的。为了避免这种情况,加2个引号就足以让编译器知道应该停止在0A处:
Print("agr\xE6\x0A""able")
本帖最后由 Myth 于 2020-4-29 15:58 编辑
第六部分:Syscalls
Syscalls(系统调用)是操作系统固有的功能。卡西欧没有做任何关于这个问题的文档,但由于Simon Lothar的工作,大多数系统调用都是已知的:https://bible.planet-casio.com/simlo/chm/v20/
这些系统调用可能不会有什么用处,但它们允许你在主/副存储器中创建一个自定义文件夹,改变对比度等。
要使用syscall,有不同的方法。这里是其中之一。
创建一个syscalls.src文件,将把它添加到项目中(与添加MonochromeLib的方法相同)。
把下面的代码放在里面。syscall_table:
.data.l H'80010070
.end
然后,当你想添加你要调用mySyscall的syscall 0x123时,添加下面的代码(在代码的顶部):
.export _monSyscall
_monSyscall:
mov.l syscall_table, r2
mov.l monSyscall_code, r0
jmp @r2
nop
monSyscall_code:
.data.l H'123
在你的.c文件中,你只需要执行mySyscall()就可以了(当然要有必要的参数)。 本帖最后由 Myth 于 2020-4-29 15:59 编辑
第七部分:SDK 的其它功能
我从来没有用过这些功能(其实,在casio上编程的时候,这些功能会很好用),但它们可能对你有用。
首先,SDK有断点,用来停止程序的执行,以便更好地调试程序。也可以在 "globalvariables "和"localvariables"窗口中查看变量的值。
当错误发生时,有一个"trace "功能,它将指向导致错误的代码行。
也可以执行"Run"→" Trace Into",这样就可以得到:
因为不能使用printf,这个功能非常便于调试。
在 " View"选项卡中可以访问一个反汇编器,但由于不了解SH3汇编器,我不能说什么(这只是个入门教程)。
它还允许:
- 查看闪存(如果你想用syscalls来接触系统的话,非常有用)。- 获得堆区、栈区和调用堆栈的视图。- 查看寄存器。
注意,你有8kb的静态RAM(全局变量存储在这里),32 kb的栈区(静态RAM占用了这32kb),64 kb的堆区(SH4上还有额外的256kb,但要通过显式指针访问)。
重要:SDK默认会生成SH3插件,对于新的计算器(>2012年),必须将其转换为SH4。可以使用此网页进行转换:https://tools.planet-casio.com/SH4compatibility/
本帖最后由 Myth 于 2020-4-29 13:05 编辑
教程翻译结束,感谢原作者@Zezombye,也感谢帮忙翻译最后三部分的@wan!
感谢翻译,法语实在看不懂
页:
[1]