Par*_*ppa 7 graphics dos retro-computing
我正在做一些有趣的复古编程.我想要创建的是使用EGA图形的DOS游戏,但我在网上找到一个很好的参考有点麻烦.每个谈论做DOS编程的人都假设程序员会使用模式13h,虽然有些页面提到了其他图形模式,但我还没有找到一个讨论正确使用的模式.
这就是我现在要努力的方法:
//------------------------------------------------------------------------------
// DOS graphics test
//
// Thanks to the following links:
// http://gamebub.com/cpp_graphics.php
//
// Written for Digital Mars C compiler to be compiled as a DOS 16 bit binary.
//------------------------------------------------------------------------------
#include <dos.h>
#include <stdio.h>
#define SCREEN_WIDTH 320;
#define SCREEN_HEIGHT 200;
unsigned char far *vram = (unsigned char far *)0xA0000000L;
//------------------------------------------------------------------------------
void set_video_mode(unsigned char mode)
{
union REGS in, out;
in.h.ah = 0;
in.h.al = mode;
int86(0x10, &in, &out);
}
//------------------------------------------------------------------------------
void plot_pixel(unsigned int x, unsigned int y, unsigned char color)
{
// this is wrong because it's only 4 bpp not 8
vram[y * 320 + x] = color;
//vram[((y<<8)+(y<<6))+x] = color;
}
//------------------------------------------------------------------------------
int main(int argc, char* argv[])
{
// EGA 320 x 200 x 16
set_video_mode(0x0d);
for (unsigned char i = 0; i < 255; i++)
{
vram[i] = i;
}
//plot_pixel(10, 10, 1);
getc(stdin);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如果您将set_video_mode()更改为取代0x13而不是0x0d,则此示例代码效果很好,但就像我说我试图在这里获取EGA图形而不是VGA.:)我意识到为了做每像素四位,我要么要么假设plot_pixel同时写入两个像素,要么做一点点twiddling以确保我只写了四位我实际上想要.
我的问题是我没有看到我期望的输出 - 特别是没有颜色!一切似乎都是单色的,这根本不是我想要的.在这种图形模式下使用调色板是否有某种不同的程序比在13h?或者我以某种方式调用了与我想要的完全不同的图形模式?非常感谢指导.
我不认为我的编译器args是相关的,但以防万一:
..\dm\bin\dmc test.c -o test -mm
Run Code Online (Sandbox Code Playgroud)
嗯..不知道这是否是一个值得回答的问题,如果我记得的话,您需要使用inport, inportb, outport,outportb到端口来控制 EGA 寄存器,这取自优秀的 FAQSYSW (大量材料集合,包括图形演示、数学,分形压缩),原始档案可以在这里和这里找到:
3C0h:属性控制器:地址寄存器
位 0-4 要写入端口 3C0h 的数据寄存器的地址。
5 如果设置屏幕输出已启用并且调色板无法修改,
如果禁用清屏输出并且可以修改调色板。
端口3C0h 的特殊之处在于它既是地址寄存器又是数据写入寄存器。
内部触发器会记住它当前是否充当地址或
数据寄存器。对属性控制器的访问必须用 at 分隔
至少250ns。读端口 3dAh 会将触发器重置为地址模式。
3C0h 索引 0-Fh (W):属性:调色板
位 0 原蓝色
1 原色绿色
2原色红
3 二次蓝
4 二次绿
5 次红
3C0h 索引 10h (W):属性:模式控制寄存器
位 0 如果设置则为图形模式,否则为字母数字模式。
1 如果设置为单色模式,否则为彩色模式。
2 个 9 位宽字符(如果设置)。
字符 C0h-DFh 的第 9 位将与
第 8 位。否则它将是背景颜色。
3 如果设置属性位 7 闪烁,则为高强度。
3C0h 索引 11h (W):属性:过扫描颜色寄存器。
位 0-5 屏幕边框颜色。颜色在调色板寄存器中定义。
注意:EGA 要求高分辨率模式下过扫描颜色为 0。
3C0h 索引 12h (W):属性:色彩平面启用寄存器
位 0 位平面 0 如果设置则启用。
1 位平面 1 如果设置则启用。
2 位平面 2 如果设置则启用。
3 位平面 3 如果设置则启用。
4-5 视频状态复用器。仅供诊断使用。
两个属性位出现在输入状态的位 4 和 5 上
寄存器 1 (3dAh)。0:红/蓝,1:蓝(I)/绿,2:红(I)/绿(I)
3C0h 索引 13h (W):属性:水平 PEL 平移寄存器
位 0-3 指示向左移动显示的像素数
值 9bit 文本模式 256 色模式 其他模式
0 1 0 0
1 2 不适用 1
2 3 1 2
3 4 不适用 3
4 5 2 4
5 6 不适用 5
6 7 3 6
7 8 不适用 7
8 0 不适用
3C2h (R):输入状态#0 寄存器
位 4 由杂项输出选择的开关状态
寄存器 3C2h 位 2-3。如果设置则切换为高电平。
5 如果设置,功能连接器 (FEAT0) 的引脚 19 为高电平
6 如果设置,功能连接器 (FEAT1) 的引脚 17 为高电平
7 如果由于垂直回扫而发生设置IRQ 2。应该清除
通过 IRQ 2 中断例程清除端口 3d4h 索引 11h 位 4。
3C2h (W):杂项输出寄存器
位 0 如果设置颜色仿真。基地址=3Dxh,否则为单声道仿真。根据
地址=3Bxh。
1 启用 CPU 对视频内存的访问(如果设置)
2-3 时钟选择。0:14MHz,1:16MHz,2:外部
4 禁用内部视频驱动程序(如果设置)
5 当处于奇数/偶数模式时 选择高 64k 组(如果已设置)
6 水平同步极性。如果设置则为负
7 垂直同步极性。如果设置则为负
位 6-7 表示显示屏上的行数:
0:200行,2:350行
注意:硬件复位时设置为全零。
3C4h 索引 0 (W):定序器:复位
位 0 异步复位(如果清零)
1 同步复位(如果清除)
3C4h 索引 1 (W):定序器:时钟模式
位 0 如果设置的字符时钟为 8 点宽,否则为 9 点。
1 如果设置,CRTC 使用 2/5 的时钟周期,否则使用 4/5。
2 如果设置每隔一个字符加载视频序列化器
时钟周期,其他每个周期。
3 如果设置点时钟为主时钟/2,否则与主时钟相同
(参见 3C2h 位 2-3)。(像素加倍)。
3C4h 索引 2 (W):定序器:映射掩码寄存器
位 0 如果设置,则启用对平面 0 的写入
1 如果设置,则启用对平面 1 的写入
2 如果设置,则启用对平面 2 的写入
3 如果设置,则启用对平面 3 的写入
3C4h 索引 3 (W):定序器:字符映射选择寄存器
位 0-1 如果字符的位 3,则选择 EGA 字符映射 (0..3)
属性明确。
2-3 如果字符的位 3,则选择 EGA 字符映射 (0..3)
属性已设置。
注意:字符映射表的放置方式如下:
地图 0 位于 0k,地图 1 位于 16k,地图 2 位于 32k,地图 3 位于 48k
3C4h 索引 4 (W):定序器:内存模式寄存器
位 0 设置是否处于字母数字模式,在图形模式下清除。
1 设置适配器上的大小是否超过 64kbyte。
2 如果设置,则启用奇/偶寻址模式。奇数/偶数模式放置所有奇数
平面 1&3 中的字节,以及平面 0&2 中的所有偶数字节。
3CAh (W):图形 2 位置
bit 0-1 选择图形控制器应控制哪些位平面
#2. 始终设置为 1。
3CCh (W):图形 1 位置
bit 0-1 选择图形控制器应控制哪些位平面
#1. 始终设置为 0。
3CEh 索引 0 (W):图形:设置/重置寄存器
位 0 如果处于写入模式 0 并且 3CEh 索引 1 的位 0 设置为写入
显示存储器会将字节的平面 0 中的所有位设置为此
位,如果在映射掩码寄存器(3CEh
索引 8)。
1 平面 1 和 3CEh 索引 1 的位 1 相同。
2 平面 2 和 3CEh 索引 1 的位 2 相同。
3 平面 3 和 3CEh 索引 1 的位 3 相同。
3CEh 索引 1 (W):图形:启用设置/重置寄存器
位 0 如果置位,则在写入模式 0 下启用平面 0 的设置/复位。
1 飞机 1 相同。
2 飞机 2 也同样。
3 飞机 3 也是如此。
3CEh 索引 2 (W):图形:颜色比较寄存器
位 0-3 在读取模式 1 下,比较读取的字节地址处的每个像素
如果此颜色和输出中的相应位设置为 1
它们匹配,如果不匹配则为 0。颜色无关寄存器(3CEh 索引 7)
可以从比较中排除位平面。
3CEh 索引 3 (W):图形:数据旋转
位 0-2 在写入数据之前旋转数据的位置数
显示内存。仅在写入模式 0 下有效。
3-4 在写入模式 2 下,该字段控制数据之间的关系
从CPU写入,从先前读取锁存的数据和
写入显示存储器的数据:
0:CPU 数据未修改地写入
1:CPU 数据与锁存数据进行“与”运算
2:CPU 数据与锁存器数据进行或运算。
3:CPU 数据与锁存数据进行异或运算。
3CEh 索引 4 (W):图形:读取地图选择寄存器
bit 0-1 读取模式 0 将读取的平面编号。
3CEh 索引 5 (W):图形:模式寄存器
bit 0-1 写入模式:控制来自 CPU 的数据之前如何转换
正在写入显示内存:
0:模式0作为读-修改-写操作。
首先,读访问加载 EGA 的数据锁存器
视频内存中寻址位置的值。然后写一个
访问将提供目标地址和CPU数据
字节。写入的数据由功能码中的修改
数据循环寄存器(3CEh 索引 3)作为 CPU 的函数
数据和锁存器,然后数据按指定的方式旋转
相同的寄存器。
1:模式 1 用于视频到视频传输。
读访问将加载数据锁存器的内容
视频内存的寻址字节。写访问将写入
锁存器的内容到寻址字节。因此单个
MOVSB指令可以复制源地址字节中的所有像素
到目的地地址。
2:模式 2 将颜色写入寻址字节中的所有像素
视频内存。CPU数据的Bit 0写入平面0等
等等。各个位可以通过启用或禁用
位掩码寄存器(3CEh 索引 8)。
2 如果设置,则强制所有输出进入高阻抗状态。
3 阅读模式
0:根据读取映射从 4 个位平面之一读取数据
选择寄存器(3CEh 索引 4)。
1:返回的数据是占用的8个像素之间的比较
读取字节和颜色比较寄存器中的颜色(3CEh
索引 2)。如果相应像素的颜色被设置一位
与寄存器匹配。
4 如果设置,则启用奇/偶模式(请参见 3C4h 索引 4 位 2)。
5 如果设置,则使用偶数/奇数位对启用 CGA 样式 4 颜色像素。
3CEh 索引 6 (W):图形:杂项寄存器
位 0 如果设置则表示图形模式,否则表示字母数字模式。
1 如果设置,则启用奇/偶模式。
2-3 内存映射:
0:使用A000h-BFFFh
1:使用 A000h-AFFFh EGA 图形模式
2:使用B000h-B7FFh单色模式
3:使用 B800h-BFFFh CGA 模式
3CEh 索引 7 (W):图形:颜色 无关寄存器
位 0 如果清除,则在读取模式 1 下忽略位平面 0。
1 如果清除,则忽略读取模式 1 中的位平面 1。
2 如果清除,则忽略读取模式 1 中的位平面 2。
3 如果清除,则忽略读取模式 1 中的位平面 3。
3CEh 索引 8 (W):图形:位掩码寄存器
位 0-7 如果设置每个位,则可以写入字节中的相应位
显示内存。
3d4h 索引 0 (W):CRTC:水平总计寄存器
位 0-7 水平总字符时钟-2
3d4h 索引 1 (W):CRTC:水平显示结束寄存器
位 0-7 显示的字符时钟数 -1
3d4h 索引 2 (W):CRTC:开始水平消隐寄存器
bit 0-7 水平消隐开始的计数
3d4h 索引 3 (W):CRTC:结束水平消隐寄存器
位 0-4 当字符的最后 5 位完成时,水平消隐结束
计数器等于该字段。
5-6 水平显示后延迟显示开始的字符时钟数
已达到总数。
3d4h 索引 4 (W):CRTC:开始水平回扫寄存器
位 0-7 当字符计数器达到此值时开始水平回扫
价值。
3d4h 索引 5 (W):CRTC:结束水平回扫寄存器
位 0-4 当字符计数器的最后 5 位达到时,水平回扫结束
等于这个值。
5-6 水平显示后延迟显示开始的字符时钟数
回溯。
7 在奇/偶模式下提供平滑滚动。当设定显示开始时
来自奇数字节。
3d4h 索引 6 (W):CRTC:垂直总计寄存器
位 0-7 垂直总计的低 8 位。位 8 位于 3d4h 索引 7 中
位 0。
3d4h 索引 7 (W):CRTC:溢出寄存器
位 0 垂直总计的位 8(3d4h 索引 6)
1 垂直显示结束位 8(3d4h 索引 12h)
2 垂直回扫开始的位 8(3d4h 索引 10h)
3 开始垂直消隐的第 8 位(3d4h 索引 15h)
4 行比较寄存器的第 8 位(3d4h 索引 18h)
3d4h 索引 8 (W):CRTC:预设行扫描寄存器
位 0-4 我们在第一个字符行中向下滚动的行数。
提供平滑的垂直滚动。
3d4h 索引 9 (W):CRTC:最大扫描行寄存器
位 0-4 字符行中的扫描线数 -1。在图形模式下这是
该行在传递到之前显示的次数 (-1)
下一行(0:正常,1:双倍,2:三倍...)。
这与位 7 无关,除了在 CGA 模式下,这似乎
要求该字段为 1 并且位 7 设置为工作。
3d4h 索引 0Ah (W):CRTC:光标起始寄存器
位 0-4 字符内光标的第一条扫描线。
3d4h 索引 0Bh (W): CRTC: 光标结束寄存器
位 0-4 字符内光标的最后一个扫描行
5-6 字符时钟中光标数据的延迟。
3d4h 索引 0Ch (W):CRTC:起始地址高位寄存器
bit 0-7 显示缓冲区起始地址的高 8 位
3d4h 索引 0Dh (W):CRTC:起始地址低位寄存器
bit 0-7 显示缓冲区起始地址的低 8 位
3d4h 索引 0Eh (W): CRTC: 光标位置高位寄存器
bit 0-7 光标地址的高8位
3d4h 索引 0Fh (W): CRTC: 光标位置低位寄存器
bit 0-7 光标地址的低8位
3d4h 索引 10h (R): CRTC: 光笔高位寄存器
bit 0-7 光笔位置地址的高 8 位。
3d4h 索引 10h (W):CRTC:垂直回扫开始寄存器
bit 0-7 垂直回扫开始的低 8 位。垂直回扫开始于
行计数器达到该值。位 8 位于 3d4h 索引 7 中
位 2。
3d4h 索引 11h (R): CRTC: 光笔低位寄存器
bit 0-7 光笔位置地址的低 8 位。
3d4h 索引 11h (W):CRTC:垂直回扫结束寄存器
位 0-3 当行计数器的最后 4 位等于时,垂直回扫结束
这个值。
4 如果清除 清除挂起的垂直中断。
5 垂直中断 (IRQ 2) 如果设置则禁用。通常可以留下
已禁用,但某些系统(包括 PS/2)要求启用它。
3d4h 索引 12h (W):CRTC:垂直显示结束寄存器
bit 0-7 垂直显示结束的低 8 位。当该行出现时,显示结束
计数器达到该值。位 8 位于 3d4h 索引 7 位 1 中。
3d4h 索引 13h (W):CRTC:偏移寄存器
bit 0-7 扫描线中的字节数 / K。其中 K 为 2 表示字节模式,4 表示
字模式,8 表示双字模式。
3d4h 索引 14h (W):CRTC:下划线位置寄存器
位 0-4 字符单元内下划线的位置。
3d4h 索引 15h (W):CRTC:起始垂直空白寄存器
bit 0-7 垂直空白起始的低 8 位。垂直消隐开始于
行计数器达到该值。位 8 位于 3d4h 索引 7 中
位 3。
3d4h 索引 16h (W):CRTC:结束垂直空白寄存器
bit 0-4 当行计数器的低 5 位达到时,垂直消隐停止
等于这个字段。
3d4h 索引 17h (W):CRTC:模式控制寄存器
位 0 如果清除,则使用 CGA 兼容内存寻址系统
通过用字符行扫描计数器位 0 替换地址位 13,
从而为偶数和奇数扫描线创建 2 个组。
1 如果清除则使用 Hercules 兼容内存寻址系统
用字符行扫描计数器位 1 替换地址位 14,
从而创建了4家银行。
2 如果设置,则仅每隔一行增加扫描行计数器。
3 如果设置,则仅每隔一个字符增加内存地址计数器
钟。
4 如果设置,则禁用 EGA 输出驱动器。
5 当处于字模式时,如果该位被设置为其他位置,则位 15 将循环至位 0
位 13 循环到位 0。
6 清除系统是否处于字模式。地址向上旋转 1 位
将位 13 或 15 放入位 0。
7 清除该位将重置显示系统,直到该位被设置为止
再次。
3d4h 索引 18h (W):CRTC:行比较寄存器
bit 0-7 线路比较的低 8 位。当线路计数器达到此值时
值,显示地址换行为0。提供分屏
设施。位 8 位于 3d4h 索引 7 位 4 中。
3dAh (R):输入状态#1 寄存器
位 0 垂直或水平回扫有效(如果设置)
1 光笔已触发(如果设置)
2 光笔开关如果设置则打开
3 正在进行垂直回扫(如果已设置)
4-5 显示 6 种颜色输出中的两种,具体取决于 3C0h 索引 12h。
属性:位 4-5:输出位 4 输出位 5
0 蓝红
1 I 蓝绿
2 我红我绿
3dAh (W):功能控制寄存器
位 0 输出到功能连接器的引脚 21。
1 输出到功能连接器的引脚 20。
| 归档时间: |
|
| 查看次数: |
4592 次 |
| 最近记录: |