## simple illustration of the circle-drawing trick from HAKMEM
        ## in the form of a 64-byte MS-DOS .COM file
        ## by Kragen Javier Sitaker, 2008, public domain
        ## don't expect too much --- this is not going to win any prizes.
        ## it's not in the same league visually as dirojed or klappquadrat.
        ## but hey, it's my first 64-byte intro, I don't know what I'm doing.

        ## compile with gas as follows:
        ## as -R morecircles.s -o morecircles.o
        ## objcopy -O binary morecircles.o morecircles.com.0
        ## dd if=morecircles.com.0 of=morecircles.com bs=256 skip=1
        
        ## I've only tested it in DOSBox and in QEMU with FreeDOS;
        ## hope it works elsewhere!

        ## registers are used as follows:
        ## %ax: X-coordinate from center of circle, sin theta
        ## %bx: scratch space
        ## %cx: loop counter
        ## %dx: Y-coordinate from center of circle, cos theta
        ## %di: scratch space used to compute address of pixel
        ## %si: center of circle (as pixel address)
        ## %bp: PRNG state
        ## %cs, %ds, %ss, %sp, %ip: the usual
        ## %es: the video RAM segment
        ## the top stack item: the current color and a counter

        .code16
        .org 0x100
        ## set video mode 13h
start:  mov $0x13, %al
        int $0x10
        ## load video segment into %es
        #mov $seg-2, %bx # if we leave this out, it actually still mostly works
        les (%bx), %bp # we don't care what goes into %bp as long as it's not 0

init:   ## change radius and position pseudorandomly
        mov %bp, %ax            # random seed is in %bp
        imulw (start+1)         # 0xcd13**n % 65536 has period 16384
        mov %ax, %bp

        xor %ax, %si            # get some "randomness" into the position
        xor %dx, %dx            # set angle to 90 degrees
        mov %ax, %cx            # number of iterations: (scaled) radius

loop:   ## turn coordinates in %ax, %dx into offset in %di
        ## first, put %dx/256 * 320 into %di
        ## sin and cos are scaled by 16 so the circle is round, not octagonal
        xor %bx, %bx
        mov %dh, %bh
        mov %bx, %di
        sar $2, %bx
        add %bx, %di

        ## now add x-coordinate, %ax/256
        mov %ax, %bx
        sar $8, %bx
        add %bx, %di

        ## now offset them both by the center of circle
        add %si, %di
        #mov %si, %di    # to see the centers only, to see how bad the RNG is

        ## now set a pixel
        pop %bx                 # we're using whatever was on the stack...
        movb %bh, %es:(%di)     # change color every 256 pixels by using %bh
        inc %bx
        push %bx

        ## this is the circle-drawing trick from HAKMEM
        ## to update sin and cos:
        ## cos += sin * scale
        mov %ax, %bx
        sar $4, %bx
        add %bx, %dx
        ## sin -= cos * scale
        mov %dx, %bx
        sar $4, %bx
        sub %bx, %ax
        
        loop loop
        ## now that we've drawn a circle, let's go to the next one
        jmp init
        
#seg:    .short 0xa000  # (see above about "it actually still mostly works")

## In case you have trouble compiling it:       
## [EMAIL PROTECTED]:~/devel/circles$ xxd < morecircles.com
## 0000000: b013 cd10 c42f 89e8 f72e 0101 89c5 31c6  ...../........1.
## 0000010: 31d2 89c1 31db 88f7 89df c1fb 0201 df89  1...1...........
## 0000020: c3c1 fb08 01df 01f7 5b26 883d 4353 89c3  ........[&.=CS..
## 0000030: c1fb 0401 da89 d3c1 fb04 29d8 e2d6 ebc6  ..........).....

Reply via email to