Merge remote-tracking branch 'ECOAR/main' into main
136
ECOAR/C/asm_part.asm
Executable 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
@ -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
BIN
ECOAR/C/dest.bmp
Normal file
|
After Width: | Height: | Size: 225 KiB |
14
ECOAR/C/makefile
Executable 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
|
After Width: | Height: | Size: 225 KiB |
369
ECOAR/C/puzzle.c
Executable 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
BIN
ECOAR/C/puzzle.out
Executable file
BIN
ECOAR/C/source.bmp
Executable file
|
After Width: | Height: | Size: 225 KiB |
BIN
ECOAR/C/tests/Outputs/test1.bmp
Normal file
|
After Width: | Height: | Size: 225 KiB |
BIN
ECOAR/C/tests/Outputs/test2.bmp
Normal file
|
After Width: | Height: | Size: 225 KiB |
BIN
ECOAR/C/tests/Outputs/test3.bmp
Normal file
|
After Width: | Height: | Size: 225 KiB |
BIN
ECOAR/C/tests/Outputs/test4.bmp
Normal file
|
After Width: | Height: | Size: 225 KiB |
BIN
ECOAR/C/tests/Outputs/test5.bmp
Normal file
|
After Width: | Height: | Size: 225 KiB |
BIN
ECOAR/C/tests/Outputs/test6.bmp
Normal file
|
After Width: | Height: | Size: 225 KiB |
BIN
ECOAR/C/tests/Outputs/test7.bmp
Normal file
|
After Width: | Height: | Size: 225 KiB |
BIN
ECOAR/C/tests/Outputs/test8.bmp
Normal file
|
After Width: | Height: | Size: 225 KiB |
BIN
ECOAR/C/tests/Sources/source1.bmp
Executable file
|
After Width: | Height: | Size: 225 KiB |
50
ECOAR/C/tests/testDescription.txt
Normal 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
@ -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
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||