Update for publishing
This commit is contained in:
parent
135fa6c2e8
commit
1a5dc08e5b
|
@ -2,3 +2,5 @@
|
|||
*.err
|
||||
*.exe
|
||||
.ccls-cache/
|
||||
ccls.log
|
||||
capture/
|
||||
|
|
42
README.md
42
README.md
|
@ -1,7 +1,47 @@
|
|||
# VGA logic units in 256 colors and SVGA mode usage
|
||||
# VGA and SVGA code examples
|
||||
|
||||
Some code to exercise the four logic units of the VGA card in
|
||||
256 color mode, as well as code that gets SVGA mode
|
||||
working. Most of this is in C, but some of it's in assembler
|
||||
to help me learn assembler better, as well as get comfortable with
|
||||
C/asm interop on x86.
|
||||
|
||||
Check out the video I wrote all this code to support:
|
||||
https://makertube.net/w/sQSZJcxh8CRuMZWVh8Q6aF
|
||||
|
||||
Read more about my project The Industrious Rabbit at
|
||||
https://theindustriousrabbit.com/
|
||||
|
||||
## Building
|
||||
|
||||
You'll need [Open Watcom 2.0](https://open-watcom.github.io/). You can use
|
||||
`wmake` on the `makefile` to build some of these, and
|
||||
`wcl386 -q -bt=dos -l=dos4g <c or asm files>` for the others. All of these
|
||||
run in 32-bit protected mode within a DPMI wrapper and in a flat memory space,
|
||||
because I *really don't* want to deal with segment:offset addressing.
|
||||
|
||||
## What's here
|
||||
|
||||
### `main.c` and `vga.asm`
|
||||
|
||||
C code that exercises a bunch of the VGA registers by transforming a colored
|
||||
cube of all 256 VGA colors in different ways. The display is set to unchained
|
||||
mode. Lots of latch copies and trasnforming data with stuff in the latches.
|
||||
The core of the transformation code is in `vga.asm`, which is also where the
|
||||
keyboard handler for exiting the program lives.
|
||||
|
||||
### `svga.c`, `vesa.c`, `dpmi.c`, and `bmp.c`
|
||||
|
||||
Display a bitmap in a 640x480x256 SVGA mode. Trying to find a fully working
|
||||
SVGA, DOS Protected Mode Interface, and VESA example was tough, so hopefully
|
||||
this will help you out if you're trying to do the same thing!
|
||||
|
||||
### `simple.c` and `asmvga.asm`
|
||||
|
||||
These both draw a single dot on the screen, but in different ways:
|
||||
|
||||
* `simple.c` draws the dot directly to VGA memory
|
||||
* `asmvga.asm` allocates a block of RAM, writes the pixel there, then
|
||||
shovels the data from the RAM into the VGA card with `rep movsb`, which
|
||||
is the procedure a game would use to draw to a non-VGA RAM buffer and then
|
||||
copy when done.
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
.386
|
||||
.model flat,c
|
||||
.STACK 100h
|
||||
|
||||
.data
|
||||
bufferPtr dword 0
|
||||
bufferHandleLow word 0
|
||||
bufferHandleHigh word 0
|
||||
|
||||
.code
|
||||
|
||||
main PROC
|
||||
; we need es the same as ds for movsb
|
||||
mov ax,ds
|
||||
mov es,ax
|
||||
|
||||
; place to catch bpint
|
||||
mov cx,0fh
|
||||
mov dx,1
|
||||
mov ah,86h
|
||||
int 15h
|
||||
|
||||
; reserve ram
|
||||
mov ax,0501h
|
||||
mov bx,0
|
||||
mov cx,64000
|
||||
int 31h
|
||||
shl ebx,16
|
||||
mov bx,cx
|
||||
mov bufferPtr,ebx
|
||||
mov bufferHandleLow,di
|
||||
mov bufferHandleHigh,si
|
||||
|
||||
; clear ram
|
||||
mov ecx,64000
|
||||
mov edi,ebx
|
||||
mov al,0
|
||||
rep stosb
|
||||
|
||||
; write pixel 15 at (10,10)
|
||||
mov edi,ebx
|
||||
add edi,320*10+10
|
||||
mov al,15
|
||||
stosb
|
||||
|
||||
; switch to 320x200 256 color chunky chained mode
|
||||
mov ah,0h
|
||||
mov al,13h
|
||||
int 10h
|
||||
|
||||
; copy buffer to vga card
|
||||
mov esi,bufferPtr
|
||||
mov edi,0a0000h
|
||||
mov ecx,320*200
|
||||
rep movsb
|
||||
|
||||
; wait 5s
|
||||
mov cx,0fh
|
||||
mov dx,5000
|
||||
mov ah,86h
|
||||
int 15h
|
||||
|
||||
; free memory
|
||||
mov ax,0502h
|
||||
mov si,bufferHandleHigh
|
||||
mov di,bufferHandleLow
|
||||
int 31h
|
||||
|
||||
; terminate with return code
|
||||
mov ah,4Ch
|
||||
mov al,00h
|
||||
int 21h
|
||||
main ENDP
|
||||
|
||||
END main
|
46
main.c
46
main.c
|
@ -47,7 +47,14 @@ void populateExampleCube(void) {
|
|||
}
|
||||
}
|
||||
|
||||
void forceReadVGA(char far *vga);
|
||||
#pragma aux forceReadVGA = \
|
||||
"mov bl,BYTE PTR [eax]" \
|
||||
parm [ eax ] \
|
||||
modify [ bl ];
|
||||
|
||||
int main(void) {
|
||||
char a;
|
||||
// activate unchained vga mode
|
||||
// place some data into video memory to be latch copied
|
||||
// show off the following
|
||||
|
@ -93,11 +100,50 @@ int main(void) {
|
|||
writeCube(10, 0x00, 0, 3);
|
||||
writeCube(15, 0x00, 3, 0);
|
||||
|
||||
outpw(0x3ce, 0x0000);
|
||||
outpw(0x3ce, 0x0001);
|
||||
outpw(0x3ce, 0x0002);
|
||||
outpw(0x3ce, 0x0003);
|
||||
/*
|
||||
outpw(0x3ce, 0x0005);
|
||||
*/
|
||||
outpw(0x3ce, 0xff08);
|
||||
outpw(0x3c4, 0x0f02);
|
||||
/*
|
||||
outp(0x3ce, 0x08);
|
||||
outp(0x3cf, 0xff);
|
||||
*/
|
||||
|
||||
VGA[0] = 255;
|
||||
// read the above. if you're reading the value and doing nothing with it, watcom will optimize it out
|
||||
forceReadVGA(VGA);
|
||||
|
||||
//outp(0x3cf, 0xff);
|
||||
// all from latches
|
||||
outpw(0x3ce, 0x0008);
|
||||
|
||||
VGA[2] = 127;
|
||||
|
||||
// all but the first bit from incoming data
|
||||
outpw(0x3ce, 0xfe08);
|
||||
|
||||
VGA[4] = 2;
|
||||
|
||||
a = VGA[4];
|
||||
|
||||
/*
|
||||
outp(0x3cf, 0x00);
|
||||
|
||||
VGA[410] = 0;
|
||||
*/
|
||||
|
||||
while (keyboardPressed == 0);
|
||||
|
||||
_dos_setvect(9, int9Save);
|
||||
|
||||
enableTextMode();
|
||||
|
||||
printf("%d\n", a);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
#include <i86.h>
|
||||
#include <dos.h>
|
||||
#include <conio.h>
|
||||
|
||||
int main(void) {
|
||||
union REGS regs;
|
||||
|
||||
regs.w.ax = 0x13;
|
||||
|
||||
int386(0x10, ®s, ®s);
|
||||
|
||||
delay(5000);
|
||||
|
||||
*((unsigned char far *)0xa0000 + (320 * 10) + 10) = 15;
|
||||
|
||||
delay(2000);
|
||||
|
||||
regs.w.ax = 0x03;
|
||||
|
||||
int386(0x10, ®s, ®s);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue