mirror of
https://github.com/fadden/6502bench.git
synced 2025-04-09 14:39:15 +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
|
||||
|
||||
KBD @ $C000 ;last key pressed
|
||||
KBDFLG @ $C008 ;
|
||||
KBD @ $C000 ;last key pressed (KA Data)
|
||||
KBDBFLG @ $C008 ;KB data
|
||||
KBDSTRB @ $C010 ;RW keyboard strobe
|
||||
SPKR @ $C030 ;RW toggle speaker (Apple II 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
|
||||
PHASOFF @ $C080 ;
|
||||
PHASON @ $C081 ;
|
||||
@ -22,24 +42,53 @@ DRV1EN @ $C08B ;
|
||||
Q6L @ $C08C ;
|
||||
Q6H @ $C08D ;
|
||||
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
|
||||
Z_REG @ $FFD0 ;zero page register
|
||||
D_DDRB @ $FFD2 ;data direction register B
|
||||
D_DDRA @ $FFD3 ;data direction register A
|
||||
TIMER1L @ $FFD8
|
||||
TIMLATCH @ $FFD9
|
||||
D_ACR @ $FFDB
|
||||
D_PCR @ $FFDC
|
||||
D_IFR @ $FFDD
|
||||
D_IER @ $FFDE
|
||||
E_REG @ $FFDF ;environment register
|
||||
E_IORB @ $FFE0
|
||||
E_DDRB @ $FFE2
|
||||
E_DDRA @ $FFE3
|
||||
E_ACR @ $FFEB
|
||||
E_PCR @ $FFEC
|
||||
E_IFR @ $FFED
|
||||
E_IER @ $FFEE
|
||||
B_REG @ $FFEF ;bank switch register
|
||||
Z_REG @ $FFD0 ;zero page register
|
||||
D_DDRB @ $FFD2 ;data direction register B
|
||||
D_DDRA @ $FFD3 ;data direction register A
|
||||
D_TIMER1C_L @ $FFD4
|
||||
D_TIMER1C_H @ $FFD5
|
||||
D_TIMER1L_L @ $FFD6
|
||||
D_TIMER1L_H @ $FFD7
|
||||
D_TIMER2C_L @ $FFD8
|
||||
D_TIMER2C_H @ $FFD9
|
||||
D_ACR @ $FFDB
|
||||
D_PCR @ $FFDC
|
||||
D_IFR @ $FFDD
|
||||
D_IER @ $FFDE
|
||||
E_REG @ $FFDF ;environment register
|
||||
E_IORB @ $FFE0
|
||||
E_DDRB @ $FFE2
|
||||
E_DDRA @ $FFE3
|
||||
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.Collections.Generic;
|
||||
|
||||
using PluginCommon;
|
||||
|
||||
/*
|
||||
@ -69,7 +68,7 @@ namespace RuntimeData.Apple {
|
||||
private static Param MISC2 = new Param(DataType.NumericLE, DataSubType.Hex, 2);
|
||||
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
|
||||
new Param[] { PARAM_COUNT, MISC1, CODEPTR }
|
||||
},
|
||||
@ -193,8 +192,8 @@ namespace RuntimeData.Apple {
|
||||
// match!
|
||||
|
||||
byte req = mFileData[offset + 3];
|
||||
int blockAddr = Util.GetWord(mFileData, offset + 4, 2, false);
|
||||
if (VERBOSE) {
|
||||
int blockAddr = Util.GetWord(mFileData, offset + 4, 2, false);
|
||||
mAppRef.DebugLog("P8 MLI call detected at +" + offset.ToString("x6") +
|
||||
", cmd=$" + req.ToString("x2") + " addr=$" + blockAddr.ToString("x4"));
|
||||
}
|
||||
@ -211,31 +210,8 @@ namespace RuntimeData.Apple {
|
||||
DataSubType.Address, null);
|
||||
|
||||
Param[] parms;
|
||||
if (ParamDescrs.TryGetValue(req, out parms)) {
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
if (mParamDescrs.TryGetValue(req, out parms)) {
|
||||
FormatParameterBlock(offset, parms);
|
||||
}
|
||||
|
||||
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 {
|
||||
public class SOS : MarshalByRefObject, IPlugin, IPlugin_SymbolList, IPlugin_InlineBrk {
|
||||
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 byte[] mFileData;
|
||||
private Dictionary<int, PlSymbol> mFunctionList;
|
||||
private AddressTranslate mAddrTrans;
|
||||
|
||||
public string Identifier {
|
||||
get {
|
||||
@ -46,6 +323,7 @@ namespace RuntimeData.Apple {
|
||||
public void Prepare(IApplication appRef, byte[] fileData, AddressTranslate addrTrans) {
|
||||
mAppRef = appRef;
|
||||
mFileData = fileData;
|
||||
mAddrTrans = addrTrans;
|
||||
|
||||
mAppRef.DebugLog("SOS(id=" + AppDomain.CurrentDomain.Id + "): prepare()");
|
||||
//System.Diagnostics.Debugger.Break();
|
||||
@ -54,6 +332,7 @@ namespace RuntimeData.Apple {
|
||||
public void Unprepare() {
|
||||
mAppRef = null;
|
||||
mFileData = null;
|
||||
mAddrTrans = null;
|
||||
}
|
||||
|
||||
public void UpdateSymbolList(List<PlSymbol> plSyms) {
|
||||
@ -89,10 +368,91 @@ namespace RuntimeData.Apple {
|
||||
mAppRef.SetInlineDataFormat(offset + 2, 2, DataType.NumericLE,
|
||||
DataSubType.Address, null);
|
||||
|
||||
// Clear the "no continue" flag unless this is a QUIT call.
|
||||
if (req != 0x65) { // QUIT call
|
||||
ParamSet pset;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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).
|
||||
;
|
||||
; 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.
|
||||
*TAG SOS-MLI-Functions
|
||||
@ -21,12 +22,12 @@ SOS_GET_FENCE = $61
|
||||
SOS_SET_TIME = $62
|
||||
SOS_GET_TIME = $63
|
||||
SOS_GET_ANALOG = $64
|
||||
; SOS ref: "TERMINATE"
|
||||
SOS_TERMINATE = $65
|
||||
; SOS ref: "No errors are possible. This is an excellent call for beginners."
|
||||
SOS_QUIT = $65
|
||||
|
||||
SOS_READBLOCK = $80
|
||||
SOS_WRITEBLOCK = $81
|
||||
; SOS ref does not describe D_READ and D_WRITE; see Undocumented Features doc.
|
||||
SOS_D_READ = $80
|
||||
SOS_D_WRITE = $81
|
||||
SOS_D_STATUS = $82
|
||||
SOS_D_CONTROL = $83
|
||||
SOS_GET_DEV_NUM = $84
|
||||
@ -42,10 +43,8 @@ SOS_SET_PREFIX = $C6
|
||||
SOS_GET_PREFIX = $C7
|
||||
SOS_OPEN = $C8
|
||||
SOS_NEWLINE = $C9
|
||||
; SOS ref: "READ"
|
||||
SOS_READFILE = $CA
|
||||
; SOS ref: "WRITE"
|
||||
SOS_WRITEFILE = $CB
|
||||
SOS_READ = $CA
|
||||
SOS_WRITE = $CB
|
||||
SOS_CLOSE = $CC
|
||||
SOS_FLUSH = $CD
|
||||
SOS_SET_MARK = $CE
|
||||
@ -54,3 +53,75 @@ SOS_SET_EOF = $D0
|
||||
SOS_GET_EOF = $D1
|
||||
SOS_SET_LEVEL = $D2
|
||||
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…
x
Reference in New Issue
Block a user