3 (formatting)
source | link

This part is pretty ugly, it sets destination at 0x400: * copies row * mirrors a row * adds 'newline' (10h at 0x1C8)

  • copies row
  • mirrors a row
  • adds 'newline' (10h at 0x1C8)

This part is pretty ugly, it sets destination at 0x400: * copies row * mirrors a row * adds 'newline' (10h at 0x1C8)

This part is pretty ugly, it sets destination at 0x400:

  • copies row
  • mirrors a row
  • adds 'newline' (10h at 0x1C8)
2 edited body
source | link

finalFinal step of translating to ascii.

final step of translating to ascii.

Final step of translating to ascii.

1
source | link

256 bytes, machine code (16-bit x86)

I was hoping I'll be able to beat at least Charcoal solution, but I haven't managed to squeeze more out of this (so far).

00000000: e8 7d 00 00 01 03 02 05 04 07 04 08 09 0a 0b 0c  .}..............
00000010: 08 0a 0a 10 28 29 5c 2f 27 2e 2b 4f 20 3a 5f 7c  ....()\/'.+O :_|
00000020: 2d 5f 5f 20 0a fd fd 1b 12 fe de 3b 7f 12 ff 1f  -__ .......;....
00000030: 5b a2 e3 5b a3 12 14 15 3d 15 14 29 3b 2d 1d 15  [..[....=..);-..
00000040: 14 42 2f 1f 6b 3b 14 15 1f 83 12 14 5c 14 19 3b  .B/.k;......\..;
00000050: 12 24 15 23 62 3d 2d 5b 2b 43 15 63 12 1f 14 1f  .$.#b=-[+C.c....
00000060: 19 3b 2b 4b 24 15 13 42 2d 5b 13 24 13 15 43 14  .;+K$..B-[.$..C.
00000070: 15 23 13 1f 19 3b 3d 13 5d 13 5d 13 1d 12 10 16  .#...;=.].].....
00000080: be 25 01 bf 00 03 57 57 b1 cc b0 08 f2 aa 5f 47  .%....WW......_G
00000090: ac d4 10 d0 ec 73 06 10 e1 f2 aa eb 05 10 e1 f2  .....s..........
000000a0: ae aa 81 fe 80 01 75 e8 ba 0c 00 5e bf 00 04 5b  ......u....^...[
000000b0: 57 b1 11 f3 a4 4e 4e b1 10 fd ac 3c 03 77 02 34  W....NN....<.w.4
000000c0: 01 fc aa e2 f4 83 c6 12 b0 10 aa 4a 75 e3 b2 0c  ...........Ju...
000000d0: be 76 05 b1 22 ac d7 aa e2 fb 83 ee 44 4a 75 f3  .v..".......DJu.
000000e0: 83 c3 11 b0 04 bf f6 04 aa 83 c7 0f aa bf 4a 06  ..............J.
000000f0: aa 83 c7 0f aa b9 0e 03 5e 89 f7 ac d7 aa e2 fb  ........^.......

Running: save to codegolf.com, dosbox to see the result you need to set breakpoint at cs:200 and dump memory at ds:400 of legth 30e... or you can append following piece, that will dump it to stdout

00000100: 31 db b9 0e 03 ba 00 04 b4 40 cd 21 cd 20        1........@.!.

This is my third code golf entry. Previous one was xor encryption.

Again: done using HT hexeditor, without compiler, but using Ctrl-a assemble instruction.

successfull attempt

How

This one took a bit to make it...

I've started with a simple approach, with one quadrant and trying to mirror it. That resulted in ~250 bytes and having only 2 of 4 quadrants. Big part of that was first quadrant itself, that took 204 bytes.

I knew this can be better.

I quickly checked that lz4 produces file with 144 bytes (skipping headers). GZ results in ~120 bytes, but clearly I wouldn't be able to create decompressor in 30 or so bytes.

So another attempt was handcrafting first quadrant by drawing it (including skipping, 4-bit encoding and such). That along with code resulted in 164 bytes (mind that's first quadrant only), nice but I was quite convinced I could do better.

I came up with some encoding, that ends up in 85 bytes for data. Along with translation table (that is not used yet) and decoder, I ended up with 144 bytes. NOICE, I'm =lz4 and already have decoder.

Next step was to merge initial mirroring from ~250 attempt to this one, this required some data tuning, but went easier than expected and resulted in 184bytes.

I realized I will need some additional markers to do horizontal mirror, which extended data to 91b and code to 190bytes (that went into trash later).

Along with horizontal mirror and final translation I've ended up with ~250 bytes.

I've managed to eat few bytes here and there, but had to add that ugly chars, that are incorrectly mirrored. That yielded 259 bytes... That is bad, cause I was using memory starting at 0x200 and did not want to redo that.

I've replaced conditions in horizontal mirror, to loop using translation table, that itself didn't save much, but combined with changing offending chars to spaces and fixing them later, saved few bytes, resulting in final 256 bytes.

You can see nice gallery, that I've done, while making this here

Dissection

As previous entries, this one also relies on initial values, although not that much as previous ones:

:0100 E8 7D 00                    call    0x180

skip data, there are 3 tables following:

:0103  db 00h,01h,03h,02h,05h,04h,07h,04h,08h,09h,0Ah,0Bh,0Ch,08h,0Ah,0Ah,10h

Translation table will be use for horizontal mirroring

:0114  db "()\/'.+O :_|-__ \n"

Translation table will be used for final substitution, to convert codes to actual ascii

:0125  db FDh,FDh,1Bh,12h,FEh,DEh,3Bh,7Fh,12h,FFh...

Encoded data, encoding is pretty simple:

  • low nibble is character code
  • high nibble:
    • if lowest bit is 1 interpret other 3 bits as 'repeat' (+ additional 1) of low nibble code
    • else interpret as number of bytes to 'skip' then place low nibble code
:0180 BE 25 01            mov     si, 125h
:0183 BF 00 03            mov     di, 300h
:0186 57                  push    di
:0187 57                  push    di
:0188 B1 CC               mov     cl, 0CCh
:018A B0 08               mov     al, 8
:018C F2 AA               repne stosb

fill 12*17 bytes with what will become space (8)

:018E 5F                  pop     di
:018F 47                  inc     di
:0190
:0190 AC                  lodsb
:0191 D4 10               aam     10h
:0193 D0 EC               shr     ah, 1
:0195 73 06               jnb     short 0x19D
:0197 10 E1               adc     cl, ah
:0199 F2 AA               repne stosb
:019B EB 05               jmp     short 0x1A2
:019D
:019D 10 E1               adc     cl, ah
:019F F2 AE               repne scasb
:01A1 AA                  stosb
:01A2
:01A2 81 FE 80 01         cmp     si, 180h
:01A6 75 E8               jnz     short 0x190

"Decompress" the data as described under table 3. Mind usage of beloved AAM instruction, and abuse of scasb to skip bytes.

:01A8 BA 0C 00            mov     dx, 0Ch
:01AB 5E                  pop     si
:01AC BF 00 04            mov     di, 400h
:01AF 5B                  pop     bx
:01B0 57                  push    di
:01B1
:01B1 B1 11               mov     cl, 11h          <--
:01B3 F3 A4               rep movsb                  |
:01B5 4E                  dec     si                 |
:01B6 4E                  dec     si                 |
:01B7 B1 10               mov     cl, 10h            |
:01B9                                                |
:01B9 FD                  std                   <--  |
:01BA AC                  lodsb                   |  |
:01BB 3C 03               cmp     al, 3           |  |
:01BD 77 02               ja      short 0x1C1 --  |  |
:01BF 34 01               xor     al, 1        |  |  |
:01C1                                          |  |  |
:01C1 FC                  cld                <--  |  |
:01C2 AA                  stosb                   |  |
:01C3 E2 F4               loop    0x1B9          --  |
:01C5 83 C6 12            add     si, 12h            |
:01C8 B0 10               mov     al, 10h            |
:01CA AA                  stosb                      |
:01CB 4A                  dec     dx                 |
:01CC 75 E3               jnz     short 0x1B1       --

This part is pretty ugly, it sets destination at 0x400: * copies row * mirrors a row * adds 'newline' (10h at 0x1C8)

Mind that mirror is done by abusing std/cld, to go through SI in reverse. Only \/() characters needs to be mirrored, that is done by xor at 0x1BF.

:01CE B2 0C               mov     dl, 0Ch
:01D0 BE 76 05            mov     si, 576h
:01D3
:01D3 B1 22               mov     cl, 22h    <--
:01D5                                          |
:01D5 AC                  lodsb        <--     |
:01D6 D7                  xlat           |     |
:01D7 AA                  stosb          |     |
:01D8 E2 FB               loop    0x1D5 --     |
:01DA                                          |
:01DA 83 EE 44            sub     si, 44h      |
:01DD 4A                  dec     dx           |
:01DE 75 F3               jnz     short 0x1D3 --
:01E0 83 C3 11            add     bx, 11h         (adjust bx for final xlat below)

This does horizontal mirror by using table 1, and using wonderful 1-byte XLAT

Then comes the boring part that fixes 4 "pixels", I'll skip it from here it's boring

:01F5 B9 0E 03            mov     cx, 30Eh
:01F8 5E                  pop     si
:01F9 89 F7               mov     di, si
:01FB
:01FB AC                  lodsb
:01FC D7                  xlat
:01FD AA                  stosb
:01FE E2 FB               loop    0x1FB

final step of translating to ascii.

PHEW! That was fun.