Update for publishing
This commit is contained in:
parent
135fa6c2e8
commit
1a5dc08e5b
2
.gitignore
vendored
2
.gitignore
vendored
@ -2,3 +2,5 @@
|
|||||||
*.err
|
*.err
|
||||||
*.exe
|
*.exe
|
||||||
.ccls-cache/
|
.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
|
Some code to exercise the four logic units of the VGA card in
|
||||||
256 color mode, as well as code that gets SVGA mode
|
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
|
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
|
to help me learn assembler better, as well as get comfortable with
|
||||||
C/asm interop on x86.
|
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.
|
||||||
|
75
asmvga.asm
Normal file
75
asmvga.asm
Normal file
@ -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) {
|
int main(void) {
|
||||||
|
char a;
|
||||||
// activate unchained vga mode
|
// activate unchained vga mode
|
||||||
// place some data into video memory to be latch copied
|
// place some data into video memory to be latch copied
|
||||||
// show off the following
|
// show off the following
|
||||||
@ -93,11 +100,50 @@ int main(void) {
|
|||||||
writeCube(10, 0x00, 0, 3);
|
writeCube(10, 0x00, 0, 3);
|
||||||
writeCube(15, 0x00, 3, 0);
|
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);
|
while (keyboardPressed == 0);
|
||||||
|
|
||||||
_dos_setvect(9, int9Save);
|
_dos_setvect(9, int9Save);
|
||||||
|
|
||||||
enableTextMode();
|
enableTextMode();
|
||||||
|
|
||||||
|
printf("%d\n", a);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
23
simple.c
Normal file
23
simple.c
Normal file
@ -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
Block a user