diff --git a/ECOAR/C/asm_part.asm b/ECOAR/C/asm_part.asm new file mode 100755 index 00000000..17b48ed6 --- /dev/null +++ b/ECOAR/C/asm_part.asm @@ -0,0 +1,136 @@ + + +section .data + + + +image_info_address EQU 8 ; First argument passed to our function starts from 8 +first_piece_address EQU 12 ; From that point we just add 4 to address of next +; arguments +piece_to_swap_with_address EQU 16 +horizontal_divisons_address EQU 20 +piece_width_address EQU 24 +piece_height_address EQU 28 +piece_width_bytes_address EQU 32 +piece_height_bytes_address EQU 36 +bytes_per_row_address EQU 40 +firstPieceStartingByte EQU 44 +secondPieceStartingByte EQU 48 + + +pImg_inside_image_info_address EQU 12 + + +image_width EQU 0 +image_height EQU 4 +bytes_per_row_inside_image_info_address EQU 8 +image_pImg EQU 12 +image_pHeaderInfo EQU 16 ; not really used + +; first.X, first.Y, second.X, second.Y + + + +%macro print 2 ;number of arguments this macro takes + mov edx, %1 ;message length + mov ecx, %2 ;message to write + mov ebx,1 ;file descriptor (stdout) + mov eax,4 ;system call number (sys_write) + int 0x80 ;call kernel +%endmacro + + + +section .text +global inner_loops ;must be declared for linker (ld) +; extern void hello_world(imageInfo* pInfo, int firstPiece, int pieceToSwapWith, +; int horizontalDivisions, int pieceWidth, +; int pieceHeight); + +; mov ecx, [ebp + 8] ; ecx <- address of imgInfo struct, not saved +; mov eax, [ebp + 12] ; eax <- firstPiece, not saved +; mov edx, [ebp + 16] ; edx <- pieceToSwapWith, not saved +; mov esi, [ecx + image_pImg] ; esi <- start of pixels in picture, saved +; mov ebx, [ebp + 20] ; ebx <- horizontalDivisions +; mov edi, [ebp + 24] ; edi <- pieceWidth + +inner_loops: ;tells linker entry point + + push ebp ; as per calling convention we need to keep the values of + ; certain registers + mov ebp,esp + push ebx + push esi + push edi + + ; what we use: + ; ecx - firstPieceFirstByteAddress + ; edx - secondPieceFirstByteAddress + ; esi + ; edi + + ; what we have: + ; eax + ; ebx + + push ebx + push eax + ;mov eax, [ebp + firstPieceStartingByte] + ;mov eax, [eax + image_pImg] + mov edi, 0 + +x_pixels_loop: + cmp edi, [ebp + piece_width_bytes_address] + ;cmp edi, 300 + jge x_pixels_loop_end + mov esi, 0 + + ; ecx = secondPieceStartingByte + ; edx = firstPieceStartingByte + ; we still have eax and ebx + ; + y_pixels_loop: + cmp esi, [ebp + piece_height_bytes_address] + ;cmp esi, 96000 + jge y_pixels_loop_end + mov ecx, [ebp + secondPieceStartingByte] + mov eax, [ebp + firstPieceStartingByte] + add ecx, edi + add ecx, esi + add eax, edi + add eax, esi + + mov BYTE bl, [eax] + mov BYTE dl, [ecx] + mov BYTE[ecx], bl + mov BYTE[eax], dl + + mov BYTE bl, [eax + 1] + mov BYTE dl, [ecx + 1] + mov BYTE[ecx + 1], bl + mov BYTE[eax + 1], dl + + mov BYTE bl, [eax + 2] + mov BYTE dl, [ecx + 2] + mov BYTE[ecx + 2], bl + mov BYTE[eax + 2], dl + + + + add esi, [ebp + bytes_per_row_address] + jmp y_pixels_loop + + + ; for(x = 0; x < pieceWidth * 3; x += 3) + y_pixels_loop_end: + add edi, 3 + jmp x_pixels_loop + + x_pixels_loop_end: + + pop esi + pop edi + pop ebx + mov esp, ebp + pop ebp + ret diff --git a/ECOAR/C/asm_part.lst b/ECOAR/C/asm_part.lst new file mode 100644 index 00000000..0115e3b4 --- /dev/null +++ b/ECOAR/C/asm_part.lst @@ -0,0 +1,136 @@ + 1 + 2 + 3 section .data + 4 + 5 + 6 + 7 image_info_address EQU 8 ; First argument passed to our function starts from 8 + 8 first_piece_address EQU 12 ; From that point we just add 4 to address of next + 9 ; arguments + 10 piece_to_swap_with_address EQU 16 + 11 horizontal_divisons_address EQU 20 + 12 piece_width_address EQU 24 + 13 piece_height_address EQU 28 + 14 piece_width_bytes_address EQU 32 + 15 piece_height_bytes_address EQU 36 + 16 bytes_per_row_address EQU 40 + 17 firstPieceStartingByte EQU 44 + 18 secondPieceStartingByte EQU 48 + 19 + 20 + 21 pImg_inside_image_info_address EQU 12 + 22 + 23 + 24 image_width EQU 0 + 25 image_height EQU 4 + 26 bytes_per_row_inside_image_info_address EQU 8 + 27 image_pImg EQU 12 + 28 image_pHeaderInfo EQU 16 ; not really used + 29 + 30 ; first.X, first.Y, second.X, second.Y + 31 + 32 + 33 + 34 %macro print 2 ;number of arguments this macro takes + 35 mov edx, %1 ;message length + 36 mov ecx, %2 ;message to write + 37 mov ebx,1 ;file descriptor (stdout) + 38 mov eax,4 ;system call number (sys_write) + 39 int 0x80 ;call kernel + 40 %endmacro + 41 + 42 + 43 + 44 section .text + 45 global inner_loops ;must be declared for linker (ld) + 46 ; extern void hello_world(imageInfo* pInfo, int firstPiece, int pieceToSwapWith, + 47 ; int horizontalDivisions, int pieceWidth, + 48 ; int pieceHeight); + 49 + 50 ; mov ecx, [ebp + 8] ; ecx <- address of imgInfo struct, not saved + 51 ; mov eax, [ebp + 12] ; eax <- firstPiece, not saved + 52 ; mov edx, [ebp + 16] ; edx <- pieceToSwapWith, not saved + 53 ; mov esi, [ecx + image_pImg] ; esi <- start of pixels in picture, saved + 54 ; mov ebx, [ebp + 20] ; ebx <- horizontalDivisions + 55 ; mov edi, [ebp + 24] ; edi <- pieceWidth + 56 + 57 inner_loops: ;tells linker entry point + 58 + 59 00000000 55 push ebp ; as per calling convention we need to keep the values of + 60 ; certain registers + 61 00000001 89E5 mov ebp,esp + 62 00000003 53 push ebx + 63 00000004 56 push esi + 64 00000005 57 push edi + 65 + 66 ; what we use: + 67 ; ecx - firstPieceFirstByteAddress + 68 ; edx - secondPieceFirstByteAddress + 69 ; esi + 70 ; edi + 71 + 72 ; what we have: + 73 ; eax + 74 ; ebx + 75 + 76 00000006 53 push ebx + 77 00000007 50 push eax + 78 ;mov eax, [ebp + firstPieceStartingByte] + 79 ;mov eax, [eax + image_pImg] + 80 00000008 BF00000000 mov edi, 0 + 81 + 82 x_pixels_loop: + 83 0000000D 3B7D20 cmp edi, [ebp + piece_width_bytes_address] + 84 ;cmp edi, 300 + 85 00000010 7D42 jge x_pixels_loop_end + 86 00000012 BE00000000 mov esi, 0 + 87 + 88 ; ecx = secondPieceStartingByte + 89 ; edx = firstPieceStartingByte + 90 ; we still have eax and ebx + 91 ; + 92 y_pixels_loop: + 93 00000017 3B7524 cmp esi, [ebp + piece_height_bytes_address] + 94 ;cmp esi, 96000 + 95 0000001A 7D33 jge y_pixels_loop_end + 96 0000001C 8B4D30 mov ecx, [ebp + secondPieceStartingByte] + 97 0000001F 8B452C mov eax, [ebp + firstPieceStartingByte] + 98 00000022 01F9 add ecx, edi + 99 00000024 01F1 add ecx, esi + 100 00000026 01F8 add eax, edi + 101 00000028 01F0 add eax, esi + 102 + 103 0000002A 8A18 mov BYTE bl, [eax] + 104 0000002C 8A11 mov BYTE dl, [ecx] + 105 0000002E 8819 mov BYTE[ecx], bl + 106 00000030 8810 mov BYTE[eax], dl + 107 + 108 00000032 8A5801 mov BYTE bl, [eax + 1] + 109 00000035 8A5101 mov BYTE dl, [ecx + 1] + 110 00000038 885901 mov BYTE[ecx + 1], bl + 111 0000003B 885001 mov BYTE[eax + 1], dl + 112 + 113 0000003E 8A5802 mov BYTE bl, [eax + 2] + 114 00000041 8A5102 mov BYTE dl, [ecx + 2] + 115 00000044 885902 mov BYTE[ecx + 2], bl + 116 00000047 885002 mov BYTE[eax + 2], dl + 117 + 118 + 119 + 120 0000004A 037528 add esi, [ebp + bytes_per_row_address] + 121 0000004D EBC8 jmp y_pixels_loop + 122 + 123 + 124 ; for(x = 0; x < pieceWidth * 3; x += 3) + 125 y_pixels_loop_end: + 126 0000004F 83C703 add edi, 3 + 127 00000052 EBB9 jmp x_pixels_loop + 128 + 129 x_pixels_loop_end: + 130 + 131 00000054 5E pop esi + 132 00000055 5F pop edi + 133 00000056 5B pop ebx + 134 00000057 89EC mov esp, ebp + 135 00000059 5D pop ebp + 136 0000005A C3 ret diff --git a/ECOAR/C/asm_part.o b/ECOAR/C/asm_part.o new file mode 100644 index 00000000..919e606c Binary files /dev/null and b/ECOAR/C/asm_part.o differ diff --git a/ECOAR/C/dest.bmp b/ECOAR/C/dest.bmp new file mode 100644 index 00000000..b60a0969 Binary files /dev/null and b/ECOAR/C/dest.bmp differ diff --git a/ECOAR/C/makefile b/ECOAR/C/makefile new file mode 100755 index 00000000..26c4d41c --- /dev/null +++ b/ECOAR/C/makefile @@ -0,0 +1,14 @@ +CC=gcc +ASMBIN=nasm + +all : asm cc link +asm : + $(ASMBIN) -o asm_part.o -f elf32 -g -l asm_part.lst asm_part.asm +cc : + $(CC) -m32 -c -g -O0 puzzle.c +link : + $(CC) -m32 -g -o puzzle.out -g puzzle.o asm_part.o -no-pie +clean : + rm *.o + rm setcol_test + rm asm_part.lst diff --git a/ECOAR/C/pictures/source.bmp b/ECOAR/C/pictures/source.bmp new file mode 100755 index 00000000..545e5a28 Binary files /dev/null and b/ECOAR/C/pictures/source.bmp differ diff --git a/ECOAR/C/puzzle.c b/ECOAR/C/puzzle.c new file mode 100755 index 00000000..bf78dde4 --- /dev/null +++ b/ECOAR/C/puzzle.c @@ -0,0 +1,369 @@ +// ECOAR x86 PUZZLE Project Krzysztof Rudnicki, 307585 +#include // fopen(); fread(); fwrite(); fclose() +#include // printf(); srand(); +#include // malloc(); free(); +#include // time(); + +const int BMP_HEADER_SIZE = 54; +// as per: https://www.daubnet.com/en/file-format-bmp +const int BMP_SIGNATURE_0x = 0x4D42; +// as per: https://www.daubnet.com/en/file-format-bmp +const int NUMBER_OF_HEADERS = 1; // There is only one header in BMP file +const int BYTE_PER_PIXEL = 24; // as per project description of the bmp file +const int DESIRED_COMPRESSION_VALUE = 0; +// as per project description of the bmp file +const int CANNOT_OPEN_FILE_FOR_WRITING = -1; +const int CANNOT_WRITE_HEADER_OR_IMAGE = -2; +const int BYTES_FOR_SINGLE_PIXEL = 3; // R byte + G byte + B byte +const int WRONG_BMP_HEADER_SIZE = 1; +const int ERROR_READING_SOURCE_FILE = 2; + +const char ENTER_VERTICAL_DIVISON_MESSAGE[] += "Enter number of vertical divisons: "; + +const char ENTER_HORIZONTAL_DIVISON_MESSAGE[] += "Enter number of horizontal divisons: "; + +const char WRONG_BMP_HEADER_SIZE_MESSAGE[] += "Check compilation options so as bmpHeaderInfo struct size is 54 bytes.\n"; + +const char READ_AND_BINARY_MODE[] = "rb"; // open file to read and binary mode +const char WRITE_AND_BINARY_MODE[] = "wb"; // open file to write and binary mode +const char SOURCE_IMAGE_NAME[] = "source.bmp"; // as per project description +const char DESTINATION_IMAGE_NAME[] = "dest.bmp"; // as per project description +const char ERROR_READING_SOURCE_FILE_MESSAGE[] += "Error reading source file (probably).\n"; + +// "Specifies the packing alignment for structure, union, and class members." +// something like .align in MIPS? +// https://docs.microsoft.com/en-us/cpp/preprocessor/pack?view=msvc-160 +#pragma pack(push, 1) +/* push - pushed to stack, n = 1 +n - (Optional) Specifies the value, in bytes, to be used for packing. +If the compiler option /Zp isn't set for the module, +the default value for n is 8. Valid values are 1, 2, 4, 8, and 16. +The alignment of a member is on a boundary that's either a +multiple of n, or a multiple of the size of the member, +whichever is smaller. */ +// We pack it to "1" to get exactly 54 bytes for bmpHeaderInfo structure +// Changing it to "8" gives us an error, changing it to "2" does not + + +typedef struct +{ + unsigned short bytesImageType; // 0x4D42 = "BMP" in Ascii, not used + unsigned long bytesFileSize; // file size in bytes, not used + unsigned short bfReservedOne; // reserved bytes from bmp file + unsigned short bfReservedTwo; // reserved bytes from bmp file + unsigned long bytesPixelDataOffset; // offset of pixel data, not used + unsigned long bytesHeaderSize; + // header size (bitmap info size), not used + long bytesImageWidth; // image width, USED + long bytesImageHeight; // image height, USED + short bytesBitmapPlanes; // bitmap planes (== 1) USED + short bytesPixelBitCount; + // bit count of a pixel (== 24) (24 from project description), USED + unsigned long bytesImageCompression; + // should be 0 (no compression), USED + unsigned long bytesImageSize; // image size (not file size!), USED + long bytesHorizontalResolution; // horizontal resolution, not used + long bytesVerticalResolution; // vertical resolution, not used + unsigned long bytesColorsUsed; + // not important for RGB images, not used + unsigned long bytesColorsImportant; + // not important for RGB images, not used +} bmpHeaderInfo; +// Struct containing info from header of a RGB type BMP file + +#pragma pack(pop) +// stack popped + +typedef struct +{ + unsigned int imageWidth; + unsigned int imageHeight; // same as in bmpHeaderInfo + unsigned int bytesPerRow; + // Bytes per row, important in MIPS, important here + unsigned char* pImg; + // pImg is a pointer to the begining of pixels data of the picture + bmpHeaderInfo *pHeaderInfo; // pointer to info from header +} imageInfo; // Stores info about image + + + + + + + +// If we want to write something to imageInfo struct first we need to empty it +imageInfo* allocateSpaceForImageInfo() +{ +// we allocate as much space as this struct needs + imageInfo* emptyImageInfo = malloc(sizeof(imageInfo)); +// Then in this "if" we basically set starting values for +// everything we care about + if (emptyImageInfo != NULL) + { + emptyImageInfo->imageWidth = 0; + emptyImageInfo->imageHeight = 0; + emptyImageInfo->bytesPerRow = 0; + emptyImageInfo->pImg = NULL; + emptyImageInfo->pHeaderInfo = NULL; + } + return emptyImageInfo; // Then we retun the struct that we will use +} + +void* freeImageInfo(imageInfo* toFree) +{ + if (toFree != NULL) // If image info is already empty no need to free it + { + if (toFree->pImg != NULL) free(toFree->pImg); + // pImg is an char* so we need to free it extra + if (toFree->pHeaderInfo != NULL) free(toFree->pHeaderInfo); + // pHeaderInfo is a struct so we need to free it extra + free(toFree); // Finally we can free the rest of the struct + } + return NULL; + // we return void* since function readBMP calling freeImageInfo returns a + // pointer +} + +// We use pFile to read/write to file and struct containing imageInfo in our +// program, we have to free memory after using these two +void* freeResources(FILE* pFile, imageInfo* toFree) +{ + if (pFile != NULL) fclose(pFile); // Close file if it isn't already closed + return freeImageInfo(toFree); +} + + +imageInfo* readBMP(const char* fileName) +{ + imageInfo* pInfo = 0; + /* https://stackoverflow.com/q/48288191 + Assignment of the constant 0 to a pointer will produce a null pointer + distinguishable from a pointer to any object. */ + FILE* bmpFile = 0; + + // allocateSpaceForImageInfo returns NULL if something went bad + pInfo = allocateSpaceForImageInfo(); + if (pInfo == NULL) return NULL; + + + // if fopen returns NULL then something bad happened + bmpFile = fopen(fileName, READ_AND_BINARY_MODE); + // cannot open file + if (bmpFile == NULL) return freeResources(bmpFile, pInfo); + + /* 1. if malloc didn't allocate any memory then something bad happened + fread arguments: buffer to which we will save data that we read + size of single data element in bytes + number of elements that we will read + stream on which this operation will be done + We will save data to pHeaderInfo so that's our buffer + We will get as much data as there is in bmpHeader + There is just one header so we will read just from one header + We will read all of that from bmp file + it returns number of correctly read values, our desired return value is + 1 so if it returns any other then there was a mistake + NUMBER_OF_HEADERS = 1 */ + pInfo->pHeaderInfo = malloc(sizeof(bmpHeaderInfo)); + size_t returnedElements = fread( (void*)pInfo->pHeaderInfo, + sizeof(bmpHeaderInfo), + NUMBER_OF_HEADERS, + bmpFile ); + + if (pInfo->pHeaderInfo == NULL || returnedElements != NUMBER_OF_HEADERS) + { + return freeResources(bmpFile, pInfo); + } + + /* We check if image type is different than BMP + We check if bitmap planes are different than 1 + we check if number of bits in one pixels is differnt than 24 + we check if there is any image compresssion + those are the project assumptions if any of them are broken then there + was a mistake + BMP_SIGNATURE_0x = 0x4D42 + BYTE_PER_PIXEL = 24 + DESIRED_COMPRESSION_VALUE = 0 */ + if( pInfo->pHeaderInfo->bytesImageType != BMP_SIGNATURE_0x || + pInfo->pHeaderInfo->bytesBitmapPlanes != 1 || + pInfo->pHeaderInfo->bytesPixelBitCount != BYTE_PER_PIXEL || + pInfo->pHeaderInfo->bytesImageCompression != DESIRED_COMPRESSION_VALUE) + { + return (imageInfo*) freeResources(bmpFile, pInfo); + } + + /* We check if we allocated any memory to the image + We check if number of read elements from the file are different than + image size in bytes if any of this this is true then + something went wrong + */ + pInfo->pImg = malloc(pInfo->pHeaderInfo->bytesImageSize); + size_t returnedElementsData = fread((void *)pInfo->pImg, + 1, + pInfo->pHeaderInfo->bytesImageSize, + bmpFile); + if( pInfo->pImg == NULL || + returnedElementsData != pInfo->pHeaderInfo->bytesImageSize) + { + return (imageInfo*) freeResources(bmpFile, pInfo); + } + + + fclose(bmpFile); // We can close the file + + pInfo->imageWidth = pInfo->pHeaderInfo->bytesImageWidth; + pInfo->imageHeight = pInfo->pHeaderInfo->bytesImageHeight; + + pInfo->bytesPerRow = pInfo->pHeaderInfo->bytesImageSize / + pInfo->pHeaderInfo->bytesImageHeight; + + // bytesPerRow = imageSize / imageHeight + return pInfo; +} + +int saveBMP(const imageInfo* pInfo, const char* fileName) +{ + FILE *bmpFile = fopen(fileName, WRITE_AND_BINARY_MODE); + + // fopen returns NULL if something went bad + // WRITE_AND_BINARY_MODE = "wb" + // cannot open file for writing + if (bmpFile == NULL) return CANNOT_OPEN_FILE_FOR_WRITING; + + /* if we wrote more or less than one header then there is something wrong + if we wrote more or less bytes to the image than there are bytes in the + image then there is something wrong + CANNOT_WRITE_HEADER_OR_IMAGE = -2 */ + size_t returnedHeaders = fwrite(pInfo->pHeaderInfo, sizeof(bmpHeaderInfo), + NUMBER_OF_HEADERS, bmpFile); + size_t returnedData = fwrite(pInfo->pImg, 1, + pInfo->pHeaderInfo->bytesImageSize, bmpFile); + + if (returnedHeaders != NUMBER_OF_HEADERS || + returnedData != pInfo->pHeaderInfo->bytesImageSize) + { + fclose(bmpFile); // cannot write header or image + return CANNOT_WRITE_HEADER_OR_IMAGE; + } + + fclose(bmpFile); + return 0; +} + +void set_pixel(unsigned char * pPix, unsigned int color) +{ + /* pImg -> pImg returns the starting addres of pixels + then we calculate byte position of a pixel we want to change by: + bytesPerRow * y_coordinate + x * 3 (3 bytes for RGB) + BYTES_FOR_SINGLE_PIXEL = 3 */ + + // if x and y are inside the image then we can commence forward + + *pPix = (color >> 16) & 0xFF; // R color of the pixel + *(pPix + 1) = (color >> 8) & 0xFF; // G color of the pixel + *(pPix + 2) = color & 0xFF; // B color of the pixel +} + +unsigned int getColor(unsigned char * pPix) +{ + char R, G, B; // change to unsigned char + R = *pPix; + G = *(pPix + 1); + B = *(pPix + 2); + unsigned int color = 0; + color = ( ((R & 0xFF) << 16) | (( G & 0xFF) << 8) | (B & 0xFF)); + return color; +} + +int calculateStartingPixelX(int pieceNumber, int horizontalDivisons, + int pieceWidth) +{ + int temp = pieceNumber % horizontalDivisons; + if(temp == 0) temp = horizontalDivisons; + return (temp - 1) * pieceWidth; +} + +int calculateStartingPixelY(int pieceNumber, int horizontalDivisons, + int pieceHeight) +{ + return (((pieceNumber - 1) / horizontalDivisons) * pieceHeight); +} + + extern void inner_loops(imageInfo* pInfo, int firstPiece, int pieceToSwapWith, + int horizontalDivisions, int pieceWidth, + int pieceHeight, int pieceWidthBytes, int bieceHeightBytes, + unsigned int bytesPerRow, + unsigned char *firstPieceStartingByte, + unsigned char *secondPieceStartingByte); // Incomplete x86 solution + +int main(/*int argc, char* argv[]*/) // argc and argv[] are not used anywhere +{ + + imageInfo* pInfo; // imageInfo holds all header data from image + unsigned int columnIndex = 0; + // bmp header and info header should be 54 bytes as per BMP documentation + // https://www.daubnet.com/en/file-format-bmp + if (sizeof(bmpHeaderInfo) != BMP_HEADER_SIZE) + { + printf(WRONG_BMP_HEADER_SIZE_MESSAGE); + return WRONG_BMP_HEADER_SIZE; + } + if ((pInfo = readBMP(SOURCE_IMAGE_NAME)) == NULL) + { + printf(ERROR_READING_SOURCE_FILE_MESSAGE); + return ERROR_READING_SOURCE_FILE; + } + + int verticalDivisions, horizontalDivisions; + printf(ENTER_VERTICAL_DIVISON_MESSAGE); + scanf("%d", &verticalDivisions); + printf(ENTER_HORIZONTAL_DIVISON_MESSAGE); + scanf("%d", &horizontalDivisions); + + int numberOfPieces = verticalDivisions * horizontalDivisions; + int pieceWidth = (pInfo -> imageWidth) / horizontalDivisions; + int pieceHeight = (pInfo -> imageHeight) / verticalDivisions; + int pieceWidthBytes = pieceWidth * 3; + int bieceHeightBytes = pieceHeight * (pInfo -> bytesPerRow); + srand(time(NULL)); + int firstPiece; + for(firstPiece = 1; firstPiece <= numberOfPieces; firstPiece++) + { + int pieceToSwapWith = rand() % numberOfPieces; + // hello_world(pInfo, firstPiece, pieceToSwapWith, horizontalDivisions, + // pieceWidth, pieceHeight, pieceWidthBytes, bieceHeightBytes, pInfo -> bytesPerRow); // Incomplete x86 solution + + + + int firstPieceStartingX = calculateStartingPixelX(firstPiece, horizontalDivisions, pieceWidth); + int firstPieceStartingY = calculateStartingPixelY(firstPiece, horizontalDivisions, pieceHeight); + unsigned char *firstPieceStartingByte = firstPieceStartingX * 3 + firstPieceStartingY * pInfo -> bytesPerRow + pInfo -> pImg; + + int secondPieceStartingX = calculateStartingPixelX(pieceToSwapWith, horizontalDivisions, pieceWidth); + int secondPieceStartingY = calculateStartingPixelY(pieceToSwapWith, horizontalDivisions, pieceHeight); + unsigned char *secondPieceStartingByte = secondPieceStartingX * 3 + secondPieceStartingY * pInfo -> bytesPerRow + pInfo -> pImg; + + inner_loops(pInfo, firstPiece, pieceToSwapWith, horizontalDivisions, + pieceWidth, pieceHeight, pieceWidthBytes, bieceHeightBytes, pInfo -> bytesPerRow, firstPieceStartingByte, secondPieceStartingByte); + /* int x = 0; + for(x = 0; x < pieceWidth * 3; x += 3) + { + int y = 0; + for(y = 0; y < pieceHeight * pInfo -> bytesPerRow; y += pInfo -> bytesPerRow) + { + unsigned int colorOne = getColor(secondPieceStartingByte + x + y); + unsigned int colorTwo = getColor(firstPieceStartingByte + x + y); + set_pixel(firstPieceStartingByte + x + y, colorOne); + set_pixel(secondPieceStartingByte + x + y, colorTwo); + } + } */ + } + + saveBMP(pInfo, DESTINATION_IMAGE_NAME); + freeResources(NULL, pInfo); + // printf("Operation failed succesfully\n"); + return 0; +} diff --git a/ECOAR/C/puzzle.o b/ECOAR/C/puzzle.o new file mode 100644 index 00000000..91c5bf6f Binary files /dev/null and b/ECOAR/C/puzzle.o differ diff --git a/ECOAR/C/puzzle.out b/ECOAR/C/puzzle.out new file mode 100755 index 00000000..0f052c22 Binary files /dev/null and b/ECOAR/C/puzzle.out differ diff --git a/ECOAR/C/source.bmp b/ECOAR/C/source.bmp new file mode 100755 index 00000000..545e5a28 Binary files /dev/null and b/ECOAR/C/source.bmp differ diff --git a/ECOAR/C/tests/Outputs/test1.bmp b/ECOAR/C/tests/Outputs/test1.bmp new file mode 100644 index 00000000..ca0aee08 Binary files /dev/null and b/ECOAR/C/tests/Outputs/test1.bmp differ diff --git a/ECOAR/C/tests/Outputs/test2.bmp b/ECOAR/C/tests/Outputs/test2.bmp new file mode 100644 index 00000000..99fbd435 Binary files /dev/null and b/ECOAR/C/tests/Outputs/test2.bmp differ diff --git a/ECOAR/C/tests/Outputs/test3.bmp b/ECOAR/C/tests/Outputs/test3.bmp new file mode 100644 index 00000000..3f8df047 Binary files /dev/null and b/ECOAR/C/tests/Outputs/test3.bmp differ diff --git a/ECOAR/C/tests/Outputs/test4.bmp b/ECOAR/C/tests/Outputs/test4.bmp new file mode 100644 index 00000000..d55aa382 Binary files /dev/null and b/ECOAR/C/tests/Outputs/test4.bmp differ diff --git a/ECOAR/C/tests/Outputs/test5.bmp b/ECOAR/C/tests/Outputs/test5.bmp new file mode 100644 index 00000000..6dde4bf6 Binary files /dev/null and b/ECOAR/C/tests/Outputs/test5.bmp differ diff --git a/ECOAR/C/tests/Outputs/test6.bmp b/ECOAR/C/tests/Outputs/test6.bmp new file mode 100644 index 00000000..27871dce Binary files /dev/null and b/ECOAR/C/tests/Outputs/test6.bmp differ diff --git a/ECOAR/C/tests/Outputs/test7.bmp b/ECOAR/C/tests/Outputs/test7.bmp new file mode 100644 index 00000000..545e5a28 Binary files /dev/null and b/ECOAR/C/tests/Outputs/test7.bmp differ diff --git a/ECOAR/C/tests/Outputs/test8.bmp b/ECOAR/C/tests/Outputs/test8.bmp new file mode 100644 index 00000000..3a6ceb34 Binary files /dev/null and b/ECOAR/C/tests/Outputs/test8.bmp differ diff --git a/ECOAR/C/tests/Sources/source1.bmp b/ECOAR/C/tests/Sources/source1.bmp new file mode 100755 index 00000000..545e5a28 Binary files /dev/null and b/ECOAR/C/tests/Sources/source1.bmp differ diff --git a/ECOAR/C/tests/testDescription.txt b/ECOAR/C/tests/testDescription.txt new file mode 100644 index 00000000..3051c7fa --- /dev/null +++ b/ECOAR/C/tests/testDescription.txt @@ -0,0 +1,50 @@ +One of the easiest scenarios, divisable in both dimensions, both being same number and low number +1. Input file : source1.bmp, + Vertical Divisions: 2 + Horizontal Divisions: 2 + Result: test1.bmp + +Both divisable and equal to 10 but higher number +2. Input file : source1.bmp, + Vertical Divisions: 10 + Horizontal Divisions: 10 + Result: test2.bmp + +Low number, divisable, different +3. Input file : source1.bmp, + Vertical Divisions: 3 + Horizontal Divisions: 4 + Result: test3.bmp + +Low number, not divisable, diffrent +4. Input file : source1.bmp, + Vertical Divisions: 4 + Horizontal Divisions: 3 + Result: test4.bmp + +Very different number, divisable +5. Input file : source1.bmp, + Vertical Divisions: 2 + Horizontal Divisions: 20 + Result: test5.bmp + +Very different number, divisable +6. Input file : source1.bmp, + Vertical Divisions: 20 + Horizontal Divisions: 2 + Result: test6.bmp + +Highest number, different, non divisable +7. Input file : source1.bmp, + Vertical Divisions: 320 + Horizontal Divisions: 240 + Result: test7.bmp + +Highest number, different, divisable +8. Input file : source1.bmp, + Vertical Divisions: 240 + Horizontal Divisions: 320 + Result: test8.bmp + + + diff --git a/ECOAR/LICENSE b/ECOAR/LICENSE new file mode 100644 index 00000000..37b2665c --- /dev/null +++ b/ECOAR/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Krzysztof Rudnicki + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/ECOAR/Puzzle/puzzle.asm b/ECOAR/Puzzle/puzzle.asm new file mode 100755 index 00000000..4da5f042 --- /dev/null +++ b/ECOAR/Puzzle/puzzle.asm @@ -0,0 +1,406 @@ +#only 24-bits 320x240 pixels BMP files are supported +# 24 * 320 * 240 = 1843200 bits = 1843200 / 8 bytes = 230400 bytes +# let's round it to 240000 for a good measure +.eqv BMP_FILE_SIZE 230454 +.eqv BYTES_PER_ROW 960 + +.data + .align 4 + res: .space 2 + image: .space BMP_FILE_SIZE + start_message_vertical: .asciiz "\nEnter number of vertical divisions:\n" # .asciiz stores the string + end_message_vertical: .asciiz "You entered this many vertical divisions: " + start_message_horizontal: .asciiz "\nEnter number of horizontal divisions:\n" + end_message_horizontal : .asciiz "You entered this many horizontal divisions: " + start_message: .asciiz "Enter number of vertical and horizontal divisions:\n" + buffer: .space 1024 + HEIGHT: .word 240 + WIDTH: .word 320 + newline: .asciiz "\n" + pieces: .word + input_file_name: .asciiz "source.bmp" # name of input file as choosen in the project instruction + output_file_name: .asciiz "dest.bmp" # name of output file as choosen in the project instruction + +.text + +_main: + jal user_input_horizontal_division # puts number of horizontal divisions to $s5 + jal user_input_vertical_division # puts number of vertical divisions to $s4 + jal calculate_number_of_pieces # puts number of pieces to $s3 + jal random_number + jal calculate_piece_WIDTH # calculates the WIDTH of a single piece based on number of vertical divisons + jal calculate_piece_HEIGHT # calculates the WIDTH of a single piece based on number of horizontal divisons + jal read_bmp + + li $a0, 8 + jal calculate_piece_position_x + li $a0, 8 + jal calculate_piece_position_y + li $a0, 9 + jal calculate_piece_position_y + li $a0, 5 + jal calculate_piece_position_y + li $a0, 2 + jal calculate_piece_position_y + li $a0, 10 + jal calculate_piece_position_y + + #put red pixel in bottom left corner + li $a0, 0 #x + li $a1, 0 #y + li $a2, 0x00FF0000 #color - 00RRGGBB + jal put_pixel + + #get pixel from x y + li $a0, 0 #x + li $a1, 0 #y + jal get_pixel_v0 + #get pixel from x y + li $a0, 0 #x + li $a1, 5 #y + jal get_pixel_v1 + + #put pixel that we got from the previous get pixel to x y position + li $a0, 0 #x + li $a1, 1 #y + move $a2, $v0 + jal put_pixel + + #put pixel that we got from the previous get pixel to x y position + li $a0, 0 #x + li $a1, 2 #y + move $a2, $v1 + jal put_pixel + + jal save_bmp + jal end_program + +.macro print(%text) + la $a0, %text + li $v0, 4 + syscall +.end_macro + +.macro print_int(%num) + li $v0, 1 # If you want to print the integer the code is 1 + move $a0, %num # move the integer stored in %num to $a0 + syscall +.end_macro + +.macro println() + la $a0, newline # New line string stored here + li $v0, 4 + syscall +.end_macro + + +calculate_piece_position_x: # piece value is taken from $a0 + div $a0, $s4 # number of vertical divisons is stored in $s4 + mfhi $a1 + beq $a1, 0, piece_position_x_mod_zero + sub $a1, $a1, 1 + println() + print_int($a1) + jr $ra + +piece_position_x_mod_zero: + li $a2, 0 + add $a2, $a2, $s5 + println() + print_int($a2) + jr $ra + + +calculate_piece_position_y: #piece value is taken from $a0 + div $a0, $s4 + mfhi $a1 + beq $a1, 0, piece_position_y_mod_zero + div $a2, $a0, $s4 + move $t0, $s4 + sub $a2, $t0, $a2 + println() + print_int($a2) + jr $ra + + +piece_position_y_mod_zero: + div $a2, $a0, $s4 + li $t0, 0 + add $t0, $s4, 1 + sub $a2, $t0, $a2 + println() + print_int($a2) + jr $ra + +calculate_number_of_pieces: + mul $s3, $s4, $s5 + jr $ra + +random_number: + move $a1, $s3 #Here you set $a1 to the max bound. + li $v0, 42 #generates the random number. + syscall + #add $a0, $a0, 100 #Here you add the lowest bound + #li $v0, 1 #1 print integer + syscall + jr $ra + + + +close_file: + li $v0, 16 + move $a0, $s6 + syscall + jr $ra + +calculate_piece_WIDTH: + lw $a0, HEIGHT + div $s1, $a0, $s4 # number of vertical divisons is kept in $s1 + jr $ra + +calculate_piece_HEIGHT: + lw $a0, WIDTH + div $s2, $a0, $s5 # number of vertical divisons is kept in $s2 + jr $ra + +display_start_message: + print(start_message) + + +user_input_vertical_division: # puts number of vertical divisions to $s4 + print(start_message_vertical) + li $v0, 5 # we want to get the integer from the keyboard + syscall # this will allow us to enter the number which will be stored in $v0 + # Store the result in $t0 + move $s4, $v0 # $t0 = $v0 + print(end_message_vertical) + print_int($s4) + jr $ra + +enter_int: + li $v0, 5 # we want to get the integer from the keyboard + syscall # this will allow us to enter the number which will be stored in $v0 + # Store the result in $t0 + move $t0, $v0 # $t0 = $v0 + jr $ra + + + +user_input_horizontal_division: # puts number of vertical divisions to $s5 + print(start_message_horizontal) + li $v0, 5 # we want to get the integer from the keyboard + syscall # this will allow us to enter the number which will be stored in $v0 + # Store the result in $t0 + move $s5, $v0 # $t0 = $v0 + print(end_message_horizontal) + print_int($s5) + jr $ra + +calculate_picture_area: + lw $t0, HEIGHT + lw $t1, WIDTH + mul $t2, $t0, $t1 + jr $ra + +read_bmp: +#description: +# reads the contents of a bmp file into memory +#arguments: +# none +#return value: none + sub $sp, $sp, 4 #push $ra to the stack + sw $ra,($sp) + sub $sp, $sp, 4 #push $s1 + sw $s1, ($sp) +#open file + li $v0, 13 + la $a0, input_file_name #file name + li $a1, 0 #flags: 0-read file + li $a2, 0 #mode: ignored + syscall + move $s1, $v0 # save the file descriptor + +#check for errors - if the file was opened +#... + +#read file + li $v0, 14 + move $a0, $s1 + la $a1, image + li $a2, BMP_FILE_SIZE + syscall + +#close file + li $v0, 16 + move $a0, $s1 + syscall + + lw $s1, ($sp) #restore (pop) $s1 + add $sp, $sp, 4 + lw $ra, ($sp) #restore (pop) $ra + add $sp, $sp, 4 + jr $ra + +put_pixel: +#description: +# sets the color of specified pixel +#arguments: +# $a0 - x coordinate +# $a1 - y coordinate - (0,0) - bottom left corner +# $a2 - 0RGB - pixel color +#return value: none + + sub $sp, $sp, 4 #push $ra to the stack + sw $ra,($sp) + + la $t1, image + 10 #adress of file offset to pixel array + lw $t2, ($t1) #file offset to pixel array in $t2 + la $t1, image #adress of bitmap + add $t2, $t1, $t2 #adress of pixel array in $t2 + + #pixel address calculation + mul $t1, $a1, BYTES_PER_ROW #t1= y*BYTES_PER_ROW + move $t3, $a0 + sll $a0, $a0, 1 + add $t3, $t3, $a0 #$t3= 3*x + add $t1, $t1, $t3 #$t1 = 3x + y*BYTES_PER_ROW + add $t2, $t2, $t1 #pixel address + + #set new color + sb $a2,($t2) #store B + srl $a2,$a2,8 + sb $a2,1($t2) #store G + srl $a2,$a2,8 + sb $a2,2($t2) #store R + + lw $ra, ($sp) #restore (pop) $ra + add $sp, $sp, 4 + jr $ra + + +get_pixel_v0: +#description: +# returns color of specified pixel +#arguments: +# $a0 - x coordinate +# $a1 - y coordinate - (0,0) - bottom left corner +#return value: +# $v0 - 0RGB - pixel color + + sub $sp, $sp, 4 #push $ra to the stack + sw $ra,($sp) + + la $t1, image + 10 #adress of file offset to pixel array + lw $t2, ($t1) #file offset to pixel array in $t2 + la $t1, image #adress of bitmap + add $t2, $t1, $t2 #adress of pixel array in $t2 + + #pixel address calculation + mul $t1, $a1, BYTES_PER_ROW #t1= y*BYTES_PER_ROW + move $t3, $a0 + sll $a0, $a0, 1 + add $t3, $t3, $a0 #$t3= 3*x + add $t1, $t1, $t3 #$t1 = 3x + y*BYTES_PER_ROW + add $t2, $t2, $t1 #pixel address + + #get color + lbu $v0,($t2) #load B + lbu $t1,1($t2) #load G + sll $t1,$t1,8 + or $v0, $v0, $t1 + lbu $t1,2($t2) #load R + sll $t1,$t1,16 + or $v0, $v0, $t1 + + lw $ra, ($sp) #restore (pop) $ra + add $sp, $sp, 4 + jr $ra + +get_pixel_v1: +#description: +# returns color of specified pixel +#arguments: +# $a0 - x coordinate +# $a1 - y coordinate - (0,0) - bottom left corner +#return value: +# $v1 - 0RGB - pixel color + + sub $sp, $sp, 4 #push $ra to the stack + sw $ra,($sp) + + la $t1, image + 10 #adress of file offset to pixel array + lw $t2, ($t1) #file offset to pixel array in $t2 + la $t1, image #adress of bitmap + add $t2, $t1, $t2 #adress of pixel array in $t2 + + #pixel address calculation + mul $t1, $a1, BYTES_PER_ROW #t1= y*BYTES_PER_ROW + move $t3, $a0 + sll $a0, $a0, 1 + add $t3, $t3, $a0 #$t3= 3*x + add $t1, $t1, $t3 #$t1 = 3x + y*BYTES_PER_ROW + add $t2, $t2, $t1 #pixel address + + #get color + lbu $v1,($t2) #load B + lbu $t1,1($t2) #load G + sll $t1,$t1,8 + or $v1 $v1, $t1 + lbu $t1,2($t2) #load R + sll $t1,$t1,16 + or $v1, $v1, $t1 + + lw $ra, ($sp) #restore (pop) $ra + add $sp, $sp, 4 + jr $ra + + save_bmp: +#description: +# saves bmp file stored in memory to a file +#arguments: +# none +#return value: none + sub $sp, $sp, 4 #push $ra to the stack + sw $ra,($sp) + sub $sp, $sp, 4 #push $s1 + sw $s1, ($sp) +#open file + li $v0, 13 + la $a0, output_file_name #file name + li $a1, 1 #flags: 1-write file + li $a2, 0 #mode: ignored + syscall + move $s1, $v0 # save the file descriptor + +#check for errors - if the file was opened +#... + +#save file + li $v0, 15 + move $a0, $s1 + la $a1, image + li $a2, BMP_FILE_SIZE + syscall + +#close file + li $v0, 16 + move $a0, $s1 + syscall + + lw $s1, ($sp) #restore (pop) $s1 + add $sp, $sp, 4 + lw $ra, ($sp) #restore (pop) $ra + add $sp, $sp, 4 + jr $ra + + + +end_program: + li $v0, 10 + syscall + + + + + +