Update for publishing

This commit is contained in:
John Bintz 2024-05-27 07:15:18 -04:00
parent 135fa6c2e8
commit 1a5dc08e5b
5 changed files with 187 additions and 1 deletions

2
.gitignore vendored
View File

@ -2,3 +2,5 @@
*.err *.err
*.exe *.exe
.ccls-cache/ .ccls-cache/
ccls.log
capture/

View File

@ -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
View 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
View File

@ -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
View 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, &regs, &regs);
delay(5000);
*((unsigned char far *)0xa0000 + (320 * 10) + 10) = 15;
delay(2000);
regs.w.ax = 0x03;
int386(0x10, &regs, &regs);
return 0;
}