146 lines
2.9 KiB
ObjectPascal
Executable file
146 lines
2.9 KiB
ObjectPascal
Executable file
unit Picogus;
|
|
|
|
interface
|
|
uses classes, windows;
|
|
const
|
|
MODE_MAGIC = $00;
|
|
MODE_PROTOCOL = $01;
|
|
MODE_FWSTRING = $02;
|
|
MODE_BOOTMODE = $03;
|
|
|
|
MODE_CDPORT = $60;
|
|
MODE_CDSTATUS = $61;
|
|
MODE_CDERROR = $62;
|
|
MODE_CDLIST = $63;
|
|
MODE_CDLOAD = $64;
|
|
MODE_CDNAME = $65;
|
|
MODE_CDAUTOADV = $66;
|
|
|
|
function DetectPicoGUS: Boolean;
|
|
function ReadModeString(mode: byte): string;
|
|
function ReadCDList: TStringList;
|
|
function SelectedCD: Byte;
|
|
procedure SelectCD(index: Byte);
|
|
|
|
implementation
|
|
const
|
|
CONTROL_PORT = $1d0;
|
|
DATA_PORT_LOW = $1d1;
|
|
DATA_PORT_HIGH = $1d2;
|
|
PICOGUS_PROTOCOL_VER = 4;
|
|
|
|
CDSTATUS_ERROR = $ff;
|
|
CDSTATUS_READY = 2;
|
|
|
|
procedure outb(port: Integer; val: byte);
|
|
begin
|
|
asm
|
|
MOV EDX, port
|
|
MOV AL, val
|
|
OUT DX, AL
|
|
end;
|
|
end;
|
|
|
|
function inb(port: Integer): byte;
|
|
var
|
|
b: byte;
|
|
begin
|
|
asm
|
|
MOV EDX, port
|
|
IN AL, DX
|
|
MOV b, AL
|
|
end;
|
|
Result := b;
|
|
end;
|
|
procedure SetMode(mode: byte);
|
|
begin
|
|
outb(CONTROL_PORT, $cc);
|
|
outb(CONTROL_PORT, mode);
|
|
end;
|
|
|
|
function DetectPicoGUS: Boolean;
|
|
begin
|
|
SetMode(MODE_MAGIC);
|
|
Result := (inb(DATA_PORT_HIGH) = $dd)
|
|
end;
|
|
|
|
function ReadDataPortString: string;
|
|
var
|
|
b: byte;
|
|
begin
|
|
Result := '';
|
|
b := inb(DATA_PORT_HIGH);
|
|
while b <> 0 do
|
|
begin
|
|
Result := Result + Chr(b);
|
|
if b = 4 then Break;
|
|
b := inb(DATA_PORT_HIGH);
|
|
end;
|
|
end;
|
|
|
|
function ReadModeString(mode: byte): string;
|
|
begin
|
|
SetMode(mode);
|
|
Result := ReadDataPortString;
|
|
end;
|
|
|
|
function ReadModeStrings(mode: byte): TStringList;
|
|
var
|
|
str: string;
|
|
begin
|
|
Result := TStringList.Create;
|
|
SetMode(mode);
|
|
repeat
|
|
str := ReadDataPortString;
|
|
if str = #4 then Break;
|
|
Result.Add(str);
|
|
until False;
|
|
end;
|
|
|
|
function AwaitCDStatus: byte;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
Sleep(10);
|
|
SetMode(MODE_CDSTATUS);
|
|
for i := 0 to 100 do
|
|
begin
|
|
Result := inb(DATA_PORT_HIGH);
|
|
if (Result = CDSTATUS_READY) or (Result = CDSTATUS_ERROR) then Break;
|
|
Sleep(1);
|
|
end;
|
|
end;
|
|
|
|
function ReadCDList: TStringList;
|
|
var
|
|
status: Byte;
|
|
begin
|
|
SetMode(MODE_CDLIST);
|
|
status := AwaitCDStatus;
|
|
if status = CDSTATUS_READY then
|
|
Result := ReadModeStrings(MODE_CDLIST)
|
|
else
|
|
begin
|
|
Result := TStringList.Create;
|
|
if status = CDSTATUS_ERROR then
|
|
begin;
|
|
Result.Add('Error reading list:');
|
|
Result.Add(ReadModeString(MODE_CDERROR));
|
|
end
|
|
else
|
|
Result.Add('Timed out reading list');
|
|
end;
|
|
end;
|
|
|
|
function SelectedCD: Byte;
|
|
begin
|
|
SetMode(MODE_CDLOAD);
|
|
Result := inb(DATA_PORT_HIGH);
|
|
end;
|
|
|
|
procedure SelectCD(index: Byte);
|
|
begin
|
|
SetMode(MODE_CDLOAD);
|
|
outb(DATA_PORT_HIGH, index);
|
|
end;
|
|
end.
|