Friday, December 31, 2021

用开源GIMP编辑GIF动图

 新年到,微信同学群大家发了一堆video和GIF动图,我不甘落后,可一时也没这么可show的,于是网上现抓,可稍好看点的都有水印,怎么办?祭出开源的PhotoShop编辑器:GIMP。网上的图可能有版权(copyright),如下例用到的,我找不到license信息(Had tried to check the site showed in the bottom of the image, but not able to access that URL. Please let me know if anybody seeing concern about this. Thanks in advance)。这里只是简单介绍怎样用GIMP快速编辑图,应该不是问题。

好久没用了,现学教程。工具板都找不到,不过GIMP倒是列出所有的layer了。

工具版不是在menu->Tools下,而是menu->Windows下,或者Recently Closed Docks,或者New Toolbox(ctrl+b)和Dockable Dialog->Tool options。所有layer都visiable时,看不清修改的效果,所以要把除Background的layer都改成invisible(click layer左边的眼睛),然后每改完当前层,就把下一层变成visible。当所有层都改完并可见后,选menu File->Export->存成GIF文件,特别注意要选GIF Option->As Animation,然后按export。



Wednesday, December 29, 2021

两个关于基因和病毒的中文科普Youtube video

 知识就是力量。科学技术是第一生产力。最近在Youtube上看到的尹烨和李治中的两个访谈和演讲,涨知识。

 

中国需要让大众崇尚科学,少些纸醉金迷、物欲横流、唯利是图的颓废。我最看不惯的就是国内的电影电视剧大都是宫廷和抗日神剧,缺少科幻和现代的影视。中国人不是写不出好作品,除了最近的刘云慈的三体,和郑渊洁的舒克贝塔,以前叶永烈写了很多金明戈亮的作品,拿到今天也未必过时。 叶永烈写的小灵通漫游未来更是给了我们一代人对未来的憧憬。我们需要更多的像果壳和知吧的网站,让下一代的孩子有开阔的眼界。

Monday, December 27, 2021

教小朋友编程之坦克大战 2

加声音并不难,最简单的办法是直接调用SDL的mixer API(需要package libSDL2_mixer-devel),参见forked的Tanks,已经加入开始,开火和击中的声音,各自用独立的channel,好处是同一声音不会overlap。

So far有点跑偏了,原因是我打算先完成Windows下的c++ code,然后port到Python的Pygame上

前面讲到,在cygwin下编译出来的可执行文件,需要依赖X server来render graphics,不是很方便。所以我想直接编译成Windows的图形界面,那么就需要用Visual Studio了,同时要设置Windows下的SDL环境。关于Windows下的SDL,可参见David的how-to-install-sdl2-in-visual-studio,主要是要下载SDL的Windows开发库,包括SDL2 core, ttf(字体), mixer(声音)和image(图像)支持,我只下载了x64 binary,目前最新的是:

我不想安装庞大的VC,也不需要VC的IDE,所以准备只安装VC的Build Tools,甚至不需要Windows SDK,因为根据SDL的文档,它没有其余的dependency。VC Build Tools选择如下:

如果像上图中所有的Optional都清空,只需要2.66GB的空间,可以运行msbuild命令,但是不能运行nmake。运行环境setup通常会看到:'C:\Program' is not recognized as an internal or external command, operable program or batch file. 一方面是空格引起的错误,另一方面环境设置文件如vcvars64.bat并未安装。参见微软文档,需要安装至少一个build环境,如上图的最新MSVC v143 - VS2022 C++ x64/x86 build t..,会额外增加1.6GB的空间。这样环境设置批处理文件都会被安装,不过运行时还会看到The system cannot find the file specified,应该可以忽略。现在可以运行nmake了,需要修改Makefile加入nmake setting,另一个选项是用CMake生成新Makefile。

CMake是Open-Source Cross-Platform Make, 支持Linux,Windows和MacOS。在VS Code中可安装CMake(用来编辑CMakeLists.txt)和CMake Tools(微软为VS Code定制的CMake extension)。如果不用微软的CMake Tools, 也可以直接创建CMake task(参见https://www.40tude.fr/compile-cpp-code-with-vscode-cmake-nmake,需要保证环境变量Path里有CMake的路径)。在用微软的CMake Tools时,我遇到了:

[proc] Executing command: "C:\Program Files\CMake\bin\cmake.EXE" --no-warn-unused-cli -DCMAKE_EXPORT_COMPILE_COMMANDS:BOOL=TRUE -Hc:/w/Tanks -Bc:/w/Tanks/build -G "Visual Studio 17 2022" -T host=x64 -A win32
[cmake] Not searching for unused variables given on the command line.
[cmake] -- Selecting Windows SDK version  to target Windows 10.0.19044.
[cmake] -- The C compiler identification is unknown
[cmake] -- The CXX compiler identification is unknown
[cmake] CMake Error at CMakeLists.txt:3 (project):
[cmake]   No CMAKE_C_COMPILER could be found.

可是MSVC v143已经安装了!CMakeOutput.log显示:

cannot open input file 'kernel32.lib'

这个kernel32.lib应该是从Windows SDK来的,难道必须安装这个庞大的SDK?这个missing lib看起来和上面的No CMAKE_C_COMPILER好像没关联?还是先试试法国人的CMake task吧(我加了 "group": "build",这样就不用"alt-t"=>选task,直接"ctrl-shift-b"=>选build。同样有错:

CMake Error: Could not create named generator 

可是task里已经设了:-G 'NMake Makefiles'。Debug了半天,原来是双引号惹的祸,而且args应该是给list,所以args line应该像这样:

            "args": ["-G \"NMake Makefiles\"", "-DCMAKE_BUILD_TYPE=Debug", ".."],

另外NMake Makefiles不支持toolset设置,如: -T host=x64 -A win32

如果看到错误:

CMake Error at CMakeLists.txt:3 (project):
  Running
   'nmake' '-?'
  failed with:
   The system cannot find the file specified

这是因为没有运行Visual Studio的环境变量设置,VS code找不到nmake可执行文件。

为了绕开诸多麻烦,我直接改了Makefile用cl直接build,然后就遇到问题:

 fatal error C1083: Cannot open include file: 'stddef.h': No such file or directory

 网上一查,Introducing the Universal CRT http://blogs.msdn.com/b/vcblog/archive/2015/03/03/introducing-the-universal-crt.aspx
"The headers, sources, and libraries are now distributed as part of a separate
Universal CRT SDK. This SDK is included with Visual Studio; it is installed by
default to C:\Program Files (x86)\Windows Kits\10."。看来还是必须安装Windows SDK,最新的Windows 11 SDK, another 2.27GB。装了Windows Kits(SDK)后,至少微软的CMake Tools可以成功生产build file。

@Update on Dec 29, 2021: 一番折腾后终于搞定CMake, 虽然不够完美。CMakeLists.txt文件已经push到forked的Tanks。上面提到的下载的SDL库和头文件要重新安排目录结构,排成和Linux的一样,就不需要改动任何源程序了,然后把所有的SDL文件放在根目录下SDL子目录,这样Makefile就可以用相对目录了。用CMake/NMake build:

  1. cd build
  2. cmake -G "NMake Makefiles" ..
  3. nmake
  4. manually copy all SDL dll file to build/out
  5. All done. Just run: build/out/tanks.exe


Wednesday, December 22, 2021

教小朋友编程之坦克大战 1

教小朋友编程是个任重道远的活,特别是当小朋友不热心学习,上课只是应付,希望混完时间好继续玩游戏。想让小朋友好好学,就要保证课程通俗易懂,又要好玩,小朋友最喜欢玩游戏。

 很多推荐从Scratch(麻省理工MIT创建的像搭积木式的流程编程)学起。Jon Woodcock写的《Coding Games in Scratch: A Step-by-Step Visual Guide to Building Your Own Computer Games》很不错,小朋友基本可以step by step一步步做下来,书中有少许bug或missing的地方可能要成人程序员的帮助才能解决,不过其中的几个小游戏还是很不错的。Scratch的问题是太过简单,对稍微大点的孩子能学到的编程知识非常有限。

就我个人看来,Python和Java是另外两个适合作为入门编程语言,Python尤为容易作为起步。教小朋友可以从游戏编程开始,比如Minecraft。Minecraft网站提供python-101,可能有些课件不是free的,可以参看David Whale, Martin O'Hanlon写的《Adventures in Minecraft》,同样有step by step的instruction,可以教小朋友Python的基本数据类型,程序逻辑等,很不错。

国内有提供Python教程以坦克大战为题,是个很好的题材。当年我们曾在游戏机上乐此不比的玩这个游戏(Tank 1990)。


我于是上网查了查,有人用C++编写了这个游戏并公布在Github,是基于C++11和SDL2 2D图形库。源程序很容易在Linux下编译运行,当我在Windows下运行时遇到了几个问题。在Windows上编译时,Makefile是针对MinGW设置的。我个人不喜欢在Cygwin上再安装MingW,所以决定改Makefile,直接用Linux的设置在Cygwin下编译运行,除了不用拷贝链接MingW的库,'-mwindows' option也没有什么作用。需要安装Cygwin SDL2 package: libSDL2-devel, libSDL2_ttf-devel, libSDL2_image-devel。奇怪的是编译后生成的可执行文件运行后,什么都没有发生。通过debug后发现,SDL_Init()返回-1,SDL_GetError返回 "No available video device"。Google结果是Cygwin下需要启动xserver,并设置DISPLAY=:0。此后终于可以在Windows下打坦克大战,只是没有声音。下一步看看怎么把声音加上,和怎样用Pygame来porting。

Saturday, August 14, 2021

Solve SSL Error when installing package with Ruby gem on Windows

Ruby is an old Script language very like Python and Tcl. Some company still use it for old framework and kits, and in some case will have to stick with an old version of the script. I had 2.2.6 installed for this reason. Ruby is using gem for installing package, just like CPAN for Perl, Pip for Python, npm for Nodes. The gem installing used to be working fine for me. Recently when I started to try something new, I would need to install a new package, then I hit this "SSL Error When installing rubygems, Unable to pull data from 'https://rubygems.org/" issue. As usually, I searched for solution via Google, and started to take action as mentioned in this Stack Overflow post: https://stackoverflow.com/questions/19150017/ssl-error-when-installing-rubygems-unable-to-pull-data-from-https-rubygems-o.

I tried gem sources -r https://rubygems.org/ first (note the slash at the end is important, as the url has to match exactly with 'gem sources' command's output, otherwise it will do nothing), then run gem sources -a http://rubygems.org/, but I was still seeing the SSL error, i.e. it is still taking the https protocol. Tried gem update --system, nothing changed, same SSL error. Eventually, I went to RubyGems ssl-certificate-update page, and realized that I will have to manually update the certificate. I followed instruction here: https://bundler.io/v2.0/guides/rubygems_tls_ssl_troubleshooting_guide.html, run this curl -Lks 'https://git.io/rg-ssl' | ruby just to confirm it is certificate issue. Note on Windows, I have to run this command from Cygwin console, otherwise the curl command outputs nothing. After replaced the certificate, now I don't see the SSl issue, instead I'm seeing a new issue: it cannot find any package from repository. Then I tried to run 'gem sources', and realized it shows empty! If I try gem sources -a command, it will complain the same, not able to find repository. This is the frustrate part started: I assume the gem sources -r screwed up something, so I tried to reinstall Ruby. However, no matter how, I just won't be able to get it back to normal. I tried to delete the old installation folder after an uninstall, tried to install to different location, tried to install a latest Ruby release, tried to search and delete all Ruby entry in Windows Registry table. But at the end, 'gem sources' still gives me an empty list.

That's the things I hate Windows, specially the Registry is huge and complex, and no easy way to search a key or value ( I mean with regular expression pattern matching). And I don't understand why an uninstall not able to clean up everything. I don't want to try the Windows Restore point. So I grabbed SystemInternals ProcMon to check why the Ruby Gem just keeps remember the source list even after a reinstall, and eventually found: there is a '.gemrc' file stored in my home folder, and that is the one gem used for the source list. Just delete it would fix all the headache.

This is the story I want to share, if any one encountering the same problem while fixing the SSL issue with Ruby gem.

Monday, May 24, 2021

滤掉烦人的广告

 Google,Facebook等大佬也要靠网页上的广告挣钱,就像本blog也有广告。但君子爱财,取之有道,那种硬弹,骗点最为深恶痛绝。好在浏览器提供插件block这些下三烂的东西,弹出广告可用NoScript,骗链可用Adblock Plus。下图是block前和block后的比较。



 
Highlighted广告在第二个图都被滤掉了,不论标题是多么的迷惑人。关于正确设置ABP filter, 参见:https://adblockplus.org/filter-cheatsheet

 




Sunday, April 25, 2021

Remote Windows PC Uart Access

Last August I posted using Python for Remote Serial Port Access. In fact, there is many other way to do the same, without the need to run a script. The widely used is opening pseudo-ttys via SSH connection, as mentioned https://github.com/npat-efault/picocom:

$ ssh -t user@termbox picocom -b 115200 /dev/ttyS0 

Picocom is a terminal emulator, similar like minicom, PuTTy and Teraterm, with very small footprint. One problem is that it is tty based, and Windows does not expose Serial Port/UART as TTY devices. Cygwin does not provide picocom package. Even we can compile picocom from source for Cygwin, it is worthless as it cannot open Windows native serial port device.

The solution is WSL. With WSL, it is possible to access native device from the Linux environment running as Windows Sub-System. Nowadays, model PC/Laptop does not have RS-232 port, mostly, external device with UART output will be connected to PC with a Uart-over-USB (FTDI chip). Unfortuenately, as of today, WSL2 still does not support USB device. As I mentioned here, may need to stick with WSL1 for this feature at this moment.

Two things need to be done on WSL: install picocom and setup SSH server.

Install picocom

Most Linux distribution provide picocom install package, such as Ubuntu/Debian, user can run sudo apt install picocom to have it installed in seconds. However there is one issue: may run into error as 'FATAL: failed to add port: Cannot get the device attributes: Inappropriate ioctl for device'. This is a known issue with custom baud-rate support, and as mentioned in the ticket the solution is either build the binary with CPPFLAGS=-DNO_CUSTOM_BAUD make or run picocom with env setting: NO_CUSTOM_BAUD=1. If taking the env setting way, need to make sure the setting is taking effect for SSH session. So better use the build option. 
To build it, download the picocom source from https://github.com/npat-efault/picocom, install gcc and make for WSL if you haven't done so:
sudo apt install gcc make
If runs into issue, likely you will need to do: sudo apt update --fix-missing
Then build the binary as mentioned above: CPPFLAGS=-DNO_CUSTOM_BAUD make
Once build is done, copy the executable to a executable path such as /usr/local/bin.

Setup SSH server

May refer this for how to setup SSH on WSL. Before try the SSH access, make sure on SSH server side, has port 22 opened from Windows Firewall.
Install and setup SSH server just like on a Linux setup: sudo apt install openssh-server
By default, it will have PasswordAuthentication off and PubkeyAuthentication on. And for pubkey, it may be using ECDSA but not RSA. So if running into SSH permission denied (publickey) issue, may need to play with sshd config setting: sudo nano /etc/ssh/sshd_config
May try ssh -vvv username@the_wsl_host to triage the error. The '-vvv' option should give out lot of useful information of the error. Once sshd_config is updated, run sudo service ssh --full-restart to restart the sshd (systemctl restart sshd for old version Linux).
 

Open UART remotely

ssh -t user@wsl_host picocom -b 115200 /dev/ttyS10

Above will try to open the COM10 on the wsl_host pc remotely. Note picocom is a terminal emulator, just like minicom, there is no GUI interface. To quit, press C-a, then C-x. Looking for help? Press C-a, then C-h.

Tuesday, February 23, 2021

The journey for updating Realtek NIC MAC

Realtek Network Interface Controller (NIC, also known as a Network Interface Card) is widely used in PC. Usually an EEPROM would be connected to the RTL NIC chip to provide programmable storage for saving some network related setting, such as MAC address. IP address is bound with the MAC. So if multiple NIC has same MAC, it would be a disaster for switch/bridge/router to correctly forward IP packet.

On Linux and Windows, it is possible to change the MAC address temporarily by using some command such as ifconfig, but the setting won't persist during reboot. It is also possible to override the MAC address with a saved file or value stored in Registry table and keep the change permanently. However, this change can also get lost if the card is moved to a different setup, or the OS gets reinstalled.

So to permanently change the MAC, will need to reprogram the EEPROM. There is an Open Source tools, rtl8168-eeprom, supposed can be used to update EEPROM. However, several issues to get it working:

1) open('/dev/mem') may fail, due to a new kernel feature 'KERNEL_LOCKDOWN'.

2) Rebuild kernel from source. After build and install, it cannot boot the new kernel with error

/boot/vmlinuz-x.y.z-generic has invalid signature

This is due to for secure boot, customer kernel has to be signed. Refer to this.

3) Tried to build kernel with CONFIG_SECURITY_LOCKDOWN_LSM disabled, will run into problem during kernel_config, as KERNEL_LOCKDOWN is forced on due to config policy setting

4) Build old kernel 4.4 from source for Ubuntu 20.04 (Focal Fossa) doesn't work very well, as the kernel version is too low which cause build problem.

5) So the way to run the tools is install kernel 4.4 deb package from LaunchPad. However, the tools cannot properly access RTL8168 EEPROM as it failed to read back the ID from EEPROM.

Ethtool has option '-m' for dump module EEPROM, '-e' for dump EEPROM, and '-E' for update MAC. However, running ethtool with these option may get  'Operation Not Permitted' error. Run 'ethtool -i devname' may get 'support-eeprom-access: no'. So the NIC driver does not support EEPROM access.

As a side note, Realtek might have released some tools for this purpose, which can run on Windows, Linux, and UEFI shell. You can search for 'RTNicPG' from Internet. I'm able to find several links but none of them from Realtek official website. Maybe it got leaked out as an internal used tools.

Sunday, February 7, 2021

Update build.gradle for build native code with NDK

Because of Android Studio/Gradle keeps evolution, and the special need of Android NDK's configuration, sometimes it is a little difficult to get things working smoothly.

There is some references like:

https://riptutorial.com/android/example/13985/enable-experimental-ndk-plugin-support-for-gradle-and-androidstudio

https://stackoverflow.com/questions/16667903/android-studio-gradle-and-ndk

https://android-developers.googleblog.com/2020/02/native-dependencies-in-android-studio-40.html

Will see some mismatch between above posts, or things not working with Android Studio, such as with Android Studio 4.1.2, Gradle model 6.5, the ndk setting in above first link will lead to weird error. The 2nd link from stackoverflow has the correct setting, i.e. ndk setting has to be put under defaultConfig, specially the abiFilters setting. As explained in the 3rd link, when deal with native code, frequently may need to link with prebuilt lib, which may only support one special ABI such as armeabi-v7a, but not all others such as 64 bit or x86. Here is an example app build.gradle file for android-eye:

apply plugin: 'com.android.application'

android {
compileSdkVersion 14
buildToolsVersion "30.0.3"
ndkVersion "17.2.4988734"

defaultConfig {
applicationId "teaonly.droideye"
targetSdkVersion 14
minSdkVersion="14"
ndk {
abiFilters 'armeabi-v7a'
// 64-bit support requires an Android API level higher than 19; Namely 21 and higher
//abiFilters 'armeabi', 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
//cppFlags.add("-O2 -Werror -Wall")
//ldLibs.addAll(['log', 'z', 'ld'])
stl = "c++_static"
}

}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
externalNativeBuild {
ndkBuild {
path file('src/main/jni/Android.mk')
}
}
}

dependencies {
implementation files('libs/java_websocket.jar')
}

Building under Android Studio may hide the detail of the build, which makes it difficult to root cause when something goes wrong.

Beside gradle related setting, sometimes developer might get sysroot setting issue. Such as compiling x264 with NDK (specially old version) sometimes need some tweak, such as sysroot setting. Refer to SO1, SO2, and BuildSystemMaintainers for latest new NDK. For old NDK, at compile time sysroot is $NDK/sysroot, and at link time sysroot points to $NDK/platforms/android-$API/arch-$ARCH. One way is refer to standalone_toolchain, run $NDK/build/tools/make_standalone_toolchain.py --arch arm --api 14 --install-dir /tmp/my_toolchain to create a standalone toolchain. May need to specify CFLAGS=-D__ANDROID_API__=$API as mentioned here. The other possible way is refer to this: Using clang instead of gcc also works, e.g. for autotools-based projects CC=arm-linux-androideabi-clang CXX=arm-linux-androideabi-clang++ ./configure --cross-prefix=arm-linux-androideabi- ... works without disabling unified headers and without specifying __ANDROID_API__

With new version NDK,  'Application.mk' has to be provided. Also, NDK will assume the 'Application.mk' and 'Android.mk' are all located under a 'jni' sub-folder. If that is not the case, then user will have to specify the path of 'Application.mk' while invoking 'ndk-build' script, by setting NDK_APPLICATION_MK, and in 'Application.mk', user has to specify the path of 'Android.mk' by set 'APP_BUILD_SCRIPT'. Refer to https://developer.android.com/ndk/guides/ndk-build for more detail.

Saturday, January 9, 2021

学习TensorFlow - 设置Python环境

 TensorFlow的网址:https://www.tensorflow.org,Wikipedia介绍,是由Google开发,后来捐献成开源项目,提供machine-learning的API和库支持。虽然TensorFlow的core是用C++开发的,TensorFlow同时提供多种语言如C++, Python, Java等的外包(wrapper),而Python目前还是ML最流行的开发语言。TensorFlow适用于底层建模,上层可用Keras等module来简化。

TensorFlow的教程很多,我也还在学习。设置Python环境是第一步,很多教程提供了不同的设置却没有明确的解释为什么。Python有很多不同的版本,其中2.x和3.x差别很大,另外Python有很多软件包,这些包也有不同版本。一个复杂的项目可能用到特定版本软件包,如果把多个项目安装在同一环境下,可能会遇到软件包版本冲突,所以简单的解决办法就是隔离每个项目的运行环境。为了达到这个目的,可以用Python的env包来设置虚拟环境,或安装Docker container,或安装Anaconda/MiniConda并建立虚拟环境。Python虚拟环境的实质就是把所有的软件包和工具安装在单独的目录下来避免冲突。所有每增加一个环境都要占用更多的硬盘空间。实际上我之前在“Get fun with google assistant”提到的Google Assistant虚拟环境可以与TensorFlow共用。

有的教程要安装PyCharm, 其实完全没必要。PyCharm是Jetbrains开发的Python集成开发环境(IDE),是个很不错的软件(Google的Android Studio是基于Jetbrains开发的IntelliJ IDEA, JetBrains的TeamCity是仅次于Jenkins的Continous Integration Tool),用Visual Studio Code开发也很适手。

注意TensorFlow 2.0有很多改变不同于1.0,所以遇到AttributeError: module 'tensorflow' has no attribute 'placeholder',请参照https://www.tensorflow.org/guide/migrate,简单的办法是把

import tensorflow as tf
改成:
import tensorflow.compat.v1 as tf
tf
.disable_v2_behavior()
@ Mar 11, 2023
Windows上设置miniconda有时有点very frustrate,主要是安装过程可能没有设置系统路径(System Environment
 Variable: PATH),所以当用户在自己打开的cmd console下运行conda command时,只会得到找不到命令的错误。
所以最好把conda的path加到Environment Variable Path setting, 注意conda.exe通常是在Scripts子目录下。
VSCode通常无法detect到conda/env setting,如果conda executable不在系统路径里。关于在VS Code中设置
Python Environment,可参见: https://code.visualstudio.com/docs/python/environments