Created
December 16, 2012 22:34
-
-
Save tangentstorm/4313762 to your computer and use it in GitHub Desktop.
just experimenting... migrated to an OO style, stripped out a bunch of error handling and just let pascal handle range checking ( by crashing with a stack trace )
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{$i xpc.inc} | |
unit romVDP; | |
interface uses romFont, SDL, SysUtils, xpc; | |
{This is a simple soft-core of a text-display processor. It features a | |
resolution of 99 columns x 40 rows and 256 colours. There exist three | |
memory areas, the character, attribute and font-data map: | |
character map (4000 byte) | |
attribute map (8000 byte) | |
font data (3584 byte) | |
A character is composed of 14 scan-lines of 8 pixel (8x14) whereby the | |
colour information for each character is stored in two bytes of the | |
attribute map start from offset zero: | |
character map 0000: 65 'A' | |
attribute map 0000: 128 foreground | |
0001: 32 background colour | |
Colour 0 is specially handled. This colour value is replaced with two | |
internal colour registers for global fore and background colours so | |
clearing the attribute map to zero enabled a mode where the fore and | |
background colour is selected by these two internal registers for the | |
whole screen! | |
All three areas can either be mapped into an unified address space or | |
handled seperatly. If the first option is choosen, the character map | |
should begin at address 0, followed by the attribute map at FA0 and | |
the font data at 2EE0. Beware the address mapping in combination with | |
handling values though the abstract tVDPData type cost performance. | |
The aternative way is to handle all maps as seperate memory areas. | |
The choice is by you !} | |
const | |
cScnXRes = 800; | |
cScnYRes = 600; | |
cScnCRes = 8; | |
cChrXRes = 8; | |
cChrYRes = 14; | |
cScnCol = 100 - 1; | |
cScnRow = 40; | |
cScnHLine = $2BC0; | |
cScnAtrMap = $FA0; | |
cScnFntDta = $2EE0; | |
cScnChrSize = $FA0 - $28; | |
cScnAtrSize = $1F40; | |
cScnFntSize = $E00; | |
type | |
tKeymap = array [0..9] of array [0..1] of char; | |
tVDPData = record | |
fontData: taChar; | |
chrMapData: byte; | |
atrMapData: array [0..1] of byte; | |
end; | |
tVDPAttrData = record | |
fg, bg : byte | |
end; | |
vdp = class | |
rFG: int32; | |
rBG: int32; | |
rBR: int32; | |
rHStart: int32; | |
rVStart: int32; | |
aCharMap: array [0..cScnChrSize] of byte; | |
aAttrMap: array [0..cScnAtrSize] of byte; | |
pBitmap: pSDL_SURFACE; | |
constructor Init; | |
function Open: boolean; | |
procedure Close; | |
function ReadAttrMap(adr: int32): tVDPAttrData; | |
procedure WriteAttrMap(adr: int32; Value: tVDPAttrData); | |
function ReadCharMap(adr: int32): byte; | |
procedure WriteCharMap(adr: int32; Value: byte); | |
procedure PlotPixel(adr: int32; Value: byte); | |
procedure RenderChar(adr: int32; Value: byte); | |
procedure RenderDisplay; | |
procedure Display; | |
function PollKeyboard: char; | |
end; | |
implementation | |
var | |
cScnColPal: array [0..255] of array [0..2] of byte; | |
cScnOfsTab: array [0..cScnChrSize] of int32; | |
procedure vdp.plotPixel( adr: int32; Value: byte); | |
var rBitmap: ^int32; | |
begin | |
rBitmap := self.rVStart * cScnXRes + self.rHStart + pBitmap^.pixels + adr; | |
rBitmap^ := Value; | |
end; | |
constructor vdp.Init; | |
var | |
i, j, n, m: int32; | |
begin | |
SDL_INIT(SDL_INIT_VIDEO); | |
SDL_EnableUnicode(1); | |
SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); | |
{transformation table bitmap address -> character offset} | |
m := 0; | |
n := 0; | |
for i := 1 to cScnRow do | |
begin | |
for j := 1 to cScnCol do | |
begin | |
cScnOfsTab[m] := n; | |
n := n + 8; | |
m := m + 1; | |
end; | |
n := i * cScnHLine; | |
end; | |
{init linear grayscale palette} | |
for i := 0 to 255 do | |
begin | |
cScnColPal[i][0] := i; | |
cScnColPal[i][1] := i; | |
cScnColPal[i][2] := i; | |
end; | |
end; | |
function vdp.Open: boolean; | |
var | |
i: int32; | |
begin | |
self.pBitmap := SDL_SETVIDEOMODE(cScnXRes, cScnYRes, cScnCRes, SDL_HWSURFACE); | |
result := self.pBitmap <> nil; | |
self.rFG := 7; | |
self.rBG := 0; | |
self.rBR := 128; | |
for i := 0 to cScnChrSize do self.aCharMap[i] := 0; | |
for i := 0 to cScnAtrSize do self.aAttrMap[i] := 0; | |
self.rHStart := 4; | |
self.rVStart := 18; | |
end; | |
procedure vdp.Close; | |
begin | |
SDL_FREESURFACE(self.pBitmap); | |
SDL_QUIT; | |
end; | |
function vdp.ReadAttrMap(adr: int32): tVDPAttrData; | |
begin | |
adr := adr * 2; | |
Result.bg := self.aAttrMap[adr]; | |
Result.fg := self.aAttrMap[adr + 1]; | |
end; | |
procedure vdp.WriteAttrMap(adr: int32; Value: tVDPAttrData); | |
begin | |
adr := adr * 2; | |
self.aAttrMap[adr] := value.fg; | |
self.aAttrMap[adr + 1] := value.fg; | |
end; | |
function vdp.ReadCharMap(adr: int32): byte; | |
begin | |
result := self.aCharMap[adr] | |
end; | |
procedure vdp.WriteCharMap(adr: int32; Value: byte); | |
begin | |
self.aCharMap[adr] := Value; | |
end; | |
procedure vdp.RenderChar(adr: int32; Value: byte); | |
var | |
attr: tVDPAttrData; | |
chr: taChar; | |
ofs: int32; | |
i, j: int32; | |
fg, bg: int32; | |
begin | |
attr := self.ReadAttrMap(adr); | |
chr := romFontReadChar(self.aCharMap[adr]); | |
if Value > 32 then | |
writeln('( ', system.chr(Value), ': ', attr.fg, '/', attr.bg); | |
if attr.fg = 0 then fg := self.rFG else fg := attr.fg; | |
if attr.fg = 0 then bg := self.rBG else bg := attr.bg; | |
ofs := cScnOfsTab[adr]; | |
for i := 0 to cChrYRes - 1 do begin | |
for j := 0 to cChrXRes - 1 do begin | |
if ((chr[i] shr 7) and 1) = 1 | |
then self.plotPixel(ofs, fg) | |
else self.plotPixel(ofs, bg); | |
inc(ofs); | |
chr[i] := chr[i] shl 1; | |
end; | |
ofs += cScnXRes - cChrXRes; | |
end; | |
end; | |
procedure vdp.RenderDisplay; | |
var | |
i: int32; | |
begin | |
for i := 0 to cScnChrSize do self.RenderChar(i, self.aCharMap[i]); | |
SDL_FLIP(self.pBitmap); | |
end; | |
procedure vdp.Display; inline; | |
begin | |
SDL_FLIP(self.pBitmap); | |
end; | |
function vdp.PollKeyboard: char; | |
var | |
done: boolean; | |
evt: pSDL_Event; | |
key: TSDLKey; | |
ch: char; | |
begin | |
done := False; | |
new(evt); | |
repeat | |
if SDL_PollEvent(evt) = 1 then | |
case evt^.type_ of | |
SDL_KEYDOWN: | |
begin | |
key := evt^.key.keysym.unicode; | |
if key in [1 .. 255] then | |
begin | |
ch := chr(key); | |
done := True; | |
result := ch; | |
end; | |
end; | |
SDL_QUITEV: halt; | |
end; | |
until done; | |
end; | |
begin | |
end. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment