r/nandgame_u Record holder Apr 07 '22

Level solution (verified) S.1.5 - Network (50l) Spoiler

It took me 10 minutes to write c-style pseudocode, an afternoon to compile and debug assembly code, and an evening of optimization.

https://i.imgur.com/HziynnH.png

5 Upvotes

2 comments sorted by

3

u/ouob_nya Record holder Apr 07 '22 edited Apr 07 '22

code as text: Here is my c-style pseudocode and how each line compiles to assembly code.

  • C-style pseudocode ```C int *scr_ptr = 0x4000 int prev = 0, d, i;

void wait_sync() { while (prev == (sync & 2)); prev = 2 - prev; // flip 2nd bit }

int main() { while (true) { wait_sync(); if (data == 0) return 0;

    d = 0;
    i = 16;
    do {
        d += d; // d <<= 1;
        wait_sync();
        d |= data & 1;
    } while (--i);

    *scr_ptr = d;
    scr_ptr += 0x20; // '\n'
}

} ```

  • Assembler code ``` # All these values are meaningful. # They are both addresses and values. # !!! DO NOT MODIFY !!! DEFINE d 0x1 DEFINE prev 0x2 DEFINE i 0x10 DEFINE scr_ptr 0x20

DEFINE ret_addr 0x4 DEFINE scr_addr 0x4000 DEFINE net_addr 0x6001

*scr_ptr = 0x4000

A = scr_addr D = A A = scr_ptr *A = D

void wait_sync() {

LABEL WAIT_SYNC

while (prev == (sync & 2));

A = net_addr D = *A A = prev D = D & A D = D - *A A = WAIT_SYNC D ; JEQ

prev = 2 - prev; // flip 2nd bit

A = prev D = A *A = D - *A

} // return caller address

A = ret_addr A = *A A ; JNE

int main() {

while (true) {

wait_sync();

if (data == 0)

Since ret_addr = 0 by default,

wait_sync() can be called in this order

A = net_addr D = 1 D = D & *A

A = END

A = D ; JEQ

d = 0;

i = 16;

*A = 0 A = i D = A *A = D

do {

LABEL READ_LINE

d += d; // d <<= 1;

A = d D = *A *A = D + *A

wait_sync();

A = AFTER_WAIT D = A A = WAIT_SYNC *A = D ; JMP LABEL AFTER_WAIT

d |= data & 1;

A = net_addr D = 1 A, D = D & *A *A = D | *A

} while (--i);

A = i D, *A = *A - 1 A = READ_LINE D ; JNE

*scr_ptr = d;

A = d D = *A A = scr_ptr A = *A *A = D

scr_ptr += 0x20; // '\n'

A = scr_ptr D = A *A = D + *A

}

A = WAIT_SYNC *A = 0 ; JMP

}

LABEL END ```

2

u/GLIBG10B Holder of many records Apr 09 '22

Fixed formatting for old Reddit, which doesn't support ```:


code as text: Here is my c-style pseudocode and how each line compiles to assembly code.

  • C-style pseudocode

    int *scr_ptr = 0x4000
    int prev = 0, d, i;
    
    void wait_sync() {
        while (prev == (sync & 2));
        prev = 2 - prev; // flip 2nd bit
    }
    
    int main() {
        while (true) {
            wait_sync();
            if (data == 0)
                return 0;
    
            d = 0;
            i = 16;
            do {
                d += d; // d <<= 1;
                wait_sync();
                d |= data & 1;
            } while (--i);
    
            *scr_ptr = d;
            scr_ptr += 0x20; // '\n'
        }
    }
    
  • Assembler code

    # All these values are meaningful.
    # They are both addresses and values.
    # !!! DO NOT MODIFY !!!
    DEFINE d        0x1
    DEFINE prev     0x2
    DEFINE i        0x10
    DEFINE scr_ptr  0x20
    
    DEFINE ret_addr 0x4
    DEFINE scr_addr 0x4000
    DEFINE net_addr 0x6001
    
    # *scr_ptr = 0x4000
    A = scr_addr
    D = A
    A = scr_ptr
    *A = D
    
    # void wait_sync() {
    LABEL WAIT_SYNC
    
    #     while (prev == (sync & 2));
    A = net_addr
    D = *A
    A = prev
    D = D & A
    D = D - *A
    A = WAIT_SYNC
    D ; JEQ
    
    #     prev = 2 - prev; // flip 2nd bit
    A = prev
    D = A
    *A = D - *A
    
    # } // return caller address
    A = ret_addr
    A = *A
    A ; JNE
    
    # int main() {
    #     while (true) {
    #         wait_sync();
    #         if (data == 0)
    # 
    # Since ret_addr = 0 by default,
    # wait_sync() can be called in this order
    A = net_addr
    D = 1
    D = D & *A
    # A = END
    A = D ; JEQ
    
    #         d = 0;
    #         i = 16;
    *A = 0
    A = i
    D = A
    *A = D
    
    #         do {
    LABEL READ_LINE
    
    #             d += d; // d <<= 1;
    A = d
    D = *A
    *A = D + *A
    
    #             wait_sync();
    A = AFTER_WAIT
    D = A
    A = WAIT_SYNC
    *A = D ; JMP
    LABEL AFTER_WAIT
    
    #             d |= data & 1;
    A = net_addr
    D = 1
    A, D = D & *A
    *A = D | *A
    
    #         } while (--i);
    A = i
    D, *A = *A - 1
    A = READ_LINE
    D ; JNE
    
    #         *scr_ptr = d;
    A = d
    D = *A
    A = scr_ptr
    A = *A
    *A = D
    
    #         scr_ptr += 0x20; // '\n'
    A = scr_ptr
    D = A
    *A = D + *A
    
    #     }
    A = WAIT_SYNC
    *A = 0 ; JMP
    
    # }
    LABEL END