mirror of
https://github.com/fadden/6502bench.git
synced 2024-10-10 04:23:44 +00:00
Update Apple /// SOS definitions
- Added SOS parameter block formatting. - Normalized SOS call names to values in SOS Reference Manual. - Added SOS call error code constants. - (from robjustice) Added more to A3-IO.sym65. Also, rearranged the ProDOS code slightly. (issue #85)
This commit is contained in:
parent
2ec2917da5
commit
53857089e9
@ -6,12 +6,32 @@
|
|||||||
|
|
||||||
*SYNOPSIS Symbols from hardware I/O areas
|
*SYNOPSIS Symbols from hardware I/O areas
|
||||||
|
|
||||||
KBD @ $C000 ;last key pressed
|
KBD @ $C000 ;last key pressed (KA Data)
|
||||||
KBDFLG @ $C008 ;
|
KBDBFLG @ $C008 ;KB data
|
||||||
KBDSTRB @ $C010 ;RW keyboard strobe
|
KBDSTRB @ $C010 ;RW keyboard strobe
|
||||||
SPKR @ $C030 ;RW toggle speaker (Apple II type)
|
SPKR @ $C030 ;RW toggle speaker (Apple II type)
|
||||||
SPKRIII @ $C040 ;RW beeps speaker (Apple /// type)
|
SPKRIII @ $C040 ;RW beeps speaker (Apple /// type)
|
||||||
JOYRDY @ $C066 ;
|
CLRTEXTGR @ $C050 ;Clear TEXT/GR mode
|
||||||
|
SETTEXTGR @ $C051 ;Set TEXT/GR mode
|
||||||
|
CLRMIX @ $C052 ;Clear MIX mode
|
||||||
|
SETMIX @ $C053 ;Set MIX mode
|
||||||
|
CLRPAGE2 @ $C054 ;Clear PAGE2 mode
|
||||||
|
SETPAGE2 @ $C055 ;Set PAGE2 mode
|
||||||
|
CLRHIRES @ $C056 ;Clear HIRES mode
|
||||||
|
SETHIRES @ $C057 ;Set HIRES mode
|
||||||
|
CLRPDL0 @ $C058 ;Clear PDL0 (A/D Addr 0)
|
||||||
|
SETPDL0 @ $C059 ;Set PDL0 (A/D Addr 0)
|
||||||
|
CLRPDL2 @ $C05A ;Clear PDL2 (A/D Addr 2)
|
||||||
|
SETPDL2 @ $C05B ;Set PDL2 (A/D Addr 2)
|
||||||
|
CLRPDLEN @ $C05C ;Clear PDLEN (A/D Ramp Start)
|
||||||
|
SETPDLEN @ $C05D ;Set PDLEN (A/D Ramp Start)
|
||||||
|
CLRPDL1 @ $C05E ;Clear PDL1 (A/D Addr 1)
|
||||||
|
SETPDL1 @ $C05F ;Set PDL1 (A/D Addr 1)
|
||||||
|
READSW0 @ $C060 ;Read SW0
|
||||||
|
READSW1 @ $C061 ;Read SW1/MGNSW
|
||||||
|
READSW2 @ $C062 ;Read SW2
|
||||||
|
READSW3 @ $C063 ;Read SW3/SCO
|
||||||
|
JOYRDY @ $C066 ;Read PDLOT (A/D Ramp Stop)
|
||||||
CLOCK @ $C070 ;clock
|
CLOCK @ $C070 ;clock
|
||||||
PHASOFF @ $C080 ;
|
PHASOFF @ $C080 ;
|
||||||
PHASON @ $C081 ;
|
PHASON @ $C081 ;
|
||||||
@ -22,24 +42,53 @@ DRV1EN @ $C08B ;
|
|||||||
Q6L @ $C08C ;
|
Q6L @ $C08C ;
|
||||||
Q6H @ $C08D ;
|
Q6H @ $C08D ;
|
||||||
Q7L @ $C08E ;
|
Q7L @ $C08E ;
|
||||||
ACIASTAT @ $C0F1 ;status of ACIA
|
CLRDSA0 @ $C0D0 ;Clear Drive Select A0
|
||||||
|
SETDSA0 @ $C0D1 ;Set Drive Select A0
|
||||||
|
CLRDSA1 @ $C0D2 ;Clear Drive Select A1
|
||||||
|
SETDSA1 @ $C0D3 ;Set Drive Select A1
|
||||||
|
CLREN1INT @ $C0D4 ;
|
||||||
|
SETEN1INT @ $C0D5 ;
|
||||||
|
CLRSIDE2 @ $C0D6 ;
|
||||||
|
SETSIDE2 @ $C0D7 ;
|
||||||
|
CLRSCR @ $C0D8 ;Clear Smooth Scroll (to turn smooth scroll off)
|
||||||
|
SETSCR @ $C0D9 ;Set Smooth Scroll (to turn smooth scroll on)
|
||||||
|
CLRENCWRT @ $C0DA ;Clear Char Set writing
|
||||||
|
SETENCWRT @ $C0DB ;Set Char Set writing
|
||||||
|
CLRENSEL @ $C0DC ;Clear enable silentype port (ENSEL)
|
||||||
|
SETENSEL @ $C0DD ;Set enable silentype port (ENSEL)
|
||||||
|
CLRENSIO @ $C0DE ;Clear enable silentype port (ENSIO)
|
||||||
|
SETENSIO @ $C0DF ;Set enable silentype port (ENSIO)
|
||||||
|
ACIADATA @ $C0F0 ;ACIA DATA REGISTER
|
||||||
|
ACIASTAT @ $C0F1 ;ACIA STATUS REGISTER
|
||||||
|
ACIACMD @ $C0F2 ;ACIA COMMAND REGISTER
|
||||||
|
ACIACTL @ $C0F3 ;ACIA CONTROL REGISTER
|
||||||
|
|
||||||
; Other hardware registers
|
; Other hardware registers
|
||||||
Z_REG @ $FFD0 ;zero page register
|
Z_REG @ $FFD0 ;zero page register
|
||||||
D_DDRB @ $FFD2 ;data direction register B
|
D_DDRB @ $FFD2 ;data direction register B
|
||||||
D_DDRA @ $FFD3 ;data direction register A
|
D_DDRA @ $FFD3 ;data direction register A
|
||||||
TIMER1L @ $FFD8
|
D_TIMER1C_L @ $FFD4
|
||||||
TIMLATCH @ $FFD9
|
D_TIMER1C_H @ $FFD5
|
||||||
D_ACR @ $FFDB
|
D_TIMER1L_L @ $FFD6
|
||||||
D_PCR @ $FFDC
|
D_TIMER1L_H @ $FFD7
|
||||||
D_IFR @ $FFDD
|
D_TIMER2C_L @ $FFD8
|
||||||
D_IER @ $FFDE
|
D_TIMER2C_H @ $FFD9
|
||||||
E_REG @ $FFDF ;environment register
|
D_ACR @ $FFDB
|
||||||
E_IORB @ $FFE0
|
D_PCR @ $FFDC
|
||||||
E_DDRB @ $FFE2
|
D_IFR @ $FFDD
|
||||||
E_DDRA @ $FFE3
|
D_IER @ $FFDE
|
||||||
E_ACR @ $FFEB
|
E_REG @ $FFDF ;environment register
|
||||||
E_PCR @ $FFEC
|
E_IORB @ $FFE0
|
||||||
E_IFR @ $FFED
|
E_DDRB @ $FFE2
|
||||||
E_IER @ $FFEE
|
E_DDRA @ $FFE3
|
||||||
B_REG @ $FFEF ;bank switch register
|
E_TIMER1C_L @ $FFE6
|
||||||
|
E_TIMER1C_H @ $FFE7
|
||||||
|
E_TIMER1L_L @ $FFE6
|
||||||
|
E_TIMER1L_H @ $FFE7
|
||||||
|
E_TIMER2C_L @ $FFE8
|
||||||
|
E_TIMER2C_H @ $FFE9
|
||||||
|
E_ACR @ $FFEB
|
||||||
|
E_PCR @ $FFEC
|
||||||
|
E_IFR @ $FFED
|
||||||
|
E_IER @ $FFEE
|
||||||
|
B_REG @ $FFEF ;bank switch register
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
using PluginCommon;
|
using PluginCommon;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -69,7 +68,7 @@ namespace RuntimeData.Apple {
|
|||||||
private static Param MISC2 = new Param(DataType.NumericLE, DataSubType.Hex, 2);
|
private static Param MISC2 = new Param(DataType.NumericLE, DataSubType.Hex, 2);
|
||||||
private static Param NULL3 = new Param(DataType.NumericLE, DataSubType.Hex, 3);
|
private static Param NULL3 = new Param(DataType.NumericLE, DataSubType.Hex, 3);
|
||||||
|
|
||||||
private Dictionary<int, Param[]> ParamDescrs = new Dictionary<int, Param[]>() {
|
private Dictionary<int, Param[]> mParamDescrs = new Dictionary<int, Param[]>() {
|
||||||
{ 0x40, // ALLOC_INTERRUPT
|
{ 0x40, // ALLOC_INTERRUPT
|
||||||
new Param[] { PARAM_COUNT, MISC1, CODEPTR }
|
new Param[] { PARAM_COUNT, MISC1, CODEPTR }
|
||||||
},
|
},
|
||||||
@ -193,8 +192,8 @@ namespace RuntimeData.Apple {
|
|||||||
// match!
|
// match!
|
||||||
|
|
||||||
byte req = mFileData[offset + 3];
|
byte req = mFileData[offset + 3];
|
||||||
int blockAddr = Util.GetWord(mFileData, offset + 4, 2, false);
|
|
||||||
if (VERBOSE) {
|
if (VERBOSE) {
|
||||||
|
int blockAddr = Util.GetWord(mFileData, offset + 4, 2, false);
|
||||||
mAppRef.DebugLog("P8 MLI call detected at +" + offset.ToString("x6") +
|
mAppRef.DebugLog("P8 MLI call detected at +" + offset.ToString("x6") +
|
||||||
", cmd=$" + req.ToString("x2") + " addr=$" + blockAddr.ToString("x4"));
|
", cmd=$" + req.ToString("x2") + " addr=$" + blockAddr.ToString("x4"));
|
||||||
}
|
}
|
||||||
@ -211,31 +210,8 @@ namespace RuntimeData.Apple {
|
|||||||
DataSubType.Address, null);
|
DataSubType.Address, null);
|
||||||
|
|
||||||
Param[] parms;
|
Param[] parms;
|
||||||
if (ParamDescrs.TryGetValue(req, out parms)) {
|
if (mParamDescrs.TryGetValue(req, out parms)) {
|
||||||
// Try to format the parameter block. Start by figuring out how long it is.
|
FormatParameterBlock(offset, parms);
|
||||||
int blockLen = 0;
|
|
||||||
foreach (Param parm in parms) {
|
|
||||||
blockLen += parm.Length;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Locate it and verify that the entire thing fits in the file.
|
|
||||||
int blockOff = mAddrTrans.AddressToOffset(offset, blockAddr);
|
|
||||||
if (Util.IsInBounds(mFileData, blockOff, blockLen)) {
|
|
||||||
if (VERBOSE) {
|
|
||||||
mAppRef.DebugLog("Formatting P8 block at +" + blockOff.ToString("x6"));
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (Param parm in parms) {
|
|
||||||
// We could try to dereference pathname buffers to see if it's a
|
|
||||||
// fixed value and not an empty buffer, but it's hard for us to
|
|
||||||
// reliably tell the difference between a length-limited pathname
|
|
||||||
// and junk. If the length byte is bad, we run the risk of lumping
|
|
||||||
// a bunch of stuff into the pathname buffer.
|
|
||||||
mAppRef.SetInlineDataFormat(blockOff, parm.Length, parm.Type,
|
|
||||||
parm.SubType, null);
|
|
||||||
blockOff += parm.Length;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req == 0x65) { // QUIT call
|
if (req == 0x65) { // QUIT call
|
||||||
@ -243,5 +219,34 @@ namespace RuntimeData.Apple {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void FormatParameterBlock(int offset, Param[] parms) {
|
||||||
|
int blockAddr = Util.GetWord(mFileData, offset + 4, 2, false);
|
||||||
|
|
||||||
|
// Try to format the parameter block. Start by figuring out how long it is.
|
||||||
|
int blockLen = 0;
|
||||||
|
foreach (Param parm in parms) {
|
||||||
|
blockLen += parm.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Locate it and verify that the entire thing fits in the file.
|
||||||
|
int blockOff = mAddrTrans.AddressToOffset(offset, blockAddr);
|
||||||
|
if (Util.IsInBounds(mFileData, blockOff, blockLen)) {
|
||||||
|
if (VERBOSE) {
|
||||||
|
mAppRef.DebugLog("Formatting P8 block at +" + blockOff.ToString("x6"));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (Param parm in parms) {
|
||||||
|
// We could try to dereference pathname buffers to see if it's a
|
||||||
|
// fixed value and not an empty buffer, but it's hard for us to
|
||||||
|
// reliably tell the difference between a length-limited pathname
|
||||||
|
// and junk. If the length byte is bad, we run the risk of lumping
|
||||||
|
// a bunch of stuff into the pathname buffer.
|
||||||
|
mAppRef.SetInlineDataFormat(blockOff, parm.Length, parm.Type,
|
||||||
|
parm.SubType, null);
|
||||||
|
blockOff += parm.Length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,11 +31,288 @@ parm_block
|
|||||||
namespace RuntimeData.Apple {
|
namespace RuntimeData.Apple {
|
||||||
public class SOS : MarshalByRefObject, IPlugin, IPlugin_SymbolList, IPlugin_InlineBrk {
|
public class SOS : MarshalByRefObject, IPlugin, IPlugin_SymbolList, IPlugin_InlineBrk {
|
||||||
private const string SOS_MLI_TAG = "SOS-MLI-Functions"; // tag used in .sym65 file
|
private const string SOS_MLI_TAG = "SOS-MLI-Functions"; // tag used in .sym65 file
|
||||||
private bool VERBOSE = true;
|
private bool VERBOSE = false;
|
||||||
|
|
||||||
|
#region Parameter block defs
|
||||||
|
|
||||||
|
private class Param {
|
||||||
|
public DataType Type { get; private set; }
|
||||||
|
public DataSubType SubType { get; private set; }
|
||||||
|
public int Length { get; private set; }
|
||||||
|
|
||||||
|
public Param(DataType type, DataSubType subType, int length) {
|
||||||
|
Type = type;
|
||||||
|
SubType = subType;
|
||||||
|
Length = length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static Param[] NO_PARAMS = new Param[0];
|
||||||
|
|
||||||
|
private class ParamSet {
|
||||||
|
public Param[] Required { get; private set; }
|
||||||
|
public Param[] Optional { get; private set; }
|
||||||
|
|
||||||
|
public ParamSet(Param[] required, Param[] optional) {
|
||||||
|
Required = required;
|
||||||
|
Optional = optional;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Param PARAM_COUNT = new Param(DataType.NumericLE, DataSubType.Decimal, 1);
|
||||||
|
private static Param OPTION_LIST = new Param(DataType.NumericLE, DataSubType.Address, 2);
|
||||||
|
private static Param OPTION_LENGTH = new Param(DataType.NumericLE, DataSubType.Decimal, 1);
|
||||||
|
private static Param SEG_ADDR = new Param(DataType.NumericLE, DataSubType.Hex, 2);
|
||||||
|
private static Param SEG_ID = new Param(DataType.NumericLE, DataSubType.Hex, 1);
|
||||||
|
private static Param SEG_NUM = new Param(DataType.NumericLE, DataSubType.Hex, 1);
|
||||||
|
private static Param PATHNAME = new Param(DataType.NumericLE, DataSubType.Address, 2);
|
||||||
|
private static Param TIME_PTR = new Param(DataType.NumericLE, DataSubType.Address, 2);
|
||||||
|
private static Param POINTER = new Param(DataType.NumericLE, DataSubType.Address, 2);
|
||||||
|
private static Param REF_NUM = new Param(DataType.NumericLE, DataSubType.Decimal, 1);
|
||||||
|
private static Param ACCESS = new Param(DataType.NumericLE, DataSubType.Hex, 1);
|
||||||
|
private static Param FILE_POS = new Param(DataType.NumericLE, DataSubType.Hex, 4);
|
||||||
|
private static Param DATE_TIME = new Param(DataType.NumericLE, DataSubType.Hex, 4);
|
||||||
|
private static Param MISC1 = new Param(DataType.NumericLE, DataSubType.Hex, 1);
|
||||||
|
private static Param MISC2 = new Param(DataType.NumericLE, DataSubType.Hex, 2);
|
||||||
|
private static Param MISC4 = new Param(DataType.NumericLE, DataSubType.Hex, 4);
|
||||||
|
private static Param UNUSED7 = new Param(DataType.Dense, DataSubType.None, 7);
|
||||||
|
|
||||||
|
private Dictionary<int, ParamSet> mParamDescrs = new Dictionary<int, ParamSet>() {
|
||||||
|
{ 0x40, // SOS_REQUEST_SEG
|
||||||
|
new ParamSet(
|
||||||
|
new Param[] { PARAM_COUNT, SEG_ADDR, SEG_ADDR, SEG_ID, SEG_NUM },
|
||||||
|
NO_PARAMS
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{ 0x41, // SOS_FIND_SEG
|
||||||
|
new ParamSet(
|
||||||
|
new Param[] { PARAM_COUNT, MISC1, SEG_ID, MISC2, SEG_ADDR, SEG_ADDR, SEG_NUM },
|
||||||
|
NO_PARAMS
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{ 0x42, // SOS_CHANGE_SEG
|
||||||
|
new ParamSet(
|
||||||
|
new Param[] { PARAM_COUNT, SEG_NUM, MISC1, MISC2 },
|
||||||
|
NO_PARAMS
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{ 0x43, // SOS_GET_SEG_INFO
|
||||||
|
new ParamSet(
|
||||||
|
new Param[] { PARAM_COUNT, SEG_NUM, SEG_ADDR, SEG_ADDR, MISC2, SEG_ID },
|
||||||
|
NO_PARAMS
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{ 0x44, // SOS_GET_SEG_NUM
|
||||||
|
new ParamSet(
|
||||||
|
new Param[] { PARAM_COUNT, SEG_ADDR, SEG_NUM },
|
||||||
|
NO_PARAMS
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{ 0x45, // SOS_RELEASE_SEG
|
||||||
|
new ParamSet(
|
||||||
|
new Param[] { PARAM_COUNT, SEG_NUM },
|
||||||
|
NO_PARAMS
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{ 0x60, // SOS_SET_FENCE
|
||||||
|
new ParamSet(
|
||||||
|
new Param[] { PARAM_COUNT, MISC1 },
|
||||||
|
NO_PARAMS
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{ 0x61, // SOS_GET_FENCE
|
||||||
|
new ParamSet(
|
||||||
|
new Param[] { PARAM_COUNT, MISC1 },
|
||||||
|
NO_PARAMS
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{ 0x62, // SOS_SET_TIME
|
||||||
|
new ParamSet(
|
||||||
|
new Param[] { PARAM_COUNT, TIME_PTR },
|
||||||
|
NO_PARAMS
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{ 0x63, // SOS_GET_TIME
|
||||||
|
new ParamSet(
|
||||||
|
new Param[] { PARAM_COUNT, TIME_PTR },
|
||||||
|
NO_PARAMS
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{ 0x64, // SOS_GET_ANALOG
|
||||||
|
new ParamSet(
|
||||||
|
new Param[] { PARAM_COUNT, MISC1, MISC4 },
|
||||||
|
NO_PARAMS
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{ 0x65, // SOS_TERMINATE
|
||||||
|
new ParamSet(
|
||||||
|
NO_PARAMS,
|
||||||
|
NO_PARAMS
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{ 0x80, // SOS_D_READ
|
||||||
|
new ParamSet(
|
||||||
|
new Param[] { PARAM_COUNT, MISC1, POINTER, MISC2, MISC2, MISC2 },
|
||||||
|
NO_PARAMS
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{ 0x81, // SOS_D_WRITE
|
||||||
|
new ParamSet(
|
||||||
|
new Param[] { PARAM_COUNT, MISC1, POINTER, MISC2, MISC2 },
|
||||||
|
NO_PARAMS
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{ 0x82, // SOS_D_STATUS
|
||||||
|
new ParamSet(
|
||||||
|
new Param[] { PARAM_COUNT, MISC1, MISC1, POINTER },
|
||||||
|
NO_PARAMS
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{ 0x83, // SOS_D_CONTROL
|
||||||
|
new ParamSet(
|
||||||
|
new Param[] { PARAM_COUNT, MISC1, MISC1, POINTER },
|
||||||
|
NO_PARAMS
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{ 0x84, // SOS_GET_DEV_NUM
|
||||||
|
new ParamSet(
|
||||||
|
new Param[] { PARAM_COUNT, PATHNAME, MISC1 },
|
||||||
|
NO_PARAMS
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{ 0x85, // SOS_D_INFO
|
||||||
|
new ParamSet(
|
||||||
|
new Param[] { PARAM_COUNT, MISC1, PATHNAME, OPTION_LIST, OPTION_LENGTH },
|
||||||
|
new Param[] { MISC1, MISC1, MISC1, MISC1, MISC1, MISC2, MISC2, MISC2 }
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{ 0xc0, // SOS_CREATE
|
||||||
|
new ParamSet(
|
||||||
|
new Param[] { PARAM_COUNT, PATHNAME, OPTION_LIST, OPTION_LENGTH },
|
||||||
|
new Param[] { MISC1, MISC2, MISC1, FILE_POS }
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{ 0xc1, // SOS_DESTROY
|
||||||
|
new ParamSet(
|
||||||
|
new Param[] { PARAM_COUNT, PATHNAME },
|
||||||
|
NO_PARAMS
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{ 0xc2, // SOS_RENAME
|
||||||
|
new ParamSet(
|
||||||
|
new Param[] { PARAM_COUNT, PATHNAME, PATHNAME },
|
||||||
|
NO_PARAMS
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{ 0xc3, // SOS_SET_FILE_INFO
|
||||||
|
new ParamSet(
|
||||||
|
new Param[] { PARAM_COUNT, PATHNAME, OPTION_LIST, OPTION_LENGTH },
|
||||||
|
new Param[] { ACCESS, MISC1, MISC2, UNUSED7, DATE_TIME }
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{ 0xc4, // SOS_GET_FILE_INFO
|
||||||
|
new ParamSet(
|
||||||
|
new Param[] { PARAM_COUNT, PATHNAME, OPTION_LIST, OPTION_LENGTH },
|
||||||
|
new Param[] { ACCESS, MISC1, MISC2, MISC1, FILE_POS, MISC2, DATE_TIME }
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{ 0xc5, // SOS_VOLUME
|
||||||
|
new ParamSet(
|
||||||
|
new Param[] { PARAM_COUNT, PATHNAME, PATHNAME, MISC2, MISC2 },
|
||||||
|
NO_PARAMS
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{ 0xc6, // SOS_SET_PREFIX
|
||||||
|
new ParamSet(
|
||||||
|
new Param[] { PARAM_COUNT, PATHNAME },
|
||||||
|
NO_PARAMS
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{ 0xc7, // SOS_GET_PREFIX
|
||||||
|
new ParamSet(
|
||||||
|
new Param[] { PARAM_COUNT, PATHNAME, MISC1 },
|
||||||
|
NO_PARAMS
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{ 0xc8, // OPEN
|
||||||
|
new ParamSet(
|
||||||
|
new Param[] { PARAM_COUNT, PATHNAME, REF_NUM, OPTION_LIST, OPTION_LENGTH },
|
||||||
|
new Param[] { ACCESS, MISC1, POINTER }
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{ 0xc9, // SOS_NEWLINE
|
||||||
|
new ParamSet(
|
||||||
|
new Param[] { PARAM_COUNT, REF_NUM, MISC1, MISC1 },
|
||||||
|
NO_PARAMS
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{ 0xca, // SOS_READ
|
||||||
|
new ParamSet(
|
||||||
|
new Param[] { PARAM_COUNT, REF_NUM, POINTER, MISC2, MISC2 },
|
||||||
|
NO_PARAMS
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{ 0xcb, // SOS_WRITE
|
||||||
|
new ParamSet(
|
||||||
|
new Param[] { PARAM_COUNT, REF_NUM, POINTER, MISC2 },
|
||||||
|
NO_PARAMS
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{ 0xcc, // SOS_CLOSE
|
||||||
|
new ParamSet(
|
||||||
|
new Param[] { PARAM_COUNT, REF_NUM },
|
||||||
|
NO_PARAMS
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{ 0xcd, // SOS_FLUSH
|
||||||
|
new ParamSet(
|
||||||
|
new Param[] { PARAM_COUNT, REF_NUM },
|
||||||
|
NO_PARAMS
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{ 0xce, // SOS_SET_MARK
|
||||||
|
new ParamSet(
|
||||||
|
new Param[] { PARAM_COUNT, REF_NUM, MISC1, FILE_POS },
|
||||||
|
NO_PARAMS
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{ 0xcf, // SOS_GET_MARK
|
||||||
|
new ParamSet(
|
||||||
|
new Param[] { PARAM_COUNT, REF_NUM, FILE_POS },
|
||||||
|
NO_PARAMS
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{ 0xd0, // SOS_SET_EOF
|
||||||
|
new ParamSet(
|
||||||
|
new Param[] { PARAM_COUNT, REF_NUM, MISC1, FILE_POS },
|
||||||
|
NO_PARAMS
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{ 0xd1, // SOS_GET_EOF
|
||||||
|
new ParamSet(
|
||||||
|
new Param[] { PARAM_COUNT, REF_NUM, FILE_POS },
|
||||||
|
NO_PARAMS
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{ 0xd2, // SOS_SET_LEVEL
|
||||||
|
new ParamSet(
|
||||||
|
new Param[] { PARAM_COUNT, MISC1 },
|
||||||
|
NO_PARAMS
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{ 0xd3, // SOS_GET_LEVEL
|
||||||
|
new ParamSet(
|
||||||
|
new Param[] { PARAM_COUNT, MISC1 },
|
||||||
|
NO_PARAMS
|
||||||
|
)
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
#endregion Parameter block defs
|
||||||
|
|
||||||
private IApplication mAppRef;
|
private IApplication mAppRef;
|
||||||
private byte[] mFileData;
|
private byte[] mFileData;
|
||||||
private Dictionary<int, PlSymbol> mFunctionList;
|
private Dictionary<int, PlSymbol> mFunctionList;
|
||||||
|
private AddressTranslate mAddrTrans;
|
||||||
|
|
||||||
public string Identifier {
|
public string Identifier {
|
||||||
get {
|
get {
|
||||||
@ -46,6 +323,7 @@ namespace RuntimeData.Apple {
|
|||||||
public void Prepare(IApplication appRef, byte[] fileData, AddressTranslate addrTrans) {
|
public void Prepare(IApplication appRef, byte[] fileData, AddressTranslate addrTrans) {
|
||||||
mAppRef = appRef;
|
mAppRef = appRef;
|
||||||
mFileData = fileData;
|
mFileData = fileData;
|
||||||
|
mAddrTrans = addrTrans;
|
||||||
|
|
||||||
mAppRef.DebugLog("SOS(id=" + AppDomain.CurrentDomain.Id + "): prepare()");
|
mAppRef.DebugLog("SOS(id=" + AppDomain.CurrentDomain.Id + "): prepare()");
|
||||||
//System.Diagnostics.Debugger.Break();
|
//System.Diagnostics.Debugger.Break();
|
||||||
@ -54,6 +332,7 @@ namespace RuntimeData.Apple {
|
|||||||
public void Unprepare() {
|
public void Unprepare() {
|
||||||
mAppRef = null;
|
mAppRef = null;
|
||||||
mFileData = null;
|
mFileData = null;
|
||||||
|
mAddrTrans = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateSymbolList(List<PlSymbol> plSyms) {
|
public void UpdateSymbolList(List<PlSymbol> plSyms) {
|
||||||
@ -89,10 +368,91 @@ namespace RuntimeData.Apple {
|
|||||||
mAppRef.SetInlineDataFormat(offset + 2, 2, DataType.NumericLE,
|
mAppRef.SetInlineDataFormat(offset + 2, 2, DataType.NumericLE,
|
||||||
DataSubType.Address, null);
|
DataSubType.Address, null);
|
||||||
|
|
||||||
// Clear the "no continue" flag unless this is a QUIT call.
|
ParamSet pset;
|
||||||
if (req != 0x65) { // QUIT call
|
if (mParamDescrs.TryGetValue(req, out pset)) {
|
||||||
|
FormatParameterBlock(offset, pset);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear the "no continue" flag unless this is a TERMINATE (QUIT) call.
|
||||||
|
if (req != 0x65) { // SOS_TERMINATE
|
||||||
noContinue = false;
|
noContinue = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void FormatParameterBlock(int offset, ParamSet pset) {
|
||||||
|
if (VERBOSE) {
|
||||||
|
mAppRef.DebugLog("SOSPARM: trying to format SOS at +" + offset.ToString("x6"));
|
||||||
|
}
|
||||||
|
int blockAddr = Util.GetWord(mFileData, offset + 2, 2, false);
|
||||||
|
|
||||||
|
// Try to format the parameter block. Start by figuring out how long the
|
||||||
|
// required portion is.
|
||||||
|
int blockLen = 0;
|
||||||
|
foreach (Param parm in pset.Required) {
|
||||||
|
blockLen += parm.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
int optionListAddr = -1;
|
||||||
|
int optionListLen = -1;
|
||||||
|
|
||||||
|
// Locate it and verify that the entire thing fits in the file.
|
||||||
|
int blockOff = mAddrTrans.AddressToOffset(offset, blockAddr);
|
||||||
|
if (VERBOSE) {
|
||||||
|
mAppRef.DebugLog("SOSPARM: checking addr=$" + blockAddr.ToString("x4") +
|
||||||
|
" off=+" + blockOff.ToString("x6") + " len=" + blockLen);
|
||||||
|
}
|
||||||
|
if (Util.IsInBounds(mFileData, blockOff, blockLen)) {
|
||||||
|
if (VERBOSE) {
|
||||||
|
mAppRef.DebugLog("SOSPARM: formatting block at +" + blockOff.ToString("x6"));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (Param parm in pset.Required) {
|
||||||
|
// Watch for option list parameters.
|
||||||
|
if (parm == OPTION_LIST) {
|
||||||
|
optionListAddr = Util.GetWord(mFileData, blockOff, 2, false);
|
||||||
|
} else if (parm == OPTION_LENGTH) {
|
||||||
|
optionListLen = mFileData[blockOff];
|
||||||
|
}
|
||||||
|
|
||||||
|
// We could try to dereference pathname buffers to see if it's a
|
||||||
|
// fixed value and not an empty buffer, but it's hard for us to
|
||||||
|
// reliably tell the difference between a length-limited pathname
|
||||||
|
// and junk. If the length byte is bad, we run the risk of lumping
|
||||||
|
// a bunch of stuff into the pathname buffer.
|
||||||
|
|
||||||
|
mAppRef.SetInlineDataFormat(blockOff, parm.Length, parm.Type,
|
||||||
|
parm.SubType, null);
|
||||||
|
blockOff += parm.Length;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (VERBOSE) {
|
||||||
|
mAppRef.DebugLog("SOSPARM: NOT in bounds");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (optionListAddr >= 0 && optionListLen > 0) {
|
||||||
|
if (VERBOSE) {
|
||||||
|
mAppRef.DebugLog("SOSPARM: format optionList addr=$" +
|
||||||
|
optionListAddr.ToString("x4") + " len=" + optionListLen);
|
||||||
|
}
|
||||||
|
blockOff = mAddrTrans.AddressToOffset(offset, optionListAddr);
|
||||||
|
if (Util.IsInBounds(mFileData, blockOff, optionListLen)) {
|
||||||
|
// Format the parts of the option list that are present.
|
||||||
|
int usedLen = 0;
|
||||||
|
|
||||||
|
foreach (Param parm in pset.Optional) {
|
||||||
|
if (usedLen + parm.Length > optionListLen) {
|
||||||
|
// This parameter was not provided.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
mAppRef.SetInlineDataFormat(blockOff, parm.Length, parm.Type,
|
||||||
|
parm.SubType, null);
|
||||||
|
blockOff += parm.Length;
|
||||||
|
usedLen += parm.Length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,10 @@
|
|||||||
; See the LICENSE.txt file for distribution terms (Apache 2.0).
|
; See the LICENSE.txt file for distribution terms (Apache 2.0).
|
||||||
;
|
;
|
||||||
; Source: SOS programmer's guide
|
; Source: SOS programmer's guide
|
||||||
; SOS Reference Manual, Volume 2 (Apple 1982)
|
; SOS Reference Manual, Volume 1 & 2 (Apple 1982)
|
||||||
|
; Undocumented Apple /// SOS Features
|
||||||
|
|
||||||
*SYNOPSIS Apple /// Sophisticated Operating System constants.
|
*SYNOPSIS Apple III Sophisticated Operating System constants.
|
||||||
|
|
||||||
; SOS MLI function codes.
|
; SOS MLI function codes.
|
||||||
*TAG SOS-MLI-Functions
|
*TAG SOS-MLI-Functions
|
||||||
@ -21,12 +22,12 @@ SOS_GET_FENCE = $61
|
|||||||
SOS_SET_TIME = $62
|
SOS_SET_TIME = $62
|
||||||
SOS_GET_TIME = $63
|
SOS_GET_TIME = $63
|
||||||
SOS_GET_ANALOG = $64
|
SOS_GET_ANALOG = $64
|
||||||
; SOS ref: "TERMINATE"
|
SOS_TERMINATE = $65
|
||||||
; SOS ref: "No errors are possible. This is an excellent call for beginners."
|
; SOS ref: "No errors are possible. This is an excellent call for beginners."
|
||||||
SOS_QUIT = $65
|
|
||||||
|
|
||||||
SOS_READBLOCK = $80
|
; SOS ref does not describe D_READ and D_WRITE; see Undocumented Features doc.
|
||||||
SOS_WRITEBLOCK = $81
|
SOS_D_READ = $80
|
||||||
|
SOS_D_WRITE = $81
|
||||||
SOS_D_STATUS = $82
|
SOS_D_STATUS = $82
|
||||||
SOS_D_CONTROL = $83
|
SOS_D_CONTROL = $83
|
||||||
SOS_GET_DEV_NUM = $84
|
SOS_GET_DEV_NUM = $84
|
||||||
@ -42,10 +43,8 @@ SOS_SET_PREFIX = $C6
|
|||||||
SOS_GET_PREFIX = $C7
|
SOS_GET_PREFIX = $C7
|
||||||
SOS_OPEN = $C8
|
SOS_OPEN = $C8
|
||||||
SOS_NEWLINE = $C9
|
SOS_NEWLINE = $C9
|
||||||
; SOS ref: "READ"
|
SOS_READ = $CA
|
||||||
SOS_READFILE = $CA
|
SOS_WRITE = $CB
|
||||||
; SOS ref: "WRITE"
|
|
||||||
SOS_WRITEFILE = $CB
|
|
||||||
SOS_CLOSE = $CC
|
SOS_CLOSE = $CC
|
||||||
SOS_FLUSH = $CD
|
SOS_FLUSH = $CD
|
||||||
SOS_SET_MARK = $CE
|
SOS_SET_MARK = $CE
|
||||||
@ -54,3 +53,75 @@ SOS_SET_EOF = $D0
|
|||||||
SOS_GET_EOF = $D1
|
SOS_GET_EOF = $D1
|
||||||
SOS_SET_LEVEL = $D2
|
SOS_SET_LEVEL = $D2
|
||||||
SOS_GET_LEVEL = $D3
|
SOS_GET_LEVEL = $D3
|
||||||
|
|
||||||
|
*TAG
|
||||||
|
|
||||||
|
;
|
||||||
|
; SOS call error codes.
|
||||||
|
;
|
||||||
|
; $01-05: problem with form of call, parameters, or pointers
|
||||||
|
; $10-2f: device call errors
|
||||||
|
; $30-3f: problem with particular device
|
||||||
|
; $40-5a: file call errors
|
||||||
|
; $70-7f: utility call errors
|
||||||
|
; $e0-ef: memory call errors
|
||||||
|
;
|
||||||
|
SOS_BADSCNUM = $01
|
||||||
|
SOS_BADCZPAGE = $02
|
||||||
|
SOS_BADXBYTE = $03
|
||||||
|
SOS_BADSCPCNT = $04
|
||||||
|
SOS_BADSCBNDS = $05
|
||||||
|
|
||||||
|
SOS_DNFERR = $10
|
||||||
|
SOS_BADDNUM = $11
|
||||||
|
SOS_BADREQCODE = $20
|
||||||
|
SOS_BADCTL = $21
|
||||||
|
SOS_BADCTLPARM = $22
|
||||||
|
SOS_NOTOPEN = $23
|
||||||
|
SOS_NORESC = $25
|
||||||
|
SOS_BADOP = $26
|
||||||
|
SOS_IOERR = $27
|
||||||
|
SOS_CRCERR = $2a
|
||||||
|
SOS_NOWRITE = $2b
|
||||||
|
SOS_BYTECNT = $2c
|
||||||
|
SOS_BLKNUM = $2d
|
||||||
|
SOS_DISKSW = $2e
|
||||||
|
|
||||||
|
SOS_BADPATH = $40
|
||||||
|
SOS_CFCBFULL = $41
|
||||||
|
SOS_FCBFULL = $42
|
||||||
|
SOS_BADREFNUM = $43
|
||||||
|
SOS_PNFERR = $44
|
||||||
|
SOS_VNFERR = $45
|
||||||
|
SOS_FNFERR = $46
|
||||||
|
SOS_DUPERR = $47
|
||||||
|
SOS_OVRERR = $48
|
||||||
|
SOS_DIRFULL = $49
|
||||||
|
SOS_CPTERR = $4a
|
||||||
|
SOS_TYPERR = $4b
|
||||||
|
SOS_EOFERR = $4c
|
||||||
|
SOS_POSNERR = $4d
|
||||||
|
SOS_ACCSERR = $4e
|
||||||
|
SOS_BTSERR = $4f
|
||||||
|
SOS_FILBUSY = $50
|
||||||
|
SOS_DIRERR = $51
|
||||||
|
SOS_NOTSOS = $52
|
||||||
|
SOS_BADLSTCNT = $53
|
||||||
|
SOS_OUTOFMEM = $54
|
||||||
|
SOS_BUFTBLFULL = $55
|
||||||
|
SOS_BADSYSBUF = $56
|
||||||
|
SOS_DUPVOL = $57
|
||||||
|
SOS_NOTBLKDEV = $58
|
||||||
|
SOS_LVLERR = $59
|
||||||
|
SOS_BITMAPADR = $5a
|
||||||
|
|
||||||
|
SOS_BADJMODE = $70
|
||||||
|
|
||||||
|
SOS_BADBKPG = $e0
|
||||||
|
SOS_SEGRQDN = $e1
|
||||||
|
SOS_SEGTBLFULL = $e2
|
||||||
|
SOS_BADSEGNUM = $e3
|
||||||
|
SOS_SEGNOTFND = $e4
|
||||||
|
SOS_BADSRCHMODE = $e5
|
||||||
|
SOS_BADCHGMODE = $e6
|
||||||
|
SOS_BADPGCNT = $e7
|
||||||
|
Loading…
Reference in New Issue
Block a user