initial commit
authorJohn Tsiombikas <nuclear@member.fsf.org>
Sat, 31 Aug 2024 02:09:34 +0000 (05:09 +0300)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Sat, 31 Aug 2024 02:09:34 +0000 (05:09 +0300)
.gitignore [new file with mode: 0644]
Makefile [new file with mode: 0644]
README.md [new file with mode: 0644]
packsrc.bat [new file with mode: 0644]
pull.bat [new file with mode: 0644]
src/dos/main.c [new file with mode: 0644]
src/dos/video.asm [new file with mode: 0644]
src/video.h [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..d433bc9
--- /dev/null
@@ -0,0 +1,8 @@
+*.o
+*.obj
+*.d
+*.swp
+*.com
+*.lnk
+*.map
+*.zip
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..9f4970d
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,42 @@
+!ifdef __UNIX__
+obj = src/dos/main.obj src/dos/video.obj
+!else
+obj = src\dos\main.obj src\dos\video.obj
+!endif
+bin = game.com
+
+opt = -3 -otexan
+dbg = -d3
+
+incpath = -Isrc
+asminc = -i src
+
+AS = nasm
+CC = wcc
+LD = wlink
+ASFLAGS = -fobj $(asminc)
+CFLAGS = $(dbg) $(opt) $(def) -ms -s -zq -bt=com $(incpath)
+
+$(bin): $(obj)
+       %write objects.lnk $(obj)
+       $(LD) name $@ debug all system com option map file { @objects }
+
+.c: src;src/dos
+.asm: src;src/dos
+
+.c.obj: .autodepend
+       $(CC) -fo=$@ $(CFLAGS) $[*
+
+.asm.obj:
+       $(AS) $(ASFLAGS) -o $@ $[*.asm
+
+!ifdef __UNIX__
+clean: .symbolic
+       rm -f $(obj)
+       rm -f $(bin)
+!else
+clean: .symbolic
+       del src\*.obj
+       del src\dos\*.obj
+       del $(bin)
+!endif
diff --git a/README.md b/README.md
new file mode 100644 (file)
index 0000000..c76dfa9
--- /dev/null
+++ b/README.md
@@ -0,0 +1 @@
+comjam24 entry
diff --git a/packsrc.bat b/packsrc.bat
new file mode 100644 (file)
index 0000000..208a9f8
--- /dev/null
@@ -0,0 +1,2 @@
+del dossrc.zip\r
+zip -r dossrc.zip . -i *.c -i *.asm -i *akefile* -i *.bat\r
diff --git a/pull.bat b/pull.bat
new file mode 100644 (file)
index 0000000..c48885b
--- /dev/null
+++ b/pull.bat
@@ -0,0 +1,9 @@
+rsync -v 192.168.0.4::comjam24/Makefile Makefile\r
+rsync -v 192.168.0.4::comjam24/*.bat .\r
+mkdir src\r
+rsync -v 192.168.0.4::comjam24/src/*.c src\r
+rsync -v 192.168.0.4::comjam24/src/*.h src\r
+mkdir src\dos\r
+rsync -v 192.168.0.4::comjam24/src/dos/*.c src/dos\r
+rsync -v 192.168.0.4::comjam24/src/dos/*.h src/dos\r
+rsync -v 192.168.0.4::comjam24/src/dos/*.asm src/dos\r
diff --git a/src/dos/main.c b/src/dos/main.c
new file mode 100644 (file)
index 0000000..962ed5d
--- /dev/null
@@ -0,0 +1,46 @@
+#include <conio.h>
+#include "video.h"
+
+static void draw(void);
+void handle_key(int key);
+
+static int quit;
+
+
+int main(void)
+{
+       init_video();
+
+       for(;;) {
+               while(kbhit()) {
+                       int c = getch();
+                       handle_key(c);
+                       if(quit) goto end;
+               }
+
+               draw();
+       }
+
+end:
+       close_video();
+       return 0;
+}
+
+static void draw(void)
+{
+       vid_clearfb();
+
+
+       vid_pgflip(1);
+}
+
+
+void handle_key(int key)
+{
+       switch(key) {
+       case 27:
+               quit = 1;
+               break;
+       }
+}
+
diff --git a/src/dos/video.asm b/src/dos/video.asm
new file mode 100644 (file)
index 0000000..9d6a52b
--- /dev/null
@@ -0,0 +1,156 @@
+       bits 16
+
+segment _TEXT class=CODE
+
+SC_ADDR                equ 3c4h        ; sequence controller address register
+CRTC_ADDR      equ 3d4h        ; CRTC address register
+
+       global init_video_
+init_video_:
+       pusha
+       mov ax, 13h
+       int 10h
+
+       ; disable chain-4 (bit 3 of sequencer memory mode register [4])
+       mov dx, SC_ADDR
+       mov ax, 0604h
+       out dx, ax
+       ; disable double-word addressing (bit 6 of CRTC underline location
+       ; register [14h])
+       mov dx, CRTC_ADDR
+       mov ax, 0014h
+       out dx, ax
+       ; enable byte mode address generation (bit 6 of CRTC mode control
+       ; register [17h])
+       mov ax, 0e317h
+       out dx, ax
+
+       ; clear all 256kb of vram
+       mov dx, SC_ADDR
+       mov ax, 0f02h   ; map mask reg (2) enable all planes (f)
+       out dx, ax
+       push word 0a000h
+       pop es
+       xor di, di
+       mov ecx, 3fffh
+       xor eax, eax
+       rep stosd
+
+       ; initial back buffer is the second page (far pointer)
+       mov word [_vid_backbuf + 2], 0a400h
+       mov word [_vid_backbuf], 0
+
+       ; set initial scanout address to page 0. if we never pageflip, we
+       ; can just draw to a0000 as usual and it will be visible.
+       ; This also makes sure the low byte is 0, because we're not touching it
+       ; while page flipping; we flip by toggling a bit in the high byte.
+       mov dx, 3dah
+.invb: in al, dx
+       and al, 8
+       jnz .invb
+       mov dx, CRTC_ADDR
+       mov ax, 000ch   ; 0ch: start address high register
+       out dx, ax
+       mov ax, 000dh   ; 0dh: start address low register
+       out dx, ax
+
+       popa
+       ret
+
+       global close_video_
+close_video_:
+       push ax
+       mov ax, 3
+       int 10h
+       pop ax
+       ret
+
+       global vid_setpalent_
+vid_setpalent_:
+       mov ah, dl
+       mov dx, 3c8h
+       out dx, al
+       inc dx
+       mov al, ah
+       shr al, 2
+       out dx, al
+       mov al, bl
+       shr al, 2
+       out dx, al
+       mov al, cl
+       shr al, 2
+       out dx, al
+       ret
+
+       ; clear the framebuffer 4 pixels at a time
+       global vid_clearfb_
+vid_clearfb_:
+       push eax
+       push ecx
+       push dx
+       push di
+       mov dx, SC_ADDR
+       mov ax, 0f02h   ; map mask reg (2) enable all planes (f)
+       out dx, ax
+       mov ax, [_vid_backbuf + 2]
+       mov es, ax
+       mov di, [_vid_backbuf]
+       mov ecx, 4000   ; 4000 dwords * 4 planes * 4 bytes = 64000 pixels
+       xor eax, eax
+       rep stosd
+       pop di
+       pop dx
+       pop ecx
+       pop eax
+       ret
+
+
+       ; vid_backbuf is the far pointer of the back buffer in video RAM
+       ; either a000:0000 or a400:0000. Flipping bit 10 of the segment,
+       ; switches between them, and the low 16bits of the linear address,
+       ; gives the CRTC start address.
+
+       global vid_pgflip_
+vid_pgflip_:
+       push bx
+       push dx
+       push ax
+       ; set the current backbuffer as the new CRTC scanout start address
+       mov ax, [_vid_backbuf + 2]
+       shl ax, 4
+       mov al, 0ch             ; CRTC start address high register
+       mov bx, ax
+
+       ; only proceed if we're out of vblank, otherwise we might think we've
+       ; set a new scanout address, but it might not be latched until the next
+       ; vblank, and we'll be drawing over the scanout buffer in the meantime.
+       mov dx, 3dah
+.wait: in al, dx
+       and al, 8
+       jnz .wait
+
+       mov dx, CRTC_ADDR
+       mov ax, bx              ; get previously prepared reg addr and value
+       out dx, ax
+
+       pop ax
+       test ax, ax
+       jz .done
+       ; we were already out of vblank, wait until we're in vblank
+       mov dx, 3dah
+.novb: in al, dx
+       and al, 8
+       jz .novb
+.done:
+       ; flip the backbuffer pointer
+       xor word [_vid_backbuf + 2], 400h
+       pop dx
+       pop bx
+       ret
+
+       section .data
+
+       align 4
+       global _vid_backbuf
+_vid_backbuf dd 0
+xyzzy  dd 01010101h
diff --git a/src/video.h b/src/video.h
new file mode 100644 (file)
index 0000000..48070b4
--- /dev/null
@@ -0,0 +1,46 @@
+#ifndef VIDEO_H_
+#define VIDEO_H_
+
+extern unsigned char far *vid_backbuf;
+
+void init_video(void);
+void close_video(void);
+void vid_setpalent(int idx, int r, int g, int b);
+
+void vid_clearfb(void);
+void vid_clearfb_rect(int x, int y, int w, int h);
+void vid_pgflip(int vsync);
+
+void vid_setmask(unsigned int mask);
+#pragma aux vid_setmask = \
+       "mov dx, 0x3c4" \
+       "mov ah, al" \
+       "mov al, 2" \
+       "out dx, ax" \
+       parm [ax] \
+       modify [ax dx];
+
+void vid_wait_vblank(void);
+#pragma aux vid_wait_vblank = \
+       "mov dx, 0x3da" \
+       "waitvb:" \
+       "in al, dx" \
+       "and al, 8" \
+       "jz waitvb" \
+       modify [al dx];
+
+void vid_vsync(void);
+#pragma aux vid_vsync = \
+       "mov dx, 0x3da" \
+       "invb:" \
+       "in al, dx" \
+       "and al, 8" \
+       "jnz invb" \
+       "waitvb:" \
+       "in al, dx" \
+       "and al, 8" \
+       "jz waitvb" \
+       modify [al dx];
+
+
+#endif /* VIDEO_H_ */