はじめに
その昔 PC-1246 を買ったので SC61860 のマシン語にとんとご縁のなかった私がひょんな事で PC-1245 を入手したばっかりに今頃になって SC61860 のマシン語でプログラムを書きたくて (以下略)。
あ、SC61860
というのは SHARP の昔のポケコンの CPU の事です。
どうやって覚えるか
実機で覚えようとすると暴走で再入力とかやってられないのでエミュレータ的な何かを作ればいいんじゃね?と思い立ち Delphi で 作ってみる事にした。ちょっと大きめの BrainFuck ですな。
ソース
SC61860 のマシン語を覚えられるくらいの内容。
uSC61860.pas
unit uSC61860;
interface
uses
System.SysUtils, System.Classes;
type
TSC61860 = record
private
function GetData: UInt8;
function GetMem(Index: UInt16): UInt8;
procedure SetMem(Index: UInt16; const Value: UInt8);
public
Memory: array [$0000..$FFFF] of UInt8;
H: UInt8; // Internal Aux. Register
P: UInt8; // Internal RAM Pointer
Q: UInt8; // Internal RAM Pointer
R: UInt8; // Internal RAM Pointer (Stack Pointer)
S: UInt8; // Unused
C: Boolean; // Carry flag
D: UInt8; // Working Register
Z: Boolean; // Zero flag
Port_IA: UInt8;
Port_IB: UInt8;
Port_Control: UInt8;
Port_FO: UInt8;
CaseCnt: UInt8;
RamStart: UInt16;
RamEnd: UInt16;
VramStart: UInt16;
VramEnd: UInt16;
procedure Init;
procedure LoadMemory(const Filename: string; StartAddr: uInt16 = $0000; EndAddr: uInt16 = $FFFF);
procedure SaveMemory(const Filename: string; StartAddr: uInt16 = $0000; EndAddr: uInt16 = $FFFF);
procedure Execute(Address: UInt16 = $0000);
property Data: UInt8 read GetData;
property RAM[Index: UInt16]: UInt8 read GetMem write SetMem;
case Boolean of
False:
(
PC: UInt16; // Program Counter
DP: UInt16; // Data pointer
I: UInt8; // Index Counter
J: UInt8; // Index Counter
A: UInt8; // Accumulator
B: UInt8; // Secondary Accumulator
X: UInt16; // 16 bit RAM pointer (XL = InternalRAM[$04], XH = InternalRAM[$05])
Y: UInt16; // 16 bit RAM pointer (YL = InternalRAM[$06], LH = InternalRAM[$07])
K: UInt8; // General Purpose Pointer
L: UInt8; // General Purpose Pointer
M: UInt8; // General Purpose Pointer
N: UInt8; // General Purpose Pointer
IR: array [$0C..$5B] of UInt8; // Internal RAM - Stack
IA: UInt8; // Port IA
IB: UInt8; // Port IB
FO: UInt8; // Port FO
OUTC: UInt8; // Control Port
);
True:
(
PCL: UInt8;
PCH: UInt8;
DPL: UInt8;
DPH: UInt8;
InternalRAM: array [$00..$5F] of UInt8
);
end;
var
SC: TSC61860;
implementation
{ TSC61860 }
procedure TSC61860.Execute(Address: UInt16 = $0000);
var
MCode: UInt8;
v: UInt8;
w: UInt16;
x1, x2: UInt32;
begin
if Address > 0 then
PC := Address;
MCode := Data;
case MCode of
$00: // LII n
begin
Inc(PC);
I := Data;
end;
$01: // LIJ n
begin
Inc(PC);
J := Data;
end;
$02: // LIA n
begin
Inc(PC);
A := Data;
end;
$03: // LIB n
begin
Inc(PC);
B := Data;
end;
$04: // IX
begin
Q := $00; // need debug
Inc(X);
DP := X;
end;
$05: // DX
begin
Q := $00; // need debug
Dec(X);
DP := X;
end;
$06: // IY
begin
Q := $00; // need debug
Inc(Y);
DP := Y;
end;
$07: // DY
begin
Q := $00; // need debug
Dec(Y);
DP := Y;
end;
$08: // MVW
begin
for var Cnt := 0 to I do
InternalRAM[P + Cnt] := InternalRAM[Q + Cnt];
Inc(P, I + 1);
Inc(Q, I + 1);
end;
$09: // EXW
begin
for var Cnt := 0 to I do
begin
v := InternalRAM[P + Cnt];
InternalRAM[P + Cnt] := InternalRAM[Q + Cnt];
InternalRAM[Q + Cnt] := v;
end;
Inc(P, I + 1);
Inc(Q, I + 1);
end;
$0A: // MVB
begin
for var Cnt := 0 to J do
InternalRAM[P + Cnt] := InternalRAM[Q + Cnt];
Inc(P, J + 1);
Inc(Q, J + 1);
end;
$0B: // EXB
begin
for var Cnt := 0 to J do
begin
v := InternalRAM[P + Cnt];
InternalRAM[P + Cnt] := InternalRAM[Q + Cnt];
InternalRAM[Q + Cnt] := v;
end;
Inc(P, J + 1);
Inc(Q, J + 1);
end;
$0C: // ADN
begin
var Num1: UInt8;
var Num2: UInt8 := (A shr 4) * 10 + (A and $0F);
var Num3: UInt8;
for var Cnt:=0 to I do
begin
Num1 := (InternalRAM[P-Cnt] shr 4) * 10 + (InternalRAM[P-Cnt] and $0F);
Num3 := Num1 + Num2;
Num2 := Num3 div 100;
Num3 := Num3 mod 100;
InternalRAM[P-Cnt] := ((Num3 div 10) shl 4) or (Num3 mod 10);
end;
C := Num2 > 0;
Z := True;
for var Cnt:=0 to I do
begin
if InternalRAM[Cnt] > 0 then
begin
Z := False;
Break;
end;
end;
end;
$0D: // SBN
begin
var Borrow: Boolean := False;
var Num1: UInt8;
var Num2: UInt8 := (A shr 4) * 10 + (A and $0F);
var Num3: UInt8;
for var Cnt:=0 to I do
begin
Num1 := (InternalRAM[P-Cnt] shr 4) * 10 + (InternalRAM[P-Cnt] and $0F);
if Borrow then
Dec(Num1);
Borrow := Num2 > Num1;
if Borrow then
Num1 := Num1 + 100;
Num3 := Num1 - Num2;
Num2 := Num3 div 100;
Num3 := Num3 mod 100;
InternalRAM[P-Cnt] := ((Num3 div 10) shl 4) or (Num3 mod 10);
end;
C := Borrow;
Z := True;
for var Cnt:=0 to I do
begin
if InternalRAM[Cnt] > 0 then
begin
Z := False;
Break;
end;
end;
end;
$0E: // ADW
begin
var Carry: Boolean := False;
var Num1: UInt8;
var Num2: UInt8;
var Num3: UInt8;
for var Cnt:=0 to I do
begin
Num1 := (InternalRAM[P-Cnt] shr 4) * 10 + (InternalRAM[P-Cnt] and $0F);
Num2 := (InternalRAM[Q-Cnt] shr 4) * 10 + (InternalRAM[Q-Cnt] and $0F);
Num3 := Num1 + Num2;
if Carry then
Inc(Num3);
Num2 := Num3 div 100;
Carry := Num2 > 0;
Num3 := Num3 mod 100;
InternalRAM[P-Cnt] := ((Num3 div 10) shl 4) or (Num3 mod 10);
end;
Z := True;
for var Cnt:=0 to I do
begin
if InternalRAM[Cnt] > 0 then
begin
Z := False;
Break;
end;
end;
end;
$0F: // SBW
begin
var Borrow: Boolean := False;
var Num1: UInt8;
var Num2: UInt8;
var Num3: UInt8;
for var Cnt:=0 to I do
begin
Num1 := (InternalRAM[P-Cnt] shr 4) * 10 + (InternalRAM[P-Cnt] and $0F);
Num2 := (InternalRAM[Q-Cnt] shr 4) * 10 + (InternalRAM[Q-Cnt] and $0F);
if Borrow then
Dec(Num1);
Borrow := Num2 > Num1;
if Borrow then
Num1 := Num1 + 100;
Num3 := Num1 - Num2;
InternalRAM[P-Cnt] := ((Num3 div 10) shl 4) or (Num3 mod 10);
end;
Z := True;
for var Cnt:=0 to I do
begin
if InternalRAM[Cnt] > 0 then
begin
Z := False;
Break;
end;
end;
end;
$10: // LIDP n m
begin
Inc(PC);
w := Data shl 8;
Inc(PC);
w := w + Data;
DP := w;
end;
$11: // LIDL n
begin
Inc(PC);
DP := (DP and $FF) or Data;
end;
$12: // LIP n
begin
Inc(PC);
P := (P and $80) or (Data and $7F);
end;
$13: // LIQ n
begin
Inc(PC);
Q := (Q and $80) or (Data and $7F);
end;
$14: // ADB
begin
x1 := (B shl 8) or A;
x2 := (InternalRAM[P + 1] shl 8) or InternalRAM[P];
x1 := x2 + x1;
C := x1 > $FFFF;
Z := x1 = 0;
InternalRAM[P + 1] := (x1 and $FFFF) shr 8;
InternalRAM[P + 0] := (x1 and $00FF);
end;
$15: // SBB
begin
x1 := (B shl 8) or A;
x2 := (InternalRAM[P + 1] shl 8) or InternalRAM[P];
x1 := x2 - x1;
C := x1 > $FFFF; // need debug
Z := x1 = 0;
InternalRAM[P + 1] := (x1 and $FFFF) shr 8;
InternalRAM[P + 0] := (x1 and $00FF);
end;
$16: // (N/A) HALT
;
$17: // (N/A) HALT
;
$18: // MVWD
begin
for var Cnt := 0 to I do
InternalRAM[P + Cnt] := Memory[DP + Cnt];
Inc(DP, I);
Inc(P, I + 1);
end;
$19: // EXWD
begin
for var Cnt := 0 to I do
begin
v := InternalRAM[P + Cnt];
InternalRAM[P + Cnt] := Memory[DP + Cnt];
RAM[DP + Cnt] := v;
end;
Inc(DP, I);
Inc(P, I + 1);
end;
$1A: // MVBD
begin
for var Cnt := 0 to J do
InternalRAM[P + Cnt] := Memory[DP + Cnt];
DP := DP + J;
P := P + J + 1;
end;
$1B: // EXBD
begin
for var Cnt := 0 to J do
begin
v := InternalRAM[P + Cnt];
InternalRAM[P + Cnt] := Memory[DP + Cnt];
RAM[DP + Cnt] := v;
end;
end;
$1C: // SRW
begin
var v2: UInt8;
for var Cnt := 0 to I - 1 do
begin
if Cnt < (I - 1) then
v2 := (InternalRAM[P + Cnt + 1] shl 4)
else
v2 := 0;
InternalRAM[P + Cnt] := (InternalRAM[P + Cnt] shr 4) or v2;
end;
end;
$1D: // SLW
begin
var v2: UInt8;
for var Cnt := 0 to I - 1 do
begin
if Cnt < (I - 1) then
v2 := (InternalRAM[P + Cnt + 1] shr 4)
else
v2 := 0;
InternalRAM[P + Cnt] := (InternalRAM[P + Cnt] shl 4) or v2;
end;
end;
$1E: // FILM
begin
for var Cnt := 0 to I do
InternalRAM[P + Cnt] := A;
Inc(P, I + 1);
end;
$1F: // FILD
begin
for var Cnt := 0 to I do
RAM[DP + Cnt] := A;
Inc(DP, I);
end;
$20: // LDP
begin
A := P;
end;
$21: // LDQ
begin
A := Q;
end;
$22: // LDR
begin
A := R;
end;
$23: // (N/A) CLRA
begin
A := $00;
end;
$24: // IXL
begin
Q := $00; // need debug
Inc(X);
DP := X;
A := Memory[DP];
end;
$25: // DXL
begin
Q := $00; // need debug
Dec(X);
DP := X;
A := Memory[DP];
end;
$26: // IYS
begin
Q := $00; // need debug
Inc(Y);
DP := Y;
RAM[DP] := A;
end;
$27: // DYS
begin
Q := $00; // need debug
Dec(Y);
DP := Y;
RAM[DP] := A;
end;
$28: // JRNZP n
begin
Inc(PC);
if not Z then
Inc(PC, Data - 1);
end;
$29: // JRNZM n
begin
Inc(PC);
if not Z then
Dec(PC, Data + 1);
end;
$2A: // JRNCP n
begin
Inc(PC);
if not C then
Inc(PC, Data - 1);
end;
$2B: // JRNCM n
begin
Inc(PC);
if not C then
Dec(PC, Data + 1);
end;
$2C: // JRP n
begin
Inc(PC);
Inc(PC, Data - 1);
end;
$2D: // JRM n
begin
Inc(PC);
Dec(PC, Data + 1);
end;
$2E: // (N/A) HALT
;
$2F: // LOOP n
begin
Inc(PC);
Dec(InternalRAM[R]);
C := InternalRAM[R] = $FF;
Z := InternalRAM[R] = $00;
if not C then
Inc(PC, Data - 1); // -1
end;
$30: // STP
begin
P := A;
end;
$31: // STQ
begin
Q := A;
end;
$32: // STR
begin
R := A;
end;
$33: // (N/A) NOPT
;
$34: // PUSH
begin
Dec(R);
InternalRAM[R] := A;
end;
$35: // RST / MVWP (未定義命令)
begin
w := (B shl 8) or A;
for var Cnt := 0 to I do
InternalRAM[P + Cnt] := Memory[w + Cnt];
end;
$36: // (N/A) HALT
;
$37: // RTN
begin
PC := (InternalRAM[R+1] shl 8) + InternalRAM[R] -1; // -1
Inc(R, 2);
end;
$38: // JRZP n
begin
Inc(PC);
if Z then
Inc(PC, Data - 1);
end;
$39: // JRZM n
begin
Inc(PC);
if Z then
Dec(PC, Data + 1);
end;
$3A: // JRCP n
begin
Inc(PC);
if C then
Inc(PC, Data - 1);
end;
$3B: // JRCM n
begin
Inc(PC);
if C then
Dec(PC, Data + 1);
end;
$3C: // (N/A) HALT
;
$3D: // (N/A) HALT
;
$3E: // (N/A) HALT
;
$3F: // (N/A) HALT
;
$40: // INCI
begin
w := I + 1;
C := w > $FF;
Z := w = $00;
Q := $00; // need debug
I := w and $FF;
end;
$41: // DECI
begin
w := I - 1;
C := w > $FF; // need debug
Z := w = $00;
Q := $00; // need debug
I := w and $FF;
end;
$42: // INCA
begin
w := A + 1;
C := w > $FF;
Z := w = $00;
Q := $00; // need debug
A := w and $FF;
end;
$43: // DECA
begin
w := A - 1;
C := w > $FF; // need debug
Z := w = $00;
Q := $00; // need debug
A := w and $FF;
end;
$44: // ADM
begin
w := InternalRAM[P] + A;
C := w > $FF; // need debug
Z := w = $00;
InternalRAM[P] := w and $FF;
end;
$45: // SBM
begin
w := InternalRAM[P] - A;
C := w > $FF; // need debug
Z := w = $00;
InternalRAM[P] := w and $FF;
end;
$46: // ANMA
begin
w := InternalRAM[P] and A;
Z := w = $00;
InternalRAM[P] := w and $FF;
end;
$47: // ORMA
begin
w := InternalRAM[P] or A;
Z := w = $00;
InternalRAM[P] := w and $FF;
end;
$48: // INCK
begin
w := K + 1;
C := w > $FF;
Z := w = $00;
Q := $00; // need debug
K := w and $FF;
end;
$49: // DECK
begin
w := K - 1;
C := w > $FF; // need debug
Z := w = $00;
Q := $00; // need debug
K := w and $FF;
end;
$4A: // INCM
begin
w := M + 1;
C := w > $FF;
Z := w = $00;
Q := $00; // need debug
M := w and $FF;
end;
$4B: // DECM
begin
w := M + 1;
C := w > $FF; // need debug
Z := w = $00;
Q := $00; // need debug
M := w and $FF;
end;
$4C: // INA
begin
A := Port_IA;
end;
$4D: // NOPW
begin
end;
$4E: // WAIT n
begin
Inc(PC);
end;
$4F: // CUP / IPXL
begin
// Not implemented yet
end;
$50: // INCP
begin
Inc(P);
end;
$51: // DECP
begin
Dec(P);
end;
$52: // STD
begin
RAM[DP] := A;
end;
$53: // MVDM
begin
RAM[DP] := InternalRAM[P];
end;
$54: // MVMP (READM)
begin
InternalRAM[P] := Memory[PC+1];
end;
$55: // MVMD
begin
InternalRAM[P] := Memory[DP];
end;
$56: // LDPC (READ)
begin
A := Memory[PC+1];
end;
$57: // LDD
begin
A := Memory[DP];
end;
$58: // SWP
begin
v := (A and $F0) shr 4;
A := (A shl 4) or v;
end;
$59: // LDM
begin
A := InternalRAM[P];
end;
$5A: // SL
begin
A := (A shl 1) or Ord(C);
end;
$5B: // POP
begin
A := InternalRAM[R];
Inc(R);
end;
$5C: // (N/A) HALT
;
$5D: // OUTA
begin
Port_IA := IA;
end;
$5E: // (N/A) HALT
;
$5F: // OUTF
begin
Port_FO := FO;
end;
$60: // ANIM n
begin
Inc(PC);
w := InternalRAM[P] and Data;
Z := w = $00;
InternalRAM[P] := w and $FF;
end;
$61: // ORIM n
begin
Inc(PC);
w := InternalRAM[P] or Data;
Z := w = $00;
InternalRAM[P] := w and $FF;
end;
$62: // TSIM n
begin
Inc(PC);
Z := (InternalRAM[P] and Data) = 0;
end;
$63: // CPIM n
begin
Inc(PC);
v := Data;
if InternalRAM[P] > v then
begin
C := False;
Z := False;
end
else if InternalRAM[P] < v then
begin
C := True;
Z := False;
end
else
begin
C := False;
Z := True;
end;
end;
$64: // ANIA n
begin
Inc(PC);
w := A and Data;
Z := w = $00;
A := w and $FF;
end;
$65: // ORIA n
begin
Inc(PC);
w := A or Data;
Z := w = $00;
A := w and $FF;
end;
$66: // TSIA n
begin
Inc(PC);
Z := (A and Data) = 0;
end;
$67: // CPIA n
begin
Inc(PC);
v := Data;
if A > v then
begin
C := False;
Z := False;
end
else if A < v then
begin
C := True;
Z := False;
end
else
begin
C := False;
Z := True;
end;
end;
$68: // (N/A) NOPT
;
$69: // CASE2 (JST)
begin
w := 0;
for var i:=0 to CaseCnt-1 do
begin
Inc(PC);
v := Data;
if A = v then
begin
Inc(PC);
w := Data shl 8;
Inc(PC);
w := w or Data;
PC := w - 1; // -1
Break;
end;
end;
if w = 0 then
begin
Inc(PC);
w := Data shl 8;
Inc(PC);
w := w or Data;
PC := w - 1;
end;
end;
$6A: // (N/A) NOPT
;
$6B: // TEST n
begin
Inc(PC);
// Not implemented yet
end;
$6C: // (N/A) HALT
;
$6D: // (N/A) HALT
;
$6E: // (N/A) HALT
;
$6F: // CDN / IPXH
begin
// Not implemented yet
end;
$70: // ADIM n
begin
Inc(PC);
w := InternalRAM[P] + Data;
C := w > $FF; // need debug
Z := w = $00;
InternalRAM[P] := w and $FF;
end;
$71: // SBIM n
begin
Inc(PC);
w := InternalRAM[P] - Data;
C := w > $FF; // need debug
Z := w = $00;
InternalRAM[P] := w and $FF;
end;
$72: // (N/A) RZ
begin
Z := False;
end;
$73: // (N/A) RZ
begin
Z := False;
end;
$74: // ADIA n
begin
Inc(PC);
w := A + Data;
C := w > $FF; // need debug
Z := w = $00;
A := w and $FF;
end;
$75: // SBIA n
begin
Inc(PC);
w := A - Data;
C := w > $FF; // need debug
Z := w = $00;
A := w and $FF;
end;
$76: // (N/A) RZ
begin
Z := False;
end;
$77: // (N/A) RZ
begin
Z := False;
end;
$78: // CALL n m
begin
w := PC + 3;
InternalRAM[R-1] := w shr 8;
InternalRAM[R-2] := w and $FF00;
Dec(R, 2);
Inc(PC);
w := Data shl 8;
Inc(PC);
w := w + Data;
PC := w - 1; // -1
end;
$79: // JP n m
begin
Inc(PC);
w := Data shl 8;
Inc(PC);
w := w or Data;
PC := w - 1;
end;
$7A: // CASE1 (SETT) l n m
begin
Inc(PC);
CaseCnt := Data;
Inc(PC);
InternalRAM[R-1] := Data;
Inc(PC);
InternalRAM[R-2] := Data;
Dec(R, 2);
end;
$7B: // (N/A) HALT
;
$7C: // JPNZ n m
begin
Inc(PC);
w := Data shl 8;
Inc(PC);
w := w or Data;
if not Z then
PC := w - 1;
end;
$7D: // JPNC n m
begin
Inc(PC);
w := Data shl 8;
Inc(PC);
w := w or Data;
if not C then
PC := w - 1;
end;
$7E: // JPZ n m
begin
Inc(PC);
w := Data shl 8;
Inc(PC);
w := w or Data;
if Z then
PC := w - 1;
end;
$7F: // JPC n m
begin
Inc(PC);
w := Data shl 8;
Inc(PC);
w := w or Data;
if C then
PC := w - 1;
end;
$80..$BF: // LP
begin
P := Data - $80;
end;
$C0: // INCJ
begin
w := J + 1;
C := w > $FF;
Z := w = $00;
Q := $00; // need debug
J := w and $FF;
end;
$C1: // DECJ
begin
w := J - 1;
C := w > $FF; // need debug
Z := w = $00;
Q := $00; // need debug
J := w and $FF;
end;
$C2: // INCB
begin
w := B + 1;
C := w > $FF;
Z := w = $00;
Q := $00; // need debug
B := w and $FF;
end;
$C3: // DECB
begin
w := B - 1;
C := w > $FF; // need debug
Z := w = $00;
Q := $00; // need debug
B := w and $FF;
end;
$C4: // ADCM
begin
w := InternalRAM[P] + A + Ord(C);
C := w > $FF;
Z := w = $00;
InternalRAM[P] := w and $FF;
end;
$C5: // SBCM
begin
w := InternalRAM[P] - A - Ord(C);
C := w > $FF; // need debug
Z := w = $00;
InternalRAM[P] := w and $FF;
end;
$C6: // TSMA (未定義命令)
begin
Z := InternalRAM[P] = A;
end;
$C7: // CPMA
begin
if InternalRAM[P] > A then
begin
C := False;
Z := False;
end
else if InternalRAM[P] < A then
begin
C := True;
Z := False;
end
else
begin
C := False;
Z := True;
end;
end;
$C8: // INCL
begin
w := L + 1;
C := w > $FF;
Z := w = $00;
Q := $00; // need debug
L := w and $FF;
end;
$C9: // DECL
begin
w := L - 1;
C := w > $FF; // need debug
Z := w = $00;
Q := $00; // need debug
L := w and $FF;
end;
$CA: // INCN
begin
w := N + 1;
C := w > $FF;
Z := w = $00;
Q := $00; // need debug
N := w and $FF;
end;
$CB: // DECN
begin
w := N - 1;
C := w > $FF; // need debug
Z := w = $00;
Q := $00; // need debug
N := w and $FF;
end;
$CC: // INB
begin
A := Port_IB;
end;
$CD: // (N/A) NOPW
;
$CE: // NOPT
begin
end;
$CF: // (N/A) HALT
;
$D0: // SC
begin
C := True;
Z := True;
end;
$D1: // RC
begin
C := False;
Z := True;
end;
$D2: // SR
begin
C := Odd(A);
A := A shr 1;
end;
$D3: // WRIT (NOPW)
begin
end;
$D4: // ANID n
begin
Inc(PC);
w := Memory[DP] and Data;
Z := w = $00;
RAM[DP] := w and $FF;
end;
$D5: // ORID n
begin
Inc(PC);
w := Memory[DP] or Data;
Z := w = $00;
RAM[DP] := w and $FF;
end;
$D6: // TSID n
begin
Inc(PC);
Z := (Memory[DP] and Data) = 0;
end;
$D7: // CPID n
begin
Inc(PC);
// Not implemented yet
end;
$D8: // LEAVE
begin
InternalRAM[R] := 0;
end;
$D9: // (N/A) NOPW
;
$DA: // EXAB
begin
v := A;
A := B;
B := v;
end;
$DB: // EXAM
begin
v := A;
A := InternalRAM[P];
InternalRAM[P] := v;
end;
$DC: // (N/A) HALT
;
$DD: // OUTB
begin
Port_IB := IB;
end;
$DE: // (N/A) HALT
;
$DF: // OUTC
begin
Port_Control := OUTC;
end;
$E0..$FF: // CAL n
begin
w := PC + 2;
InternalRAM[R-1] := w shr 8;
InternalRAM[R-2] := w and $FF00;
Dec(R, 2);
w := (Data - $E0) shl 8;
Inc(PC);
w := w + Data;
PC := w - 1; // -1
end;
end;
Inc(PC);
end;
function TSC61860.GetData: UInt8;
begin
result := Memory[PC];
end;
function TSC61860.GetMem(Index: UInt16): UInt8;
begin
result := Memory[Index];
end;
procedure TSC61860.SetMem(Index: UInt16; const Value: UInt8);
begin
if ((Index >= RamStart ) and (Index <= RamEnd )) or
((Index >= VramStart) and (Index <= VramEnd)) then
Memory[Index] := Value;
end;
procedure TSC61860.Init;
begin
Self := Default(TSC61860);
R := $5B;
RamStart := $C000; // PC-1245/50
//RamStart := $B800; // PC-1251
//RamStart := $A000; // PC-1255
//RamStart := $5800; // PC-1260
//RamStart := $4000; // PC-1261/62
//RamStart := $6000; // PC-1350
RamEnd := $C7FF; // PC-1245/5x
//RamEnd := $67FF; // PC-126x
//RamEnd := $6FFF; // PC-1350
VramStart := $F800; // PC-1245/5x
//VramStart := $2000; // PC-126x
//VramStart := $7000; // PC-1350
VramEnd := $F8BF; // PC-1245/5x
//VramEnd := $38BF; // PC-126x
//VramEnd := $7FFF; // PC-1350
end;
procedure TSC61860.LoadMemory(const Filename: string; StartAddr,
EndAddr: uInt16);
begin
var MS := TMemoryStream.Create;
try
MS.LoadFromFile(Filename);
MS.Read(Memory[StartAddr], Succ(EndAddr - StartAddr));
finally
MS.Free;
end;
end;
procedure TSC61860.SaveMemory(const Filename: string; StartAddr,
EndAddr: uInt16);
begin
var MS := TMemoryStream.Create;
try
MS.Write(Memory[StartAddr], Succ(EndAddr - StartAddr));
MS.SaveToFile(Filename);
finally
MS.Free;
end;
end;
end.
キャリーフラグとゼロフラグが適当ではないかもしれない。実機と異なる挙動があったら都度修正する事にする。
使い方
Delphi プロジェクトの uses に uSC61860
を追加して、
uses
..., uSC61860;
適当な場所でコードを書く。
procedure TForm1.Button1Click(Sender: TObject);
begin
SC.Init;
//SC.LoadRom('pc1245mem.bin'); // Start Address 0x0000
Memo1.Lines.Clear;
SC.P := $3F;
SC.Q := $3C;
SC.I := $02;
SC.InternalRAM[$3A] := $01;
SC.InternalRAM[$3B] := $23;
SC.InternalRAM[$3C] := $45;
SC.InternalRAM[$3D] := $45;
SC.InternalRAM[$3E] := $67;
SC.InternalRAM[$3F] := $89;
SC.RAM[$C400] := $0F;
SC.Execute($C400);
Memo1.Lines.Add(Format('3D=%.2x', [SC.InternalRAM[$3D]]));
Memo1.Lines.Add(Format('3E=%.2x', [SC.InternalRAM[$3E]]));
Memo1.Lines.Add(Format('3F=%.2x', [SC.InternalRAM[$3F]]));
...
end;
SC.Execute()
を実行する度に 1 命令分逐次実行される。
おわりに
コードを書いたので、命令セットにどんなものがあるのかはもう覚えた (w
先述のコードを元に、トレーナー兼簡易アセンブラ を作成中。
See also: