2021年5月16日 星期日

TI Launchpad MSP430 with PIR(紅外線感應器)

緣起:
最近聽到有人的辦公室座位坐在靠走道人來人往,隱私被看光光,所以想研究能夠偵測有人靠近的"紅外線感應器(PIR)",將心得寫成此篇blog.本篇blog有不足之處,日後補上,轉貼或引用本篇文章, 不必交代出處!

系統架構: 
MSP430+PIR當偵測到有人靠近就送出一個字元資料'@'透過rs232傳輸到個人電腦PC端, PC端寫一個專門接收rs232(COM3)訊號的程式(ezPIR),當ezPIR程式收到rs232介面傳過來的資料, 馬上模擬鍵盤向作業系統送出一個"視窗鍵+D(將所有工作視窗縮小並顯示桌面)", 網購的PIR型號AM312如下:

所有程式碼下載連結:
https://drive.google.com/file/d/1FKPrjo4tR3qEZACkTcZNQEiyiAl1ANcX/view?usp=sharing


2021年1月31日 星期日

Win32視窗程式_WM_CLOSE_trace code_第二彈

緣起:
最近在研究Win32平台的組合語言, 想看一下Win32API視窗程式在使用者按下右上角紅色叉叉觸發WM_CLOSE訊息後,是怎樣關閉整個視窗的,將心得寫成此篇blog.本篇blog有不足之處,日後補上,轉貼或引用本篇文章, 不必交代出處!

過程:
1.開啟Visual Studio 201x->新增專案->Visual C++ ->Win32專案->取名為traceWM_CLOSE->完成,
2.修改traceWM_CLOSE.cpp程式,在UpdateWindow(hWnd);這行的底下加入底下的程式:
   PostMessage(hWnd,WM_CLOSE,0,0);
   p.s.在主訊息迴圈那設中斷點導致無法按視窗右上角的紅色叉叉,只好用程式送WM_CLOSE訊息,

3.另外將return DefWindowProc(hWnd, message, wParam, lParam);這行註解,改為底下的程式:
   int LRESULT=DefWindowProc(hWnd, message, wParam, lParam);
   return LRESULT;

4.先在PostMessage()這行設中斷點, 按F5, 
5.取消中斷點, 在GetMessage()跟DispatchMessage()這兩行設中斷,不斷按F5直到msg數值為0x10,
6.在WndProc()內第1行及return DefWindowProc()設中斷,不斷按F5,同時觀察"呼叫堆疊"的變化如下:
   WM_CLOSE(0x10)
     ->產生WM_XXX(0x90)
      ->WM_WINDOWPOSCHANGING(0x46)
        ->WM_WINDOWPOSCHANGED(0x47) 此時視窗已消失,但"工作管理員"仍顯示該行程!
          ->WM_IME_SETCONTEXT(0x281)
            ->WM_IME_NOTIFY(0x282)
              ->WM_DESTROY(0x2) 此時先在PostQuitMessage(0);設中斷點,按F5可看到跳到中斷點這,
               ->WM_NCDESTROY(0x82), 此時已產生WM_QUIT於系統訊息queue,
7.程式到此才處理完WM_CLOSE訊息,返回主訊息迴圈,可觀察msg仍維持0x10(WM_CLOSE),這時再GetMessage()就得到WM_QUIT(0x12)而跳出迴圈, 然後return結束整個程式,此時在工作管理員已看不到這個行程!

結果:
關於以上過程各步驟的精彩截圖, 請到底下這個網址下載WORD檔來觀看:
https://drive.google.com/file/d/1eiJcAJ3KfBOps49S63CGp6kN6zyFLXIY/view?usp=sharing

2021年1月23日 星期六

C語言_main函數_trace code

緣起:
最近在研究Win32平台的組合語言, 想看一下C語言的底層長甚麼樣子,就拿最簡單的程式來看:
  int main( )
 {
 }
將心得寫成此篇blog.本篇blog有不足之處,日後補上,轉貼或引用本篇文章, 不必交代出處!

過程:
1.開啟Visual Studio 201x -> 新增專案 -> Visual C++ -> Win32主控台應用程式 -> 勾選空專案,
2.方案總管->原始程式檔->加入->新增項目->C++檔(.cpp)->檔名為Source.cpp
3.在Source.cpp內輸入下列程式碼:
  int main()
 {
 }

4.在int main()這行前面設定中斷點,按F5開始偵錯, 切到"反組譯碼", 按F11一步一步執行如下,特別注意圖上右邊三塊粉紅色區塊跟粉紅色字的區塊,最下面的區塊表示最早看到的呼叫堆疊, 只要F11按得夠久就可看到粉紅色字的區塊顯示的ExitProcess函數(VC++2010 express可看到,VS2015則看不到,那些是從google找到別人使用VS2015看到的造成runtime error當時的callStack),等該函數執行完就結束整個行程(process)[註1][註2]:

5.上圖中執行到ret(pop下一行指令的位址存到eip)後回到上一層函數內,上圖跟下圖是分兩次trace,所以stack內存的位址會不同:

6.將stack看到的參數2位址006da008打入"記憶體"內的位址這欄內按enter,解析如下:

7.將stack看到的參數3位址00687cc0打入"記憶體"內的位址這欄內按enter,解析如下:

註1:第四個步驟的附圖中提到cc cc cc cc共192Bytes的區塊是當作stack預留的guard band是錯誤的,
       因為隨後自行trace函數main內有程式碼的案例, 發現這區塊被拿來存main()內宣告的變數/指
       標,請見下圖:

註2.除了記憶體視窗/暫存器視窗/反組譯碼視窗以外,VS201x系列還提供命令視窗可輸入指令也可
       看到記憶體內容/暫存器/反組譯碼,這種方式的優點:可看出程式執行前後差異,缺點:常打指令,
       詳細指令請參考微軟網站:
https://docs.microsoft.com/zh-tw/visualstudio/ide/reference/list-memory-command?view=vs-2019


2018年1月21日 星期日

GridView轉Excel(純手工)

緣起:
最近聽到有人提起舊版Crystal Report的簡單報表要轉到新系統去又不想繼續用crystal report維護,就著手研究如何將GridView轉成Excel,將心得寫成此篇blog.本篇blog有不足之處,日後補上,引用本篇blog不必註明出處,但程式部分有些參考網路上的資料而修改的,請注意智慧財產權!

程式參考網站:
1.ASP.NET Response.End()使用時請小心 - SlashLook
 slashlook.com/articles_20131117.html
2.[CSS]網頁資料輸出轉為Excel檔案時數字資料強制為文字呈現(含其他mso支援格式轉換)
 https://dotblogs.com.tw/blackie1019/2013/09/30/122114

3.[ASP.NET][WebControl] GridView簡易匯出Excel
 https://dotblogs.com.tw/shunnien/2013/04/11/101414

程式細節:
1.一般GridView轉Excel網路上找到的文章大多是利用RenderControl函數來做,這邊不再贅述!請自行google關鍵字"gridview轉excel"就會找到一脫拉庫的文章講如何轉以及相關注意事項!這裡要介紹的是ASP.NET網頁有使用MasterPage的,利用網路上教的RenderControl函數轉出來的報表會連同MasterPage的東西也一併轉出來,若只想將子網頁的GridView表格轉成Excel就要自己寫程式去做本來RenderControl函數自動會做的事,就是自己寫程式手動render一些HTML標籤(請參考上述第3個參考網站).

2.若直接使用Response.End()會產生錯誤的請參考上述第1個參考網站!

3.有時候將資料轉成Excel時,Excel會自作聰明將0開頭的數字自動去除開頭的0,請參考上述的第2個參考網站!

範例程式:
https://drive.google.com/file/d/1nJuQxjriRGIxJbCbZ_x8Lu24qMTOSRfN/view?usp=sharing

2017年7月1日 星期六

用C#寫crawler(網路爬蟲)

緣起:
最近聽到有人提起新需求,就寫了一個小工具,需求情境如下:假設有人叫你到某個網頁看"名單"(每月公告1次),然後根據"名單"去更改你SQL資料庫某張table的內容,如果名單很長,眼睛會看到花掉,手也會很痠,而且每個月只做1次,常常忘了做!所以你會想寫一個小工具,設到作業系統的"排程"裡面,每月或每周1次,時間到了,排程自然會呼叫小工具去幫你做這件事,做完會將結果存成log檔,你有空再去看看log即可!本篇blog有不足之處,日後補上,引用本篇blog不必註明出處,但程式部分有些參考網路上的資料而修改的,請注意智慧財產權,

程式參考網站:
1.C#實現通過程序自動抓取遠程Web網頁信息的代碼
 http://dark99.pixnet.net/blog/post/38459994-c%23%E5%AF%A6%E7%8F%BE%E9%80%9A%E9%81%8E%E7%A8%8B%E5%BA%8F%E8%87%AA%E5%8B%95%E6%8A%93%E5%8F%96%E9%81%A0%E7%A8%8Bweb%E7%B6%B2%E9%A0%81%E4%BF%A1%E6%81%AF%E7%9A%84%E4%BB%A3
2.Windows 7-善用工作排程器
 http://isvincent.pixnet.net/blog/post/38936955-windows-7-%E5%96%84%E7%94%A8%E5%B7%A5%E4%BD%9C%E6%8E%92%E7%A8%8B%E5%99%A8

程式細節:
這個算是初級的crawler(網路爬蟲),程式大略分三部分:
 - 1.去網路上抓資料(圖1),

 - 2.解析抓回來的資料(圖2),












 - 3.連到SQL資料庫做事(圖3),










注意事項:
程式需要做"例外處理"增強程式的強固性(robust),避免程式因發生例外而中止執行。無論是利用C#語言特性(try-catch機制)或是函數回傳值判斷等等,

本篇blog附上範例程式的使用方式:
1.本篇blog是以windows7電腦為例子,請自行去微軟官網下載.net framework SDK或是Visual Studio 201X community(稍早的VS2010免費版叫express)來安裝,安裝好之後請到"開始"->"所有程式"->Visual Studio 201X community,找看看裡面是否有VS201X x86 Tools命令提示字元,跑起來就是一個MS-DOS命令列視窗,

2.將本篇blog附上的zip檔解壓縮,用"記事本"打開crawler3.cs開始依自己需求編輯程式,存檔,

3.另外AssemblyInfo.cs也可用記事本打開進去編輯,稍後編譯成功會在build目錄內看到可執行檔(*.exe),將滑鼠移到這個檔名可看到版號跟公司名,

4.另外crawler3.exe.config也可用記事本打開進去編輯,這個檔是用來指定要將source編譯成哪個目標平台(.net framework的版本)的可執行檔, 在編譯完成之後要跟.exe放在一起才會有作用,假設你把這個可執行檔拿到win xp(.net framework最高到4.0)去跑,自動先幫你檢查目前電腦內是否有裝目標平台(.net 4.6),結果沒有,就會跳出一個警告視窗說你缺少.net framework 4.6,請你先去裝好再來跑這個可執行檔,這個.config假設沒跟.exe放在同一目錄下或是名字不一致,就會跳過這個檢查,然後以目前最高版本.net 4.0(假設你xp有裝.net 4.0的話)來跑可執行檔,直到碰壁為止(遇到call .net 4.6的api就會exception跳出),

5.另外一個AssemblyAttributes.cs也可用記事本打開編輯,這個檔也是告訴編譯器csc.exe要用哪個目標.net framework版本下去編譯,搭配參數/reference指定引用哪個目標版本的library,

6.在步驟一開啟的MS-DOS命令視窗內,輸入dos指令到達剛解壓縮目錄內的src目錄底下,輸入"build"按enter開始編譯,因為有加參數"/debug+",編譯成功後除了產生可執行檔外還會產生*.pdb,這個是用來讓你可以進去VS201X community裡面逐步執行debug用的,也就是可執行檔案產生之後,除了直接輸入"crawler3.exe"來跑程式,也可輸入"devenv crawler3.exe",進到VS201X後馬上按F11(逐步偵錯)會叫出crawler3.cs,可在某行設置中斷點debug,利用VS201X來跑你的執行檔另一個好處是可將VS201X當成sandbox,無論你的程式寫的多糟糕導致不可預期的例外發生都會被侷限在VS201X內部,若你在"檔案總管"左鍵點兩下跑可執行檔,到時候程式當掉,可能會危及作業系統當時正在跑的其他應用程式,
p.s.devenv.exe就是你裝的Visual Studio 201X的執行檔(VS201X的桌面捷徑->右鍵"內容"),有些版本的VS201X不叫devenv.exe而是別的名稱,

7.參考上面說的網頁"Windows 7-善用工作排程器",將crawler3.exe設到排程裡頭,時間到了,排程器會叫醒crawler3.exe起來工作,到時候就可以到D槽底下找今天日期的log檔,

範例程式:
https://drive.google.com/file/d/0B6EVEd5P2B9cVW90bzdDMGZhQkU/view?usp=sharing

2016年6月19日 星期日

用C++寫2D捲軸射擊遊戲_第二彈

緣起:
1.繼上次5月15號發表文章到現在,所做的事情就是重構當時所附的程式,依物件導向三大精神(封裝/繼承/多型)繼續擴充下去,將類別的程式從game.h移出,1個類別就單獨寫成1個檔案(*.h),
2.另外就是新增3條命(我機設定不再是無敵狀態)/計分/大絕招/Lv1新增怪物種類/Lv1 Boss/Lv1過場動畫/遊戲說明,
3.目前寫完第一關卡,大家可以參考這個更好的雛型修改成自己想要的模樣,本篇blog有不足之處,日後補上,請注意引用本篇blog不必註明出處,但程式部分有些參考網路上的資料而修改的,請注意智慧財產權,

程式參考網站:
1.C++實務班(http://garfstudio.blogspot.tw/2015/12/cyoutube.html),
2.DirectX教學網站(http://www.rastertek.com/dx11tut14.html),

程式細節:
1.先由game.h抽出基底類別circle,由此衍生出bullet類別跟unit類別:
 - bullet類別是所有子彈類別(例如:大絕招EMP)的基底類別,
 - unit類別是敵機(史萊姆slime,哥布林goblin,豆腐tofu)跟我機類別(hero)的基底類別,
 - 而用bullet類別建立的物件又是unit類別的成員,

2.將unit類別改為抽象類別,建立多型的架構:
 - 每個衍生類別各自覆寫draw函數/move函數/shoot函數,這樣就可以有各自的造型/移動模式/子彈類型,
 - 所有的不同種類的敵機,包含boss(tofu.h),通通被塞入vMonster的linked list當中,在game.h內用迭代器(同一介面)走訪linked list內所有的敵機,就可以有各種不同造型/移動模式/子彈的敵機,

3.同理,bullet類別也建立多型的架構,繼承bullet類別的迴力鏢boomerang跟EMP也都通通塞入vBullet的linked list當中,用同一介面走訪linked list內所有的子彈,

4.新增腳本類別script,這類別就像是扮演導演的角色,安排何時該由哪個敵機上場演出(由Score去劃分),
 - 亦即今天要新增新的敵機種類只要去改script.h跟新增新種敵機的.h檔即可,不需要改到走訪的介面(game.h),

本篇blog附上範例程式的使用方式:
1.在任何一種版本的Visual Studio建立C++ win32專案,專案名稱打"JustShootIt",專案建立後再修改專案->屬性->不使用Unicode字集,專案->屬性->C/C++->先行編譯標頭檔->不使用先行編譯標頭檔,開啟JustShootIt.cpp,清光內容,
2.將範例程式解壓縮,除了JustShootIt.cpp以外,其他檔案都放到專案的那個目錄內,用記事本打開JustShootIt.cpp,全部複製貼到Visual Studio編輯視窗的JustShootIt.cpp裡頭,
3.依序為專案加入*.h,soundclass.cpp,
4.build->Run,

遊戲操作方式:
1.射擊子彈:空白鍵,
2.上下左右方向鍵控制我機的移動方向,
3.大絕招EMP:Z鍵,

遊戲畫面:
範例程式:
https://drive.google.com/file/d/0B6EVEd5P2B9cTzlVNzAzTF9lRFE/view?usp=sharing

062516更新:
1.修正boomerang移動模式,
2.修正一些bug,
3.修改directSound每回play音效都先設定音量,改成初始化時就先設好音量,

範例程式:
https://drive.google.com/file/d/0B6EVEd5P2B9cN3BuN3R0alI5eXM/view?usp=sharing

082918更新:
提供底下新版的範例程式,編譯的方式請參考另一篇文章"用C#寫crawler(網路爬蟲)":
https://drive.google.com/file/d/1epY8jdeezFkcUH4l7nMf1jAKZghcmOr4/view?usp=sharing

2016年5月15日 星期日

用C++寫2D捲軸射擊遊戲

緣起:
學習C++多年,一直想自己寫個game,近日寫game的background knowledge已趨完整俱備,就寫了一個2D垂直向捲軸射擊game雛型,中文就叫"射擊就對了",這個game已具備2D捲軸射擊基本要素:我機(目前設定是無敵狀態)/敵機/子彈/場景/音效,目前改進的空間還很大,日後會補上計分系統/吃彈藥包等等,大家可以參考這個雛型修改成自己想要的模樣,本篇blog有不足之處,日後補上,請注意引用本篇blog不必註明出處,但程式的部分是參考網路上的資料而修改的,請注意智慧財產權,

程式參考網站:
1.C++實務班(http://garfstudio.blogspot.tw/2015/12/cyoutube.html),
2.DirectX教學網站(http://www.rastertek.com/dx11tut14.html),

程式細節:
1.我機/敵機/子彈:這部分的程式是參考底下這個網站修改而成:
http://garfstudio.blogspot.tw/2015/12/cyoutube.html
這位作者(Gary Lin老師)在youtube有放上完整教學影片_C++程式設計:(https://www.youtube.com/channel/UC6kvAnrYEXwE4tVG8zOdWvw),
建議初學者請先完整看完全部29小時的課程(29部影片),所以這部分程式不多作解釋,

2.背景捲軸:原本從天文網站抓一張星象圖裁成800*600的24-bit BMP無縫圖,每次向上捲動幾個pixel,結果原先只有白背景+我機+敵機+子彈時的fps還有1k~2k,加上背景後只剩4,最後換另一種做法,將背景圖切成10x10的小矩形,由這些小矩形來構成背景圖,然後每次捲動一列,fps可提升到幾百,但目前暫時限制住fps為30左右,

3.音效:由C++實務班的youtube影片中得知簡單播放音樂的函數是playsound(),但無法同時播放兩種以上的音效(這叫混音),在第一個背景音樂(重複播放)播放時,又播放第二個音效檔,會導致第一個音效停止播放,微軟論壇有人問過這個問題:
https://social.msdn.microsoft.com/Forums/vstudio/en-US/de87d08e-dab6-4b4e-948a-3ef4142b7e04/how-could-i-mutiple-sounds-with-playsound?forum=vclanguage,
有人提出Direct Sound(DirectX SDK的一部份)這組api可以做出"混音"效果,先抓微軟官網的DirectX SDK回來安裝,其實只要安裝include(標頭檔)跟Lib即可讓程式編譯,在網路上有找到教學網站(DirectX教學網站:http://www.rastertek.com/dx11tut14.html),拿範例程式(soundclass.h,soundclass.cpp)來改成同時播三個音效,這三個音效檔是windows作業系統內建的,DS1.wav當背景音樂所以設成重複播放,DS2.wav當發射子彈的音效,DS3.wav當子彈打到敵機的音效,

本篇blog附上範例程式的使用方式:
1.在任何一種版本的Visual Studio建立C++ win32專案,專案名稱打"JustShootIt",專案建立後再修改專案->屬性->不使用Unicode字集,專案->屬性->C/C++->先行編譯標頭檔->不使用先行編譯標頭檔,開啟JustShootIt.cpp,清光內容,

2.將範例程式解壓縮,除了JustShootIt.cpp以外,其他檔案都放到專案的那個目錄內,用記事本打開JustShootIt.cpp,全部複製貼到Visual Studio編輯視窗的JustShootIt.cpp裡頭,

3.依序為專案加入game.h,dsound.h,fps_time.h,key_state.h,map.h,soundclass.h,soundclass.cpp,

4.build->Run,

遊戲操作方式:
1.射擊子彈(滑鼠游標跟我機連成一線的方向就是子彈的射出方向):Shift鍵+Z,
2.上下左右方向鍵控制我機的移動方向,

遊戲畫面:

範例程式:
https://drive.google.com/file/d/0B6EVEd5P2B9cVDhIaGFqRVI3OUk/view?usp=sharing