O'Niel
O'Niel

Reputation: 1787

Color specific row in bitmap ASM

I want to create a red screen in the MARS Bitmap-display, than I want to make the borders yellow.

I do this by first making the first and last row yellow, and than the first and last columns.

This is my code:

#MIPS
#ND
#1 b

li $t0, -4          #$t0 holds current iterator
li $s0, 0           #Current COLOMN_iterator
li $s1, 0           #Current ROW_iterator
main:
    li $t1, 0x00ff0000      #Loading RED in register
    li $t2, 0x00ffff00      #Loading YELLOW in register

    addi $gp, $gp, 4        #Incrementing register with one word (next pixel in display)
    addi $t0, $t0, 4        #Incrementing current location to next pixel

    addi $s0, $s0, 1        #Column++


    blt $s1, 1, makePixelYellow #if currentRow == 1
    beq $s1, 31, makePixelYellow    #if currentRow == 31

    j makePixelRed


makePixelYellow:
    sw $t2, -4($gp)         #Make pixel yellow

    bne $s0, 32, main
    addi $s1, $s1, 1        #Column finsihed, so row++
    li $s0, 0           #Resetting column

    j main

makePixelRed:
    sw $t1, -4($gp)         #Make pixel red

j main

Output & settings of the Bitmap display: Mips error

I think the problem occurs somewhere on line 19. I'm able to make all the rows below a specific n yellow using Branch-less than. But I'm not able to color one specific row using Branch-equal.

The label is only executing correctly on branch-less than, not branch-equal. It's MIPS ASM by the way.

Upvotes: 2

Views: 6080

Answers (1)

Ped7g
Ped7g

Reputation: 16606

Answer by Jester: you don't update row/column when you branch to makePixelRed code.


My general advice about computer graphics programming:

Usually when programming some pixel graphics, you don't want to branch per-pixel, that's very costly in terms of performance, with code aimed for performance you do the opposite, rather emit more code-paths covering different situations to draw desired output with minimal branching involved.

The "calculate something + branch a lot + draw single pixel + loop" is used only when performance is not critical, but instead you want to have only single general code for pixel drawing and looping (like column/row advancing, which would actually save you from your error, if you would use those branches only to set yellow/red pixel, and then return to some "main" ending to finish the loop code), like in some raytracer code, or when coding on minimal binary size (256B intros use often this kind of architecture, one quite complex formulae to calculate pixel colour and then single setPixel code and loop = it's slow, but it saves many bytes by not having multiple setPixel copies everywhere).

Here is some more direct "set yellow border + red body" example from me (tested with MARS 4.5, delayed branching OFF, and I used the same Bitmap setting like you (16x16 unit with 512x256 display, which means 32x16 bitmap target .. UX FTW!)

    li      $t1, 0x00ff0000     #Loading RED in register
    li      $t2, 0x00ffff00     #Loading YELLOW in register
big_loop:
    # top row + first column
    move    $a0, $gp            # pointer to write to
    li      $a1, 33             # 32 pixels for first row, +1 for left column
    move    $a2, $t2            # yellow
    jal     setPixels
    # 14 red rows with yellow endings+starts
    li      $t0, 14
red_rows_loop:
    li      $a1, 30
    move    $a2, $t1
    jal     setPixels           # set 30 red pixels in middle
    sw      $t2, ($a0)          # set 1 yellow at end, and 1 at start of next row
    sw      $t2, 4($a0)
    addi    $a0, $a0, 8
    addi    $t0, $t0, -1
    bnez    $t0, red_rows_loop
    # finish last row to be full yellow
    li      $a1, 31             # 31 pixels more needed (1 is already there)
    move    $a2, $t2            # yellow
    jal     setPixels

    li      $v0, 32             # MARS service delay(ms)
    li      $a0, 40             # 40ms = ~25 FPS if the draw would be instant
    syscall

    addiu   $t1, $t1, 0xFE0408  # adjust main color (red -2, green +4, blue +8 + overflows (B -> G -> R)
    andi    $t1, $t1, 0xFFFFFF  # force "alpha" to zero
    j       big_loop            # infinite loop will animated colours...

# Sets $a1 pixels to $a2 value starting at $a0 (memory fill)
# a0 = pointer to write to, a1 = count of pixels, a2 = value of pixel to set
# a0 will be updated to point right after the last written word
setPixels:
    sw      $a2, ($a0)      # set pixel (or simply memory word)
    addi    $a0, $a0, 4     # advance memory pointer
    addi    $a1, $a1, -1    # count-down loop
    bnez    $a1, setPixels
    jr      $ra             # return

Upvotes: 2

Related Questions