<<

INDIAN INSTITUTE OF TECHNOLOGY, BOMBAY EKLAVYA SUMMER INTERNSHIP 2019 (FUNDAMENTAL RESEARCH GROUP)

Porting of /C++ Applications on the Web

Under the guidance of: Prof. S. Sudarshan

Team: Mentors: Ajit Kumar Mr. Nagesh Karmali Akash Soni Mr. Rajesh Kushalkar Sarthak Mishra Shikhar Suman Yasasvi V Peruvemba text Summer Internship 2019 Project Approval Certificate

Department of Computer Science and Engineering

Indian Institute of Technology Bombay

Certificate

The project entitled Porting of C or CPP Desktop Applications on the web sub- mitted by Mr. Ajit Kumar, Mr. Akash Soni, Mr. Sarthak Mishra, Mr. Shikhar Suman and Mr. Yasasvi V Peruvemba is approved for Summer Internship 2019 programme from 19th May 2019 to 9th July 2019, at Department of Computer Science and Engineering, IIT Bombay.

Prof. S. SUDARSHAN Mr. NAGESH KARMALI Dept. of CSE, IITB Dept. of CSE, IITB Principle Investigator Sr. Project Manager

Mr. RAJESH KUSHALKAR Dept. of CSE, IITB Sr. Project Manager

Date: July 4, 2019 text Acknowledgement

We have spent a lot of effort on this project. However, it would not have been pos- sible without the kind support of various individuals and organizations, we would like to extend our sincere thanks to all of them.

We would like to express our sincere thanks and regards to Prof. D.B.Phatak and Prof. S. Sudarshan, Indian Institute of Technology, Bombay for providing us this unparalleled opportunity to work on this esteemed project. We would also like to extend our sincere thanks to Mr. Nagesh Karmali for supervising our project. Our sincere thanks to Mr.Rajesh Kushalkar, without whom the project would not be this refined and successful.

Finally we usher our thanks to the open-source community and others who have willingly assisted us in the smallest possible manners in the development of the project. Declaration

I declare that this written submission represents my ideas in my own words and where others’ ideas or words have been included, I have adequately cited and ref- erenced the original sources. I also declare that I have adhered to all principles of academic honesty and integrity and have not misrepresented or fabricated or falsi- fied any idea/data/fact/source in my submission. I understand that any violation of the above will be cause for disciplinary action by the institute and can also evoke penal action from the sources which have thus not been properly cited or from whom proper permission has not been taken when needed

AJIT KUMAR SHIKHAR SUMAN IIT ISM DHANBAD IIT ISM DHANBAD

AKASH SONI YASASVI V PERUVEMBA NIT HAMIRPUR IIT INDORE

SARTHAK MISHRA SIT TUMKUR Abstract

Porting of applications to the web, refers to the transpiling of desktop applications, coded in C/C++ into it’s JavaScript counterpart, which can then be hosted as a web-service. This is an FRG Project aimed towards a more secure and space effi- cient alternative for native applications.

In the upcoming sections, the methodologies and techniques used are described, along with the specified results. Also, more insight about the key technologies used is given, justifying why they were necessary for the project. The basis behind the applied technology is also justified below.

In this project, we have achieved success in porting four different applications viz. PNGCrush, Tetris, GNUPlot and SimAVR. text List of Figures

1.1 WebAssembly Flow ...... 4

2.1 Emscripten Flow ...... 5 2.2 Emscripten Toolchain[1] ...... 6 2.3 Console output for Example 2 ...... 8 2.4 Emscripten Development Flow ...... 9

3.1 PNGCrush via Terminal ...... 13 3.2 PNGCrush in Browser ...... 15 3.3 Download Option ...... 16

4.1 Tetris gameplay ...... 18 4.2 ...... 19 4.3 HTML File ...... 20 4.4 Modification in constants.h ...... 21 4.5 Original display score() ...... 21 4.6 Modified display score() ...... 22 4.7 Tetris on web gameplay ...... 23 4.8 Tetris on web gameplay ...... 23 4.9 Tetris on web gameplay ...... 24

5.1 Plot of Example 1 ...... 29 5.2 Plot of Example 2 ...... 30 5.3 Plot of Example 3 ...... 31 5.4 Plot of Example 4 ...... 32

6.1 GTK Wave Trace ...... 34 6.2 Error 1 ...... 36 6.3 Error 2 ...... 36 6.4 LED program output ...... 37 6.5 LED program output ...... 37

ii text Contents

1 Introduction 2 1.1 Why Porting? ...... 2 1.2 The Need ...... 2 1.3 C/C++ ...... 3 1.3.1 C Programming Language ...... 3 1.3.2 C++ Programming Language ...... 3 1.4 asm.js ...... 3 1.5 WebAssembly ...... 4

2 Emscripten 5 2.1 Overview ...... 5 2.2 Examples ...... 7 2.2.1 Example 1 ...... 7 2.2.2 Example 2 ...... 7 2.3 Building Projects with Emscripten ...... 8 2.3.1 emconfigure ...... 8 2.3.2 emmake ...... 8 2.4 Insight on Generated JS Files ...... 9 2.5 Interacting with C/C++ functions from JavaScript through Em- scripten ...... 10 2.5.1 ccall ...... 10 2.5.2 cwrap ...... 11 2.6 FileSystem API ...... 11

3 PNGCrush 13 3.1 About ...... 13 3.2 Downloading Source Code ...... 14 3.3 Porting the application ...... 14 3.3.1 Generating js file ...... 14 3.3.2 Running js file browser ...... 14 3.3.3 Making the js file work ...... 15 3.3.4 Creating input png file ...... 15 3.3.5 Running PNGCrush ...... 16

iv CONTENTS Project: P1

4 Tetris 17 4.1 Overview ...... 17 4.2 Note about porting ...... 17 4.3 Porting of Tetris to Web ...... 17 4.3.1 Understanding the C/C++ source code ...... 17 4.3.2 Adding the Web ...... 18 4.3.3 Making appropriate changes to C/C++ source code . . . . 18 4.3.4 Porting of the game on the web using Emscripten ...... 18 4.4 Understanding the C/C++ source code ...... 19 4.5 Adding the Web ...... 20 4.6 Making changes in C++ Files ...... 20 4.7 Porting of the game on the web using Emscripten...... 22 4.8 Github Repository for the Port of Tetris ...... 24

5 GNUPlot 25 5.1 About ...... 25 5.2 Source Code for Generating JS Files ...... 26 5.3 Porting the Application ...... 26 5.3.1 Building the Application ...... 26 5.3.2 Generating the JS File ...... 27 5.3.3 Creating the Front-End ...... 27 5.4 Github Repository ...... 28 5.5 Examples ...... 28 5.6 Further Development ...... 32

6 SimAVR 33 6.1 Overview ...... 33 6.2 Need to Port SimAVR ...... 33 6.3 History ...... 33 6.4 Procedure to Port ...... 34 6.5 Errors Faced ...... 35 6.6 Examples ...... 36 6.7 UseCase ...... 37 6.8 Limitations ...... 38 6.9 Further Development ...... 38 6.10 Github Repository for the Port of SimAVR ...... 38

7 Appendix 39 7.1 Emsripten Installation ...... 39

Fundamental Research Group, IIT Bombay v text Chapter 1

Introduction

This project aims at converting C/C++ desktop applications to the web. To aid us in porting applications to the web, i.e, in converting C/C++ logic into it’s JavaScript counterpart, there are a few tools. In particular, we will be dealing with Emscripten, an LLVM compiler which forms the base of our project. The reason for why we used Emscripten other than it’s more recent counterparts is justified in the following sections. The main aim of this project is to aid the Porting of Educational Applications.

1.1 Why Porting?

In engineering, porting is the process of adapting software for the purpose of achieving some form of execution in a computing environment that is different from the one that a given program (meant for such execution) was originally de- signed for (e.g. different CPU, operating system, or third party library). The term is also used when software/hardware is changed to make them usable in different environments. [2]

For our project, we are concerned with porting application logic from C/C++ to JavaScript.

1.2 The Need

A lot of Applications are built in C/C++ due to their superior high speed per- formance. In the modern world, everyone has access to the and it will definitely helpful if various Educational Applications were available on the Web. A straightforward way to do so would be to write the entire program logic in JavaScript from scratch. This being a very tedious task, also won’t provide performance as that of Native Applications. Hence, the need of Porting arises, which led to the development of Emscripten, an LLVM-to-JavaScript compiler, to aid in Porting.

2 CHAPTER 1. INTRODUCTION Project: P1

1.3 C/C++

These are the languages in which the Desktop Applications that we port are written and developed in. They are also widely regarded among the most popular languages for every Computer Science enthusiast.

For the purpose of our project, it is important to note that any of the applica- tion that we port could be written in either C or C++.

1.3.1 C Programming Language C is a general-purpose, procedural language supporting structured programming, lexical variable scope, and recursion, while a static type system prevents unintended operations. By design, C provides constructs that map efficiently to typical machine instructions, and has found lasting use in applica- tions previously coded in assembly language. Such applications include operating systems, as well as various application software for computers ranging from super- computers to embedded systems. [3]

1.3.2 C++ Programming Language C++ is also a general-purpose, procedural computer programming language, which was developed as an extension of the C language by Bjarne Stroustrup. It is also referred to as “C with Classes”. It provides a great deal of features that include generic, functional and object-oriented, in addition to low-level memory manipula- tion.

1.4 asm.js asm.js is a subset of JavaScript designed to allow computer software written in languages such as C/C++ to be run as web applications while maintaining perfor- mance characteristics considerably better than standard JavaScript, which is the typical language used for such applications. asm.js enables significant performance improvements for web applications, but does not aim to improve the performance of hand-written JavaScript code, nor does it enable anything other than enhanced performance. [4]

Fundamental Research Group, IIT Bombay 3 CHAPTER 1. INTRODUCTION Project: P1

1.5 WebAssembly

WebAssembly is a successor to ams.js, as it saw Google, and a plethora of other browser developing companies, put it’s resources into the development process.

WebAssembly is a new type of code that can be run in modern web browsers — it is a low-level assembly-like language with a compact binary format that runs with near-native performance and provides languages such as C/C++ and Rust with a compilation target so that they can run on the web. It is also designed to run alongside JavaScript, allowing both to work together.

The wasm format makes it possible to support graphics-heavy games in a browser without plug-ins. It can be used to port scientific simulation and other compute- intensive applications to the . It also has non-web applications such as the Internet of Things, mobile apps and JavaScript virtual machines. [5]

The following figure shows the WebAssembly Flow.

Figure 1.1: WebAssembly Flow

WebAssembly was developed in spite of the pre-existence of asm.js, because, Asm.js was stored as text, whereas WASM is stored as binary code, hence being space ef- ficient.

Fundamental Research Group, IIT Bombay 4 Chapter 2

Emscripten

Emscripten is a toolchain for compiling to asm.js and WebAssembly, built using LLVM, that lets you run C and C++ on the web at near-native speed without plugins.[1] Emscripten is a source to source compiler that generates asm.js from C and C++ source files. It takes an LLVM bitcode (the code generated as output of compiler such as for C/C++ files)

2.1 Overview

Emscripten uses Emscripten kit known as emsdk. EMSDK consists of: ˆ Clang/LLVM ˆ Emscripten Compiler (emcc,em++) ˆ Binaryen

Figure 2.1: Emscripten Compiler Flow

5 CHAPTER 2. EMSCRIPTEN Project: P1

Clang/LLVM generates the bitcode from the C/C++ source files. emcc is the Em- scripten compiler that works similar like gcc while em++ is analogous to g++. These are used to convert the bitcode into asm.js file Binaryen is a compiler and toolchain infrastructure library for WebAssembly, written in C++. It aims to make compiling to WebAssembly. Emscripten uses Binaryen’s asm2wasm tool to compile asm.js to WASM. [1]

The following figure shows the Emscripten Toolchain.

Figure 2.2: Emscripten Toolchain[1]

Fundamental Research Group, IIT Bombay 6 CHAPTER 2. EMSCRIPTEN Project: P1

2.2 Examples

2.2.1 Example 1 HelloPorting.cpp

#include using namespace std; int main(){ cout<<”This is the first Porting Example using Emscripten”<

To generate JavaScript files emcc HelloPorting.cpp -o HelloPorting.js

To generate HTML files (this generates a HTML file from cpp files into a pre- defined template) emcc HelloPorting.cpp -o HelloPorting. Html output file output

Another way : emcc HelloPorting.cpp -o HelloPorting.bc emcc HelloPorting.bc -o HelloPorting.html

2.2.2 Example 2 test.html

Test

Figure 2.3: Console output for Example 2

2.3 Building Projects with Emscripten

To build using Emscripten you need to replace gcc with emcc in your makefiles. This is done using emconfigure, which sets the appropriate environment variables like CXX (C++ compiler) and CC (the compiler).

2.3.1 emconfigure emconfigure is called with the normal configure as an argument (in configure-based build systems). emconfigure does the job of replacing gcc/g++ with emcc/em++ while generating the Makefiles of a given application.

2.3.2 emmake emmake does the job of generating the linked LLVM bitcode.

It does not automatically generate JavaScript during linking because all the files must be compiled using the same optimizations and compiler options and it makes sense to do this in the final conversion from bitcode to JavaScript.

Fundamental Research Group, IIT Bombay 8 CHAPTER 2. EMSCRIPTEN Project: P1

Figure 2.4: Emscripten Development Flow

2.4 Insight on Generated JS Files

Whenever we compile the source C/C++ files with emcc, it generates the js files linked with either WASM or asm.js. The generated js file contains a global object called Module.

”Module is a global JavaScript object with attributes that Emscripten- generated code calls at various points in its execution.”[1]

Module object contains several properties and methods that are useful in the inter- action with the source C/C++ files and generated JS file.

Some of the important properties and methods are :

Module.arguments The commandline arguments. The value of arguments contains the values returned if compiled code checks argc and argv.

Module.noInitialRun If noInitialRun is set to true, main() will not be automatically called (you can do so yourself later). The program will still call global initializers, set up memory initialization, and so forth.

Module.print Called when something is printed to standard output (stdout).

Module.printErr Called when something is printed to standard error (stderr).

Fundamental Research Group, IIT Bombay 9 CHAPTER 2. EMSCRIPTEN Project: P1

Module.callMain This method helps to call the main function and accepts one parameter i.e. an array of arguments.

We can also define our custom print function and printErr function through Module object. var module = { noInitialRun : true; print: function(text){ console.log(text); } printErr : function(text){ console.error(text); };

Add this above code snippet, just below the declaration of the Module object in the generated JS file, to print the standard output from the source C/C++ files.

2.5 Interacting with C/C++ functions from JavaScript through Emscripten

Emscripten provides two functions ccall() and cwrap() for calling C/C++ compiled functions from JavaScript.

If your function is used in other functions, LLVM may inline it and it will not appear as a unique function in the JavaScript. Prevent inlining by defining the function with EMSCRIPTEN KEEPALIVE: void EMSCRIPTEN KEEPALIVE yourCfunc() {..}

EMSCRIPTEN KEEPALIVE also exports the function, as if it were on EXPORTED FUNCTIONS. All functions not kept alive through EXPORTED FUNCTIONS or EMSCRIPTEN KEEPALIVE, will potentially be removed. Make sure you keep the things you need alive using one or both of those methods.

2.5.1 ccall ccall(ident, returnType, argTypes, args, opts)

Call a compiled C function from JavaScript. The function executes a compiled C function from JavaScript and returns the result. To prevent name mangling in C++ function needs to wrapped in extern “C” block.

Fundamental Research Group, IIT Bombay 10 CHAPTER 2. EMSCRIPTEN Project: P1 returnType and argTypes let you specify the types of parameters and the return value. The possible types are ”number”, ”string”, ”array”, or ”boolean”, which correspond to the appropriate JavaScript types. You can also specify null for the returnType if the function is void.

2.5.2 cwrap cwrap(ident, returnType, argTypes)

Returns a native JavaScript wrapper for a C function.This is similar to ccall(), but returns a JavaScript function that can be reused as many times as needed. The C function can be defined in the C file, or be a C-compatible C++ function defined using extern ”C” (to prevent name mangling). returnType and argTypes let you specify the types of parameters and the return value. The possible types are ”number”, ”string”, ”array”, or ”boolean”, which correspond to the appropriate JavaScript types. You can also specify null for the returnType if the function is void.

2.6 FileSystem API

Till now we have seen that Emscripten provides several methods and functions to help us interact with compiled C/C++ files. But many C /C++ applications need files to store and read data.

Handling Files in JS is not easy and the Emscripten FIle System API comes handy here. File System API, defined as an FS object provides support for handling files and file-based input and output.

Emscripten predominantly compiles code that uses synchronous file I/O, so the majority of the FS member functions offer a synchronous interface (with errors be- ing reported by raising exceptions of type FS.ErrnoError).[6]

If we only need to read or write from a particular file in a C/C++ application then at the time of porting it to JavaScript, we can use “–preload-file” flag, passing the file/directory as an argument. This file will be accessible by name through fopen and other functions within the program.

For more advanced options such as dynamic creation and deletion of files we need File System API.

File System API provides several methods to interact with files. Some of them used frequently by us are:

FS.createDataFile(parent , name, data, canRead, canWrite, canOwn) It creates a data file in the address specified as parent (mostly “/”, i.e root) with

Fundamental Research Group, IIT Bombay 11 CHAPTER 2. EMSCRIPTEN Project: P1 name and data provided. Arguments : parent(string) : address where file is to be created( normally set to “/”, i.e root) name(string) : name of the file with extension data(UTF8array) : data to be stored in file canRead(bool) : boolean value if set to true provide read access canWrite(bool) : boolean value if set to true provide write access canOwn(bool) : boolean value if set to true give owner access FS.unlink(name) Deletes the file with given name if present else throws error. Arguments : name(String) : name of the file to be deleted

FS.findObject(name) Returns the file object with given name if found else null Arguments : name(string) : name of the file to be found

Several other methods can be found on https://emscripten.org/docs/api_reference/ Filesystem-API.html

Note: If files are being used within C/C++ source files then file system support in Emscripten is added by default but in case it doesn’t, we can forcefully add File System support by passing flag -s FORCE FILESYSTEM=1 to emcc when com- piling.

In combination to all these we can also use the local-storage feature of window object provided by HTML5 to store files and their data as key value pairs.

Fundamental Research Group, IIT Bombay 12 Chapter 3

PNGCrush[7]

3.1 About

PNGCrush is a free and open-source command-line utility for optimizing PNG im- age files. It reduces the size of the file losslessly – that is, the resulting ”crushed” image will have the same quality as the source image.[8]

It lets you reduce the size of PNG images by various methods. It’s completely writ- ten in C so makes a suitable choice to understand how porting works. PNGCrush uses files for input and output so provide a great opportunity to understand the FILESYSTEM API of the emscripten. In the simplest form, pngcrush can be told to generate a ”crushed” file from an unoptimized one by using the following format on the command line: pngcrush imageInput.png imageOutput.png

The following image shows running PNGCrush via terminal.

Figure 3.1: PNGCrush via Terminal

13 CHAPTER 3. PNGCRUSH Project: P1

3.2 Downloading Source Code

The source files are available at https://pmt.sourceforge.io/pngcrush

We have worked with version 1.8.11

Untar the source files tar -xzvf pngcrush.1.8.11.tar.xz

Git Hub Repository for the same can be found at : https://github.com/ajit3259/pngcrush.js

3.3 Porting the application cd pngcrush1.8.11 Moving to the directory where pngcrush was extracted.

We were unable to build projects as explained earlier by swapping ./configure and make with emconfigure ./configure and emmake make respectively. This was be- cause PNGCrush did not have a configure file, but instead had a Makefile.

To cope with the above situation we made changes to the Makefile. The Make- file can be opened with any text editor. Once the Makefile is opened just replace the value of CC variable to ”emcc” from ”gcc”.

This did our job. It worked as emcc and gcc are almost analogous to each other ex- cept the kind of output that they produce. gcc produces an executable file whereas emcc produces a binary output file when used with the Makefile.

3.3.1 Generating js file make Generated the file named pncrush in src folder in bitcode form. mv pngcrush pngcrush.bc Renamed the file so that emcc could recognise it. emcc pngcrush.bc -o pngcrush.js This generated the pngcrush.js file

3.3.2 Running js file browser Using the js file was a bit trickier as pngcrush accepts minimum two arguments as “inputpngfile” and “outputpngfile” along with several optional flags.

Fundamental Research Group, IIT Bombay 14 CHAPTER 3. PNGCRUSH Project: P1

We tried to run it through node.js and it showed error message along with pngcrush usage instruction as no png image was given as input.

We unable to give file inputs via nodejs from command-line as we could to C/C++ files. The generation of HTML with Emscripten also did not solve our problem.

Figure 3.2: PNGCrush in Browser

3.3.3 Making the js file work We used the Emscripten File System API to input png images and then passed them through Module’s callMain() function.

3.3.4 Creating input png file Images were read from a simple html page through input tag. The data was stored in a variable imageData once read through readAsDataURL() function provided by FileReader in JavaScript.

This created a problem as the png image read by the above method was in b64 i.e. base 64 encoding and we can not store it using File System API of Emscripten.

To solve the above problem we converted the b64 data to a byteArray. Once byteAr- ray was created it was stored by the use of: var inputfile = FS.createDataFile(\/", \input.png", byteArray, true, false);

Fundamental Research Group, IIT Bombay 15 CHAPTER 3. PNGCRUSH Project: P1

3.3.5 Running PNGCrush var args = [‘input.png’, ‘output.png’] Module.callMain(args);

After running the Module.callMain(args) function the compressed file ‘output.png’ was created. It can be found and stored in a variable by using the findObject() function. var file = FS.findObject(‘output.png’);

To allow the users to download the output.png we used Blob and used saveAs functionality through FileSaver.js

A Blob object represents a file-like object of immutable, raw data. Blobs repre- sent data that isn’t necessarily in a JavaScript-native format. The File interface is based on Blob, inheriting blob functionality and expanding it to support files on the user’s system. FileSaver.js helps to save files on the client-side. It is perfect for web applic- taion that need to generate files, or for saving sensitive information that shouldn’t be sent to an external server. FileSaver.js implements the HTML5 W3C saveAs() FileSaver interface in browsers that do not natively support it.

Figure 3.3: Download Option

Github Repository for FileSaver.js can be fount at : https://github.com/eligrey/ FileSaver.js

Fundamental Research Group, IIT Bombay 16 Chapter 4

Tetris[9]

4.1 Overview

Tetris is a tile matching puzzle video game whose first playable version was re- leased back in 1984. Since then the game has been launched on various platforms including but not limited to video game consoles,personal computers, graphing cal- culator,mobile phones,PDA’s etc.

The main aim of the game is to rotate and moves pieces of various shape within a playing field to create a row of blocks without gap. When this happens the row is removed and score increases by one. The aim of the game is to increase your score as much as possible. As the game progresses it increases its speed and the player has to react faster to stay alive in the game. The game ends when the whole playing field gets filled with tetrominoes.

4.2 Note about porting

Porting any application on web is not always a simple task. Games that make use of several third party libraries or even few third party libraries of considerable complexity requires significant amount of effort, specially when not all of them are provided by Emscripten. Fortunately the Tetris game only uses the SDL third party library which is provided by Emscripten.

4.3 Porting of Tetris to Web

Porting of tetris or for that matter any application can be reduced to 4 major tasks.

4.3.1 Understanding the C/C++ source code Necessary so that appropriate changes can be done whenever required for the pur- pose of porting.

17 CHAPTER 4. TETRIS Project: P1

Figure 4.1: Tetris gameplay

4.3.2 Adding the Web Although emscripten does provide the feature to generate an HTML file, but to add flexibility and clarity it is usually recommended to write the HTML and CSS manually and let Emscripten generate the JavaScript code.

4.3.3 Making appropriate changes to C/C++ source code Since not all features of a C/C++ file can be handled by Emscripten some modifi- cation is required in the base code. Also some changes were done in this project to remove the complexity of the code by excluding a third party library SDL ttf.

4.3.4 Porting of the game on the web using Emscripten This step converts the C/C++ code into equivalent JavaScript/WASM code which can then be integrated with other files to finally run the game on the web.

Fundamental Research Group, IIT Bombay 18 CHAPTER 4. TETRIS Project: P1

4.4 Understanding the C/C++ source code

Figure 4.2: Source code

1. Codebase consists of C++ class files(.cpp) and Header files(.h) that represents objects within the context of the game.

2. The various classes include the Piece class, Board class and the Game class.

3. The constants.h stores all the global variables used in the project so as to increase the readability of the code.

4. The Piece class contains logic to define pieces in terms of shape, color and current orientation. It contains functions to move the block, to rotate the block and the isblock() function to determine which kind of piece is present, its location and orientation.

5. The Board class contains instances of the Pieces class and contains functions to display pieces which have reached the bottom of the board, detect collision between the pieces and to the unite function to clear any full row from the board, moving all pieces above it down by one and to increase the score by one.

6. The game class contains functions to manage the whole game, including gen- erating new random pieces and to enable one to move pieces around the board with key presses.

7. The main.cpp file acts as the entry point to the game and runs the game loop until SDL quit is triggered.

Fundamental Research Group, IIT Bombay 19 CHAPTER 4. TETRIS Project: P1

4.5 Adding the Web

1. The game requires one to add basic frontend to display the game in the browser.

2. The HTML files manually written creates a canvas on which the game can be loaded and also includes a div tag under which the current score is displayed using the inner.HTML attribute.

Figure 4.3: HTML File

3. The CSS file is optional but is required to display the current score in exactly the same font as would have been displayed by SDL2 ttf (true type font).

4.6 Making changes in C++ Files

1. Although SDL ttf is supported by Emscripten and can be ported but since its function is only to display the score, for reducing the unnecessary complexity of the program the use of SDL ttf to display score was removed and the same was displayed using DOM.

2. Since the display score is not part of the C++ file, the extra space allotted in the screen height global variable was removed.

Fundamental Research Group, IIT Bombay 20 CHAPTER 4. TETRIS Project: P1

Figure 4.4: Modification in constants.h

3. In the Board class, the display score() function was changed so that the score will be displayed by DOM. Here Emscripten run script action finds thehspani element on the DOM and sets the inner.HTML to the current score.

Figure 4.5: Original display score()

Fundamental Research Group, IIT Bombay 21 CHAPTER 4. TETRIS Project: P1

Figure 4.6: Modified display score()

4. Now since the SDL ttf is not required, all the functions and header files using the SDL ttf library are updated.

5. Emscipten provides a Emscipten set main loop function that accepts a em callback func looping function. However the gameloop() can’t be passed to em callback func since it will fail to build. So the game class itself is removed and its logic is moved to main.cpp and reordered in such a way that all the functions are declared before they are used.

4.7 Porting of the game on the web using Em- scripten.

To port the game to the web first navigate to the project directory. emcc --bind src/board.cpp src/piece.cpp src/main.cpp -std=c++14 -O3 -s WASM=1 -s USE MODULARIZE=1 -s USE SDL -o public/index.js was typed in the command line. Here, –bind argument with the corresponding cpp files, tells the compiler that all the files after –bind are required to build the project. -std=c++14 tells the compiler to use c++14 version, O3 tells the compiler to aggressively optimise the code, -s WASM=1 to produce the wasm file, -s USE MODULARIZE=1 to Modularize the ported code into js and .wasm file , -USE SDL to tell the compiler that the given program uses SDL and -o public/index.js for defining the name and location of the code generated by emscripten. emrun --browser firefox --no emrun detect public/index.html was run from the terminal (Google Chrome).

Fundamental Research Group, IIT Bombay 22 CHAPTER 4. TETRIS Project: P1

Here the –no emrun detect flag hides a message in the terminal stating that the HTML page is not emrun capable.

The game is successfully ported on the web and can be played on localhost.

Figure 4.7: Tetris on web gameplay

Figure 4.8: Tetris on web gameplay

Fundamental Research Group, IIT Bombay 23 CHAPTER 4. TETRIS Project: P1

Figure 4.9: Tetris on web gameplay

4.8 Github Repository for the Port of Tetris

All of the files that were generated and created for the functional Port of Tetris can be found at https://github.com/shikhar8/tetris.git.

Fundamental Research Group, IIT Bombay 24 Chapter 5

GNUPlot[10]

GNUPlot is a command-line program that can generate two and three-dimensional plots of functions, data, and data fits. The source code is copyrighted but freely distributed. We chose this application because it possessed varied educational ap- plications and was widely used throughout the community. It also had a wide consumer base, hence making it easy on us if we ran into trouble during the devel- opment process.

5.1 About

It was originally created to allow scientists and students to visualize mathematical functions and data interactively, but has grown to support many non-interactive uses such as web scripting. It is also used as a plotting engine by third-party ap- plications like Octave. Gnuplot has been supported and under active development since 1986.[11]

As the application is completely written in C, it makes it an ideal application to port. GNUPlot works as a command-line program, hence alllowing users to write their own code in accordance to the coding paradigm and rules set by the applica- tion. It can also make use of ”.txt” or ”.dat” files, residing in the source folder, to create graphs from the data stored in those files.

This program can be thought of as a step forward PNGCrush which only accepted files as input, to something which can support both files as input and commands from the command-line console.

Commands can vary from the simples of ones like ”plot x” to more complex and beautiful designs like : plot [-10:10] [-5:3] 1.5+sin(x)/x with filledcurve x2, sin(x)/x with filledcurve, 1+sin(x)/x with lines, -1+sin(x)/x with filledcurve y1=-2, -2.5+sin(x)/x with filledcurve xy=-5,-4.,

25 CHAPTER 5. GNUPLOT Project: P1

-4.3+sin(x)/x with filledcurve x1, (x>3.5 ? x/3-3 : 1/0) with filledcurve y2

5.2 Source Code for Generating JS Files

We were able to get a hold of the source files in a pretty straight forward manner, as it was available at their official SourceForge Repository. In any case, the source files can be found at https://sourceforge.net/projects/gnuplot/files/gnuplot/ 4.6.3

5.3 Porting the Application

After we got a hold of the source files, it was time to finally build the application and port it.

5.3.1 Building the Application As mentioned in Subsection 4.3 of Section 4 under Emscripten, we used the com- mand emconfigure ./configure to build the files using emcc/em++ instead of gcc/g++. We encountered a few errors when we ran emmake make after configur- ing the application. These errors were raised due to lack of permission to access files from the docs directory under the main application. Since we do not require documentation for GNUPlot in our Port, we decided to skip the docs directory and jumped straight into the src directory. Running the same command as before, emmake make we were able to generate the binary bitcode file for GNUPlot. We copied the file back to another directory (giving it a .o extension in the process, so that Emscripten can recognise it) which had the pre.js file, where we intend to build the final Ported Project.

Now, we created a pre.js file with the following contents, so that we could initialise the global Module object with print and printErr functions, and also ensure that the JS File does not execute straight away after loading. var outstr=””; var Module = { ”noInitialRun”: true, print: function(text){ //console.log(text); outstr += text; }, printErr: function(text) { console.error(text); } };

Fundamental Research Group, IIT Bombay 26 CHAPTER 5. GNUPLOT Project: P1

5.3.2 Generating the JS File Now, with both the pre.js and gnuplot.o files, we can finally use Emscripten to generate the JavaScript file for our use.

When we initially ran emcc to generate the JS files, we encountered a problem relat- ing to asynchronous calls from the generated WASM Module. Since we were unable to identify the problem in depth, we decided to use the asm.js standard instead. Since we need to use the functions intArrayFromString and intArrayToString, we need to pass them using the EXTRA EXPORTED RUNTIME METHODS flag onto emcc.

Finally, we need to passthe pre.js file through the ”--pre-js” flag, along with importing the Emscripten filesystem, as we need to use it. The filesystem can be imported via passing the FORCE FILESYSTEM=1 flag onto emcc.

In the directory containing the pre.js and gnuplot.o files : emcc -s WASM=0 -O2 -s FORCE FILESYSTEM=1 -s ’EXTRA EXPORTED RUNTIME METHODS=["intArrayFromString","intArraytoString"]’ gnuplot.o -o gnuplot.js --pre-js pre.js

This command succesfully creates the JavaScript file that we use with the front-end HTML.

5.3.3 Creating the Front-End Initially, we were unable to figure out how to run any command that would originally be run inside the console. So we simply called the Module.callMain() function to observe what happens. This made the JavaScript call the main function of the ap- plication written inside the C files, hence causing a window prompt to open and take input like that of command line. Now, since that wasn’t viable, we tried passing arguments to the callMain function by ourselves, to see if we could access the ap- plication in that manner. So we passed the following command onto the JavaScript.

Module.callMain(["set","terminal","svg"]).

To our surprise, it returned an error stating that the first argument passed was ’not a file’, i.e it returned the request with ”file ’set’ was not found”.

This made us understand that inside the ported JavaScript file, the callMain func- tion accepted filename as input, and then proceeded to execute that file if it was available. After knowing this fact, it became a simple enough problem to solve.

We made a text-area to take input code from the user, and then on a button-click, saved the contents of the text-area into a file, using the FS.createDataFile() function present in the Emscripten FileSystem API. We then sent this filename as

Fundamental Research Group, IIT Bombay 27 CHAPTER 5. GNUPLOT Project: P1 input to the callMain function.

The file created was executed and the results of the execution were displayed on the browser console. We then simply had to take the text that was being outputed to the console and use it to generate the graph within the HTML. GNUPlot in itself, comes with a plethora of inbuilt types, which can be used according to the environment that it is run in. For Web interfaces, it comes inbuilt with a svg and a canvas type. We used the svg type for porting, as we could then finally allow the user to download the image of the graph after it was plotted.

After setting the mode to svg, and collecting the text from where the JavaScript provided console output, we noticed that it always lacked a closing <\svg> tag. So, after appending the closing tag to the generated output, we simply displayed it by using it as the innerHTML under a paragraph element.

We were hence succesful in plotting the graph, according to whatever code the user wrote inside the text-area.

Now, we needed to provide the storage of files which can be used to store data, which inturn can be used by GNUPlot to generate a graph. This was also a simple task, we made use of the inbuilt FileReader() function of JavaScript, and stored it again using the FS.createDataFile() function. Now, when a file is uploaded and the code references the uploaded file, GNUPlot automatically detects that the specified file is present and hence proceeds to provide the svg output for the graph.

Finally, to provide users the ability to download their graph, we made use of a convenient FileSaver.js file, which provided the inbuilt functionality to down- load any file. We simply had to breate a blob element of the generated svg graph, which can be done as : var blob = new Blob([svgtext],{type: "image/svg;charset=utf-8"})

Hence, we were able to achieve success in porting the GNUPlot application, only because of the countless faliures that we experienced throughtout the course of the Project.

5.4 Github Repository

All of the files that were generated and created for the functional Port of GNUPlot can be found at https://github.com/YasasviPeruvemba/gnuplot.js.

5.5 Examples

All of the examples used to test the working of the port were taken from the Homepage of GNUPlot[11]

Fundamental Research Group, IIT Bombay 28 CHAPTER 5. GNUPLOT Project: P1

1. Simple plot command

plot x

Figure 5.1: Plot of Example 1

2. Complex Plot Commands without files

set dummy u, v set key bmargin center horizontal Right noreverse enhanced autotitle nobox set parametric set view 45, 50, 1, 1 set isosamples 50, 10 set hidden3d back offset 1 trianglepattern 3 undefined 1 altdiagonal bentover set style data lines set ztics norangelimit -1.00000,0.25,1.00000 set title "Parametric Sphere" set urange [ -1.57080 : 1.57080 ] noreverse nowriteback set vrange [ 0.00000 : 6.28319 ] noreverse nowriteback splot cos(u)*cos(v),cos(u)*sin(v),sin(u)

Fundamental Research Group, IIT Bombay 29 CHAPTER 5. GNUPLOT Project: P1

Figure 5.2: Plot of Example 2

3. Simple Command using Data files

set style data lines set title "Fill area between two curves" set xrange [ 10.0000 : * ] noreverse nowriteback set yrange [ 0.00000 : 175.000 ] noreverse nowriteback ## Last datafile plotted: "silver.dat" plot ’silver.dat’ u 1:2:3 "%lf %lf %lf" w filledcu, ’’ u 1:2 lt -1 notitle, ’’ u 1:3 lt -1 notitle

Fundamental Research Group, IIT Bombay 30 CHAPTER 5. GNUPLOT Project: P1

Figure 5.3: Plot of Example 3

4. Complex Commands with Data Files

set tmargin 0 set bmargin 0 set lmargin 3 set rmargin 3 unset xtics unset ytics set multiplot layout 4,1 title "Auto-layout of stacked plots\n" font ",12" set key autotitle column nobox samplen 1 noenhanced unset title set style data boxes set yrange [0 : 800000] plot ’immigration.dat’ using 3 lt 1 - plot ’immigration.dat’ using 8 lt 3 set xtics nomirror set tics scale 0 font ",8" set xlabel "Immigration to U.S. by Decade" plot ’immigration.dat’ using 21:xtic(1) lt 4 unset multiplot

Fundamental Research Group, IIT Bombay 31 CHAPTER 5. GNUPLOT Project: P1

Figure 5.4: Plot of Example 4

5.6 Further Development

1. Untill now, there does not exist any support for the other Terminal outputs of GNUPlot. We look forward to tackling this issue in the near future.

2. The size of the JavaScript file is a bit large (5.23 MB), so we can work on optimizations to reduce the file size.

3. There are a few demos that require user interaction, which renders frames at a constant rate. We hope to resolve this issue as well.

Fundamental Research Group, IIT Bombay 32 Chapter 6

SimAVR[12]

6.1 Overview

Like many MicroControllers available namely 8051, 8031 etc which basically uses C (embedded C) code, we also have others like Atmel ATMega 1280 mcu(Micro Controller Unit) i.e among Atmel ATMega 8 series, which uses AVR codes [13]. Like other programming, Programming in AVR also needs knowledge about its syntax but its like impractical to say that ‘errors won’t be arised’. So, as a debugger and also many a times in the simulation of such programs in the absence of actual hardware, comes the need of some debugging tool or software which can help us to do so for which “SimAVR”. It basically requires elf file, producing a vcd file which is then fed as an input to GTKWave in which corresponding waveforms are graphed, serving as its final output.

6.2 Need to Port SimAVR

SimAVR comes as an github repository from which it needs to be cloned first and then installation of a software named GTKWave is required for simulation. As we know, it is not really practical and possible to have all necessary machine requirements, memory space, time and most importantly patience to download, install and follow their “ReadMe” in this modern era of mobile phones, which are much more handy than laptops or systems. Thus, we found the need of an hour and so we here present Port of SimAVR to make it accessible through web on every device(even on, thus, phones) at no cost of installation memory, time or patience.

6.3 History

Till date, we use namely WinAVR, Atmel Studio for AVR Programming and Keil uVision IDE, Flash Magic Tool for C being used in microcontrollers like 8051, 8031, for programming and dumping the generated .hex files on actual hard- ware to run. With time got evolved, we found the use of some simulation tool required for debugging as well as running on virtual hardware and thus, SimAVR

33 CHAPTER 6. SIMAVR Project: P1

Figure 6.1: GTK Wave Trace got developed to simulate the effect of hardware devices with GTKWave, producing waveforms.

6.4 Procedure to Port

1. Clone simavr from https://github.com/buserror/simavr.

2. As it contains support for wide variety of microcontrollers, we decided to port a specific module namely “Atmel ATMega 1280 mcu” i.e among Atmel ATMega 8 series, selecting its repective connected files and run the MakeFile of SimAVR using Emscripten. Also, another reason for selecting it in specific, was that we got the configure file(CMakeLists.txt) of this particular module and main file along with hd44780 for LCD and wdg0151, a module for LCD, to build. We changed the respective directory path in the configure file, ”CMakeLists.txt” to correctly include ”libsimavr.so” file. [14]

3. The code doesn’t work in just simply compiling with emscripten. The follow- ing changes were made in order to make it get compiled and run successfully

(a) After making such suitable changes, remove libelf dependency from Make- file. (b) Configure cmake file and make necessary builds to take place. emconfigure cmake (c) Update link.txt file to make it generate js without wasm, passing neces- sary flags to emcc command as: emcc -s ASM JS=1 -s WASM=0 -s FORCE FILESYSTEM=1 \ -s ERROR ON UNDEFINED SYMBOLS=0 \ -s EXTRA EXPORTED RUNTIME METHODS=’[\ccall","cwrap","ALLOC NORMAL"]’

Fundamental Research Group, IIT Bombay 34 CHAPTER 6. SIMAVR Project: P1

(d) Main.c file was updated with the following few changes: i. Inclusion of ‘hd44780’ c and header file to call its functions which returns machine cycles and time taken (in uS). ii. Inclusion of “simelf.c” file function which was not being run earlier. iii. Declaration of the pointer of hd44780 type and initializing its func- tions like init() through it. iv. Calling specific functions of wdg0151.c which were not being called on own earlier. v. Rendering of extra but necessary information like Total LEDs on, machine cycles etc(depending upon logic implemented in AVR code) on own Terminal.

6.5 Errors Faced

1. Python(.py) file errors in emscripten module.[15]

Reason: Due to unsuccessful compilation of project, we changed even stan- dard I/O files of emscripten which couldn’t get undo.

Fix: Reinstalling emscripten couldn’t address the issue as it stores some files in system cache which weren’t being deleted and the errors were same. So, we had to reinstall whole virtual machine on which we were working upon.

2. “Errors on Undefined Symbols” (HD44780 can’t be included)

Reason: MakeFile needs an object file i.e “hd44780.c.o” which, it was not able to find and thus the error.

Fix: Just replicating the process of building of “wdg0151.c.o” in MakeFile i.e Building object file through it addressed the issue successfully.

3. While generation of .elf or .hex files, AVR ERRORS[16]

Reason: Make file of WinAVR requires many compiler dependencies, un- necessary at times.

Fix: Remove these two lines from ”Makefile” of WinAVR: # flags to generate dependency files. GENDEPFLAGS = -MMD -MP -MF .dep/$(@F).d

Fundamental Research Group, IIT Bombay 35 CHAPTER 6. SIMAVR Project: P1

Figure 6.2: Error 1

Figure 6.3: Error 2

6.6 Examples

Input File: LEDProg.hex (Source Code on https://github.com/sarthaksarm/Port-of-SimAVR. git

Output:

Fundamental Research Group, IIT Bombay 36 CHAPTER 6. SIMAVR Project: P1

Figure 6.4: LED program output

Figure 6.5: LED program output

6.7 UseCase

1. Novice Programmers, as LEDs being used on Port may give direct visual effect as an actual output. Comparing which with expected output, may validate.

2. Experienced Programmers, along with LEDs it includes a Terminal/Command Prompt like screen to display in-depth information, necessary to debug. For Eg. Time Delay, No. of machine cycles etc., depending upon the type of program input as .hex file.

3. Companies to test large programs and softwares which may lot of time to dump into actual hardware and test. Debugging through it, thus, becomes easier.

4. Educational Institutes/Organizations to test the validity of code of students, in limitation or lack of hardware devices, in just one go.

Fundamental Research Group, IIT Bombay 37 CHAPTER 6. SIMAVR Project: P1

6.8 Limitations

1. The port supports especially ATMega 1280 mcu, thus other versions of mcu are not supported.

2. Rendering of LCD screen i.e Graphic representation is not available. However, mostly information is being printed on terminal at this stage to simplify debug process.

3. The timing is fixed as described for the 5V-versions.[17]

4. Only .hex file format is acceptable. However, command has been provided to convert an elf file into .hex .

6.9 Further Development

1. Support for other AVRs and also Microcontrollers namely 8051, 8031 etc.

2. Rendering of Graphics in forms of waveforms produced, as the GLCD module.

3. Text Editor for direct input of AVR and embedded C codes and generating hex files directly.

6.10 Github Repository for the Port of SimAVR

All of the files that were generated and created for the functional Port of Tetris can be found at https://github.com/sarthaksarm/Port-of-SimAVR.

Fundamental Research Group, IIT Bombay 38 Chapter 7

Appendix

7.1 Emsripten Installation

Dependencies: Python 2.7 , CMake , Java (optional, required for closure compiler). Youcan install them on your Linux based kernel, by executing the following com- mand on the terminal window. sudo apt-get install python cmake default-jre

The core of the emscripten SDK is written in python so above dependencies must be installed.

Get the emsdk repo git clone https://github.com/emscripten-core/emsdk.git

Enter that directory cd emsdk

Fetch the latest version of the emsdk (not needed the first time you clone) git pull

Download and install the latest SDK tools. ./emsdk install latest

Make the ”latest” SDK ”active” for the current user. (writes /.emscripten file) ./emsdk activate latest

Activate PATH and other environment variables in the current terminal source ./emsdk env.sh

To access emscripten sdk compiler emcc, emsdk env is run in the terminal.

39 text References

[1] “Official website of Emscripten, can be found at ”https://emscripten.org”.”

[2] D. Whitten, “A machine and configuration independent Fortran: Portable Fortran,” IEEE Transactions on Software Engineering, March 1995.

[3] “General information about C, found at ”https://en.wikipedia.org/wiki/ C_(programming_language)”.”

[4] “General information about Asm.js, found at ”https://en.wikipedia.org/ wiki/Asm.js”.”

[5] “General information about WebAssembly, found at ”https://en. wikipedia.org/wiki/C_(programming_language)”.”

[6] “FileSystem API of Emscripten, can be found at ”https://emscripten.org/ docs/api_reference/Filesystem-API.html”.”

[7] “Port of PNGCrush, can be cloned at ”https://github.com/ajit3259/ pngcrush.js”.”

[8] “General Information about PNGCrush, can be found at ”https://en. wikipedia.org/wiki/Pngcrush”.”

[9] “Port of GNUPlot, can be cloned at ”https://github.com/shikhar8/ tetris”.”

[10] “Port of GNUPlot, can be cloned at ”https://github.com/ YasasviPeruvemba/gnuplot.js”.”

[11] “Homepage of GNUPlot, can be found at ”http://www.gnuplot.info/”.”

[12] “Port of SimAvr, can be cloned at ”https://github.com/sarthaksarm/ Port-of-SimAVR”.”

[13] “ATMega Introduction, can be accessed at ”http://sembedded.net/ REQHandler/index.php?token=true&x=3&y=0&z=0&i=1”.”

[14]“” https://github.com/donothingloop/simavr.js_c”.”

[15] “Errors in Emscripten Python files, ”https://github.com/ emscripten-core/emscripten/issues/8799”.”

41 REFERENCES Project: P1

[16] “Compilation Errors, can be viewed at ”https://www.avrfreaks.net/forum/ windows-81-compilation-error”.”

[17] “SimulAVR, can be viewed at ”https://www.nongnu.org/simulavr/ contents.html”.”

Fundamental Research Group, IIT Bombay 42