From b3292c1df9f98cebe299850842d26e91a08bc324 Mon Sep 17 00:00:00 2001 From: Valentina Vispo Date: Tue, 1 Jun 2021 21:10:29 -0300 Subject: [PATCH 01/47] global --- Makefile | 4 +++- animations.s | 14 +++++++++----- app.s | 32 +++++++++++++++++--------------- draw.s | 12 ++++++++---- font.s | 33 ++++++++++++++++++++++++++++----- owl.s | 2 +- raven.s | 2 +- screen_animations.s | 16 ++++++++++------ start.s | 4 ++-- 9 files changed, 79 insertions(+), 40 deletions(-) diff --git a/Makefile b/Makefile index 040dc6a..1e0eae2 100644 --- a/Makefile +++ b/Makefile @@ -27,4 +27,6 @@ runQEMU : kernel8.img qemu-system-aarch64 -s -S -M raspi3 -kernel kernel8.img runGDB: - gdb-multiarch -ex "set architecture aarch64" -ex "target remote localhost:1234" --ex "dashboard registers -style list 'x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 x11 x12 x13 x14 x15 x16 x17 x18 x19 x20 x21 x22 x23 x24 x25 x26 x27 x28 x29 x30 sp pc cpsr'" \-ex "add-symbol-file app.o 0x00000000000900c8" \-ex "b break" \-ex "continue" + gdb-multiarch -ex "set architecture aarch64" -ex "target remote localhost:1234" --ex "dashboard registers -style list 'x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 x11 x12 x13 x14 x15 x16 x17 x18 x19 x20 x21 x22 x23 x24 x25 x26 x27 x28 x29 x30 sp pc cpsr'" \-ex "add-symbol-file app.o 0x00000000000c5f54" +#0x00000000000900c8" +#\-ex "b break" \-ex "continue" diff --git a/animations.s b/animations.s index 2d0b77f..33da062 100644 --- a/animations.s +++ b/animations.s @@ -1,18 +1,22 @@ -.ifndef _ANIMATIONS_S -.equ _ANIMATIONS_S, 1 +//.ifndef _ANIMATIONS_S +//.equ _ANIMATIONS_S, 1 -.include "app.s" +//.include "app.s" +.globl delay // NOTE delay delay: add x8, xzr, xzr // counter = 0 add x8, x8, #0xFFF // counter = 0xF...F (un numero enorme) lsl x8, x8, #11 // 3th = * 2^~10 (slow = 1s) // * 2^~9 (medium = ~0,3s) delayloop: - cbz x8, return + cbz x8, delayEnd ldur x9, [sp, #0] stur x9, [sp, #0] sub x8, x8, #1 // counter-- b delayloop -.endif +delayEnd: + ret + +//.endif diff --git a/app.s b/app.s index 17db507..449d137 100644 --- a/app.s +++ b/app.s @@ -1,5 +1,5 @@ -.ifndef _APP_S -.equ _APP_S, 1 +//.ifndef _APP_S +//.equ _APP_S, 1 .equ SCREEN_WIDTH, 640 .equ SCREEN_HEIGH, 480 @@ -8,9 +8,6 @@ .equ COLOR_2, 0xFFFF // Color blanco GB // 0x1607 .equ COLOR_NEGRO, 0x00 -.data - WHITE: .word 0xFFFFFF - // 32 bits (4 bytes) // Registros basura: x1, x2, x8, x9, x10 @@ -21,17 +18,18 @@ // x18 Colour // x20 Base del framebuffer -.include "font.s" -.include "draw.s" -.include "animations.s" -.include "screen_animations.s" +//.include "font.s" +//.include "draw.s" +//.include "animations.s" +//.include "screen_animations.s" -//.globl main -//.globl setColour // https://stackoverflow.com/questions/54918639/linking-2-object-files -//.globl drawPixel +.globl main +.globl setColour // https://stackoverflow.com/questions/54918639/linking-2-object-files +.globl drawPixel +.globl setPixel # NOTE Main main: -break: +//break: mov x20, x0 // X0 Direccion base del framebuffer bl cleanScreen // Limpiamos la pantalla mov x13, 96 // R @@ -157,6 +155,7 @@ break: mov x21, #320 // xc x centro mov x22, #300 // yc y centro +break: bl doRaven // Dibujamos un cuervo //bl circleTest @@ -167,7 +166,7 @@ break: mov x15, 0 // B bl setColour // R+G+B = Rojo //bl doValentinaVispo - bl delay + //bl delay bl cleanScreen // cleanScreen negro @@ -287,6 +286,7 @@ verLineEnd: add sp, sp, #16 // Libera el stack ret +.globl doHorizontalLine // NOTE LineH doHorizontalLine: // Crea líneas horizontales en la coordenada (xo, po) con w cantidad de pixeles que se extienden hacia la derecha // // Args @@ -319,6 +319,7 @@ endHorizontalLine: // BL (Break and link -> funciones) es para salto incondicional, cambia el program counter y cambia el registro x30 // // B (Break dentro de funciones) es para saltos condicionales cambia el program counter // +.globl cleanScreen // NOTE cleanScreen cleanScreen: // Pinta toda la pantalla de negro sub sp, sp, #8 @@ -332,6 +333,7 @@ cleanScreen: // Pinta toda la pantalla de negro add sp, sp, #8 ret +.globl paintScreen // NOTE paintScreen paintScreen: // 320w 240h -> 76800 + 240 // Return -> nada @@ -349,4 +351,4 @@ paintScreenLoop: cbnz x8, paintScreenLoop // If not end row jump ret -.endif +//.endif diff --git a/draw.s b/draw.s index 2760398..5fcf85c 100644 --- a/draw.s +++ b/draw.s @@ -1,8 +1,9 @@ -.ifndef _DRAW_S -.equ _DRAW_S, 1 +//.ifndef _DRAW_S +//.equ _DRAW_S, 1 -.include "app.s" +//.include "app.s" +.globl doSquare // NOTE Square doSquare: // Return -> nada @@ -23,6 +24,7 @@ doSquare: add sp, sp, #16 // Liberamos espacio en memoria ret +.globl doRectangle // NOTE Rectangle alto(h) x largo(w) doRectangle: // alto x largo// // @Diego @@ -59,6 +61,7 @@ endRectangule: add sp, sp, #16 // Liberamos la memoria (movemos el sp "más arriba") ret +.globl doCircle // NOTE Circle doCircle: // Mid-Point Circle Drawing Algorithm // // (0, 0) centro @@ -171,6 +174,7 @@ circleEnd: add sp, sp, #8 ret +.globl doTriangle // NOTE Triangle doTriangle: // @Diego @@ -224,4 +228,4 @@ rectIzq: endTriang: //TODO revisar ret -.endif +//.endif diff --git a/font.s b/font.s index 0241c81..fb35a2c 100644 --- a/font.s +++ b/font.s @@ -1,50 +1,68 @@ -.ifndef _FONT_S -.equ _FONT_S, 1 +//.ifndef _FONT_S +//.equ _FONT_S, 1 -.include "app.s" +//.include "app.s" // Font https://www.dafont.com/es/minitel.font?text=console +.equ SCREEN_WIDTH, 640 +.equ SCREEN_HEIGH, 480 +.equ BITS_PER_PIXEL, 32 +.equ COLOR_1, 0xFF // Color blanco R // 0xC7 +.equ COLOR_2, 0xFFFF // Color blanco GB // 0x1607 +.equ COLOR_NEGRO, 0x00 + +.globl doA // NOTE a doA: // @Vale +.globl doE // NOTE e doE: // @Diego +.globl doI // NOTE i doI: // @Diego +.globl doO // NOTE o doO: // @Diego +.globl doDm // NOTE D doDm: // @Diego +.globl doL // NOTE l doL: // @Vale +.globl doDm // NOTE s doS: // @Vale +.globl doP // NOTE p doP: // @Vale +.globl doM // NOTE m doM: // @Diego +.globl doN // NOTE n doN: // @Vale +.globl doVm // NOTE V doVm: // @Vale @@ -62,23 +80,27 @@ doVm: ret - +.globl doT // NOTE t doT: // @Vale +.globl doZ // NOTE z doZ: // @Diego +.globl doGm // NOTE G doGm: // @Diego +.globl doG // NOTE g doG: // @Diego +.globl doDiego // NOTE Diego doDiego: // @Diego @@ -97,6 +119,7 @@ doDiego: // bl doZ ret +.globl doValentinaVispo // NOTE Vale doValentinaVispo: // @Valentina Vispo @@ -121,4 +144,4 @@ doValentinaVispo: // bl doO ret -.endif +//.endif diff --git a/owl.s b/owl.s index a17bc14..e697cd2 100644 --- a/owl.s +++ b/owl.s @@ -1,4 +1,4 @@ -.include "draw.s" +//.include "draw.s" .globl doOwl doOwl: diff --git a/raven.s b/raven.s index ec6ea3a..fafbd69 100644 --- a/raven.s +++ b/raven.s @@ -1,4 +1,4 @@ -.include "draw.s" +//.include "draw.s" .globl doRaven doRaven: diff --git a/screen_animations.s b/screen_animations.s index f7e1875..38036b9 100644 --- a/screen_animations.s +++ b/screen_animations.s @@ -1,8 +1,12 @@ -.ifndef _SCREEN_ANIMATIONS_S -.equ _SCREEN_ANIMATIONS_S, 1 +//.ifndef _SCREEN_ANIMATIONS_S +//.equ _SCREEN_ANIMATIONS_S, 1 -.include "app.s" +//.include "app.s" +.data + WHITE: .word 0xFFFFFF + +.globl animationTest // NOTE Animation Test animationTest: sub sp, sp, #8 @@ -19,6 +23,7 @@ antestloop: add sp, sp, #8 ret +.globl circleAnimation1 // NOTE circle Animation 1 circleAnimation1: sub sp, sp, #8 @@ -50,6 +55,7 @@ circlend: add sp, sp, #8 ret +.globl circleAnimation2 // NOTE circle Animation 2 circleAnimation2: sub sp, sp, #8 @@ -83,6 +89,4 @@ circ2lend: add sp, sp, #8 ret - - -.endif +//.endif diff --git a/start.s b/start.s index bb11abd..3b59aae 100644 --- a/start.s +++ b/start.s @@ -26,7 +26,7 @@ .equ Set_ClkRate, 0x00038002 // UART: Set Clock Rate .equ MMIO_BASE_ALTA, 0x3f20 - + .equ GPFSEL0, 0x0000 .equ GPFSEL1, 0x0004 .equ GPPUD, 0x0094 @@ -136,4 +136,4 @@ FB_SIZE: .word 0x00000000 // $0 (End Tag) FB_STRUCT_END: -.include "app.s" +//.include "app.s" From 76792e4a7811d18a23aeceb8e6579562d2c647e5 Mon Sep 17 00:00:00 2001 From: Valentina Vispo Date: Tue, 1 Jun 2021 22:34:05 -0300 Subject: [PATCH 02/47] drawLine --- Makefile | 3 +- app.s | 55 ++++++++++++++++++++++++++--- draw.s | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 157 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 1e0eae2..b70b738 100644 --- a/Makefile +++ b/Makefile @@ -27,6 +27,7 @@ runQEMU : kernel8.img qemu-system-aarch64 -s -S -M raspi3 -kernel kernel8.img runGDB: - gdb-multiarch -ex "set architecture aarch64" -ex "target remote localhost:1234" --ex "dashboard registers -style list 'x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 x11 x12 x13 x14 x15 x16 x17 x18 x19 x20 x21 x22 x23 x24 x25 x26 x27 x28 x29 x30 sp pc cpsr'" \-ex "add-symbol-file app.o 0x00000000000c5f54" + gdb-multiarch -ex "set architecture aarch64" -ex "target remote localhost:1234" --ex "dashboard registers -style list 'x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 x11 x12 x13 x14 x15 x16 x17 x18 x19 x20 x21 x22 x23 x24 x25 x26 x27 x28 x29 x30 sp pc cpsr'" \-ex "add-symbol-file app.o 0x00000000000c601c" \-ex "add-symbol-file draw.o 0x00000000000900c8" + #0x00000000000900c8" #\-ex "b break" \-ex "continue" diff --git a/app.s b/app.s index 449d137..949a254 100644 --- a/app.s +++ b/app.s @@ -151,11 +151,56 @@ main: mov x21, #150 // xc x centro mov x22, #150 // yc y centro - bl doOwl // Dibujamos un búho + //bl doOwl // Dibujamos un búho + + // Dibujamos una línea "vertical" + mov x21, 59 + mov x22, 59 + mov x23, 100 + mov x24, 100 + mov x13, 255 // R + mov x14, 145 // G + mov x15, 0 // B + bl setColour // R+G+B = Naranja + bl drawLine + + mov x13, 17 // R + mov x14, 253 // G + mov x15, 64 // B + bl setColour // Verde + mov x16, 59 + mov x12, 59 + bl drawPixel + mov x16, 100 + mov x12, 100 + bl drawPixel + /// + + // Dibujamos una línea xc0, yc0 -> xc1, yc1 + mov x21, 150 + mov x22, 30 + mov x23, 50 + mov x24, 200 + mov x13, 85 // R + mov x14, 255 // G + mov x15, 237 // B + bl setColour // R+G+B = cyan 55ffed + bl drawLine + + mov x13, 255 // R + mov x14, 251 // G + mov x15, 0 // B + bl setColour // Amarillo fffb00 + mov x16, 150 + mov x12, 30 + bl drawPixel + mov x16, 50 + mov x12, 200 + bl drawPixel + /// mov x21, #320 // xc x centro mov x22, #300 // yc y centro -break: bl doRaven // Dibujamos un cuervo //bl circleTest @@ -168,17 +213,17 @@ break: //bl doValentinaVispo //bl delay - bl cleanScreen // cleanScreen negro + //bl cleanScreen // cleanScreen negro //bl animationTest - bl circleAnimation1 + //bl circleAnimation1 mov x13, 250 // R mov x14, 81 // G mov x15, 171 // B bl setColour // R+G+B = Rosa mov x21, 100 - bl verticalLine + //bl verticalLine EndMain: bl delay diff --git a/draw.s b/draw.s index 5fcf85c..1c58de4 100644 --- a/draw.s +++ b/draw.s @@ -3,6 +3,111 @@ //.include "app.s" +.globl drawLine +// NOTE Line +drawLine: + // Args + // x21 xc0 coordenada x del primer punto + // x22 yc0 coordenada y del primer punto + // x23 xc1 coordenada x del segundo punto + // x24 yc1 coordenada y del segundo punto + // Used + // x4 dx + // x5 sx + // x6 dy + // x7 sy + // x19 err + + sub sp, sp, #48 // Reservamos 6 registros de memoria + stur x30, [sp, #40] // Guardamos el return pointer en memoria + stur x19, [sp, #32] + stur x4, [sp, #24] + stur x5, [sp, #16] + stur x6, [sp, #8] + stur x7, [sp, #0] + + // (x0, y0) to (x1, y1) + // (xc0, yc0) to (xc1, yc1) + + // y = f(x) = mx+b + // y = mx +b + // y = ((tri (y)) / (tri (x))) x + b + + // dx = abs(xc1 - xc0) + cmp x21, x23 // comparamos xc0 con el xc1 + b.gt lineGreaterThan1 // xc0 > xc1 + // if here -> xc1 > xc0 + sub x4, x23, x21 // dx = xc1 - xc0 lineDx + mov x5, #1 // xc0 < xc1 -> sx = xc0 < xc1 ? 1 : -1 + b endlineGreaterThan1 + +lineGreaterThan1: // xc0 > xc1 + sub x4, x21, x23 // dx = xc0 - xc1 + mov x5, #1 + sub x5, xzr, x5 // sx = xc0 < xc1 ? 1 : -1 + // endlineGreaterThan1... + +endlineGreaterThan1: + // dy = -abs(yc1 - yc0) + cmp x22, x24 // comparamos yc0 con el yc1 + b.gt lineGreaterThan2 // yc0 > yc1 + sub x6, x22, x24 // dy = yc0 - yc1 + mov x7, #1 // yc0 < yc1 -> sy = yc0 < yc1 ? 1 : -1 + b endlineGreaterThan2 + +lineGreaterThan2: // yc0 > yc1 + sub x6, x24, x22 // dy = yc1 - yc0 + mov x7, #1 + sub x7, xzr, x7 // sy = yc0 < yc1 ? 1 : -1 + // endlineGreaterThan2... + +endlineGreaterThan2: + add x19, x4, x6 // err = dx+dy (error value e_xy) + b loopLine // init loop + +loopLine: + mov x16, x21 // xdraw = xc0 + mov x12, x22 // ydraw = yc0 + bl drawPixel // plot(xc0, yc0) + + cmp x21, x23 // Comparamos xc0 con xc1 + b.ne checkLine // xc0 != xc1 // FIXME + b endDrawLine // break + +checkLine: + cmp x22, x24 // Comparamos yc0 con yc1 + b.ne lineNoBreak // yc0 != yc1 // FIXME + b endDrawLine // break + +lineNoBreak: + //lsl x8, x19, #1 // x8 = e2 = 2*err + add x8, x19, x19 // x8 = e2 = 2*err + + cmp x8, x6 + b.lt skipIf1 // e2 < dy + // If we are here -> e2 >= dy + add x19, x19, x6 // err += dy + add x21, x21, x5 // xc0 += sx + +skipIf1: + cmp x8, x4 + b.gt loopLine // e2 > dx + // If we are here -> e2 <= dx +break2: + add x19, x19, x4 // err += dx + add x22, x22, x7 // yc0 += sy + b loopLine + +endDrawLine: + ldur x30, [sp, #40] + ldur x19, [sp, #32] + ldur x4, [sp, #24] + ldur x5, [sp, #16] + ldur x6, [sp, #8] + ldur x7, [sp, #0] + add sp, sp, #48 // Liberamos espacio en memoria + ret + .globl doSquare // NOTE Square doSquare: From 746e9d3f4858aad4e38adefecbcc9241607df3cd Mon Sep 17 00:00:00 2001 From: Valentina Vispo Date: Tue, 1 Jun 2021 23:56:51 -0300 Subject: [PATCH 03/47] Add lineAnimation and logical algorithm RGB --- animations.s | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++ app.s | 1 + 2 files changed, 118 insertions(+) diff --git a/animations.s b/animations.s index 33da062..2a919b6 100644 --- a/animations.s +++ b/animations.s @@ -19,4 +19,121 @@ delayloop: delayEnd: ret +.globl lineAnimation +lineAnimation: + sub sp, sp, #8 // Guardamos 1 lugar del stack + stur x30, [sp, #0] // Registro 30 para el RET en el stack + + mov x4, 320 + mov x5, 140 + mov x6, 10 + mov x7, 260 + +lineAnimationLoop: + mov x13, 255 // R + mov x14, 0 // G + mov x15, 0 // B + bl setColour // R+G+B = Rojo + mov x8, #260 + cmp x8, x6 + b.eq endlineAnimation + mov x21, x4 + mov x22, x5 + mov x23, x6 + mov x24, x7 + bl drawLine + bl delay + bl cleanScreen + mov x13, 0 // R + mov x14, 255 // G + mov x15, 0 // B + bl setColour // R+G+B = Rojo + sub x21, x4, #1 + sub x22, x5, #1 + mov x23, #3 + bl doSquare + sub x21, x6, #1 + sub x22, x7, #1 + bl doSquare + add x6, x6, #1 + sub x4, x4, #1 + b lineAnimationLoop + +endlineAnimation: + ldur x30, [sp, #0] // Carga lo que guardó en el stack + add sp, sp, #8 // Libera el stack + ret + +.globl rgbAnimation +rgbAnimation: + // Args + // x13 r actual + // x14 g actual + // x15 b actual + // setColour -> x18 + + // x = 128, r = 255, g = 0, b = 0 + // ...Rojo (255, 0, 0) -> Naranja (255, 128, 0) -> Amarillo (255, 255, 0)... + // --r >= g && r == 255 && g < 255 -> g = g + 128-borrar?- + // r == 255 && b == 0 && g < 255 -> g = g + 128 + + // x = 128, r = 255, g = 255, b = 0 + // Amarillo (255, 255, 0) -> Verde claro (128, 255, 0) -> Verde (0, 255, 0)... + // --r == g && r == 255 -> r = r - 128-borrar?- + // b == 0 && g == 255 && r > 0 -> r = r - 128 + + // Verde (0, 255, 0) -> Verde lima? (0, 255, 128) -> Celeste (0, 255, 255)... + // r == 0 && g == 255 && b b = b + 128 + + // Celeste (0, 255, 255) -> Mar (0, 128, 255) -> Azul (0, 0, 255)... + // r == 0 && b == 255 && g > 0 -> g = g - 128 + + // Azul (0, 0, 255) -> Morado (128, 0, 255) -> Rosa (255, 0, 255)... + // -> r = r + 128 + + // Rosa (255, 0, 255) -> Pink2 (255, 0, 128) -> Rojo (255, 0, 0)... + // -> b = b - 128 + + // x = 85 + // 0 -> 85 -> 170 -> 255 + + //////////////////////////////////////// + // x13 r actual + // x14 g actual + // x15 b actual + // ------ inc = 85 ------ +case1: // r == 255 && b == 0 && g < 255 ---> g += inc (Rojo>>>Amarillo) + cbz x15, case3 // no es case1 ni case2 + +case2: // g == 255 && b == 0 && r > 0 ---> r -= inc (Amarillo->->->Verde) + //cbz, x, case + +case3: // g == 255 && r == 0 && b < 255 ---> b += inc (Verde>>>Cyan) + //cbz, x, case5 + +case4: // b == 255 && r == 0 && g > 0 ---> g -= inc (Cyan>>>Azul) + //cbz, x, case5 + +case5: // b == 255 && g == 0 && r < 255 ---> r += inc (Azul>>>Violeta) + // (0, 0, 255) -> (85, 0, 255) -> (170, 0, 255) -> (255, 0, 255) + +case6: // r == 255 && g == 0 && b > 0 ---> b -= inc (Violeta>>>Rojo) + + + //////////////////////////////////////// + // Sencuencia "ciclo por ciclo" + // case 1 + // (255, 0, 0) -> (255, 85, 0) -> (255, 170, 0) -> (255, 255, 0) + // case 2 + // (255, 255, 0) -> (170, 255, 0) -> (85, 255, 0) -> (0, 255, 0) + // case 3 + // (0, 255, 0) -> (0, 255, 85) -> (0, 255, 170) -> (0, 255, 255) + // case 4 + // (0, 255, 255) -> (0, 170, 255) -> (0, 85, 255) -> (0, 0, 255) + // case 5 + // (255, 0, 255) -> (255, 0, 170) -> (255, 0, 85) -> (255, 0, 0) + +endRgbAnimation: + ret + //.endif diff --git a/app.s b/app.s index 949a254..a1380a0 100644 --- a/app.s +++ b/app.s @@ -224,6 +224,7 @@ main: bl setColour // R+G+B = Rosa mov x21, 100 //bl verticalLine + bl lineAnimation EndMain: bl delay From 8711db6d187abc308ea623415370117e90b5fd75 Mon Sep 17 00:00:00 2001 From: Valentina Vispo Date: Wed, 2 Jun 2021 00:47:27 -0300 Subject: [PATCH 04/47] Add rgbAnimation --- Makefile | 2 +- animations.s | 86 ++++++++++++++++++++++++++++++++++++++++------------ app.s | 11 ++++++- 3 files changed, 77 insertions(+), 22 deletions(-) diff --git a/Makefile b/Makefile index b70b738..0f0785e 100644 --- a/Makefile +++ b/Makefile @@ -27,7 +27,7 @@ runQEMU : kernel8.img qemu-system-aarch64 -s -S -M raspi3 -kernel kernel8.img runGDB: - gdb-multiarch -ex "set architecture aarch64" -ex "target remote localhost:1234" --ex "dashboard registers -style list 'x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 x11 x12 x13 x14 x15 x16 x17 x18 x19 x20 x21 x22 x23 x24 x25 x26 x27 x28 x29 x30 sp pc cpsr'" \-ex "add-symbol-file app.o 0x00000000000c601c" \-ex "add-symbol-file draw.o 0x00000000000900c8" + gdb-multiarch -ex "set architecture aarch64" -ex "target remote localhost:1234" --ex "dashboard registers -style list 'x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 x11 x12 x13 x14 x15 x16 x17 x18 x19 x20 x21 x22 x23 x24 x25 x26 x27 x28 x29 x30 sp pc cpsr'" \-ex "add-symbol-file app.o 0x00000000000c6024" \-ex "add-symbol-file draw.o 0x00000000000900c8" \-ex "add-symbol-file animations.o 0x0000000000146398" #0x00000000000900c8" #\-ex "b break" \-ex "continue" diff --git a/animations.s b/animations.s index 2a919b6..987290c 100644 --- a/animations.s +++ b/animations.s @@ -20,6 +20,7 @@ delayEnd: ret .globl lineAnimation +// NOTE lineAnimation lineAnimation: sub sp, sp, #8 // Guardamos 1 lugar del stack stur x30, [sp, #0] // Registro 30 para el RET en el stack @@ -65,6 +66,7 @@ endlineAnimation: ret .globl rgbAnimation +// NOTE rgbAnimation rgbAnimation: // Args // x13 r actual @@ -102,38 +104,82 @@ rgbAnimation: // x14 g actual // x15 b actual // ------ inc = 85 ------ + mov x9, #85 case1: // r == 255 && b == 0 && g < 255 ---> g += inc (Rojo>>>Amarillo) - cbz x15, case3 // no es case1 ni case2 + cbnz x15, case3 // b != 0 -> next case + cmp x13, #255 // NOTA: Legal + b.ne case2 // r != 255 -> next case + cmp x14, #255 + b.eq case2 // g == 255 -> next case + add x14, x14, x9 // g += inc + b endRgbAnimation + +case2: // g == 255 && b == 0 && r > 0 ---> r -= inc (Amarillo>>>>Verde) + cmp x14, #255 + b.ne case4 // g != 255 -> next case + cmp x13, xzr + b.le case3 // r <= 0 + cbnz x15, case3 // b != 0 -> next case + cbz x13, case3 // r == 0 -> next case + sub x13, x13, x9 // r -= inc + b endRgbAnimation + +case3: // g == 255 && r == 0 && b < 255 ---> b += inc (Verde>>>>Celeste) + cbnz x13, case5 // r != 0 -> next case + cmp x14, #255 + b.ne case4 // g != 255 -> next case + cmp x15, #255 + b.eq case4 // b == 255 -> next case + add x15, x15, x9 // b += inc + b endRgbAnimation + +case4: // b == 255 && r == 0 && g > 0 ---> g -= inc (Cyan>>>>Azul) + cmp x15, #255 + b.ne case6 // b != 255 -> no es ni case4 ni case5 + cbnz x13, case5 // r != 0 -> next case + cbz x14, case5 // g == 0 -> next case + sub x14, x14, x9 // g -= inc + b endRgbAnimation + +case5: // b == 255 && g == 0 && r < 255 ---> r += inc (Azul>>>>Violeta) + cmp x13, #255 + b.eq case6 // r == 255 --> last case + add x13, x13, x9 // r += inc + b endRgbAnimation + +case6: // r == 255 && g == 0 && b > 0 ---> b -= inc (Violeta>>>>Rojo) + sub x15, x15, x9 // b -= inc + b endRgbAnimation -case2: // g == 255 && b == 0 && r > 0 ---> r -= inc (Amarillo->->->Verde) - //cbz, x, case - -case3: // g == 255 && r == 0 && b < 255 ---> b += inc (Verde>>>Cyan) - //cbz, x, case5 - -case4: // b == 255 && r == 0 && g > 0 ---> g -= inc (Cyan>>>Azul) - //cbz, x, case5 - -case5: // b == 255 && g == 0 && r < 255 ---> r += inc (Azul>>>Violeta) - // (0, 0, 255) -> (85, 0, 255) -> (170, 0, 255) -> (255, 0, 255) - -case6: // r == 255 && g == 0 && b > 0 ---> b -= inc (Violeta>>>Rojo) - +endRgbAnimation: + ret //////////////////////////////////////// // Sencuencia "ciclo por ciclo" // case 1 - // (255, 0, 0) -> (255, 85, 0) -> (255, 170, 0) -> (255, 255, 0) + // Rojo (255, 0, 0) -> (255, 85, 0) -> (255, 170, 0) -> (255, 255, 0) // case 2 // (255, 255, 0) -> (170, 255, 0) -> (85, 255, 0) -> (0, 255, 0) // case 3 - // (0, 255, 0) -> (0, 255, 85) -> (0, 255, 170) -> (0, 255, 255) + // (0, 255, 0) -> (0, 255, 85) -> (0, 255, 170) -> Celeste (0, 255, 255) // case 4 // (0, 255, 255) -> (0, 170, 255) -> (0, 85, 255) -> (0, 0, 255) // case 5 + // (0, 0, 255) -> (85, 0, 255) -> (170, 0, 255) -> (255, 0, 255) + // case 6 // (255, 0, 255) -> (255, 0, 170) -> (255, 0, 85) -> (255, 0, 0) -endRgbAnimation: - ret - //.endif + +.globl rgbcycletest +rgbcycletest: + mov x13, 255 // R + mov x14, 0 // G + mov x15, 0 // B +rgbaniloop: + bl setColour + bl paintScreen + bl delay + bl rgbAnimation + b rgbaniloop + diff --git a/app.s b/app.s index a1380a0..a89d05f 100644 --- a/app.s +++ b/app.s @@ -224,7 +224,8 @@ main: bl setColour // R+G+B = Rosa mov x21, 100 //bl verticalLine - bl lineAnimation + //bl lineAnimation + bl rgbcycletest EndMain: bl delay @@ -300,10 +301,18 @@ setColour: // x14 g // x15 b // 24 bits + sub sp, sp, #16 + stur x13, [sp, #8] + stur x14, [sp, #0] + lsl x13, x13, 16 // Movemos 16 bits lsl x14, x14, 8 // Movemos 8 bits add x18, x13, x14 // R+G add x18, x18, x15 // RG+B + + ldur x13, [sp, #8] + ldur x14, [sp, #0] + add sp, sp, #16 ret // NOTE Line From f4206404c8b184dd7bab87b1743815e3437192be Mon Sep 17 00:00:00 2001 From: Diego Gimenez <30444439+diegogimenez04@users.noreply.github.com> Date: Wed, 2 Jun 2021 10:41:50 -0300 Subject: [PATCH 05/47] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2b31dc5..2096246 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ # Vc framebuffer Framebuffer to the graphics device access method of a computer system, in which each pixel on the screen is represented as locations of a specific portion of the random access memory map (main memory system) -# Instalation +# Debian Based Instalation `sudo apt update` `sudo apt install gcc-aarch64-linux-gnu` From d5c1b402f80f217e987e2d75cc23a8243f486027 Mon Sep 17 00:00:00 2001 From: diegogimenez04 Date: Wed, 2 Jun 2021 11:18:53 -0300 Subject: [PATCH 06/47] temp Triangulo --- app.s | 4 ++-- draw.s | 75 ++++++++++++++++++++++++++++++---------------------------- 2 files changed, 41 insertions(+), 38 deletions(-) diff --git a/app.s b/app.s index a89d05f..3869f0f 100644 --- a/app.s +++ b/app.s @@ -109,14 +109,14 @@ main: stur x18, [x0] // Pintamos un cuadrado en el medio de la pantalla - mov x21, 100 // x2 + mov x21, 200 // x2 mov x22, 200 // y2 mov x23, 20 // w largo de pixeles mov x13, 255 // R mov x14, 0 // G mov x15, 8 // B bl setColour // R+G+B = Rojo - bl doRectangle + bl doTriangle // Dibujamos un círculo // Medio es 320 x 240 diff --git a/draw.s b/draw.s index 1c58de4..2298fcc 100644 --- a/draw.s +++ b/draw.s @@ -280,54 +280,57 @@ circleEnd: ret .globl doTriangle -// NOTE Triangle -doTriangle: +// NOTE Triangulo +doTriangle: //FIXME Ver por que no funciona // @Diego // Args - // x21 x2 lugar dónde empiezo a dibujar la figura - // x22 y2 lugar dónde empiezo a dibujar la figura + // x21 x lugar dónde empiezo a dibujar la figura + // x22 y lugar dónde empiezo a dibujar la figura // x23 w cantidad de píxeles // x18 colour // A) Asignar el primer pixel de lado izquierdo inferior - mov x16, x21 // Instancio x16 para setPixel + mov x16, x21 // Instancio x16 para dibujar mov x12, x22 // Instancio x12 para setPixel - mov x9, x16 - mov x10, x12 - + bl setPixel // Calculo la posicion inicial + mov x10, x0 // Guardo la posicion inicial + mov x19, x23 // La cantidad de pixeles sera la cantidad de veces que entro al ciclo + mov x9, #0 // Instancio un contador que me va a servir para contar cantidad de pixeles + b rectAr + +preRectAr: + cmp x19, #0 // Si itere w cantidad de veces --> + b.eq endTriang // termino rectAr: - bl setPixel // Calculo el pixel - stur x18, [x0] // Lo pinto - // Bucle... Movernos al siguiente píxel (arriba o abajo) + bl setPixel // Calculo el pixel + stur x18, [x0] // Lo pinto add x16, x16, #1 // Me muevo al siguiente - add x12, x12, #1 // Me muevo al siguiente - sub x9, x21, x23 // Calculo el rango entre el principio y el final - //sdiv x9, x9, #2 // TODO Corregir, idea: Calculo la mitad - sub x9, x9, #1 // - cbnz x9, rectAr - // Hasta w... + sub x12, x12, #1 // Me muevo arriba + cmp x9, x19 // Comparo mi contador con mi cantidad de pixeles + b.eq rectBaj // Si llegue a la cantidad bajo + add x9, x9, #1 // Si no le sumo 1 + b rectAr // Empiezo de nuevo rectBaj: - bl setPixel - stur x18, [x0] - sub x12, x12, #1 - add x16, x16, #1 - cmp x16, x23 - b.eq rectIzq - // Luego bucle: bajamos hasta w - b rectBaj - - // Nos movemos hacia la izquierda hasta w-1 - + bl setPixel // Calculo el pixel + stur x18, [x0] // Lo pinto + add x16, x16, #1 // Me muevo al siguiente + add x12, x12, #1 // Bajo 1 unidad + cmp x9, #0 // Comparo el contador a w con 0 + b.eq preRectIzq // Si llegue a la "base" voy hacia la izquierda + sub x9, x9, #1 // Si no, le resto 1 al contador + b rectBaj // Bajo de nuevo + +preRectIzq: + add x10, x10, #1 // Llego hasta la posicion incial + 1 + sub x19, x19, #1 // Como tengo que iterar w veces, resto una vez a w rectIzq: - bl setPixel - stur x18, [x0] - sub x21, x21, #1 - sub x9, x23, #1 - adds xzr, x9, #0 - b.eq endTriang - cmp x21, x9 - b.eq rectAr + bl setPixel // Calculo el pixel + stur x18, [x0] // Lo pinto + sub x16, x16, #1 // Retrocedo hasta el punto incial + cmp x16, x10 // Comparo si llegue a uno menos que el punto inicial + b.eq preRectAr // Subo de nuevo, viendo si termine + b rectIzq // Si no me muevo de nuevo hacia la izquierda // Repetimos paso A)... hasta w=0 endTriang: //TODO revisar From f194ded0d55f7c2a1baae9c2a784db5c2275df76 Mon Sep 17 00:00:00 2001 From: diegogimenez04 Date: Wed, 2 Jun 2021 17:37:23 -0300 Subject: [PATCH 07/47] Triangulo final --- app.s | 22 +++++++++++++--------- draw.s | 31 ++++++++++++++++++------------- 2 files changed, 31 insertions(+), 22 deletions(-) diff --git a/app.s b/app.s index 3869f0f..f2d969b 100644 --- a/app.s +++ b/app.s @@ -106,17 +106,19 @@ main: mov x14, 0 // G mov x15, 8 // B bl setColour // R+G+B = Rojo - stur x18, [x0] + stur x18, [x0] // Lo pinto + bl cleanScreen // Pintamos un cuadrado en el medio de la pantalla - mov x21, 200 // x2 + mov x21, 400 // x2 mov x22, 200 // y2 - mov x23, 20 // w largo de pixeles + mov x23, 120 // w largo de pixeles mov x13, 255 // R - mov x14, 0 // G + mov x14, 244 // G mov x15, 8 // B bl setColour // R+G+B = Rojo - bl doTriangle + bl doTriangle // REVIEW Checkear + //ret // Dibujamos un círculo // Medio es 320 x 240 @@ -377,15 +379,17 @@ endHorizontalLine: .globl cleanScreen // NOTE cleanScreen cleanScreen: // Pinta toda la pantalla de negro - sub sp, sp, #8 - stur x30, [sp, #0] // Guardamos el return pointer en memoria + sub sp, sp, #16 + stur lr, [sp] // Guardo el link register para no pisarlo + stur x30, [sp, #8] // Guardamos el return pointer en memoria mov x13, xzr // R mov x14, xzr // G mov x15, xzr // B bl setColour // Negro bl paintScreen - ldur x30, [sp, #0] // Guardamos el return pointer en memoria ret - add sp, sp, #8 + ldur x30, [sp, #8] // Guardamos el return pointer en memoria ret + ldur lr, [sp] // Devuelvo el link register + add sp, sp, #16 ret .globl paintScreen diff --git a/draw.s b/draw.s index 2298fcc..7815343 100644 --- a/draw.s +++ b/draw.s @@ -281,7 +281,7 @@ circleEnd: .globl doTriangle // NOTE Triangulo -doTriangle: //FIXME Ver por que no funciona +doTriangle: // @Diego // Args // x21 x lugar dónde empiezo a dibujar la figura @@ -290,18 +290,17 @@ doTriangle: //FIXME Ver por que no funciona // x18 colour // A) Asignar el primer pixel de lado izquierdo inferior + sub sp, sp, #8 + stur lr, [sp] // Guardo el link register para no pisarlo en la subrutina setPixel mov x16, x21 // Instancio x16 para dibujar mov x12, x22 // Instancio x12 para setPixel bl setPixel // Calculo la posicion inicial - mov x10, x0 // Guardo la posicion inicial + ldur x10, [x0] // Guardo la posicion inicial mov x19, x23 // La cantidad de pixeles sera la cantidad de veces que entro al ciclo mov x9, #0 // Instancio un contador que me va a servir para contar cantidad de pixeles - b rectAr + b preRectIzq -preRectAr: - cmp x19, #0 // Si itere w cantidad de veces --> - b.eq endTriang // termino -rectAr: +rectAr: // Dibuja la diagonal hacia arriba bl setPixel // Calculo el pixel stur x18, [x0] // Lo pinto add x16, x16, #1 // Me muevo al siguiente @@ -311,7 +310,7 @@ rectAr: add x9, x9, #1 // Si no le sumo 1 b rectAr // Empiezo de nuevo -rectBaj: +rectBaj: // Dibuja la diagonal hacia abajo bl setPixel // Calculo el pixel stur x18, [x0] // Lo pinto add x16, x16, #1 // Me muevo al siguiente @@ -321,19 +320,25 @@ rectBaj: sub x9, x9, #1 // Si no, le resto 1 al contador b rectBaj // Bajo de nuevo -preRectIzq: +preRectIzq: // Se encarga de calcular el valor al cual debe llegar cuando se dibuje la "base" y calcula nuevamente la altura add x10, x10, #1 // Llego hasta la posicion incial + 1 sub x19, x19, #1 // Como tengo que iterar w veces, resto una vez a w -rectIzq: +rectIzq: // Dibuja hacia la izquierda bl setPixel // Calculo el pixel stur x18, [x0] // Lo pinto sub x16, x16, #1 // Retrocedo hasta el punto incial - cmp x16, x10 // Comparo si llegue a uno menos que el punto inicial + cmp x16, x23 // Comparo si llegue a uno menos que el punto inicial b.eq preRectAr // Subo de nuevo, viendo si termine b rectIzq // Si no me muevo de nuevo hacia la izquierda - // Repetimos paso A)... hasta w=0 -endTriang: //TODO revisar +preRectAr: // Se fija si itero la cantidad de veces necesarias + cmp x19, #0 // Si itere w cantidad de veces --> + b.eq endTriang // Termino + b rectAr // Si no, sigo + +endTriang: + ldur lr, [sp] + add sp, sp, #8 ret //.endif From a94807530443cfb293e183ac1622fd83c4e5fdef Mon Sep 17 00:00:00 2001 From: diegogimenez04 Date: Thu, 3 Jun 2021 21:18:04 -0300 Subject: [PATCH 08/47] Fixed Triangle --- app.s | 76 +++++++++++++++++++++++++++++++++++++++++++----- draw.s | 92 +++++++++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 137 insertions(+), 31 deletions(-) diff --git a/app.s b/app.s index f2d969b..e201270 100644 --- a/app.s +++ b/app.s @@ -110,15 +110,15 @@ main: bl cleanScreen // Pintamos un cuadrado en el medio de la pantalla - mov x21, 400 // x2 + mov x21, 300 // x2 mov x22, 200 // y2 mov x23, 120 // w largo de pixeles mov x13, 255 // R - mov x14, 244 // G + mov x14, 244 // G mov x15, 8 // B bl setColour // R+G+B = Rojo - bl doTriangle // REVIEW Checkear - //ret + bl doTriangleUp // REVIEW Checkear + ret // Dibujamos un círculo // Medio es 320 x 240 @@ -236,13 +236,74 @@ EndMain: return: ret -// TODO draw Border +// TODO revisar drawBorder: // Args // x18 colour - mov x16, SCREEN_HEIGH - mov x12, SCREEN_WIDTH + sub sp, sp, #8 // Guardo el link register para no sobreescribirlo + stur lr, [sp] + + mov x16, 0 // Guardo la posicion en x a la que quiero llegar + mov x12, SCREEN_HEIGH // Guardo la posicion y donde quiero llegar + bl setPixel + ldur x9, [x0] + + mov x16, SCREEN_WIDTH // REVIEW esto esta bien? No deberia ser SCREEN_WIDTH para los x? + mov x12, SCREEN_HEIGH // Y SCREEN_HEIGH para los y? + bl setPixel + stur x18, [x0] + +drawLeft: + bl setPixel + stur x18, [x0] + sub x16, x16, #1 + cmp x9, x0 + b.eq preDrawUp + b drawLeft + +preDrawUp: + mov x9, #0 +drawUp: + bl setPixel + stur x18, [x0] + sub x12, x12, #1 + cmp x9, x0 + b.eq preDrawRight + b drawUp + +preDrawRight: + mov x12, #0 + mov x16, SCREEN_WIDTH + bl setPixel + ldur x9, [x0] +drawRight: + bl setPixel + stur x18, [x0] + sub x16, x16, #1 + cmp x9, x0 + b.eq preDrawDown + b drawRight + +preDrawDown: + mov x12, SCREEN_HEIGH + mov x16, SCREEN_WIDTH + bl setPixel + ldur x9, [x0] +drawDown: bl setPixel + stur x18, [x0] + add x12, x12, #1 + cmp x9, x0 + b.eq endBorder + b drawDown + +endBorder: + ldur lr, [sp] + add sp, sp, #8 + ret + +/* +endDraw: // TODO borderLoop: @@ -251,6 +312,7 @@ borderLoop: borderEnd: // TODO +*/ // NOTE Circle Test circleTest: diff --git a/draw.s b/draw.s index 7815343..8295e47 100644 --- a/draw.s +++ b/draw.s @@ -279,9 +279,9 @@ circleEnd: add sp, sp, #8 ret -.globl doTriangle +.globl doTriangleUp // NOTE Triangulo -doTriangle: +doTriangleUp: // @Diego // Args // x21 x lugar dónde empiezo a dibujar la figura @@ -289,54 +289,98 @@ doTriangle: // x23 w cantidad de píxeles // x18 colour - // A) Asignar el primer pixel de lado izquierdo inferior sub sp, sp, #8 stur lr, [sp] // Guardo el link register para no pisarlo en la subrutina setPixel mov x16, x21 // Instancio x16 para dibujar mov x12, x22 // Instancio x12 para setPixel bl setPixel // Calculo la posicion inicial - ldur x10, [x0] // Guardo la posicion inicial mov x19, x23 // La cantidad de pixeles sera la cantidad de veces que entro al ciclo mov x9, #0 // Instancio un contador que me va a servir para contar cantidad de pixeles - b preRectIzq + b rectAr rectAr: // Dibuja la diagonal hacia arriba - bl setPixel // Calculo el pixel - stur x18, [x0] // Lo pinto add x16, x16, #1 // Me muevo al siguiente sub x12, x12, #1 // Me muevo arriba + bl setPixel // Calculo el pixel + stur x18, [x0] // Lo pinto cmp x9, x19 // Comparo mi contador con mi cantidad de pixeles b.eq rectBaj // Si llegue a la cantidad bajo add x9, x9, #1 // Si no le sumo 1 b rectAr // Empiezo de nuevo rectBaj: // Dibuja la diagonal hacia abajo - bl setPixel // Calculo el pixel - stur x18, [x0] // Lo pinto add x16, x16, #1 // Me muevo al siguiente add x12, x12, #1 // Bajo 1 unidad + bl setPixel // Calculo el pixel + stur x18, [x0] // Lo pinto cmp x9, #0 // Comparo el contador a w con 0 - b.eq preRectIzq // Si llegue a la "base" voy hacia la izquierda + b.eq preRectAr // Si llegue a la "base" arranco de nuevo desde 1 posicion menos sub x9, x9, #1 // Si no, le resto 1 al contador b rectBaj // Bajo de nuevo -preRectIzq: // Se encarga de calcular el valor al cual debe llegar cuando se dibuje la "base" y calcula nuevamente la altura - add x10, x10, #1 // Llego hasta la posicion incial + 1 - sub x19, x19, #1 // Como tengo que iterar w veces, resto una vez a w -rectIzq: // Dibuja hacia la izquierda +preRectAr: // Se fija si itero la cantidad de veces necesarias + add x21, x21, #1 // Itero una vez menos + mov x16, x21 // Empiezo de nuevo + mov x12, x22 // Instancio x12 para setPixel + cmp x19, xzr // Si itere w cantidad de veces --> + b.eq endTriang // Termino + sub x19, x19, #1 // Si no, resto 1 iteracion + b rectAr // sigo + +endTriang: + ldur lr, [sp] + add sp, sp, #8 + ret + +.globl doTriangleDown +// NOTE Triangulo +doTriangleDown: + // @Diego + // Args + // x21 x lugar dónde empiezo a dibujar la figura + // x22 y lugar dónde empiezo a dibujar la figura + // x23 w cantidad de píxeles + // x18 colour + + sub sp, sp, #8 + stur lr, [sp] // Guardo el link register para no pisarlo en la subrutina setPixel + mov x16, x21 // Instancio x16 para dibujar + mov x12, x22 // Instancio x12 para setPixel + bl setPixel // Calculo la posicion inicial + mov x19, x23 // La cantidad de pixeles sera la cantidad de veces que entro al ciclo + mov x9, #0 // Instancio un contador que me va a servir para contar cantidad de pixeles + b rectArDown + +rectArDown: // Dibuja la diagonal hacia arriba + add x16, x16, #1 // Me muevo al siguiente + add x12, x12, #1 // Me muevo arriba bl setPixel // Calculo el pixel stur x18, [x0] // Lo pinto - sub x16, x16, #1 // Retrocedo hasta el punto incial - cmp x16, x23 // Comparo si llegue a uno menos que el punto inicial - b.eq preRectAr // Subo de nuevo, viendo si termine - b rectIzq // Si no me muevo de nuevo hacia la izquierda - -preRectAr: // Se fija si itero la cantidad de veces necesarias - cmp x19, #0 // Si itere w cantidad de veces --> - b.eq endTriang // Termino - b rectAr // Si no, sigo + cmp x9, x19 // Comparo mi contador con mi cantidad de pixeles + b.eq rectBajDown // Si llegue a la cantidad bajo + add x9, x9, #1 // Si no le sumo 1 + b rectArDown // Empiezo de nuevo -endTriang: +rectBajDown: // Dibuja la diagonal hacia abajo + add x16, x16, #1 // Me muevo al siguiente + sub x12, x12, #1 // Bajo 1 unidad + bl setPixel // Calculo el pixel + stur x18, [x0] // Lo pinto + cmp x9, #0 // Comparo el contador a w con 0 + b.eq preRectArDown // Si llegue a la "base" arranco de nuevo desde 1 posicion menos + sub x9, x9, #1 // Si no, le resto 1 al contador + b rectBajDown // Bajo de nuevo + +preRectArDown: // Se fija si itero la cantidad de veces necesarias + add x21, x21, #1 // Itero una vez menos + mov x16, x21 // Empiezo de nuevo + mov x12, x22 // Instancio x12 para setPixel + cmp x19, xzr // Si itere w cantidad de veces --> + b.eq endTriangDown // Termino + sub x19, x19, #1 // Si no, resto 1 iteracion + b rectArDown // sigo + +endTriangDown: ldur lr, [sp] add sp, sp, #8 ret From 7c84d3cfbaed06cce5c388b882f661b8098dfc0e Mon Sep 17 00:00:00 2001 From: diegogimenez04 Date: Thu, 3 Jun 2021 23:56:40 -0300 Subject: [PATCH 09/47] Piramide --- app.s | 6 +++--- draw.s | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 3 deletions(-) diff --git a/app.s b/app.s index e201270..a76253c 100644 --- a/app.s +++ b/app.s @@ -111,13 +111,13 @@ main: bl cleanScreen // Pintamos un cuadrado en el medio de la pantalla mov x21, 300 // x2 - mov x22, 200 // y2 - mov x23, 120 // w largo de pixeles + mov x22, 300 // y2 + mov x23, 50 // w largo de pixeles mov x13, 255 // R mov x14, 244 // G mov x15, 8 // B bl setColour // R+G+B = Rojo - bl doTriangleUp // REVIEW Checkear + bl doPiramide // REVIEW Checkear ret // Dibujamos un círculo diff --git a/draw.s b/draw.s index 8295e47..5ed97ef 100644 --- a/draw.s +++ b/draw.s @@ -385,4 +385,57 @@ endTriangDown: add sp, sp, #8 ret +.globl doPiramide +// NOTE Triangulo +doPiramide: + // @Diego + // Args + // x21 x lugar dónde empiezo a dibujar la figura + // x22 y lugar dónde empiezo a dibujar la figura + // x23 w cantidad de píxeles + // x18 colour + + sub sp, sp, #8 + stur lr, [sp] // Guardo el link register para no pisarlo en la subrutina setPixel + mov x16, x21 // Instancio x16 para dibujar + mov x12, x22 // Instancio x12 para setPixel + bl setPixel // Calculo la posicion inicial + mov x19, x23 // La cantidad de pixeles sera la cantidad de veces que entro al ciclo + mov x9, #0 // Instancio un contador que me va a servir para contar cantidad de pixeles + b pirAr + +pirAr: // Dibuja la diagonal hacia arriba + sub x16, x16, #1 // Me muevo al siguiente + sub x12, x12, #1 // Me muevo arriba + bl setPixel // Calculo el pixel + stur x18, [x0] // Lo pinto + cmp x9, x19 // Comparo mi contador con mi cantidad de pixeles + b.eq pirBaj // Si llegue a la cantidad bajo + add x9, x9, #1 // Si no le sumo 1 + b pirAr // Empiezo de nuevo + +pirBaj: // Dibuja la diagonal hacia abajo + sub x16, x16, #1 // Me muevo al siguiente + add x12, x12, #1 // Bajo 1 unidad + bl setPixel // Calculo el pixel + stur x18, [x0] // Lo pinto + cmp x9, #0 // Comparo el contador a w con 0 + b.eq prepirAr // Si llegue a la "base" arranco de nuevo desde 1 posicion menos + sub x9, x9, #1 // Si no, le resto 1 al contador + b pirBaj // Bajo de nuevo + +prepirAr: // Se fija si itero la cantidad de veces necesarias + add x21, x21, #1 // Itero una vez menos + mov x16, x21 // Empiezo de nuevo + mov x12, x22 // Instancio x12 para setPixel + cmp x19, xzr // Si itere w cantidad de veces --> + b.eq endPir // Termino + sub x19, x19, #1 // Si no, resto 1 iteracion + b pirAr // sigo + +endPir: + ldur lr, [sp] + add sp, sp, #8 + ret + //.endif From 7cd83c70d5c1b417e708215e937fccc75c78a278 Mon Sep 17 00:00:00 2001 From: Valentina Vispo Date: Fri, 4 Jun 2021 00:14:14 -0300 Subject: [PATCH 10/47] Commit for push to develop --- animations.s | 36 +++--------------------------- app.s | 4 ++-- assets/colours/c1-1_255_0_0.png | Bin 0 -> 3894 bytes assets/colours/c1-2_255_255_0.png | Bin 0 -> 3804 bytes assets/colours/c1-2_255_85_0.png | Bin 0 -> 4125 bytes assets/colours/c1-3_255_170_0.png | Bin 0 -> 4253 bytes assets/video/rgbAnimation.mkv | Bin 0 -> 8614088 bytes png/gnu-arm-directives.pdf | Bin 0 -> 111341 bytes todo.md | 2 ++ 9 files changed, 7 insertions(+), 35 deletions(-) create mode 100644 assets/colours/c1-1_255_0_0.png create mode 100644 assets/colours/c1-2_255_255_0.png create mode 100644 assets/colours/c1-2_255_85_0.png create mode 100644 assets/colours/c1-3_255_170_0.png create mode 100644 assets/video/rgbAnimation.mkv create mode 100644 png/gnu-arm-directives.pdf diff --git a/animations.s b/animations.s index 987290c..8b7f026 100644 --- a/animations.s +++ b/animations.s @@ -8,7 +8,8 @@ delay: add x8, xzr, xzr // counter = 0 add x8, x8, #0xFFF // counter = 0xF...F (un numero enorme) - lsl x8, x8, #11 // 3th = * 2^~10 (slow = 1s) // * 2^~9 (medium = ~0,3s) + lsl x8, x8, #9 // 3th = * 2^~10 (slow = 1s) // * 2^~9 (medium = ~0,3s) + delayloop: cbz x8, delayEnd ldur x9, [sp, #0] @@ -72,39 +73,8 @@ rgbAnimation: // x13 r actual // x14 g actual // x15 b actual - // setColour -> x18 - - // x = 128, r = 255, g = 0, b = 0 - // ...Rojo (255, 0, 0) -> Naranja (255, 128, 0) -> Amarillo (255, 255, 0)... - // --r >= g && r == 255 && g < 255 -> g = g + 128-borrar?- - // r == 255 && b == 0 && g < 255 -> g = g + 128 - - // x = 128, r = 255, g = 255, b = 0 - // Amarillo (255, 255, 0) -> Verde claro (128, 255, 0) -> Verde (0, 255, 0)... - // --r == g && r == 255 -> r = r - 128-borrar?- - // b == 0 && g == 255 && r > 0 -> r = r - 128 - - // Verde (0, 255, 0) -> Verde lima? (0, 255, 128) -> Celeste (0, 255, 255)... - // r == 0 && g == 255 && b b = b + 128 - - // Celeste (0, 255, 255) -> Mar (0, 128, 255) -> Azul (0, 0, 255)... - // r == 0 && b == 255 && g > 0 -> g = g - 128 - - // Azul (0, 0, 255) -> Morado (128, 0, 255) -> Rosa (255, 0, 255)... - // -> r = r + 128 + mov x9, #85 // inc = 85 - // Rosa (255, 0, 255) -> Pink2 (255, 0, 128) -> Rojo (255, 0, 0)... - // -> b = b - 128 - - // x = 85 - // 0 -> 85 -> 170 -> 255 - - //////////////////////////////////////// - // x13 r actual - // x14 g actual - // x15 b actual - // ------ inc = 85 ------ - mov x9, #85 case1: // r == 255 && b == 0 && g < 255 ---> g += inc (Rojo>>>Amarillo) cbnz x15, case3 // b != 0 -> next case cmp x13, #255 // NOTA: Legal diff --git a/app.s b/app.s index a89d05f..813926a 100644 --- a/app.s +++ b/app.s @@ -151,7 +151,7 @@ main: mov x21, #150 // xc x centro mov x22, #150 // yc y centro - //bl doOwl // Dibujamos un búho + bl doOwl // Dibujamos un búho // Dibujamos una línea "vertical" mov x21, 59 @@ -225,7 +225,7 @@ main: mov x21, 100 //bl verticalLine //bl lineAnimation - bl rgbcycletest + //bl rgbcycletest EndMain: bl delay diff --git a/assets/colours/c1-1_255_0_0.png b/assets/colours/c1-1_255_0_0.png new file mode 100644 index 0000000000000000000000000000000000000000..e3ea077e04dd25c89852479cc2f4418868d3cb2e GIT binary patch literal 3894 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 literal 0 HcmV?d00001 diff --git a/assets/colours/c1-3_255_170_0.png b/assets/colours/c1-3_255_170_0.png new file mode 100644 index 0000000000000000000000000000000000000000..ffce1a3a2a5758680f092c75f226f48122d532f1 GIT binary patch literal 4253 zcmeI0S5OlSvxXxeAX0@-ssU^?krJhbB1J_?5K%xNp(Y}|h7v*t0|KHVp`%hnCDR5|>-R7p#cFmt&uc-XwCi72_(nY0qfa^Q3l!~dv>-Py zri5Nig9Bs{m<7`fBXH#r=`8w>4851#36wbytyMLPfU+nODFcG~6BC4Q!$gRsHVm*Bl zcO>>Ug0mfZ|NecA=p9U%T->R##Dr}E2`@+omeqy5I-Bbu(zPOJ3D*DtJV5MIt zl2A%9ejvGlsv`gPrjd_9{IKpsHl-N;&0Nsu%+>h~?&T1q<>@`=&(`@MJC*d@{U15y zHboja#LHO7t&^dVhkWrV%f&Bw7s)*%p%)gUlw@JE;+|-n1(BW9-=O zEq0%Wx)aWKEZyIdaRG;<<8T_^NzIFOtB3P_`8+U`s?|BTxT_mA%y`%kOMUm)nbXOblV2%v=7d24St$;pd8JS6Suy6P}%T?MlQ+^+~Je> zv8lP!Pt>m0yt%SKtY6b=Ioc&^H;T&Tmhp&y&RxP6$t-1NJ=!ZNkd1~cM_j*N5zBvS zg8%0vhmZ@(BeA_ls59Q2k30EH(>oX~G$7uvzs&m5OoL}@iZDN}m~!G5pzc{}A(zwW z7qs7q8c+JRYz(d;pAD3a5$aXHWl6FBv=o5wXX(S( z-_An9gtyu5ipEkJy{=Di99U&LMLz!>TcKs-4^GHY?0m(Am3=nwG?jRwRyQ2`YN5f_ z3r1+LbEcl14tyZMV(RLL;~(ofB#!nBM{lMQB9rjW=b-XFi+=qm?QBi=oN~*E!{prV z%-r_jPnAC;R%d=-Q_yjdyC&n5iR>!5H>b5^16!*rx-PC);S0_8#;Tq zE-D-z-iY#QZsdmObquBFH2^rqG1u7=-I%`RfNPZ3z8n-clNDW=n_5ybe-A=}hW5K8 zEx%6*l~n2Vfvm6}R7{Yc@~6wIR~Rd@BHYylwCyY3qG=dB4!%Q*qIBKQ(IA1l*6oS?uKC zK^}w!tbU8+fABPJ)PJW#WcuXb>ExN6#wKRaW0V5KwdBmj_1RuS86!kgK(w}3Ou+}~ zlAE#yroQj8(XS<66u)SAP&8_{%n~9=N5ruMZ0j}9Sr8h$9txeEZj0n6%LWDszExuh z-;Os_$SFO*`>PfKWeuL(cN`-N>zQc`9Vjz(HZo?#C{5q1f81T~L}!lFVD5QOAe^A> z&Fs9s;a^u0Pq2Z8mzwW9d6>1oAec)(KkV{+(jy)l?9Uqh#=DqxY4=r50QlM`{2Apo zdsx5d-pr*TX>_-6Y-Rs#oLKnGiq?YnMsM1wv1bYc>;(IQFqcgmXw;r3dT(nfup<1N zUXS;#)WOeTRWBlM|-jwL)OloNKLSlOBrb&bowx-avI#J6hy zEyunppRbZmlK_jQ3ZWKPM+(YQlZZ`nge%636zJ{A1<&<1W}+kPYC^@P~Ze0EFTkMV)4M!Q5;6jhc^(W z1_cJ(oBI0->LV5WFIz-=X)s>d?gh2)Yr|CS=9i@RTvGgdn=`=Pj`+Sj4BiUsp7n$o zp$dexehJ;cwjnhvTyV|q$(hK!+SsnxE)FB1q0s&Q?C8wdae4@n5@DS8B5YD{x9H#A z@xMFC|JdbS-YQ$NLv0PFJcfZuQ7g?|^+%HPDhxZS!^7#4x5sTh%An=0m2;Q*uyr+d z-f~e!Q@GZYdVNH`l|^E3?=R9!qRi$}rhp#B+}*}yVD&iSWUxTzpe1%+59Cb zynb;BY7Zf$Cso2o@S#`Ah~TNr`GE=UxfuXAN$XJ#YdJ)Ws$iqN;STy9^F zR89MZWklZFfRAoK(?#WJJiMkgr|pfe%q-t_q^zQc+U4+ll*WM`GJbZ~Vk%de|6PHG9${{~sHo28alM9*j-D8*5FYNf`vgPQN#}Zu7{ANq z@wqE3G_G^Zo9YDEI!df9)^8>}r{dV9BAKFzF{qNmV4PdVpcBTLl+PO$-Rt_=OWkud zk1Wm**0}^+@T)xTH199`jaQMFg|>C_4uliHTuxL0+fe(-p@yOddlD!`QNd~~(4q0Y4R*Wb9#EQwcMZvLCcwd=Uv{I&aFjm4@Wc8))vZ#h;{R^yf2 z_#P{JHS)}(Cl=Sqz^$$ZOk_!cWtGn@0OMw=6CZfc&yB@ZBAW-7F#dh4pg0NJsNO-X z%B&9=@FYz-Uz)7^;1Vl`+V3WVJC4i4@3ArN$H?*+smzhF1FMt!7H?4y!~k#0~bEt()(7dXe?_+vc@{Hn>wH!lEb;E#L)_RG}%s z8ci|c36q=r8-6^a{~&ZBna!?W&SI}9S8-ol(^L4Ln))jw$CwucV)Op7Vmrpc$|i(9 znX)oAAHnS6k^qg`#D&B>eQ6QrHVn}!a*@AkLiPIUGV6MUlpP&dRG%7mT43)0y^l6P zPXX<*^CKI79qNof+FZG4*7>>#wFCxnoM4$hK3b99!Q02bA3^W7dHt8xMCQ%&OVd_= zc1Y>3DYcX6oD7@#1La-^@Y%9HGpnNNpO}K_putY%hNjR<08oY4O~^T85%3od@#Wg%d|L+XPkSQG6)Xdx_i=eQhL0OvMfxG z(ddH|>tSZ3PwxrA>&yAy?b?O zcS@KqV|vHA9R5&n$z5LjkRg2Yj#rV=9xj?bKEzf|bXq)(_nUZSn}_%~oS-sFBnd40 zwwAPSAcA?fLj}KfDzh*lh0`H^iFG61`)z}%F5kcWIf?G=($P+dROk0E{}YY`YNyPf VAKHZk|M@Qf%uKCJa7Hfi{{mcgL&E?7 literal 0 HcmV?d00001 diff --git a/assets/video/rgbAnimation.mkv b/assets/video/rgbAnimation.mkv new file mode 100644 index 0000000000000000000000000000000000000000..903d2f5e7d05daee66221fa7b53a013ad5a7ac09 GIT binary patch literal 8614088 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

%V++_9aS|7f1HkBU@MGF8HnsMu>e&TUuS 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�wEBK%)mVR&c=KmY;|fB*y_009U<00Izz00bZa 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 Date: Fri, 4 Jun 2021 01:44:05 -0300 Subject: [PATCH 11/47] usar w en vez de x para colores --- app.s | 16 +++++++++++++--- draw.s | 51 ++++++++++++++++++++++++--------------------------- font.s | 2 +- 3 files changed, 38 insertions(+), 31 deletions(-) diff --git a/app.s b/app.s index a76253c..04f075b 100644 --- a/app.s +++ b/app.s @@ -112,9 +112,19 @@ main: // Pintamos un cuadrado en el medio de la pantalla mov x21, 300 // x2 mov x22, 300 // y2 - mov x23, 50 // w largo de pixeles + mov x23, 50 // w largo de pixeles mov x13, 255 // R - mov x14, 244 // G + mov x14, 255 // G + mov x15, 8 // B + bl setColour // R+G+B = Rojo + //bl doSquare + + // Pintamos una forma triangular (variable) en el medio de la pantalla + mov x21, 300 // x2 + mov x22, 300 // y2 + mov x23, 50 // w largo de pixeles + mov x13, 255 // R + mov x14, 255 // G mov x15, 8 // B bl setColour // R+G+B = Rojo bl doPiramide // REVIEW Checkear @@ -340,7 +350,7 @@ drawPixel: sub sp, sp, #8 stur x30, [sp, #0] bl setPixel - stur w18, [x0] // stur xN guarda 64bits, y stur wN guarda medio registro (32bits) + stur w18, [x0] // stur xN guarda 64bits, y stur wN guarda medio registro (32bits) IMPORTANTE!!!!!!!!! ldur x30, [sp, #0] add sp, sp, #8 ret diff --git a/draw.s b/draw.s index 5ed97ef..c59e7bd 100644 --- a/draw.s +++ b/draw.s @@ -280,7 +280,7 @@ circleEnd: ret .globl doTriangleUp -// NOTE Triangulo +// NOTE Triangulo hacia arriba doTriangleUp: // @Diego // Args @@ -293,7 +293,6 @@ doTriangleUp: stur lr, [sp] // Guardo el link register para no pisarlo en la subrutina setPixel mov x16, x21 // Instancio x16 para dibujar mov x12, x22 // Instancio x12 para setPixel - bl setPixel // Calculo la posicion inicial mov x19, x23 // La cantidad de pixeles sera la cantidad de veces que entro al ciclo mov x9, #0 // Instancio un contador que me va a servir para contar cantidad de pixeles b rectAr @@ -302,7 +301,7 @@ rectAr: // Dibuja la diagonal hacia arriba add x16, x16, #1 // Me muevo al siguiente sub x12, x12, #1 // Me muevo arriba bl setPixel // Calculo el pixel - stur x18, [x0] // Lo pinto + stur w18, [x0] // Lo pinto cmp x9, x19 // Comparo mi contador con mi cantidad de pixeles b.eq rectBaj // Si llegue a la cantidad bajo add x9, x9, #1 // Si no le sumo 1 @@ -312,7 +311,7 @@ rectBaj: // Dibuja la diagonal hacia abajo add x16, x16, #1 // Me muevo al siguiente add x12, x12, #1 // Bajo 1 unidad bl setPixel // Calculo el pixel - stur x18, [x0] // Lo pinto + stur w18, [x0] // Lo pinto cmp x9, #0 // Comparo el contador a w con 0 b.eq preRectAr // Si llegue a la "base" arranco de nuevo desde 1 posicion menos sub x9, x9, #1 // Si no, le resto 1 al contador @@ -333,7 +332,7 @@ endTriang: ret .globl doTriangleDown -// NOTE Triangulo +// NOTE Triangulo hacia abajo doTriangleDown: // @Diego // Args @@ -351,34 +350,34 @@ doTriangleDown: mov x9, #0 // Instancio un contador que me va a servir para contar cantidad de pixeles b rectArDown -rectArDown: // Dibuja la diagonal hacia arriba +rectArDown: // Dibuja la diagonal hacia arriba add x16, x16, #1 // Me muevo al siguiente add x12, x12, #1 // Me muevo arriba bl setPixel // Calculo el pixel - stur x18, [x0] // Lo pinto + stur w18, [x0] // Lo pinto cmp x9, x19 // Comparo mi contador con mi cantidad de pixeles - b.eq rectBajDown // Si llegue a la cantidad bajo + b.eq rectBajDown // Si llegue a la cantidad bajo add x9, x9, #1 // Si no le sumo 1 - b rectArDown // Empiezo de nuevo + b rectArDown // Empiezo de nuevo rectBajDown: // Dibuja la diagonal hacia abajo add x16, x16, #1 // Me muevo al siguiente sub x12, x12, #1 // Bajo 1 unidad bl setPixel // Calculo el pixel - stur x18, [x0] // Lo pinto + bl drawPixel // Lo pinto cmp x9, #0 // Comparo el contador a w con 0 - b.eq preRectArDown // Si llegue a la "base" arranco de nuevo desde 1 posicion menos + b.eq preRectArDown // Si llegue a la "base" arranco de nuevo desde 1 posicion menos sub x9, x9, #1 // Si no, le resto 1 al contador - b rectBajDown // Bajo de nuevo + b rectBajDown // Bajo de nuevo -preRectArDown: // Se fija si itero la cantidad de veces necesarias +preRectArDown: // Se fija si itero la cantidad de veces necesarias add x21, x21, #1 // Itero una vez menos mov x16, x21 // Empiezo de nuevo mov x12, x22 // Instancio x12 para setPixel cmp x19, xzr // Si itere w cantidad de veces --> - b.eq endTriangDown // Termino + b.eq endTriangDown // Termino sub x19, x19, #1 // Si no, resto 1 iteracion - b rectArDown // sigo + b rectArDown // sigo endTriangDown: ldur lr, [sp] @@ -386,39 +385,37 @@ endTriangDown: ret .globl doPiramide -// NOTE Triangulo +// NOTE Piramide doPiramide: // @Diego // Args // x21 x lugar dónde empiezo a dibujar la figura // x22 y lugar dónde empiezo a dibujar la figura // x23 w cantidad de píxeles - // x18 colour + // w18 colour sub sp, sp, #8 stur lr, [sp] // Guardo el link register para no pisarlo en la subrutina setPixel mov x16, x21 // Instancio x16 para dibujar mov x12, x22 // Instancio x12 para setPixel - bl setPixel // Calculo la posicion inicial mov x19, x23 // La cantidad de pixeles sera la cantidad de veces que entro al ciclo mov x9, #0 // Instancio un contador que me va a servir para contar cantidad de pixeles - b pirAr pirAr: // Dibuja la diagonal hacia arriba - sub x16, x16, #1 // Me muevo al siguiente + sub x16, x16, #1 // Me muevo atras sub x12, x12, #1 // Me muevo arriba bl setPixel // Calculo el pixel - stur x18, [x0] // Lo pinto + stur w18, [x0] // Lo pinto cmp x9, x19 // Comparo mi contador con mi cantidad de pixeles - b.eq pirBaj // Si llegue a la cantidad bajo - add x9, x9, #1 // Si no le sumo 1 - b pirAr // Empiezo de nuevo + b.eq pirBaj // Si llegue a la cantidad bajo + add x9, x9, #1 // Si no le sumo 1 al contador + b pirAr // Empiezo de nuevo -pirBaj: // Dibuja la diagonal hacia abajo - sub x16, x16, #1 // Me muevo al siguiente +pirBaj: // Dibuja la diagonal hacia abajo + sub x16, x16, #1 // Me muevo atras add x12, x12, #1 // Bajo 1 unidad bl setPixel // Calculo el pixel - stur x18, [x0] // Lo pinto + stur w18, [x0] // Lo pinto cmp x9, #0 // Comparo el contador a w con 0 b.eq prepirAr // Si llegue a la "base" arranco de nuevo desde 1 posicion menos sub x9, x9, #1 // Si no, le resto 1 al contador diff --git a/font.s b/font.s index fb35a2c..0e95c8c 100644 --- a/font.s +++ b/font.s @@ -98,7 +98,7 @@ doGm: .globl doG // NOTE g doG: - // @Diego + //@Diego .globl doDiego // NOTE Diego From 365066cded3cb16245ce26181644dcb243855380 Mon Sep 17 00:00:00 2001 From: diegogimenez04 Date: Fri, 4 Jun 2021 11:30:31 -0300 Subject: [PATCH 12/47] Aproximacion de I --- app.s | 14 ++++++++++++-- draw.s | 2 +- font.s | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 3 deletions(-) diff --git a/app.s b/app.s index 04f075b..47a5089 100644 --- a/app.s +++ b/app.s @@ -124,10 +124,20 @@ main: mov x22, 300 // y2 mov x23, 50 // w largo de pixeles mov x13, 255 // R - mov x14, 255 // G + mov x14, 0 // G + mov x15, 8 // B + bl setColour // R+G+B = Rojo + //bl doPiramide // REVIEW Checkear + + // Pintamos una I en la pantalla + mov x21, 300 // x2 + mov x22, 300 // y2 + mov x23, 50 // w largo de pixeles + mov x13, 255 // R + mov x14, 0 // G mov x15, 8 // B bl setColour // R+G+B = Rojo - bl doPiramide // REVIEW Checkear + bl doI // FIXME Checkear ret // Dibujamos un círculo diff --git a/draw.s b/draw.s index c59e7bd..692b70b 100644 --- a/draw.s +++ b/draw.s @@ -339,7 +339,7 @@ doTriangleDown: // x21 x lugar dónde empiezo a dibujar la figura // x22 y lugar dónde empiezo a dibujar la figura // x23 w cantidad de píxeles - // x18 colour + // w18 colour sub sp, sp, #8 stur lr, [sp] // Guardo el link register para no pisarlo en la subrutina setPixel diff --git a/font.s b/font.s index 0e95c8c..ed686ca 100644 --- a/font.s +++ b/font.s @@ -26,6 +26,57 @@ doE: // NOTE i doI: // @Diego + // Args + // x21 x lugar dónde empiezo a dibujar la figura + // x22 y lugar dónde empiezo a dibujar la figura + // w18 color + sub sp, sp, 40 + stur lr, [sp] + stur x21, [sp, #8] + stur x22, [sp, #16] + stur x23, [sp, #24] + stur x24, [sp, #32] + mov x16, x21 + mov x12, x22 + mov x9, #0 + +doITop: + bl drawPixel + add x21, x21, 1 + cmp x9, 20 + b.eq preIDown + add x9, x9, 1 + b doITop + +preIDown: + mov x21, x16 + mov x22, x12 + add x16, x16, #10 + +doIDown: + bl drawPixel + add x12, x12, #1 + cmp x9, #20 + b.eq endI + add x9, x9, #1 + b doIDown + +doIBot: + bl drawPixel + sub x21, x21, 1 + cmp x9, 0 + b.eq endI + sub x9, x9, 1 + b doITop + +endI: + ldur x24, [sp, #32] + ldur x23, [sp, #24] + ldur x22, [sp, #16] + ldur x21, [sp, #8] + ldur lr, [sp] + add sp, sp, 40 + ret .globl doO // NOTE o From 57a474be16542224ed415af7bbed1f580b580290 Mon Sep 17 00:00:00 2001 From: diegogimenez04 Date: Fri, 4 Jun 2021 20:45:56 -0300 Subject: [PATCH 13/47] NO SALE EL I --- app.s | 10 +++++----- font.s | 26 +++++++------------------- 2 files changed, 12 insertions(+), 24 deletions(-) diff --git a/app.s b/app.s index 47a5089..4d8baa7 100644 --- a/app.s +++ b/app.s @@ -121,23 +121,23 @@ main: // Pintamos una forma triangular (variable) en el medio de la pantalla mov x21, 300 // x2 - mov x22, 300 // y2 + mov x22, 400 // y2 mov x23, 50 // w largo de pixeles mov x13, 255 // R - mov x14, 0 // G + mov x14, 254 // G mov x15, 8 // B bl setColour // R+G+B = Rojo - //bl doPiramide // REVIEW Checkear +// bl doPiramide // REVIEW Checkear // Pintamos una I en la pantalla mov x21, 300 // x2 mov x22, 300 // y2 mov x23, 50 // w largo de pixeles mov x13, 255 // R - mov x14, 0 // G + mov x14, 0 // G mov x15, 8 // B bl setColour // R+G+B = Rojo - bl doI // FIXME Checkear + bl doI // FIXME Checkear ret // Dibujamos un círculo diff --git a/font.s b/font.s index ed686ca..ad6ac71 100644 --- a/font.s +++ b/font.s @@ -38,36 +38,24 @@ doI: stur x24, [sp, #32] mov x16, x21 mov x12, x22 - mov x9, #0 + mov x10, x23 + mov x9, 0 doITop: - bl drawPixel - add x21, x21, 1 - cmp x9, 20 - b.eq preIDown - add x9, x9, 1 - b doITop - -preIDown: - mov x21, x16 - mov x22, x12 - add x16, x16, #10 + mov x23, 20 + bl doHorizontalLine + mov x23, x10 doIDown: bl drawPixel add x12, x12, #1 cmp x9, #20 - b.eq endI + b.eq doIBot add x9, x9, #1 b doIDown doIBot: - bl drawPixel - sub x21, x21, 1 - cmp x9, 0 - b.eq endI - sub x9, x9, 1 - b doITop + mov endI: ldur x24, [sp, #32] From 7e307498b6f6d4c927cd2b146030022ce330fd96 Mon Sep 17 00:00:00 2001 From: diegogimenez04 Date: Mon, 7 Jun 2021 11:03:59 -0300 Subject: [PATCH 14/47] Finished I, fix E --- app.s | 4 ++-- draw.s | 10 ++++----- font.s | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 69 insertions(+), 14 deletions(-) diff --git a/app.s b/app.s index 4d8baa7..2e315f3 100644 --- a/app.s +++ b/app.s @@ -127,7 +127,7 @@ main: mov x14, 254 // G mov x15, 8 // B bl setColour // R+G+B = Rojo -// bl doPiramide // REVIEW Checkear + //bl doPiramide // Pintamos una I en la pantalla mov x21, 300 // x2 @@ -137,7 +137,7 @@ main: mov x14, 0 // G mov x15, 8 // B bl setColour // R+G+B = Rojo - bl doI // FIXME Checkear + bl doE ret // Dibujamos un círculo diff --git a/draw.s b/draw.s index 692b70b..37e8bc4 100644 --- a/draw.s +++ b/draw.s @@ -19,12 +19,12 @@ drawLine: // x19 err sub sp, sp, #48 // Reservamos 6 registros de memoria - stur x30, [sp, #40] // Guardamos el return pointer en memoria - stur x19, [sp, #32] - stur x4, [sp, #24] - stur x5, [sp, #16] - stur x6, [sp, #8] stur x7, [sp, #0] + stur x6, [sp, #8] + stur x5, [sp, #16] + stur x4, [sp, #24] + stur x19, [sp, #32] + stur x30, [sp, #40] // Guardamos el return pointer en memoria // (x0, y0) to (x1, y1) // (xc0, yc0) to (xc1, yc1) diff --git a/font.s b/font.s index ad6ac71..bf33cac 100644 --- a/font.s +++ b/font.s @@ -19,12 +19,59 @@ doA: .globl doE // NOTE e -doE: +doE: //FIXME // @Diego + // Args + // x21 x lugar dónde empiezo a dibujar la figura + // x22 y lugar dónde empiezo a dibujar la figura + // w18 color + sub sp, sp, 32 + stur lr, [sp] + stur x21, [sp, #8] + stur x22, [sp, #16] + stur x23, [sp, #24] + mov x9, #0 + +doETop: + mov x23, 15 + bl doHorizontalLine + ldur x21, [sp, #8] + ldur x22, [sp, #16] + mov x16, x21 + mov x12, x22 + +doEDown: + bl drawPixel + add x12, x12, #1 + cmp x9, #10 + b.eq drawEMid + cmp x9, #20 + b.eq endE + add x9, x9, #1 + b doEDown + +drawEMid: + mov x23, #10 + bl doHorizontalLine + add x9, x9, #1 + b doEDown + + +drawEBot: + mov x23, 15 + bl doHorizontalLine + b endE + +endE: + ldur x23, [sp, #24] + ldur x22, [sp, #16] + ldur x21, [sp, #8] + ldur lr, [sp] + ret .globl doI // NOTE i -doI: +doI: //REVIEW Done // @Diego // Args // x21 x lugar dónde empiezo a dibujar la figura @@ -41,21 +88,29 @@ doI: mov x10, x23 mov x9, 0 -doITop: +drawITop: mov x23, 20 bl doHorizontalLine - mov x23, x10 + ldur x21, [sp, #8] + ldur x22, [sp, #16] + mov x16, x21 + mov x12, x22 + add x16, x16, 10 doIDown: bl drawPixel add x12, x12, #1 cmp x9, #20 - b.eq doIBot + b.eq drawIBot add x9, x9, #1 b doIDown -doIBot: - mov +drawIBot: + mov x23, 20 + ldur x21, [sp, #8] + ldur x22, [sp, #16] + add x22, x22, 20 + bl doHorizontalLine endI: ldur x24, [sp, #32] From fcff54559fd33da57ca059944dd25770a7031794 Mon Sep 17 00:00:00 2001 From: diegogimenez04 Date: Tue, 8 Jun 2021 09:58:25 -0300 Subject: [PATCH 15/47] Terminado E --- app.s | 20 +++++++++++++++----- font.s | 19 +++++++++++-------- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/app.s b/app.s index 2e315f3..b60192a 100644 --- a/app.s +++ b/app.s @@ -127,7 +127,7 @@ main: mov x14, 254 // G mov x15, 8 // B bl setColour // R+G+B = Rojo - //bl doPiramide + bl doI // Pintamos una I en la pantalla mov x21, 300 // x2 @@ -268,8 +268,8 @@ drawBorder: bl setPixel ldur x9, [x0] - mov x16, SCREEN_WIDTH // REVIEW esto esta bien? No deberia ser SCREEN_WIDTH para los x? - mov x12, SCREEN_HEIGH // Y SCREEN_HEIGH para los y? + mov x16, SCREEN_WIDTH + mov x12, SCREEN_HEIGH bl setPixel stur x18, [x0] @@ -435,7 +435,12 @@ doHorizontalLine: // Crea líneas horizontales en la coordenada (xo, po) con w c // Used // drawPixel: setPixel x16 x, x12 y // x18 Colour - sub sp, sp, #8 + sub sp, sp, #48 + stur x12, [sp, #40] + stur x16, [sp, #32] + stur x23, [sp, #24] + stur x22, [sp, #16] + stur x21, [sp, #8] stur x30, [sp, #0] // Guardamos el return pointer en memoria mov x16, x21 // x = xo // horLineLoop... @@ -451,7 +456,12 @@ horLineLoop: endHorizontalLine: ldur x30, [sp, #0] // Guardamos el return pointer en memoria - add sp, sp, #8 // Liberamos espacio en memoria + ldur x21, [sp, #8] + ldur x22, [sp, #16] + ldur x23, [sp, #24] + ldur x16, [sp, #32] + ldur x12, [sp, #40] + add sp, sp, #48 // Liberamos espacio en memoria ret // BL sobreescribe el registro x30 y RET lee el registro x30 // diff --git a/font.s b/font.s index bf33cac..b49b5de 100644 --- a/font.s +++ b/font.s @@ -19,12 +19,14 @@ doA: .globl doE // NOTE e -doE: //FIXME +doE: // REVIEW Done // @Diego // Args // x21 x lugar dónde empiezo a dibujar la figura // x22 y lugar dónde empiezo a dibujar la figura // w18 color + // Usa: + // x23 para la funcion doHorizontalLine sub sp, sp, 32 stur lr, [sp] stur x21, [sp, #8] @@ -35,23 +37,22 @@ doE: //FIXME doETop: mov x23, 15 bl doHorizontalLine - ldur x21, [sp, #8] - ldur x22, [sp, #16] mov x16, x21 mov x12, x22 doEDown: bl drawPixel add x12, x12, #1 + add x22, x22, #1 cmp x9, #10 b.eq drawEMid cmp x9, #20 - b.eq endE + b.eq drawEBot add x9, x9, #1 b doEDown drawEMid: - mov x23, #10 + mov x23, 10 bl doHorizontalLine add x9, x9, #1 b doEDown @@ -91,8 +92,8 @@ doI: //REVIEW Done drawITop: mov x23, 20 bl doHorizontalLine - ldur x21, [sp, #8] - ldur x22, [sp, #16] + add x22, x22, 1 + bl doHorizontalLine mov x16, x21 mov x12, x22 add x16, x16, 10 @@ -111,6 +112,8 @@ drawIBot: ldur x22, [sp, #16] add x22, x22, 20 bl doHorizontalLine + add x22, x22, 1 + bl doHorizontalLine endI: ldur x24, [sp, #32] @@ -136,7 +139,7 @@ doDm: doL: // @Vale -.globl doDm +.globl doS // NOTE s doS: // @Vale From 4d366fca1afb0561dab1fbf5ec58694c781ab20b Mon Sep 17 00:00:00 2001 From: diegogimenez04 Date: Wed, 9 Jun 2021 10:24:14 -0300 Subject: [PATCH 16/47] M, Z, D --- app.s | 6 +- font.s | 203 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 203 insertions(+), 6 deletions(-) diff --git a/app.s b/app.s index b60192a..637e43e 100644 --- a/app.s +++ b/app.s @@ -130,14 +130,14 @@ main: bl doI // Pintamos una I en la pantalla - mov x21, 300 // x2 - mov x22, 300 // y2 + mov x21, 250 // x2 + mov x22, 400 // y2 mov x23, 50 // w largo de pixeles mov x13, 255 // R mov x14, 0 // G mov x15, 8 // B bl setColour // R+G+B = Rojo - bl doE + bl doO ret // Dibujamos un círculo diff --git a/font.s b/font.s index b49b5de..72e5d3f 100644 --- a/font.s +++ b/font.s @@ -128,11 +128,111 @@ endI: // NOTE o doO: // @Diego + sub sp, sp, 24 + stur x22, [sp, #16] + stur x21, [sp, #8] + stur lr, [sp] + mov x16, x21 + mov x12, x22 + mov x9, 0 + + mov x23, 5 + bl doHorizontalLine + +endO: + stur lr, [sp] + stur x21, [sp, #8] + stur x22, [sp, #16] + add sp, sp, 24 + ret .globl doDm // NOTE D -doDm: +doDm: // REVIEW Done // @Diego + // Args + // x21 x inicial + // x22 y inicial + // w18 color + // Uses + // x23 par doHorizontalLine + sub sp, sp, 24 + stur lr, [sp] + stur x21, [sp, #8] + stur x22, [sp, #16] + mov x16, x21 + mov x12, x22 + mov x9, 0 + +dIzq: + add x12, x12, 1 + bl drawPixel + cmp x9, 20 + b.eq preDDer + add x9, x9, 1 + b dIzq + +preDDer: + mov x23, 5 + bl doHorizontalLine + add x21, x21, 6 + add x22, x22, 1 + mov x16, x21 + mov x12, x22 + bl drawPixel + add x16, x16, 1 + add x12, x12, 1 + bl drawPixel + add x16, x16, 1 + add x12, x12, 1 + bl drawPixel + add x16, x16, 1 + add x12, x12, 1 + bl drawPixel + add x16, x16, 1 + add x12, x12, 1 + bl drawPixel + mov x9, 0 + +dDer: + add x12, x12, 1 + bl drawPixel + cmp x9, 10 + b.eq dDoIzq + add x9, x9, 1 + b dDer + +dDoIzq: + sub x16, x16, 1 + add x12, x12, 1 + bl drawPixel + sub x16, x16, 1 + add x12, x12, 1 + bl drawPixel + sub x16, x16, 1 + add x12, x12, 1 + bl drawPixel + sub x16, x16, 1 + add x12, x12, 1 + bl drawPixel + sub x16, x16, 1 + add x12, x12, 1 + bl drawPixel + sub x16, x16, 1 + bl drawPixel + sub x16, x16, 1 + bl drawPixel + sub x16, x16, 1 + bl drawPixel + sub x16, x16, 1 + bl drawPixel + +endD: + stur x22, [sp, #16] + stur x21, [sp, #8] + stur lr, [sp] + sub sp, sp, 24 + ret .globl doL // NOTE l @@ -151,8 +251,65 @@ doP: .globl doM // NOTE m -doM: +doM: // REVIEW Done // @Diego + // Args + // x21 x inicial + // x22 y inicial + // w18 color + // Uses + // x23 par doHorizontalLine + sub sp, sp, 24 + stur lr, [sp] + stur x21, [sp, #8] + stur x22, [sp, #16] + mov x16, x21 + mov x12, x22 + mov x9, 0 + +doPalo: + add x12, x12, 1 + bl drawPixel + cmp x9, 20 + b.eq doMr + add x9, x9, 1 + b doPalo + +doMr: + mov x12, x22 + mov x9, 0 +doMrLoop: + add x16, x16, 1 + add x12, x12, 1 + bl drawPixel + cmp x9, 10 + b.eq doMrUp + add x9, x9, 1 + b doMrLoop + +doMrUp: + add x16, x16, 1 + sub x12, x12, 1 + bl drawPixel + cmp x9, 0 + b.eq doPaloD + sub x9, x9, 1 + b doMrUp + +doPaloD: + add x12, x12, 1 + bl drawPixel + cmp x9, 20 + b.eq endM + add x9, x9, 1 + b doPaloD + +endM: + ldur x22, [sp, #16] + ldur x21, [sp, #8] + ldur lr, [sp] + add sp, sp, 24 + ret .globl doN // NOTE n @@ -184,8 +341,48 @@ doT: .globl doZ // NOTE z -doZ: +doZ: // REVIEW Done // @Diego + // Args + // x21 x inicial + // x22 y inicial + // x18 Color + // Usa: + // x23 para doHorizontalLine + sub sp, sp, 24 + stur lr, [sp, 16] + stur x21, [sp, 8] + stur x22, [sp] + mov x16, x21 + mov x12, x22 + mov x9, 0 + + mov x23, 20 + bl doHorizontalLine + add x21, x21, 20 + add x16, x16, 20 + +doZDiag: + bl drawPixel + add x22, x22, 1 + sub x21, x21, 1 + sub x16, x16, 1 + add x12, x12, 1 + cmp x9, 20 + b.eq doZBot + add x9, x9, 1 + b doZDiag + +doZBot: + mov x23, 20 + bl doHorizontalLine + +endZ: + ldur x22, [sp] + ldur x21, [sp, 8] + ldur lr, [sp, 16] + add sp, sp, 24 + ret .globl doGm // NOTE G From ad836191bc0ee34fbba5417a1ca288a56fe8767d Mon Sep 17 00:00:00 2001 From: diegogimenez04 Date: Fri, 11 Jun 2021 19:01:23 -0300 Subject: [PATCH 17/47] G mayuscula, g minuscula en proceso --- app.s | 2 +- draw.s | 46 ++++++++++++++++--- font.s | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 174 insertions(+), 13 deletions(-) diff --git a/app.s b/app.s index 637e43e..9af1190 100644 --- a/app.s +++ b/app.s @@ -137,7 +137,7 @@ main: mov x14, 0 // G mov x15, 8 // B bl setColour // R+G+B = Rojo - bl doO + bl doG ret // Dibujamos un círculo diff --git a/draw.s b/draw.s index 37e8bc4..e17eb3a 100644 --- a/draw.s +++ b/draw.s @@ -3,6 +3,42 @@ //.include "app.s" +.globl vertLine +// NOTE Vertilcal line with a height +vertLine: + // Args + // x21 x + // x22 y + // x18 colour + // x23 height + sub sp, sp, 40 + stur x9, [sp, 32] + stur x21, [sp, 24] + stur x22, [sp, 16] + stur x23, [sp, 8] + stur lr, [sp] + mov x16, x21 + mov x12, x22 + mov x9, 0 + +doVertL: + bl drawPixel + add x12, x12, 1 + cmp x9, x23 + b.eq endVertLine + add x9, x9, 1 + b doVertL + +endVertLine: + ldur lr, [sp] + ldur x23, [sp, 8] + ldur x22, [sp, 16] + ldur x21, [sp, 24] + ldur x9, [sp, 32] + add sp, sp, 40 + ret + + .globl drawLine // NOTE Line drawLine: @@ -19,12 +55,12 @@ drawLine: // x19 err sub sp, sp, #48 // Reservamos 6 registros de memoria - stur x7, [sp, #0] - stur x6, [sp, #8] - stur x5, [sp, #16] - stur x4, [sp, #24] - stur x19, [sp, #32] stur x30, [sp, #40] // Guardamos el return pointer en memoria + stur x19, [sp, #32] + stur x4, [sp, #24] + stur x5, [sp, #16] + stur x6, [sp, #8] + stur x7, [sp, #0] // (x0, y0) to (x1, y1) // (xc0, yc0) to (xc1, yc1) diff --git a/font.s b/font.s index 72e5d3f..1e1d210 100644 --- a/font.s +++ b/font.s @@ -132,12 +132,8 @@ doO: stur x22, [sp, #16] stur x21, [sp, #8] stur lr, [sp] - mov x16, x21 - mov x12, x22 - mov x9, 0 - mov x23, 5 - bl doHorizontalLine + bl doCircle endO: stur lr, [sp] @@ -386,13 +382,142 @@ endZ: .globl doGm // NOTE G -doGm: +doGm: //REVIEW Done // @Diego + // Args + // x21 x inicial + // x22 y inicial + // x18 color + // AUX fun: + // doVertLine + sub sp, sp, 40 + stur x21, [sp, 32] + stur x22, [sp, 24] + stur x18, [sp, 16] + stur x23, [sp, 8] + stur lr, [sp] + mov x16, x21 + mov x12, x22 + mov x23, 3 + mov x9, 0 + bl doHorizontalLine + add x16, x16, 3 + +doGmStart: + bl drawPixel + add x12, x12, 1 + add x16, x16, 1 + cmp x9, 5 + b.eq preDoGMDiag + add x9, x9, 1 + b doGmStart + +preDoGMDiag: + mov x9, 0 + mov x16, x21 + mov x12, x22 + +doGMDiag: + bl drawPixel + add x12, x12, 1 + sub x16, x16, 1 + cmp x9, 10 + b.eq preDoGMDiagR + add x9, x9, 1 + b doGMDiag + +preDoGMDiagR: + mov x21, x16 + mov x22, x12 + mov x23, 10 + bl vertLine + +doGMDiagR: + bl drawPixel + add x12, x12, 1 + add x16, x16, 1 + cmp x9, 0 + b.eq doGMbot + sub x9, x9, 1 + b doGMDiagR + +doGMbot: + mov x21, x16 + mov x22, x12 + mov x23, 5 + bl doHorizontalLine + add x16, x16, 5 + mov x9, 0 + +doGMdiagUR: + bl drawPixel + add x16, x16, 1 + sub x12, x12, 1 + cmp x9, 10 + b.eq doGend + add x9, x9, 1 + b doGMdiagUR + +doGend: + mov x22, x12 + mov x21, x16 + sub x22, x22, 5 + mov x23, 5 + bl vertLine + sub x21, x21, 10 + mov x23, 10 + bl doHorizontalLine + +endGm: + ldur x21, [sp, 32] + ldur x22, [sp, 24] + ldur x18, [sp, 16] + ldur x23, [sp, 8] + ldur lr, [sp] + add sp, sp, 40 + ret .globl doG // NOTE g doG: - //@Diego + // @Diego + // Args + // x21 x inicial + // x22 y inicial + // x18 color + sub sp, sp, 40 + stur x21, [sp, 32] + stur x22, [sp, 24] + stur x18, [sp, 16] + stur x23, [sp, 8] + stur lr, [sp] + mov x16, x21 + mov x12, x22 + mov x23, 3 + mov x9, 0 + bl doCircle + add x16, x16, x23 + add x16, x16, x23 + add x12, x12, x23 + add x12, x12, 1 + +doGDiag: + bl drawPixel + add x12, x12, 1 + sub x16, x16, 1 + cmp x9, 10 + b.eq endG + add x9, x9, 1 + b doGDiag + +endG: + ldur x21, [sp, 32] + ldur x22, [sp, 24] + ldur x18, [sp, 16] + ldur x23, [sp, 8] + ldur lr, [sp] + add sp, sp, 40 + ret .globl doDiego // NOTE Diego From e59b7898bf04ed5a0ab11ad8d350dca0256c3ab7 Mon Sep 17 00:00:00 2001 From: diegogimenez04 Date: Sat, 12 Jun 2021 10:05:46 -0300 Subject: [PATCH 18/47] nada --- app.s | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/app.s b/app.s index 9af1190..a9f579a 100644 --- a/app.s +++ b/app.s @@ -137,7 +137,16 @@ main: mov x14, 0 // G mov x15, 8 // B bl setColour // R+G+B = Rojo - bl doG + bl doD + + mov x21, 250 // x2 + mov x22, 400 // y2 + mov x23, 50 // w largo de pixeles + mov x13, 255 // R + mov x14, 0 // G + mov x15, 8 // B + bl setColour // R+G+B = Rojo + bl doE ret // Dibujamos un círculo From 27147af36c8b31bb2cc467ce9a4b07d9bb0d8fef Mon Sep 17 00:00:00 2001 From: diegogimenez04 Date: Sat, 12 Jun 2021 10:17:03 -0300 Subject: [PATCH 19/47] hotfix doDm no terminaba --- app.s | 6 +++--- font.s | 11 ++++++----- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/app.s b/app.s index c28d84b..1e01889 100644 --- a/app.s +++ b/app.s @@ -130,14 +130,14 @@ main: bl doI // Pintamos una I en la pantalla - mov x21, 250 // x2 + mov x21, 500 // x2 mov x22, 400 // y2 mov x23, 50 // w largo de pixeles mov x13, 255 // R mov x14, 0 // G mov x15, 8 // B bl setColour // R+G+B = Rojo - bl doD + bl doDm mov x21, 250 // x2 mov x22, 400 // y2 @@ -146,7 +146,7 @@ main: mov x14, 0 // G mov x15, 8 // B bl setColour // R+G+B = Rojo - bl doE + bl doE ret // Dibujamos un círculo diff --git a/font.s b/font.s index 1e1d210..4927010 100644 --- a/font.s +++ b/font.s @@ -144,7 +144,7 @@ endO: .globl doDm // NOTE D -doDm: // REVIEW Done +doDm: // REVIEW Solucionado // @Diego // Args // x21 x inicial @@ -222,12 +222,13 @@ dDoIzq: bl drawPixel sub x16, x16, 1 bl drawPixel + b endD endD: - stur x22, [sp, #16] - stur x21, [sp, #8] - stur lr, [sp] - sub sp, sp, 24 + ldur x22, [sp, #16] + ldur x21, [sp, #8] + ldur lr, [sp] + add sp, sp, 24 ret .globl doL From f1136c415d8743d4e7b440fbc0e3b0d3a52e7162 Mon Sep 17 00:00:00 2001 From: diegogimenez04 Date: Sat, 12 Jun 2021 10:55:59 -0300 Subject: [PATCH 20/47] fine e and i --- app.s | 31 ++------------ font.s | 131 +++++++++++++++++++++++++++++++++++++++++++++++++++----- todo.md | 8 ++-- 3 files changed, 127 insertions(+), 43 deletions(-) diff --git a/app.s b/app.s index 1e01889..1e5a2bb 100644 --- a/app.s +++ b/app.s @@ -119,34 +119,9 @@ main: bl setColour // R+G+B = Rojo //bl doSquare - // Pintamos una forma triangular (variable) en el medio de la pantalla - mov x21, 300 // x2 - mov x22, 400 // y2 - mov x23, 50 // w largo de pixeles - mov x13, 255 // R - mov x14, 254 // G - mov x15, 8 // B - bl setColour // R+G+B = Rojo - bl doI - - // Pintamos una I en la pantalla - mov x21, 500 // x2 - mov x22, 400 // y2 - mov x23, 50 // w largo de pixeles - mov x13, 255 // R - mov x14, 0 // G - mov x15, 8 // B - bl setColour // R+G+B = Rojo - bl doDm - - mov x21, 250 // x2 - mov x22, 400 // y2 - mov x23, 50 // w largo de pixeles - mov x13, 255 // R - mov x14, 0 // G - mov x15, 8 // B - bl setColour // R+G+B = Rojo - bl doE + mov x21, 100 + mov x22, 100 + bl doDiego ret // Dibujamos un círculo diff --git a/font.s b/font.s index 4927010..964414f 100644 --- a/font.s +++ b/font.s @@ -17,9 +17,9 @@ doA: // @Vale -.globl doE +.globl doEm // NOTE e -doE: // REVIEW Done +doEm: // REVIEW Done // @Diego // Args // x21 x lugar dónde empiezo a dibujar la figura @@ -70,9 +70,53 @@ endE: ldur lr, [sp] ret -.globl doI +.globl doE +// NOTE e +doE: // REVIEW Done + // @Diego + // Args + // x21 x lugar dónde empiezo a dibujar la figura + // x22 y lugar dónde empiezo a dibujar la figura + // w18 color + // Usa: + // x23 para la funcion doHorizontalLine + sub sp, sp, 32 + stur lr, [sp] + stur x21, [sp, #8] + stur x22, [sp, #16] + stur x23, [sp, #24] + + mov x23, 10 + add x22, x22, 10 + sub x21, x21, 5 + bl doHorizontalLine + add x21, x21, 11 + sub x22, x22, 7 + mov x23, 6 + bl vertLine + sub x21, x21, 14 + sub x22, x22, 1 + mov x23, 14 + bl doHorizontalLine + sub x21, x21, 1 + add x22, x22, 1 + mov x23, 14 + bl vertLine + add x21, x21, 1 + add x22, x22, 15 + mov x23, 14 + bl doHorizontalLine + + ldur x23, [sp, #24] + ldur x22, [sp, #16] + ldur x21, [sp, #8] + ldur lr, [sp] + add sp, sp, 32 + ret + +.globl doIm // NOTE i -doI: //REVIEW Done +doIm: //REVIEW Done // @Diego // Args // x21 x lugar dónde empiezo a dibujar la figura @@ -124,6 +168,43 @@ endI: add sp, sp, 40 ret +.globl doI +// NOTE i +doI: //REVIEW Done + // @Diego + // Args + // x21 x lugar dónde empiezo a dibujar la figura + // x22 y lugar dónde empiezo a dibujar la figura + // w18 color + sub sp, sp, 40 + stur lr, [sp] + stur x21, [sp, #8] + stur x22, [sp, #16] + stur x23, [sp, #24] + stur x24, [sp, #32] + mov x16, x21 + mov x12, x22 + bl drawPixel + sub x21, x21, 5 + add x22, x22, 5 + mov x23, 5 + bl doHorizontalLine + add x21, x21, 5 + mov x23, 15 + bl vertLine + sub x21, x21, 8 + add x22, x22, 15 + mov x23, 15 + bl doHorizontalLine + + ldur x24, [sp, #32] + ldur x23, [sp, #24] + ldur x22, [sp, #16] + ldur x21, [sp, #8] + ldur lr, [sp] + add sp, sp, 40 + ret + .globl doO // NOTE o doO: @@ -422,7 +503,7 @@ doGMDiag: bl drawPixel add x12, x12, 1 sub x16, x16, 1 - cmp x9, 10 + cmp x9, 5 b.eq preDoGMDiagR add x9, x9, 1 b doGMDiag @@ -454,7 +535,7 @@ doGMdiagUR: bl drawPixel add x16, x16, 1 sub x12, x12, 1 - cmp x9, 10 + cmp x9, 5 b.eq doGend add x9, x9, 1 b doGMdiagUR @@ -524,11 +605,33 @@ endG: // NOTE Diego doDiego: // @Diego - // bl doDm - // bl doI - // bl doE - // bl doG - // bl doO + // Args + // x21 x + // x22 y + // w18 color + // x23 for O + sub sp, sp, 40 + stur x23, [sp, 32] + stur x21, [sp, 24] + stur x22, [sp, 16] + stur w18, [sp, 8] + stur lr, [sp] + + bl doDm + + add x21, x21, 50 + bl doI + + add x21, x21, 50 + bl doE + + add x21, x21, 50 + bl doGm + + add x21, x21, 50 + add x22, x22, 10 + mov x23, 10 + bl doO // bl doGm // bl doI @@ -537,6 +640,12 @@ doDiego: // bl doN // bl doE // bl doZ + ldur lr, [sp] + ldur w18, [sp, 8] + ldur x22, [sp, 16] + ldur x21, [sp, 24] + ldur x23, [sp, 32] + add sp, sp, 40 ret .globl doValentinaVispo diff --git a/todo.md b/todo.md index 64acb6e..f8330be 100644 --- a/todo.md +++ b/todo.md @@ -93,14 +93,14 @@ NOTA IMPORTANTE: Tener en cuenta las diferencias existentes entre el set de inst - [ ] Añadir el checkeo de que no se escriban píxeles fuera del framebuffer. - Crear las siguientes letras con esta [fuente](https://www.dafont.com/es/minitel.font?text=console) y en este archivo [font.s](font.s) (@diegogimenez04): - - [ ] doDm (crea una `D` en mayúscula) - - [ ] doO (crea una `o` en minúscula) + - [x] doDm (crea una `D` en mayúscula) + - [x] doO (crea una `o` en minúscula) - [ ] doE (crea una `e` en minúscula) - [ ] doI (crea una `i` en minúscula) - - [ ] doZ (crea una `z` en minúscula) + - [x] doZ (crea una `z` en minúscula) - [ ] doM (crea una `m` en minúscula) - [ ] doG (crea una `g` en minúscula) - - [ ] doGm (crea una `G` en mayúscula) + - [x] doGm (crea una `G` en mayúscula) - Crear las siguientes letras con esta [fuente](https://www.dafont.com/es/minitel.font?text=console) [font.s](font.s) (@shirosweets): - [ ] doAm (crea una `a` en minúscula) From c684f9dbed851dc098ef3b4aa65bd96bec7d9ef4 Mon Sep 17 00:00:00 2001 From: diegogimenez04 Date: Sat, 12 Jun 2021 13:10:10 -0300 Subject: [PATCH 21/47] Terminadas las letras. Empezando con animacion --- app.s | 19 +++++ draw.s | 4 ++ font.s | 215 +++++++++++++++++++++++++++++---------------------------- 3 files changed, 133 insertions(+), 105 deletions(-) diff --git a/app.s b/app.s index 1e5a2bb..e990e6e 100644 --- a/app.s +++ b/app.s @@ -124,6 +124,25 @@ main: bl doDiego ret +/* + bl delay + bl cleanScreen + add x21, x21, 100 + mov x13, 255 // R + mov x14, 0 // G + mov x15, 0 // B + bl setColour // R+G+B = Gris + bl doDiego + + bl delay + bl cleanScreen + add x21, x21, 100 + mov x13, 255 // R + mov x14, 0 // G + mov x15, 0 // B + bl setColour // R+G+B = Gris + bl doTriangleUp + */ // Dibujamos un círculo // Medio es 320 x 240 // FIXME Checkear diff --git a/draw.s b/draw.s index e17eb3a..322b258 100644 --- a/draw.s +++ b/draw.s @@ -3,6 +3,10 @@ //.include "app.s" +.globl doCompuVentana +doCompuVentana: + + .globl vertLine // NOTE Vertilcal line with a height vertLine: diff --git a/font.s b/font.s index 964414f..d30b9b4 100644 --- a/font.s +++ b/font.s @@ -86,7 +86,7 @@ doE: // REVIEW Done stur x22, [sp, #16] stur x23, [sp, #24] - mov x23, 10 + mov x23, 11 add x22, x22, 10 sub x21, x21, 5 bl doHorizontalLine @@ -100,10 +100,10 @@ doE: // REVIEW Done bl doHorizontalLine sub x21, x21, 1 add x22, x22, 1 - mov x23, 14 + mov x23, 16 bl vertLine add x21, x21, 1 - add x22, x22, 15 + add x22, x22, 17 mov x23, 14 bl doHorizontalLine @@ -207,19 +207,32 @@ doI: //REVIEW Done .globl doO // NOTE o -doO: +doO: //REVIEW Done // @Diego + // Args + // x21 x + // x22 y + // w18 color sub sp, sp, 24 stur x22, [sp, #16] stur x21, [sp, #8] stur lr, [sp] - bl doCircle + add x21, x21, 1 + mov x23, 10 + bl doHorizontalLine + sub x21, x21, 1 + add x22, x22, 1 + bl vertLine + add x21, x21, 11 + bl vertLine + sub x21, x21, 10 + add x22, x22, 11 + bl doHorizontalLine -endO: - stur lr, [sp] - stur x21, [sp, #8] - stur x22, [sp, #16] + ldur lr, [sp] + ldur x21, [sp, #8] + ldur x22, [sp, #16] add sp, sp, 24 ret @@ -341,10 +354,27 @@ doM: // REVIEW Done stur lr, [sp] stur x21, [sp, #8] stur x22, [sp, #16] - mov x16, x21 - mov x12, x22 - mov x9, 0 + mov x23, 16 + bl vertLine + + mov x23, 5 + bl doHorizontalLine + add x21, x21, 6 + add x22, x22, 1 + mov x23, 15 + bl vertLine + add x21, x21, 1 + sub x22, x22, 1 + mov x23, 5 + bl doHorizontalLine + add x21, x21, 6 + add x22, x22, 1 + mov x23, 15 + bl vertLine + + +/* doPalo: add x12, x12, 1 bl drawPixel @@ -381,6 +411,7 @@ doPaloD: b.eq endM add x9, x9, 1 b doPaloD +*/ endM: ldur x22, [sp, #16] @@ -463,7 +494,7 @@ endZ: ret .globl doGm -// NOTE G +// NOTE G mayus doGm: //REVIEW Done // @Diego // Args @@ -478,79 +509,34 @@ doGm: //REVIEW Done stur x18, [sp, 16] stur x23, [sp, 8] stur lr, [sp] - mov x16, x21 - mov x12, x22 - mov x23, 3 + mov x23, 11 mov x9, 0 bl doHorizontalLine add x16, x16, 3 -doGmStart: - bl drawPixel - add x12, x12, 1 - add x16, x16, 1 - cmp x9, 5 - b.eq preDoGMDiag - add x9, x9, 1 - b doGmStart - -preDoGMDiag: - mov x9, 0 - mov x16, x21 - mov x12, x22 - -doGMDiag: - bl drawPixel - add x12, x12, 1 - sub x16, x16, 1 - cmp x9, 5 - b.eq preDoGMDiagR - add x9, x9, 1 - b doGMDiag - -preDoGMDiagR: - mov x21, x16 - mov x22, x12 - mov x23, 10 + add x21, x21, 11 + add x22, x22, 1 + mov x23, 3 bl vertLine -doGMDiagR: - bl drawPixel - add x12, x12, 1 - add x16, x16, 1 - cmp x9, 0 - b.eq doGMbot - sub x9, x9, 1 - b doGMDiagR + sub x21, x21, 12 + mov x23, 18 + bl vertLine -doGMbot: - mov x21, x16 - mov x22, x12 - mov x23, 5 + add x21, x21, 1 + add x22, x22, 19 + mov x23, 10 bl doHorizontalLine - add x16, x16, 5 - mov x9, 0 -doGMdiagUR: - bl drawPixel - add x16, x16, 1 - sub x12, x12, 1 - cmp x9, 5 - b.eq doGend - add x9, x9, 1 - b doGMdiagUR + add x21, x21, 11 + sub x22, x22, 8 + mov x23, 7 + bl vertLine -doGend: - mov x22, x12 - mov x21, x16 - sub x22, x22, 5 + sub x21, x21, 5 mov x23, 5 - bl vertLine - sub x21, x21, 10 - mov x23, 10 bl doHorizontalLine -endGm: ldur x21, [sp, 32] ldur x22, [sp, 24] ldur x18, [sp, 16] @@ -561,7 +547,7 @@ endGm: .globl doG // NOTE g -doG: +doG: //REVIEW Done // @Diego // Args // x21 x inicial @@ -573,26 +559,34 @@ doG: stur x18, [sp, 16] stur x23, [sp, 8] stur lr, [sp] - mov x16, x21 - mov x12, x22 - mov x23, 3 - mov x9, 0 - bl doCircle - add x16, x16, x23 - add x16, x16, x23 - add x12, x12, x23 - add x12, x12, 1 -doGDiag: - bl drawPixel - add x12, x12, 1 - sub x16, x16, 1 - cmp x9, 10 - b.eq endG - add x9, x9, 1 - b doGDiag + mov x23, 10 + bl doHorizontalLine + sub x21, x21, 1 + add x22, x22, 1 + mov x23, 5 + bl vertLine + + add x21, x21, 1 + add x22, x22, 5 + mov x23, 10 + bl doHorizontalLine + + add x21, x21, 10 + sub x22, x22, 5 + mov x23, 14 + bl vertLine + + add x22, x22, 15 + sub x21, x21, 9 + mov x23, 9 + bl doHorizontalLine + + sub x21, x21, 1 + sub x22, x22, 5 + mov x23, 4 + bl vertLine -endG: ldur x21, [sp, 32] ldur x22, [sp, 24] ldur x18, [sp, 16] @@ -619,27 +613,38 @@ doDiego: bl doDm - add x21, x21, 50 + add x21, x21, 25 bl doI - add x21, x21, 50 + add x21, x21, 25 bl doE - add x21, x21, 50 + add x21, x21, 20 bl doGm - add x21, x21, 50 - add x22, x22, 10 - mov x23, 10 + add x21, x21, 20 + add x22, x22, 8 bl doO - // bl doGm - // bl doI - // bl doM - // bl doE - // bl doN - // bl doE - // bl doZ + sub x22, x22, 8 + add x21, x21, 50 + bl doGm + add x21, x21, 20 + bl doI + add x21, x21, 10 + add x22, x22, 5 + bl doM + sub x22, x22, 5 + add x21, x21, 30 + bl doE + add x21, x21, 20 + bl doN + add x21, x21, 20 + bl doE + add x21, x21, 20 + bl doZ + +endDiego: ldur lr, [sp] ldur w18, [sp, 8] ldur x22, [sp, 16] From e5ec6541c28d631ced221c9e5a9eb2d8502377c3 Mon Sep 17 00:00:00 2001 From: diegogimenez04 Date: Sat, 12 Jun 2021 15:16:39 -0300 Subject: [PATCH 22/47] Pantalla de computadora terminada --- app.s | 3 +- draw.s | 177 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 171 insertions(+), 9 deletions(-) diff --git a/app.s b/app.s index e990e6e..50b4168 100644 --- a/app.s +++ b/app.s @@ -121,7 +121,8 @@ main: mov x21, 100 mov x22, 100 - bl doDiego + bl doCompuVentana + ret /* diff --git a/draw.s b/draw.s index 322b258..7a1c5ed 100644 --- a/draw.s +++ b/draw.s @@ -5,7 +5,160 @@ .globl doCompuVentana doCompuVentana: - + sub sp, sp, 56 + stur x15, [sp, 48] + stur x14, [sp, 40] + stur x13, [sp, 32] + stur x21, [sp, 24] + stur x22, [sp, 16] + stur w18, [sp, 8] + stur lr, [sp] + + // Fondo + mov x13, 110 + mov x14, 50 + mov x15, 50 + bl setColour + mov x21, 0 + mov x22, 0 + mov x23, 640 + mov x24, 480 + bl doRectangle + + // Marco + mov x13, 0 + mov x14, 0 + mov x15, 0 + bl setColour + mov x21, 100 + mov x22, 50 + mov x23, 450 + mov x24, 300 + bl doRectangle + + // Pie de monitor + add x21, x21, 150 + add x22, x22, 300 + mov x23, 150 + mov x24, 50 + bl doRectangle + + // Base del monitor + sub x21, x21, 100 + add x22, x22, 50 + mov x23, 350 + mov x24, 10 + bl doRectangle + + // Pantalla "real" + movz w18, 0xe6, lsl 16 + movk w18, 0xf9af, lsl 0 + mov x21, 110 + mov x22, 60 + mov x23, 430 + mov x24, 280 + bl doRectangle + + // Boton de play + movz w18, 0x0d, lsl 16 + movk w18, 0x0630, lsl 0 + mov x21, 270 + mov x22, 150 + mov x23, 100 + mov x24, 100 + bl doRectangle + + // Triangulo del medio del boton + movz w18, 0x8b, lsl 16 + movk w18, 0xbeb2, lsl 0 + mov x21, 310 + mov x22, 165 + mov x23, 30 + mov x24, 80 + bl triangDer + + // Boton de salida + movz w18, 0x38, lsl 16 + movk w18, 0x4e77, lsl 0 + mov x21, 520 + mov x22, 60 + mov x23, 20 + mov x24, 20 + bl doRectangle + + // Boton de salida + movz w18, 0x18, lsl 16 + movk w18, 0x314f, lsl 0 + mov x21, 500 + mov x22, 60 + mov x23, 20 + mov x24, 20 + bl doRectangle + + ldur lr, [sp] + ldur w18, [sp, 8] + ldur x22, [sp, 16] + ldur x21, [sp, 24] + ldur x13, [sp, 32] + ldur x14, [sp, 40] + ldur x15, [sp, 48] + add sp, sp, 56 + ret + +.globl triangDer +// NOTE Triangulo apuntando a la derecha +triangDer: + // @Diego + // Args + // x21 x + // x22 y + // x23 w (cantidad de figuras) + sub sp, sp, 32 + stur x21, [sp, 24] + stur x22, [sp, 16] + stur x23, [sp, 8] + stur lr, [sp] + mov x16, x21 + mov x12, x22 + mov x9, 0 + +triangDerLoop: + bl drawPixel + add x16, x16, 1 + add x12, x12, 1 + cmp x9, x23 + b.eq triangDerBack + add x9, x9, 1 + b triangDerLoop + +triangDerBack: + bl drawPixel + sub x16, x16, 1 + add x12, x12, 1 + cmp x9, 0 + b.eq cmpTriang + sub x9, x9, 1 + b triangDerBack + +cmpTriang: + cmp x23, 0 + b.eq preEndTriangDer + sub x23, x23, 1 + add x22, x22, 1 + mov x12, x22 + b triangDerLoop + +preEndTriangDer: + ldur x23, [sp, 8] + add x23, x23, 2 + bl vertLine +endTriangDer: + ldur lr, [sp] + ldur x23, [sp, 8] + ldur x22, [sp, 16] + ldur x21, [sp, 24] + add sp, sp, 32 + ret .globl vertLine // NOTE Vertilcal line with a height @@ -179,16 +332,20 @@ doRectangle: // alto x largo// // x22 y2 lugar dónde empiezo a dibujar la figura // x23 w largo en pixeles // x24 h alto en pixeles - // x18 colour + // w18 colour // Used // doHorizontalLine // drawPixel: setPixel x16 x, x12 y // x9 posición inicial de x // x10 posición inicial de y - sub sp, sp, #16 // Reservamos 2 registros de memoria - stur x30, [sp, #8] // Guardamos el return pointer en memoria (8 direcciones de memoria = 1 registro de 64bits) - stur x5, [sp, #0] // Guardamos el x5 en memoria (8 direcciones de memoria = 1 registro de 64bits) + sub sp, sp, #48 // Reservamos 2 registros de memoria + stur x21, [sp, 40] + stur x22, [sp, 32] + stur x23, [sp, 24] + stur x24, [sp, 16] + stur lr, [sp, 8] // Guardamos el return pointer en memoria (8 direcciones de memoria = 1 registro de 64bits) + stur x5, [sp] // Guardamos el x5 en memoria (8 direcciones de memoria = 1 registro de 64bits) mov x5, x22 // x5 fila inicial @@ -201,9 +358,13 @@ rectangleLoop: // Se encarga de cambiar la fila b rectangleLoop endRectangule: - ldur x5, [sp, #0] // Restauramos el x5 original - ldur x30, [sp, #8] // Guardamos el return pointer en memoria - add sp, sp, #16 // Liberamos la memoria (movemos el sp "más arriba") + ldur x5, [sp] + ldur lr, [sp, 8] // Cargamos el return pointer en memoria (8 direcciones de memoria = 1 regildro de 64bits) + ldur x24, [sp, 16] + ldur x23, [sp, 24] + ldur x22, [sp, 32] + ldur x21, [sp, 40] + add sp, sp, 48 // Reservamos 2 registros de memoria ret .globl doCircle From a89fbccaa464c41e90f0190af48c2ded907fc983 Mon Sep 17 00:00:00 2001 From: diegogimenez04 Date: Sat, 12 Jun 2021 16:17:36 -0300 Subject: [PATCH 23/47] Fix FrameBuffer --- animations.s | 2 +- app.s | 11 +++++----- draw.s | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++ start.s | 3 +++ 4 files changed, 70 insertions(+), 6 deletions(-) diff --git a/animations.s b/animations.s index 8b7f026..ed30e4c 100644 --- a/animations.s +++ b/animations.s @@ -8,7 +8,7 @@ delay: add x8, xzr, xzr // counter = 0 add x8, x8, #0xFFF // counter = 0xF...F (un numero enorme) - lsl x8, x8, #9 // 3th = * 2^~10 (slow = 1s) // * 2^~9 (medium = ~0,3s) + lsl x8, x8, #12 // 3th = * 2^~10 (slow = 1s) // * 2^~9 (medium = ~0,3s) delayloop: cbz x8, delayEnd diff --git a/app.s b/app.s index 50b4168..5853297 100644 --- a/app.s +++ b/app.s @@ -23,6 +23,7 @@ //.include "animations.s" //.include "screen_animations.s" +//.include "start.s" .globl main .globl setColour // https://stackoverflow.com/questions/54918639/linking-2-object-files .globl drawPixel @@ -31,6 +32,7 @@ main: //break: mov x20, x0 // X0 Direccion base del framebuffer + adr x29, PreFrameBuffer bl cleanScreen // Limpiamos la pantalla mov x13, 96 // R mov x14, 96 // G @@ -118,11 +120,10 @@ main: mov x15, 8 // B bl setColour // R+G+B = Rojo //bl doSquare - - mov x21, 100 - mov x22, 100 - bl doCompuVentana - + bl cleanScreen + mov x21, 200 + mov x22, 250 + bl doAnimacionInicial ret /* diff --git a/draw.s b/draw.s index 7a1c5ed..dd1776c 100644 --- a/draw.s +++ b/draw.s @@ -3,6 +3,66 @@ //.include "app.s" +.globl doAnimacionInicial +doAnimacionInicial: + sub sp, sp, 48 + stur x25, [sp, 40] + stur x24, [sp, 32] + stur x23, [sp, 24] + stur x21, [sp, 16] + stur x22, [sp, 8] + stur lr, [sp] + mov x25, 0 + +loopDelay: + bl delay + add x21, x21, 10 + sub x22, x22, 5 + bl doCompuVentana + bl doMouse + cmp x25, 10 + b.eq endAnimacion + add x25, x25, 1 + b loopDelay + +endAnimacion: + ldur lr, [sp] + ldur x22, [sp, 8] + ldur x21, [sp, 16] + ldur x23, [sp, 24] + ldur x24, [sp, 32] + ldur x25, [sp, 40] + add sp, sp, 48 + ret + +.globl doMouse +doMouse: + // @Diego + // Args + // x21 x + // x22 y + sub sp, sp, 40 + stur x24, [sp, 32] + stur x23, [sp, 24] + stur x21, [sp, 16] + stur x22, [sp, 8] + stur lr, [sp] + + mov x23, 3 + mov x24, 5 + bl doTriangleUp + sub x21, x21, 4 + mov x23, 9 + bl doRectangle + + ldur lr, [sp] + ldur x22, [sp, 8] + ldur x21, [sp, 16] + ldur x23, [sp, 24] + ldur x24, [sp, 32] + add sp, sp, 24 + ret + .globl doCompuVentana doCompuVentana: sub sp, sp, 56 diff --git a/start.s b/start.s index 3b59aae..2e5cc67 100644 --- a/start.s +++ b/start.s @@ -1,6 +1,9 @@ .text .org 0x80000 +.globl PreFrameBuffer +.data +PreFrameBuffer: .skip 4*640*480 // Setup Frame Buffer .equ SCREEN_WIDTH, 640 .equ SCREEN_HEIGH, 480 From c6eae795b10ff2514e1012043c88248dc18a95ff Mon Sep 17 00:00:00 2001 From: diegogimenez04 Date: Sat, 12 Jun 2021 17:32:53 -0300 Subject: [PATCH 24/47] No parpadea mas --- app.s | 133 +++++++++++++++++++------------------------------------- draw.s | 17 +++----- font.s | 8 ++-- start.s | 2 +- 4 files changed, 56 insertions(+), 104 deletions(-) diff --git a/app.s b/app.s index 5853297..1f984c9 100644 --- a/app.s +++ b/app.s @@ -1,6 +1,11 @@ //.ifndef _APP_S //.equ _APP_S, 1 +.equ SCREEN_BYTES, 4*640*480 +.equ SCREEN_PIXELS, 640*480 +.data + TOTAL_PIXELS: .dword SCREEN_PIXELS + .equ SCREEN_WIDTH, 640 .equ SCREEN_HEIGH, 480 .equ BITS_PER_PIXEL, 32 @@ -33,82 +38,6 @@ main: //break: mov x20, x0 // X0 Direccion base del framebuffer adr x29, PreFrameBuffer - bl cleanScreen // Limpiamos la pantalla - mov x13, 96 // R - mov x14, 96 // G - mov x15, 96 // B - bl setColour // R+G+B = Gris - //bl paintScreen // NOTE OK - - //bl circleTest - - // Dibujamos un pixel azul al medio de la pantalla - mov x16, 320 // x s0etPixel - mov x12, 240 // y setPixel - bl setPixel // Pixel a pintar - mov x13, 17 // R - mov x14, 88 // G - mov x15, 253 // B - bl setColour // R+G+B = Azul - stur x18, [x0] - - // Dibujamos un pixel verde - mov x16, 230 // x setPixel - mov x12, 340 // y setPixel - bl setPixel // Pixel a pintar - mov x13, 17 // R - mov x14, 253 // G - mov x15, 64 // B - bl setColour // Verde - //stur x18, [x0] - - // Dibujamos un pixel amarillo - mov x16, 200 // x setPixel - mov x12, 300 // y setPixel - bl setPixel // Pixel a pintar - mov x13, 255 // R - mov x14, 255 // G - mov x15, 0 // B - bl setColour // Amarillo - //stur x18, [x0] - - // Pintamos los límites de la pantalla - mov x13, 255 // R - mov x14, 255 // G - mov x15, 255 // B - bl setColour // Blanco - //bl drawBorder // TODO - - // NOTE Línea horizontal - mov x21, 320 // xo - mov x22, 240 // yo - mov x23, 100 // w - mov x13, 255 // R - mov x14, 255 // G - mov x15, 0 // B - bl setColour // R+G+B = Amarillo - bl doHorizontalLine - - // Pintamos un rectágulo en el medio de la pantalla - mov x21, 320 // x2 - mov x22, 240 // y2 - mov x23, 20 // w largo de pixeles - mov x24, 40 // h alto de pixeles - mov x13, 255 // R - mov x14, 255 // G - mov x15, 255 // B - bl setColour // R+G+B = Blanco - bl doRectangle - - // Pintamos el origen del rectágunlo - mov x16, 320 // x s0etPixel - mov x12, 240 // y setPixel - bl setPixel // Pixel a pintar - mov x13, 255 // R - mov x14, 0 // G - mov x15, 8 // B - bl setColour // R+G+B = Rojo - stur x18, [x0] // Lo pinto bl cleanScreen // Pintamos un cuadrado en el medio de la pantalla @@ -262,6 +191,7 @@ return: ret // TODO revisar +/* drawBorder: // Args // x18 colour @@ -326,7 +256,7 @@ endBorder: ldur lr, [sp] add sp, sp, #8 ret - + */ /* endDraw: // TODO @@ -340,6 +270,7 @@ borderEnd: */ // NOTE Circle Test +/* circleTest: sub sp, sp, #8 stur x30, [sp, #0] // Guardamos el return pointer en memoria @@ -358,27 +289,51 @@ circleTest: ldur x30, [sp, #0] // Guardamos el return pointer en memoria ret add sp, sp, #8 // Liberamos memoria ret - + */ // NOTE drawPixel drawPixel: // Args: y=x12 -- x=x16 -- colour=x18 - sub sp, sp, #8 + sub sp, sp, #16 + stur x29, [sp, 8] stur x30, [sp, #0] bl setPixel - stur w18, [x0] // stur xN guarda 64bits, y stur wN guarda medio registro (32bits) IMPORTANTE!!!!!!!!! + stur w18, [x29] // stur xN guarda 64bits, y stur wN guarda medio registro (32bits) IMPORTANTE!!!!!!!!! ldur x30, [sp, #0] - add sp, sp, #8 + ldur x29, [sp, 8] + add sp, sp, #16 ret // NOTE setPixel setPixel: // Return: x0 Pixel a pintar - // Args: y=x12 -- x=x16 + // Args: y=x12 -- x=x16 mov x8, SCREEN_WIDTH - mul x0, x12, x8 // y * WIDTH - add x0, x0, x16 // + x - lsl x0, x0, 2 // *4 - add x0, x20, x0 // Pixel a pintar + mul x17, x12, x8 // y * WIDTH + add x17, x17, x16 // + x + lsl x17, x17, 2 // *4 + add x29, x29, x17 // Pixel a pintar + ret + +.globl drawUpdate +drawUpdate: + // x29 PreFrameBuffer + // x20 FrameBuffer + mov x8, x20 + mov x7, x29 + mov x9, 0 + ldr x10, TOTAL_PIXELS + +updateLoop: + ldr w6, [x7] + str w6, [x8] + add x8, x8, 4 + add x7, x7, 4 + cmp x9, x10 + b.eq endUpdate + add x9, x9, 1 + b updateLoop + +endUpdate: ret // NOTE setColour @@ -494,15 +449,15 @@ cleanScreen: // Pinta toda la pantalla de negro paintScreen: // 320w 240h -> 76800 + 240 // Return -> nada // Args: x18 Colour - mov x0, x20 // Origen del frameBuffer + adr x29, PreFrameBuffer // Origen del frameBuffer mov x8, SCREEN_WIDTH mov x9, SCREEN_HEIGH mul x8, x8, x9 // x8 contador de pixeles a pintar // paintScreenLoop... paintScreenLoop: - stur w18, [x0] // Set color of pixel N - add x0, x0, 4 // Next pixel + stur w18, [x29] // Set color of pixel N + add x29, x29, 4 // Next pixel sub x8, x8, 1 // decrement pixel counter cbnz x8, paintScreenLoop // If not end row jump ret diff --git a/draw.s b/draw.s index dd1776c..bcbd84e 100644 --- a/draw.s +++ b/draw.s @@ -15,7 +15,9 @@ doAnimacionInicial: mov x25, 0 loopDelay: + bl drawUpdate bl delay + bl cleanScreen add x21, x21, 10 sub x22, x22, 5 bl doCompuVentana @@ -561,8 +563,7 @@ doTriangleUp: rectAr: // Dibuja la diagonal hacia arriba add x16, x16, #1 // Me muevo al siguiente sub x12, x12, #1 // Me muevo arriba - bl setPixel // Calculo el pixel - stur w18, [x0] // Lo pinto + bl drawPixel cmp x9, x19 // Comparo mi contador con mi cantidad de pixeles b.eq rectBaj // Si llegue a la cantidad bajo add x9, x9, #1 // Si no le sumo 1 @@ -571,8 +572,7 @@ rectAr: // Dibuja la diagonal hacia arriba rectBaj: // Dibuja la diagonal hacia abajo add x16, x16, #1 // Me muevo al siguiente add x12, x12, #1 // Bajo 1 unidad - bl setPixel // Calculo el pixel - stur w18, [x0] // Lo pinto + bl drawPixel cmp x9, #0 // Comparo el contador a w con 0 b.eq preRectAr // Si llegue a la "base" arranco de nuevo desde 1 posicion menos sub x9, x9, #1 // Si no, le resto 1 al contador @@ -614,8 +614,7 @@ doTriangleDown: rectArDown: // Dibuja la diagonal hacia arriba add x16, x16, #1 // Me muevo al siguiente add x12, x12, #1 // Me muevo arriba - bl setPixel // Calculo el pixel - stur w18, [x0] // Lo pinto + bl drawPixel cmp x9, x19 // Comparo mi contador con mi cantidad de pixeles b.eq rectBajDown // Si llegue a la cantidad bajo add x9, x9, #1 // Si no le sumo 1 @@ -665,8 +664,7 @@ doPiramide: pirAr: // Dibuja la diagonal hacia arriba sub x16, x16, #1 // Me muevo atras sub x12, x12, #1 // Me muevo arriba - bl setPixel // Calculo el pixel - stur w18, [x0] // Lo pinto + bl drawPixel cmp x9, x19 // Comparo mi contador con mi cantidad de pixeles b.eq pirBaj // Si llegue a la cantidad bajo add x9, x9, #1 // Si no le sumo 1 al contador @@ -675,8 +673,7 @@ pirAr: // Dibuja la diagonal hacia arriba pirBaj: // Dibuja la diagonal hacia abajo sub x16, x16, #1 // Me muevo atras add x12, x12, #1 // Bajo 1 unidad - bl setPixel // Calculo el pixel - stur w18, [x0] // Lo pinto + bl drawPixel cmp x9, #0 // Comparo el contador a w con 0 b.eq prepirAr // Si llegue a la "base" arranco de nuevo desde 1 posicion menos sub x9, x9, #1 // Si no, le resto 1 al contador diff --git a/font.s b/font.s index d30b9b4..61355fe 100644 --- a/font.s +++ b/font.s @@ -434,10 +434,10 @@ doVm: // x0 // Pixel superior izquierdo mov x8, SCREEN_WIDTH - mul x0, x12, x8 // y * WIDTH - add x0, x0, x16 // + x - lsl x0, x0, 2 // *4 - add x0, x20, x0 // Pixel inicial a pintar + mul x29, x12, x8 // y * WIDTH + add x29, x29, x16 // + x + lsl x29, x29, 2 // *4 + add x29, x20, x29 // Pixel inicial a pintar // TODO diff --git a/start.s b/start.s index 2e5cc67..a1cf2fc 100644 --- a/start.s +++ b/start.s @@ -3,7 +3,7 @@ .globl PreFrameBuffer .data -PreFrameBuffer: .skip 4*640*480 + PreFrameBuffer: .skip 4*640*480 // Setup Frame Buffer .equ SCREEN_WIDTH, 640 .equ SCREEN_HEIGH, 480 From 784262b4e85199ee828d365a7b9721c1bfaf8b98 Mon Sep 17 00:00:00 2001 From: diegogimenez04 Date: Sat, 12 Jun 2021 17:43:50 -0300 Subject: [PATCH 25/47] NO TOCAR REGISTRO X28 PreFrameBuffer ahi --- app.s | 20 ++++++++++---------- draw.s | 17 ++++++++++------- font.s | 8 ++++---- 3 files changed, 24 insertions(+), 21 deletions(-) diff --git a/app.s b/app.s index 1f984c9..ecde66a 100644 --- a/app.s +++ b/app.s @@ -37,7 +37,7 @@ main: //break: mov x20, x0 // X0 Direccion base del framebuffer - adr x29, PreFrameBuffer + adr x28, PreFrameBuffer bl cleanScreen // Pintamos un cuadrado en el medio de la pantalla @@ -294,12 +294,12 @@ circleTest: drawPixel: // Args: y=x12 -- x=x16 -- colour=x18 sub sp, sp, #16 - stur x29, [sp, 8] + stur x28, [sp, 8] stur x30, [sp, #0] bl setPixel - stur w18, [x29] // stur xN guarda 64bits, y stur wN guarda medio registro (32bits) IMPORTANTE!!!!!!!!! + stur w18, [x28] // stur xN guarda 64bits, y stur wN guarda medio registro (32bits) IMPORTANTE!!!!!!!!! ldur x30, [sp, #0] - ldur x29, [sp, 8] + ldur x28, [sp, 8] add sp, sp, #16 ret @@ -311,15 +311,15 @@ setPixel: mul x17, x12, x8 // y * WIDTH add x17, x17, x16 // + x lsl x17, x17, 2 // *4 - add x29, x29, x17 // Pixel a pintar + add x28, x28, x17 // Pixel a pintar ret .globl drawUpdate drawUpdate: - // x29 PreFrameBuffer + // x28 PreFrameBuffer // x20 FrameBuffer mov x8, x20 - mov x7, x29 + mov x7, x28 mov x9, 0 ldr x10, TOTAL_PIXELS @@ -449,15 +449,15 @@ cleanScreen: // Pinta toda la pantalla de negro paintScreen: // 320w 240h -> 76800 + 240 // Return -> nada // Args: x18 Colour - adr x29, PreFrameBuffer // Origen del frameBuffer + adr x28, PreFrameBuffer // Origen del frameBuffer mov x8, SCREEN_WIDTH mov x9, SCREEN_HEIGH mul x8, x8, x9 // x8 contador de pixeles a pintar // paintScreenLoop... paintScreenLoop: - stur w18, [x29] // Set color of pixel N - add x29, x29, 4 // Next pixel + stur w18, [x28] // Set color of pixel N + add x28, x28, 4 // Next pixel sub x8, x8, 1 // decrement pixel counter cbnz x8, paintScreenLoop // If not end row jump ret diff --git a/draw.s b/draw.s index bcbd84e..a3fef4c 100644 --- a/draw.s +++ b/draw.s @@ -23,17 +23,20 @@ loopDelay: bl doCompuVentana bl doMouse cmp x25, 10 - b.eq endAnimacion + b.eq loopDelay2 add x25, x25, 1 b loopDelay +loopDelay2: + ret + endAnimacion: - ldur lr, [sp] - ldur x22, [sp, 8] - ldur x21, [sp, 16] - ldur x23, [sp, 24] - ldur x24, [sp, 32] - ldur x25, [sp, 40] + ldr lr, [sp] + ldr x22, [sp, 8] + ldr x21, [sp, 16] + ldr x23, [sp, 24] + ldr x24, [sp, 32] + ldr x25, [sp, 40] add sp, sp, 48 ret diff --git a/font.s b/font.s index 61355fe..43a0f94 100644 --- a/font.s +++ b/font.s @@ -434,10 +434,10 @@ doVm: // x0 // Pixel superior izquierdo mov x8, SCREEN_WIDTH - mul x29, x12, x8 // y * WIDTH - add x29, x29, x16 // + x - lsl x29, x29, 2 // *4 - add x29, x20, x29 // Pixel inicial a pintar + mul x28, x12, x8 // y * WIDTH + add x28, x28, x16 // + x + lsl x28, x28, 2 // *4 + add x28, x20, x28 // Pixel inicial a pintar // TODO From af1599c34979747480d62a1447d7eda9090fae47 Mon Sep 17 00:00:00 2001 From: diegogimenez04 Date: Sat, 12 Jun 2021 17:45:22 -0300 Subject: [PATCH 26/47] NO TOCAR REGISTRO X28 PreFrameBuffer ahi --- draw.s | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/draw.s b/draw.s index a3fef4c..a0d6685 100644 --- a/draw.s +++ b/draw.s @@ -447,7 +447,8 @@ doCircle: // Mid-Point Circle Drawing Algorithm // // x25 x // x26 y // x28 P - sub sp, sp, #8 + sub sp, sp, #16 + stur x28, [sp, 8] stur x30, [sp, #0] // Guardamos el return pointer en memoria mov x25, x23 // x = r mov x26, xzr // y = 0 (xzr = 0) @@ -542,7 +543,8 @@ cirif2: // if (x < y) circleEnd: ldur x30, [sp, #0] // Guardamos el return pointer en memoria ret - add sp, sp, #8 + ldur x28, [sp, 8] + add sp, sp, #16 ret .globl doTriangleUp From d1d200bc83d7cd5d7b070a560b126922edb28d03 Mon Sep 17 00:00:00 2001 From: diegogimenez04 Date: Sat, 12 Jun 2021 19:33:10 -0300 Subject: [PATCH 27/47] Animacion breve --- animations.s | 4 +- app.s | 64 +++++++++++++--------- draw.s | 149 ++++++++++++++++++++++++++++++++++++--------------- font.s | 3 +- todo.md | 10 ++-- variables.md | 2 +- 6 files changed, 155 insertions(+), 77 deletions(-) diff --git a/animations.s b/animations.s index ed30e4c..c95b9fd 100644 --- a/animations.s +++ b/animations.s @@ -8,7 +8,7 @@ delay: add x8, xzr, xzr // counter = 0 add x8, x8, #0xFFF // counter = 0xF...F (un numero enorme) - lsl x8, x8, #12 // 3th = * 2^~10 (slow = 1s) // * 2^~9 (medium = ~0,3s) + lsl x8, x8, #8 // 3th = * 2^~10 (slow = 1s) // * 2^~9 (medium = ~0,3s) delayloop: cbz x8, delayEnd @@ -21,7 +21,7 @@ delayEnd: ret .globl lineAnimation -// NOTE lineAnimation +// FIXME lineAnimation lineAnimation: sub sp, sp, #8 // Guardamos 1 lugar del stack stur x30, [sp, #0] // Registro 30 para el RET en el stack diff --git a/app.s b/app.s index ecde66a..52ad64c 100644 --- a/app.s +++ b/app.s @@ -294,18 +294,18 @@ circleTest: drawPixel: // Args: y=x12 -- x=x16 -- colour=x18 sub sp, sp, #16 - stur x28, [sp, 8] - stur x30, [sp, #0] + str x28, [sp, 8] + str x30, [sp, #0] bl setPixel - stur w18, [x28] // stur xN guarda 64bits, y stur wN guarda medio registro (32bits) IMPORTANTE!!!!!!!!! - ldur x30, [sp, #0] - ldur x28, [sp, 8] + str w18, [x28] // stur xN guarda 64bits, y stur wN guarda medio registro (32bits) IMPORTANTE!!!!!!!!! + ldr x30, [sp, #0] + ldr x28, [sp, 8] add sp, sp, #16 ret // NOTE setPixel setPixel: - // Return: x0 Pixel a pintar + // Return: x29 Pixel a pintar // Args: y=x12 -- x=x16 mov x8, SCREEN_WIDTH mul x17, x12, x8 // y * WIDTH @@ -318,6 +318,12 @@ setPixel: drawUpdate: // x28 PreFrameBuffer // x20 FrameBuffer + sub sp, sp, 40 + str x8, [sp, 32] + str x7, [sp, 24] + str x9, [sp, 16] + str x10, [sp, 8] + str lr, [sp] mov x8, x20 mov x7, x28 mov x9, 0 @@ -334,6 +340,12 @@ updateLoop: b updateLoop endUpdate: + ldr x8, [sp, 32] + ldr x7, [sp, 24] + ldr x9, [sp, 16] + ldr x10, [sp, 8] + ldr lr, [sp] + add sp, sp, 40 ret // NOTE setColour @@ -346,16 +358,16 @@ setColour: // x15 b // 24 bits sub sp, sp, #16 - stur x13, [sp, #8] - stur x14, [sp, #0] + str x13, [sp, #8] + str x14, [sp, #0] lsl x13, x13, 16 // Movemos 16 bits lsl x14, x14, 8 // Movemos 8 bits add x18, x13, x14 // R+G add x18, x18, x15 // RG+B - ldur x13, [sp, #8] - ldur x14, [sp, #0] + ldr x13, [sp, #8] + ldr x14, [sp, #0] add sp, sp, #16 ret @@ -365,8 +377,8 @@ verticalLine: // x21 x // x18 Colour sub sp, sp, #16 // Guardamos 2 lugares del stack - stur x30, [sp, #8] // registro 30 para el RET en el stack - stur x1, [sp, #0] // Guardamos en el stack pointer el registro x1 anterior + str x30, [sp, #8] // registro 30 para el RET en el stack + str x1, [sp, #0] // Guardamos en el stack pointer el registro x1 anterior mov x1, SCREEN_HEIGH mov x16, x21 // x = argument mov x12, xzr // y = 0 @@ -380,8 +392,8 @@ verLineLoop: b verLineLoop // Continuamos con el loop verLineEnd: - ldur x1, [sp, #0] // Carga lo que guardó en el stack - ldur x30, [sp, #8] // Cargamos variables anteriores + ldr x1, [sp, #0] // Carga lo que guardó en el stack + ldr x30, [sp, #8] // Cargamos variables anteriores add sp, sp, #16 // Libera el stack ret @@ -396,12 +408,12 @@ doHorizontalLine: // Crea líneas horizontales en la coordenada (xo, po) con w c // drawPixel: setPixel x16 x, x12 y // x18 Colour sub sp, sp, #48 - stur x12, [sp, #40] - stur x16, [sp, #32] - stur x23, [sp, #24] - stur x22, [sp, #16] - stur x21, [sp, #8] - stur x30, [sp, #0] // Guardamos el return pointer en memoria + str x12, [sp, #40] + str x16, [sp, #32] + str x23, [sp, #24] + str x22, [sp, #16] + str x21, [sp, #8] + str x30, [sp, #0] // Guardamos el return pointer en memoria mov x16, x21 // x = xo // horLineLoop... @@ -415,12 +427,12 @@ horLineLoop: b horLineLoop endHorizontalLine: - ldur x30, [sp, #0] // Guardamos el return pointer en memoria - ldur x21, [sp, #8] - ldur x22, [sp, #16] - ldur x23, [sp, #24] - ldur x16, [sp, #32] - ldur x12, [sp, #40] + ldr x30, [sp, #0] // Guardamos el return pointer en memoria + ldr x21, [sp, #8] + ldr x22, [sp, #16] + ldr x23, [sp, #24] + ldr x16, [sp, #32] + ldr x12, [sp, #40] add sp, sp, #48 // Liberamos espacio en memoria ret diff --git a/draw.s b/draw.s index a0d6685..8bd34e8 100644 --- a/draw.s +++ b/draw.s @@ -6,29 +6,33 @@ .globl doAnimacionInicial doAnimacionInicial: sub sp, sp, 48 - stur x25, [sp, 40] - stur x24, [sp, 32] - stur x23, [sp, 24] - stur x21, [sp, 16] - stur x22, [sp, 8] - stur lr, [sp] + str x25, [sp, 40] + str x24, [sp, 32] + str x23, [sp, 24] + str x21, [sp, 16] + str x22, [sp, 8] + str lr, [sp] mov x25, 0 loopDelay: - bl drawUpdate - bl delay - bl cleanScreen - add x21, x21, 10 - sub x22, x22, 5 + bl delay // Retraso + bl cleanScreen // Limpio la pantalla + bl drawUpdate // Actualizo FB bl doCompuVentana + add x21, x21, 6 // + sub x22, x22, 3 // Muevo el mouse bl doMouse - cmp x25, 10 + cmp x25, 19 b.eq loopDelay2 add x25, x25, 1 b loopDelay loopDelay2: - ret + bl delay + bl cleanScreen + bl doComputerBroken + bl drawUpdate + bl cleanScreen endAnimacion: ldr lr, [sp] @@ -40,31 +44,68 @@ endAnimacion: add sp, sp, 48 ret +.globl doComputerBroken +doComputerBroken: + sub sp, sp, 48 + stur x25, [sp, 40] + stur x24, [sp, 32] + stur x23, [sp, 24] + stur x21, [sp, 16] + stur x22, [sp, 8] + stur lr, [sp] + + bl doCompuVentana + bl doMouse + mov x21, 115 + mov x22, 114 + mov x23, 10 + mov x24, 10 + bl doRectangle + add x21, x21, 50 + add x22, x22, 20 + bl doRectangle + add x21, x21, 100 + sub x22, x22, 40 + bl doRectangle + + mov x21, 300 + mov x22, 300 + mov x23, 5 + bl doRectangle + + mov x21, 350 + mov x22, 200 + bl doRectangle + + ldr lr, [sp] + ldr x22, [sp, 8] + ldr x21, [sp, 16] + ldr x23, [sp, 24] + ldr x24, [sp, 32] + ldr x25, [sp, 40] + add sp, sp, 48 + ret + .globl doMouse doMouse: // @Diego // Args // x21 x // x22 y - sub sp, sp, 40 - stur x24, [sp, 32] - stur x23, [sp, 24] - stur x21, [sp, 16] - stur x22, [sp, 8] - stur lr, [sp] + sub sp, sp, 24 + str x24, [sp, 16] + str x23, [sp, 8] + str lr, [sp] mov x23, 3 mov x24, 5 bl doTriangleUp - sub x21, x21, 4 mov x23, 9 bl doRectangle - ldur lr, [sp] - ldur x22, [sp, 8] - ldur x21, [sp, 16] - ldur x23, [sp, 24] - ldur x24, [sp, 32] + ldr lr, [sp] + ldr x23, [sp, 8] + ldr x24, [sp, 16] add sp, sp, 24 ret @@ -76,7 +117,7 @@ doCompuVentana: stur x13, [sp, 32] stur x21, [sp, 24] stur x22, [sp, 16] - stur w18, [sp, 8] + stur x18, [sp, 8] stur lr, [sp] // Fondo @@ -160,6 +201,12 @@ doCompuVentana: mov x24, 20 bl doRectangle + mov x21, 0 + mov x22, 410 + mov x23, 640 + mov x24, 70 + bl doRectangle + ldur lr, [sp] ldur w18, [sp, 8] ldur x22, [sp, 16] @@ -446,14 +493,14 @@ doCircle: // Mid-Point Circle Drawing Algorithm // // Used // x25 x // x26 y - // x28 P + // x27 P sub sp, sp, #16 - stur x28, [sp, 8] + stur x27, [sp, 8] stur x30, [sp, #0] // Guardamos el return pointer en memoria mov x25, x23 // x = r mov x26, xzr // y = 0 (xzr = 0) sub x8, xzr, x23 // x8 = -r - add x28, x8, #1 // P = 1 - r + add x27, x8, #1 // P = 1 - r // Dibujamos las esquinas mov x16, x21 // x16 xd = xc @@ -473,7 +520,7 @@ doCircle: // Mid-Point Circle Drawing Algorithm // doCircleLoop: // While x > y add x26, x26, #1 // Mid-point is inside or on the perimeter - cmp x28, xzr // P <= 0 + cmp x27, xzr // P <= 0 b.le cirif1 // Si P <= 0 entra en el if b cirelse1 // Si no, entra en el else @@ -482,7 +529,7 @@ cirif1: // if (P <= 0) // F(p) = 0 -> the point is on the perimeter lsl x8, x26, #1 // x8 = 2*y add x8, x8, #1 // x8 = 2*y + 1 - add x28, x28, x8 // P = P + 2*y + 1 + add x27, x27, x8 // P = P + 2*y + 1 b cirif2 cirelse1: // Mid-point is outside the perimeter @@ -492,7 +539,7 @@ cirelse1: // Mid-point is outside the perimeter lsl x9, x26, #1 // x9 = 2*y add x8, x8, #1 // x8 = 2*x + 1 sub x9, x9, x8 // x9 = 2*y - (2*x + 1) - add x28, x28, x9 // P = P + 2*y - 2*x + 1 + add x27, x27, x9 // P = P + 2*y - 2*x + 1 // cirif2... cirif2: // if (x < y) @@ -543,7 +590,7 @@ cirif2: // if (x < y) circleEnd: ldur x30, [sp, #0] // Guardamos el return pointer en memoria ret - ldur x28, [sp, 8] + ldur x27, [sp, 8] add sp, sp, #16 ret @@ -557,8 +604,11 @@ doTriangleUp: // x23 w cantidad de píxeles // x18 colour - sub sp, sp, #8 - stur lr, [sp] // Guardo el link register para no pisarlo en la subrutina setPixel + sub sp, sp, #32 + str x23, [sp, 24] + str x22, [sp, 16] + str x21, [sp, 8] + str lr, [sp] // Guardo el link register para no pisarlo en la subrutina setPixel mov x16, x21 // Instancio x16 para dibujar mov x12, x22 // Instancio x12 para setPixel mov x19, x23 // La cantidad de pixeles sera la cantidad de veces que entro al ciclo @@ -593,8 +643,11 @@ preRectAr: // Se fija si itero la cantidad de veces necesarias b rectAr // sigo endTriang: - ldur lr, [sp] - add sp, sp, #8 + ldr lr, [sp] + ldr x21, [sp, 8] + ldr x22, [sp, 16] + ldr x23, [sp, 24] + add sp, sp, #32 ret .globl doTriangleDown @@ -607,7 +660,10 @@ doTriangleDown: // x23 w cantidad de píxeles // w18 colour - sub sp, sp, #8 + sub sp, sp, #32 + stur x23, [sp, 24] + stur x22, [sp, 16] + stur x21, [sp, 8] stur lr, [sp] // Guardo el link register para no pisarlo en la subrutina setPixel mov x16, x21 // Instancio x16 para dibujar mov x12, x22 // Instancio x12 para setPixel @@ -645,8 +701,11 @@ preRectArDown: // Se fija si itero la cantidad de veces necesarias b rectArDown // sigo endTriangDown: - ldur lr, [sp] - add sp, sp, #8 + ldr lr, [sp] + ldr x21, [sp, 8] + ldr x22, [sp, 16] + ldr x23, [sp, 24] + add sp, sp, #32 ret .globl doPiramide @@ -659,7 +718,10 @@ doPiramide: // x23 w cantidad de píxeles // w18 colour - sub sp, sp, #8 + sub sp, sp, #32 + str x23, [sp, 24] + str x22, [sp, 16] + str x21, [sp, 8] stur lr, [sp] // Guardo el link register para no pisarlo en la subrutina setPixel mov x16, x21 // Instancio x16 para dibujar mov x12, x22 // Instancio x12 para setPixel @@ -695,7 +757,10 @@ prepirAr: // Se fija si itero la cantidad de veces necesarias endPir: ldur lr, [sp] - add sp, sp, #8 + ldr x21, [sp, 8] + ldr x22, [sp, 16] + ldr x23, [sp, 24] + add sp, sp, #32 ret //.endif diff --git a/font.s b/font.s index 43a0f94..80914a9 100644 --- a/font.s +++ b/font.s @@ -433,12 +433,13 @@ doVm: // x12 y // x0 // Pixel superior izquierdo +/* mov x8, SCREEN_WIDTH mul x28, x12, x8 // y * WIDTH add x28, x28, x16 // + x lsl x28, x28, 2 // *4 add x28, x20, x28 // Pixel inicial a pintar - + */ // TODO ret diff --git a/todo.md b/todo.md index f8330be..b0194b7 100644 --- a/todo.md +++ b/todo.md @@ -95,11 +95,11 @@ NOTA IMPORTANTE: Tener en cuenta las diferencias existentes entre el set de inst - Crear las siguientes letras con esta [fuente](https://www.dafont.com/es/minitel.font?text=console) y en este archivo [font.s](font.s) (@diegogimenez04): - [x] doDm (crea una `D` en mayúscula) - [x] doO (crea una `o` en minúscula) - - [ ] doE (crea una `e` en minúscula) - - [ ] doI (crea una `i` en minúscula) + - [x] doE (crea una `e` en minúscula) + - [x] doI (crea una `i` en minúscula) - [x] doZ (crea una `z` en minúscula) - - [ ] doM (crea una `m` en minúscula) - - [ ] doG (crea una `g` en minúscula) + - [x] doM (crea una `m` en minúscula) + - [x] doG (crea una `g` en minúscula) - [x] doGm (crea una `G` en mayúscula) - Crear las siguientes letras con esta [fuente](https://www.dafont.com/es/minitel.font?text=console) [font.s](font.s) (@shirosweets): @@ -118,7 +118,7 @@ NOTA IMPORTANTE: Tener en cuenta las diferencias existentes entre el set de inst - [ ] Averiguar por qué corre más rápido al separar archivos. -- [ ] Finalizar una estructura básica del EJ1. +- [x] Finalizar una estructura básica del EJ1. - [ ] Estructura básica del EJ2. diff --git a/variables.md b/variables.md index e52c591..dbe22c2 100644 --- a/variables.md +++ b/variables.md @@ -49,7 +49,7 @@ doCircle(xc = x21, yc = x22, radio=x23, colour=x18) -> None x25 = x x26 = y -x28 = P +x27 = P ``` `xc` - coordenada x del centro From 2123ac75e70489ba665cd624f4239bdb8ea019dd Mon Sep 17 00:00:00 2001 From: Valentina Vispo Date: Sat, 12 Jun 2021 21:24:58 -0300 Subject: [PATCH 28/47] Fix whitespaces --- start.s | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/start.s b/start.s index 3b59aae..d0f6218 100644 --- a/start.s +++ b/start.s @@ -49,8 +49,8 @@ _start: mrs x1, mpidr_el1 // X0 = Multiprocessor Affinity Register (MPIDR) and x1, x1, #3 // X0 = CPU ID (Bits 0..1) cbz x1, StackInit // IF (CPU ID == 0) Branch To Finit else (Core ID 1..3) CoreLoop - // Infinite Loop For Core 1, 2 and 3 -CoreLoop: + // Infinite Loop For Core 1, 2 and 3 +CoreLoop: b CoreLoop StackInit: @@ -61,7 +61,7 @@ StackInit: // clear bss ldr x1, =__bss_start ldr w2, =__bss_size -_StackInit_loop: +_StackInit_loop: cbz w2, FB_Init str xzr, [x1], #8 sub w2, w2, #1 From 38a0b7d1825caee05db6b110f24bac32e19892b1 Mon Sep 17 00:00:00 2001 From: diegogimenez04 Date: Sat, 12 Jun 2021 22:41:57 -0300 Subject: [PATCH 29/47] pepe --- app.s | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app.s b/app.s index 52ad64c..7ac1a5e 100644 --- a/app.s +++ b/app.s @@ -53,6 +53,10 @@ main: mov x21, 200 mov x22, 250 bl doAnimacionInicial + mov x21, #320 // xc x centro + mov x22, #250 // yc y centro + bl doRaven + bl drawUpdate ret /* From abadbe8b0a5552e392ea8280e673258f8555e423 Mon Sep 17 00:00:00 2001 From: Valentina Vispo Date: Sun, 13 Jun 2021 03:32:44 -0300 Subject: [PATCH 30/47] Fix setPixel and drawPixel for use framebuffer with x0 (or nothing) and preFrameBuffer with x28 Minor fixes: - Update todo.md, README.md, and Reorganice files and functions --- .gitignore | 2 + README.md | 8 +- aScreenAnimations.s | 206 +++++++++ animations.s | 51 +-- app.s | 406 +----------------- baseCore.s | 111 +++++ .../Screenshot from 2021-05-28 20-09-07.png | Bin ...tion-mnemonics_integer-class_container.png | Bin .../AArch64/load-store_addressing-modes.png | Bin {assets => docs}/AArch64/register-names.png | Bin .../ARMv8_Reference_Manual.pdf | Bin ..._ VC FrameBuffer en QEMU emulando RPi3.pdf | Bin variables.md => docs/variables.md | 0 draw.s | 169 ++++++-- font.s | 47 +- png/owl_med.png | Bin 0 -> 42889 bytes screen_animations.s | 92 ---- start.s | 50 ++- test.s | 240 +++++++++++ todo.md | 84 +++- owl.s => zowl.s | 1 - raven.s => zraven.s | 1 - 22 files changed, 824 insertions(+), 644 deletions(-) create mode 100644 aScreenAnimations.s create mode 100644 baseCore.s rename {assets => docs}/AArch64/Screenshot from 2021-05-28 20-09-07.png (100%) rename {assets => docs}/AArch64/intruction-mnemonics_integer-class_container.png (100%) rename {assets => docs}/AArch64/load-store_addressing-modes.png (100%) rename {assets => docs}/AArch64/register-names.png (100%) rename ARMv8_Reference_Manual.pdf => docs/ARMv8_Reference_Manual.pdf (100%) rename Trabajo de Laboratorio_ VC FrameBuffer en QEMU emulando RPi3.pdf => docs/Trabajo de Laboratorio_ VC FrameBuffer en QEMU emulando RPi3.pdf (100%) rename variables.md => docs/variables.md (100%) create mode 100644 png/owl_med.png delete mode 100644 screen_animations.s create mode 100644 test.s rename owl.s => zowl.s (99%) rename raven.s => zraven.s (99%) diff --git a/.gitignore b/.gitignore index abd0e85..c976553 100644 --- a/.gitignore +++ b/.gitignore @@ -30,8 +30,10 @@ assets/algorithms # Krita *.kra +*.kra~ # ToDos README todo_readme.md +tod # Archivos grandes diff --git a/README.md b/README.md index 2096246..f1f4cd8 100644 --- a/README.md +++ b/README.md @@ -111,22 +111,24 @@ Your browser does not support the video tag. **[app.s](app.s)** **→** "main" +**[baseCore.s](baseCore.s)** **→** low level abstractions for framebuffer manipulation + **[draw.s](draw.s)** **→** basic lines and figures **[font.s](font.s)** **→** upper case and lower case **[animations.s](animations.s)** **→** delay -**[screen_animations.s](screen_animation.s)** **→** screen animations (animations across the screen) +**[aScreenAnimations.s](aScreenAnimation.s)** **→** screen animations (animations across the screen) **[todo.md](todo.md)** -**[owl.s](owl.s)** **→** Pixel Art +**[zowl.s](zowl.s)** **→** Pixel Art

-**[raven.s](raven.s)** **→** Pixel Art +**[zraven.s](zraven.s)** **→** Pixel Art

diff --git a/aScreenAnimations.s b/aScreenAnimations.s new file mode 100644 index 0000000..fe3a234 --- /dev/null +++ b/aScreenAnimations.s @@ -0,0 +1,206 @@ + +.equ SCREEN_WIDTH, 640 +.equ SCREEN_HEIGH, 480 + +.data + WHITE: .word 0xFFFFFF + +.globl animationTest +// NOTE Animation Test +animationTest: + sub sp, sp, #8 + stur x30, [sp, #0] // Guardamos el return pointer en memoria + mov x18, xzr // Empieza en negro +antestloop: + bl paintScreen // Pinta la pantalla + bl delay + add x18, x18, #1 + mov x8, WHITE + cmp x18, x8 + b.ne antestloop + ldur x30, [sp, #0] // Guardamos el return pointer en memoria ret + add sp, sp, #8 + ret + +.globl circleAnimation1 +// NOTE circle Animation 1 +circleAnimation1: + sub sp, sp, #8 + stur x30, [sp, #0] // Guardamos el return pointer en memoria + mov x21, 320 + mov x22, 240 + mov x23, 10 // x23 = Radio + mov x24, 30 // x24 = Color + // circloop1... + +circloop1: + mov x13, x24 // R + mov x14, 10 // G + mov x15, x24 // B + bl setColour // R+G+B = Naranja + bl doCircle + add x23, x23, #1 // r++ + bl doCircle + bl delay + add x23, x23, #2 // r++ + mov x8, #255 + cmp x24, x8 + b.eq circlend + add x24, x24, #1 // colour++ + b circloop1 + +circlend: + ldur x30, [sp, #0] // Guardamos el return pointer en memoria ret + add sp, sp, #8 + ret + +.globl circleAnimation2 +// NOTE circle Animation 2 +circleAnimation2: + sub sp, sp, #8 + stur x30, [sp, #0] // Guardamos el return pointer en memoria + mov x21, 320 + mov x22, 240 + mov x23, 10 // x23 = Radio + mov x24, 30 // x24 = Color + // circloop2... + +circ2loop1: + mov x13, x24 // R + mov x14, 10 // G + mov x15, 10 // B + bl setColour // R+G+B = Naranja + bl doCircle + add x23, x23, #1 // r++ + bl doCircle + add x23, x23, #1 // r++ + bl doCircle + bl delay + add x23, x23, #1 // r++ + mov x8, #255 + cmp x24, x8 + b.eq circ2lend + add x24, x24, #1 // colour++ + b circ2loop1 + +circ2lend: + ldur x30, [sp, #0] // Guardamos el return pointer en memoria ret + add sp, sp, #8 + ret + +// BL sobreescribe el registro x30 y RET lee el registro x30 // +// BL (Break and link -> funciones) es para salto incondicional, cambia el program counter y cambia el registro x30 // +// B (Break dentro de funciones) es para saltos condicionales cambia el program counter // + +.globl cleanScreen +// NOTE cleanScreen +cleanScreen: // Pinta toda la pantalla de negro + sub sp, sp, #16 + stur lr, [sp] // Guardo el link register para no pisarlo + stur x30, [sp, #8] // Guardamos el return pointer en memoria + mov x13, xzr // R + mov x14, xzr // G + mov x15, xzr // B + bl setColour // Negro + bl paintScreen + ldur x30, [sp, #8] // Guardamos el return pointer en memoria ret + ldur lr, [sp] // Devuelvo el link register + add sp, sp, #16 + ret + +.globl paintScreen +// NOTE paintScreen +paintScreen: // 320w 240h -> 76800 + 240 + // Return -> nada + // Args: x18 Colour + adr x28, PreFrameBuffer // Origen del frameBuffer + mov x8, SCREEN_WIDTH + mov x9, SCREEN_HEIGH + mul x8, x8, x9 // x8 contador de pixeles a pintar + // paintScreenLoop... + +paintScreenLoop: + stur w18, [x28] // Set color of pixel N + add x28, x28, 4 // Next pixel + sub x8, x8, 1 // decrement pixel counter + cbnz x8, paintScreenLoop // If not end row jump + ret + +// TODO revisar +/* +drawBorder: + // Args + // x18 colour + sub sp, sp, #8 // Guardo el link register para no sobreescribirlo + stur lr, [sp] + + mov x16, 0 // Guardo la posicion en x a la que quiero llegar + mov x12, SCREEN_HEIGH // Guardo la posicion y donde quiero llegar + bl setPixel + ldur x9, [x0] + + mov x16, SCREEN_WIDTH + mov x12, SCREEN_HEIGH + bl setPixel + stur x18, [x0] + +drawLeft: + bl setPixel + stur x18, [x0] + sub x16, x16, #1 + cmp x9, x0 + b.eq preDrawUp + b drawLeft + +preDrawUp: + mov x9, #0 +drawUp: + bl setPixel + stur x18, [x0] + sub x12, x12, #1 + cmp x9, x0 + b.eq preDrawRight + b drawUp + +preDrawRight: + mov x12, #0 + mov x16, SCREEN_WIDTH + bl setPixel + ldur x9, [x0] +drawRight: + bl setPixel + stur x18, [x0] + sub x16, x16, #1 + cmp x9, x0 + b.eq preDrawDown + b drawRight + +preDrawDown: + mov x12, SCREEN_HEIGH + mov x16, SCREEN_WIDTH + bl setPixel + ldur x9, [x0] +drawDown: + bl setPixel + stur x18, [x0] + add x12, x12, #1 + cmp x9, x0 + b.eq endBorder + b drawDown + +endBorder: + ldur lr, [sp] + add sp, sp, #8 + ret + */ +/* +endDraw: + // TODO + +borderLoop: + // TODO Hacer + b borderLoop + +borderEnd: + // TODO +*/ diff --git a/animations.s b/animations.s index c95b9fd..38a0d43 100644 --- a/animations.s +++ b/animations.s @@ -1,7 +1,3 @@ -//.ifndef _ANIMATIONS_S -//.equ _ANIMATIONS_S, 1 - -//.include "app.s" .globl delay // NOTE delay @@ -73,52 +69,52 @@ rgbAnimation: // x13 r actual // x14 g actual // x15 b actual - mov x9, #85 // inc = 85 + mov x9, #85 // inc = 85 case1: // r == 255 && b == 0 && g < 255 ---> g += inc (Rojo>>>Amarillo) - cbnz x15, case3 // b != 0 -> next case - cmp x13, #255 // NOTA: Legal - b.ne case2 // r != 255 -> next case + cbnz x15, case3 // b != 0 -> next case + cmp x13, #255 // NOTA: Legal + b.ne case2 // r != 255 -> next case cmp x14, #255 - b.eq case2 // g == 255 -> next case - add x14, x14, x9 // g += inc + b.eq case2 // g == 255 -> next case + add x14, x14, x9 // g += inc b endRgbAnimation case2: // g == 255 && b == 0 && r > 0 ---> r -= inc (Amarillo>>>>Verde) cmp x14, #255 - b.ne case4 // g != 255 -> next case + b.ne case4 // g != 255 -> next case cmp x13, xzr - b.le case3 // r <= 0 - cbnz x15, case3 // b != 0 -> next case - cbz x13, case3 // r == 0 -> next case - sub x13, x13, x9 // r -= inc + b.le case3 // r <= 0 + cbnz x15, case3 // b != 0 -> next case + cbz x13, case3 // r == 0 -> next case + sub x13, x13, x9 // r -= inc b endRgbAnimation case3: // g == 255 && r == 0 && b < 255 ---> b += inc (Verde>>>>Celeste) - cbnz x13, case5 // r != 0 -> next case + cbnz x13, case5 // r != 0 -> next case cmp x14, #255 - b.ne case4 // g != 255 -> next case + b.ne case4 // g != 255 -> next case cmp x15, #255 - b.eq case4 // b == 255 -> next case - add x15, x15, x9 // b += inc + b.eq case4 // b == 255 -> next case + add x15, x15, x9 // b += inc b endRgbAnimation case4: // b == 255 && r == 0 && g > 0 ---> g -= inc (Cyan>>>>Azul) cmp x15, #255 - b.ne case6 // b != 255 -> no es ni case4 ni case5 - cbnz x13, case5 // r != 0 -> next case - cbz x14, case5 // g == 0 -> next case - sub x14, x14, x9 // g -= inc + b.ne case6 // b != 255 -> no es ni case4 ni case5 + cbnz x13, case5 // r != 0 -> next case + cbz x14, case5 // g == 0 -> next case + sub x14, x14, x9 // g -= inc b endRgbAnimation case5: // b == 255 && g == 0 && r < 255 ---> r += inc (Azul>>>>Violeta) cmp x13, #255 - b.eq case6 // r == 255 --> last case - add x13, x13, x9 // r += inc + b.eq case6 // r == 255 --> last case + add x13, x13, x9 // r += inc b endRgbAnimation case6: // r == 255 && g == 0 && b > 0 ---> b -= inc (Violeta>>>>Rojo) - sub x15, x15, x9 // b -= inc + sub x15, x15, x9 // b -= inc b endRgbAnimation endRgbAnimation: @@ -139,8 +135,6 @@ endRgbAnimation: // case 6 // (255, 0, 255) -> (255, 0, 170) -> (255, 0, 85) -> (255, 0, 0) -//.endif - .globl rgbcycletest rgbcycletest: mov x13, 255 // R @@ -152,4 +146,3 @@ rgbaniloop: bl delay bl rgbAnimation b rgbaniloop - diff --git a/app.s b/app.s index 7ac1a5e..6982b88 100644 --- a/app.s +++ b/app.s @@ -1,5 +1,3 @@ -//.ifndef _APP_S -//.equ _APP_S, 1 .equ SCREEN_BYTES, 4*640*480 .equ SCREEN_PIXELS, 640*480 @@ -22,24 +20,17 @@ // x0 Pixel a pintar // x18 Colour // x20 Base del framebuffer +// x28 PreFrameBuffer -//.include "font.s" -//.include "draw.s" -//.include "animations.s" -//.include "screen_animations.s" - -//.include "start.s" .globl main -.globl setColour // https://stackoverflow.com/questions/54918639/linking-2-object-files -.globl drawPixel -.globl setPixel # NOTE Main main: //break: - mov x20, x0 // X0 Direccion base del framebuffer - adr x28, PreFrameBuffer + mov x20, x0 // X0 Dirección base del FrameBuffer + adr x28, PreFrameBuffer // x28 Dirección base del PreFrameBuffer bl cleanScreen + // Pintamos un cuadrado en el medio de la pantalla mov x21, 300 // x2 mov x22, 300 // y2 @@ -55,8 +46,11 @@ main: bl doAnimacionInicial mov x21, #320 // xc x centro mov x22, #250 // yc y centro - bl doRaven bl drawUpdate + bl doRaven + mov x21, #150 // xc x centro + mov x22, #150 // yc y centro + bl doOwl // Dibujamos un búho ret /* @@ -78,93 +72,9 @@ main: bl setColour // R+G+B = Gris bl doTriangleUp */ - // Dibujamos un círculo - // Medio es 320 x 240 - // FIXME Checkear - mov x16, 320 - mov x12, 240 - bl setPixel - // - mov x13, 250 // R - mov x14, 81 // G - mov x15, 171 // B - bl setColour // R+G+B = Rosa - //stur x18, [x0] - //mov x16, 320 - //mov x12, 240 - mov x21, 110 // xc x centro - mov x22, 110 // yc y centro - mov x23, #100 // radio - bl doCircle - - mov x13, 255 // R - mov x14, 145 // G - mov x15, 0 // B - bl setColour // R+G+B = Naranja - mov x21, 200 - //bl verticalLine - - mov x21, 300 - //bl verticalLine // NOTE OK //bl cleanScreen // cleanScreen negro - mov x21, #150 // xc x centro - mov x22, #150 // yc y centro - bl doOwl // Dibujamos un búho - - // Dibujamos una línea "vertical" - mov x21, 59 - mov x22, 59 - mov x23, 100 - mov x24, 100 - mov x13, 255 // R - mov x14, 145 // G - mov x15, 0 // B - bl setColour // R+G+B = Naranja - bl drawLine - - mov x13, 17 // R - mov x14, 253 // G - mov x15, 64 // B - bl setColour // Verde - mov x16, 59 - mov x12, 59 - bl drawPixel - mov x16, 100 - mov x12, 100 - bl drawPixel - /// - - // Dibujamos una línea xc0, yc0 -> xc1, yc1 - mov x21, 150 - mov x22, 30 - mov x23, 50 - mov x24, 200 - mov x13, 85 // R - mov x14, 255 // G - mov x15, 237 // B - bl setColour // R+G+B = cyan 55ffed - bl drawLine - - mov x13, 255 // R - mov x14, 251 // G - mov x15, 0 // B - bl setColour // Amarillo fffb00 - mov x16, 150 - mov x12, 30 - bl drawPixel - mov x16, 50 - mov x12, 200 - bl drawPixel - /// - - mov x21, #320 // xc x centro - mov x22, #300 // yc y centro - bl doRaven // Dibujamos un cuervo - - //bl circleTest - // Creamos el nombre Valentina Vispo mov x13, 209 // R mov x14, 0 // G @@ -173,19 +83,7 @@ main: //bl doValentinaVispo //bl delay - //bl cleanScreen // cleanScreen negro - - //bl animationTest - //bl circleAnimation1 - - mov x13, 250 // R - mov x14, 81 // G - mov x15, 171 // B - bl setColour // R+G+B = Rosa - mov x21, 100 - //bl verticalLine - //bl lineAnimation - //bl rgbcycletest + //bl cleanScreen // cleanScreen negro EndMain: bl delay @@ -193,289 +91,3 @@ EndMain: return: ret - -// TODO revisar -/* -drawBorder: - // Args - // x18 colour - sub sp, sp, #8 // Guardo el link register para no sobreescribirlo - stur lr, [sp] - - mov x16, 0 // Guardo la posicion en x a la que quiero llegar - mov x12, SCREEN_HEIGH // Guardo la posicion y donde quiero llegar - bl setPixel - ldur x9, [x0] - - mov x16, SCREEN_WIDTH - mov x12, SCREEN_HEIGH - bl setPixel - stur x18, [x0] - -drawLeft: - bl setPixel - stur x18, [x0] - sub x16, x16, #1 - cmp x9, x0 - b.eq preDrawUp - b drawLeft - -preDrawUp: - mov x9, #0 -drawUp: - bl setPixel - stur x18, [x0] - sub x12, x12, #1 - cmp x9, x0 - b.eq preDrawRight - b drawUp - -preDrawRight: - mov x12, #0 - mov x16, SCREEN_WIDTH - bl setPixel - ldur x9, [x0] -drawRight: - bl setPixel - stur x18, [x0] - sub x16, x16, #1 - cmp x9, x0 - b.eq preDrawDown - b drawRight - -preDrawDown: - mov x12, SCREEN_HEIGH - mov x16, SCREEN_WIDTH - bl setPixel - ldur x9, [x0] -drawDown: - bl setPixel - stur x18, [x0] - add x12, x12, #1 - cmp x9, x0 - b.eq endBorder - b drawDown - -endBorder: - ldur lr, [sp] - add sp, sp, #8 - ret - */ -/* -endDraw: - // TODO - -borderLoop: - // TODO Hacer - b borderLoop - -borderEnd: - // TODO -*/ - -// NOTE Circle Test -/* -circleTest: - sub sp, sp, #8 - stur x30, [sp, #0] // Guardamos el return pointer en memoria - // Dibujamos un círculo - // Medio es 320 x 240 - mov x13, 250 // R - mov x14, 81 // G - mov x15, 171 // B - bl setColour // R+G+B = Rosa - stur x18, [x0] - mov x21, 320 // xc x centro - mov x22, 240 // yc y centro - mov x23, 20 // radio - bl doCircle - // Return - ldur x30, [sp, #0] // Guardamos el return pointer en memoria ret - add sp, sp, #8 // Liberamos memoria - ret - */ -// NOTE drawPixel -drawPixel: - // Args: y=x12 -- x=x16 -- colour=x18 - sub sp, sp, #16 - str x28, [sp, 8] - str x30, [sp, #0] - bl setPixel - str w18, [x28] // stur xN guarda 64bits, y stur wN guarda medio registro (32bits) IMPORTANTE!!!!!!!!! - ldr x30, [sp, #0] - ldr x28, [sp, 8] - add sp, sp, #16 - ret - -// NOTE setPixel -setPixel: - // Return: x29 Pixel a pintar - // Args: y=x12 -- x=x16 - mov x8, SCREEN_WIDTH - mul x17, x12, x8 // y * WIDTH - add x17, x17, x16 // + x - lsl x17, x17, 2 // *4 - add x28, x28, x17 // Pixel a pintar - ret - -.globl drawUpdate -drawUpdate: - // x28 PreFrameBuffer - // x20 FrameBuffer - sub sp, sp, 40 - str x8, [sp, 32] - str x7, [sp, 24] - str x9, [sp, 16] - str x10, [sp, 8] - str lr, [sp] - mov x8, x20 - mov x7, x28 - mov x9, 0 - ldr x10, TOTAL_PIXELS - -updateLoop: - ldr w6, [x7] - str w6, [x8] - add x8, x8, 4 - add x7, x7, 4 - cmp x9, x10 - b.eq endUpdate - add x9, x9, 1 - b updateLoop - -endUpdate: - ldr x8, [sp, 32] - ldr x7, [sp, 24] - ldr x9, [sp, 16] - ldr x10, [sp, 8] - ldr lr, [sp] - add sp, sp, 40 - ret - -// NOTE setColour -setColour: - // Return - // x18 Color a pintar - // Args - // x13 r - // x14 g - // x15 b - // 24 bits - sub sp, sp, #16 - str x13, [sp, #8] - str x14, [sp, #0] - - lsl x13, x13, 16 // Movemos 16 bits - lsl x14, x14, 8 // Movemos 8 bits - add x18, x13, x14 // R+G - add x18, x18, x15 // RG+B - - ldr x13, [sp, #8] - ldr x14, [sp, #0] - add sp, sp, #16 - ret - -// NOTE Line -verticalLine: - // Args - // x21 x - // x18 Colour - sub sp, sp, #16 // Guardamos 2 lugares del stack - str x30, [sp, #8] // registro 30 para el RET en el stack - str x1, [sp, #0] // Guardamos en el stack pointer el registro x1 anterior - mov x1, SCREEN_HEIGH - mov x16, x21 // x = argument - mov x12, xzr // y = 0 - // verLineLoop... - -verLineLoop: - cmp x1, x12 // Comparamos SCREEN_HEIGH con y - b.eq verLineEnd // Si x1 es igual a x12 termina - bl drawPixel - add x12, x12, #1 // Pasamos a la siguiente "fila" (bajamos 1 en y) - b verLineLoop // Continuamos con el loop - -verLineEnd: - ldr x1, [sp, #0] // Carga lo que guardó en el stack - ldr x30, [sp, #8] // Cargamos variables anteriores - add sp, sp, #16 // Libera el stack - ret - -.globl doHorizontalLine -// NOTE LineH -doHorizontalLine: // Crea líneas horizontales en la coordenada (xo, po) con w cantidad de pixeles que se extienden hacia la derecha // - // Args - // x21 xo valor de origen x - // x22 yo valor de origen y - // x23 w cantidad de pixeles - // Used - // drawPixel: setPixel x16 x, x12 y - // x18 Colour - sub sp, sp, #48 - str x12, [sp, #40] - str x16, [sp, #32] - str x23, [sp, #24] - str x22, [sp, #16] - str x21, [sp, #8] - str x30, [sp, #0] // Guardamos el return pointer en memoria - mov x16, x21 // x = xo - // horLineLoop... - -horLineLoop: - sub x8, x16, x21 // Cuantos pixeles hemos dibujado hasta ahora - cmp x23, x8 // Comparamos x23=w con x8 - b.eq endHorizontalLine // Si son iguales terminamos porque pintamos todo ya - mov x12, x22 - bl drawPixel // Sino, dibujamos - add x16, x16, #1 // Nos movemos de pixel, x++ - b horLineLoop - -endHorizontalLine: - ldr x30, [sp, #0] // Guardamos el return pointer en memoria - ldr x21, [sp, #8] - ldr x22, [sp, #16] - ldr x23, [sp, #24] - ldr x16, [sp, #32] - ldr x12, [sp, #40] - add sp, sp, #48 // Liberamos espacio en memoria - ret - -// BL sobreescribe el registro x30 y RET lee el registro x30 // -// BL (Break and link -> funciones) es para salto incondicional, cambia el program counter y cambia el registro x30 // -// B (Break dentro de funciones) es para saltos condicionales cambia el program counter // - -.globl cleanScreen -// NOTE cleanScreen -cleanScreen: // Pinta toda la pantalla de negro - sub sp, sp, #16 - stur lr, [sp] // Guardo el link register para no pisarlo - stur x30, [sp, #8] // Guardamos el return pointer en memoria - mov x13, xzr // R - mov x14, xzr // G - mov x15, xzr // B - bl setColour // Negro - bl paintScreen - ldur x30, [sp, #8] // Guardamos el return pointer en memoria ret - ldur lr, [sp] // Devuelvo el link register - add sp, sp, #16 - ret - -.globl paintScreen -// NOTE paintScreen -paintScreen: // 320w 240h -> 76800 + 240 - // Return -> nada - // Args: x18 Colour - adr x28, PreFrameBuffer // Origen del frameBuffer - mov x8, SCREEN_WIDTH - mov x9, SCREEN_HEIGH - mul x8, x8, x9 // x8 contador de pixeles a pintar - // paintScreenLoop... - -paintScreenLoop: - stur w18, [x28] // Set color of pixel N - add x28, x28, 4 // Next pixel - sub x8, x8, 1 // decrement pixel counter - cbnz x8, paintScreenLoop // If not end row jump - ret - -//.endif diff --git a/baseCore.s b/baseCore.s new file mode 100644 index 0000000..948454b --- /dev/null +++ b/baseCore.s @@ -0,0 +1,111 @@ + +.equ SCREEN_BYTES, 4*640*480 +.equ SCREEN_PIXELS, 640*480 +.data + TOTAL_PIXELS: .dword SCREEN_PIXELS + +.equ SCREEN_WIDTH, 640 +.equ SCREEN_HEIGH, 480 +.equ BITS_PER_PIXEL, 32 +.equ COLOR_1, 0xFF // Color blanco R // 0xC7 +.equ COLOR_2, 0xFFFF // Color blanco GB // 0x1607 +.equ COLOR_NEGRO, 0x00 + + +.globl drawPixel +drawPixel: + // Args: y=x12 -- x=x16 -- colour=x18 + sub sp, sp, #8 + stur x30, [sp, #0] + bl setPixel // ret : x0 + cbz x3, drawBuffer // if x3 == 0 dibujar en el buffer + b drawPrebuffer // else dibujar en el prebuffer + +drawBuffer: + mov x8, x0 // Dibujamos el valor original x0 + b drawPixelEnd + +drawPrebuffer: // then dibujar en x28 + // direccion del buffer = x20 + // direccion del prebuffer = x28 + // x20 + (x28-x20) = x28 + // x20 + offset + (x28-x20) = x28 + offset + // x20 + offset = X0 -> + // X0 + X28 - X20 = X28 + offset == traducción del buffer al prebuffer + add x8, x0, x28 + sub x8, x8, x20 + +drawPixelEnd: + stur w18, [x8] // stur xN guarda 64bits, y stur wN guarda medio registro (32bits) + ldur x30, [sp, #0] + add sp, sp, #8 + ret + +.globl setPixel +setPixel: + // Return: x0 Pixel a pintar + // Args: y=x12 -- x=x16 + mov x8, SCREEN_WIDTH + mul x0, x12, x8 // y * WIDTH + add x0, x0, x16 // + x + lsl x0, x0, 2 // *4 + add x0, x20, x0 // Pixel a pintar + ret + +.globl drawUpdate +drawUpdate: + // x28 PreFrameBuffer + // x20 FrameBuffer + sub sp, sp, 40 + str x8, [sp, 32] + str x7, [sp, 24] + str x9, [sp, 16] + str x10, [sp, 8] + str lr, [sp] + mov x8, x20 + mov x7, x28 + mov x9, 0 + ldr x10, TOTAL_PIXELS + +updateLoop: + ldr w6, [x7] + str w6, [x8] + add x8, x8, 4 + add x7, x7, 4 + cmp x9, x10 + b.eq endUpdate + add x9, x9, 1 + b updateLoop + +endUpdate: + ldr x8, [sp, 32] + ldr x7, [sp, 24] + ldr x9, [sp, 16] + ldr x10, [sp, 8] + ldr lr, [sp] + add sp, sp, 40 + ret + +.globl setColour // https://stackoverflow.com/questions/54918639/linking-2-object-files +// NOTE setColour +setColour: + // Return + // x18 Color a pintar + // Args + // x13 r + // x14 g + // x15 b + // 24 bits + sub sp, sp, #16 + str x13, [sp, #8] + str x14, [sp, #0] + + lsl x13, x13, 16 // Movemos 16 bits + lsl x14, x14, 8 // Movemos 8 bits + add x18, x13, x14 // R+G + add x18, x18, x15 // RG+B + + ldr x13, [sp, #8] + ldr x14, [sp, #0] + add sp, sp, #16 + ret diff --git a/assets/AArch64/Screenshot from 2021-05-28 20-09-07.png b/docs/AArch64/Screenshot from 2021-05-28 20-09-07.png similarity index 100% rename from assets/AArch64/Screenshot from 2021-05-28 20-09-07.png rename to docs/AArch64/Screenshot from 2021-05-28 20-09-07.png diff --git a/assets/AArch64/intruction-mnemonics_integer-class_container.png b/docs/AArch64/intruction-mnemonics_integer-class_container.png similarity index 100% rename from assets/AArch64/intruction-mnemonics_integer-class_container.png rename to docs/AArch64/intruction-mnemonics_integer-class_container.png diff --git a/assets/AArch64/load-store_addressing-modes.png b/docs/AArch64/load-store_addressing-modes.png similarity index 100% rename from assets/AArch64/load-store_addressing-modes.png rename to docs/AArch64/load-store_addressing-modes.png diff --git a/assets/AArch64/register-names.png b/docs/AArch64/register-names.png similarity index 100% rename from assets/AArch64/register-names.png rename to docs/AArch64/register-names.png diff --git a/ARMv8_Reference_Manual.pdf b/docs/ARMv8_Reference_Manual.pdf similarity index 100% rename from ARMv8_Reference_Manual.pdf rename to docs/ARMv8_Reference_Manual.pdf diff --git a/Trabajo de Laboratorio_ VC FrameBuffer en QEMU emulando RPi3.pdf b/docs/Trabajo de Laboratorio_ VC FrameBuffer en QEMU emulando RPi3.pdf similarity index 100% rename from Trabajo de Laboratorio_ VC FrameBuffer en QEMU emulando RPi3.pdf rename to docs/Trabajo de Laboratorio_ VC FrameBuffer en QEMU emulando RPi3.pdf diff --git a/variables.md b/docs/variables.md similarity index 100% rename from variables.md rename to docs/variables.md diff --git a/draw.s b/draw.s index 8bd34e8..f45c482 100644 --- a/draw.s +++ b/draw.s @@ -1,11 +1,21 @@ -//.ifndef _DRAW_S -//.equ _DRAW_S, 1 -//.include "app.s" +.equ SCREEN_BYTES, 4*640*480 +.equ SCREEN_PIXELS, 640*480 +.data + TOTAL_PIXELS: .dword SCREEN_PIXELS + +.equ SCREEN_WIDTH, 640 +.equ SCREEN_HEIGH, 480 +.equ BITS_PER_PIXEL, 32 +.equ COLOR_1, 0xFF // Color blanco R // 0xC7 +.equ COLOR_2, 0xFFFF // Color blanco GB // 0x1607 +.equ COLOR_NEGRO, 0x00 .globl doAnimacionInicial +// NOTE doAnimacionInicial doAnimacionInicial: - sub sp, sp, 48 + sub sp, sp, 56 + str x3, [sp, 48] str x25, [sp, 40] str x24, [sp, 32] str x23, [sp, 24] @@ -13,14 +23,15 @@ doAnimacionInicial: str x22, [sp, 8] str lr, [sp] mov x25, 0 + mov x3, #1 // Seteamos al PreFrameBuffer loopDelay: - bl delay // Retraso - bl cleanScreen // Limpio la pantalla - bl drawUpdate // Actualizo FB + bl delay // Retraso + bl cleanScreen // Limpio la pantalla + bl drawUpdate // Actualizo FB bl doCompuVentana - add x21, x21, 6 // - sub x22, x22, 3 // Muevo el mouse + add x21, x21, 6 // + sub x22, x22, 3 // Muevo el mouse bl doMouse cmp x25, 19 b.eq loopDelay2 @@ -41,10 +52,12 @@ endAnimacion: ldr x23, [sp, 24] ldr x24, [sp, 32] ldr x25, [sp, 40] - add sp, sp, 48 + ldr x3, [sp, 48] + add sp, sp, 56 ret .globl doComputerBroken +// NOTE doComputerBroken doComputerBroken: sub sp, sp, 48 stur x25, [sp, 40] @@ -87,6 +100,7 @@ doComputerBroken: ret .globl doMouse +// NOTE doMouse doMouse: // @Diego // Args @@ -110,9 +124,10 @@ doMouse: ret .globl doCompuVentana +// NOTE doCompuVentana doCompuVentana: sub sp, sp, 56 - stur x15, [sp, 48] + stur x15, [sp, 48] stur x14, [sp, 40] stur x13, [sp, 32] stur x21, [sp, 24] @@ -165,7 +180,7 @@ doCompuVentana: mov x24, 280 bl doRectangle - // Boton de play + // Botón de play movz w18, 0x0d, lsl 16 movk w18, 0x0630, lsl 0 mov x21, 270 @@ -174,7 +189,7 @@ doCompuVentana: mov x24, 100 bl doRectangle - // Triangulo del medio del boton + // Triángulo del medio del boton movz w18, 0x8b, lsl 16 movk w18, 0xbeb2, lsl 0 mov x21, 310 @@ -183,7 +198,7 @@ doCompuVentana: mov x24, 80 bl triangDer - // Boton de salida + // Botón de salida movz w18, 0x38, lsl 16 movk w18, 0x4e77, lsl 0 mov x21, 520 @@ -192,7 +207,7 @@ doCompuVentana: mov x24, 20 bl doRectangle - // Boton de salida + // Botón de salida movz w18, 0x18, lsl 16 movk w18, 0x314f, lsl 0 mov x21, 500 @@ -213,12 +228,12 @@ doCompuVentana: ldur x21, [sp, 24] ldur x13, [sp, 32] ldur x14, [sp, 40] - ldur x15, [sp, 48] + ldur x15, [sp, 48] add sp, sp, 56 ret .globl triangDer -// NOTE Triangulo apuntando a la derecha +// NOTE Triángulo apuntando a la derecha triangDer: // @Diego // Args @@ -264,6 +279,7 @@ preEndTriangDer: ldur x23, [sp, 8] add x23, x23, 2 bl vertLine + endTriangDer: ldur lr, [sp] ldur x23, [sp, 8] @@ -309,7 +325,7 @@ endVertLine: .globl drawLine -// NOTE Line +// NOTE drawLine Line drawLine: // Args // x21 xc0 coordenada x del primer punto @@ -376,16 +392,16 @@ loopLine: bl drawPixel // plot(xc0, yc0) cmp x21, x23 // Comparamos xc0 con xc1 - b.ne checkLine // xc0 != xc1 // FIXME + b.ne checkLine // xc0 != xc1 b endDrawLine // break checkLine: cmp x22, x24 // Comparamos yc0 con yc1 - b.ne lineNoBreak // yc0 != yc1 // FIXME + b.ne lineNoBreak // yc0 != yc1 b endDrawLine // break lineNoBreak: - //lsl x8, x19, #1 // x8 = e2 = 2*err + //lsl x8, x19, #1 // x8 = e2 = 2*err add x8, x19, x19 // x8 = e2 = 2*err cmp x8, x6 @@ -457,7 +473,7 @@ doRectangle: // alto x largo// stur x23, [sp, 24] stur x24, [sp, 16] stur lr, [sp, 8] // Guardamos el return pointer en memoria (8 direcciones de memoria = 1 registro de 64bits) - stur x5, [sp] // Guardamos el x5 en memoria (8 direcciones de memoria = 1 registro de 64bits) + stur x5, [sp] // Guardamos el x5 en memoria (8 direcciones de memoria = 1 registro de 64bits) mov x5, x22 // x5 fila inicial @@ -524,7 +540,7 @@ doCircleLoop: // While x > y b.le cirif1 // Si P <= 0 entra en el if b cirelse1 // Si no, entra en el else -cirif1: // if (P <= 0) +cirif1: // if (P <= 0) // F(p) < 0 -> the point is inside the circle // F(p) = 0 -> the point is on the perimeter lsl x8, x26, #1 // x8 = 2*y @@ -542,7 +558,7 @@ cirelse1: // Mid-point is outside the perimeter add x27, x27, x9 // P = P + 2*y - 2*x + 1 // cirif2... -cirif2: // if (x < y) +cirif2: // if (x < y) cmp x25, x26 b.lt circleEnd @@ -595,7 +611,7 @@ circleEnd: ret .globl doTriangleUp -// NOTE Triangulo hacia arriba +// NOTE Triángulo hacia arriba doTriangleUp: // @Diego // Args @@ -608,11 +624,11 @@ doTriangleUp: str x23, [sp, 24] str x22, [sp, 16] str x21, [sp, 8] - str lr, [sp] // Guardo el link register para no pisarlo en la subrutina setPixel - mov x16, x21 // Instancio x16 para dibujar - mov x12, x22 // Instancio x12 para setPixel - mov x19, x23 // La cantidad de pixeles sera la cantidad de veces que entro al ciclo - mov x9, #0 // Instancio un contador que me va a servir para contar cantidad de pixeles + str lr, [sp] // Guardo el link register para no pisarlo en la subrutina setPixel + mov x16, x21 // Instancio x16 para dibujar + mov x12, x22 // Instancio x12 para setPixel + mov x19, x23 // La cantidad de pixeles sera la cantidad de veces que entro al ciclo + mov x9, #0 // Instancio un contador que me va a servir para contar cantidad de pixeles b rectAr rectAr: // Dibuja la diagonal hacia arriba @@ -651,7 +667,7 @@ endTriang: ret .globl doTriangleDown -// NOTE Triangulo hacia abajo +// NOTE Triángulo hacia abajo doTriangleDown: // @Diego // Args @@ -664,12 +680,12 @@ doTriangleDown: stur x23, [sp, 24] stur x22, [sp, 16] stur x21, [sp, 8] - stur lr, [sp] // Guardo el link register para no pisarlo en la subrutina setPixel - mov x16, x21 // Instancio x16 para dibujar - mov x12, x22 // Instancio x12 para setPixel - bl setPixel // Calculo la posicion inicial - mov x19, x23 // La cantidad de pixeles sera la cantidad de veces que entro al ciclo - mov x9, #0 // Instancio un contador que me va a servir para contar cantidad de pixeles + stur lr, [sp] // Guardo el link register para no pisarlo en la subrutina setPixel + mov x16, x21 // Instancio x16 para dibujar + mov x12, x22 // Instancio x12 para setPixel + bl setPixel // Calculo la posicion inicial + mov x19, x23 // La cantidad de pixeles sera la cantidad de veces que entro al ciclo + mov x9, #0 // Instancio un contador que me va a servir para contar cantidad de pixeles b rectArDown rectArDown: // Dibuja la diagonal hacia arriba @@ -681,7 +697,7 @@ rectArDown: // Dibuja la diagonal hacia arriba add x9, x9, #1 // Si no le sumo 1 b rectArDown // Empiezo de nuevo -rectBajDown: // Dibuja la diagonal hacia abajo +rectBajDown: // Dibuja la diagonal hacia abajo add x16, x16, #1 // Me muevo al siguiente sub x12, x12, #1 // Bajo 1 unidad bl setPixel // Calculo el pixel @@ -709,7 +725,7 @@ endTriangDown: ret .globl doPiramide -// NOTE Piramide +// NOTE Pirámide doPiramide: // @Diego // Args @@ -722,11 +738,11 @@ doPiramide: str x23, [sp, 24] str x22, [sp, 16] str x21, [sp, 8] - stur lr, [sp] // Guardo el link register para no pisarlo en la subrutina setPixel - mov x16, x21 // Instancio x16 para dibujar - mov x12, x22 // Instancio x12 para setPixel - mov x19, x23 // La cantidad de pixeles sera la cantidad de veces que entro al ciclo - mov x9, #0 // Instancio un contador que me va a servir para contar cantidad de pixeles + stur lr, [sp] // Guardo el link register para no pisarlo en la subrutina setPixel + mov x16, x21 // Instancio x16 para dibujar + mov x12, x22 // Instancio x12 para setPixel + mov x19, x23 // La cantidad de pixeles sera la cantidad de veces que entro al ciclo + mov x9, #0 // Instancio un contador que me va a servir para contar cantidad de pixeles pirAr: // Dibuja la diagonal hacia arriba sub x16, x16, #1 // Me muevo atras @@ -763,4 +779,67 @@ endPir: add sp, sp, #32 ret -//.endif +// NOTE Line +verticalLine: + // Args + // x21 x + // x18 Colour + sub sp, sp, #16 // Guardamos 2 lugares del stack + str x30, [sp, #8] // registro 30 para el RET en el stack + str x1, [sp, #0] // Guardamos en el stack pointer el registro x1 anterior + mov x1, SCREEN_HEIGH + mov x16, x21 // x = argument + mov x12, xzr // y = 0 + // verLineLoop... + +verLineLoop: + cmp x1, x12 // Comparamos SCREEN_HEIGH con y + b.eq verLineEnd // Si x1 es igual a x12 termina + bl drawPixel + add x12, x12, #1 // Pasamos a la siguiente "fila" (bajamos 1 en y) + b verLineLoop // Continuamos con el loop + +verLineEnd: + ldr x1, [sp, #0] // Carga lo que guardó en el stack + ldr x30, [sp, #8] // Cargamos variables anteriores + add sp, sp, #16 // Libera el stack + ret + +.globl doHorizontalLine +// NOTE LineH +doHorizontalLine: // Crea líneas horizontales en la coordenada (xo, po) con w cantidad de pixeles que se extienden hacia la derecha // + // Args + // x21 xo valor de origen x + // x22 yo valor de origen y + // x23 w cantidad de pixeles + // Used + // drawPixel: setPixel x16 x, x12 y + // x18 Colour + sub sp, sp, #48 + str x12, [sp, #40] + str x16, [sp, #32] + str x23, [sp, #24] + str x22, [sp, #16] + str x21, [sp, #8] + str x30, [sp, #0] // Guardamos el return pointer en memoria + mov x16, x21 // x = xo + // horLineLoop... + +horLineLoop: + sub x8, x16, x21 // Cuantos pixeles hemos dibujado hasta ahora + cmp x23, x8 // Comparamos x23=w con x8 + b.eq endHorizontalLine // Si son iguales terminamos porque pintamos todo ya + mov x12, x22 + bl drawPixel // Sino, dibujamos + add x16, x16, #1 // Nos movemos de pixel, x++ + b horLineLoop + +endHorizontalLine: + ldr x30, [sp, #0] // Guardamos el return pointer en memoria + ldr x21, [sp, #8] + ldr x22, [sp, #16] + ldr x23, [sp, #24] + ldr x16, [sp, #32] + ldr x12, [sp, #40] + add sp, sp, #48 // Liberamos espacio en memoria + ret diff --git a/font.s b/font.s index 80914a9..137b017 100644 --- a/font.s +++ b/font.s @@ -1,8 +1,3 @@ -//.ifndef _FONT_S -//.equ _FONT_S, 1 - -//.include "app.s" - // Font https://www.dafont.com/es/minitel.font?text=console .equ SCREEN_WIDTH, 640 @@ -16,11 +11,11 @@ // NOTE a doA: // @Vale + .globl doEm -// NOTE e -doEm: // REVIEW Done - // @Diego +// NOTE E +doEm: // Args // x21 x lugar dónde empiezo a dibujar la figura // x22 y lugar dónde empiezo a dibujar la figura @@ -72,8 +67,7 @@ endE: .globl doE // NOTE e -doE: // REVIEW Done - // @Diego +doE: // Args // x21 x lugar dónde empiezo a dibujar la figura // x22 y lugar dónde empiezo a dibujar la figura @@ -115,9 +109,8 @@ doE: // REVIEW Done ret .globl doIm -// NOTE i -doIm: //REVIEW Done - // @Diego +// NOTE I +doIm: // Args // x21 x lugar dónde empiezo a dibujar la figura // x22 y lugar dónde empiezo a dibujar la figura @@ -170,8 +163,7 @@ endI: .globl doI // NOTE i -doI: //REVIEW Done - // @Diego +doI: // Args // x21 x lugar dónde empiezo a dibujar la figura // x22 y lugar dónde empiezo a dibujar la figura @@ -188,7 +180,7 @@ doI: //REVIEW Done sub x21, x21, 5 add x22, x22, 5 mov x23, 5 - bl doHorizontalLine + bl doHorizontalLine add x21, x21, 5 mov x23, 15 bl vertLine @@ -207,8 +199,7 @@ doI: //REVIEW Done .globl doO // NOTE o -doO: //REVIEW Done - // @Diego +doO: // Args // x21 x // x22 y @@ -342,8 +333,7 @@ doP: .globl doM // NOTE m -doM: // REVIEW Done - // @Diego +doM: // Args // x21 x inicial // x22 y inicial @@ -451,8 +441,7 @@ doT: .globl doZ // NOTE z -doZ: // REVIEW Done - // @Diego +doZ: // Args // x21 x inicial // x22 y inicial @@ -496,8 +485,7 @@ endZ: .globl doGm // NOTE G mayus -doGm: //REVIEW Done - // @Diego +doGm: // Args // x21 x inicial // x22 y inicial @@ -548,7 +536,7 @@ doGm: //REVIEW Done .globl doG // NOTE g -doG: //REVIEW Done +doG: // @Diego // Args // x21 x inicial @@ -572,17 +560,17 @@ doG: //REVIEW Done add x22, x22, 5 mov x23, 10 bl doHorizontalLine - + add x21, x21, 10 sub x22, x22, 5 mov x23, 14 bl vertLine - + add x22, x22, 15 sub x21, x21, 9 mov x23, 9 bl doHorizontalLine - + sub x21, x21, 1 sub x22, x22, 5 mov x23, 4 @@ -599,7 +587,6 @@ doG: //REVIEW Done .globl doDiego // NOTE Diego doDiego: - // @Diego // Args // x21 x // x22 y @@ -678,5 +665,3 @@ doValentinaVispo: // bl doP // bl doO ret - -//.endif diff --git a/png/owl_med.png b/png/owl_med.png new file mode 100644 index 0000000000000000000000000000000000000000..096f2bb3a20370dc272afa61e7f1442bad5f1951 GIT binary patch literal 42889 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 Ot(vuOx~j=bAN(KfOAE08 literal 0 HcmV?d00001 diff --git a/screen_animations.s b/screen_animations.s deleted file mode 100644 index 38036b9..0000000 --- a/screen_animations.s +++ /dev/null @@ -1,92 +0,0 @@ -//.ifndef _SCREEN_ANIMATIONS_S -//.equ _SCREEN_ANIMATIONS_S, 1 - -//.include "app.s" - -.data - WHITE: .word 0xFFFFFF - -.globl animationTest -// NOTE Animation Test -animationTest: - sub sp, sp, #8 - stur x30, [sp, #0] // Guardamos el return pointer en memoria - mov x18, xzr // Empieza en negro -antestloop: - bl paintScreen // Pinta la pantalla - bl delay - add x18, x18, #1 - mov x8, WHITE - cmp x18, x8 - b.ne antestloop - ldur x30, [sp, #0] // Guardamos el return pointer en memoria ret - add sp, sp, #8 - ret - -.globl circleAnimation1 -// NOTE circle Animation 1 -circleAnimation1: - sub sp, sp, #8 - stur x30, [sp, #0] // Guardamos el return pointer en memoria - mov x21, 320 - mov x22, 240 - mov x23, 10 // x23 = Radio - mov x24, 30 // x24 = Color - // circloop1... - -circloop1: - mov x13, x24 // R - mov x14, 10 // G - mov x15, x24 // B - bl setColour // R+G+B = Naranja - bl doCircle - add x23, x23, #1 // r++ - bl doCircle - bl delay - add x23, x23, #2 // r++ - mov x8, #255 - cmp x24, x8 - b.eq circlend - add x24, x24, #1 // colour++ - b circloop1 - -circlend: - ldur x30, [sp, #0] // Guardamos el return pointer en memoria ret - add sp, sp, #8 - ret - -.globl circleAnimation2 -// NOTE circle Animation 2 -circleAnimation2: - sub sp, sp, #8 - stur x30, [sp, #0] // Guardamos el return pointer en memoria - mov x21, 320 - mov x22, 240 - mov x23, 10 // x23 = Radio - mov x24, 30 // x24 = Color - // circloop2... - -circ2loop1: - mov x13, x24 // R - mov x14, 10 // G - mov x15, 10 // B - bl setColour // R+G+B = Naranja - bl doCircle - add x23, x23, #1 // r++ - bl doCircle - add x23, x23, #1 // r++ - bl doCircle - bl delay - add x23, x23, #1 // r++ - mov x8, #255 - cmp x24, x8 - b.eq circ2lend - add x24, x24, #1 // colour++ - b circ2loop1 - -circ2lend: - ldur x30, [sp, #0] // Guardamos el return pointer en memoria ret - add sp, sp, #8 - ret - -//.endif diff --git a/start.s b/start.s index a1cf2fc..fdd922c 100644 --- a/start.s +++ b/start.s @@ -9,12 +9,12 @@ .equ SCREEN_HEIGH, 480 .equ BITS_PER_PIXEL, 32 - .equ MAIL_BASE, 0xB880 // Mailbox Base Address + .equ MAIL_BASE, 0xB880 // Mailbox Base Address .equ MAIL_WRITE, 0x20 // Mailbox Write Register - .equ MAIL_TAGS, 0x8 // Mailbox Channel 8: Tags (ARM to VC) + .equ MAIL_TAGS, 0x8 // Mailbox Channel 8: Tags (ARM to VC) .equ PERIPHERAL_BASE, 0x3F000000 // Peripheral Base Address - .equ Get_Allocate_Buffer, 0x00040001 // Frame Buffer: Allocate Buffer (Response: Frame Buffer Base Address In Bytes, Frame Buffer Size In Bytes) + .equ Get_Allocate_Buffer, 0x00040001 // Frame Buffer: Allocate Buffer (Response: Frame Buffer Base Address In Bytes, Frame Buffer Size In Bytes) .equ Set_Physical_Display, 0x00048003 // Frame Buffer: Set Physical (Display) Width/Height (Response: Width In Pixels, Height In Pixels) .equ Set_Virtual_Buffer, 0x00048004 // Frame Buffer: Set Virtual (Buffer) Width/Height (Response: Width In Pixels, Height In Pixels) @@ -49,39 +49,39 @@ .globl _start _start: - mrs x1, mpidr_el1 // X0 = Multiprocessor Affinity Register (MPIDR) - and x1, x1, #3 // X0 = CPU ID (Bits 0..1) - cbz x1, StackInit // IF (CPU ID == 0) Branch To Finit else (Core ID 1..3) CoreLoop - // Infinite Loop For Core 1, 2 and 3 -CoreLoop: + mrs x1, mpidr_el1 // X0 = Multiprocessor Affinity Register (MPIDR) + and x1, x1, #3 // X0 = CPU ID (Bits 0..1) + cbz x1, StackInit // IF (CPU ID == 0) Branch To Finit else (Core ID 1..3) CoreLoop + // Infinite Loop For Core 1, 2 and 3 +CoreLoop: b CoreLoop StackInit: // set stack before our code - ldr x1, =_start - mov sp, x1 + ldr x1, =_start + mov sp, x1 // clear bss - ldr x1, =__bss_start - ldr w2, =__bss_size -_StackInit_loop: - cbz w2, FB_Init - str xzr, [x1], #8 - sub w2, w2, #1 - cbnz w2, _StackInit_loop + ldr x1, =__bss_start + ldr w2, =__bss_size +_StackInit_loop: + cbz w2, FB_Init + str xzr, [x1], #8 + sub w2, w2, #1 + cbnz w2, _StackInit_loop // Core 0 Init the framebuffer FB_Init: ldr x0, =(FB_STRUCT + MAIL_TAGS) ldr x1, =MAIL_BASE ldr x2, =FB_POINTER - orr x1,x1,PERIPHERAL_BASE - str w0,[x1,MAIL_WRITE + MAIL_TAGS] // Mail Box Write - ldr w0,[x2] // W0 = Frame Buffer Pointer - cbz w0,FB_Init // IF (Frame Buffer Pointer == Zero) Re-Initialize Frame Buffer - and w0,w0,0x3FFFFFFF // Convert Mail Box Frame Buffer Pointer From BUS Address To Physical Address ($CXXXXXXX -> $3XXXXXXX) - str w0,[x2] // Store Frame Buffer Pointer Physical Address - add w10,w0,wzr + orr x1, x1, PERIPHERAL_BASE + str w0, [x1, MAIL_WRITE + MAIL_TAGS] // Mail Box Write + ldr w0, [x2] // W0 = Frame Buffer Pointer + cbz w0, FB_Init // IF (Frame Buffer Pointer == Zero) Re-Initialize Frame Buffer + and w0, w0, 0x3FFFFFFF // Convert Mail Box Frame Buffer Pointer From BUS Address To Physical Address ($CXXXXXXX -> $3XXXXXXX) + str w0, [x2] // Store Frame Buffer Pointer Physical Address + add w10, w0, wzr b main .align 16 @@ -138,5 +138,3 @@ FB_SIZE: .word 0x00000000 // $0 (End Tag) FB_STRUCT_END: - -//.include "app.s" diff --git a/test.s b/test.s new file mode 100644 index 0000000..2f79ef7 --- /dev/null +++ b/test.s @@ -0,0 +1,240 @@ + +.globl makeSomePixels +// NOTE makeSomePixels +makeSomePixels: + sub sp, sp, #8 + stur x30, [sp, #0] // Guardamos el return pointer en memoria + + // Primero con setPixel + mov x16, 320 // x setPixel + mov x12, 240 // y setPixel + bl setPixel // Pixel a pintar + mov x13, 17 // R + mov x14, 88 // G + mov x15, 253 // B + bl setColour // R+G+B = Azul + stur w18, [x0] + + mov x13, 250 // R + mov x14, 250 // G + mov x15, 250 // B + bl setColour // R+G+B = Azul + + mov x16, 330 // x setPixel + mov x12, 240 // y setPixel + bl setPixel // Pixel a pintar + stur w18, [x0] + mov x16, 310 // x setPixel + mov x12, 240 // y setPixel + bl setPixel // Pixel a pintar + stur w18, [x0] + mov x16, 320 // x setPixel + mov x12, 250 // y setPixel + bl setPixel // Pixel a pintar + stur w18, [x0] + mov x16, 320 // x setPixel + mov x12, 230 // y setPixel + bl setPixel // Pixel a pintar + stur w18, [x0] + + // Luego con drawPixel + mov x13, 10 // R + mov x14, 250 // G + mov x15, 10 // B + bl setColour // R+G+B = Azul + mov x16, 10 // x setPixel + mov x12, 10 // y setPixel + bl drawPixel // Dibuja el pixel + mov x16, 470 // x setPixel + mov x12, 630 // y setPixel + bl setPixel // Pixel a pintar + mov x16, 480 // x setPixel + mov x12, 10 // y setPixel + bl setPixel // Pixel a pintar + mov x16, 10 // x setPixel + mov x12, 640 // y setPixel + bl setPixel // Pixel a pintar + + ldur x30, [sp, #0] // Guardamos el return pointer en memoria ret + add sp, sp, #8 // Liberamos memoria + ret + +.globl makeSomeLines +// NOTE makeSomeLines +makeSomeLines: // TODO Limpiar y cambiar x -> w en los stur + sub sp, sp, #8 + stur x30, [sp, #0] // Guardamos el return pointer en memoria + mov x21, 320 // xo + mov x22, 240 // yo + mov x23, 100 // w + mov x13, 255 // R + mov x14, 255 // G + mov x15, 0 // B + bl setColour // R+G+B = Amarillo + bl doHorizontalLine + + // Pintamos un rectágulo en el medio de la pantalla + mov x21, 320 // x2 + mov x22, 240 // y2 + mov x23, 20 // w largo de pixeles + mov x24, 40 // h alto de pixeles + mov x13, 255 // R + mov x14, 255 // G + mov x15, 255 // B + bl setColour // R+G+B = Blanco + bl doRectangle + + // Pintamos el origen del rectágunlo + mov x16, 320 // x s0etPixel + mov x12, 240 // y setPixel + bl setPixel // Pixel a pintar + mov x13, 255 // R + mov x14, 0 // G + mov x15, 8 // B + bl setColour // R+G+B = Rojo + stur x18, [x0] // Lo pinto + ldur x30, [sp, #0] // Guardamos el return pointer en memoria ret + add sp, sp, #8 // Liberamos memoria + ret + +.globl circleTest +// NOTE circleTest +circleTest: + sub sp, sp, #8 + stur x30, [sp, #0] // Guardamos el return pointer en memoria + mov x13, 250 // R + mov x14, 81 // G + mov x15, 171 // B + bl setColour // R+G+B = Rosa + stur x18, [x0] + mov x21, 320 // xc x centro + mov x22, 240 // yc y centro + mov x23, 20 // radio + bl doCircle + // Return + ldur x30, [sp, #0] // Guardamos el return pointer en memoria ret + add sp, sp, #8 // Liberamos memoria + ret + +.globl testLines +// NOTE testLines +testLines: + // Dibujamos una línea xc0, yc0 -> xc1, yc1 + mov x21, 150 + mov x22, 30 + mov x23, 50 + mov x24, 200 + mov x13, 85 // R + mov x14, 255 // G + mov x15, 237 // B + bl setColour // R+G+B = cyan 55ffed + bl drawLine + + // Task + mov x13, 255 // R + mov x14, 251 // G + mov x15, 0 // B + bl setColour // Amarillo fffb00 + mov x16, 150 + mov x12, 30 + bl drawPixel + mov x16, 50 + mov x12, 200 + bl drawPixel + + mov x21, #320 // xc x centro + mov x22, #300 // yc y centro + bl doRaven // Dibujamos un cuervo + + // Dibujamos una línea "vertical" + mov x21, 59 + mov x22, 59 + mov x23, 100 + mov x24, 100 + mov x13, 255 // R + mov x14, 145 // G + mov x15, 0 // B + bl setColour // R+G+B = Naranja + bl drawLine + + mov x13, 17 // R + mov x14, 253 // G + mov x15, 64 // B + bl setColour // Verde + mov x16, 59 + mov x12, 59 + bl drawPixel + mov x16, 100 + mov x12, 100 + bl drawPixel + + mov x13, 255 // R + mov x14, 145 // G + mov x15, 0 // B + bl setColour // R+G+B = Naranja + mov x21, 200 + //bl verticalLine + + mov x21, 300 + //bl verticalLine // NOTE OK + +.globl testRGB1 +// NOTE testRGB1 +testRGB1: + mov x13, 250 // R + mov x14, 81 // G + mov x15, 171 // B + bl setColour // R+G+B = Rosa + mov x21, 100 + //bl verticalLine + //bl lineAnimation + //bl rgbcycletest + +.globl testAnit +// NOTE testAnit +testAnit: + bl animationTest + bl circleAnimation1 + +.globl circleTest2 +// NOTE Circle Test2 +circleTest2: + sub sp, sp, #8 + stur x30, [sp, #0] // Guardamos el return pointer en memoria + // Dibujamos un círculo + // Medio es 320 x 240 + mov x13, 250 // R + mov x14, 81 // G + mov x15, 171 // B + bl setColour // R+G+B = Rosa + stur x18, [x0] + mov x21, 320 // xc x centro + mov x22, 240 // yc y centro + mov x23, 20 // radio + bl doCircle + // Return + ldur x30, [sp, #0] // Guardamos el return pointer en memoria ret + add sp, sp, #8 // Liberamos memoria + ret + +.globl testThings2 +// NOTE testThings2 +testThings2: + // Dibujamos un círculo + // Medio es 320 x 240 + // FIXME Checkear + mov x16, 320 + mov x12, 240 + bl setPixel + // + mov x13, 250 // R + mov x14, 81 // G + mov x15, 171 // B + bl setColour // R+G+B = Rosa + //stur x18, [x0] + //mov x16, 320 + //mov x12, 240 + mov x21, 110 // xc x centro + mov x22, 110 // yc y centro + mov x23, #100 // radio + bl doCircle diff --git a/todo.md b/todo.md index b0194b7..927de08 100644 --- a/todo.md +++ b/todo.md @@ -1,17 +1,20 @@ # Contenido -- [¿Cómo se corre desde el QEMU?](#¿Cómo-se-corre-desde-el-QEMU?) -- [Ejercicio 1](#Ejercicio-1) -- [Ejercicio 2](#Ejercicio-2) -- [TODO](#Todo) -- [Figuras a dibujar](#Figuras-a-dibujar) -- [Animaciones](#Animaciones) -- [Escenas](#Escenas) -- [Pixel Art](#Pixel-Art) - - [Colores](#Colores) +- [Contenido](#contenido) +- [¿Cómo se corre desde el QEMU?](#cómo-se-corre-desde-el-qemu) + - [Correr sin QEMU](#correr-sin-qemu) +- [Ejercicio 1](#ejercicio-1) +- [Ejercicio 2](#ejercicio-2) +- [TODO](#todo) +- [Animaciones](#animaciones) +- [Escenas](#escenas) +- [Figuras a dibujar](#figuras-a-dibujar) +- [Pixel Art](#pixel-art) + - [Colores](#colores) + - [Bugs XD](#bugs-xd) # ¿Cómo se corre desde el QEMU? -`make` +`make clean` `make runQEMU` @@ -55,7 +58,7 @@ NOTA IMPORTANTE: Tener en cuenta las diferencias existentes entre el set de inst - [x] Agregar y definir la variable del color del fondo. - [x] Definir variable de la velocidad de la animación (discutir). - - [ ] Definir la función `delay`. + - [x] Definir la función `delay`. - [x] Crear función `doHorizontalLine` para dibujar líneas horizontales. ```js @@ -68,7 +71,7 @@ NOTA IMPORTANTE: Tener en cuenta las diferencias existentes entre el set de inst x18 : Colour ``` -- [ ] Completar función para dibujar cuadrados. +- [x] Completar función para dibujar cuadrados. - [x] Completar función para dibujar rectángulos. @@ -81,8 +84,8 @@ NOTA IMPORTANTE: Tener en cuenta las diferencias existentes entre el set de inst - [x] Averiguar como correrlo con GBA (si es que se puede). - [-] (\S) Si no se puede, encontrar alternativa. -- [ ] Definir escenas para dibujarlas. - - [ ] Definir animaciones de transición. +- [x] Definir escenas para dibujarlas. + - [x] Definir animaciones de transición. - [x] Definir la función `paintScreen`. Esta función lo que hace es pintar la pantalla de un color. ```js Argumentos @@ -96,14 +99,16 @@ NOTA IMPORTANTE: Tener en cuenta las diferencias existentes entre el set de inst - [x] doDm (crea una `D` en mayúscula) - [x] doO (crea una `o` en minúscula) - [x] doE (crea una `e` en minúscula) + - [x] doEm (crea una `E` en mayúscula) - [x] doI (crea una `i` en minúscula) + - [x] doIm (crea una `I` en mayúscula) - [x] doZ (crea una `z` en minúscula) - [x] doM (crea una `m` en minúscula) - [x] doG (crea una `g` en minúscula) - [x] doGm (crea una `G` en mayúscula) - Crear las siguientes letras con esta [fuente](https://www.dafont.com/es/minitel.font?text=console) [font.s](font.s) (@shirosweets): - - [ ] doAm (crea una `a` en minúscula) + - [ ] doA (crea una `a` en minúscula) - [ ] doT (crea una `t` en minúscula) - [ ] doVm (crea una `V` en mayúscula) - [ ] doN (crea una `n` en minúscula) @@ -116,15 +121,24 @@ NOTA IMPORTANTE: Tener en cuenta las diferencias existentes entre el set de inst - [ ] Breve descripción de lo que hace. - [ ] "Argumentos" a utilizar. -- [ ] Averiguar por qué corre más rápido al separar archivos. +- [x] Averiguar por qué corre más rápido al separar archivos. - [x] Finalizar una estructura básica del EJ1. -- [ ] Estructura básica del EJ2. +- [x] Estructura básica del EJ2. - [ ] Repasar -- [ ] Buscar alternativa para no tener que checkear el memory_map.txt +- [x] Buscar alternativa para no tener que checkear el memory_map.txt + +- [x] Mover las animaciones de pantalla completa a `aScreenAnimations.s` + +- [x] Mover las funciones base para setear pixeles, pintar, etc. a `baseCore.s` + +- [ ] En el archivo `test.s`, en la función `makeSomeLines`: limpiar y cambiar x -> w en los stur + +- [ ] Importante: agregar guardado del registro **x30** de las funciones del archivo `test.s` + # Animaciones 1. Girar colores en RBG @@ -171,4 +185,36 @@ https://nootall.tumblr.com/image/613601319149846528 ## Colores https://www.rapidtables.com/web/color/RGB_Color.html -https://htmlcolorcodes.com/es/ \ No newline at end of file +https://htmlcolorcodes.com/es/ + +## Bugs XD + +Cuando ocurre este error hermoso: +```bash +shirosweets@shiro:~/Desktop/ORG/vc-framebuffer$ make remake +rm -f *.o memory_map.txt kernel8.list kernel8.img kernel8.elf +make run +make[1]: Entering directory '/home/shirosweets/Desktop/ORG/vc-framebuffer' +aarch64-linux-gnu-as -g --warn --fatal-warnings animations.s -o animations.o +aarch64-linux-gnu-as -g --warn --fatal-warnings draw.s -o draw.o +aarch64-linux-gnu-as -g --warn --fatal-warnings raven.s -o raven.o +aarch64-linux-gnu-as -g --warn --fatal-warnings font.s -o font.o +aarch64-linux-gnu-as -g --warn --fatal-warnings test.s -o test.o +aarch64-linux-gnu-as -g --warn --fatal-warnings owl.s -o owl.o +aarch64-linux-gnu-as -g --warn --fatal-warnings app.s -o app.o +aarch64-linux-gnu-as -g --warn --fatal-warnings baseCore.s -o baseCore.o +aarch64-linux-gnu-as -g --warn --fatal-warnings start.s -o start.o +aarch64-linux-gnu-as -g --warn --fatal-warnings screenAnimations.s -o screenAnimations.o +aarch64-linux-gnu-ld animations.o draw.o raven.o font.o test.o owl.o app.o baseCore.o start.o screenAnimations.o -T memmap -o kernel8.elf -M > memory_map.txt +screenAnimations.o: in function `paintScreen': +(.data+0x124): relocation truncated to fit: R_AARCH64_ADR_PREL_LO21 against symbol `PreFrameBuffer' defined in .data section in start.o +make[1]: *** [Makefile:16: kernel8.img] Error 1 +make[1]: Leaving directory '/home/shirosweets/Desktop/ORG/vc-framebuffer' +make: *** [Makefile:24: remake] Error 2 +``` + +Es porque el BL que debe realizar al compilarse es mayor al que puede realizar xdxdxd. + +Solución: renombre el archivo para que esté más arriba uwu + +--- \ No newline at end of file diff --git a/owl.s b/zowl.s similarity index 99% rename from owl.s rename to zowl.s index e697cd2..e444ba8 100644 --- a/owl.s +++ b/zowl.s @@ -1,4 +1,3 @@ -//.include "draw.s" .globl doOwl doOwl: diff --git a/raven.s b/zraven.s similarity index 99% rename from raven.s rename to zraven.s index fafbd69..d827f1c 100644 --- a/raven.s +++ b/zraven.s @@ -1,4 +1,3 @@ -//.include "draw.s" .globl doRaven doRaven: From 744b9e3b3bd9887b68f192a433702ad64510efcd Mon Sep 17 00:00:00 2001 From: diegogimenez04 Date: Sun, 13 Jun 2021 08:44:11 -0300 Subject: [PATCH 31/47] Added extra description for drawPixel --- baseCore.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/baseCore.s b/baseCore.s index 948454b..87a5b2b 100644 --- a/baseCore.s +++ b/baseCore.s @@ -14,7 +14,7 @@ .globl drawPixel drawPixel: - // Args: y=x12 -- x=x16 -- colour=x18 + // Args: y=x12 -- x=x16 -- colour=x18 -- BufferSwitch = x3 sub sp, sp, #8 stur x30, [sp, #0] bl setPixel // ret : x0 From 81ece8855579b517204d80e1f3b071fffdf8a315 Mon Sep 17 00:00:00 2001 From: diegogimenez04 Date: Sun, 13 Jun 2021 13:50:06 -0300 Subject: [PATCH 32/47] Escena de piramides con sol --- animations.s | 26 +++++++- app.s | 4 +- baseCore.s | 36 ++++++++++- draw.s | 167 ++++++++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 220 insertions(+), 13 deletions(-) diff --git a/animations.s b/animations.s index 38a0d43..2984f77 100644 --- a/animations.s +++ b/animations.s @@ -4,7 +4,7 @@ delay: add x8, xzr, xzr // counter = 0 add x8, x8, #0xFFF // counter = 0xF...F (un numero enorme) - lsl x8, x8, #8 // 3th = * 2^~10 (slow = 1s) // * 2^~9 (medium = ~0,3s) + lsl x8, x8, #9 // 3th = * 2^~10 (slow = 1s) // * 2^~9 (medium = ~0,3s) delayloop: cbz x8, delayEnd @@ -16,6 +16,30 @@ delayloop: delayEnd: ret +.globl longDelay +// NOTE delay +longDelay: + sub sp, sp, 16 + str x8, [sp, 8] + str x9, [sp] + + mov x8, 0 + add x8, x8, #0xFFF + lsl x8, x8, 15 + +ldelayloop: + cbz x8, ldelayEnd + ldur x9, [sp, #0] + stur x9, [sp, #0] + sub x8, x8, #1 // counter-- + b ldelayloop + +ldelayEnd: + ldr x9, [sp] + ldr x8, [sp, 8] + add sp, sp, 16 + ret + .globl lineAnimation // FIXME lineAnimation lineAnimation: diff --git a/app.s b/app.s index 6982b88..242d80c 100644 --- a/app.s +++ b/app.s @@ -44,13 +44,13 @@ main: mov x21, 200 mov x22, 250 bl doAnimacionInicial - mov x21, #320 // xc x centro + /*mov x21, #320 // xc x centro mov x22, #250 // yc y centro bl drawUpdate bl doRaven mov x21, #150 // xc x centro mov x22, #150 // yc y centro - bl doOwl // Dibujamos un búho + bl doOwl*/ // Dibujamos un búho ret /* diff --git a/baseCore.s b/baseCore.s index 87a5b2b..5597b33 100644 --- a/baseCore.s +++ b/baseCore.s @@ -11,7 +11,6 @@ .equ COLOR_2, 0xFFFF // Color blanco GB // 0x1607 .equ COLOR_NEGRO, 0x00 - .globl drawPixel drawPixel: // Args: y=x12 -- x=x16 -- colour=x18 -- BufferSwitch = x3 @@ -86,6 +85,41 @@ endUpdate: add sp, sp, 40 ret +.globl drawUpdateWithCleanScreen +drawUpdateWithCleanScreen: + // x28 PreFrameBuffer + // x20 FrameBuffer + sub sp, sp, 40 + str x8, [sp, 32] + str x7, [sp, 24] + str x9, [sp, 16] + str x10, [sp, 8] + str lr, [sp] + mov x8, x20 + mov x7, x28 + mov x9, 0 + ldr x10, TOTAL_PIXELS + mov w15, 0x00 + +updateLoopWithClean: + str w15, [x7] + str w15, [x8] + add x8, x8, 4 + add x7, x7, 4 + cmp x9, x10 + b.eq endUpdateAndClean + add x9, x9, 1 + b updateLoopWithClean + +endUpdateAndClean: + ldr x8, [sp, 32] + ldr x7, [sp, 24] + ldr x9, [sp, 16] + ldr x10, [sp, 8] + ldr lr, [sp] + add sp, sp, 40 + ret + .globl setColour // https://stackoverflow.com/questions/54918639/linking-2-object-files // NOTE setColour setColour: diff --git a/draw.s b/draw.s index f45c482..506fcc3 100644 --- a/draw.s +++ b/draw.s @@ -25,6 +25,7 @@ doAnimacionInicial: mov x25, 0 mov x3, #1 // Seteamos al PreFrameBuffer + loopDelay: bl delay // Retraso bl cleanScreen // Limpio la pantalla @@ -32,18 +33,63 @@ loopDelay: bl doCompuVentana add x21, x21, 6 // sub x22, x22, 3 // Muevo el mouse - bl doMouse - cmp x25, 19 - b.eq loopDelay2 + bl doMouse // Lo dibujo + cmp x25, 18 // Comparo si itere un par de veces + b.eq endFirstDelay // Cuando toque el boton del medio de la pantalla. Se rompe add x25, x25, 1 b loopDelay -loopDelay2: +endFirstDelay: bl delay bl cleanScreen bl doComputerBroken bl drawUpdate + bl longDelay + bl drawUpdateWithCleanScreen + bl drawUpdate + mov x21, 39 + mov x9, 0 + sub sp, sp, 8 + stur x9, [sp, 56] +doSun: bl cleanScreen + bl anPiramidesDia + + mov w18, 0xFFFFFF + mov x23, 30 + mov x22, 0 + bl circRelleno + + add x21, x21, 10 + bl drawUpdate + + ldr x9, [sp, 56] + cmp x9, 57 + b.eq endAnimacion + add x9, x9, 1 + str x9, [sp, 56] + + b doSun + +doNight: + +.globl circRelleno +circRelleno: + sub sp, sp, 16 + str x23, [sp, 8] + str lr, [sp] + +loopRelleno: + bl doCircle + cbz x23, endRellenoCir + sub x23, x23, 1 + b loopRelleno + +endRellenoCir: + ldr lr, [sp] + ldr x23, [sp, 8] + add sp, sp, 16 + ret endAnimacion: ldr lr, [sp] @@ -99,6 +145,101 @@ doComputerBroken: add sp, sp, 48 ret +.globl anPiramidesDia +// NOTE Segunda animacion +anPiramidesDia: + sub sp, sp, 56 + str x3, [sp, 40] + str x21, [sp, 32] + str x22, [sp, 24] + str x23, [sp, 16] + str x24, [sp, 8] + str lr, [sp] + mov x3, 1 + + // Fondo + movz w18, 0xF3, lsl 16 + movk w18, 0x9F18, lsl 0 + mov x21, 0 + mov x22, 0 + mov x23, 640 + mov x24, 480 + bl doRectangle + + // Piramides + mov w18, 0xFFFF00 + mov x21, 200 + mov x22, 300 + mov x23, 50 + bl doPiramide + add x21, x21, 200 + add x23, x23, x23 + bl doPiramide + + // Desierto + mov x21, 0 + mov x23, 640 + mov x24, 480 + bl doRectangle + mov x21, 50 + mov x22, 0 + mov x23, 50 + +endAnPir: + ldr lr, [sp] + ldr x24, [sp, 8] + ldr x23, [sp, 16] + ldr x22, [sp, 24] + ldr x21, [sp, 32] + ldr x3, [sp, 40] + add sp, sp, 56 + ret + +.globl anPiramideNoche +anPiramideNoche: + sub sp, sp, 40 + str x21, [sp, 32] + str x22, [sp, 24] + str x23, [sp, 16] + str x24, [sp, 8] + str lr, [sp] + + // Fondo + movz w18, 0xF3, lsl 16 + movk w18, 0x9F18, lsl 0 + mov x21, 0 + mov x22, 0 + mov x23, 640 + mov x24, 480 + bl doRectangle + + // Piramides + mov w18, 0xFFFF00 + mov x21, 200 + mov x22, 300 + mov x23, 50 + bl doPiramide + add x21, x21, 200 + add x23, x23, x23 + bl doPiramide + + // Desierto + mov x21, 0 + mov x23, 640 + mov x24, 480 + bl doRectangle + mov x21, 50 + mov x22, 0 + mov x23, 50 + + ldr lr, [sp] + ldr x24, [sp, 8] + ldr x23, [sp, 16] + ldr x22, [sp, 24] + ldr x21, [sp, 32] + add sp, sp, 40 + + .globl doMouse // NOTE doMouse doMouse: @@ -467,7 +608,8 @@ doRectangle: // alto x largo// // x9 posición inicial de x // x10 posición inicial de y - sub sp, sp, #48 // Reservamos 2 registros de memoria + sub sp, sp, #56 // Reservamos memoria + str x3, [sp, 48] stur x21, [sp, 40] stur x22, [sp, 32] stur x23, [sp, 24] @@ -492,7 +634,8 @@ endRectangule: ldur x23, [sp, 24] ldur x22, [sp, 32] ldur x21, [sp, 40] - add sp, sp, 48 // Reservamos 2 registros de memoria + ldr x3, [sp, 48] + add sp, sp, 56 // Reservamos 2 registros de memoria ret .globl doCircle @@ -510,7 +653,10 @@ doCircle: // Mid-Point Circle Drawing Algorithm // // x25 x // x26 y // x27 P - sub sp, sp, #16 + sub sp, sp, #40 + stur x23, [sp, 32] + stur x22, [sp, 24] + stur x21, [sp, 16] stur x27, [sp, 8] stur x30, [sp, #0] // Guardamos el return pointer en memoria mov x25, x23 // x = r @@ -605,9 +751,12 @@ cirif2: // if (x < y) b.gt doCircleLoop circleEnd: - ldur x30, [sp, #0] // Guardamos el return pointer en memoria ret + ldur x30, [sp] // Guardamos el return pointer en memoria ret ldur x27, [sp, 8] - add sp, sp, #16 + ldur x21, [sp, 16] + ldur x22, [sp, 24] + ldur x23, [sp, 32] + add sp, sp, 40 ret .globl doTriangleUp From f398ddd0c1d7c30628af870e028abc215484adb5 Mon Sep 17 00:00:00 2001 From: diegogimenez04 Date: Sun, 13 Jun 2021 14:27:11 -0300 Subject: [PATCH 33/47] Animacion piramide dia y noche --- draw.s | 66 +++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 45 insertions(+), 21 deletions(-) diff --git a/draw.s b/draw.s index 506fcc3..699c81d 100644 --- a/draw.s +++ b/draw.s @@ -25,7 +25,6 @@ doAnimacionInicial: mov x25, 0 mov x3, #1 // Seteamos al PreFrameBuffer - loopDelay: bl delay // Retraso bl cleanScreen // Limpio la pantalla @@ -45,12 +44,11 @@ endFirstDelay: bl doComputerBroken bl drawUpdate bl longDelay - bl drawUpdateWithCleanScreen - bl drawUpdate mov x21, 39 mov x9, 0 sub sp, sp, 8 stur x9, [sp, 56] + doSun: bl cleanScreen bl anPiramidesDia @@ -65,13 +63,46 @@ doSun: ldr x9, [sp, 56] cmp x9, 57 - b.eq endAnimacion + b.eq doNoche add x9, x9, 1 str x9, [sp, 56] b doSun -doNight: +doNoche: + add sp, sp, 8 + sub sp, sp, 8 + mov x9, 0 + str x9, [sp, 56] + mov x21, 0 +loopNoche: + bl cleanScreen + bl anPiramidesNoche + + mov w18, 0xFFFFFF + mov x23, 30 + mov x22, 0 + bl circRelleno + add x21, x21, 10 + bl drawUpdate + + ldr x9, [sp, 56] + cmp x9, 57 + b.eq endAnimacion + add x9, x9, 1 + str x9, [sp, 56] + b loopNoche + +endAnimacion: + ldr lr, [sp] + ldr x22, [sp, 8] + ldr x21, [sp, 16] + ldr x23, [sp, 24] + ldr x24, [sp, 32] + ldr x25, [sp, 40] + ldr x3, [sp, 48] + add sp, sp, 56 + ret .globl circRelleno circRelleno: @@ -91,16 +122,6 @@ endRellenoCir: add sp, sp, 16 ret -endAnimacion: - ldr lr, [sp] - ldr x22, [sp, 8] - ldr x21, [sp, 16] - ldr x23, [sp, 24] - ldr x24, [sp, 32] - ldr x25, [sp, 40] - ldr x3, [sp, 48] - add sp, sp, 56 - ret .globl doComputerBroken // NOTE doComputerBroken @@ -195,8 +216,8 @@ endAnPir: add sp, sp, 56 ret -.globl anPiramideNoche -anPiramideNoche: +.globl anPiramidesNoche +anPiramidesNoche: sub sp, sp, 40 str x21, [sp, 32] str x22, [sp, 24] @@ -205,8 +226,8 @@ anPiramideNoche: str lr, [sp] // Fondo - movz w18, 0xF3, lsl 16 - movk w18, 0x9F18, lsl 0 + movz w18, 0x31, lsl 16 + movk w18, 0x1f62, lsl 0 mov x21, 0 mov x22, 0 mov x23, 640 @@ -214,7 +235,8 @@ anPiramideNoche: bl doRectangle // Piramides - mov w18, 0xFFFF00 + movz w18, 0x8d, lsl 16 + movk w18, 0x5273, lsl0 mov x21, 200 mov x22, 300 mov x23, 50 @@ -224,6 +246,8 @@ anPiramideNoche: bl doPiramide // Desierto + movz w18, 0xc3, lsl 16 + movk w18, 0x727c, lsl0 mov x21, 0 mov x23, 640 mov x24, 480 @@ -238,7 +262,7 @@ anPiramideNoche: ldr x22, [sp, 24] ldr x21, [sp, 32] add sp, sp, 40 - + ret .globl doMouse // NOTE doMouse From aa50d98dcbfb4edd77042caed980140e68a485ad Mon Sep 17 00:00:00 2001 From: diegogimenez04 Date: Sun, 13 Jun 2021 14:45:40 -0300 Subject: [PATCH 34/47] Loop infinito dia y noche --- draw.s | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/draw.s b/draw.s index 699c81d..0f22d91 100644 --- a/draw.s +++ b/draw.s @@ -44,11 +44,12 @@ endFirstDelay: bl doComputerBroken bl drawUpdate bl longDelay + +preDoSun: mov x21, 39 mov x9, 0 sub sp, sp, 8 stur x9, [sp, 56] - doSun: bl cleanScreen bl anPiramidesDia @@ -87,8 +88,8 @@ loopNoche: bl drawUpdate ldr x9, [sp, 56] - cmp x9, 57 - b.eq endAnimacion + cmp x9, 65 + b.eq preDoSun add x9, x9, 1 str x9, [sp, 56] b loopNoche From 40a86b7401aaf21ac06d14a8955524eff3d2c84c Mon Sep 17 00:00:00 2001 From: diegogimenez04 Date: Sun, 13 Jun 2021 14:55:34 -0300 Subject: [PATCH 35/47] Better colors for day --- draw.s | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/draw.s b/draw.s index 0f22d91..7e31a48 100644 --- a/draw.s +++ b/draw.s @@ -54,7 +54,8 @@ doSun: bl cleanScreen bl anPiramidesDia - mov w18, 0xFFFFFF + movz w18, 0xF2, lsl 16 + movk w18, 0x740B, lsl 0 mov x23, 30 mov x22, 0 bl circRelleno @@ -63,7 +64,7 @@ doSun: bl drawUpdate ldr x9, [sp, 56] - cmp x9, 57 + cmp x9, 58 b.eq doNoche add x9, x9, 1 str x9, [sp, 56] @@ -180,8 +181,8 @@ anPiramidesDia: mov x3, 1 // Fondo - movz w18, 0xF3, lsl 16 - movk w18, 0x9F18, lsl 0 + movz w18, 0xA3, lsl 16 + movk w18, 0x371F, lsl 0 mov x21, 0 mov x22, 0 mov x23, 640 @@ -189,7 +190,8 @@ anPiramidesDia: bl doRectangle // Piramides - mov w18, 0xFFFF00 + movz w18, 0xDF, lsl 16 + movk w18, 0x915E, lsl 0 mov x21, 200 mov x22, 300 mov x23, 50 @@ -199,6 +201,8 @@ anPiramidesDia: bl doPiramide // Desierto + movz w18, 0x6B, lsl 16 + movk w18, 0x3E3E, lsl 0 mov x21, 0 mov x23, 640 mov x24, 480 From 7591a33d6bf6984029fe2b46a8450feaa6ba49d4 Mon Sep 17 00:00:00 2001 From: diegogimenez04 Date: Sun, 13 Jun 2021 18:12:00 -0300 Subject: [PATCH 36/47] Pepe --- draw.s | 12 ++++++++++++ font.s | 36 +++++++++++++++++++++++++++++++----- 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/draw.s b/draw.s index 7e31a48..5f9e732 100644 --- a/draw.s +++ b/draw.s @@ -211,6 +211,12 @@ anPiramidesDia: mov x22, 0 mov x23, 50 + movz w18, 0xFF, lsl 16 + movk w18, 0xFFFF, lsl 0 + mov x22, 350 + mov x21, 100 + bl doDiego + endAnPir: ldr lr, [sp] ldr x24, [sp, 8] @@ -261,6 +267,12 @@ anPiramidesNoche: mov x22, 0 mov x23, 50 + movz w18, 0x00, lsl 16 + movk w18, 0x0000, lsl 0 + mov x22, 350 + mov x21, 100 + bl doDiego + ldr lr, [sp] ldr x24, [sp, 8] ldr x23, [sp, 16] diff --git a/font.s b/font.s index 137b017..6b1b4e8 100644 --- a/font.s +++ b/font.s @@ -414,6 +414,32 @@ endM: // NOTE n doN: // @Vale + // Args + // x21 x + // x22 y + sub sp, sp, 32 + str x21, [sp, 24] + str x22, [sp, 16] + str x23, [sp, 8] + str lr, [sp] + + add x22, x22, 5 + + mov x23, 15 + bl vertLine + mov x23, 9 + bl doHorizontalLine + add x21, x21, 10 + add x22, x22, 1 + mov x23, 14 + bl vertLine + + ldr lr, [sp] + ldr x23, [sp, 8] + ldr x22, [sp, 16] + ldr x21, [sp, 24] + add sp, sp, 32 + ret .globl doVm // NOTE V @@ -467,7 +493,7 @@ doZDiag: sub x21, x21, 1 sub x16, x16, 1 add x12, x12, 1 - cmp x9, 20 + cmp x9, 19 b.eq doZBot add x9, x9, 1 b doZDiag @@ -617,7 +643,7 @@ doDiego: sub x22, x22, 8 add x21, x21, 50 bl doGm - add x21, x21, 20 + add x21, x21, 25 bl doI add x21, x21, 10 add x22, x22, 5 @@ -625,11 +651,11 @@ doDiego: sub x22, x22, 5 add x21, x21, 30 bl doE - add x21, x21, 20 + add x21, x21, 15 bl doN - add x21, x21, 20 + add x21, x21, 25 bl doE - add x21, x21, 20 + add x21, x21, 15 bl doZ endDiego: From 3fec7bb34d6ea9559e39b2237d0e19baa17a35b1 Mon Sep 17 00:00:00 2001 From: Valentina Vispo Date: Sun, 13 Jun 2021 21:48:09 -0300 Subject: [PATCH 37/47] Add doCircle with Fill, fix cleanScreen and paintScreen, and add cleanScreenBuffer and paintScreenBuffer --- aScreenAnimations.s | 34 +++++++++++++++++ animations.s | 13 +++++++ app.s | 5 +++ baseCore.s | 10 +---- docs/variables.md | 90 +++++++++++++++++++++++++++++--------------- draw.s | 73 ++++++++++++++++++++++++++++++++--- png/circle.png | Bin 0 -> 26091 bytes test.s | 36 ++++++++++++++++-- 8 files changed, 213 insertions(+), 48 deletions(-) create mode 100644 png/circle.png diff --git a/aScreenAnimations.s b/aScreenAnimations.s index fe3a234..4504861 100644 --- a/aScreenAnimations.s +++ b/aScreenAnimations.s @@ -108,6 +108,40 @@ cleanScreen: // Pinta toda la pantalla de negro add sp, sp, #16 ret +.globl cleanScreenBuffer +// NOTE cleanScreenBuffer +cleanScreenBuffer: // Pinta toda la pantalla de negro + sub sp, sp, #16 + stur lr, [sp] // Guardo el link register para no pisarlo + stur x30, [sp, #8] // Guardamos el return pointer en memoria + mov x13, xzr // R + mov x14, xzr // G + mov x15, xzr // B + bl setColour // Negro + bl paintScreenBuffer + ldur x30, [sp, #8] // Guardamos el return pointer en memoria ret + ldur lr, [sp] // Devuelvo el link register + add sp, sp, #16 + ret + +.globl paintScreenBuffer +// NOTE paintScreenBuffer +paintScreenBuffer: // 320w 240h -> 76800 + 240 + // Return -> nada + // Args: x18 Colour + mov x0, x20 // Origen del frameBuffer + mov x8, SCREEN_WIDTH + mov x9, SCREEN_HEIGH + mul x8, x8, x9 // x8 contador de pixeles a pintar + // paintScreenBufferLoop... + +paintScreenBufferLoop: + stur w18, [x0] // Set color of pixel N + add x0, x0, 4 // Next pixel + sub x8, x8, 1 // decrement pixel counter + cbnz x8, paintScreenBufferLoop // If not end row jump + ret + .globl paintScreen // NOTE paintScreen paintScreen: // 320w 240h -> 76800 + 240 diff --git a/animations.s b/animations.s index 38a0d43..067ef97 100644 --- a/animations.s +++ b/animations.s @@ -146,3 +146,16 @@ rgbaniloop: bl delay bl rgbAnimation b rgbaniloop + +.globl doSceneEye +// NOTE dpScemeEue +doSceneEye: + //sub sp, sp, #??? // Guardamos 1 lugar del stack + stur x30, [sp, #0] // Registro 30 para el RET en el stack + // Ojo + + // + +endDoSceneEye: + ret + diff --git a/app.s b/app.s index 6982b88..6cc9487 100644 --- a/app.s +++ b/app.s @@ -51,6 +51,11 @@ main: mov x21, #150 // xc x centro mov x22, #150 // yc y centro bl doOwl // Dibujamos un búho + mov x3, #0 + //bl circleTest + bl circleTestFill + //bl cleanScreenBuffer + b EndMain ret /* diff --git a/baseCore.s b/baseCore.s index 87a5b2b..19eb642 100644 --- a/baseCore.s +++ b/baseCore.s @@ -26,14 +26,8 @@ drawBuffer: b drawPixelEnd drawPrebuffer: // then dibujar en x28 - // direccion del buffer = x20 - // direccion del prebuffer = x28 - // x20 + (x28-x20) = x28 - // x20 + offset + (x28-x20) = x28 + offset - // x20 + offset = X0 -> - // X0 + X28 - X20 = X28 + offset == traducción del buffer al prebuffer - add x8, x0, x28 - sub x8, x8, x20 + add x8, x0, x28 // Traducción del buffer al prebuffer: + sub x8, x8, x20 // x8 = x0 + (X28 - X20) drawPixelEnd: stur w18, [x8] // stur xN guarda 64bits, y stur wN guarda medio registro (32bits) diff --git a/docs/variables.md b/docs/variables.md index dbe22c2..dd94f3c 100644 --- a/docs/variables.md +++ b/docs/variables.md @@ -7,15 +7,33 @@ .equ COLOR_2, 0xFFFF // Color blanco GB // 0x1607 .equ COLOR_NEGRO, 0x00 ``` -// NOTE Registros globales // -// SCREEN_HEIGH -// SCREEN_WIDTH -// x0 Pixel a pintar -// x18 Colour -// x20 Base del framebuffer +## Registros globales +`SCREEN_HEIGH` +`SCREEN_WIDTH` +`x0` Pixel a pintar +`x18` Colour +`x20` Base del framebuffer +`x28` PreFrameBuffer + +## Registros basura +Son aquellos registros que no se puede estar seguro de qué contienen o que su contenido no se sobreescribe. Se deben utilizar con precaución. +`x1` +`x2` +`x8` +`x9` +`x10` # drawPixel -Args: y=x12 -- x=x16 -- colour=x18 +```java +drawPixel(x = x16, y = x12, colour = x18, bufferSwitch = x3) -> None +``` +**Args** + +x - Coordena x del pixel + +y - Coordena y del pixel + +bufferSwitch - Si es **x3 == 0** lo dibuja en el buffer principal (alocado en `x0` y `x20`), sino en el buffer secundario (alocado en `x28`) # setPixel ```java @@ -27,30 +45,42 @@ setPixel(x = x16, y = x12) -> x0 : Pixel a pintar setColour(r = x13, g = x14, b = x15) -> x18 : Color a pintar ``` +# cleanScreen +Limpia la pantalla en el buffer secundario (alocado en `x28`) +```java +cleanScreen(colour = x18) -> None +``` +**Importante**: lo pinta de negro puro, si se desea cambiar se debe modificar la función + +# cleanScreenBuffer +Limpia la pantalla en el buffer principal (alocado en `x0` y `x20`) +```java +cleanScreenBuffer(colout = x18) -> None +``` +**Importante**: lo pinta de negro puro, si se desea cambiar se debe modificar la función + +--- # doSquare +```java +doSquare(xo = x21, yo = x22, w = x23, colour = x18) -> None +``` +`xo` - x dónde empiezo a dibujar la figura +`yo` - y dónde empiezo a dibujar la figura + +`w` - cantidad de pixeles -# doRectangule - // Args - // setPixel x16 x, x12 y - // x21 x2 lugar dónde empiezo a dibujar la figura - // x22 y2 lugar dónde empiezo a dibujar la figura - // x23 w largo en pixeles - // x24 h alto en pixeles - // x18 colour - // Used - // x9 posición inicial de x - // x10 posición inicial de y # doCircle (S1) https://en.wikipedia.org/wiki/Midpoint_circle_algorithm ```java -doCircle(xc = x21, yc = x22, radio=x23, colour=x18) -> None +doCircle(xc = x21, yc = x22, radio=x23, colour=x18, no_fill=x24) -> None + +no_fill != 0 -> circulo relleno x25 = x x26 = y x27 = P - ``` `xc` - coordenada x del centro `yc `- coordenada y del centro @@ -76,12 +106,15 @@ x27 = P doRectangle(x0 = x21, y0 = x22, width = x23, height = x24, colour = x18) ``` -Return -> nada -Args -x21 x2 lugar dónde empiezo a dibujar la figura -x22 y2 lugar dónde empiezo a dibujar la figura -x23 w cantidad de píxeles -x18 colour +**Args** + +x21 - x2 lugar dónde empiezo a dibujar la figura + +x22 - y2 lugar dónde empiezo a dibujar la figura + +x23 - w cantidad de píxeles + +x18 - colour # doTriangle ```java @@ -90,8 +123,3 @@ doTriangle(x2 = x21, y2 = x22, w = x23, colour = x18) -> None `x2` - lugar dónde empiezo a dibujar la figura `y2` - lugar dónde empiezo a dibujar la figura `w` - cantidad de píxeles - -# cleanScreen -```java -cleanScreen(colour = x18) -> None -``` \ No newline at end of file diff --git a/draw.s b/draw.s index f45c482..8506fda 100644 --- a/draw.s +++ b/draw.s @@ -11,6 +11,7 @@ .equ COLOR_2, 0xFFFF // Color blanco GB // 0x1607 .equ COLOR_NEGRO, 0x00 + .globl doAnimacionInicial // NOTE doAnimacionInicial doAnimacionInicial: @@ -102,7 +103,6 @@ doComputerBroken: .globl doMouse // NOTE doMouse doMouse: - // @Diego // Args // x21 x // x22 y @@ -235,7 +235,6 @@ doCompuVentana: .globl triangDer // NOTE Triángulo apuntando a la derecha triangDer: - // @Diego // Args // x21 x // x22 y @@ -432,7 +431,6 @@ endDrawLine: .globl doSquare // NOTE Square doSquare: - // Return -> nada // Args // x21 xo lugar dónde empiezo a dibujar la figura // x22 yo lugar dónde empiezo a dibujar la figura @@ -453,8 +451,6 @@ doSquare: .globl doRectangle // NOTE Rectangle alto(h) x largo(w) doRectangle: // alto x largo// - // @Diego - // Return -> nada // Args // x21 x2 lugar dónde empiezo a dibujar la figura // x22 y2 lugar dónde empiezo a dibujar la figura @@ -505,6 +501,7 @@ doCircle: // Mid-Point Circle Drawing Algorithm // // x21 xc x centro // x22 yc y centro // x23 r radio (asumimos que el radio es mayor que 0) + // x24 no fill in: (x24 == 0 -> Fill, x24 != 0 -> No Fill) // x18 colour // Used // x25 x @@ -531,6 +528,26 @@ doCircle: // Mid-Point Circle Drawing Algorithm // sub x16, x21, x23 // x16 xd = xc - r mov x12, x22 // x12 yd = yc bl drawPixel + cbnz x24, doCircleLoop // doCircleLoop... + b doPixelsForCircleFill + +doPixelsForCircleFill: + sub sp, sp, #16 + stur x6, [sp, #8] + stur x5, [sp, #0] + + mov x5, x22 // x5 = yc + mov x6, x23 // x6 = r + + sub x22, x5, x6 // yd = yc - r + lsl x23, x6, #1 // h = 2 * r + bl vertLine // x21 x - x22 y - x23 height + + mov x22, x5 + mov x23, x6 + ldur x6, [sp, #8] + ldur x5, [sp, #0] + add sp, sp, #16 // doCircleLoop... doCircleLoop: // While x > y @@ -561,7 +578,11 @@ cirelse1: // Mid-point is outside the perimeter cirif2: // if (x < y) cmp x25, x26 b.lt circleEnd + cbnz x24, circlNoFill + bl circleFillAux + b doCircleLoop +circlNoFill: add x16, x25, x21 // x16 xd = x + x_centre add x12, x26, x22 // x12 yd = y + y_centre bl drawPixel @@ -610,6 +631,48 @@ circleEnd: add sp, sp, #16 ret +circleFillAux: + sub sp, sp, #32 + stur x4, [sp, #24] + stur x5, [sp, #16] + stur x23, [sp, #8] + stur x30, [sp, #0] // Guardamos el return pointer en memoria ret + + mov x4, x21 // x4 = xc + mov x5, x22 // x5 = yc + add x21, x4, x25 // x = xc + x + sub x22, x5, x26 // y = yc - y + mov x23, x26 + add x23, x23, x26 // height = 2*y + 1 + bl vertLine + + sub x21, x4, x25 // x = xc - x + bl vertLine + + cmp x25, x26 + b.eq endCircleFillAux // Siguientes cuadrantes... + + add x21, x4, x26 // x = xc + y + sub x22, x5, x25 // y = yc - x + add x23, x25, x25 // height = 2 * x + bl vertLine + + sub x21, x4, x26 // x = xc - y + sub x22, x5, x25 // y = yc - x + mov x23, x25 + add x23, x23, x25 // height = 2 * x + bl vertLine + +endCircleFillAux: + mov x21, x4 + mov x22, x5 + ldur x30, [sp, #0] // Guardamos el return pointer en memoria ret + ldur x23, [sp, #8] + ldur x5, [sp, #16] + ldur x4, [sp, #24] + add sp, sp, #32 + ret + .globl doTriangleUp // NOTE Triángulo hacia arriba doTriangleUp: diff --git a/png/circle.png b/png/circle.png new file mode 100644 index 0000000000000000000000000000000000000000..94517cc31a23658e96b181e64210b30cdd9b5001 GIT binary patch literal 26091 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 z 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 C22l xc1, yc1 mov x21, 150 mov x22, 30 @@ -177,6 +202,9 @@ testLines: mov x21, 300 //bl verticalLine // NOTE OK + ldur x30, [sp, #0] // Guardamos el return pointer en memoria ret + add sp, sp, #8 // Liberamos memoria + ret .globl testRGB1 // NOTE testRGB1 From 1b27eaff9c617c592f476abbf1134e02b4492e61 Mon Sep 17 00:00:00 2001 From: diegogimenez04 Date: Sun, 13 Jun 2021 21:58:31 -0300 Subject: [PATCH 38/47] Arreglando ultimas cosas en tema piramides --- baseCore.s | 17 +++++++++++------ draw.s | 47 +++++++++++++++++++++++++++++------------------ font.s | 12 +++++++----- 3 files changed, 47 insertions(+), 29 deletions(-) diff --git a/baseCore.s b/baseCore.s index 5597b33..609f72c 100644 --- a/baseCore.s +++ b/baseCore.s @@ -14,7 +14,8 @@ .globl drawPixel drawPixel: // Args: y=x12 -- x=x16 -- colour=x18 -- BufferSwitch = x3 - sub sp, sp, #8 + sub sp, sp, #16 + str x8, [sp, 8] stur x30, [sp, #0] bl setPixel // ret : x0 cbz x3, drawBuffer // if x3 == 0 dibujar en el buffer @@ -37,7 +38,8 @@ drawPrebuffer: // then dibujar en x28 drawPixelEnd: stur w18, [x8] // stur xN guarda 64bits, y stur wN guarda medio registro (32bits) ldur x30, [sp, #0] - add sp, sp, #8 + ldr x8, [sp, 8] + add sp, sp, #16 ret .globl setPixel @@ -61,6 +63,7 @@ drawUpdate: str x9, [sp, 16] str x10, [sp, 8] str lr, [sp] + mov x8, x20 mov x7, x28 mov x9, 0 @@ -71,17 +74,19 @@ updateLoop: str w6, [x8] add x8, x8, 4 add x7, x7, 4 + cmp x9, x10 b.eq endUpdate + add x9, x9, 1 b updateLoop endUpdate: - ldr x8, [sp, 32] - ldr x7, [sp, 24] - ldr x9, [sp, 16] - ldr x10, [sp, 8] ldr lr, [sp] + ldr x10, [sp, 8] + ldr x9, [sp, 16] + ldr x7, [sp, 24] + ldr x8, [sp, 32] add sp, sp, 40 ret diff --git a/draw.s b/draw.s index 5f9e732..6186b0f 100644 --- a/draw.s +++ b/draw.s @@ -128,7 +128,10 @@ endRellenoCir: .globl doComputerBroken // NOTE doComputerBroken doComputerBroken: - sub sp, sp, 48 + sub sp, sp, 72 + str x7, [sp, 64] + str x8, [sp, 56] + str x9, [sp, 48] stur x25, [sp, 40] stur x24, [sp, 32] stur x23, [sp, 24] @@ -138,34 +141,42 @@ doComputerBroken: bl doCompuVentana bl doMouse - mov x21, 115 - mov x22, 114 - mov x23, 10 - mov x24, 10 - bl doRectangle - add x21, x21, 50 + mov x22, 80 + mov x23, 8 + mov x24, 8 + mov x10, 40 + mov x9, 0 + mov x7, 0 + +loopCompBro1: //FIXME No anda + cmp x9, 12 + b.eq endCompBro + mov x7, 0 add x22, x22, 20 - bl doRectangle - add x21, x21, 100 - sub x22, x22, 40 - bl doRectangle + mov x21, 120 - mov x21, 300 - mov x22, 300 - mov x23, 5 - bl doRectangle +loopCompBro2: + cmp x7, x10 + b.eq endLoopCompBro2 - mov x21, 350 - mov x22, 200 + add x21, x21, 10 bl doRectangle + + add x7, x7, 1 + b loopCompBro2 +endLoopCompBro2: + add x9, x9, 1 + b loopCompBro1 +endCompBro: ldr lr, [sp] ldr x22, [sp, 8] ldr x21, [sp, 16] ldr x23, [sp, 24] ldr x24, [sp, 32] ldr x25, [sp, 40] - add sp, sp, 48 + ldr x9, [sp, 48] + add sp, sp, 56 ret .globl anPiramidesDia diff --git a/font.s b/font.s index 6b1b4e8..244610a 100644 --- a/font.s +++ b/font.s @@ -467,7 +467,7 @@ doT: .globl doZ // NOTE z -doZ: +doZ: // REVIEW Done // Args // x21 x inicial // x22 y inicial @@ -511,7 +511,7 @@ endZ: .globl doGm // NOTE G mayus -doGm: +doGm: // REVIEW Done // Args // x21 x inicial // x22 y inicial @@ -562,7 +562,7 @@ doGm: .globl doG // NOTE g -doG: +doG: // REVIEW Done // @Diego // Args // x21 x inicial @@ -612,7 +612,7 @@ doG: .globl doDiego // NOTE Diego -doDiego: +doDiego: // REVIEW Done // Args // x21 x // x22 y @@ -634,7 +634,9 @@ doDiego: bl doE add x21, x21, 20 - bl doGm + add x22, x22, 10 + bl doG + sub x22, x22, 10 add x21, x21, 20 add x22, x22, 8 From 40976dbd202c5a9d5dff8ea2dd4d6abe051fa556 Mon Sep 17 00:00:00 2001 From: diegogimenez04 Date: Sun, 13 Jun 2021 23:33:59 -0300 Subject: [PATCH 39/47] Estrella --- draw.s | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/draw.s b/draw.s index 6186b0f..d95efda 100644 --- a/draw.s +++ b/draw.s @@ -86,6 +86,8 @@ loopNoche: mov x22, 0 bl circRelleno add x21, x21, 10 + mov x18, 0xFFFFFF + bl doEstrella bl drawUpdate ldr x9, [sp, 56] @@ -106,6 +108,29 @@ endAnimacion: add sp, sp, 56 ret +.globl doEstrella +// NOTE Estrella +doEstrella: + sub sp, sp, 32 + str x21, [sp, 24] + str x22, [sp, 16] + str x23, [sp, 8] + str lr, [sp] + + mov x23, 5 + bl doHorizontalLine + add x21, x21, 2 + sub x22, x22, 2 + bl vertLine + + ldr lr, [sp] + ldr x23, [sp, 8] + ldr x22, [sp, 16] + ldr x21, [sp, 24] + add sp, sp, 32 + + ret + .globl circRelleno circRelleno: sub sp, sp, 16 From 12759f59e4bdd448fda04e7edde6f6528d277c10 Mon Sep 17 00:00:00 2001 From: diegogimenez04 Date: Mon, 14 Jun 2021 00:17:01 -0300 Subject: [PATCH 40/47] Limpie llamada a funcion estrella en doNight --- draw.s | 2 -- 1 file changed, 2 deletions(-) diff --git a/draw.s b/draw.s index d95efda..763c279 100644 --- a/draw.s +++ b/draw.s @@ -86,8 +86,6 @@ loopNoche: mov x22, 0 bl circRelleno add x21, x21, 10 - mov x18, 0xFFFFFF - bl doEstrella bl drawUpdate ldr x9, [sp, 56] From b37fd7dbe305644f1b088b16b964cda6c1f3e1e2 Mon Sep 17 00:00:00 2001 From: Valentina Vispo Date: Mon, 14 Jun 2021 11:08:11 -0300 Subject: [PATCH 41/47] New doG and doO (and fix bug in other branch) --- app.s | 14 +++++++- font.s | 107 +++++++++++++++++++++++++++++++-------------------------- 2 files changed, 71 insertions(+), 50 deletions(-) diff --git a/app.s b/app.s index 55d213c..9382866 100644 --- a/app.s +++ b/app.s @@ -43,7 +43,19 @@ main: bl cleanScreen mov x21, 200 mov x22, 250 - bl doAnimacionInicial + //bl doAnimacionInicial + mov x13, 255 // R + mov x14, 255 // G + mov x15, 255 // B + bl setColour // R+G+B = Blanco + mov x23, 400 + bl doHorizontalLine + mov x13, 255 // R + mov x14, 255 // G + mov x15, 8 // B + bl setColour // R+G+B = Rojo + mov x23, 20 + bl doDiego /*mov x21, #320 // xc x centro mov x22, #250 // yc y centro bl drawUpdate diff --git a/font.s b/font.s index 244610a..03b5f8c 100644 --- a/font.s +++ b/font.s @@ -200,31 +200,30 @@ doI: .globl doO // NOTE o doO: - // Args - // x21 x - // x22 y - // w18 color - sub sp, sp, 24 + sub sp, sp, 32 + str x23, [sp, 24] stur x22, [sp, #16] stur x21, [sp, #8] stur lr, [sp] add x21, x21, 1 - mov x23, 10 - bl doHorizontalLine + + mov x23, 7 // Cant de pixeles + bl doHorizontalLine // Linea h inferior + add x21, x21, 7 + sub x22, x22, 8 + mov x23, 7 + bl vertLine // Linea v derecha + sub x21, x21, 7 + sub x22, x22, 1 + bl doHorizontalLine // Linea h superior sub x21, x21, 1 add x22, x22, 1 - bl vertLine - add x21, x21, 11 - bl vertLine - sub x21, x21, 10 - add x22, x22, 11 - bl doHorizontalLine - ldur lr, [sp] - ldur x21, [sp, #8] - ldur x22, [sp, #16] - add sp, sp, 24 + bl vertLine // Linea v izquierda + + ldr x23, [sp, 24] + add sp, sp, 32 ret .globl doDm @@ -561,58 +560,68 @@ doGm: // REVIEW Done ret .globl doG -// NOTE g -doG: // REVIEW Done - // @Diego +// NOTE g minus +doG: // 16x8 // Args // x21 x inicial // x22 y inicial - // x18 color - sub sp, sp, 40 - stur x21, [sp, 32] - stur x22, [sp, 24] - stur x18, [sp, 16] - stur x23, [sp, 8] + // w18 color + // x23 = w = 16 + sub sp, sp, #48 + mov x3, 0 + stur x9, [sp, #40] // x1 + stur x10, [sp, #32] // x2 + stur x21, [sp, #24] + stur x22, [sp, #16] + stur x23, [sp, #8] stur lr, [sp] - mov x23, 10 + add x21, x21, 1 // Ignoramos el primer pixel + mov x23, 7 + bl doHorizontalLine // Linea h inferior + add x21, x21, 7 + mov x10, x22 // yih + sub x22, x22, 7 + mov x9, x21 // xih + bl vertLine // Linea v derecha + sub x21, x21, 7 + mov x23, 7 bl doHorizontalLine - sub x21, x21, 1 + + sub x21, x21, 1 // Ignoramos el primer pixel add x22, x22, 1 mov x23, 5 - bl vertLine - add x21, x21, 1 - add x22, x22, 5 - mov x23, 10 - bl doHorizontalLine + bl vertLine // Linea v izq - add x21, x21, 10 - sub x22, x22, 5 - mov x23, 14 + mov x21, x9 + mov x22, x10 + + mov x23, 6 // hago la line hacia abajo bl vertLine - add x22, x22, 15 - sub x21, x21, 9 - mov x23, 9 + add x22, x22, 7 + sub x21, x21, 6 + mov x23, 6 bl doHorizontalLine - + sub x22, x22, 1 sub x21, x21, 1 - sub x22, x22, 5 - mov x23, 4 - bl vertLine - ldur x21, [sp, 32] - ldur x22, [sp, 24] - ldur x18, [sp, 16] - ldur x23, [sp, 8] + mov x23, 1 + bl doHorizontalLine + ldur lr, [sp] - add sp, sp, 40 + ldur x23, [sp, #8] + ldur x22, [sp, #16] + ldur x21, [sp, #24] + ldur x10, [sp, #32] + ldur x9, [sp, #40] + add sp, sp, #48 ret .globl doDiego // NOTE Diego -doDiego: // REVIEW Done +doDiego: // Args // x21 x // x22 y From 8133e2d549e60026f07c6eff1072a020ac35bdb3 Mon Sep 17 00:00:00 2001 From: Valentina Vispo Date: Mon, 14 Jun 2021 14:35:17 -0300 Subject: [PATCH 42/47] Finish --- .gitignore | 2 +- animations.s | 86 ++++++- app.s | 72 +----- baseCore.s | 8 +- colores.md | 25 +- draw.s | 46 ++-- font.s | 625 ++++++++++++++++++++++++++++++++++------------- sprite_parser.py | 51 ++++ todo.md | 19 +- 9 files changed, 663 insertions(+), 271 deletions(-) create mode 100644 sprite_parser.py diff --git a/.gitignore b/.gitignore index c976553..23fb724 100644 --- a/.gitignore +++ b/.gitignore @@ -23,7 +23,7 @@ kernel8.img kernel8.list # Python -sprite_parser.py + # Examples assets/algorithms diff --git a/animations.s b/animations.s index 261decc..005f915 100644 --- a/animations.s +++ b/animations.s @@ -4,7 +4,7 @@ delay: add x8, xzr, xzr // counter = 0 add x8, x8, #0xFFF // counter = 0xF...F (un numero enorme) - lsl x8, x8, #9 // 3th = * 2^~10 (slow = 1s) // * 2^~9 (medium = ~0,3s) + lsl x8, x8, #10 // 3th = * 2^~10 (slow = 1s) // * 2^~9 (medium = ~0,3s) delayloop: cbz x8, delayEnd @@ -16,8 +16,25 @@ delayloop: delayEnd: ret +.globl fastDelay +// NOTE fastDelay +fastDelay: + add x8, xzr, xzr // counter = 0 + add x8, x8, #0xFFF // counter = 0xF...F (un numero enorme) + lsl x8, x8, #2 // 3th = * 2^~10 (slow = 1s) // * 2^~9 (medium = ~0,3s) + +fastDelayloop: + cbz x8, fastDelayEnd + ldur x9, [sp, #0] + stur x9, [sp, #0] + sub x8, x8, #1 // counter-- + b fastDelayloop + +fastDelayEnd: + ret + .globl longDelay -// NOTE delay +// NOTE longDelay longDelay: sub sp, sp, 16 str x8, [sp, 8] @@ -41,7 +58,7 @@ ldelayEnd: ret .globl lineAnimation -// FIXME lineAnimation +// NOTE lineAnimation lineAnimation: sub sp, sp, #8 // Guardamos 1 lugar del stack stur x30, [sp, #0] // Registro 30 para el RET en el stack @@ -183,3 +200,66 @@ doSceneEye: endDoSceneEye: ret +.globl rgbLinesAnim +// NOTE rgbLinesAnim +rgbLinesAnim: + sub sp, sp, #24 // Guardamos 1 lugar del stack + stur x5, [sp, #16] + stur x3, [sp, #8] + stur x30, [sp, #0] // Registro 30 para el RET en el stack + mov x3, #1 // Buffer secundario + mov x5, xzr + mov x13, #255 // R Inicial + mov x14, #0 // G Inicial + mov x15, #0 // B Inicial + bl setColour + +rgbLinesAnimLoop: + cmp x5, #319 // Si x5 ya terminó + b.ge rgbLinesAnimEnd + mov x21, #295 + mov x22, xzr + mov x23, #50 + mov x24, #480 + bl doRectangle + bl rgbAnimation + bl setColour + mov x21, #320 + mov x22, #240 + mov x23, x5 + bl doCircle + add x23, x23, #1 + bl doCircle + bl rgbAnimation + bl setColour + mov x21, xzr + +rgbLinesAnimSubLoop: + cmp x21, #640 + b.ge rgbLinesAnimSubEnd + mov x22, xzr // y = 0 + mov x23, #640 // x = WIDTH + sub x23, x23, x21 // x = WIDTH - x21 + sub x23, x23, #1 // x = WIDTH - x21 - 1 + mov x24, #480 + bl drawLine + add x21, x21, #1 + add x23, x23, #1 + bl drawLine + bl rgbAnimation + bl setColour + add x21, x21, #1 + b rgbLinesAnimSubLoop + +rgbLinesAnimSubEnd: + add x5, x5, #1 + bl drawUpdate + bl fastDelay + b rgbLinesAnimLoop + +rgbLinesAnimEnd: + ldur x30, [sp, #0] // Registro 30 para el RET en el stack + ldur x3, [sp, #8] + ldur x5, [sp, #16] + add sp, sp, #24 // Guardamos 1 lugar del stack + ret diff --git a/app.s b/app.s index 9382866..98aca24 100644 --- a/app.s +++ b/app.s @@ -32,75 +32,13 @@ main: bl cleanScreen // Pintamos un cuadrado en el medio de la pantalla - mov x21, 300 // x2 - mov x22, 300 // y2 - mov x23, 50 // w largo de pixeles - mov x13, 255 // R - mov x14, 255 // G - mov x15, 8 // B - bl setColour // R+G+B = Rojo - //bl doSquare - bl cleanScreen - mov x21, 200 - mov x22, 250 - //bl doAnimacionInicial - mov x13, 255 // R - mov x14, 255 // G - mov x15, 255 // B - bl setColour // R+G+B = Blanco - mov x23, 400 - bl doHorizontalLine - mov x13, 255 // R - mov x14, 255 // G - mov x15, 8 // B - bl setColour // R+G+B = Rojo - mov x23, 20 - bl doDiego - /*mov x21, #320 // xc x centro - mov x22, #250 // yc y centro - bl drawUpdate - bl doRaven - mov x21, #150 // xc x centro - mov x22, #150 // yc y centro - bl doOwl // Dibujamos un búho - mov x3, #0 - //bl circleTest - bl circleTestFill - //bl cleanScreenBuffer - b EndMain - ret - -/* - bl delay - bl cleanScreen - add x21, x21, 100 - mov x13, 255 // R - mov x14, 0 // G - mov x15, 0 // B - bl setColour // R+G+B = Gris - bl doDiego - bl delay - bl cleanScreen - add x21, x21, 100 - mov x13, 255 // R - mov x14, 0 // G - mov x15, 0 // B - bl setColour // R+G+B = Gris - bl doTriangleUp - */ - - //bl cleanScreen // cleanScreen negro + mov x21, 200 // x Posición inicial del mouse + mov x22, 250 // y Posición inicial del mouse + bl doAnimacionInicial // Computadora -> Glitch -> Pirámides - // Creamos el nombre Valentina Vispo - mov x13, 209 // R - mov x14, 0 // G - mov x15, 0 // B - bl setColour // R+G+B = Rojo - //bl doValentinaVispo - //bl delay - - //bl cleanScreen // cleanScreen negro + b EndMain + ret EndMain: bl delay diff --git a/baseCore.s b/baseCore.s index 9167707..f2ebfd5 100644 --- a/baseCore.s +++ b/baseCore.s @@ -71,7 +71,6 @@ updateLoop: cmp x9, x10 b.eq endUpdate - add x9, x9, 1 b updateLoop @@ -85,6 +84,7 @@ endUpdate: ret .globl drawUpdateWithCleanScreen +// NOTE drawUpdateWithCleanScreen drawUpdateWithCleanScreen: // x28 PreFrameBuffer // x20 FrameBuffer @@ -129,9 +129,10 @@ setColour: // x14 g // x15 b // 24 bits - sub sp, sp, #16 + sub sp, sp, #24 str x13, [sp, #8] str x14, [sp, #0] + str x15, [sp, #16] lsl x13, x13, 16 // Movemos 16 bits lsl x14, x14, 8 // Movemos 8 bits @@ -140,5 +141,6 @@ setColour: ldr x13, [sp, #8] ldr x14, [sp, #0] - add sp, sp, #16 + ldr x15, [sp, #16] + add sp, sp, #24 ret diff --git a/colores.md b/colores.md index ba0fa4d..9fa9c8a 100644 --- a/colores.md +++ b/colores.md @@ -23,4 +23,27 @@ F9FF33 FF8C33 -FF3333 \ No newline at end of file +FF3333 + +## Rojo + mov x13, 255 // R + mov x14, 0 // G + mov x15, 0 // B + bl setColour // R+G+B = Rojo + +## Amarillo + mov x13, 255 // R + mov x14, 255 // G + mov x15, 0 // B + bl setColour // R+G+B = Amarillo +## Rosa + +## Celeste + +## Verde + +## Blanco + mov x13, 255 // R + mov x14, 255 // G + mov x15, 255 // B + bl setColour // R+G+B = Blanco \ No newline at end of file diff --git a/draw.s b/draw.s index deaa510..522a49d 100644 --- a/draw.s +++ b/draw.s @@ -35,7 +35,7 @@ loopDelay: sub x22, x22, 3 // Muevo el mouse bl doMouse // Lo dibujo cmp x25, 18 // Comparo si itere un par de veces - b.eq endFirstDelay // Cuando toque el boton del medio de la pantalla. Se rompe + b.eq endFirstDelay // Cuando toque el boton del medio de la pantalla. Se rompe add x25, x25, 1 b loopDelay @@ -45,12 +45,15 @@ endFirstDelay: bl doComputerBroken bl drawUpdate bl longDelay + bl drawUpdateWithCleanScreen + bl rgbLinesAnim + bl drawUpdate preDoSun: mov x21, 39 mov x9, 0 sub sp, sp, 8 - stur x9, [sp, 56] + stur x9, [sp, 56] doSun: bl cleanScreen bl anPiramidesDia @@ -60,7 +63,7 @@ doSun: mov x23, 30 mov x22, 0 bl circRelleno - + add x21, x21, 10 bl drawUpdate @@ -132,20 +135,19 @@ doEstrella: .globl circRelleno circRelleno: - sub sp, sp, 16 + sub sp, sp, 24 + str x24, [sp, 16] str x23, [sp, 8] str lr, [sp] + mov x24, xzr -loopRelleno: bl doCircle - cbz x23, endRellenoCir - sub x23, x23, 1 - b loopRelleno endRellenoCir: ldr lr, [sp] ldr x23, [sp, 8] - add sp, sp, 16 + ldr x24, [sp, 16] + add sp, sp, 24 ret @@ -185,7 +187,7 @@ loopCompBro2: add x21, x21, 10 bl doRectangle - + add x7, x7, 1 b loopCompBro2 endLoopCompBro2: @@ -306,7 +308,7 @@ anPiramidesNoche: movk w18, 0x0000, lsl 0 mov x22, 350 mov x21, 100 - bl doDiego + bl doValentinaVispo ldr lr, [sp] ldr x24, [sp, 8] @@ -554,7 +556,11 @@ drawLine: // x7 sy // x19 err - sub sp, sp, #48 // Reservamos 6 registros de memoria + sub sp, sp, #80 // Reservamos 6 registros de memoria + stur x24, [sp, #72] + stur x23, [sp, #64] + stur x22, [sp, #56] + stur x21, [sp, #48] stur x30, [sp, #40] // Guardamos el return pointer en memoria stur x19, [sp, #32] stur x4, [sp, #24] @@ -635,13 +641,17 @@ break2: b loopLine endDrawLine: - ldur x30, [sp, #40] - ldur x19, [sp, #32] - ldur x4, [sp, #24] - ldur x5, [sp, #16] - ldur x6, [sp, #8] ldur x7, [sp, #0] - add sp, sp, #48 // Liberamos espacio en memoria + ldur x6, [sp, #8] + ldur x5, [sp, #16] + ldur x4, [sp, #24] + ldur x19, [sp, #32] + ldur x30, [sp, #40] + ldur x21, [sp, #48] + ldur x22, [sp, #56] + ldur x23, [sp, #64] + ldur x24, [sp, #72] + add sp, sp, #80 // Liberamos espacio en memoria ret .globl doSquare diff --git a/font.s b/font.s index 03b5f8c..8833e78 100644 --- a/font.s +++ b/font.s @@ -7,11 +7,81 @@ .equ COLOR_2, 0xFFFF // Color blanco GB // 0x1607 .equ COLOR_NEGRO, 0x00 +.globl doAm +// NOTE a minus +doAm: // 16x8 + sub sp, sp, 32 + str x21, [sp, 24] + str x22, [sp, 16] + str x23, [sp, 8] + str lr, [sp] + + sub x22, x22, 19 + mov x23, 19 + bl vertLine + add x21, x21, 1 + sub x22, x22, 1 + mov x23, 10 + bl doHorizontalLine + add x21, x21, 11 + add x22, x22, 1 + mov x23, 19 + bl vertLine + add x22, x22, 10 + sub x21, x21, 10 + mov x23, 10 + bl doHorizontalLine + + ldr lr, [sp] + ldr x23, [sp, 8] + ldr x22, [sp, 16] + ldr x21, [sp, 24] + add sp, sp, 32 + ret + .globl doA -// NOTE a -doA: - // @Vale +doA: // 16x8 + sub sp, sp, 32 + str x21, [sp, 24] + str x22, [sp, 16] + str x23, [sp, 8] + str lr, [sp] + + add x21, x21, 1 + mov x23, 5 + bl doHorizontalLine + sub x21, x21, 1 + sub x22, x22, 7 + mov x23, 6 + bl vertLine + + add x21, x21, 1 + sub x22, x22, 1 + mov x23, 4 + bl doHorizontalLine + + add x21, x21, 4 + add x22, x22, 1 + mov x23, 1 + bl doHorizontalLine + + add x21, x21, 1 + sub x22, x22, 1 + mov x23, 8 + bl vertLine + + add x22, x22, 7 + sub x21, x21, 1 + mov x23, 1 + bl vertLine + + ldr lr, [sp] + ldr x23, [sp, 8] + ldr x22, [sp, 16] + ldr x21, [sp, 24] + add sp, sp, 32 + ret .globl doEm // NOTE E @@ -66,46 +136,45 @@ endE: ret .globl doE -// NOTE e -doE: +// NOTE e minus +doE: // 16x8 // Args // x21 x lugar dónde empiezo a dibujar la figura // x22 y lugar dónde empiezo a dibujar la figura // w18 color // Usa: - // x23 para la funcion doHorizontalLine - sub sp, sp, 32 + // x23 para la función doHorizontalLine + sub sp, sp, #32 stur lr, [sp] stur x21, [sp, #8] stur x22, [sp, #16] stur x23, [sp, #24] - mov x23, 11 - add x22, x22, 10 - sub x21, x21, 5 - bl doHorizontalLine - add x21, x21, 11 + add x21, x21, 1 + mov x23, 6 + bl doHorizontalLine // Linea h inferior + sub x21, x21, 1 sub x22, x22, 7 mov x23, 6 - bl vertLine - sub x21, x21, 14 + bl vertLine // Linea vert izquierda + add x21, x21, 1 sub x22, x22, 1 - mov x23, 14 - bl doHorizontalLine - sub x21, x21, 1 + mov x23, 5 + bl doHorizontalLine // Linea sup + add x21, x21, 5 add x22, x22, 1 - mov x23, 16 - bl vertLine - add x21, x21, 1 - add x22, x22, 17 - mov x23, 14 - bl doHorizontalLine + mov x23, 2 + bl vertLine // Linea v derecha + sub x21, x21, 5 + add x22, x22, 2 + mov x23, 5 + bl doHorizontalLine // Linea intermedia ldur x23, [sp, #24] ldur x22, [sp, #16] ldur x21, [sp, #8] ldur lr, [sp] - add sp, sp, 32 + add sp, sp, #32 ret .globl doIm @@ -174,19 +243,19 @@ doI: stur x22, [sp, #16] stur x23, [sp, #24] stur x24, [sp, #32] - mov x16, x21 - mov x12, x22 - bl drawPixel - sub x21, x21, 5 - add x22, x22, 5 - mov x23, 5 + + mov x23, 10 bl doHorizontalLine add x21, x21, 5 - mov x23, 15 + sub x22, x22, 10 + mov x23, 10 bl vertLine - sub x21, x21, 8 - add x22, x22, 15 - mov x23, 15 + sub x22, x22, 3 + mov x23, 1 + bl doHorizontalLine + add x22, x22, 3 + sub x21, x21, 3 + mov x23, 3 bl doHorizontalLine ldur x24, [sp, #32] @@ -200,8 +269,8 @@ doI: .globl doO // NOTE o doO: - sub sp, sp, 32 - str x23, [sp, 24] + sub sp, sp, #32 + str x23, [sp, #24] stur x22, [sp, #16] stur x21, [sp, #8] stur lr, [sp] @@ -222,14 +291,16 @@ doO: bl vertLine // Linea v izquierda - ldr x23, [sp, 24] - add sp, sp, 32 + ldr lr, [sp] + ldr x21, [sp, #8] + ldr x22, [sp, #16] + ldr x23, [sp, #24] + add sp, sp, #32 ret .globl doDm // NOTE D -doDm: // REVIEW Solucionado - // @Diego +doDm: // Args // x21 x inicial // x22 y inicial @@ -244,13 +315,9 @@ doDm: // REVIEW Solucionado mov x12, x22 mov x9, 0 -dIzq: - add x12, x12, 1 - bl drawPixel - cmp x9, 20 - b.eq preDDer - add x9, x9, 1 - b dIzq + sub x22, x22, 20 + mov x23, 20 + bl vertLine preDDer: mov x23, 5 @@ -277,7 +344,7 @@ preDDer: dDer: add x12, x12, 1 bl drawPixel - cmp x9, 10 + cmp x9, 9 b.eq dDoIzq add x9, x9, 1 b dDer @@ -312,23 +379,112 @@ endD: ldur x22, [sp, #16] ldur x21, [sp, #8] ldur lr, [sp] - add sp, sp, 24 + add sp, sp, #24 ret .globl doL -// NOTE l -doL: - // @Vale +// NOTE l minus +doL: // 16x8 + // Args + // x21 x inicial + // x22 y inicial + // x23 w + // w18 color + sub sp, sp, #32 + str x21, [sp, #24] + str x22, [sp, #16] + str x23, [sp, #8] + str lr, [sp] + + add x21, x21, 2 + mov x23, 8 + bl doHorizontalLine + add x21, x21, 4 + sub x22, x22, 17 + mov x23, 16 + bl vertLine + sub x21, x21, 3 + mov x23, 4 + bl doHorizontalLine + + ldr lr, [sp] + ldr x21, [sp, #24] + ldr x22, [sp, #16] + ldr x23, [sp, #8] + add sp, sp, #32 + ret .globl doS -// NOTE s -doS: - // @Vale +// NOTE s minus +doS: // 16x8 + // Args + // x21 x inicial + // x22 y inicial + // x23 w + // w18 color + sub sp, sp, #24 + str x21, [sp, #16] + str x22, [sp, #8] + str lr, [sp] + + mov x23, 8 + bl doHorizontalLine + add x21, x21, 8 + sub x22, x22, 3 + mov x23, 3 + bl vertLine + sub x21, x21, 7 + sub x22, x22, 1 + mov x23, 7 + bl doHorizontalLine + sub x21, x21, 1 + sub x22, x22, 3 + mov x23, 3 + bl vertLine + add x21, x21, 1 + sub x22, x22, 1 + mov x23, 7 + bl doHorizontalLine + + ldr lr, [sp] + ldr x22, [sp, #8] + ldr x21, [sp, #16] + add sp, sp, #24 + ret .globl doP // NOTE p -doP: - // @Vale +doP: // 16x8 + // Args + // x21 x inicial + // x22 y inicial + // x23 w + // w18 color + sub sp, sp, 32 + str x23, [sp, 24] + str x21, [sp, 16] + str x22, [sp, 8] + str lr, [sp] + + mov x23, 9 + bl doHorizontalLine + add x21, x21, 8 + sub x22, x22, 4 + mov x23, 3 + bl vertLine + sub x21, x21, 8 + sub x22, x22, 1 + mov x23, 8 + bl doHorizontalLine + mov x23, 12 + bl vertLine + + ldr lr, [sp] + ldr x23, [sp, 24] + ldr x21, [sp, 16] + ldr x22, [sp, 8] + add sp, sp, 32 + ret .globl doM // NOTE m @@ -344,14 +500,15 @@ doM: stur x21, [sp, #8] stur x22, [sp, #16] - mov x23, 16 + sub x22, x22, 8 + mov x23, 8 bl vertLine mov x23, 5 bl doHorizontalLine add x21, x21, 6 add x22, x22, 1 - mov x23, 15 + mov x23, 7 bl vertLine add x21, x21, 1 sub x22, x22, 1 @@ -359,7 +516,7 @@ doM: bl doHorizontalLine add x21, x21, 6 add x22, x22, 1 - mov x23, 15 + mov x23, 7 bl vertLine @@ -412,7 +569,6 @@ endM: .globl doN // NOTE n doN: - // @Vale // Args // x21 x // x22 y @@ -422,15 +578,14 @@ doN: str x23, [sp, 8] str lr, [sp] - add x22, x22, 5 - - mov x23, 15 + sub x22, x22, 8 + mov x23, 8 bl vertLine - mov x23, 9 + mov x23, 5 bl doHorizontalLine - add x21, x21, 10 + add x21, x21, 6 add x22, x22, 1 - mov x23, 14 + mov x23, 7 bl vertLine ldr lr, [sp] @@ -443,30 +598,94 @@ doN: .globl doVm // NOTE V doVm: - // @Vale - // x16 x - // x12 y - // x0 - // Pixel superior izquierdo -/* - mov x8, SCREEN_WIDTH - mul x28, x12, x8 // y * WIDTH - add x28, x28, x16 // + x - lsl x28, x28, 2 // *4 - add x28, x20, x28 // Pixel inicial a pintar - */ - // TODO + sub sp, sp, 32 + str x21, [sp, 24] + str x22, [sp, 16] + str x23, [sp, 8] + str lr, [sp] + + sub x22, x22, 20 + mov x23, 5 + bl vertLine + + add x21, x21, 6 + bl vertLine + sub x21, x21, 6 + + add x21, x21, 1 + add x22, x22, 6 + bl vertLine + + add x21, x21, 4 + bl vertLine + sub x21, x21, 4 + + add x21, x21, 1 + add x22, x22, 6 + bl vertLine + + add x21, x21, 2 + bl vertLine + sub x21, x21, 2 + + add x21, x21, 1 + add x22, x22, 6 + bl vertLine + ldr lr, [sp] + ldr x23, [sp, 8] + ldr x22, [sp, 16] + ldr x21, [sp, 24] + add sp, sp, 32 ret -.globl doT -// NOTE t -doT: - // @Vale +.globl doZzzeta +// NOTE doZzzeta +doZzzeta: + // Args + // x21 x inicial + // x22 y inicial + // x18 Color + // Usa: + // x23 para doHorizontalLine + sub sp, sp, 24 + stur lr, [sp, 16] + stur x21, [sp, 8] + stur x22, [sp] + mov x16, x21 + mov x12, x22 + mov x9, 0 + + mov x23, 20 + bl doHorizontalLine + add x21, x21, 19 + mov x16, x21 + +doZDiagz: + bl drawPixel + sub x22, x22, 1 + add x21, x21, 1 + add x16, x16, 1 + sub x12, x12, 1 + cmp x9, 19 + b.eq doZBotz + add x9, x9, 1 + b doZDiagz + +doZBotz: + mov x23, 20 + bl doHorizontalLine + +endZz: + ldur x22, [sp] + ldur x21, [sp, 8] + ldur lr, [sp, 16] + add sp, sp, 24 + ret .globl doZ -// NOTE z -doZ: // REVIEW Done +// NOTE z minus +doZ: // Args // x21 x inicial // x22 y inicial @@ -481,10 +700,13 @@ doZ: // REVIEW Done mov x12, x22 mov x9, 0 - mov x23, 20 + sub x22, x22, 8 + + mov x23, 8 bl doHorizontalLine - add x21, x21, 20 - add x16, x16, 20 + add x21, x21, 8 + mov x16, x21 + mov x12, x22 doZDiag: bl drawPixel @@ -492,13 +714,13 @@ doZDiag: sub x21, x21, 1 sub x16, x16, 1 add x12, x12, 1 - cmp x9, 19 + cmp x9, 7 b.eq doZBot add x9, x9, 1 b doZDiag doZBot: - mov x23, 20 + mov x23, 8 bl doHorizontalLine endZ: @@ -510,53 +732,52 @@ endZ: .globl doGm // NOTE G mayus -doGm: // REVIEW Done +doGm: // Args // x21 x inicial // x22 y inicial - // x18 color + // w18 color // AUX fun: // doVertLine - sub sp, sp, 40 - stur x21, [sp, 32] - stur x22, [sp, 24] - stur x18, [sp, 16] + sub sp, sp, 32 + stur x21, [sp, 24] + stur x22, [sp, 16] stur x23, [sp, 8] stur lr, [sp] - mov x23, 11 - mov x9, 0 - bl doHorizontalLine - add x16, x16, 3 - add x21, x21, 11 - add x22, x22, 1 - mov x23, 3 - bl vertLine - - sub x21, x21, 12 - mov x23, 18 - bl vertLine - - add x21, x21, 1 - add x22, x22, 19 + add x21, x21, 1 // Ignoramos el primer pixel mov x23, 10 - bl doHorizontalLine + bl doHorizontalLine // Linea h inferior - add x21, x21, 11 - sub x22, x22, 8 - mov x23, 7 + add x21, x21, 10 + sub x22, x22, 6 + mov x23, 5 bl vertLine sub x21, x21, 5 mov x23, 5 bl doHorizontalLine - ldur x21, [sp, 32] - ldur x22, [sp, 24] - ldur x18, [sp, 16] - ldur x23, [sp, 8] + sub x21, x21, 5 + sub x22, x22, 9 + mov x23, 14 + bl vertLine // Linea v izquierda + + add x21, x21, 1 + sub x22, x22, 1 + mov x23, 9 + bl doHorizontalLine // Linea h superior + + add x21, x21, 9 + add x22, x22, 1 + mov x23, 1 + bl vertLine + ldur lr, [sp] - add sp, sp, 40 + ldur x23, [sp, 8] + ldur x22, [sp, 16] + ldur x21, [sp, 24] + add sp, sp, 32 ret .globl doG @@ -568,7 +789,6 @@ doG: // 16x8 // w18 color // x23 = w = 16 sub sp, sp, #48 - mov x3, 0 stur x9, [sp, #40] // x1 stur x10, [sp, #32] // x2 stur x21, [sp, #24] @@ -619,6 +839,34 @@ doG: // 16x8 add sp, sp, #48 ret +.globl doT +// NOTE doT minus +doT: // 16x8 + sub sp, sp, 32 + str lr, [sp] + str x23, [sp, 8] + str x22, [sp, 16] + str x21, [sp, 24] + + add x21, x21, 1 + mov x23, 3 + bl doHorizontalLine + sub x21, x21, 1 + sub x22, x22, 17 + mov x23, 16 + bl vertLine + + add x22, x22, 7 + mov x23, 4 + bl doHorizontalLine + + ldr lr, [sp] + ldr x23, [sp, 8] + ldr x22, [sp, 16] + ldr x21, [sp, 24] + add sp, sp, 32 + ret + .globl doDiego // NOTE Diego doDiego: @@ -627,78 +875,117 @@ doDiego: // x22 y // w18 color // x23 for O - sub sp, sp, 40 - stur x23, [sp, 32] - stur x21, [sp, 24] - stur x22, [sp, 16] - stur w18, [sp, 8] - stur lr, [sp] + sub sp, sp, #40 + str x18, [sp, #32] + str x23, [sp, #24] + str x22, [sp, #16] + str x21, [sp, #8] + str lr, [sp] bl doDm - add x21, x21, 25 + add x21, x21, 15 // Espacio entre letras bl doI - add x21, x21, 25 + add x21, x21, 15 // Espacio entre letras bl doE - add x21, x21, 20 - add x22, x22, 10 + add x21, x21, 15 // Espacio entre letras bl doG - sub x22, x22, 10 - add x21, x21, 20 - add x22, x22, 8 + add x21, x21, 15 // Espacio entre letras bl doO - sub x22, x22, 8 - add x21, x21, 50 + add x21, x21, 30 // Espacio entre letras bl doGm - add x21, x21, 25 + + add x21, x21, 15 // Espacio entre letras bl doI - add x21, x21, 10 - add x22, x22, 5 + + add x21, x21, 15 // Espacio entre letras bl doM - sub x22, x22, 5 - add x21, x21, 30 + + add x21, x21, 20 // Espacio entre letras bl doE - add x21, x21, 15 + + add x21, x21, 14 // Espacio entre letras bl doN - add x21, x21, 25 + + add x21, x21, 15 // Espacio entre letras bl doE - add x21, x21, 15 + + add x21, x21, 15 // Espacio entre letras bl doZ endDiego: - ldur lr, [sp] - ldur w18, [sp, 8] - ldur x22, [sp, 16] - ldur x21, [sp, 24] - ldur x23, [sp, 32] - add sp, sp, 40 + ldr lr, [sp] + ldr x21, [sp, #8] + ldr x22, [sp, #16] + ldr x23, [sp, #24] + ldr x18, [sp, #32] + add sp, sp, #40 ret .globl doValentinaVispo // NOTE Vale doValentinaVispo: // @Valentina Vispo - // x16 xo - // x12 yo - // w cantidad de pixeles ((2*w)xw) - // x18 Colour + // x21 xo + // x22 yo + // w18 Colour + sub sp, sp, #40 + str x18, [sp, #32] + str x23, [sp, #24] + str x22, [sp, #16] + str x21, [sp, #8] + str lr, [sp] + bl doVm - // bl doA - // bl doL - // bl doE - // bl doN - // bl doT - // bl doI - // bl doN - // bl doA - - // bl doVm - // bl doI - // bl doS - // bl doP - // bl doO + + add x21, x21, 15 // Espacio entre letras + bl doA + + add x21, x21, 15 // Espacio entre letras + bl doL + + add x21, x21, 15 // Espacio entre letras + bl doE + + add x21, x21, 15 // Espacio entre letras + bl doN + + add x21, x21, 15 // Espacio entre letras + bl doT + + add x21, x21, 15 // Espacio entre letras + bl doI + + add x21, x21, 15 // Espacio entre letras + bl doN + + add x21, x21, 15 // Espacio entre letras + bl doA + + add x21, x21, 30 // Espacio entre letras + bl doVm + + add x21, x21, 10 // Espacio entre letras + bl doI + + add x21, x21, 15 // Espacio entre letras + bl doS + + add x21, x21, 15 // Espacio entre letras + bl doP + + add x21, x21, 15 // Espacio entre letras + bl doO + +endDoValentinaVispo: + ldr lr, [sp] + ldr x21, [sp, #8] + ldr x22, [sp, #16] + ldr x23, [sp, #24] + ldr x18, [sp, #32] + add sp, sp, #40 ret diff --git a/sprite_parser.py b/sprite_parser.py new file mode 100644 index 0000000..00616df --- /dev/null +++ b/sprite_parser.py @@ -0,0 +1,51 @@ +from PIL import Image # Pillow + +PATH_BASE = "/home/shirosweets/Desktop/ORG/vc-framebuffer/png/" +IMAGE_NAME = "beep.png" # 900x620 +IMAGE_NAME_2 = "owl_100x100.png" +IMAGE_NAME_3 = "owl.png" +IMAGE_NAME_4 = "raven_100x100.png" +IMAGE_NAME_5 = "owl_med.png" +IMAGE_PATH = f"{PATH_BASE}{IMAGE_NAME_5}" + +# creating a image object + +def print_assembly(x, y, r, g, b): + print(f"\tadd x16, x21, {x}\t\t// (x+xc)") # add x16, x21, x // (x+xc, + print(f"\tadd x12, x22, {y}\t// (y+yc)") # add x12, x22, y // (y+yc) + print(f"\tmov x13, {r}\t\t// R") # mov x13, r // R + print(f"\tmov x14, {g}\t\t// G") # mov x14, g // G + print(f"\tmov x15, {b}\t\t// B") # mov x15, b // B + print(f"\tbl setColour\t\t// R+G+B = Colour") # bl setColour // R+G+B = Colour + print(f"\tbl drawPixel") # bl drawPixel + print() + +def print_all_pixels(image_path): + im = Image.open(image_path) + px = im.load() + width, height = im.size + im_mode = im.mode + #print(f"{image_path}: size {width}x{height} mode: {im_mode}") + print(f"\tsub sp, sp, #8\t\t//Reserva espacio en el stack") # sub sp, sp, #8 // + print(f"\tstur x30, [sp, #0]\t//Guarda la dir de retorno en el stack") # stur x30, [sp, #0] + + for x in range(width): + for y in range(height): + coordinate = (x, y) + pixel = im.getpixel(coordinate) + if pixel[3] > 100: + red = pixel[0] + green = pixel[1] + blue = pixel[2] + print_assembly(x, y, red, green, blue) + + print(f"\tldur x30, [sp, #0]\t\t//Carga la direccion de retorno") # ldur x30, [sp, #0] + print(f"\tadd sp, sp, #8\t\t\t//Libera la memoria del stack") # add sp, sp, #8 + print(f"\tret") # ret + +def main(): + print_all_pixels(IMAGE_PATH) + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/todo.md b/todo.md index 927de08..448241a 100644 --- a/todo.md +++ b/todo.md @@ -77,7 +77,7 @@ NOTA IMPORTANTE: Tener en cuenta las diferencias existentes entre el set de inst - [x] Completar función para dibujar círculos. - [x] Arreglar la "cruz" en los ejes `xc` e `yc` (no se pintan). - - [ ] Añadir lógica de rellenar la figura con un argumento. + - [x] Añadir lógica de rellenar la figura con un argumento. - [-] Modificar función `setPixel` para que use el stack pointer **(no la necesita)**. @@ -108,13 +108,14 @@ NOTA IMPORTANTE: Tener en cuenta las diferencias existentes entre el set de inst - [x] doGm (crea una `G` en mayúscula) - Crear las siguientes letras con esta [fuente](https://www.dafont.com/es/minitel.font?text=console) [font.s](font.s) (@shirosweets): - - [ ] doA (crea una `a` en minúscula) - - [ ] doT (crea una `t` en minúscula) - - [ ] doVm (crea una `V` en mayúscula) - - [ ] doN (crea una `n` en minúscula) - - [ ] doP (crea una `p` en minúscula) - - [ ] doS (crea una `s` en minúscula) - - [ ] doL (crea una `l` en minúscula) + - [x] doA (crea una `a` en minúscula) + - [x] doAm (crea una `A` en mayúscula) + - [x] doT (crea una `t` en minúscula) + - [x] doVm (crea una `V` en mayúscula) + - [x] doN (crea una `n` en minúscula) + - [x] doP (crea una `p` en minúscula) + - [x] doS (crea una `s` en minúscula) + - [x] doL (crea una `l` en minúscula) - Añadir al archivo [variables.md](variables.md): - [ ] Tags/funciones usadas como título. @@ -127,7 +128,7 @@ NOTA IMPORTANTE: Tener en cuenta las diferencias existentes entre el set de inst - [x] Estructura básica del EJ2. -- [ ] Repasar +- [x] Repasar - [x] Buscar alternativa para no tener que checkear el memory_map.txt From 1a6b1b4585cfe05810ace2613b4184935296bd6f Mon Sep 17 00:00:00 2001 From: Valentina Vispo Date: Mon, 14 Jun 2021 15:33:23 -0300 Subject: [PATCH 43/47] Update --- .gitignore | 2 +- draw.s | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 23fb724..d1f8d8f 100644 --- a/.gitignore +++ b/.gitignore @@ -11,7 +11,7 @@ rec assets/rename_me # Ignora -*.txt +assets/owl_md.txt *.o app.o start.o diff --git a/draw.s b/draw.s index 522a49d..d8e6a60 100644 --- a/draw.s +++ b/draw.s @@ -1076,6 +1076,7 @@ endPir: add sp, sp, #32 ret +.globl verticalLine // NOTE Line verticalLine: // Args From 40860f6ebea44f554d4b7be9b48d91add7a14e32 Mon Sep 17 00:00:00 2001 From: Valentina Vispo Date: Mon, 14 Jun 2021 15:33:44 -0300 Subject: [PATCH 44/47] Separate to send --- ejercicio1/Makefile | 33 + ejercicio1/TPQEMU_Gimenez_Vispo.txt | 10 + ejercicio1/app.s | 36 + ejercicio1/baseCore.s | 144 ++++ ejercicio1/draw.s | 597 ++++++++++++++ ejercicio1/font.s | 931 ++++++++++++++++++++++ ejercicio1/start.s | 142 ++++ ejercicio2/Makefile | 33 + ejercicio2/TPQEMU_Gimenez_Vispo.txt | 16 + ejercicio2/aScreenAnimations.s | 150 ++++ ejercicio2/animations.s | 265 +++++++ ejercicio2/app.s | 44 ++ ejercicio2/baseCore.s | 146 ++++ ejercicio2/draw.s | 1143 +++++++++++++++++++++++++++ ejercicio2/font.s | 991 +++++++++++++++++++++++ ejercicio2/start.s | 142 ++++ 16 files changed, 4823 insertions(+) create mode 100644 ejercicio1/Makefile create mode 100644 ejercicio1/TPQEMU_Gimenez_Vispo.txt create mode 100644 ejercicio1/app.s create mode 100644 ejercicio1/baseCore.s create mode 100644 ejercicio1/draw.s create mode 100644 ejercicio1/font.s create mode 100644 ejercicio1/start.s create mode 100644 ejercicio2/Makefile create mode 100644 ejercicio2/TPQEMU_Gimenez_Vispo.txt create mode 100644 ejercicio2/aScreenAnimations.s create mode 100644 ejercicio2/animations.s create mode 100644 ejercicio2/app.s create mode 100644 ejercicio2/baseCore.s create mode 100644 ejercicio2/draw.s create mode 100644 ejercicio2/font.s create mode 100644 ejercicio2/start.s diff --git a/ejercicio1/Makefile b/ejercicio1/Makefile new file mode 100644 index 0000000..0f0785e --- /dev/null +++ b/ejercicio1/Makefile @@ -0,0 +1,33 @@ +ARMGNU ?= aarch64-linux-gnu + +AOPS = -g --warn --fatal-warnings +ASM_SRCS = $(wildcard *.s) +ASM_OBJS = $(ASM_SRCS:.s=.o) + +all : kernel8.img + +%.o: %.s + $(ARMGNU)-as $(AOPS) $< -o $@ + +clean : + rm -f *.o memory_map.txt kernel8.list kernel8.img kernel8.elf + +kernel8.img : memmap $(ASM_OBJS) + $(ARMGNU)-ld $(ASM_OBJS) -T memmap -o kernel8.elf -M > memory_map.txt + $(ARMGNU)-objdump -D kernel8.elf > kernel8.list + $(ARMGNU)-objcopy kernel8.elf -O binary kernel8.img + +run : all + qemu-system-aarch64 -M raspi3 -kernel kernel8.img -serial stdio + +remake: clean + make run + +runQEMU : kernel8.img + qemu-system-aarch64 -s -S -M raspi3 -kernel kernel8.img + +runGDB: + gdb-multiarch -ex "set architecture aarch64" -ex "target remote localhost:1234" --ex "dashboard registers -style list 'x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 x11 x12 x13 x14 x15 x16 x17 x18 x19 x20 x21 x22 x23 x24 x25 x26 x27 x28 x29 x30 sp pc cpsr'" \-ex "add-symbol-file app.o 0x00000000000c6024" \-ex "add-symbol-file draw.o 0x00000000000900c8" \-ex "add-symbol-file animations.o 0x0000000000146398" + +#0x00000000000900c8" +#\-ex "b break" \-ex "continue" diff --git a/ejercicio1/TPQEMU_Gimenez_Vispo.txt b/ejercicio1/TPQEMU_Gimenez_Vispo.txt new file mode 100644 index 0000000..6207c55 --- /dev/null +++ b/ejercicio1/TPQEMU_Gimenez_Vispo.txt @@ -0,0 +1,10 @@ +Ejercicio 1: + +En el ejercicio uno se ven 2 pirámides durante el día con los nombres de los integrantes. + +Trabajo en Github: +https://github.com/shirosweets/vc-framebuffer + +Alumnos: +- Gimenez, Diego Nicolás +- Vispo, Valentina Solange \ No newline at end of file diff --git a/ejercicio1/app.s b/ejercicio1/app.s new file mode 100644 index 0000000..1241470 --- /dev/null +++ b/ejercicio1/app.s @@ -0,0 +1,36 @@ + +.equ SCREEN_BYTES, 4*640*480 +.equ SCREEN_PIXELS, 640*480 +.data + TOTAL_PIXELS: .dword SCREEN_PIXELS + +.equ SCREEN_WIDTH, 640 +.equ SCREEN_HEIGH, 480 +.equ BITS_PER_PIXEL, 32 +.equ COLOR_1, 0xFF // Color blanco R // 0xC7 +.equ COLOR_2, 0xFFFF // Color blanco GB // 0x1607 +.equ COLOR_NEGRO, 0x00 + +// 32 bits (4 bytes) +// Registros basura: x1, x2, x8, x9, x10 + +// Registros globales // +// SCREEN_HEIGH +// SCREEN_WIDTH +// x0 Pixel a pintar +// x18 Colour +// x20 Base del framebuffer +// x28 PreFrameBuffer + +.globl main +main: + mov x20, x0 // X0 Dirección base del FrameBuffer + adr x28, PreFrameBuffer // x28 Dirección base del PreFrameBuffer + + bl cleanScreen + + bl anPiramidesDia // Pirámides de día junto con los nombres de los integrantes + bl drawUpdate + +return: + ret diff --git a/ejercicio1/baseCore.s b/ejercicio1/baseCore.s new file mode 100644 index 0000000..6eef569 --- /dev/null +++ b/ejercicio1/baseCore.s @@ -0,0 +1,144 @@ + +.equ SCREEN_BYTES, 4*640*480 +.equ SCREEN_PIXELS, 640*480 +.data + TOTAL_PIXELS: .dword SCREEN_PIXELS + +.equ SCREEN_WIDTH, 640 +.equ SCREEN_HEIGH, 480 +.equ BITS_PER_PIXEL, 32 +.equ COLOR_1, 0xFF // Color blanco R // 0xC7 +.equ COLOR_2, 0xFFFF // Color blanco GB // 0x1607 +.equ COLOR_NEGRO, 0x00 + +.globl drawPixel +drawPixel: + // Args: y=x12 -- x=x16 -- colour=x18 -- BufferSwitch = x3 + sub sp, sp, #16 + str x8, [sp, 8] + stur x30, [sp, #0] + bl setPixel // ret : x0 + cbz x3, drawBuffer // if x3 == 0 dibujar en el buffer + b drawPrebuffer // else dibujar en el prebuffer + +drawBuffer: + mov x8, x0 // Dibujamos el valor original x0 + b drawPixelEnd + +drawPrebuffer: // then dibujar en x28 + add x8, x0, x28 // Traducción del buffer al prebuffer: + sub x8, x8, x20 // x8 = x0 + (X28 - X20) + +drawPixelEnd: + stur w18, [x8] // stur xN guarda 64bits, y stur wN guarda medio registro (32bits) + ldur x30, [sp, #0] + ldr x8, [sp, 8] + add sp, sp, #16 + ret + +.globl setPixel +setPixel: + // Return: x0 Pixel a pintar + // Args: y=x12 -- x=x16 + mov x8, SCREEN_WIDTH + mul x0, x12, x8 // y * WIDTH + add x0, x0, x16 // + x + lsl x0, x0, 2 // *4 + add x0, x20, x0 // Pixel a pintar + ret + +.globl drawUpdate +drawUpdate: + // x28 PreFrameBuffer + // x20 FrameBuffer + sub sp, sp, 40 + str x8, [sp, 32] + str x7, [sp, 24] + str x9, [sp, 16] + str x10, [sp, 8] + str lr, [sp] + + mov x8, x20 + mov x7, x28 + mov x9, 0 + ldr x10, TOTAL_PIXELS + +updateLoop: + ldr w6, [x7] + str w6, [x8] + add x8, x8, 4 + add x7, x7, 4 + + cmp x9, x10 + b.eq endUpdate + add x9, x9, 1 + b updateLoop + +endUpdate: + ldr lr, [sp] + ldr x10, [sp, 8] + ldr x9, [sp, 16] + ldr x7, [sp, 24] + ldr x8, [sp, 32] + add sp, sp, 40 + ret + +.globl drawUpdateWithCleanScreen +drawUpdateWithCleanScreen: + // x28 PreFrameBuffer + // x20 FrameBuffer + sub sp, sp, 40 + str x8, [sp, 32] + str x7, [sp, 24] + str x9, [sp, 16] + str x10, [sp, 8] + str lr, [sp] + mov x8, x20 + mov x7, x28 + mov x9, 0 + ldr x10, TOTAL_PIXELS + mov w15, 0x00 + +updateLoopWithClean: + str w15, [x7] + str w15, [x8] + add x8, x8, 4 + add x7, x7, 4 + cmp x9, x10 + b.eq endUpdateAndClean + add x9, x9, 1 + b updateLoopWithClean + +endUpdateAndClean: + ldr x8, [sp, 32] + ldr x7, [sp, 24] + ldr x9, [sp, 16] + ldr x10, [sp, 8] + ldr lr, [sp] + add sp, sp, 40 + ret + +.globl setColour +setColour: + // Return + // x18 Color a pintar + // Args + // x13 r + // x14 g + // x15 b + // 24 bits + sub sp, sp, #24 + str x13, [sp, #8] + str x14, [sp, #0] + str x15, [sp, #16] + + lsl x13, x13, 16 // Movemos 16 bits + lsl x14, x14, 8 // Movemos 8 bits + add x18, x13, x14 // R+G + add x18, x18, x15 // RG+B + + ldr x13, [sp, #8] + ldr x14, [sp, #0] + ldr x15, [sp, #16] + add sp, sp, #24 + ret diff --git a/ejercicio1/draw.s b/ejercicio1/draw.s new file mode 100644 index 0000000..53209b3 --- /dev/null +++ b/ejercicio1/draw.s @@ -0,0 +1,597 @@ + +.equ SCREEN_BYTES, 4*640*480 +.equ SCREEN_PIXELS, 640*480 +.data + TOTAL_PIXELS: .dword SCREEN_PIXELS + +.equ SCREEN_WIDTH, 640 +.equ SCREEN_HEIGH, 480 +.equ BITS_PER_PIXEL, 32 +.equ COLOR_1, 0xFF // Color blanco R // 0xC7 +.equ COLOR_2, 0xFFFF // Color blanco GB // 0x1607 +.equ COLOR_NEGRO, 0x00 + +.globl anPiramidesDia +anPiramidesDia: + sub sp, sp, 56 + str x3, [sp, 40] + str x21, [sp, 32] + str x22, [sp, 24] + str x23, [sp, 16] + str x24, [sp, 8] + str lr, [sp] + mov x3, 1 + + // Fondo + movz w18, 0xA3, lsl 16 + movk w18, 0x371F, lsl 0 + mov x21, 0 + mov x22, 0 + mov x23, 640 + mov x24, 480 + bl doRectangle + + // Piramides + movz w18, 0xDF, lsl 16 + movk w18, 0x915E, lsl 0 + mov x21, 200 + mov x22, 300 + mov x23, 50 + bl doPiramide + add x21, x21, 200 + add x23, x23, x23 + bl doPiramide + + // Desierto + movz w18, 0x6B, lsl 16 + movk w18, 0x3E3E, lsl 0 + mov x21, 0 + mov x23, 640 + mov x24, 480 + bl doRectangle + mov x21, 50 + mov x22, 0 + mov x23, 50 + + mov x13, 0xF2 + mov x14, 0x74 + mov x15, 0x0B + bl setColour + mov x21, 100 + mov x22, 70 + mov x23, 50 + mov x24, xzr + bl doCircle + + movz w18, 0xFF, lsl 16 + movk w18, 0xFFFF, lsl 0 + mov x22, 350 + mov x21, 350 + bl doDiego + + add x22, x22, 50 + bl doValentinaVispo + +endAnPir: + ldr lr, [sp] + ldr x24, [sp, 8] + ldr x23, [sp, 16] + ldr x22, [sp, 24] + ldr x21, [sp, 32] + ldr x3, [sp, 40] + add sp, sp, 56 + ret + +.globl circRelleno +circRelleno: + sub sp, sp, 24 + str x24, [sp, 16] + str x23, [sp, 8] + str lr, [sp] + mov x24, xzr + + bl doCircle + +endRellenoCir: + ldr lr, [sp] + ldr x23, [sp, 8] + ldr x24, [sp, 16] + add sp, sp, 24 + ret +.globl doEstrella +doEstrella: + sub sp, sp, 32 + str x21, [sp, 24] + str x22, [sp, 16] + str x23, [sp, 8] + str lr, [sp] + + mov x23, 5 + bl doHorizontalLine + add x21, x21, 2 + sub x22, x22, 2 + bl vertLine + + ldr lr, [sp] + ldr x23, [sp, 8] + ldr x22, [sp, 16] + ldr x21, [sp, 24] + add sp, sp, 32 + + ret + +.globl anPiramidesNoche +anPiramidesNoche: + sub sp, sp, 40 + str x21, [sp, 32] + str x22, [sp, 24] + str x23, [sp, 16] + str x24, [sp, 8] + str lr, [sp] + + // Fondo + movz w18, 0x31, lsl 16 + movk w18, 0x1f62, lsl 0 + mov x21, 0 + mov x22, 0 + mov x23, 640 + mov x24, 480 + bl doRectangle + + // Piramides + movz w18, 0x8d, lsl 16 + movk w18, 0x5273, lsl0 + mov x21, 200 + mov x22, 300 + mov x23, 50 + bl doPiramide + add x21, x21, 200 + add x23, x23, x23 + bl doPiramide + + // Desierto + movz w18, 0xc3, lsl 16 + movk w18, 0x727c, lsl0 + mov x21, 0 + mov x23, 640 + mov x24, 480 + bl doRectangle + mov x21, 50 + mov x22, 0 + mov x23, 50 + + movz w18, 0x00, lsl 16 + movk w18, 0x0000, lsl 0 + mov x22, 350 + mov x21, 100 + bl doValentinaVispo + + ldr lr, [sp] + ldr x24, [sp, 8] + ldr x23, [sp, 16] + ldr x22, [sp, 24] + ldr x21, [sp, 32] + add sp, sp, 40 + ret + +.globl doRectangle +doRectangle: // alto x largo// + // Args + // x21 x2 lugar dónde empiezo a dibujar la figura + // x22 y2 lugar dónde empiezo a dibujar la figura + // x23 w largo en pixeles + // x24 h alto en pixeles + // w18 colour + // Used + // doHorizontalLine + // drawPixel: setPixel x16 x, x12 y + // x9 posición inicial de x + // x10 posición inicial de y + + sub sp, sp, #56 // Reservamos memoria + str x3, [sp, 48] + stur x21, [sp, 40] + stur x22, [sp, 32] + stur x23, [sp, 24] + stur x24, [sp, 16] + stur lr, [sp, 8] // Guardamos el return pointer en memoria (8 direcciones de memoria = 1 registro de 64bits) + stur x5, [sp] // Guardamos el x5 en memoria (8 direcciones de memoria = 1 registro de 64bits) + + mov x5, x22 // x5 fila inicial + +rectangleLoop: // Se encarga de cambiar la fila + sub x8, x22, x5 // Cantidad de filas que dibujamos hasta ahora + cmp x8, x24 // Comparamos la cantidad de líneas dibujadas con h + b.eq endRectangule // Si son iguales ya pintamos todo + bl doHorizontalLine // Sino, pintamos la línea + add x22, x22, #1 // Nos movemos al pixel de la fila de abajo, y++ + b rectangleLoop + +endRectangule: + ldur x5, [sp] + ldur lr, [sp, 8] // Cargamos el return pointer en memoria (8 direcciones de memoria = 1 regildro de 64bits) + ldur x24, [sp, 16] + ldur x23, [sp, 24] + ldur x22, [sp, 32] + ldur x21, [sp, 40] + ldr x3, [sp, 48] + add sp, sp, 56 // Reservamos 2 registros de memoria + ret + +.globl doCircle +doCircle: // Mid-Point Circle Drawing Algorithm // + // (0, 0) centro + // point p(x, y) + // F(p) = x^2 + y^2 - r^2 + // Args + // x21 xc x centro + // x22 yc y centro + // x23 r radio (asumimos que el radio es mayor que 0) + // x24 no fill in: (x24 == 0 -> Fill, x24 != 0 -> No Fill) + // x18 colour + // Used + // x25 x + // x26 y + // x27 P + sub sp, sp, #40 + stur x23, [sp, 32] + stur x22, [sp, 24] + stur x21, [sp, 16] + stur x27, [sp, 8] + stur x30, [sp, #0] // Guardamos el return pointer en memoria + mov x25, x23 // x = r + mov x26, xzr // y = 0 (xzr = 0) + sub x8, xzr, x23 // x8 = -r + add x27, x8, #1 // P = 1 - r + + // Dibujamos las esquinas + mov x16, x21 // x16 xd = xc + add x12, x22, x23 // x12 yd = yc + r + bl drawPixel + mov x16, x21 // x16 xd = xc + sub x12, x22, x23 // x12 yd = yc - r + bl drawPixel + add x16, x21, x23 // x16 xd = xc + r + mov x12, x22 // x12 yd = yc + bl drawPixel + sub x16, x21, x23 // x16 xd = xc - r + mov x12, x22 // x12 yd = yc + bl drawPixel + cbnz x24, doCircleLoop // doCircleLoop... + b doPixelsForCircleFill + +doPixelsForCircleFill: + sub sp, sp, #16 + stur x6, [sp, #8] + stur x5, [sp, #0] + + mov x5, x22 // x5 = yc + mov x6, x23 // x6 = r + + sub x22, x5, x6 // yd = yc - r + lsl x23, x6, #1 // h = 2 * r + bl vertLine // x21 x - x22 y - x23 height + + mov x22, x5 + mov x23, x6 + ldur x6, [sp, #8] + ldur x5, [sp, #0] + add sp, sp, #16 + // doCircleLoop... + +doCircleLoop: // While x > y + add x26, x26, #1 + // Mid-point is inside or on the perimeter + cmp x27, xzr // P <= 0 + b.le cirif1 // Si P <= 0 entra en el if + b cirelse1 // Si no, entra en el else + +cirif1: // if (P <= 0) + // F(p) < 0 -> the point is inside the circle + // F(p) = 0 -> the point is on the perimeter + lsl x8, x26, #1 // x8 = 2*y + add x8, x8, #1 // x8 = 2*y + 1 + add x27, x27, x8 // P = P + 2*y + 1 + b cirif2 + +cirelse1: // Mid-point is outside the perimeter + // F(p) > 0 -> the point is outside the circle + sub x25, x25, #1 // x-- + lsl x8, x25, #1 // x8 = 2*x + lsl x9, x26, #1 // x9 = 2*y + add x8, x8, #1 // x8 = 2*x + 1 + sub x9, x9, x8 // x9 = 2*y - (2*x + 1) + add x27, x27, x9 // P = P + 2*y - 2*x + 1 + // cirif2... + +cirif2: // if (x < y) + cmp x25, x26 + b.lt circleEnd + cbnz x24, circlNoFill + bl circleFillAux + b doCircleLoop + +circlNoFill: + add x16, x25, x21 // x16 xd = x + x_centre + add x12, x26, x22 // x12 yd = y + y_centre + bl drawPixel + + sub x16, x21, x25 // x16 draw x = -x + x_centre + add x12, x26, x22 // x12 draw y = y + y_centre + bl drawPixel + + add x16, x25, x21 // x16 xd = x + x_centre + sub x12, x22, x26 // x12 draw y = -y + y_centre + bl drawPixel + + sub x16, x21, x25 // x16 draw x = -x + x_centre + sub x12, x22, x26 // x12 draw y = -y + y_centre + bl drawPixel + + cmp x25, x26 + b.eq doCircleLoop + + // If the generated point is on the line x = y then + // the perimeter points have already been printed + // if (x != y) : + + add x16, x26, x21 // x16 draw x = y + x_centre + add x12, x25, x22 // x12 draw y = x + y_centre + bl drawPixel + + sub x16, x21, x26 // x16 draw x = -y + x_centre + add x12, x25, x22 // x12 draw y = x + y_centre + bl drawPixel + + add x16, x26, x21 // x16 draw x = y + x_centre + sub x12, x22, x25 // x12 draw y = -x + y_centre + bl drawPixel + + sub x16, x21, x26 // x16 draw x = -y + x_centre + sub x12, x22, x25 // x12 draw y = -x + y_centre + bl drawPixel + + cmp x25, x26 + b.gt doCircleLoop + +circleEnd: + ldur x30, [sp] // Guardamos el return pointer en memoria ret + ldur x27, [sp, 8] + ldur x21, [sp, 16] + ldur x22, [sp, 24] + ldur x23, [sp, 32] + add sp, sp, 40 + ret + +circleFillAux: + sub sp, sp, #32 + stur x4, [sp, #24] + stur x5, [sp, #16] + stur x23, [sp, #8] + stur x30, [sp, #0] // Guardamos el return pointer en memoria ret + + mov x4, x21 // x4 = xc + mov x5, x22 // x5 = yc + add x21, x4, x25 // x = xc + x + sub x22, x5, x26 // y = yc - y + mov x23, x26 + add x23, x23, x26 // height = 2*y + 1 + bl vertLine + + sub x21, x4, x25 // x = xc - x + bl vertLine + + cmp x25, x26 + b.eq endCircleFillAux // Siguientes cuadrantes... + + add x21, x4, x26 // x = xc + y + sub x22, x5, x25 // y = yc - x + add x23, x25, x25 // height = 2 * x + bl vertLine + + sub x21, x4, x26 // x = xc - y + sub x22, x5, x25 // y = yc - x + mov x23, x25 + add x23, x23, x25 // height = 2 * x + bl vertLine + +endCircleFillAux: + mov x21, x4 + mov x22, x5 + ldur x30, [sp, #0] // Guardamos el return pointer en memoria ret + ldur x23, [sp, #8] + ldur x5, [sp, #16] + ldur x4, [sp, #24] + add sp, sp, #32 + ret + + +.globl doPiramide +doPiramide: + // Args + // x21 x lugar dónde empiezo a dibujar la figura + // x22 y lugar dónde empiezo a dibujar la figura + // x23 w cantidad de píxeles + // w18 colour + + sub sp, sp, #32 + str x23, [sp, 24] + str x22, [sp, 16] + str x21, [sp, 8] + stur lr, [sp] // Guardo el link register para no pisarlo en la subrutina setPixel + mov x16, x21 // Instancio x16 para dibujar + mov x12, x22 // Instancio x12 para setPixel + mov x19, x23 // La cantidad de pixeles sera la cantidad de veces que entro al ciclo + mov x9, #0 // Instancio un contador que me va a servir para contar cantidad de pixeles + +pirAr: // Dibuja la diagonal hacia arriba + sub x16, x16, #1 // Me muevo atras + sub x12, x12, #1 // Me muevo arriba + bl drawPixel + cmp x9, x19 // Comparo mi contador con mi cantidad de pixeles + b.eq pirBaj // Si llegue a la cantidad bajo + add x9, x9, #1 // Si no le sumo 1 al contador + b pirAr // Empiezo de nuevo + +pirBaj: // Dibuja la diagonal hacia abajo + sub x16, x16, #1 // Me muevo atras + add x12, x12, #1 // Bajo 1 unidad + bl drawPixel + cmp x9, #0 // Comparo el contador a w con 0 + b.eq prepirAr // Si llegue a la "base" arranco de nuevo desde 1 posicion menos + sub x9, x9, #1 // Si no, le resto 1 al contador + b pirBaj // Bajo de nuevo + +prepirAr: // Se fija si itero la cantidad de veces necesarias + add x21, x21, #1 // Itero una vez menos + mov x16, x21 // Empiezo de nuevo + mov x12, x22 // Instancio x12 para setPixel + cmp x19, xzr // Si itere w cantidad de veces --> + b.eq endPir // Termino + sub x19, x19, #1 // Si no, resto 1 iteracion + b pirAr // sigo + +endPir: + ldur lr, [sp] + ldr x21, [sp, 8] + ldr x22, [sp, 16] + ldr x23, [sp, 24] + add sp, sp, #32 + ret + +.globl doHorizontalLine +doHorizontalLine: // Crea líneas horizontales en la coordenada (xo, po) con w cantidad de pixeles que se extienden hacia la derecha // + // Args + // x21 xo valor de origen x + // x22 yo valor de origen y + // x23 w cantidad de pixeles + // Used + // drawPixel: setPixel x16 x, x12 y + // x18 Colour + sub sp, sp, #48 + str x12, [sp, #40] + str x16, [sp, #32] + str x23, [sp, #24] + str x22, [sp, #16] + str x21, [sp, #8] + str x30, [sp, #0] // Guardamos el return pointer en memoria + mov x16, x21 // x = xo + // horLineLoop... + +horLineLoop: + sub x8, x16, x21 // Cuantos pixeles hemos dibujado hasta ahora + cmp x23, x8 // Comparamos x23=w con x8 + b.eq endHorizontalLine // Si son iguales terminamos porque pintamos todo ya + mov x12, x22 + bl drawPixel // Sino, dibujamos + add x16, x16, #1 // Nos movemos de pixel, x++ + b horLineLoop + +endHorizontalLine: + ldr x30, [sp, #0] // Guardamos el return pointer en memoria + ldr x21, [sp, #8] + ldr x22, [sp, #16] + ldr x23, [sp, #24] + ldr x16, [sp, #32] + ldr x12, [sp, #40] + add sp, sp, #48 // Liberamos espacio en memoria + ret + +.globl cleanScreen +cleanScreen: // Pinta toda la pantalla de negro + sub sp, sp, #16 + stur lr, [sp] // Guardo el link register para no pisarlo + stur x30, [sp, #8] // Guardamos el return pointer en memoria + mov x13, xzr // R + mov x14, xzr // G + mov x15, xzr // B + bl setColour // Negro + bl paintScreen + ldur x30, [sp, #8] // Guardamos el return pointer en memoria ret + ldur lr, [sp] // Devuelvo el link register + add sp, sp, #16 + ret + +.globl cleanScreenBuffer +cleanScreenBuffer: // Pinta toda la pantalla de negro + sub sp, sp, #16 + stur lr, [sp] // Guardo el link register para no pisarlo + stur x30, [sp, #8] // Guardamos el return pointer en memoria + mov x13, xzr // R + mov x14, xzr // G + mov x15, xzr // B + bl setColour // Negro + bl paintScreenBuffer + ldur x30, [sp, #8] // Guardamos el return pointer en memoria ret + ldur lr, [sp] // Devuelvo el link register + add sp, sp, #16 + ret + +.globl paintScreenBuffer +paintScreenBuffer: // 320w 240h -> 76800 + 240 + // Return -> nada + // Args: x18 Colour + mov x0, x20 // Origen del frameBuffer + mov x8, SCREEN_WIDTH + mov x9, SCREEN_HEIGH + mul x8, x8, x9 // x8 contador de pixeles a pintar + // paintScreenBufferLoop... + +paintScreenBufferLoop: + stur w18, [x0] // Set color of pixel N + add x0, x0, 4 // Next pixel + sub x8, x8, 1 // decrement pixel counter + cbnz x8, paintScreenBufferLoop // If not end row jump + ret + +.globl paintScreen +paintScreen: // 320w 240h -> 76800 + 240 + // Return -> nada + // Args: x18 Colour + adr x28, PreFrameBuffer // Origen del frameBuffer + mov x8, SCREEN_WIDTH + mov x9, SCREEN_HEIGH + mul x8, x8, x9 // x8 contador de pixeles a pintar + // paintScreenLoop... + +paintScreenLoop: + stur w18, [x28] // Set color of pixel N + add x28, x28, 4 // Next pixel + sub x8, x8, 1 // decrement pixel counter + cbnz x8, paintScreenLoop // If not end row jump + ret + +.globl vertLine +vertLine: + // Args + // x21 x + // x22 y + // x18 colour + // x23 height + sub sp, sp, 40 + stur x9, [sp, 32] + stur x21, [sp, 24] + stur x22, [sp, 16] + stur x23, [sp, 8] + stur lr, [sp] + mov x16, x21 + mov x12, x22 + mov x9, 0 + +doVertL: + bl drawPixel + add x12, x12, 1 + cmp x9, x23 + b.eq endVertLine + add x9, x9, 1 + b doVertL + +endVertLine: + ldur lr, [sp] + ldur x23, [sp, 8] + ldur x22, [sp, 16] + ldur x21, [sp, 24] + ldur x9, [sp, 32] + add sp, sp, 40 + ret + diff --git a/ejercicio1/font.s b/ejercicio1/font.s new file mode 100644 index 0000000..1cce5e1 --- /dev/null +++ b/ejercicio1/font.s @@ -0,0 +1,931 @@ +// Font https://www.dafont.com/es/minitel.font?text=console + +.equ SCREEN_WIDTH, 640 +.equ SCREEN_HEIGH, 480 +.equ BITS_PER_PIXEL, 32 +.equ COLOR_1, 0xFF // Color blanco R // 0xC7 +.equ COLOR_2, 0xFFFF // Color blanco GB // 0x1607 +.equ COLOR_NEGRO, 0x00 + +.globl doAm +doAm: // 16x8 + sub sp, sp, 32 + str x21, [sp, 24] + str x22, [sp, 16] + str x23, [sp, 8] + str lr, [sp] + + sub x22, x22, 19 + mov x23, 19 + bl vertLine + add x21, x21, 1 + sub x22, x22, 1 + mov x23, 10 + bl doHorizontalLine + add x21, x21, 11 + add x22, x22, 1 + mov x23, 19 + bl vertLine + add x22, x22, 10 + sub x21, x21, 10 + mov x23, 10 + bl doHorizontalLine + + ldr lr, [sp] + ldr x23, [sp, 8] + ldr x22, [sp, 16] + ldr x21, [sp, 24] + add sp, sp, 32 + ret + +.globl doA +doA: // 16x8 + sub sp, sp, 32 + str x21, [sp, 24] + str x22, [sp, 16] + str x23, [sp, 8] + str lr, [sp] + + add x21, x21, 1 + mov x23, 5 + bl doHorizontalLine + + sub x21, x21, 1 + sub x22, x22, 7 + mov x23, 6 + bl vertLine + + add x21, x21, 1 + sub x22, x22, 1 + mov x23, 4 + bl doHorizontalLine + + add x21, x21, 4 + add x22, x22, 1 + mov x23, 1 + bl doHorizontalLine + + add x21, x21, 1 + sub x22, x22, 1 + mov x23, 8 + bl vertLine + + add x22, x22, 7 + sub x21, x21, 1 + mov x23, 1 + bl vertLine + + ldr lr, [sp] + ldr x23, [sp, 8] + ldr x22, [sp, 16] + ldr x21, [sp, 24] + add sp, sp, 32 + ret + +.globl doEm +doEm: + // Args + // x21 x lugar dónde empiezo a dibujar la figura + // x22 y lugar dónde empiezo a dibujar la figura + // w18 color + // Usa: + // x23 para la funcion doHorizontalLine + sub sp, sp, 32 + stur lr, [sp] + stur x21, [sp, #8] + stur x22, [sp, #16] + stur x23, [sp, #24] + mov x9, #0 + +doETop: + mov x23, 15 + bl doHorizontalLine + mov x16, x21 + mov x12, x22 + +doEDown: + bl drawPixel + add x12, x12, #1 + add x22, x22, #1 + cmp x9, #10 + b.eq drawEMid + cmp x9, #20 + b.eq drawEBot + add x9, x9, #1 + b doEDown + +drawEMid: + mov x23, 10 + bl doHorizontalLine + add x9, x9, #1 + b doEDown + + +drawEBot: + mov x23, 15 + bl doHorizontalLine + b endE + +endE: + ldur x23, [sp, #24] + ldur x22, [sp, #16] + ldur x21, [sp, #8] + ldur lr, [sp] + ret + +.globl doE +doE: // 16x8 + // Args + // x21 x lugar dónde empiezo a dibujar la figura + // x22 y lugar dónde empiezo a dibujar la figura + // w18 color + // Usa: + // x23 para la función doHorizontalLine + sub sp, sp, #32 + stur lr, [sp] + stur x21, [sp, #8] + stur x22, [sp, #16] + stur x23, [sp, #24] + + add x21, x21, 1 + mov x23, 6 + bl doHorizontalLine // Linea h inferior + sub x21, x21, 1 + sub x22, x22, 7 + mov x23, 6 + bl vertLine // Linea vert izquierda + add x21, x21, 1 + sub x22, x22, 1 + mov x23, 5 + bl doHorizontalLine // Linea sup + add x21, x21, 5 + add x22, x22, 1 + mov x23, 2 + bl vertLine // Linea v derecha + sub x21, x21, 5 + add x22, x22, 2 + mov x23, 5 + bl doHorizontalLine // Linea intermedia + + ldur x23, [sp, #24] + ldur x22, [sp, #16] + ldur x21, [sp, #8] + ldur lr, [sp] + add sp, sp, #32 + ret + +.globl doIm +doIm: + // Args + // x21 x lugar dónde empiezo a dibujar la figura + // x22 y lugar dónde empiezo a dibujar la figura + // w18 color + sub sp, sp, 40 + stur lr, [sp] + stur x21, [sp, #8] + stur x22, [sp, #16] + stur x23, [sp, #24] + stur x24, [sp, #32] + mov x16, x21 + mov x12, x22 + mov x10, x23 + mov x9, 0 + +drawITop: + mov x23, 20 + bl doHorizontalLine + add x22, x22, 1 + bl doHorizontalLine + mov x16, x21 + mov x12, x22 + add x16, x16, 10 + +doIDown: + bl drawPixel + add x12, x12, #1 + cmp x9, #20 + b.eq drawIBot + add x9, x9, #1 + b doIDown + +drawIBot: + mov x23, 20 + ldur x21, [sp, #8] + ldur x22, [sp, #16] + add x22, x22, 20 + bl doHorizontalLine + add x22, x22, 1 + bl doHorizontalLine + +endI: + ldur x24, [sp, #32] + ldur x23, [sp, #24] + ldur x22, [sp, #16] + ldur x21, [sp, #8] + ldur lr, [sp] + add sp, sp, 40 + ret + +.globl doI +doI: + // Args + // x21 x lugar dónde empiezo a dibujar la figura + // x22 y lugar dónde empiezo a dibujar la figura + // w18 color + sub sp, sp, 40 + stur lr, [sp] + stur x21, [sp, #8] + stur x22, [sp, #16] + stur x23, [sp, #24] + stur x24, [sp, #32] + + mov x23, 10 + bl doHorizontalLine + add x21, x21, 5 + sub x22, x22, 10 + mov x23, 10 + bl vertLine + sub x22, x22, 3 + mov x23, 1 + bl doHorizontalLine + add x22, x22, 3 + sub x21, x21, 3 + mov x23, 3 + bl doHorizontalLine + + ldur x24, [sp, #32] + ldur x23, [sp, #24] + ldur x22, [sp, #16] + ldur x21, [sp, #8] + ldur lr, [sp] + add sp, sp, 40 + ret + +.globl doO +doO: + sub sp, sp, #32 + str x23, [sp, #24] + stur x22, [sp, #16] + stur x21, [sp, #8] + stur lr, [sp] + + add x21, x21, 1 + + mov x23, 7 // Cant de pixeles + bl doHorizontalLine // Linea h inferior + add x21, x21, 7 + sub x22, x22, 8 + mov x23, 7 + bl vertLine // Linea v derecha + sub x21, x21, 7 + sub x22, x22, 1 + bl doHorizontalLine // Linea h superior + sub x21, x21, 1 + add x22, x22, 1 + + bl vertLine // Linea v izquierda + + ldr lr, [sp] + ldr x21, [sp, #8] + ldr x22, [sp, #16] + ldr x23, [sp, #24] + add sp, sp, #32 + ret + +.globl doDm +doDm: + // Args + // x21 x inicial + // x22 y inicial + // w18 color + // Uses + // x23 par doHorizontalLine + sub sp, sp, 24 + stur lr, [sp] + stur x21, [sp, #8] + stur x22, [sp, #16] + mov x16, x21 + mov x12, x22 + mov x9, 0 + + sub x22, x22, 20 + mov x23, 20 + bl vertLine + +preDDer: + mov x23, 5 + bl doHorizontalLine + add x21, x21, 6 + add x22, x22, 1 + mov x16, x21 + mov x12, x22 + bl drawPixel + add x16, x16, 1 + add x12, x12, 1 + bl drawPixel + add x16, x16, 1 + add x12, x12, 1 + bl drawPixel + add x16, x16, 1 + add x12, x12, 1 + bl drawPixel + add x16, x16, 1 + add x12, x12, 1 + bl drawPixel + mov x9, 0 + +dDer: + add x12, x12, 1 + bl drawPixel + cmp x9, 9 + b.eq dDoIzq + add x9, x9, 1 + b dDer + +dDoIzq: + sub x16, x16, 1 + add x12, x12, 1 + bl drawPixel + sub x16, x16, 1 + add x12, x12, 1 + bl drawPixel + sub x16, x16, 1 + add x12, x12, 1 + bl drawPixel + sub x16, x16, 1 + add x12, x12, 1 + bl drawPixel + sub x16, x16, 1 + add x12, x12, 1 + bl drawPixel + sub x16, x16, 1 + bl drawPixel + sub x16, x16, 1 + bl drawPixel + sub x16, x16, 1 + bl drawPixel + sub x16, x16, 1 + bl drawPixel + b endD + +endD: + ldur x22, [sp, #16] + ldur x21, [sp, #8] + ldur lr, [sp] + add sp, sp, #24 + ret + +.globl doL +doL: // 16x8 + // Args + // x21 x inicial + // x22 y inicial + // x23 w + // w18 color + sub sp, sp, #32 + str x21, [sp, #24] + str x22, [sp, #16] + str x23, [sp, #8] + str lr, [sp] + + add x21, x21, 2 + mov x23, 8 + bl doHorizontalLine + add x21, x21, 4 + sub x22, x22, 17 + mov x23, 16 + bl vertLine + sub x21, x21, 3 + mov x23, 4 + bl doHorizontalLine + + ldr lr, [sp] + ldr x21, [sp, #24] + ldr x22, [sp, #16] + ldr x23, [sp, #8] + add sp, sp, #32 + ret + +.globl doS +doS: // 16x8 + // Args + // x21 x inicial + // x22 y inicial + // x23 w + // w18 color + sub sp, sp, #24 + str x21, [sp, #16] + str x22, [sp, #8] + str lr, [sp] + + mov x23, 8 + bl doHorizontalLine + add x21, x21, 8 + sub x22, x22, 3 + mov x23, 3 + bl vertLine + sub x21, x21, 7 + sub x22, x22, 1 + mov x23, 7 + bl doHorizontalLine + sub x21, x21, 1 + sub x22, x22, 3 + mov x23, 3 + bl vertLine + add x21, x21, 1 + sub x22, x22, 1 + mov x23, 7 + bl doHorizontalLine + + ldr lr, [sp] + ldr x22, [sp, #8] + ldr x21, [sp, #16] + add sp, sp, #24 + ret + +.globl doP +doP: // 16x8 + // Args + // x21 x inicial + // x22 y inicial + // x23 w + // w18 color + sub sp, sp, 32 + str x23, [sp, 24] + str x21, [sp, 16] + str x22, [sp, 8] + str lr, [sp] + + mov x23, 9 + bl doHorizontalLine + add x21, x21, 8 + sub x22, x22, 4 + mov x23, 3 + bl vertLine + sub x21, x21, 8 + sub x22, x22, 1 + mov x23, 8 + bl doHorizontalLine + mov x23, 12 + bl vertLine + + ldr lr, [sp] + ldr x23, [sp, 24] + ldr x21, [sp, 16] + ldr x22, [sp, 8] + add sp, sp, 32 + ret + +.globl doM +doM: + // Args + // x21 x inicial + // x22 y inicial + // w18 color + // Uses + // x23 par doHorizontalLine + sub sp, sp, 24 + stur lr, [sp] + stur x21, [sp, #8] + stur x22, [sp, #16] + + sub x22, x22, 8 + mov x23, 8 + bl vertLine + + mov x23, 5 + bl doHorizontalLine + add x21, x21, 6 + add x22, x22, 1 + mov x23, 7 + bl vertLine + add x21, x21, 1 + sub x22, x22, 1 + mov x23, 5 + bl doHorizontalLine + add x21, x21, 6 + add x22, x22, 1 + mov x23, 7 + bl vertLine + +endM: + ldur x22, [sp, #16] + ldur x21, [sp, #8] + ldur lr, [sp] + add sp, sp, 24 + ret + +.globl doN +doN: + // Args + // x21 x + // x22 y + sub sp, sp, 32 + str x21, [sp, 24] + str x22, [sp, 16] + str x23, [sp, 8] + str lr, [sp] + + sub x22, x22, 8 + mov x23, 8 + bl vertLine + mov x23, 5 + bl doHorizontalLine + add x21, x21, 6 + add x22, x22, 1 + mov x23, 7 + bl vertLine + + ldr lr, [sp] + ldr x23, [sp, 8] + ldr x22, [sp, 16] + ldr x21, [sp, 24] + add sp, sp, 32 + ret + +.globl doVm +doVm: + sub sp, sp, 32 + str x21, [sp, 24] + str x22, [sp, 16] + str x23, [sp, 8] + str lr, [sp] + + sub x22, x22, 20 + mov x23, 5 + bl vertLine + + add x21, x21, 6 + bl vertLine + sub x21, x21, 6 + + add x21, x21, 1 + add x22, x22, 6 + bl vertLine + + add x21, x21, 4 + bl vertLine + sub x21, x21, 4 + + add x21, x21, 1 + add x22, x22, 6 + bl vertLine + + add x21, x21, 2 + bl vertLine + sub x21, x21, 2 + + add x21, x21, 1 + add x22, x22, 6 + bl vertLine + + ldr lr, [sp] + ldr x23, [sp, 8] + ldr x22, [sp, 16] + ldr x21, [sp, 24] + add sp, sp, 32 + ret + +.globl doZzzeta +doZzzeta: + // Args + // x21 x inicial + // x22 y inicial + // x18 Color + // Usa: + // x23 para doHorizontalLine + sub sp, sp, 24 + stur lr, [sp, 16] + stur x21, [sp, 8] + stur x22, [sp] + mov x16, x21 + mov x12, x22 + mov x9, 0 + + mov x23, 20 + bl doHorizontalLine + add x21, x21, 19 + mov x16, x21 + +doZDiagz: + bl drawPixel + sub x22, x22, 1 + add x21, x21, 1 + add x16, x16, 1 + sub x12, x12, 1 + cmp x9, 19 + b.eq doZBotz + add x9, x9, 1 + b doZDiagz + +doZBotz: + mov x23, 20 + bl doHorizontalLine + +endZz: + ldur x22, [sp] + ldur x21, [sp, 8] + ldur lr, [sp, 16] + add sp, sp, 24 + ret + +.globl doZ +doZ: + // Args + // x21 x inicial + // x22 y inicial + // x18 Color + // Usa: + // x23 para doHorizontalLine + sub sp, sp, 24 + stur lr, [sp, 16] + stur x21, [sp, 8] + stur x22, [sp] + mov x16, x21 + mov x12, x22 + mov x9, 0 + + sub x22, x22, 8 + + mov x23, 8 + bl doHorizontalLine + add x21, x21, 8 + mov x16, x21 + mov x12, x22 + +doZDiag: + bl drawPixel + add x22, x22, 1 + sub x21, x21, 1 + sub x16, x16, 1 + add x12, x12, 1 + cmp x9, 7 + b.eq doZBot + add x9, x9, 1 + b doZDiag + +doZBot: + mov x23, 8 + bl doHorizontalLine + +endZ: + ldur x22, [sp] + ldur x21, [sp, 8] + ldur lr, [sp, 16] + add sp, sp, 24 + ret + +.globl doGm +doGm: + // Args + // x21 x inicial + // x22 y inicial + // w18 color + // AUX fun: + // doVertLine + sub sp, sp, 32 + stur x21, [sp, 24] + stur x22, [sp, 16] + stur x23, [sp, 8] + stur lr, [sp] + + add x21, x21, 1 // Ignoramos el primer pixel + mov x23, 10 + bl doHorizontalLine // Linea h inferior + + add x21, x21, 10 + sub x22, x22, 6 + mov x23, 5 + bl vertLine + + sub x21, x21, 5 + mov x23, 5 + bl doHorizontalLine + + sub x21, x21, 5 + sub x22, x22, 9 + mov x23, 14 + bl vertLine // Linea v izquierda + + add x21, x21, 1 + sub x22, x22, 1 + mov x23, 9 + bl doHorizontalLine // Linea h superior + + add x21, x21, 9 + add x22, x22, 1 + mov x23, 1 + bl vertLine + + ldur lr, [sp] + ldur x23, [sp, 8] + ldur x22, [sp, 16] + ldur x21, [sp, 24] + add sp, sp, 32 + ret + +.globl doG +doG: // 16x8 + // Args + // x21 x inicial + // x22 y inicial + // w18 color + // x23 = w = 16 + sub sp, sp, #48 + stur x9, [sp, #40] // x1 + stur x10, [sp, #32] // x2 + stur x21, [sp, #24] + stur x22, [sp, #16] + stur x23, [sp, #8] + stur lr, [sp] + + add x21, x21, 1 // Ignoramos el primer pixel + mov x23, 7 + bl doHorizontalLine // Linea h inferior + add x21, x21, 7 + mov x10, x22 // yih + sub x22, x22, 7 + mov x9, x21 // xih + bl vertLine // Linea v derecha + sub x21, x21, 7 + mov x23, 7 + bl doHorizontalLine + + sub x21, x21, 1 // Ignoramos el primer pixel + add x22, x22, 1 + mov x23, 5 + + bl vertLine // Linea v izq + + mov x21, x9 + mov x22, x10 + + mov x23, 6 // hago la line hacia abajo + bl vertLine + + add x22, x22, 7 + sub x21, x21, 6 + mov x23, 6 + bl doHorizontalLine + sub x22, x22, 1 + sub x21, x21, 1 + + mov x23, 1 + bl doHorizontalLine + + ldur lr, [sp] + ldur x23, [sp, #8] + ldur x22, [sp, #16] + ldur x21, [sp, #24] + ldur x10, [sp, #32] + ldur x9, [sp, #40] + add sp, sp, #48 + ret + +.globl doT +doT: // 16x8 + sub sp, sp, 32 + str lr, [sp] + str x23, [sp, 8] + str x22, [sp, 16] + str x21, [sp, 24] + + add x21, x21, 1 + mov x23, 3 + bl doHorizontalLine + sub x21, x21, 1 + sub x22, x22, 17 + mov x23, 16 + bl vertLine + + add x22, x22, 7 + mov x23, 4 + bl doHorizontalLine + + ldr lr, [sp] + ldr x23, [sp, 8] + ldr x22, [sp, 16] + ldr x21, [sp, 24] + add sp, sp, 32 + ret + +.globl doDiego +doDiego: + // Args + // x21 x + // x22 y + // w18 color + // x23 for O + sub sp, sp, #40 + str x18, [sp, #32] + str x23, [sp, #24] + str x22, [sp, #16] + str x21, [sp, #8] + str lr, [sp] + + bl doDm + + add x21, x21, 15 // Espacio entre letras + bl doI + + add x21, x21, 15 // Espacio entre letras + bl doE + + add x21, x21, 15 // Espacio entre letras + bl doG + + add x21, x21, 15 // Espacio entre letras + bl doO + + add x21, x21, 30 // Espacio entre letras + bl doGm + + add x21, x21, 15 // Espacio entre letras + bl doI + + add x21, x21, 15 // Espacio entre letras + bl doM + + add x21, x21, 20 // Espacio entre letras + bl doE + + add x21, x21, 14 // Espacio entre letras + bl doN + + add x21, x21, 15 // Espacio entre letras + bl doE + + add x21, x21, 15 // Espacio entre letras + bl doZ + +endDiego: + ldr lr, [sp] + ldr x21, [sp, #8] + ldr x22, [sp, #16] + ldr x23, [sp, #24] + ldr x18, [sp, #32] + add sp, sp, #40 + ret + +.globl doValentinaVispo +doValentinaVispo: + // @Valentina Vispo + // x21 xo + // x22 yo + // w18 Colour + sub sp, sp, #40 + str x18, [sp, #32] + str x23, [sp, #24] + str x22, [sp, #16] + str x21, [sp, #8] + str lr, [sp] + + bl doVm + + add x21, x21, 15 // Espacio entre letras + bl doA + + add x21, x21, 15 // Espacio entre letras + bl doL + + add x21, x21, 15 // Espacio entre letras + bl doE + + add x21, x21, 15 // Espacio entre letras + bl doN + + add x21, x21, 15 // Espacio entre letras + bl doT + + add x21, x21, 15 // Espacio entre letras + bl doI + + add x21, x21, 15 // Espacio entre letras + bl doN + + add x21, x21, 15 // Espacio entre letras + bl doA + + add x21, x21, 30 // Espacio entre letras + bl doVm + + add x21, x21, 10 // Espacio entre letras + bl doI + + add x21, x21, 15 // Espacio entre letras + bl doS + + add x21, x21, 15 // Espacio entre letras + bl doP + + add x21, x21, 15 // Espacio entre letras + bl doO + +endDoValentinaVispo: + ldr lr, [sp] + ldr x21, [sp, #8] + ldr x22, [sp, #16] + ldr x23, [sp, #24] + ldr x18, [sp, #32] + add sp, sp, #40 + ret diff --git a/ejercicio1/start.s b/ejercicio1/start.s new file mode 100644 index 0000000..d9c432e --- /dev/null +++ b/ejercicio1/start.s @@ -0,0 +1,142 @@ + .text + .org 0x80000 + +.globl PreFrameBuffer +.data + PreFrameBuffer: .skip 4*640*480 + // Setup Frame Buffer + .equ SCREEN_WIDTH, 640 + .equ SCREEN_HEIGH, 480 + .equ BITS_PER_PIXEL, 32 + + .equ MAIL_BASE, 0xB880 // Mailbox Base Address + .equ MAIL_WRITE, 0x20 // Mailbox Write Register + .equ MAIL_TAGS, 0x8 // Mailbox Channel 8: Tags (ARM to VC) + .equ PERIPHERAL_BASE, 0x3F000000 // Peripheral Base Address + + .equ Get_Allocate_Buffer, 0x00040001 // Frame Buffer: Allocate Buffer (Response: Frame Buffer Base Address In Bytes, Frame Buffer Size In Bytes) + + .equ Set_Physical_Display, 0x00048003 // Frame Buffer: Set Physical (Display) Width/Height (Response: Width In Pixels, Height In Pixels) + .equ Set_Virtual_Buffer, 0x00048004 // Frame Buffer: Set Virtual (Buffer) Width/Height (Response: Width In Pixels, Height In Pixels) + .equ Set_Depth, 0x00048005 // Frame Buffer: Set Depth (Response: Bits Per Pixel) + .equ Set_Virtual_Offset, 0x00048009 // Frame Buffer: Set Virtual Offset (Response: X In Pixels, Y In Pixels) + .equ Set_Palette, 0x0004800B // Frame Buffer: Set Palette (Response: RGBA Palette Values (Index 0 To 255)) + .equ Set_Pixel_Order, 0x00048006 // Frame Buffer: Set Pixel Order + .equ Get_Pixel_pitch, 0x00048006 // Frame Buffer: Set Pixel Order + + // UART data + .equ Set_Power, 0x00028001 // UART: Set Power + .equ Set_ClkRate, 0x00038002 // UART: Set Clock Rate + + .equ MMIO_BASE_ALTA, 0x3f20 + + .equ GPFSEL0, 0x0000 + .equ GPFSEL1, 0x0004 + .equ GPPUD, 0x0094 + .equ GPPUDCLK0, 0x0098 + + .equ UART0_DR, 0x1000 + .equ UART0_FR, 0x1018 + .equ UART0_IBRD, 0x1024 + .equ UART0_FBRD, 0x1028 + .equ UART0_LCRH, 0x102C + .equ UART0_CR, 0x1030 + .equ UART0_IMSC, 0x1038 + .equ UART0_ICR, 0x1044 +// Return CPU ID (0..3) Of The CPU Executed On + +.section ".text.boot" +.globl _start + +_start: + + mrs x1, mpidr_el1 // X0 = Multiprocessor Affinity Register (MPIDR) + and x1, x1, #3 // X0 = CPU ID (Bits 0..1) + cbz x1, StackInit // IF (CPU ID == 0) Branch To Finit else (Core ID 1..3) CoreLoop + // Infinite Loop For Core 1, 2 and 3 +CoreLoop: + b CoreLoop + +StackInit: +// set stack before our code + ldr x1, =_start + mov sp, x1 + + // clear bss + + ldr x1, =__bss_start + ldr w2, =__bss_size +_StackInit_loop: + cbz w2, FB_Init + str xzr, [x1], #8 + sub w2, w2, #1 + cbnz w2, _StackInit_loop + +// Core 0 Init the framebuffer +FB_Init: + ldr x0, =(FB_STRUCT + MAIL_TAGS) + ldr x1, =MAIL_BASE + ldr x2, =FB_POINTER + orr x1, x1, PERIPHERAL_BASE + str w0, [x1, MAIL_WRITE + MAIL_TAGS] // Mail Box Write + ldr w0, [x2] // W0 = Frame Buffer Pointer + cbz w0, FB_Init // IF (Frame Buffer Pointer == Zero) Re-Initialize Frame Buffer + and w0, w0, 0x3FFFFFFF // Convert Mail Box Frame Buffer Pointer From BUS Address To Physical Address ($CXXXXXXX -> $3XXXXXXX) + str w0, [x2] // Store Frame Buffer Pointer Physical Address + add w10, w0, wzr + b main + +.align 16 +FB_STRUCT: // Mailbox Property Interface Buffer Structure + .word FB_STRUCT_END - FB_STRUCT // Buffer Size In Bytes (Including The Header Values, The End Tag And Padding) + .word 0x00000000 // Buffer Request/Response Code + // Request Codes: $00000000 Process Request Response Codes: $80000000 Request Successful, $80000001 Partial Response + // Sequence Of Concatenated Tags + .word Set_Physical_Display // Tag Identifier + .word 0x00000008 // Value Buffer Size In Bytes + .word 0x00000008 // 1 bit (MSB) Request/Response Indicator (0=Request, 1=Response), 31 bits (LSB) Value Length In Bytes + .word SCREEN_WIDTH // Value Buffer + .word SCREEN_HEIGH // Value Buffer + + .word Set_Virtual_Buffer // Tag Identifier + .word 0x00000008 // Value Buffer Size In Bytes + .word 0x00000008 // 1 bit (MSB) Request/Response Indicator (0=Request, 1=Response), 31 bits (LSB) Value Length In Bytes + .word SCREEN_WIDTH // Value Buffer + .word SCREEN_HEIGH // Value Buffer + + .word Set_Virtual_Offset // Tag Identifier + .word 0x00000008 // Value Buffer Size In Bytes + .word 0x00000008 // 1 bit (MSB) Request/Response Indicator (0=Request, 1=Response), 31 bits (LSB) Value Length In Bytes +FB_OFFSET_X: + .word 0 // Value Buffer +FB_OFFSET_Y: + .word 0 // Value Buffer + + .word Set_Depth // Tag Identifier + .word 0x00000004 // Value Buffer Size In Bytes + .word 0x00000004 // 1 bit (MSB) Request/Response Indicator (0=Request, 1=Response), 31 bits (LSB) Value Length In Bytes + .word BITS_PER_PIXEL // Value Buffer + + .word 0x48006 // Tag Identifier + .word 0x00000004 // Value Buffer Size In Bytes + .word 0x00000004 // 1 bit (MSB) Request/Response Indicator (0=Request, 1=Response), 31 bits (LSB) Value Length In Bytes + .word 0 // RGB, not BGR preferably + + .word Set_Palette // Tag Identifier + .word 0x00000010 // Value Buffer Size In Bytes + .word 0x00000010 // 1 bit (MSB) Request/Response Indicator (0=Request, 1=Response), 31 bits (LSB) Value Length In Bytes + .word 0 // Value Buffer (Offset: First Palette Index To Set (0-255)) + .word 2 // Value Buffer (Length: Number Of Palette Entries To Set (1-256)) +FB_PAL: + .word 0x00000000,0xFFFFFFFF // RGBA Palette Values (Offset To Offset+Length-1) + + .word Get_Allocate_Buffer // Tag Identifier + .word 0x00000008 // Value Buffer Size In Bytes + .word 0x00000008 // 1 bit (MSB) Request/Response Indicator (0=Request, 1=Response), 31 bits (LSB) Value Length In Bytes +FB_POINTER: + .word 0 // FrameBuffer Pointer +FB_SIZE: + .word 0 // FrameBuffer Size + + .word 0x00000000 // $0 (End Tag) +FB_STRUCT_END: diff --git a/ejercicio2/Makefile b/ejercicio2/Makefile new file mode 100644 index 0000000..0f0785e --- /dev/null +++ b/ejercicio2/Makefile @@ -0,0 +1,33 @@ +ARMGNU ?= aarch64-linux-gnu + +AOPS = -g --warn --fatal-warnings +ASM_SRCS = $(wildcard *.s) +ASM_OBJS = $(ASM_SRCS:.s=.o) + +all : kernel8.img + +%.o: %.s + $(ARMGNU)-as $(AOPS) $< -o $@ + +clean : + rm -f *.o memory_map.txt kernel8.list kernel8.img kernel8.elf + +kernel8.img : memmap $(ASM_OBJS) + $(ARMGNU)-ld $(ASM_OBJS) -T memmap -o kernel8.elf -M > memory_map.txt + $(ARMGNU)-objdump -D kernel8.elf > kernel8.list + $(ARMGNU)-objcopy kernel8.elf -O binary kernel8.img + +run : all + qemu-system-aarch64 -M raspi3 -kernel kernel8.img -serial stdio + +remake: clean + make run + +runQEMU : kernel8.img + qemu-system-aarch64 -s -S -M raspi3 -kernel kernel8.img + +runGDB: + gdb-multiarch -ex "set architecture aarch64" -ex "target remote localhost:1234" --ex "dashboard registers -style list 'x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 x11 x12 x13 x14 x15 x16 x17 x18 x19 x20 x21 x22 x23 x24 x25 x26 x27 x28 x29 x30 sp pc cpsr'" \-ex "add-symbol-file app.o 0x00000000000c6024" \-ex "add-symbol-file draw.o 0x00000000000900c8" \-ex "add-symbol-file animations.o 0x0000000000146398" + +#0x00000000000900c8" +#\-ex "b break" \-ex "continue" diff --git a/ejercicio2/TPQEMU_Gimenez_Vispo.txt b/ejercicio2/TPQEMU_Gimenez_Vispo.txt new file mode 100644 index 0000000..4285fdd --- /dev/null +++ b/ejercicio2/TPQEMU_Gimenez_Vispo.txt @@ -0,0 +1,16 @@ +Ejercicio 2: + +En el ejercicio 2 la idea es hacer 3 escenas diferentes: + +En la primera escena se encuentra una computadora, un mouse clickea un botón como inicio de la animación, esto provoca que se "rompa" la pantalla. + +La siguiente escena empieza como una especie de cuenta regresiva con colores (se ven líneas que convergen desde el punto central mientras se expande un círculo, ambos con colores RBG). + +Cuando termina esa cuenta se muestran pirámides y el nombre y apellido de cada intetgrante (un ciclo es de día y el otro de noche). Arriba se ve el respectivo sol/luna moviéndose de izquierda a derecha. Esta esta última escena se repite en bucle. + +Trabajo en Github: +https://github.com/shirosweets/vc-framebuffer + +Alumnos: +- Gimenez, Diego Nicolás +- Vispo, Valentina Solange \ No newline at end of file diff --git a/ejercicio2/aScreenAnimations.s b/ejercicio2/aScreenAnimations.s new file mode 100644 index 0000000..a0985e5 --- /dev/null +++ b/ejercicio2/aScreenAnimations.s @@ -0,0 +1,150 @@ + +.equ SCREEN_WIDTH, 640 +.equ SCREEN_HEIGH, 480 + +.data + WHITE: .word 0xFFFFFF + +.globl animationTest +animationTest: + sub sp, sp, #8 + stur x30, [sp, #0] // Guardamos el return pointer en memoria + mov x18, xzr // Empieza en negro +antestloop: + bl paintScreen // Pinta la pantalla + bl delay + add x18, x18, #1 + mov x8, WHITE + cmp x18, x8 + b.ne antestloop + ldur x30, [sp, #0] // Guardamos el return pointer en memoria ret + add sp, sp, #8 + ret + +.globl circleAnimation1 +circleAnimation1: + sub sp, sp, #8 + stur x30, [sp, #0] // Guardamos el return pointer en memoria + mov x21, 320 + mov x22, 240 + mov x23, 10 // x23 = Radio + mov x24, 30 // x24 = Color + // circloop1... + +circloop1: + mov x13, x24 // R + mov x14, 10 // G + mov x15, x24 // B + bl setColour // R+G+B = Naranja + bl doCircle + add x23, x23, #1 // r++ + bl doCircle + bl delay + add x23, x23, #2 // r++ + mov x8, #255 + cmp x24, x8 + b.eq circlend + add x24, x24, #1 // colour++ + b circloop1 + +circlend: + ldur x30, [sp, #0] // Guardamos el return pointer en memoria ret + add sp, sp, #8 + ret + +.globl circleAnimation2 +circleAnimation2: + sub sp, sp, #8 + stur x30, [sp, #0] // Guardamos el return pointer en memoria + mov x21, 320 + mov x22, 240 + mov x23, 10 // x23 = Radio + mov x24, 30 // x24 = Color + // circloop2... + +circ2loop1: + mov x13, x24 // R + mov x14, 10 // G + mov x15, 10 // B + bl setColour // R+G+B = Naranja + bl doCircle + add x23, x23, #1 // r++ + bl doCircle + add x23, x23, #1 // r++ + bl doCircle + bl delay + add x23, x23, #1 // r++ + mov x8, #255 + cmp x24, x8 + b.eq circ2lend + add x24, x24, #1 // colour++ + b circ2loop1 + +circ2lend: + ldur x30, [sp, #0] // Guardamos el return pointer en memoria ret + add sp, sp, #8 + ret + +.globl cleanScreen +cleanScreen: // Pinta toda la pantalla de negro + sub sp, sp, #16 + stur lr, [sp] // Guardo el link register para no pisarlo + stur x30, [sp, #8] // Guardamos el return pointer en memoria + mov x13, xzr // R + mov x14, xzr // G + mov x15, xzr // B + bl setColour // Negro + bl paintScreen + ldur x30, [sp, #8] // Guardamos el return pointer en memoria ret + ldur lr, [sp] // Devuelvo el link register + add sp, sp, #16 + ret + +.globl cleanScreenBuffer +cleanScreenBuffer: // Pinta toda la pantalla de negro + sub sp, sp, #16 + stur lr, [sp] // Guardo el link register para no pisarlo + stur x30, [sp, #8] // Guardamos el return pointer en memoria + mov x13, xzr // R + mov x14, xzr // G + mov x15, xzr // B + bl setColour // Negro + bl paintScreenBuffer + ldur x30, [sp, #8] // Guardamos el return pointer en memoria ret + ldur lr, [sp] // Devuelvo el link register + add sp, sp, #16 + ret + +.globl paintScreenBuffer +paintScreenBuffer: // 320w 240h -> 76800 + 240 + // Return -> nada + // Args: x18 Colour + mov x0, x20 // Origen del frameBuffer + mov x8, SCREEN_WIDTH + mov x9, SCREEN_HEIGH + mul x8, x8, x9 // x8 contador de pixeles a pintar + // paintScreenBufferLoop... + +paintScreenBufferLoop: + stur w18, [x0] // Set color of pixel N + add x0, x0, 4 // Next pixel + sub x8, x8, 1 // decrement pixel counter + cbnz x8, paintScreenBufferLoop // If not end row jump + ret + +.globl paintScreen +paintScreen: // 320w 240h -> 76800 + 240 + // Return -> nada + // Args: x18 Colour + adr x28, PreFrameBuffer // Origen del frameBuffer + mov x8, SCREEN_WIDTH + mov x9, SCREEN_HEIGH + mul x8, x8, x9 // x8 contador de pixeles a pintar + // paintScreenLoop... + +paintScreenLoop: + stur w18, [x28] // Set color of pixel N + add x28, x28, 4 // Next pixel + sub x8, x8, 1 // decrement pixel counter + cbnz x8, paintScreenLoop // If not end row jump + ret diff --git a/ejercicio2/animations.s b/ejercicio2/animations.s new file mode 100644 index 0000000..005f915 --- /dev/null +++ b/ejercicio2/animations.s @@ -0,0 +1,265 @@ + +.globl delay +// NOTE delay +delay: + add x8, xzr, xzr // counter = 0 + add x8, x8, #0xFFF // counter = 0xF...F (un numero enorme) + lsl x8, x8, #10 // 3th = * 2^~10 (slow = 1s) // * 2^~9 (medium = ~0,3s) + +delayloop: + cbz x8, delayEnd + ldur x9, [sp, #0] + stur x9, [sp, #0] + sub x8, x8, #1 // counter-- + b delayloop + +delayEnd: + ret + +.globl fastDelay +// NOTE fastDelay +fastDelay: + add x8, xzr, xzr // counter = 0 + add x8, x8, #0xFFF // counter = 0xF...F (un numero enorme) + lsl x8, x8, #2 // 3th = * 2^~10 (slow = 1s) // * 2^~9 (medium = ~0,3s) + +fastDelayloop: + cbz x8, fastDelayEnd + ldur x9, [sp, #0] + stur x9, [sp, #0] + sub x8, x8, #1 // counter-- + b fastDelayloop + +fastDelayEnd: + ret + +.globl longDelay +// NOTE longDelay +longDelay: + sub sp, sp, 16 + str x8, [sp, 8] + str x9, [sp] + + mov x8, 0 + add x8, x8, #0xFFF + lsl x8, x8, 15 + +ldelayloop: + cbz x8, ldelayEnd + ldur x9, [sp, #0] + stur x9, [sp, #0] + sub x8, x8, #1 // counter-- + b ldelayloop + +ldelayEnd: + ldr x9, [sp] + ldr x8, [sp, 8] + add sp, sp, 16 + ret + +.globl lineAnimation +// NOTE lineAnimation +lineAnimation: + sub sp, sp, #8 // Guardamos 1 lugar del stack + stur x30, [sp, #0] // Registro 30 para el RET en el stack + + mov x4, 320 + mov x5, 140 + mov x6, 10 + mov x7, 260 + +lineAnimationLoop: + mov x13, 255 // R + mov x14, 0 // G + mov x15, 0 // B + bl setColour // R+G+B = Rojo + mov x8, #260 + cmp x8, x6 + b.eq endlineAnimation + mov x21, x4 + mov x22, x5 + mov x23, x6 + mov x24, x7 + bl drawLine + bl delay + bl cleanScreen + mov x13, 0 // R + mov x14, 255 // G + mov x15, 0 // B + bl setColour // R+G+B = Rojo + sub x21, x4, #1 + sub x22, x5, #1 + mov x23, #3 + bl doSquare + sub x21, x6, #1 + sub x22, x7, #1 + bl doSquare + add x6, x6, #1 + sub x4, x4, #1 + b lineAnimationLoop + +endlineAnimation: + ldur x30, [sp, #0] // Carga lo que guardó en el stack + add sp, sp, #8 // Libera el stack + ret + +.globl rgbAnimation +// NOTE rgbAnimation +rgbAnimation: + // Args + // x13 r actual + // x14 g actual + // x15 b actual + mov x9, #85 // inc = 85 + +case1: // r == 255 && b == 0 && g < 255 ---> g += inc (Rojo>>>Amarillo) + cbnz x15, case3 // b != 0 -> next case + cmp x13, #255 // NOTA: Legal + b.ne case2 // r != 255 -> next case + cmp x14, #255 + b.eq case2 // g == 255 -> next case + add x14, x14, x9 // g += inc + b endRgbAnimation + +case2: // g == 255 && b == 0 && r > 0 ---> r -= inc (Amarillo>>>>Verde) + cmp x14, #255 + b.ne case4 // g != 255 -> next case + cmp x13, xzr + b.le case3 // r <= 0 + cbnz x15, case3 // b != 0 -> next case + cbz x13, case3 // r == 0 -> next case + sub x13, x13, x9 // r -= inc + b endRgbAnimation + +case3: // g == 255 && r == 0 && b < 255 ---> b += inc (Verde>>>>Celeste) + cbnz x13, case5 // r != 0 -> next case + cmp x14, #255 + b.ne case4 // g != 255 -> next case + cmp x15, #255 + b.eq case4 // b == 255 -> next case + add x15, x15, x9 // b += inc + b endRgbAnimation + +case4: // b == 255 && r == 0 && g > 0 ---> g -= inc (Cyan>>>>Azul) + cmp x15, #255 + b.ne case6 // b != 255 -> no es ni case4 ni case5 + cbnz x13, case5 // r != 0 -> next case + cbz x14, case5 // g == 0 -> next case + sub x14, x14, x9 // g -= inc + b endRgbAnimation + +case5: // b == 255 && g == 0 && r < 255 ---> r += inc (Azul>>>>Violeta) + cmp x13, #255 + b.eq case6 // r == 255 --> last case + add x13, x13, x9 // r += inc + b endRgbAnimation + +case6: // r == 255 && g == 0 && b > 0 ---> b -= inc (Violeta>>>>Rojo) + sub x15, x15, x9 // b -= inc + b endRgbAnimation + +endRgbAnimation: + ret + + //////////////////////////////////////// + // Sencuencia "ciclo por ciclo" + // case 1 + // Rojo (255, 0, 0) -> (255, 85, 0) -> (255, 170, 0) -> (255, 255, 0) + // case 2 + // (255, 255, 0) -> (170, 255, 0) -> (85, 255, 0) -> (0, 255, 0) + // case 3 + // (0, 255, 0) -> (0, 255, 85) -> (0, 255, 170) -> Celeste (0, 255, 255) + // case 4 + // (0, 255, 255) -> (0, 170, 255) -> (0, 85, 255) -> (0, 0, 255) + // case 5 + // (0, 0, 255) -> (85, 0, 255) -> (170, 0, 255) -> (255, 0, 255) + // case 6 + // (255, 0, 255) -> (255, 0, 170) -> (255, 0, 85) -> (255, 0, 0) + +.globl rgbcycletest +rgbcycletest: + mov x13, 255 // R + mov x14, 0 // G + mov x15, 0 // B +rgbaniloop: + bl setColour + bl paintScreen + bl delay + bl rgbAnimation + b rgbaniloop + +.globl doSceneEye +// NOTE dpScemeEue +doSceneEye: + //sub sp, sp, #??? // Guardamos 1 lugar del stack + stur x30, [sp, #0] // Registro 30 para el RET en el stack + // Ojo + + // + +endDoSceneEye: + ret + +.globl rgbLinesAnim +// NOTE rgbLinesAnim +rgbLinesAnim: + sub sp, sp, #24 // Guardamos 1 lugar del stack + stur x5, [sp, #16] + stur x3, [sp, #8] + stur x30, [sp, #0] // Registro 30 para el RET en el stack + mov x3, #1 // Buffer secundario + mov x5, xzr + mov x13, #255 // R Inicial + mov x14, #0 // G Inicial + mov x15, #0 // B Inicial + bl setColour + +rgbLinesAnimLoop: + cmp x5, #319 // Si x5 ya terminó + b.ge rgbLinesAnimEnd + mov x21, #295 + mov x22, xzr + mov x23, #50 + mov x24, #480 + bl doRectangle + bl rgbAnimation + bl setColour + mov x21, #320 + mov x22, #240 + mov x23, x5 + bl doCircle + add x23, x23, #1 + bl doCircle + bl rgbAnimation + bl setColour + mov x21, xzr + +rgbLinesAnimSubLoop: + cmp x21, #640 + b.ge rgbLinesAnimSubEnd + mov x22, xzr // y = 0 + mov x23, #640 // x = WIDTH + sub x23, x23, x21 // x = WIDTH - x21 + sub x23, x23, #1 // x = WIDTH - x21 - 1 + mov x24, #480 + bl drawLine + add x21, x21, #1 + add x23, x23, #1 + bl drawLine + bl rgbAnimation + bl setColour + add x21, x21, #1 + b rgbLinesAnimSubLoop + +rgbLinesAnimSubEnd: + add x5, x5, #1 + bl drawUpdate + bl fastDelay + b rgbLinesAnimLoop + +rgbLinesAnimEnd: + ldur x30, [sp, #0] // Registro 30 para el RET en el stack + ldur x3, [sp, #8] + ldur x5, [sp, #16] + add sp, sp, #24 // Guardamos 1 lugar del stack + ret diff --git a/ejercicio2/app.s b/ejercicio2/app.s new file mode 100644 index 0000000..ad20d39 --- /dev/null +++ b/ejercicio2/app.s @@ -0,0 +1,44 @@ + +.equ SCREEN_BYTES, 4*640*480 +.equ SCREEN_PIXELS, 640*480 +.data + TOTAL_PIXELS: .dword SCREEN_PIXELS + +.equ SCREEN_WIDTH, 640 +.equ SCREEN_HEIGH, 480 +.equ BITS_PER_PIXEL, 32 +.equ COLOR_1, 0xFF // Color blanco R // 0xC7 +.equ COLOR_2, 0xFFFF // Color blanco GB // 0x1607 +.equ COLOR_NEGRO, 0x00 + +// 32 bits (4 bytes) +// Registros basura: x1, x2, x8, x9, x10 + +// Registros globales // +// SCREEN_HEIGH +// SCREEN_WIDTH +// x0 Pixel a pintar +// x18 Colour +// x20 Base del framebuffer +// x28 PreFrameBuffer + +.globl main +main: + mov x20, x0 // X0 Dirección base del FrameBuffer + adr x28, PreFrameBuffer // x28 Dirección base del PreFrameBuffer + + bl cleanScreen + + mov x21, 200 // x Posición inicial del mouse + mov x22, 250 // y Posición inicial del mouse + bl doAnimacionInicial // Computadora -> Glitch -> Pirámides + + b EndMain + ret + +EndMain: + bl delay + b EndMain + +return: + ret diff --git a/ejercicio2/baseCore.s b/ejercicio2/baseCore.s new file mode 100644 index 0000000..f2ebfd5 --- /dev/null +++ b/ejercicio2/baseCore.s @@ -0,0 +1,146 @@ + +.equ SCREEN_BYTES, 4*640*480 +.equ SCREEN_PIXELS, 640*480 +.data + TOTAL_PIXELS: .dword SCREEN_PIXELS + +.equ SCREEN_WIDTH, 640 +.equ SCREEN_HEIGH, 480 +.equ BITS_PER_PIXEL, 32 +.equ COLOR_1, 0xFF // Color blanco R // 0xC7 +.equ COLOR_2, 0xFFFF // Color blanco GB // 0x1607 +.equ COLOR_NEGRO, 0x00 + +.globl drawPixel +drawPixel: + // Args: y=x12 -- x=x16 -- colour=x18 -- BufferSwitch = x3 + sub sp, sp, #16 + str x8, [sp, 8] + stur x30, [sp, #0] + bl setPixel // ret : x0 + cbz x3, drawBuffer // if x3 == 0 dibujar en el buffer + b drawPrebuffer // else dibujar en el prebuffer + +drawBuffer: + mov x8, x0 // Dibujamos el valor original x0 + b drawPixelEnd + +drawPrebuffer: // then dibujar en x28 + add x8, x0, x28 // Traducción del buffer al prebuffer: + sub x8, x8, x20 // x8 = x0 + (X28 - X20) + +drawPixelEnd: + stur w18, [x8] // stur xN guarda 64bits, y stur wN guarda medio registro (32bits) + ldur x30, [sp, #0] + ldr x8, [sp, 8] + add sp, sp, #16 + ret + +.globl setPixel +setPixel: + // Return: x0 Pixel a pintar + // Args: y=x12 -- x=x16 + mov x8, SCREEN_WIDTH + mul x0, x12, x8 // y * WIDTH + add x0, x0, x16 // + x + lsl x0, x0, 2 // *4 + add x0, x20, x0 // Pixel a pintar + ret + +.globl drawUpdate +drawUpdate: + // x28 PreFrameBuffer + // x20 FrameBuffer + sub sp, sp, 40 + str x8, [sp, 32] + str x7, [sp, 24] + str x9, [sp, 16] + str x10, [sp, 8] + str lr, [sp] + + mov x8, x20 + mov x7, x28 + mov x9, 0 + ldr x10, TOTAL_PIXELS + +updateLoop: + ldr w6, [x7] + str w6, [x8] + add x8, x8, 4 + add x7, x7, 4 + + cmp x9, x10 + b.eq endUpdate + add x9, x9, 1 + b updateLoop + +endUpdate: + ldr lr, [sp] + ldr x10, [sp, 8] + ldr x9, [sp, 16] + ldr x7, [sp, 24] + ldr x8, [sp, 32] + add sp, sp, 40 + ret + +.globl drawUpdateWithCleanScreen +// NOTE drawUpdateWithCleanScreen +drawUpdateWithCleanScreen: + // x28 PreFrameBuffer + // x20 FrameBuffer + sub sp, sp, 40 + str x8, [sp, 32] + str x7, [sp, 24] + str x9, [sp, 16] + str x10, [sp, 8] + str lr, [sp] + mov x8, x20 + mov x7, x28 + mov x9, 0 + ldr x10, TOTAL_PIXELS + mov w15, 0x00 + +updateLoopWithClean: + str w15, [x7] + str w15, [x8] + add x8, x8, 4 + add x7, x7, 4 + cmp x9, x10 + b.eq endUpdateAndClean + add x9, x9, 1 + b updateLoopWithClean + +endUpdateAndClean: + ldr x8, [sp, 32] + ldr x7, [sp, 24] + ldr x9, [sp, 16] + ldr x10, [sp, 8] + ldr lr, [sp] + add sp, sp, 40 + ret + +.globl setColour // https://stackoverflow.com/questions/54918639/linking-2-object-files +// NOTE setColour +setColour: + // Return + // x18 Color a pintar + // Args + // x13 r + // x14 g + // x15 b + // 24 bits + sub sp, sp, #24 + str x13, [sp, #8] + str x14, [sp, #0] + str x15, [sp, #16] + + lsl x13, x13, 16 // Movemos 16 bits + lsl x14, x14, 8 // Movemos 8 bits + add x18, x13, x14 // R+G + add x18, x18, x15 // RG+B + + ldr x13, [sp, #8] + ldr x14, [sp, #0] + ldr x15, [sp, #16] + add sp, sp, #24 + ret diff --git a/ejercicio2/draw.s b/ejercicio2/draw.s new file mode 100644 index 0000000..d8e6a60 --- /dev/null +++ b/ejercicio2/draw.s @@ -0,0 +1,1143 @@ + +.equ SCREEN_BYTES, 4*640*480 +.equ SCREEN_PIXELS, 640*480 +.data + TOTAL_PIXELS: .dword SCREEN_PIXELS + +.equ SCREEN_WIDTH, 640 +.equ SCREEN_HEIGH, 480 +.equ BITS_PER_PIXEL, 32 +.equ COLOR_1, 0xFF // Color blanco R // 0xC7 +.equ COLOR_2, 0xFFFF // Color blanco GB // 0x1607 +.equ COLOR_NEGRO, 0x00 + + +.globl doAnimacionInicial +// NOTE doAnimacionInicial +doAnimacionInicial: + sub sp, sp, 56 + str x3, [sp, 48] + str x25, [sp, 40] + str x24, [sp, 32] + str x23, [sp, 24] + str x21, [sp, 16] + str x22, [sp, 8] + str lr, [sp] + mov x25, 0 + mov x3, #1 // Seteamos al PreFrameBuffer + +loopDelay: + bl delay // Retraso + bl cleanScreen // Limpio la pantalla + bl drawUpdate // Actualizo FB + bl doCompuVentana + add x21, x21, 6 // + sub x22, x22, 3 // Muevo el mouse + bl doMouse // Lo dibujo + cmp x25, 18 // Comparo si itere un par de veces + b.eq endFirstDelay // Cuando toque el boton del medio de la pantalla. Se rompe + add x25, x25, 1 + b loopDelay + +endFirstDelay: + bl delay + bl cleanScreen + bl doComputerBroken + bl drawUpdate + bl longDelay + bl drawUpdateWithCleanScreen + bl rgbLinesAnim + bl drawUpdate + +preDoSun: + mov x21, 39 + mov x9, 0 + sub sp, sp, 8 + stur x9, [sp, 56] +doSun: + bl cleanScreen + bl anPiramidesDia + + movz w18, 0xF2, lsl 16 + movk w18, 0x740B, lsl 0 + mov x23, 30 + mov x22, 0 + bl circRelleno + + add x21, x21, 10 + bl drawUpdate + + ldr x9, [sp, 56] + cmp x9, 58 + b.eq doNoche + add x9, x9, 1 + str x9, [sp, 56] + + b doSun + +doNoche: + add sp, sp, 8 + sub sp, sp, 8 + mov x9, 0 + str x9, [sp, 56] + mov x21, 0 +loopNoche: + bl cleanScreen + bl anPiramidesNoche + + mov w18, 0xFFFFFF + mov x23, 30 + mov x22, 0 + bl circRelleno + add x21, x21, 10 + bl drawUpdate + + ldr x9, [sp, 56] + cmp x9, 65 + b.eq preDoSun + add x9, x9, 1 + str x9, [sp, 56] + b loopNoche + +endAnimacion: + ldr lr, [sp] + ldr x22, [sp, 8] + ldr x21, [sp, 16] + ldr x23, [sp, 24] + ldr x24, [sp, 32] + ldr x25, [sp, 40] + ldr x3, [sp, 48] + add sp, sp, 56 + ret + +.globl doEstrella +// NOTE Estrella +doEstrella: + sub sp, sp, 32 + str x21, [sp, 24] + str x22, [sp, 16] + str x23, [sp, 8] + str lr, [sp] + + mov x23, 5 + bl doHorizontalLine + add x21, x21, 2 + sub x22, x22, 2 + bl vertLine + + ldr lr, [sp] + ldr x23, [sp, 8] + ldr x22, [sp, 16] + ldr x21, [sp, 24] + add sp, sp, 32 + + ret + +.globl circRelleno +circRelleno: + sub sp, sp, 24 + str x24, [sp, 16] + str x23, [sp, 8] + str lr, [sp] + mov x24, xzr + + bl doCircle + +endRellenoCir: + ldr lr, [sp] + ldr x23, [sp, 8] + ldr x24, [sp, 16] + add sp, sp, 24 + ret + + +.globl doComputerBroken +// NOTE doComputerBroken +doComputerBroken: + sub sp, sp, 72 + str x7, [sp, 64] + str x8, [sp, 56] + str x9, [sp, 48] + stur x25, [sp, 40] + stur x24, [sp, 32] + stur x23, [sp, 24] + stur x21, [sp, 16] + stur x22, [sp, 8] + stur lr, [sp] + + bl doCompuVentana + bl doMouse + mov x22, 80 + mov x23, 8 + mov x24, 8 + mov x10, 40 + mov x9, 0 + mov x7, 0 + +loopCompBro1: //FIXME No anda + cmp x9, 12 + b.eq endCompBro + mov x7, 0 + add x22, x22, 20 + mov x21, 120 + +loopCompBro2: + cmp x7, x10 + b.eq endLoopCompBro2 + + add x21, x21, 10 + bl doRectangle + + add x7, x7, 1 + b loopCompBro2 +endLoopCompBro2: + add x9, x9, 1 + b loopCompBro1 + +endCompBro: + ldr lr, [sp] + ldr x22, [sp, 8] + ldr x21, [sp, 16] + ldr x23, [sp, 24] + ldr x24, [sp, 32] + ldr x25, [sp, 40] + ldr x9, [sp, 48] + add sp, sp, 56 + ret + +.globl anPiramidesDia +// NOTE Segunda animacion +anPiramidesDia: + sub sp, sp, 56 + str x3, [sp, 40] + str x21, [sp, 32] + str x22, [sp, 24] + str x23, [sp, 16] + str x24, [sp, 8] + str lr, [sp] + mov x3, 1 + + // Fondo + movz w18, 0xA3, lsl 16 + movk w18, 0x371F, lsl 0 + mov x21, 0 + mov x22, 0 + mov x23, 640 + mov x24, 480 + bl doRectangle + + // Piramides + movz w18, 0xDF, lsl 16 + movk w18, 0x915E, lsl 0 + mov x21, 200 + mov x22, 300 + mov x23, 50 + bl doPiramide + add x21, x21, 200 + add x23, x23, x23 + bl doPiramide + + // Desierto + movz w18, 0x6B, lsl 16 + movk w18, 0x3E3E, lsl 0 + mov x21, 0 + mov x23, 640 + mov x24, 480 + bl doRectangle + mov x21, 50 + mov x22, 0 + mov x23, 50 + + movz w18, 0xFF, lsl 16 + movk w18, 0xFFFF, lsl 0 + mov x22, 350 + mov x21, 100 + bl doDiego + +endAnPir: + ldr lr, [sp] + ldr x24, [sp, 8] + ldr x23, [sp, 16] + ldr x22, [sp, 24] + ldr x21, [sp, 32] + ldr x3, [sp, 40] + add sp, sp, 56 + ret + +.globl anPiramidesNoche +anPiramidesNoche: + sub sp, sp, 40 + str x21, [sp, 32] + str x22, [sp, 24] + str x23, [sp, 16] + str x24, [sp, 8] + str lr, [sp] + + // Fondo + movz w18, 0x31, lsl 16 + movk w18, 0x1f62, lsl 0 + mov x21, 0 + mov x22, 0 + mov x23, 640 + mov x24, 480 + bl doRectangle + + // Piramides + movz w18, 0x8d, lsl 16 + movk w18, 0x5273, lsl0 + mov x21, 200 + mov x22, 300 + mov x23, 50 + bl doPiramide + add x21, x21, 200 + add x23, x23, x23 + bl doPiramide + + // Desierto + movz w18, 0xc3, lsl 16 + movk w18, 0x727c, lsl0 + mov x21, 0 + mov x23, 640 + mov x24, 480 + bl doRectangle + mov x21, 50 + mov x22, 0 + mov x23, 50 + + movz w18, 0x00, lsl 16 + movk w18, 0x0000, lsl 0 + mov x22, 350 + mov x21, 100 + bl doValentinaVispo + + ldr lr, [sp] + ldr x24, [sp, 8] + ldr x23, [sp, 16] + ldr x22, [sp, 24] + ldr x21, [sp, 32] + add sp, sp, 40 + ret + +.globl doMouse +// NOTE doMouse +doMouse: + // Args + // x21 x + // x22 y + sub sp, sp, 24 + str x24, [sp, 16] + str x23, [sp, 8] + str lr, [sp] + + mov x23, 3 + mov x24, 5 + bl doTriangleUp + mov x23, 9 + bl doRectangle + + ldr lr, [sp] + ldr x23, [sp, 8] + ldr x24, [sp, 16] + add sp, sp, 24 + ret + +.globl doCompuVentana +// NOTE doCompuVentana +doCompuVentana: + sub sp, sp, 56 + stur x15, [sp, 48] + stur x14, [sp, 40] + stur x13, [sp, 32] + stur x21, [sp, 24] + stur x22, [sp, 16] + stur x18, [sp, 8] + stur lr, [sp] + + // Fondo + mov x13, 110 + mov x14, 50 + mov x15, 50 + bl setColour + mov x21, 0 + mov x22, 0 + mov x23, 640 + mov x24, 480 + bl doRectangle + + // Marco + mov x13, 0 + mov x14, 0 + mov x15, 0 + bl setColour + mov x21, 100 + mov x22, 50 + mov x23, 450 + mov x24, 300 + bl doRectangle + + // Pie de monitor + add x21, x21, 150 + add x22, x22, 300 + mov x23, 150 + mov x24, 50 + bl doRectangle + + // Base del monitor + sub x21, x21, 100 + add x22, x22, 50 + mov x23, 350 + mov x24, 10 + bl doRectangle + + // Pantalla "real" + movz w18, 0xe6, lsl 16 + movk w18, 0xf9af, lsl 0 + mov x21, 110 + mov x22, 60 + mov x23, 430 + mov x24, 280 + bl doRectangle + + // Botón de play + movz w18, 0x0d, lsl 16 + movk w18, 0x0630, lsl 0 + mov x21, 270 + mov x22, 150 + mov x23, 100 + mov x24, 100 + bl doRectangle + + // Triángulo del medio del boton + movz w18, 0x8b, lsl 16 + movk w18, 0xbeb2, lsl 0 + mov x21, 310 + mov x22, 165 + mov x23, 30 + mov x24, 80 + bl triangDer + + // Botón de salida + movz w18, 0x38, lsl 16 + movk w18, 0x4e77, lsl 0 + mov x21, 520 + mov x22, 60 + mov x23, 20 + mov x24, 20 + bl doRectangle + + // Botón de salida + movz w18, 0x18, lsl 16 + movk w18, 0x314f, lsl 0 + mov x21, 500 + mov x22, 60 + mov x23, 20 + mov x24, 20 + bl doRectangle + + mov x21, 0 + mov x22, 410 + mov x23, 640 + mov x24, 70 + bl doRectangle + + ldur lr, [sp] + ldur w18, [sp, 8] + ldur x22, [sp, 16] + ldur x21, [sp, 24] + ldur x13, [sp, 32] + ldur x14, [sp, 40] + ldur x15, [sp, 48] + add sp, sp, 56 + ret + +.globl triangDer +// NOTE Triángulo apuntando a la derecha +triangDer: + // Args + // x21 x + // x22 y + // x23 w (cantidad de figuras) + sub sp, sp, 32 + stur x21, [sp, 24] + stur x22, [sp, 16] + stur x23, [sp, 8] + stur lr, [sp] + mov x16, x21 + mov x12, x22 + mov x9, 0 + +triangDerLoop: + bl drawPixel + add x16, x16, 1 + add x12, x12, 1 + cmp x9, x23 + b.eq triangDerBack + add x9, x9, 1 + b triangDerLoop + +triangDerBack: + bl drawPixel + sub x16, x16, 1 + add x12, x12, 1 + cmp x9, 0 + b.eq cmpTriang + sub x9, x9, 1 + b triangDerBack + +cmpTriang: + cmp x23, 0 + b.eq preEndTriangDer + sub x23, x23, 1 + add x22, x22, 1 + mov x12, x22 + b triangDerLoop + +preEndTriangDer: + ldur x23, [sp, 8] + add x23, x23, 2 + bl vertLine + +endTriangDer: + ldur lr, [sp] + ldur x23, [sp, 8] + ldur x22, [sp, 16] + ldur x21, [sp, 24] + add sp, sp, 32 + ret + +.globl vertLine +// NOTE Vertilcal line with a height +vertLine: + // Args + // x21 x + // x22 y + // x18 colour + // x23 height + sub sp, sp, 40 + stur x9, [sp, 32] + stur x21, [sp, 24] + stur x22, [sp, 16] + stur x23, [sp, 8] + stur lr, [sp] + mov x16, x21 + mov x12, x22 + mov x9, 0 + +doVertL: + bl drawPixel + add x12, x12, 1 + cmp x9, x23 + b.eq endVertLine + add x9, x9, 1 + b doVertL + +endVertLine: + ldur lr, [sp] + ldur x23, [sp, 8] + ldur x22, [sp, 16] + ldur x21, [sp, 24] + ldur x9, [sp, 32] + add sp, sp, 40 + ret + + +.globl drawLine +// NOTE drawLine Line +drawLine: + // Args + // x21 xc0 coordenada x del primer punto + // x22 yc0 coordenada y del primer punto + // x23 xc1 coordenada x del segundo punto + // x24 yc1 coordenada y del segundo punto + // Used + // x4 dx + // x5 sx + // x6 dy + // x7 sy + // x19 err + + sub sp, sp, #80 // Reservamos 6 registros de memoria + stur x24, [sp, #72] + stur x23, [sp, #64] + stur x22, [sp, #56] + stur x21, [sp, #48] + stur x30, [sp, #40] // Guardamos el return pointer en memoria + stur x19, [sp, #32] + stur x4, [sp, #24] + stur x5, [sp, #16] + stur x6, [sp, #8] + stur x7, [sp, #0] + + // (x0, y0) to (x1, y1) + // (xc0, yc0) to (xc1, yc1) + + // y = f(x) = mx+b + // y = mx +b + // y = ((tri (y)) / (tri (x))) x + b + + // dx = abs(xc1 - xc0) + cmp x21, x23 // comparamos xc0 con el xc1 + b.gt lineGreaterThan1 // xc0 > xc1 + // if here -> xc1 > xc0 + sub x4, x23, x21 // dx = xc1 - xc0 lineDx + mov x5, #1 // xc0 < xc1 -> sx = xc0 < xc1 ? 1 : -1 + b endlineGreaterThan1 + +lineGreaterThan1: // xc0 > xc1 + sub x4, x21, x23 // dx = xc0 - xc1 + mov x5, #1 + sub x5, xzr, x5 // sx = xc0 < xc1 ? 1 : -1 + // endlineGreaterThan1... + +endlineGreaterThan1: + // dy = -abs(yc1 - yc0) + cmp x22, x24 // comparamos yc0 con el yc1 + b.gt lineGreaterThan2 // yc0 > yc1 + sub x6, x22, x24 // dy = yc0 - yc1 + mov x7, #1 // yc0 < yc1 -> sy = yc0 < yc1 ? 1 : -1 + b endlineGreaterThan2 + +lineGreaterThan2: // yc0 > yc1 + sub x6, x24, x22 // dy = yc1 - yc0 + mov x7, #1 + sub x7, xzr, x7 // sy = yc0 < yc1 ? 1 : -1 + // endlineGreaterThan2... + +endlineGreaterThan2: + add x19, x4, x6 // err = dx+dy (error value e_xy) + b loopLine // init loop + +loopLine: + mov x16, x21 // xdraw = xc0 + mov x12, x22 // ydraw = yc0 + bl drawPixel // plot(xc0, yc0) + + cmp x21, x23 // Comparamos xc0 con xc1 + b.ne checkLine // xc0 != xc1 + b endDrawLine // break + +checkLine: + cmp x22, x24 // Comparamos yc0 con yc1 + b.ne lineNoBreak // yc0 != yc1 + b endDrawLine // break + +lineNoBreak: + //lsl x8, x19, #1 // x8 = e2 = 2*err + add x8, x19, x19 // x8 = e2 = 2*err + + cmp x8, x6 + b.lt skipIf1 // e2 < dy + // If we are here -> e2 >= dy + add x19, x19, x6 // err += dy + add x21, x21, x5 // xc0 += sx + +skipIf1: + cmp x8, x4 + b.gt loopLine // e2 > dx + // If we are here -> e2 <= dx +break2: + add x19, x19, x4 // err += dx + add x22, x22, x7 // yc0 += sy + b loopLine + +endDrawLine: + ldur x7, [sp, #0] + ldur x6, [sp, #8] + ldur x5, [sp, #16] + ldur x4, [sp, #24] + ldur x19, [sp, #32] + ldur x30, [sp, #40] + ldur x21, [sp, #48] + ldur x22, [sp, #56] + ldur x23, [sp, #64] + ldur x24, [sp, #72] + add sp, sp, #80 // Liberamos espacio en memoria + ret + +.globl doSquare +// NOTE Square +doSquare: + // Args + // x21 xo lugar dónde empiezo a dibujar la figura + // x22 yo lugar dónde empiezo a dibujar la figura + // x23 w cantidad de píxeles + // x18 colour + sub sp, sp, #16 // Reservamos espacio en memoria + stur x24, [sp, #8] // Guardamos el registro que usamos despues + stur x30, [sp, #0] // Guardamos el return pointer en memoria + + mov x24, x23 // h := w + bl doRectangle // w x w + + ldur x24, [sp, #8] // Restauramos el x24 usado antes + ldur x30, [sp, #0] // Guardamos el return pointer en memoria + add sp, sp, #16 // Liberamos espacio en memoria + ret + +.globl doRectangle +// NOTE Rectangle alto(h) x largo(w) +doRectangle: // alto x largo// + // Args + // x21 x2 lugar dónde empiezo a dibujar la figura + // x22 y2 lugar dónde empiezo a dibujar la figura + // x23 w largo en pixeles + // x24 h alto en pixeles + // w18 colour + // Used + // doHorizontalLine + // drawPixel: setPixel x16 x, x12 y + // x9 posición inicial de x + // x10 posición inicial de y + + sub sp, sp, #56 // Reservamos memoria + str x3, [sp, 48] + stur x21, [sp, 40] + stur x22, [sp, 32] + stur x23, [sp, 24] + stur x24, [sp, 16] + stur lr, [sp, 8] // Guardamos el return pointer en memoria (8 direcciones de memoria = 1 registro de 64bits) + stur x5, [sp] // Guardamos el x5 en memoria (8 direcciones de memoria = 1 registro de 64bits) + + mov x5, x22 // x5 fila inicial + +rectangleLoop: // Se encarga de cambiar la fila + sub x8, x22, x5 // Cantidad de filas que dibujamos hasta ahora + cmp x8, x24 // Comparamos la cantidad de líneas dibujadas con h + b.eq endRectangule // Si son iguales ya pintamos todo + bl doHorizontalLine // Sino, pintamos la línea + add x22, x22, #1 // Nos movemos al pixel de la fila de abajo, y++ + b rectangleLoop + +endRectangule: + ldur x5, [sp] + ldur lr, [sp, 8] // Cargamos el return pointer en memoria (8 direcciones de memoria = 1 regildro de 64bits) + ldur x24, [sp, 16] + ldur x23, [sp, 24] + ldur x22, [sp, 32] + ldur x21, [sp, 40] + ldr x3, [sp, 48] + add sp, sp, 56 // Reservamos 2 registros de memoria + ret + +.globl doCircle +// NOTE Circle +doCircle: // Mid-Point Circle Drawing Algorithm // + // (0, 0) centro + // point p(x, y) + // F(p) = x^2 + y^2 - r^2 + // Args + // x21 xc x centro + // x22 yc y centro + // x23 r radio (asumimos que el radio es mayor que 0) + // x24 no fill in: (x24 == 0 -> Fill, x24 != 0 -> No Fill) + // x18 colour + // Used + // x25 x + // x26 y + // x27 P + sub sp, sp, #40 + stur x23, [sp, 32] + stur x22, [sp, 24] + stur x21, [sp, 16] + stur x27, [sp, 8] + stur x30, [sp, #0] // Guardamos el return pointer en memoria + mov x25, x23 // x = r + mov x26, xzr // y = 0 (xzr = 0) + sub x8, xzr, x23 // x8 = -r + add x27, x8, #1 // P = 1 - r + + // Dibujamos las esquinas + mov x16, x21 // x16 xd = xc + add x12, x22, x23 // x12 yd = yc + r + bl drawPixel + mov x16, x21 // x16 xd = xc + sub x12, x22, x23 // x12 yd = yc - r + bl drawPixel + add x16, x21, x23 // x16 xd = xc + r + mov x12, x22 // x12 yd = yc + bl drawPixel + sub x16, x21, x23 // x16 xd = xc - r + mov x12, x22 // x12 yd = yc + bl drawPixel + cbnz x24, doCircleLoop // doCircleLoop... + b doPixelsForCircleFill + +doPixelsForCircleFill: + sub sp, sp, #16 + stur x6, [sp, #8] + stur x5, [sp, #0] + + mov x5, x22 // x5 = yc + mov x6, x23 // x6 = r + + sub x22, x5, x6 // yd = yc - r + lsl x23, x6, #1 // h = 2 * r + bl vertLine // x21 x - x22 y - x23 height + + mov x22, x5 + mov x23, x6 + ldur x6, [sp, #8] + ldur x5, [sp, #0] + add sp, sp, #16 + // doCircleLoop... + +doCircleLoop: // While x > y + add x26, x26, #1 + // Mid-point is inside or on the perimeter + cmp x27, xzr // P <= 0 + b.le cirif1 // Si P <= 0 entra en el if + b cirelse1 // Si no, entra en el else + +cirif1: // if (P <= 0) + // F(p) < 0 -> the point is inside the circle + // F(p) = 0 -> the point is on the perimeter + lsl x8, x26, #1 // x8 = 2*y + add x8, x8, #1 // x8 = 2*y + 1 + add x27, x27, x8 // P = P + 2*y + 1 + b cirif2 + +cirelse1: // Mid-point is outside the perimeter + // F(p) > 0 -> the point is outside the circle + sub x25, x25, #1 // x-- + lsl x8, x25, #1 // x8 = 2*x + lsl x9, x26, #1 // x9 = 2*y + add x8, x8, #1 // x8 = 2*x + 1 + sub x9, x9, x8 // x9 = 2*y - (2*x + 1) + add x27, x27, x9 // P = P + 2*y - 2*x + 1 + // cirif2... + +cirif2: // if (x < y) + cmp x25, x26 + b.lt circleEnd + cbnz x24, circlNoFill + bl circleFillAux + b doCircleLoop + +circlNoFill: + add x16, x25, x21 // x16 xd = x + x_centre + add x12, x26, x22 // x12 yd = y + y_centre + bl drawPixel + + sub x16, x21, x25 // x16 draw x = -x + x_centre + add x12, x26, x22 // x12 draw y = y + y_centre + bl drawPixel + + add x16, x25, x21 // x16 xd = x + x_centre + sub x12, x22, x26 // x12 draw y = -y + y_centre + bl drawPixel + + sub x16, x21, x25 // x16 draw x = -x + x_centre + sub x12, x22, x26 // x12 draw y = -y + y_centre + bl drawPixel + + cmp x25, x26 + b.eq doCircleLoop + + // If the generated point is on the line x = y then + // the perimeter points have already been printed + // if (x != y) : + + add x16, x26, x21 // x16 draw x = y + x_centre + add x12, x25, x22 // x12 draw y = x + y_centre + bl drawPixel + + sub x16, x21, x26 // x16 draw x = -y + x_centre + add x12, x25, x22 // x12 draw y = x + y_centre + bl drawPixel + + add x16, x26, x21 // x16 draw x = y + x_centre + sub x12, x22, x25 // x12 draw y = -x + y_centre + bl drawPixel + + sub x16, x21, x26 // x16 draw x = -y + x_centre + sub x12, x22, x25 // x12 draw y = -x + y_centre + bl drawPixel + + cmp x25, x26 + b.gt doCircleLoop + +circleEnd: + ldur x30, [sp] // Guardamos el return pointer en memoria ret + ldur x27, [sp, 8] + ldur x21, [sp, 16] + ldur x22, [sp, 24] + ldur x23, [sp, 32] + add sp, sp, 40 + ret + +circleFillAux: + sub sp, sp, #32 + stur x4, [sp, #24] + stur x5, [sp, #16] + stur x23, [sp, #8] + stur x30, [sp, #0] // Guardamos el return pointer en memoria ret + + mov x4, x21 // x4 = xc + mov x5, x22 // x5 = yc + add x21, x4, x25 // x = xc + x + sub x22, x5, x26 // y = yc - y + mov x23, x26 + add x23, x23, x26 // height = 2*y + 1 + bl vertLine + + sub x21, x4, x25 // x = xc - x + bl vertLine + + cmp x25, x26 + b.eq endCircleFillAux // Siguientes cuadrantes... + + add x21, x4, x26 // x = xc + y + sub x22, x5, x25 // y = yc - x + add x23, x25, x25 // height = 2 * x + bl vertLine + + sub x21, x4, x26 // x = xc - y + sub x22, x5, x25 // y = yc - x + mov x23, x25 + add x23, x23, x25 // height = 2 * x + bl vertLine + +endCircleFillAux: + mov x21, x4 + mov x22, x5 + ldur x30, [sp, #0] // Guardamos el return pointer en memoria ret + ldur x23, [sp, #8] + ldur x5, [sp, #16] + ldur x4, [sp, #24] + add sp, sp, #32 + ret + +.globl doTriangleUp +// NOTE Triángulo hacia arriba +doTriangleUp: + // @Diego + // Args + // x21 x lugar dónde empiezo a dibujar la figura + // x22 y lugar dónde empiezo a dibujar la figura + // x23 w cantidad de píxeles + // x18 colour + + sub sp, sp, #32 + str x23, [sp, 24] + str x22, [sp, 16] + str x21, [sp, 8] + str lr, [sp] // Guardo el link register para no pisarlo en la subrutina setPixel + mov x16, x21 // Instancio x16 para dibujar + mov x12, x22 // Instancio x12 para setPixel + mov x19, x23 // La cantidad de pixeles sera la cantidad de veces que entro al ciclo + mov x9, #0 // Instancio un contador que me va a servir para contar cantidad de pixeles + b rectAr + +rectAr: // Dibuja la diagonal hacia arriba + add x16, x16, #1 // Me muevo al siguiente + sub x12, x12, #1 // Me muevo arriba + bl drawPixel + cmp x9, x19 // Comparo mi contador con mi cantidad de pixeles + b.eq rectBaj // Si llegue a la cantidad bajo + add x9, x9, #1 // Si no le sumo 1 + b rectAr // Empiezo de nuevo + +rectBaj: // Dibuja la diagonal hacia abajo + add x16, x16, #1 // Me muevo al siguiente + add x12, x12, #1 // Bajo 1 unidad + bl drawPixel + cmp x9, #0 // Comparo el contador a w con 0 + b.eq preRectAr // Si llegue a la "base" arranco de nuevo desde 1 posicion menos + sub x9, x9, #1 // Si no, le resto 1 al contador + b rectBaj // Bajo de nuevo + +preRectAr: // Se fija si itero la cantidad de veces necesarias + add x21, x21, #1 // Itero una vez menos + mov x16, x21 // Empiezo de nuevo + mov x12, x22 // Instancio x12 para setPixel + cmp x19, xzr // Si itere w cantidad de veces --> + b.eq endTriang // Termino + sub x19, x19, #1 // Si no, resto 1 iteracion + b rectAr // sigo + +endTriang: + ldr lr, [sp] + ldr x21, [sp, 8] + ldr x22, [sp, 16] + ldr x23, [sp, 24] + add sp, sp, #32 + ret + +.globl doTriangleDown +// NOTE Triángulo hacia abajo +doTriangleDown: + // @Diego + // Args + // x21 x lugar dónde empiezo a dibujar la figura + // x22 y lugar dónde empiezo a dibujar la figura + // x23 w cantidad de píxeles + // w18 colour + + sub sp, sp, #32 + stur x23, [sp, 24] + stur x22, [sp, 16] + stur x21, [sp, 8] + stur lr, [sp] // Guardo el link register para no pisarlo en la subrutina setPixel + mov x16, x21 // Instancio x16 para dibujar + mov x12, x22 // Instancio x12 para setPixel + bl setPixel // Calculo la posicion inicial + mov x19, x23 // La cantidad de pixeles sera la cantidad de veces que entro al ciclo + mov x9, #0 // Instancio un contador que me va a servir para contar cantidad de pixeles + b rectArDown + +rectArDown: // Dibuja la diagonal hacia arriba + add x16, x16, #1 // Me muevo al siguiente + add x12, x12, #1 // Me muevo arriba + bl drawPixel + cmp x9, x19 // Comparo mi contador con mi cantidad de pixeles + b.eq rectBajDown // Si llegue a la cantidad bajo + add x9, x9, #1 // Si no le sumo 1 + b rectArDown // Empiezo de nuevo + +rectBajDown: // Dibuja la diagonal hacia abajo + add x16, x16, #1 // Me muevo al siguiente + sub x12, x12, #1 // Bajo 1 unidad + bl setPixel // Calculo el pixel + bl drawPixel // Lo pinto + cmp x9, #0 // Comparo el contador a w con 0 + b.eq preRectArDown // Si llegue a la "base" arranco de nuevo desde 1 posicion menos + sub x9, x9, #1 // Si no, le resto 1 al contador + b rectBajDown // Bajo de nuevo + +preRectArDown: // Se fija si itero la cantidad de veces necesarias + add x21, x21, #1 // Itero una vez menos + mov x16, x21 // Empiezo de nuevo + mov x12, x22 // Instancio x12 para setPixel + cmp x19, xzr // Si itere w cantidad de veces --> + b.eq endTriangDown // Termino + sub x19, x19, #1 // Si no, resto 1 iteracion + b rectArDown // sigo + +endTriangDown: + ldr lr, [sp] + ldr x21, [sp, 8] + ldr x22, [sp, 16] + ldr x23, [sp, 24] + add sp, sp, #32 + ret + +.globl doPiramide +// NOTE Pirámide +doPiramide: + // @Diego + // Args + // x21 x lugar dónde empiezo a dibujar la figura + // x22 y lugar dónde empiezo a dibujar la figura + // x23 w cantidad de píxeles + // w18 colour + + sub sp, sp, #32 + str x23, [sp, 24] + str x22, [sp, 16] + str x21, [sp, 8] + stur lr, [sp] // Guardo el link register para no pisarlo en la subrutina setPixel + mov x16, x21 // Instancio x16 para dibujar + mov x12, x22 // Instancio x12 para setPixel + mov x19, x23 // La cantidad de pixeles sera la cantidad de veces que entro al ciclo + mov x9, #0 // Instancio un contador que me va a servir para contar cantidad de pixeles + +pirAr: // Dibuja la diagonal hacia arriba + sub x16, x16, #1 // Me muevo atras + sub x12, x12, #1 // Me muevo arriba + bl drawPixel + cmp x9, x19 // Comparo mi contador con mi cantidad de pixeles + b.eq pirBaj // Si llegue a la cantidad bajo + add x9, x9, #1 // Si no le sumo 1 al contador + b pirAr // Empiezo de nuevo + +pirBaj: // Dibuja la diagonal hacia abajo + sub x16, x16, #1 // Me muevo atras + add x12, x12, #1 // Bajo 1 unidad + bl drawPixel + cmp x9, #0 // Comparo el contador a w con 0 + b.eq prepirAr // Si llegue a la "base" arranco de nuevo desde 1 posicion menos + sub x9, x9, #1 // Si no, le resto 1 al contador + b pirBaj // Bajo de nuevo + +prepirAr: // Se fija si itero la cantidad de veces necesarias + add x21, x21, #1 // Itero una vez menos + mov x16, x21 // Empiezo de nuevo + mov x12, x22 // Instancio x12 para setPixel + cmp x19, xzr // Si itere w cantidad de veces --> + b.eq endPir // Termino + sub x19, x19, #1 // Si no, resto 1 iteracion + b pirAr // sigo + +endPir: + ldur lr, [sp] + ldr x21, [sp, 8] + ldr x22, [sp, 16] + ldr x23, [sp, 24] + add sp, sp, #32 + ret + +.globl verticalLine +// NOTE Line +verticalLine: + // Args + // x21 x + // x18 Colour + sub sp, sp, #16 // Guardamos 2 lugares del stack + str x30, [sp, #8] // registro 30 para el RET en el stack + str x1, [sp, #0] // Guardamos en el stack pointer el registro x1 anterior + mov x1, SCREEN_HEIGH + mov x16, x21 // x = argument + mov x12, xzr // y = 0 + // verLineLoop... + +verLineLoop: + cmp x1, x12 // Comparamos SCREEN_HEIGH con y + b.eq verLineEnd // Si x1 es igual a x12 termina + bl drawPixel + add x12, x12, #1 // Pasamos a la siguiente "fila" (bajamos 1 en y) + b verLineLoop // Continuamos con el loop + +verLineEnd: + ldr x1, [sp, #0] // Carga lo que guardó en el stack + ldr x30, [sp, #8] // Cargamos variables anteriores + add sp, sp, #16 // Libera el stack + ret + +.globl doHorizontalLine +// NOTE LineH +doHorizontalLine: // Crea líneas horizontales en la coordenada (xo, po) con w cantidad de pixeles que se extienden hacia la derecha // + // Args + // x21 xo valor de origen x + // x22 yo valor de origen y + // x23 w cantidad de pixeles + // Used + // drawPixel: setPixel x16 x, x12 y + // x18 Colour + sub sp, sp, #48 + str x12, [sp, #40] + str x16, [sp, #32] + str x23, [sp, #24] + str x22, [sp, #16] + str x21, [sp, #8] + str x30, [sp, #0] // Guardamos el return pointer en memoria + mov x16, x21 // x = xo + // horLineLoop... + +horLineLoop: + sub x8, x16, x21 // Cuantos pixeles hemos dibujado hasta ahora + cmp x23, x8 // Comparamos x23=w con x8 + b.eq endHorizontalLine // Si son iguales terminamos porque pintamos todo ya + mov x12, x22 + bl drawPixel // Sino, dibujamos + add x16, x16, #1 // Nos movemos de pixel, x++ + b horLineLoop + +endHorizontalLine: + ldr x30, [sp, #0] // Guardamos el return pointer en memoria + ldr x21, [sp, #8] + ldr x22, [sp, #16] + ldr x23, [sp, #24] + ldr x16, [sp, #32] + ldr x12, [sp, #40] + add sp, sp, #48 // Liberamos espacio en memoria + ret diff --git a/ejercicio2/font.s b/ejercicio2/font.s new file mode 100644 index 0000000..8833e78 --- /dev/null +++ b/ejercicio2/font.s @@ -0,0 +1,991 @@ +// Font https://www.dafont.com/es/minitel.font?text=console + +.equ SCREEN_WIDTH, 640 +.equ SCREEN_HEIGH, 480 +.equ BITS_PER_PIXEL, 32 +.equ COLOR_1, 0xFF // Color blanco R // 0xC7 +.equ COLOR_2, 0xFFFF // Color blanco GB // 0x1607 +.equ COLOR_NEGRO, 0x00 + +.globl doAm +// NOTE a minus +doAm: // 16x8 + sub sp, sp, 32 + str x21, [sp, 24] + str x22, [sp, 16] + str x23, [sp, 8] + str lr, [sp] + + sub x22, x22, 19 + mov x23, 19 + bl vertLine + add x21, x21, 1 + sub x22, x22, 1 + mov x23, 10 + bl doHorizontalLine + add x21, x21, 11 + add x22, x22, 1 + mov x23, 19 + bl vertLine + add x22, x22, 10 + sub x21, x21, 10 + mov x23, 10 + bl doHorizontalLine + + ldr lr, [sp] + ldr x23, [sp, 8] + ldr x22, [sp, 16] + ldr x21, [sp, 24] + add sp, sp, 32 + ret + +.globl doA +doA: // 16x8 + sub sp, sp, 32 + str x21, [sp, 24] + str x22, [sp, 16] + str x23, [sp, 8] + str lr, [sp] + + add x21, x21, 1 + mov x23, 5 + bl doHorizontalLine + + sub x21, x21, 1 + sub x22, x22, 7 + mov x23, 6 + bl vertLine + + add x21, x21, 1 + sub x22, x22, 1 + mov x23, 4 + bl doHorizontalLine + + add x21, x21, 4 + add x22, x22, 1 + mov x23, 1 + bl doHorizontalLine + + add x21, x21, 1 + sub x22, x22, 1 + mov x23, 8 + bl vertLine + + add x22, x22, 7 + sub x21, x21, 1 + mov x23, 1 + bl vertLine + + ldr lr, [sp] + ldr x23, [sp, 8] + ldr x22, [sp, 16] + ldr x21, [sp, 24] + add sp, sp, 32 + ret + +.globl doEm +// NOTE E +doEm: + // Args + // x21 x lugar dónde empiezo a dibujar la figura + // x22 y lugar dónde empiezo a dibujar la figura + // w18 color + // Usa: + // x23 para la funcion doHorizontalLine + sub sp, sp, 32 + stur lr, [sp] + stur x21, [sp, #8] + stur x22, [sp, #16] + stur x23, [sp, #24] + mov x9, #0 + +doETop: + mov x23, 15 + bl doHorizontalLine + mov x16, x21 + mov x12, x22 + +doEDown: + bl drawPixel + add x12, x12, #1 + add x22, x22, #1 + cmp x9, #10 + b.eq drawEMid + cmp x9, #20 + b.eq drawEBot + add x9, x9, #1 + b doEDown + +drawEMid: + mov x23, 10 + bl doHorizontalLine + add x9, x9, #1 + b doEDown + + +drawEBot: + mov x23, 15 + bl doHorizontalLine + b endE + +endE: + ldur x23, [sp, #24] + ldur x22, [sp, #16] + ldur x21, [sp, #8] + ldur lr, [sp] + ret + +.globl doE +// NOTE e minus +doE: // 16x8 + // Args + // x21 x lugar dónde empiezo a dibujar la figura + // x22 y lugar dónde empiezo a dibujar la figura + // w18 color + // Usa: + // x23 para la función doHorizontalLine + sub sp, sp, #32 + stur lr, [sp] + stur x21, [sp, #8] + stur x22, [sp, #16] + stur x23, [sp, #24] + + add x21, x21, 1 + mov x23, 6 + bl doHorizontalLine // Linea h inferior + sub x21, x21, 1 + sub x22, x22, 7 + mov x23, 6 + bl vertLine // Linea vert izquierda + add x21, x21, 1 + sub x22, x22, 1 + mov x23, 5 + bl doHorizontalLine // Linea sup + add x21, x21, 5 + add x22, x22, 1 + mov x23, 2 + bl vertLine // Linea v derecha + sub x21, x21, 5 + add x22, x22, 2 + mov x23, 5 + bl doHorizontalLine // Linea intermedia + + ldur x23, [sp, #24] + ldur x22, [sp, #16] + ldur x21, [sp, #8] + ldur lr, [sp] + add sp, sp, #32 + ret + +.globl doIm +// NOTE I +doIm: + // Args + // x21 x lugar dónde empiezo a dibujar la figura + // x22 y lugar dónde empiezo a dibujar la figura + // w18 color + sub sp, sp, 40 + stur lr, [sp] + stur x21, [sp, #8] + stur x22, [sp, #16] + stur x23, [sp, #24] + stur x24, [sp, #32] + mov x16, x21 + mov x12, x22 + mov x10, x23 + mov x9, 0 + +drawITop: + mov x23, 20 + bl doHorizontalLine + add x22, x22, 1 + bl doHorizontalLine + mov x16, x21 + mov x12, x22 + add x16, x16, 10 + +doIDown: + bl drawPixel + add x12, x12, #1 + cmp x9, #20 + b.eq drawIBot + add x9, x9, #1 + b doIDown + +drawIBot: + mov x23, 20 + ldur x21, [sp, #8] + ldur x22, [sp, #16] + add x22, x22, 20 + bl doHorizontalLine + add x22, x22, 1 + bl doHorizontalLine + +endI: + ldur x24, [sp, #32] + ldur x23, [sp, #24] + ldur x22, [sp, #16] + ldur x21, [sp, #8] + ldur lr, [sp] + add sp, sp, 40 + ret + +.globl doI +// NOTE i +doI: + // Args + // x21 x lugar dónde empiezo a dibujar la figura + // x22 y lugar dónde empiezo a dibujar la figura + // w18 color + sub sp, sp, 40 + stur lr, [sp] + stur x21, [sp, #8] + stur x22, [sp, #16] + stur x23, [sp, #24] + stur x24, [sp, #32] + + mov x23, 10 + bl doHorizontalLine + add x21, x21, 5 + sub x22, x22, 10 + mov x23, 10 + bl vertLine + sub x22, x22, 3 + mov x23, 1 + bl doHorizontalLine + add x22, x22, 3 + sub x21, x21, 3 + mov x23, 3 + bl doHorizontalLine + + ldur x24, [sp, #32] + ldur x23, [sp, #24] + ldur x22, [sp, #16] + ldur x21, [sp, #8] + ldur lr, [sp] + add sp, sp, 40 + ret + +.globl doO +// NOTE o +doO: + sub sp, sp, #32 + str x23, [sp, #24] + stur x22, [sp, #16] + stur x21, [sp, #8] + stur lr, [sp] + + add x21, x21, 1 + + mov x23, 7 // Cant de pixeles + bl doHorizontalLine // Linea h inferior + add x21, x21, 7 + sub x22, x22, 8 + mov x23, 7 + bl vertLine // Linea v derecha + sub x21, x21, 7 + sub x22, x22, 1 + bl doHorizontalLine // Linea h superior + sub x21, x21, 1 + add x22, x22, 1 + + bl vertLine // Linea v izquierda + + ldr lr, [sp] + ldr x21, [sp, #8] + ldr x22, [sp, #16] + ldr x23, [sp, #24] + add sp, sp, #32 + ret + +.globl doDm +// NOTE D +doDm: + // Args + // x21 x inicial + // x22 y inicial + // w18 color + // Uses + // x23 par doHorizontalLine + sub sp, sp, 24 + stur lr, [sp] + stur x21, [sp, #8] + stur x22, [sp, #16] + mov x16, x21 + mov x12, x22 + mov x9, 0 + + sub x22, x22, 20 + mov x23, 20 + bl vertLine + +preDDer: + mov x23, 5 + bl doHorizontalLine + add x21, x21, 6 + add x22, x22, 1 + mov x16, x21 + mov x12, x22 + bl drawPixel + add x16, x16, 1 + add x12, x12, 1 + bl drawPixel + add x16, x16, 1 + add x12, x12, 1 + bl drawPixel + add x16, x16, 1 + add x12, x12, 1 + bl drawPixel + add x16, x16, 1 + add x12, x12, 1 + bl drawPixel + mov x9, 0 + +dDer: + add x12, x12, 1 + bl drawPixel + cmp x9, 9 + b.eq dDoIzq + add x9, x9, 1 + b dDer + +dDoIzq: + sub x16, x16, 1 + add x12, x12, 1 + bl drawPixel + sub x16, x16, 1 + add x12, x12, 1 + bl drawPixel + sub x16, x16, 1 + add x12, x12, 1 + bl drawPixel + sub x16, x16, 1 + add x12, x12, 1 + bl drawPixel + sub x16, x16, 1 + add x12, x12, 1 + bl drawPixel + sub x16, x16, 1 + bl drawPixel + sub x16, x16, 1 + bl drawPixel + sub x16, x16, 1 + bl drawPixel + sub x16, x16, 1 + bl drawPixel + b endD + +endD: + ldur x22, [sp, #16] + ldur x21, [sp, #8] + ldur lr, [sp] + add sp, sp, #24 + ret + +.globl doL +// NOTE l minus +doL: // 16x8 + // Args + // x21 x inicial + // x22 y inicial + // x23 w + // w18 color + sub sp, sp, #32 + str x21, [sp, #24] + str x22, [sp, #16] + str x23, [sp, #8] + str lr, [sp] + + add x21, x21, 2 + mov x23, 8 + bl doHorizontalLine + add x21, x21, 4 + sub x22, x22, 17 + mov x23, 16 + bl vertLine + sub x21, x21, 3 + mov x23, 4 + bl doHorizontalLine + + ldr lr, [sp] + ldr x21, [sp, #24] + ldr x22, [sp, #16] + ldr x23, [sp, #8] + add sp, sp, #32 + ret + +.globl doS +// NOTE s minus +doS: // 16x8 + // Args + // x21 x inicial + // x22 y inicial + // x23 w + // w18 color + sub sp, sp, #24 + str x21, [sp, #16] + str x22, [sp, #8] + str lr, [sp] + + mov x23, 8 + bl doHorizontalLine + add x21, x21, 8 + sub x22, x22, 3 + mov x23, 3 + bl vertLine + sub x21, x21, 7 + sub x22, x22, 1 + mov x23, 7 + bl doHorizontalLine + sub x21, x21, 1 + sub x22, x22, 3 + mov x23, 3 + bl vertLine + add x21, x21, 1 + sub x22, x22, 1 + mov x23, 7 + bl doHorizontalLine + + ldr lr, [sp] + ldr x22, [sp, #8] + ldr x21, [sp, #16] + add sp, sp, #24 + ret + +.globl doP +// NOTE p +doP: // 16x8 + // Args + // x21 x inicial + // x22 y inicial + // x23 w + // w18 color + sub sp, sp, 32 + str x23, [sp, 24] + str x21, [sp, 16] + str x22, [sp, 8] + str lr, [sp] + + mov x23, 9 + bl doHorizontalLine + add x21, x21, 8 + sub x22, x22, 4 + mov x23, 3 + bl vertLine + sub x21, x21, 8 + sub x22, x22, 1 + mov x23, 8 + bl doHorizontalLine + mov x23, 12 + bl vertLine + + ldr lr, [sp] + ldr x23, [sp, 24] + ldr x21, [sp, 16] + ldr x22, [sp, 8] + add sp, sp, 32 + ret + +.globl doM +// NOTE m +doM: + // Args + // x21 x inicial + // x22 y inicial + // w18 color + // Uses + // x23 par doHorizontalLine + sub sp, sp, 24 + stur lr, [sp] + stur x21, [sp, #8] + stur x22, [sp, #16] + + sub x22, x22, 8 + mov x23, 8 + bl vertLine + + mov x23, 5 + bl doHorizontalLine + add x21, x21, 6 + add x22, x22, 1 + mov x23, 7 + bl vertLine + add x21, x21, 1 + sub x22, x22, 1 + mov x23, 5 + bl doHorizontalLine + add x21, x21, 6 + add x22, x22, 1 + mov x23, 7 + bl vertLine + + +/* +doPalo: + add x12, x12, 1 + bl drawPixel + cmp x9, 20 + b.eq doMr + add x9, x9, 1 + b doPalo + +doMr: + mov x12, x22 + mov x9, 0 +doMrLoop: + add x16, x16, 1 + add x12, x12, 1 + bl drawPixel + cmp x9, 10 + b.eq doMrUp + add x9, x9, 1 + b doMrLoop + +doMrUp: + add x16, x16, 1 + sub x12, x12, 1 + bl drawPixel + cmp x9, 0 + b.eq doPaloD + sub x9, x9, 1 + b doMrUp + +doPaloD: + add x12, x12, 1 + bl drawPixel + cmp x9, 20 + b.eq endM + add x9, x9, 1 + b doPaloD +*/ + +endM: + ldur x22, [sp, #16] + ldur x21, [sp, #8] + ldur lr, [sp] + add sp, sp, 24 + ret + +.globl doN +// NOTE n +doN: + // Args + // x21 x + // x22 y + sub sp, sp, 32 + str x21, [sp, 24] + str x22, [sp, 16] + str x23, [sp, 8] + str lr, [sp] + + sub x22, x22, 8 + mov x23, 8 + bl vertLine + mov x23, 5 + bl doHorizontalLine + add x21, x21, 6 + add x22, x22, 1 + mov x23, 7 + bl vertLine + + ldr lr, [sp] + ldr x23, [sp, 8] + ldr x22, [sp, 16] + ldr x21, [sp, 24] + add sp, sp, 32 + ret + +.globl doVm +// NOTE V +doVm: + sub sp, sp, 32 + str x21, [sp, 24] + str x22, [sp, 16] + str x23, [sp, 8] + str lr, [sp] + + sub x22, x22, 20 + mov x23, 5 + bl vertLine + + add x21, x21, 6 + bl vertLine + sub x21, x21, 6 + + add x21, x21, 1 + add x22, x22, 6 + bl vertLine + + add x21, x21, 4 + bl vertLine + sub x21, x21, 4 + + add x21, x21, 1 + add x22, x22, 6 + bl vertLine + + add x21, x21, 2 + bl vertLine + sub x21, x21, 2 + + add x21, x21, 1 + add x22, x22, 6 + bl vertLine + + ldr lr, [sp] + ldr x23, [sp, 8] + ldr x22, [sp, 16] + ldr x21, [sp, 24] + add sp, sp, 32 + ret + +.globl doZzzeta +// NOTE doZzzeta +doZzzeta: + // Args + // x21 x inicial + // x22 y inicial + // x18 Color + // Usa: + // x23 para doHorizontalLine + sub sp, sp, 24 + stur lr, [sp, 16] + stur x21, [sp, 8] + stur x22, [sp] + mov x16, x21 + mov x12, x22 + mov x9, 0 + + mov x23, 20 + bl doHorizontalLine + add x21, x21, 19 + mov x16, x21 + +doZDiagz: + bl drawPixel + sub x22, x22, 1 + add x21, x21, 1 + add x16, x16, 1 + sub x12, x12, 1 + cmp x9, 19 + b.eq doZBotz + add x9, x9, 1 + b doZDiagz + +doZBotz: + mov x23, 20 + bl doHorizontalLine + +endZz: + ldur x22, [sp] + ldur x21, [sp, 8] + ldur lr, [sp, 16] + add sp, sp, 24 + ret + +.globl doZ +// NOTE z minus +doZ: + // Args + // x21 x inicial + // x22 y inicial + // x18 Color + // Usa: + // x23 para doHorizontalLine + sub sp, sp, 24 + stur lr, [sp, 16] + stur x21, [sp, 8] + stur x22, [sp] + mov x16, x21 + mov x12, x22 + mov x9, 0 + + sub x22, x22, 8 + + mov x23, 8 + bl doHorizontalLine + add x21, x21, 8 + mov x16, x21 + mov x12, x22 + +doZDiag: + bl drawPixel + add x22, x22, 1 + sub x21, x21, 1 + sub x16, x16, 1 + add x12, x12, 1 + cmp x9, 7 + b.eq doZBot + add x9, x9, 1 + b doZDiag + +doZBot: + mov x23, 8 + bl doHorizontalLine + +endZ: + ldur x22, [sp] + ldur x21, [sp, 8] + ldur lr, [sp, 16] + add sp, sp, 24 + ret + +.globl doGm +// NOTE G mayus +doGm: + // Args + // x21 x inicial + // x22 y inicial + // w18 color + // AUX fun: + // doVertLine + sub sp, sp, 32 + stur x21, [sp, 24] + stur x22, [sp, 16] + stur x23, [sp, 8] + stur lr, [sp] + + add x21, x21, 1 // Ignoramos el primer pixel + mov x23, 10 + bl doHorizontalLine // Linea h inferior + + add x21, x21, 10 + sub x22, x22, 6 + mov x23, 5 + bl vertLine + + sub x21, x21, 5 + mov x23, 5 + bl doHorizontalLine + + sub x21, x21, 5 + sub x22, x22, 9 + mov x23, 14 + bl vertLine // Linea v izquierda + + add x21, x21, 1 + sub x22, x22, 1 + mov x23, 9 + bl doHorizontalLine // Linea h superior + + add x21, x21, 9 + add x22, x22, 1 + mov x23, 1 + bl vertLine + + ldur lr, [sp] + ldur x23, [sp, 8] + ldur x22, [sp, 16] + ldur x21, [sp, 24] + add sp, sp, 32 + ret + +.globl doG +// NOTE g minus +doG: // 16x8 + // Args + // x21 x inicial + // x22 y inicial + // w18 color + // x23 = w = 16 + sub sp, sp, #48 + stur x9, [sp, #40] // x1 + stur x10, [sp, #32] // x2 + stur x21, [sp, #24] + stur x22, [sp, #16] + stur x23, [sp, #8] + stur lr, [sp] + + add x21, x21, 1 // Ignoramos el primer pixel + mov x23, 7 + bl doHorizontalLine // Linea h inferior + add x21, x21, 7 + mov x10, x22 // yih + sub x22, x22, 7 + mov x9, x21 // xih + bl vertLine // Linea v derecha + sub x21, x21, 7 + mov x23, 7 + bl doHorizontalLine + + sub x21, x21, 1 // Ignoramos el primer pixel + add x22, x22, 1 + mov x23, 5 + + bl vertLine // Linea v izq + + mov x21, x9 + mov x22, x10 + + mov x23, 6 // hago la line hacia abajo + bl vertLine + + add x22, x22, 7 + sub x21, x21, 6 + mov x23, 6 + bl doHorizontalLine + sub x22, x22, 1 + sub x21, x21, 1 + + mov x23, 1 + bl doHorizontalLine + + ldur lr, [sp] + ldur x23, [sp, #8] + ldur x22, [sp, #16] + ldur x21, [sp, #24] + ldur x10, [sp, #32] + ldur x9, [sp, #40] + add sp, sp, #48 + ret + +.globl doT +// NOTE doT minus +doT: // 16x8 + sub sp, sp, 32 + str lr, [sp] + str x23, [sp, 8] + str x22, [sp, 16] + str x21, [sp, 24] + + add x21, x21, 1 + mov x23, 3 + bl doHorizontalLine + sub x21, x21, 1 + sub x22, x22, 17 + mov x23, 16 + bl vertLine + + add x22, x22, 7 + mov x23, 4 + bl doHorizontalLine + + ldr lr, [sp] + ldr x23, [sp, 8] + ldr x22, [sp, 16] + ldr x21, [sp, 24] + add sp, sp, 32 + ret + +.globl doDiego +// NOTE Diego +doDiego: + // Args + // x21 x + // x22 y + // w18 color + // x23 for O + sub sp, sp, #40 + str x18, [sp, #32] + str x23, [sp, #24] + str x22, [sp, #16] + str x21, [sp, #8] + str lr, [sp] + + bl doDm + + add x21, x21, 15 // Espacio entre letras + bl doI + + add x21, x21, 15 // Espacio entre letras + bl doE + + add x21, x21, 15 // Espacio entre letras + bl doG + + add x21, x21, 15 // Espacio entre letras + bl doO + + add x21, x21, 30 // Espacio entre letras + bl doGm + + add x21, x21, 15 // Espacio entre letras + bl doI + + add x21, x21, 15 // Espacio entre letras + bl doM + + add x21, x21, 20 // Espacio entre letras + bl doE + + add x21, x21, 14 // Espacio entre letras + bl doN + + add x21, x21, 15 // Espacio entre letras + bl doE + + add x21, x21, 15 // Espacio entre letras + bl doZ + +endDiego: + ldr lr, [sp] + ldr x21, [sp, #8] + ldr x22, [sp, #16] + ldr x23, [sp, #24] + ldr x18, [sp, #32] + add sp, sp, #40 + ret + +.globl doValentinaVispo +// NOTE Vale +doValentinaVispo: + // @Valentina Vispo + // x21 xo + // x22 yo + // w18 Colour + sub sp, sp, #40 + str x18, [sp, #32] + str x23, [sp, #24] + str x22, [sp, #16] + str x21, [sp, #8] + str lr, [sp] + + bl doVm + + add x21, x21, 15 // Espacio entre letras + bl doA + + add x21, x21, 15 // Espacio entre letras + bl doL + + add x21, x21, 15 // Espacio entre letras + bl doE + + add x21, x21, 15 // Espacio entre letras + bl doN + + add x21, x21, 15 // Espacio entre letras + bl doT + + add x21, x21, 15 // Espacio entre letras + bl doI + + add x21, x21, 15 // Espacio entre letras + bl doN + + add x21, x21, 15 // Espacio entre letras + bl doA + + add x21, x21, 30 // Espacio entre letras + bl doVm + + add x21, x21, 10 // Espacio entre letras + bl doI + + add x21, x21, 15 // Espacio entre letras + bl doS + + add x21, x21, 15 // Espacio entre letras + bl doP + + add x21, x21, 15 // Espacio entre letras + bl doO + +endDoValentinaVispo: + ldr lr, [sp] + ldr x21, [sp, #8] + ldr x22, [sp, #16] + ldr x23, [sp, #24] + ldr x18, [sp, #32] + add sp, sp, #40 + ret diff --git a/ejercicio2/start.s b/ejercicio2/start.s new file mode 100644 index 0000000..d9c432e --- /dev/null +++ b/ejercicio2/start.s @@ -0,0 +1,142 @@ + .text + .org 0x80000 + +.globl PreFrameBuffer +.data + PreFrameBuffer: .skip 4*640*480 + // Setup Frame Buffer + .equ SCREEN_WIDTH, 640 + .equ SCREEN_HEIGH, 480 + .equ BITS_PER_PIXEL, 32 + + .equ MAIL_BASE, 0xB880 // Mailbox Base Address + .equ MAIL_WRITE, 0x20 // Mailbox Write Register + .equ MAIL_TAGS, 0x8 // Mailbox Channel 8: Tags (ARM to VC) + .equ PERIPHERAL_BASE, 0x3F000000 // Peripheral Base Address + + .equ Get_Allocate_Buffer, 0x00040001 // Frame Buffer: Allocate Buffer (Response: Frame Buffer Base Address In Bytes, Frame Buffer Size In Bytes) + + .equ Set_Physical_Display, 0x00048003 // Frame Buffer: Set Physical (Display) Width/Height (Response: Width In Pixels, Height In Pixels) + .equ Set_Virtual_Buffer, 0x00048004 // Frame Buffer: Set Virtual (Buffer) Width/Height (Response: Width In Pixels, Height In Pixels) + .equ Set_Depth, 0x00048005 // Frame Buffer: Set Depth (Response: Bits Per Pixel) + .equ Set_Virtual_Offset, 0x00048009 // Frame Buffer: Set Virtual Offset (Response: X In Pixels, Y In Pixels) + .equ Set_Palette, 0x0004800B // Frame Buffer: Set Palette (Response: RGBA Palette Values (Index 0 To 255)) + .equ Set_Pixel_Order, 0x00048006 // Frame Buffer: Set Pixel Order + .equ Get_Pixel_pitch, 0x00048006 // Frame Buffer: Set Pixel Order + + // UART data + .equ Set_Power, 0x00028001 // UART: Set Power + .equ Set_ClkRate, 0x00038002 // UART: Set Clock Rate + + .equ MMIO_BASE_ALTA, 0x3f20 + + .equ GPFSEL0, 0x0000 + .equ GPFSEL1, 0x0004 + .equ GPPUD, 0x0094 + .equ GPPUDCLK0, 0x0098 + + .equ UART0_DR, 0x1000 + .equ UART0_FR, 0x1018 + .equ UART0_IBRD, 0x1024 + .equ UART0_FBRD, 0x1028 + .equ UART0_LCRH, 0x102C + .equ UART0_CR, 0x1030 + .equ UART0_IMSC, 0x1038 + .equ UART0_ICR, 0x1044 +// Return CPU ID (0..3) Of The CPU Executed On + +.section ".text.boot" +.globl _start + +_start: + + mrs x1, mpidr_el1 // X0 = Multiprocessor Affinity Register (MPIDR) + and x1, x1, #3 // X0 = CPU ID (Bits 0..1) + cbz x1, StackInit // IF (CPU ID == 0) Branch To Finit else (Core ID 1..3) CoreLoop + // Infinite Loop For Core 1, 2 and 3 +CoreLoop: + b CoreLoop + +StackInit: +// set stack before our code + ldr x1, =_start + mov sp, x1 + + // clear bss + + ldr x1, =__bss_start + ldr w2, =__bss_size +_StackInit_loop: + cbz w2, FB_Init + str xzr, [x1], #8 + sub w2, w2, #1 + cbnz w2, _StackInit_loop + +// Core 0 Init the framebuffer +FB_Init: + ldr x0, =(FB_STRUCT + MAIL_TAGS) + ldr x1, =MAIL_BASE + ldr x2, =FB_POINTER + orr x1, x1, PERIPHERAL_BASE + str w0, [x1, MAIL_WRITE + MAIL_TAGS] // Mail Box Write + ldr w0, [x2] // W0 = Frame Buffer Pointer + cbz w0, FB_Init // IF (Frame Buffer Pointer == Zero) Re-Initialize Frame Buffer + and w0, w0, 0x3FFFFFFF // Convert Mail Box Frame Buffer Pointer From BUS Address To Physical Address ($CXXXXXXX -> $3XXXXXXX) + str w0, [x2] // Store Frame Buffer Pointer Physical Address + add w10, w0, wzr + b main + +.align 16 +FB_STRUCT: // Mailbox Property Interface Buffer Structure + .word FB_STRUCT_END - FB_STRUCT // Buffer Size In Bytes (Including The Header Values, The End Tag And Padding) + .word 0x00000000 // Buffer Request/Response Code + // Request Codes: $00000000 Process Request Response Codes: $80000000 Request Successful, $80000001 Partial Response + // Sequence Of Concatenated Tags + .word Set_Physical_Display // Tag Identifier + .word 0x00000008 // Value Buffer Size In Bytes + .word 0x00000008 // 1 bit (MSB) Request/Response Indicator (0=Request, 1=Response), 31 bits (LSB) Value Length In Bytes + .word SCREEN_WIDTH // Value Buffer + .word SCREEN_HEIGH // Value Buffer + + .word Set_Virtual_Buffer // Tag Identifier + .word 0x00000008 // Value Buffer Size In Bytes + .word 0x00000008 // 1 bit (MSB) Request/Response Indicator (0=Request, 1=Response), 31 bits (LSB) Value Length In Bytes + .word SCREEN_WIDTH // Value Buffer + .word SCREEN_HEIGH // Value Buffer + + .word Set_Virtual_Offset // Tag Identifier + .word 0x00000008 // Value Buffer Size In Bytes + .word 0x00000008 // 1 bit (MSB) Request/Response Indicator (0=Request, 1=Response), 31 bits (LSB) Value Length In Bytes +FB_OFFSET_X: + .word 0 // Value Buffer +FB_OFFSET_Y: + .word 0 // Value Buffer + + .word Set_Depth // Tag Identifier + .word 0x00000004 // Value Buffer Size In Bytes + .word 0x00000004 // 1 bit (MSB) Request/Response Indicator (0=Request, 1=Response), 31 bits (LSB) Value Length In Bytes + .word BITS_PER_PIXEL // Value Buffer + + .word 0x48006 // Tag Identifier + .word 0x00000004 // Value Buffer Size In Bytes + .word 0x00000004 // 1 bit (MSB) Request/Response Indicator (0=Request, 1=Response), 31 bits (LSB) Value Length In Bytes + .word 0 // RGB, not BGR preferably + + .word Set_Palette // Tag Identifier + .word 0x00000010 // Value Buffer Size In Bytes + .word 0x00000010 // 1 bit (MSB) Request/Response Indicator (0=Request, 1=Response), 31 bits (LSB) Value Length In Bytes + .word 0 // Value Buffer (Offset: First Palette Index To Set (0-255)) + .word 2 // Value Buffer (Length: Number Of Palette Entries To Set (1-256)) +FB_PAL: + .word 0x00000000,0xFFFFFFFF // RGBA Palette Values (Offset To Offset+Length-1) + + .word Get_Allocate_Buffer // Tag Identifier + .word 0x00000008 // Value Buffer Size In Bytes + .word 0x00000008 // 1 bit (MSB) Request/Response Indicator (0=Request, 1=Response), 31 bits (LSB) Value Length In Bytes +FB_POINTER: + .word 0 // FrameBuffer Pointer +FB_SIZE: + .word 0 // FrameBuffer Size + + .word 0x00000000 // $0 (End Tag) +FB_STRUCT_END: From cf2754daa4bca4f9bf551e2f89431673afd8075f Mon Sep 17 00:00:00 2001 From: Valentina Vispo Date: Mon, 14 Jun 2021 17:50:02 -0300 Subject: [PATCH 45/47] Remove comments --- ejercicio2/TPQEMU_Gimenez_Vispo.txt | 7 ++- ejercicio2/baseCore.s | 7 +-- ejercicio2/draw.s | 29 +++---------- ejercicio2/font.s | 67 ++--------------------------- 4 files changed, 18 insertions(+), 92 deletions(-) diff --git a/ejercicio2/TPQEMU_Gimenez_Vispo.txt b/ejercicio2/TPQEMU_Gimenez_Vispo.txt index 4285fdd..2734355 100644 --- a/ejercicio2/TPQEMU_Gimenez_Vispo.txt +++ b/ejercicio2/TPQEMU_Gimenez_Vispo.txt @@ -1,10 +1,15 @@ Ejercicio 2: +Explicación breve: + +La animación es una serie de escenas donde se ve una computadora con una selección, una transición de círculos y líneas RGB para luego mostrar dos pirámides con el nombre de los integrantes que va cambiando entre día y noche respectivamente. + +** Explicación completa En el ejercicio 2 la idea es hacer 3 escenas diferentes: En la primera escena se encuentra una computadora, un mouse clickea un botón como inicio de la animación, esto provoca que se "rompa" la pantalla. -La siguiente escena empieza como una especie de cuenta regresiva con colores (se ven líneas que convergen desde el punto central mientras se expande un círculo, ambos con colores RBG). +La siguiente escena empieza como una especie de cuenta regresiva con colores y formas en un fondo negro. Se ven líneas que convergen desde el punto central y se extienen hacia el lado inferior y superior de la ventana; estas líneas van cambiando de colores RBG de izquierda a derecha en la parte superior y de derecha a izquierda en la parte inferior. Esto ocurre mientras se expande un círculo desde el centro, ambos con colores RBG. Cuando termina esa cuenta se muestran pirámides y el nombre y apellido de cada intetgrante (un ciclo es de día y el otro de noche). Arriba se ve el respectivo sol/luna moviéndose de izquierda a derecha. Esta esta última escena se repite en bucle. diff --git a/ejercicio2/baseCore.s b/ejercicio2/baseCore.s index f2ebfd5..6c91de8 100644 --- a/ejercicio2/baseCore.s +++ b/ejercicio2/baseCore.s @@ -84,7 +84,6 @@ endUpdate: ret .globl drawUpdateWithCleanScreen -// NOTE drawUpdateWithCleanScreen drawUpdateWithCleanScreen: // x28 PreFrameBuffer // x20 FrameBuffer @@ -119,11 +118,9 @@ endUpdateAndClean: add sp, sp, 40 ret -.globl setColour // https://stackoverflow.com/questions/54918639/linking-2-object-files -// NOTE setColour +.globl setColour setColour: - // Return - // x18 Color a pintar + // Return x18 Color a pintar // Args // x13 r // x14 g diff --git a/ejercicio2/draw.s b/ejercicio2/draw.s index d8e6a60..40f38bb 100644 --- a/ejercicio2/draw.s +++ b/ejercicio2/draw.s @@ -12,8 +12,8 @@ .equ COLOR_NEGRO, 0x00 + .globl doAnimacionInicial -// NOTE doAnimacionInicial doAnimacionInicial: sub sp, sp, 56 str x3, [sp, 48] @@ -54,6 +54,7 @@ preDoSun: mov x9, 0 sub sp, sp, 8 stur x9, [sp, 56] + doSun: bl cleanScreen bl anPiramidesDia @@ -81,6 +82,7 @@ doNoche: mov x9, 0 str x9, [sp, 56] mov x21, 0 + loopNoche: bl cleanScreen bl anPiramidesNoche @@ -111,7 +113,6 @@ endAnimacion: ret .globl doEstrella -// NOTE Estrella doEstrella: sub sp, sp, 32 str x21, [sp, 24] @@ -152,7 +153,6 @@ endRellenoCir: .globl doComputerBroken -// NOTE doComputerBroken doComputerBroken: sub sp, sp, 72 str x7, [sp, 64] @@ -174,7 +174,7 @@ doComputerBroken: mov x9, 0 mov x7, 0 -loopCompBro1: //FIXME No anda +loopCompBro1: cmp x9, 12 b.eq endCompBro mov x7, 0 @@ -190,6 +190,7 @@ loopCompBro2: add x7, x7, 1 b loopCompBro2 + endLoopCompBro2: add x9, x9, 1 b loopCompBro1 @@ -206,7 +207,6 @@ endCompBro: ret .globl anPiramidesDia -// NOTE Segunda animacion anPiramidesDia: sub sp, sp, 56 str x3, [sp, 40] @@ -319,7 +319,6 @@ anPiramidesNoche: ret .globl doMouse -// NOTE doMouse doMouse: // Args // x21 x @@ -342,7 +341,6 @@ doMouse: ret .globl doCompuVentana -// NOTE doCompuVentana doCompuVentana: sub sp, sp, 56 stur x15, [sp, 48] @@ -451,7 +449,6 @@ doCompuVentana: ret .globl triangDer -// NOTE Triángulo apuntando a la derecha triangDer: // Args // x21 x @@ -506,7 +503,6 @@ endTriangDer: ret .globl vertLine -// NOTE Vertilcal line with a height vertLine: // Args // x21 x @@ -540,9 +536,7 @@ endVertLine: add sp, sp, 40 ret - .globl drawLine -// NOTE drawLine Line drawLine: // Args // x21 xc0 coordenada x del primer punto @@ -635,6 +629,7 @@ skipIf1: cmp x8, x4 b.gt loopLine // e2 > dx // If we are here -> e2 <= dx + break2: add x19, x19, x4 // err += dx add x22, x22, x7 // yc0 += sy @@ -655,7 +650,6 @@ endDrawLine: ret .globl doSquare -// NOTE Square doSquare: // Args // x21 xo lugar dónde empiezo a dibujar la figura @@ -675,7 +669,6 @@ doSquare: ret .globl doRectangle -// NOTE Rectangle alto(h) x largo(w) doRectangle: // alto x largo// // Args // x21 x2 lugar dónde empiezo a dibujar la figura @@ -688,7 +681,6 @@ doRectangle: // alto x largo// // drawPixel: setPixel x16 x, x12 y // x9 posición inicial de x // x10 posición inicial de y - sub sp, sp, #56 // Reservamos memoria str x3, [sp, 48] stur x21, [sp, 40] @@ -720,7 +712,6 @@ endRectangule: ret .globl doCircle -// NOTE Circle doCircle: // Mid-Point Circle Drawing Algorithm // // (0, 0) centro // point p(x, y) @@ -908,9 +899,7 @@ endCircleFillAux: ret .globl doTriangleUp -// NOTE Triángulo hacia arriba doTriangleUp: - // @Diego // Args // x21 x lugar dónde empiezo a dibujar la figura // x22 y lugar dónde empiezo a dibujar la figura @@ -964,9 +953,7 @@ endTriang: ret .globl doTriangleDown -// NOTE Triángulo hacia abajo doTriangleDown: - // @Diego // Args // x21 x lugar dónde empiezo a dibujar la figura // x22 y lugar dónde empiezo a dibujar la figura @@ -1022,9 +1009,7 @@ endTriangDown: ret .globl doPiramide -// NOTE Pirámide doPiramide: - // @Diego // Args // x21 x lugar dónde empiezo a dibujar la figura // x22 y lugar dónde empiezo a dibujar la figura @@ -1077,7 +1062,6 @@ endPir: ret .globl verticalLine -// NOTE Line verticalLine: // Args // x21 x @@ -1104,7 +1088,6 @@ verLineEnd: ret .globl doHorizontalLine -// NOTE LineH doHorizontalLine: // Crea líneas horizontales en la coordenada (xo, po) con w cantidad de pixeles que se extienden hacia la derecha // // Args // x21 xo valor de origen x diff --git a/ejercicio2/font.s b/ejercicio2/font.s index 8833e78..1a096fe 100644 --- a/ejercicio2/font.s +++ b/ejercicio2/font.s @@ -7,8 +7,9 @@ .equ COLOR_2, 0xFFFF // Color blanco GB // 0x1607 .equ COLOR_NEGRO, 0x00 + + .globl doAm -// NOTE a minus doAm: // 16x8 sub sp, sp, 32 str x21, [sp, 24] @@ -50,7 +51,7 @@ doA: // 16x8 add x21, x21, 1 mov x23, 5 bl doHorizontalLine - + sub x21, x21, 1 sub x22, x22, 7 mov x23, 6 @@ -65,7 +66,7 @@ doA: // 16x8 add x22, x22, 1 mov x23, 1 bl doHorizontalLine - + add x21, x21, 1 sub x22, x22, 1 mov x23, 8 @@ -84,7 +85,6 @@ doA: // 16x8 ret .globl doEm -// NOTE E doEm: // Args // x21 x lugar dónde empiezo a dibujar la figura @@ -136,7 +136,6 @@ endE: ret .globl doE -// NOTE e minus doE: // 16x8 // Args // x21 x lugar dónde empiezo a dibujar la figura @@ -178,7 +177,6 @@ doE: // 16x8 ret .globl doIm -// NOTE I doIm: // Args // x21 x lugar dónde empiezo a dibujar la figura @@ -231,7 +229,6 @@ endI: ret .globl doI -// NOTE i doI: // Args // x21 x lugar dónde empiezo a dibujar la figura @@ -267,7 +264,6 @@ doI: ret .globl doO -// NOTE o doO: sub sp, sp, #32 str x23, [sp, #24] @@ -299,7 +295,6 @@ doO: ret .globl doDm -// NOTE D doDm: // Args // x21 x inicial @@ -383,7 +378,6 @@ endD: ret .globl doL -// NOTE l minus doL: // 16x8 // Args // x21 x inicial @@ -415,7 +409,6 @@ doL: // 16x8 ret .globl doS -// NOTE s minus doS: // 16x8 // Args // x21 x inicial @@ -453,7 +446,6 @@ doS: // 16x8 ret .globl doP -// NOTE p doP: // 16x8 // Args // x21 x inicial @@ -487,7 +479,6 @@ doP: // 16x8 ret .globl doM -// NOTE m doM: // Args // x21 x inicial @@ -519,46 +510,6 @@ doM: mov x23, 7 bl vertLine - -/* -doPalo: - add x12, x12, 1 - bl drawPixel - cmp x9, 20 - b.eq doMr - add x9, x9, 1 - b doPalo - -doMr: - mov x12, x22 - mov x9, 0 -doMrLoop: - add x16, x16, 1 - add x12, x12, 1 - bl drawPixel - cmp x9, 10 - b.eq doMrUp - add x9, x9, 1 - b doMrLoop - -doMrUp: - add x16, x16, 1 - sub x12, x12, 1 - bl drawPixel - cmp x9, 0 - b.eq doPaloD - sub x9, x9, 1 - b doMrUp - -doPaloD: - add x12, x12, 1 - bl drawPixel - cmp x9, 20 - b.eq endM - add x9, x9, 1 - b doPaloD -*/ - endM: ldur x22, [sp, #16] ldur x21, [sp, #8] @@ -567,7 +518,6 @@ endM: ret .globl doN -// NOTE n doN: // Args // x21 x @@ -596,7 +546,6 @@ doN: ret .globl doVm -// NOTE V doVm: sub sp, sp, 32 str x21, [sp, 24] @@ -640,7 +589,6 @@ doVm: ret .globl doZzzeta -// NOTE doZzzeta doZzzeta: // Args // x21 x inicial @@ -684,7 +632,6 @@ endZz: ret .globl doZ -// NOTE z minus doZ: // Args // x21 x inicial @@ -731,7 +678,6 @@ endZ: ret .globl doGm -// NOTE G mayus doGm: // Args // x21 x inicial @@ -781,7 +727,6 @@ doGm: ret .globl doG -// NOTE g minus doG: // 16x8 // Args // x21 x inicial @@ -840,7 +785,6 @@ doG: // 16x8 ret .globl doT -// NOTE doT minus doT: // 16x8 sub sp, sp, 32 str lr, [sp] @@ -868,7 +812,6 @@ doT: // 16x8 ret .globl doDiego -// NOTE Diego doDiego: // Args // x21 x @@ -927,9 +870,7 @@ endDiego: ret .globl doValentinaVispo -// NOTE Vale doValentinaVispo: - // @Valentina Vispo // x21 xo // x22 yo // w18 Colour From 7e3c5432ac949cd85bff482925674c9401368e6c Mon Sep 17 00:00:00 2001 From: Valentina Vispo Date: Mon, 14 Jun 2021 17:51:01 -0300 Subject: [PATCH 46/47] Style --- ejercicio2/TPQEMU_Gimenez_Vispo.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ejercicio2/TPQEMU_Gimenez_Vispo.txt b/ejercicio2/TPQEMU_Gimenez_Vispo.txt index 2734355..6ef457d 100644 --- a/ejercicio2/TPQEMU_Gimenez_Vispo.txt +++ b/ejercicio2/TPQEMU_Gimenez_Vispo.txt @@ -4,7 +4,9 @@ Explicación breve: La animación es una serie de escenas donde se ve una computadora con una selección, una transición de círculos y líneas RGB para luego mostrar dos pirámides con el nombre de los integrantes que va cambiando entre día y noche respectivamente. -** Explicación completa +--- + +** Explicación completa ** En el ejercicio 2 la idea es hacer 3 escenas diferentes: En la primera escena se encuentra una computadora, un mouse clickea un botón como inicio de la animación, esto provoca que se "rompa" la pantalla. @@ -13,6 +15,8 @@ La siguiente escena empieza como una especie de cuenta regresiva con colores y f Cuando termina esa cuenta se muestran pirámides y el nombre y apellido de cada intetgrante (un ciclo es de día y el otro de noche). Arriba se ve el respectivo sol/luna moviéndose de izquierda a derecha. Esta esta última escena se repite en bucle. +--- + Trabajo en Github: https://github.com/shirosweets/vc-framebuffer From 397a3012cb88b1569dafa12c1439ddd75ec8e1ff Mon Sep 17 00:00:00 2001 From: Valentina Vispo Date: Mon, 14 Jun 2021 17:56:55 -0300 Subject: [PATCH 47/47] Add .tar --- ejercicio1/baseCore.s | 3 +-- ejercicio1/draw.s | 6 +++--- ejercicio1/font.s | 3 ++- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ejercicio1/baseCore.s b/ejercicio1/baseCore.s index 6eef569..6c91de8 100644 --- a/ejercicio1/baseCore.s +++ b/ejercicio1/baseCore.s @@ -120,8 +120,7 @@ endUpdateAndClean: .globl setColour setColour: - // Return - // x18 Color a pintar + // Return x18 Color a pintar // Args // x13 r // x14 g diff --git a/ejercicio1/draw.s b/ejercicio1/draw.s index 53209b3..0abe133 100644 --- a/ejercicio1/draw.s +++ b/ejercicio1/draw.s @@ -11,6 +11,8 @@ .equ COLOR_2, 0xFFFF // Color blanco GB // 0x1607 .equ COLOR_NEGRO, 0x00 + + .globl anPiramidesDia anPiramidesDia: sub sp, sp, 56 @@ -98,6 +100,7 @@ endRellenoCir: ldr x24, [sp, 16] add sp, sp, 24 ret + .globl doEstrella doEstrella: sub sp, sp, 32 @@ -529,7 +532,6 @@ cleanScreenBuffer: // Pinta toda la pantalla de negro .globl paintScreenBuffer paintScreenBuffer: // 320w 240h -> 76800 + 240 - // Return -> nada // Args: x18 Colour mov x0, x20 // Origen del frameBuffer mov x8, SCREEN_WIDTH @@ -546,7 +548,6 @@ paintScreenBufferLoop: .globl paintScreen paintScreen: // 320w 240h -> 76800 + 240 - // Return -> nada // Args: x18 Colour adr x28, PreFrameBuffer // Origen del frameBuffer mov x8, SCREEN_WIDTH @@ -594,4 +595,3 @@ endVertLine: ldur x9, [sp, 32] add sp, sp, 40 ret - diff --git a/ejercicio1/font.s b/ejercicio1/font.s index 1cce5e1..1a096fe 100644 --- a/ejercicio1/font.s +++ b/ejercicio1/font.s @@ -7,6 +7,8 @@ .equ COLOR_2, 0xFFFF // Color blanco GB // 0x1607 .equ COLOR_NEGRO, 0x00 + + .globl doAm doAm: // 16x8 sub sp, sp, 32 @@ -869,7 +871,6 @@ endDiego: .globl doValentinaVispo doValentinaVispo: - // @Valentina Vispo // x21 xo // x22 yo // w18 Colour