Merge remote-tracking branch 'ECOAR/main' into main

This commit is contained in:
PolishPigeon 2022-06-18 00:51:36 +02:00
commit 399ec5e532
22 changed files with 1132 additions and 0 deletions

136
ECOAR/C/asm_part.asm Executable file
View File

@ -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

136
ECOAR/C/asm_part.lst Normal file
View File

@ -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

BIN
ECOAR/C/asm_part.o Normal file

Binary file not shown.

BIN
ECOAR/C/dest.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 KiB

14
ECOAR/C/makefile Executable file
View File

@ -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

BIN
ECOAR/C/pictures/source.bmp Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 KiB

369
ECOAR/C/puzzle.c Executable file
View File

@ -0,0 +1,369 @@
// ECOAR x86 PUZZLE Project Krzysztof Rudnicki, 307585
#include <stdio.h> // fopen(); fread(); fwrite(); fclose()
#include <stdlib.h> // printf(); srand();
#include <memory.h> // malloc(); free();
#include <time.h> // 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;
}

BIN
ECOAR/C/puzzle.o Normal file

Binary file not shown.

BIN
ECOAR/C/puzzle.out Executable file

Binary file not shown.

BIN
ECOAR/C/source.bmp Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 KiB

BIN
ECOAR/C/tests/Sources/source1.bmp Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 KiB

View File

@ -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

21
ECOAR/LICENSE Normal file
View File

@ -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.

406
ECOAR/Puzzle/puzzle.asm Executable file
View File

@ -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