PgrAm
Experienced Member
Hey all I've been experimenting on different ways to implement transparent sprites in mode X and I came up with a method that I haven't seen before so I thought I might share.
The image is stored in a standard planar format, with palette index zero representing a transparent pixel, and blitted in the following manner:
The outer parts are psuedocode because the code I wrote this for is complicated in a way that isn't really relevant here. The interesting idea is generating a mask based on the pixels value and using the vga card mask to avoid branching. This could also work with a pre-computed mask but I didn't really want to waste the memory for that in my application.
Advantages:
- No branching required
- clipping is fairly straightforward
- can be stored in the same format as opaque sprites
Disadvantages:
- Reads the each pixel twice, I tried keeping the data around in a register but juggling registers made it slower on my target (286) but might be worth it on 8088.
- Requires an out instruction for each pixel, slow on protected mode 386/486
Well that's the gist of it, I'm curious to hear what you guys think of it or if there are any improvements you can think of?
The image is stored in a standard planar format, with palette index zero representing a transparent pixel, and blitted in the following manner:
Code:
outb(SC_INDEX, MAP_MASK);
for each plane:
{
mov cx, VGA_SEGMENT
mov es, cx
lds si, planeData ;the bitmap data
mov ah, planeMask ;the bit mask to enable this plane
mov bx, bmpHeight ;image height
mov dx, SC_DATA
rowLoop :
mov cx, bytes_per_line ;load the pixel counter
pixLoop:
xor al, al ;AL = 0
cmp al, ds : [si] ;if ds:[si] > 0 CF = 1 else CF = 0
sbb al, al ;AL = 0 - CF, AL = 0 if 0, 0xFF if 1
and al, ah ;combine with the plane mask
out dx, al ;output the new mask setting
movsb ;plot the pixel
loop pixLoop ;continue as long as there are pixels left
add si, lineDiff ;add the remaining distance to the edge of the bitmap
add di, screenDiff ;add the remaining distance to the edge of the screen
dec bx ;continue as long as there are rows left
jnz rowLoop
}
The outer parts are psuedocode because the code I wrote this for is complicated in a way that isn't really relevant here. The interesting idea is generating a mask based on the pixels value and using the vga card mask to avoid branching. This could also work with a pre-computed mask but I didn't really want to waste the memory for that in my application.
Advantages:
- No branching required
- clipping is fairly straightforward
- can be stored in the same format as opaque sprites
Disadvantages:
- Reads the each pixel twice, I tried keeping the data around in a register but juggling registers made it slower on my target (286) but might be worth it on 8088.
- Requires an out instruction for each pixel, slow on protected mode 386/486
Well that's the gist of it, I'm curious to hear what you guys think of it or if there are any improvements you can think of?