From f4526b73c0f490c7099fc00350528b0d9145c5d1 Mon Sep 17 00:00:00 2001 From: Marek Karcz Date: Thu, 15 Sep 2016 14:41:32 -0400 Subject: [PATCH] Graphics device text/character mode. Linux port. Graphics device text/character mode. Linux port. Documentation updates. --- ConsoleIO.cpp | 202 +- ConsoleIO.h | 20 +- Display.cpp | 18 +- Display.h | 4 +- GraphDisp.cpp | 96 + GraphDisp.h | 47 +- MemMapDev.cpp | 188 +- MemMapDev.h | 59 +- ProgrammersReferenceManual.txt | 115 +- VMachine.cpp | 63 +- c64_char.dat | 268 + eh_basic.asm | 17446 +++++++++++++++---------------- eh_basic_mk.asm | 8733 ++++++++++++++++ ehbas_xx.dat | 1049 ++ main.cpp | 52 +- makefile | 30 +- test_grtxt.bas | 20 + 17 files changed, 19484 insertions(+), 8926 deletions(-) create mode 100644 c64_char.dat create mode 100644 eh_basic_mk.asm create mode 100644 ehbas_xx.dat create mode 100644 test_grtxt.bas diff --git a/ConsoleIO.cpp b/ConsoleIO.cpp index 7d56767..1161b90 100644 --- a/ConsoleIO.cpp +++ b/ConsoleIO.cpp @@ -7,7 +7,8 @@ * * Purpose: Implementation of ConsoleIO class. * The ConsoleIO class has methods helpful when - * UI is utilizing STDIO (DOS) console. + * UI is utilizing STDIO (DOS) console OR curses on + * Linux. * * Date: 8/26/2016 * @@ -44,6 +45,15 @@ #include #endif +#if defined(LINUX) +#include +#include +#include +#include + +static WINDOW *g_pWin = NULL; +#endif + using namespace std; namespace MKBasic { @@ -141,7 +151,7 @@ void ConsoleIO::ScrHome() SetConsoleCursorPosition( hStdOut, homeCoords ); } -#endif +#endif // WINDOWS #if defined(LINUX) @@ -155,7 +165,12 @@ void ConsoleIO::ScrHome() */ void ConsoleIO::ClearScreen() { - system("clear"); + if (isendwin() || NULL == g_pWin) { + system("clear"); + } else { + clear(); + refresh(); + } } /* @@ -168,9 +183,184 @@ void ConsoleIO::ClearScreen() */ void ConsoleIO::ScrHome() { - cout << "\033[1;1H"; + if (!isendwin() && NULL != g_pWin) { + move(0, 0); + refresh(); + } else { + cout << "\033[1;1H"; + } } -#endif // #devine LINUX +#endif // #define LINUX -} // END namespace MKBasic \ No newline at end of file +/* + *-------------------------------------------------------------------- + * Method: GetChar() + * Purpose: Get character from console. + * Arguments: n/a + * Returns: int - character code. + *-------------------------------------------------------------------- + */ +int ConsoleIO::GetChar() +{ +#if defined(LINUX) + if (!isendwin() && NULL != g_pWin) + return getch(); + else + return getchar(); +#else + return getch(); +#endif +} +/* + *-------------------------------------------------------------------- + * Method: KbHit() + * Purpose: Check if key has been pressed. + * Arguments: n/a + * Returns: bool - true if key pressed + *-------------------------------------------------------------------- + */ +bool ConsoleIO::KbHit() +{ +#if defined(LINUX) + if (!isendwin() && NULL != g_pWin) { + int ch = getch(); + + if (ch != ERR) { + ungetch(ch); + return true; + } else { + return false; + } + } else { + static const int STDIN = 0; + static bool initialized = false; + + if (! initialized) { + // Use termios to turn off line buffering + termios term; + tcgetattr(STDIN, &term); + term.c_lflag &= ~(ICANON | ECHO); + tcsetattr(STDIN, TCSANOW, &term); + setbuf(stdin, NULL); + initialized = true; + } + + int bytesWaiting; + ioctl(STDIN, FIONREAD, &bytesWaiting); + return (bytesWaiting > 0); + + } +#else + return (kbhit() != 0); +#endif +} + + +/* + *-------------------------------------------------------------------- + * Method: InitCursesScr() + * Purpose: Initialize nsurses screen. + * Arguments: n/a + * Returns: n/a + *-------------------------------------------------------------------- + */ +void ConsoleIO::InitCursesScr() +{ + fflush(stdin); +#if defined(LINUX) + if (NULL == g_pWin) { + g_pWin = initscr(); + cbreak(); + keypad(stdscr, TRUE); + noecho(); + nodelay(stdscr, TRUE); + scrollok(stdscr, TRUE); + } else if (isendwin()) { + refresh(); + } +#endif +} + +/* + *-------------------------------------------------------------------- + * Method: closeCursesScr() + * Purpose: Close nsurses screen. + * Arguments: n/a + * Returns: n/a + *-------------------------------------------------------------------- + */ +void ConsoleIO::CloseCursesScr() +{ +#if defined(LINUX) + if (!isendwin() && NULL != g_pWin) { + endwin(); + } +#endif +} + +/* + *-------------------------------------------------------------------- + * Method: PrintChar() + * Purpose: Print character on the screen. + * Arguments: char - character. + * Returns: n/a + *-------------------------------------------------------------------- + */ +void ConsoleIO::PrintChar(char c) +{ +#if defined(LINUX) + if (!isendwin() && NULL != g_pWin) { + echochar(c); + } else { + cout << c << flush; + } +#else + cout << c; +#endif +} + +/* + *-------------------------------------------------------------------- + * Method: PrintString() + * Purpose: Print string on the screen. + * Arguments: char * - pointer to char array. + * Returns: n/a + *-------------------------------------------------------------------- + */ +void ConsoleIO::PrintString(string s) +{ +#if defined(LINUX) + if (!isendwin() && NULL != g_pWin) { + addstr(s.c_str()); + refresh(); + } else { + cout << s; + } +#else + cout << s; +#endif +} + +/* + *-------------------------------------------------------------------- + * Method: Beep() + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +void ConsoleIO::Beep() +{ +#if defined(LINUX) + if (!isendwin() && NULL != g_pWin) { + beep(); + } else { + cout << "\a"; + } +#else + cout << "\a"; +#endif +} + +} // END namespace MKBasic diff --git a/ConsoleIO.h b/ConsoleIO.h index 5a67dad..afec51c 100644 --- a/ConsoleIO.h +++ b/ConsoleIO.h @@ -35,6 +35,7 @@ #include #include #include +#include #include "system.h" //#define WINDOWS 1 @@ -42,20 +43,29 @@ #include #endif +using namespace std; + namespace MKBasic { class ConsoleIO { public: - ConsoleIO(); - ~ConsoleIO(); + ConsoleIO(); + ~ConsoleIO(); - void ClearScreen(); - void ScrHome(); + void ClearScreen(); + void ScrHome(); + void InitCursesScr(); + void CloseCursesScr(); + void PrintChar(char c); + void PrintString(string s); + bool KbHit(); + int GetChar(); + void Beep(); }; } // namespace MKBasic -#endif // #ifndef CONSOLEIO_H \ No newline at end of file +#endif // #ifndef CONSOLEIO_H diff --git a/Display.cpp b/Display.cpp index 70ae1ad..deab204 100644 --- a/Display.cpp +++ b/Display.cpp @@ -34,14 +34,23 @@ *-------------------------------------------------------------------- */ -#include "Display.h" #include #include #include #include +#include "Display.h" +#include "MKGenException.h" using namespace std; + +#if defined(LINUX) +#include + +extern bool g_initialized; + +#endif + /* *-------------------------------------------------------------------- * Method: @@ -88,6 +97,9 @@ Display::~Display() */ void Display::InitScr() { + mpConIO = new ConsoleIO(); + if (NULL == mpConIO) + throw MKGenException("Display::InitScr() : Out of memory - ConsoleIO"); mLastChar = 0; mScrLines = SCREENDIM_ROW; mScrColumns = SCREENDIM_COL; @@ -248,7 +260,7 @@ void Display::PutChar(char c) mCursorCoord.col = 0; } else if (c == SCREENSPECCHARS_TB) { mLastChar = SCREENSPECCHARS_TB; - mCursorCoord.col += TABSIZE; + mCursorCoord.col += DISP_TABSIZE; if (mCursorCoord.col >= mScrColumns) { mCursorCoord.col = mScrColumns-1; // must work on it some more } @@ -339,7 +351,7 @@ void Display::ShowScr() if (mShellConsoleWidth > mScrColumns) line = line + "\n"; scr = scr + line; } - cout << scr; + mpConIO->PrintString(scr); } /* diff --git a/Display.h b/Display.h index 5cbb8bb..25cfb60 100644 --- a/Display.h +++ b/Display.h @@ -34,8 +34,9 @@ #define DISPLAY_H #include "system.h" +#include "ConsoleIO.h" -#define TABSIZE 4 +#define DISP_TABSIZE 4 namespace MKBasic { @@ -81,6 +82,7 @@ class Display unsigned int mShellConsoleWidth; unsigned int mScrLines; unsigned int mScrColumns; + ConsoleIO *mpConIO; void InitScr(); void ScrollUp(); diff --git a/GraphDisp.cpp b/GraphDisp.cpp index e083ec4..8df3982 100644 --- a/GraphDisp.cpp +++ b/GraphDisp.cpp @@ -111,8 +111,28 @@ void GraphDisp::Initialize() { int desk_w, desk_h, winbd_top = 5, winbd_right = 5; + mContLoop = true; + mMainLoopActive = false; + + mWidth = GRDISP_VR_X; // virtual display width + mHeight = GRDISP_VR_Y; // virtual display height + mPixelSizeX = GRAPHDISP_MAXW / mWidth; mPixelSizeY = GRAPHDISP_MAXH / mHeight; + + mWinPosX = 0; // SDL window position coordinate X + mWinPosY = 0; // SDL window position coordinate Y + mBgRgbR = 0; // bg color, RGB red intensity + mBgRgbG = 0; // bg color, RGB green intensity + mBgRgbB = 0; // bg color, RGB blue intensity + mFgRgbR = 0xFF; // fg color, RGB red intensity + mFgRgbG = 0xFF; // fg color, RGB green intensity + mFgRgbB = 0xFF; // fg color, RGB blue intensity + + mpWindow = NULL; + mpSurface = NULL; + mpRenderer = NULL; + GetDesktopResolution(desk_w, desk_h); // Available in version > 2.0.4 //SDL_GetWindowBordersSize(mpWindow, &winbd_top, NULL, NULL, &winbd_right); @@ -245,6 +265,82 @@ void GraphDisp::RenderPixel(int x, int y, bool set) SDL_UpdateWindowSurface(mpWindow); } +/* + *-------------------------------------------------------------------- + * Method: RendedChar8x8() + * Purpose: Draw 8x8 character from its pixel definition. + * Arguments: chdef - character definition in 8x8 bit matrix + * x, y - coordinates + * reversed - reversed (true) or normal (false) + * Returns: n/a + *-------------------------------------------------------------------- + */ +void GraphDisp::RenderChar8x8(unsigned char chdef[8], int x, int y, bool reversed) +{ + SDL_Rect rtf; + + int rgb_r = 0, rgb_g = 0, rgb_b = 0; + for (int yy = y, j=0; j < 8; j++, yy++) { + unsigned char chd = chdef[j]; + for (int xx = x, i=0; i < 8; i++, xx++) { + bool pixset = (chd & 0x80) == 0x80; + if (reversed) pixset = !pixset; + rtf.x = xx * mPixelSizeX; rtf.y = yy * mPixelSizeY; + rtf.w = mPixelSizeX; + rtf.h = mPixelSizeY; + if (pixset) { + rgb_r = mFgRgbR; + rgb_g = mFgRgbG; + rgb_b = mFgRgbB; + } else { + rgb_r = mBgRgbR; + rgb_g = mBgRgbG; + rgb_b = mBgRgbB; + } + SDL_FillRect(mpSurface, &rtf, SDL_MapRGB(mpSurface->format, rgb_r, rgb_g, rgb_b)); + chd = chd << 1; chd &= 0xFE; + } + } + SDL_UpdateWindowSurface(mpWindow); +} + +/* + *-------------------------------------------------------------------- + * Method: CopyCharRom8x8() + * Purpose: Copy provided 8x8 characters table to internal buffer. + * Arguments: pchrom - pointer to characters defintions table + * Returns: + *-------------------------------------------------------------------- + */ +void GraphDisp::CopyCharRom8x8(unsigned char *pchrom) +{ + for (int i=0; i #include +// defaults +#define GRDISP_VR_X 320 +#define GRDISP_VR_Y 200 +#define CHROM_8x8_SIZE 2048 + using namespace std; namespace MKBasic { @@ -51,8 +56,8 @@ class GraphDisp { public: - bool mContLoop = true; - bool mMainLoopActive = false; + bool mContLoop; // = true; + bool mMainLoopActive; // = false; GraphDisp(); GraphDisp(int width, int height); @@ -70,35 +75,39 @@ class GraphDisp { void ClearScreen(); //void MainLoop(); bool IsMainLoopActive(); + void PrintChar8x8(int code, int col, int row, bool reversed); + void CopyCharRom8x8(unsigned char *pchrom); private: - int mWidth = 320; // virtual display width - int mHeight = 200; // virtual display height - int mPixelSizeX = 3; // virtual pixel width - int mPixelSizeY = 3; // virtual pixel height - int mWinPosX = 0; // SDL window position coordinate X - int mWinPosY = 0; // SDL window position coordinate Y - int mBgRgbR = 0; // bg color, RGB red intensity - int mBgRgbG = 0; // bg color, RGB green intensity - int mBgRgbB = 0; // bg color, RGB blue intensity - int mFgRgbR = 0xFF; // fg color, RGB red intensity - int mFgRgbG = 0xFF; // fg color, RGB green intensity - int mFgRgbB = 0xFF; // fg color, RGB blue intensity - SDL_Window *mpWindow = NULL; - SDL_Surface *mpSurface = NULL; - SDL_Renderer *mpRenderer = NULL; + int mWidth; // virtual display width + int mHeight; // virtual display height + int mPixelSizeX; // virtual pixel width + int mPixelSizeY; // virtual pixel height + int mWinPosX; // SDL window position coordinate X + int mWinPosY; // SDL window position coordinate Y + int mBgRgbR; // bg color, RGB red intensity + int mBgRgbG; // bg color, RGB green intensity + int mBgRgbB; // bg color, RGB blue intensity + int mFgRgbR; // fg color, RGB red intensity + int mFgRgbG; // fg color, RGB green intensity + int mFgRgbB; // fg color, RGB blue intensity + SDL_Window *mpWindow; + SDL_Surface *mpSurface; + SDL_Renderer *mpRenderer; thread mMainLoopThread; + unsigned char mCharROM8x8[CHROM_8x8_SIZE]; void Initialize(); void UpdateSurface(); void Clear(); void GetDesktopResolution(int& horizontal, int& vertical); void DrawLine(int x1, int y1, int x2, int y2, bool draworerase); - void RenderPixel(int x, int y, bool set); + void RenderPixel(int x, int y, bool set); + void RenderChar8x8(unsigned char chdef[8], int x, int y, bool reversed); }; // class GraphDisp } // namespace MKBasic -#endif \ No newline at end of file +#endif diff --git a/MemMapDev.cpp b/MemMapDev.cpp index ee786f9..e38c50f 100644 --- a/MemMapDev.cpp +++ b/MemMapDev.cpp @@ -47,6 +47,8 @@ #include "MKGenException.h" #include +#include +#include #include #if defined(WINDOWS) #include @@ -120,6 +122,9 @@ MemMapDev::~MemMapDev() */ void MemMapDev::Initialize() { + mpConsoleIO = new ConsoleIO(); + if (NULL == mpConsoleIO) + throw MKGenException("MemMapDev::Initialize() : Out of memory - ConsoleIO"); mInBufDataBegin = mInBufDataEnd = 0; mOutBufDataBegin = mOutBufDataEnd = 0; mIOEcho = false; @@ -127,6 +132,11 @@ void MemMapDev::Initialize() mGraphDispAddr = GRDISP_ADDR; mpGraphDisp = NULL; mpCharIODisp = NULL; + mGrDevRegs.mGraphDispChrTbl = CHARTBL_BANK; + mCharTblAddr = CHARTBL_BANK * ((MAX_8BIT_ADDR+1) / 0x10); + mGrDevRegs.mGraphDispTxtCurX = 0; + mGrDevRegs.mGraphDispTxtCurY = 0; + mGrDevRegs.mGraphDispCrsMode = GRAPHDEVCRSMODE_BLOCK; AddrRange addr_range(CHARIO_ADDR, CHARIO_ADDR+1); DevPar dev_par("echo", "false"); MemAddrRanges addr_ranges_chario; @@ -255,84 +265,28 @@ int MemMapDev::SetupDevice(int devnum, } #if defined(LINUX) + #include #include #include -struct termios orig_termios; +#include +#endif // LINUX /* *-------------------------------------------------------------------- - * Method: - * Purpose: + * Method: SetCurses() + * Purpose: Initialize curses screen. * Arguments: * Returns: *-------------------------------------------------------------------- */ -void reset_terminal_mode() + /*** +void MemMapDev::SetCurses() { - tcsetattr(0, TCSANOW, &orig_termios); + mpConsoleIO->InitCursesScr(); } - -/* - *-------------------------------------------------------------------- - * Method: - * Purpose: - * Arguments: - * Returns: - *-------------------------------------------------------------------- - */ -void MemMapDev::set_conio_terminal_mode() -{ - struct termios new_termios; - - /* take two copies - one for now, one for later */ - tcgetattr(0, &orig_termios); - memcpy(&new_termios, &orig_termios, sizeof(new_termios)); - - /* register cleanup handler, and set the new terminal mode */ - atexit(reset_terminal_mode); - cfmakeraw(&new_termios); - tcsetattr(0, TCSANOW, &new_termios); -} - -/* - *-------------------------------------------------------------------- - * Method: - * Purpose: - * Arguments: - * Returns: - *-------------------------------------------------------------------- - */ -int MemMapDev::kbhit() -{ - struct timeval tv = { 0L, 0L }; - fd_set fds; - FD_ZERO(&fds); - FD_SET(0, &fds); - return select(1, &fds, NULL, NULL, &tv); -} - -/* - *-------------------------------------------------------------------- - * Method: - * Purpose: - * Arguments: - * Returns: - *-------------------------------------------------------------------- - */ -int MemMapDev::getch() -{ - int r; - unsigned char c; - if ((r = read(0, &c, sizeof(c))) < 0) { - return r; - } else { - return c; - } -} - -#endif // #define LINUX +***/ /* *-------------------------------------------------------------------- @@ -346,37 +300,36 @@ int MemMapDev::getch() unsigned char MemMapDev::ReadCharKb(bool nonblock) { unsigned char ret = 0; -#if defined(LINUX) - set_conio_terminal_mode(); -#endif static int c = ' '; // static, initializes once, remembers prev. // value - // checking mCharIOActive may be too much of a precaution since - // this method will not be called unless char I/O is enabled - if (mCharIOActive && mIOEcho && isprint(c)) putchar(c); + if (mIOEcho && isprint(c)) mpConsoleIO->PrintChar(c); if (nonblock) { + // get a keystroke only if character is already in buffer - if (kbhit()) c = getch(); + if (mpConsoleIO->KbHit()) c = mpConsoleIO->GetChar(); else c = 0; } else { + // wait for a keystroke, then get the character from buffer - while(!kbhit()); - c = getch(); + while(!mpConsoleIO->KbHit()); + c = mpConsoleIO->GetChar(); } #if defined(LINUX) if (c == 3) { // capture CTRL-C in CONIO mode - reset_terminal_mode(); + mpConsoleIO->CloseCursesScr(); kill(getpid(),SIGINT); - } + } else if (c == 0x0A) { + c = 0x0D; // without this conversion EhBasic won't work + } else if (c == KEY_BACKSPACE) { + c = 8; // raw/cbreak modes do not pass the backspace + } #endif mCharIOBufIn[mInBufDataEnd] = c; mInBufDataEnd++; if (mInBufDataEnd >= CHARIO_BUF_SIZE) mInBufDataEnd = 0; ret = c; -#if defined(LINUX) - reset_terminal_mode(); -#endif + return ret; } @@ -456,7 +409,22 @@ void MemMapDev::PutCharIO(char c) mOutBufDataEnd++; if (mOutBufDataEnd >= CHARIO_BUF_SIZE) mOutBufDataEnd = 0; if (mCharIOActive) { - putchar((int)c); +#if defined(LINUX) + // because ncurses will remove characters if sequence is + // CR,NL, I convert CR,NL to NL,CR (NL=0x0A, CR=0x0D) + static char prevc = 0; + if (c == 7) mpConsoleIO->Beep(); + else + if (c == 0x0D && prevc != 0x0A) { prevc = c; c = 0x0A; } + else if (c == 0x0A && prevc == 0x0D) { + prevc = c; c = 0x0D; + mpConsoleIO->PrintChar(prevc); + mpConsoleIO->PrintChar(c); + } + else { prevc = c; mpConsoleIO->PrintChar(c); } +#else + mpConsoleIO->PrintChar(c); +#endif CharIOFlush(); } } @@ -471,7 +439,8 @@ void MemMapDev::PutCharIO(char c) */ void MemMapDev::CharIODevice_Write(int addr, int val) { - if ((unsigned int)addr == mCharIOAddr) { + if ((unsigned int)addr == mCharIOAddr + || (unsigned int)addr == mCharIOAddr+1) { PutCharIO ((char) val); } } @@ -664,6 +633,44 @@ void MemMapDev::GraphDispDevice_Write(int addr, int val) } else if ((unsigned int)addr == mGraphDispAddr + GRAPHDEVREG_Y2) { // setup Y coordinate of the end of line mGrDevRegs.mGraphDispY2 = (unsigned char)val; + } else if ((unsigned int)addr == mGraphDispAddr + GRAPHDEVREG_CHRTBL) { + // set new address of the character table, 2 kB bank #0-31 + mGrDevRegs.mGraphDispChrTbl = (unsigned char)(val & 0x003F); + mCharTblAddr = mGrDevRegs.mGraphDispChrTbl * ((MAX_8BIT_ADDR+1) / 0x20); + unsigned char char_rom[CHROM_8x8_SIZE]; + for (unsigned int i=0; iPeek8bitImg((unsigned short)((mCharTblAddr + i) & 0xFFFF)); + } + mpGraphDisp->CopyCharRom8x8(char_rom); + } else if ((unsigned int)addr == mGraphDispAddr + GRAPHDEVREG_TXTCURX) { + if (val <= TXTCRSR_MAXCOL) + mGrDevRegs.mGraphDispTxtCurX = (unsigned char) (val & 0x007F); + } else if ((unsigned int)addr == mGraphDispAddr + GRAPHDEVREG_TXTCURY) { + if (val <= TXTCRSR_MAXROW) + mGrDevRegs.mGraphDispTxtCurY = (unsigned char) (val & 0x001F); + } else if ((unsigned int)addr == mGraphDispAddr + GRAPHDEVREG_CRSMODE) { + if (val < GRAPHDEVCRSMODE_END) + mGrDevRegs.mGraphDispCrsMode = (unsigned char) (val & 0x000F); + } else if ((unsigned int)addr == mGraphDispAddr + GRAPHDEVREG_TXTMODE) { + if (val < GRAPHDEVTXTMODE_END) + mGrDevRegs.mGraphDispTxtMode = (unsigned char) (val & 0x000F); + } else if ((unsigned int)addr == mGraphDispAddr + GRAPHDEVREG_PUTC) { + if (val <= 0xFF) { + mpGraphDisp->PrintChar8x8(val, + mGrDevRegs.mGraphDispTxtCurX, + mGrDevRegs.mGraphDispTxtCurY, + (mGrDevRegs.mGraphDispTxtMode == GRAPHDEVTXTMODE_REVERSE)); + /*** + unsigned int n = val * 8; + int x = mGrDevRegs.mGraphDispTxtCurX * 8; + int y = mGrDevRegs.mGraphDispTxtCurY * 8; + unsigned char chdef[8]; + for (int i=0; i<8; i++, n++) { + chdef[i] = mpMem->Peek8bitImg((unsigned short)((mCharTblAddr + n) & 0xFFFF)); + } + mpGraphDisp->RenderChar8x8(chdef, x, y, (mGrDevRegs.mGraphDispTxtMode == GRAPHDEVTXTMODE_REVERSE)); + ***/ + } } else if ((unsigned int)addr == mGraphDispAddr + GRAPHDEVREG_CMD) { // execute command switch (val) { @@ -721,7 +728,6 @@ void MemMapDev::GraphDispDevice_Write(int addr, int val) } GraphDisp_ReadEvents(); GraphDisp_Update(); - //mpGraphDisp->Update(); } // if (NULL != mpGraphDisp) } @@ -752,7 +758,6 @@ void MemMapDev::ActivateGraphDisp() mGrDevRegs.mGraphDispPixColG, mGrDevRegs.mGraphDispPixColB); GraphDisp_Update(); - //mpGraphDisp->Start(mpGraphDisp); } } @@ -771,7 +776,6 @@ void MemMapDev::DeactivateGraphDisp() cout << "DBG: ERROR: Main Loop is already inactive in Graphics Display." << endl; } #endif - //mpGraphDisp->Stop(); if (NULL != mpGraphDisp) delete mpGraphDisp; mpGraphDisp = NULL; } @@ -802,20 +806,4 @@ void MemMapDev::GraphDisp_Update() if (NULL != mpGraphDisp) mpGraphDisp->Update(); } -/* - *-------------------------------------------------------------------- - * Method: SetCharIODispPtr() - * Purpose: Set internal pointer to character I/O device object. - * Arguments: p - pointer to Display object. - * active - bool, true if character I/O is active - * Returns: n/a - *-------------------------------------------------------------------- - */ - /* -void MemMapDev::SetCharIODispPtr(Display *p, bool active) -{ - mpCharIODisp = p; - mCharIOActive = active; -}*/ - } // namespace MKBasic diff --git a/MemMapDev.h b/MemMapDev.h index 9706eec..2031c2d 100644 --- a/MemMapDev.h +++ b/MemMapDev.h @@ -39,6 +39,7 @@ //#include "Memory.h" #include "GraphDisp.h" #include "Display.h" +#include "ConsoleIO.h" #if defined(LINUX) #include @@ -50,6 +51,10 @@ #define CHARIO_ADDR 0xE000 #define GRDISP_ADDR 0xE002 #define CHARIO_BUF_SIZE 256 +#define CHARTBL_BANK 0x0B // $B000 +#define CHARTBL_LEN 0x1000 // 4 kB +#define TXTCRSR_MAXCOL 79 +#define TXTCRSR_MAXROW 24 using namespace std; @@ -138,7 +143,7 @@ typedef vector MemMappedDevices; // currently supported devices enum DevNums { DEVNUM_CHARIO = 0, // character I/O device - DEVNUM_GRDISP = 1, // raster graphics display device + DEVNUM_GRDISP = 1 // raster graphics display device }; /* @@ -174,9 +179,24 @@ enum GraphDevRegs { GRAPHDEVREG_CMD = 9, GRAPHDEVREG_X2 = 10, GRAPHDEVREG_Y2 = 12, + GRAPHDEVREG_CHRTBL = 13, // set the 2 kB bank where char. table resides + GRAPHDEVREG_TXTCURX = 14, // set text cursor position (column) + GRAPHDEVREG_TXTCURY = 15, // set text cursor position (row) + GRAPHDEVREG_PUTC = 16, // output char. to current pos. and move cursor + GRAPHDEVREG_CRSMODE = 17, // set cursor mode (0 - not visible, 1 - block...) + GRAPHDEVREG_TXTMODE = 18, // set text mode (0 - normal, 1 - reverse) //--------------------------- GRAPHDEVREG_END }; +/* + * Note to GRAPHDEVREG_PUTC: + * value put to register is not an ASCII code of the character, but rather + * a screen code in order how character is positioned in character table. + * Each character definition takes 8 bytes. There is 4096 bytes which defines + * 512 characters. First 256 are normal color and next 256 are reverse color + * definitions. + */ + // graphics display commands enum GraphDevCmds { @@ -189,6 +209,25 @@ enum GraphDevCmds { GRAPHDEVCMD_ERASLN = 6 }; +// Cursor modes. +// note: bit 7 will decide if cursor will blink (1) +#define CRS_BLINK 0x80 +enum TextCursorModes { + GRAPHDEVCRSMODE_BLANK = 0, // not visible + GRAPHDEVCRSMODE_BLOCK = 1, // block + GRAPHDEVCRSMODE_UND = 2, // underscore + //------------------------------------------ + GRAPHDEVCRSMODE_END +}; + +// Text modes. +enum TextModes { + GRAPHDEVTXTMODE_NORMAL = 0, // normal mode + GRAPHDEVTXTMODE_REVERSE = 1, // reverse colors mode + //------------------------------------------ + GRAPHDEVTXTMODE_END +}; + struct GraphDeviceRegs { unsigned char mGraphDispLoX; unsigned char mGraphDispHiX; @@ -202,6 +241,11 @@ struct GraphDeviceRegs { unsigned char mGraphDispBgColR; unsigned char mGraphDispBgColG; unsigned char mGraphDispBgColB; + unsigned char mGraphDispChrTbl; // 2 kB char. table bank (0-31) + unsigned char mGraphDispTxtCurX; // text cursor column + unsigned char mGraphDispTxtCurY; // text cursor row + unsigned char mGraphDispCrsMode; // cursor mode + unsigned char mGraphDispTxtMode; // text mode }; // Functionality of memory mapped devices @@ -258,22 +302,17 @@ class MemMapDev { Display *mpCharIODisp; // pointer to character I/O device object bool mCharIOActive; // indicate if character I/O is active GraphDeviceRegs mGrDevRegs; // graphics display device registers + unsigned int mCharTblAddr; // start address of characters table + ConsoleIO *mpConsoleIO; void Initialize(); unsigned char ReadCharKb(bool nonblock); void PutCharIO(char c); - -#if defined(LINUX) - - void set_conio_terminal_mode(); - int kbhit(); - int getch(); - -#endif + //void SetCurses(); }; } // namespace MKBasic -#endif // MEMMAPDEV_H \ No newline at end of file +#endif // MEMMAPDEV_H diff --git a/ProgrammersReferenceManual.txt b/ProgrammersReferenceManual.txt index de31e1d..05710c4 100644 --- a/ProgrammersReferenceManual.txt +++ b/ProgrammersReferenceManual.txt @@ -500,7 +500,7 @@ Op-code execute history: disabled. 0 GRAPHDEVREG_X_LO Least significant part of pixel's X (column) coordinate or begin of line coord. (0-255) 1 GRAPHDEVREG_X_HI Most significant part of pixel's X (column) - coordinate or begin of line coord. (0-1) + coordinate or begin of line coord. (0-1) 2 GRAPHDEVREG_Y Pixel's Y (row) coordinate (0-199) 3 GRAPHDEVREG_PXCOL_R Pixel's RGB color component - Red (0-255) 4 GRAPHDEVREG_PXCOL_G Pixel's RGB color component - Green (0-255) @@ -514,6 +514,14 @@ Op-code execute history: disabled. 11 GRAPHDEVREG_X2_HI Most significant part of end of line's X coordinate 12 GRAPHDEVREG_Y2 End of line's Y (row) coordinate (0-199) + 13 GRAPHDEVREG_CHRTBL Set the 2 kB bank where char. table resides + 14 GRAPHDEVREG_TXTCURX Set text cursor position (column) + 15 GRAPHDEVREG_TXTCURY Set text cursor position (row) + 16 GRAPHDEVREG_PUTC Output char. to current pos. and move cursor + 17 GRAPHDEVREG_CRSMODE Set cursor mode : 0 - not visible, 1 - block + 18 GRAPHDEVREG_TXTMODE Set text mode : 0 - normal, 1 - reverse + + NOTE: Functionality maintaining text cursor is not yet implemented. Writing values to above memory locations when Graphics Device is enabled allows to set the corresponding parameters of the device, while writing to @@ -603,6 +611,33 @@ Op-code execute history: disabled. 1310 NEXT Y 1320 RETURN +And another one to show how to render characters. +Before entering program below, load files c64_char.dat and ehbas_xx.dat to the +emulator. The two 2 kB C64 character banks reside at $B000. +The EhBasic version in file ehbas_xx.dat has top of RAM capped at $AFFF. + + 5 PRINT:PRINT "BITMAP TEXT DEMO. PRESS [SPACE] TO QUIT...":PRINT + 10 C=0:M=0:N=22:B=65506:POKE B+9,0 + 12 PRINT "NORMAL MODE, CHAR BANK ";N*2048 + 15 POKE B+13,N:POKE B+17,0:POKE B+18,0 + 20 FOR Y=0 TO 24 + 30 FOR X=0 TO 39 + 40 POKE B+14,X:POKE B+15,Y + 50 POKE B+16,C + 60 C=C+1:IF C<256 THEN 120 + 70 IF N=22 THEN N=23:GOTO 100 + 80 N=22:IF M=0 THEN M=1:GOTO 100 + 90 M=0 + 100 POKE B+13,N:POKE B+18,M + 110 Y=Y+1:X=-1:C=0 + 115 IF M=0 THEN PRINT "NORMAL"; ELSE PRINT "REVERSE"; + 116 PRINT " MODE, CHAR BANK ";N*2048 + 120 GET K$:IF K$=" " THEN END + 130 NEXT X + 140 NEXT Y + 150 GOTO 5 + + 4.1. Adding new device implementation. MemMapDev.h and MemMapDev.cpp define the higher abstraction layer for memory @@ -700,7 +735,7 @@ Op-code execute history: disabled. in all read/write memory methods. Some local methods and flags specific to the devices may be needed for implementation convenience. - Important relevant methods in Memory class: + Important relevant methods in Memory class: int AddDevice(int devnum); int DeleteDevice(int devnum); @@ -766,3 +801,79 @@ Op-code execute history: disabled. to creation of debug message unnecessarily if the debugging messages are disabled. +5. Linux port. + + I don't pay as much attention to Linux version of this software, however +I try my best to make the program work correctly on Linux and behave in the +same manner on both Windows and Linux platforms. +The most challenging part surprisingly was implementation of the character +I/O emulation on Linux. Easy on Windows with its conio.h header and kbhit() +and getch() functions that provide non-blocking keyboard input, Linux part +required some research and implementing some known programming tricks to get +this to work. I got it working but then lost touch with Linux version for +a while. After I added graphics device and SDL2 library, I worked on Linux +port to have these features working on Linux platform as well. To my surprise +I discovered then that my implementation of character I/O (the non-blocking +character input) stopped working. After many failed attempts and research +I decided to rewrite the Linux character I/O part using ncurses library. +This works although has its own problems. E.g.: ncurses getch() returns NL +character (0x0A) when ENTER is pressed, while Windows conio equivalent returns +CR (0x0D) and this is the code that 6502 programs, like Tiny Basic or EhBasic +expect. Backspace also wasn't working. I enabled function keys during ncurses +initialization and intercept backspace code for later conversion. This +solved it, but there may be more issues discovered later which I didn't fully +test. + +unsigned char MemMapDev::ReadCharKb(bool nonblock) +{ +[...] + +#if defined(LINUX) + if (c == 3) { // capture CTRL-C in CONIO mode + mpConsoleIO->CloseCursesScr(); + kill(getpid(),SIGINT); + } else if (c == 0x0A) { + c = 0x0D; // without this conversion EhBasic won't work + } else if (c == KEY_BACKSPACE) { + c = 8; // raw/cbreak modes do not pass the backspace + } +#endif + +[...] + +Another issue was that when 6502 code sends CR/LF sequence, the CR code +moves the cursor to the beginning of the line before applying NL (new line) +and clears the characters on its path! Therefore I'd have the text removed +from the screen (although my internal display device emulation in Display +class has its own buffer and all characters were there, it was only a visual +side effect). Therefore I have to convert CR/LF sequences to LF/CR. +Also because of the way I output characters to nsurses screen, control +characters don't work and must be intercepted and properly converted to +appropriate action. Example - the bell (audible) code 7: + +void MemMapDev::PutCharIO(char c) +{ + mCharIOBufOut[mOutBufDataEnd] = c; + mOutBufDataEnd++; + if (mOutBufDataEnd >= CHARIO_BUF_SIZE) mOutBufDataEnd = 0; + if (mCharIOActive) { +#if defined(LINUX) + // because ncurses will remove characters if sequence is + // CR,NL, I convert CR,NL to NL,CR (NL=0x0A, CR=0x0D) + static char prevc = 0; + if (c == 7) mpConsoleIO->Beep(); + else + if (c == 0x0D && prevc != 0x0A) { prevc = c; c = 0x0A; } + else if (c == 0x0A && prevc == 0x0D) { + prevc = c; c = 0x0D; + mpConsoleIO->PrintChar(prevc); + mpConsoleIO->PrintChar(c); + } + else { prevc = c; mpConsoleIO->PrintChar(c); } +#else + mpConsoleIO->PrintChar(c); +#endif + CharIOFlush(); + } +} + diff --git a/VMachine.cpp b/VMachine.cpp index fcdef4a..132aec7 100644 --- a/VMachine.cpp +++ b/VMachine.cpp @@ -42,25 +42,10 @@ #include "VMachine.h" #include "MKGenException.h" -/* -#if defined(WINDOWS) -#include -#endif -*/ - using namespace std; namespace MKBasic { -/* - *-------------------------------------------------------------------- - * Method: - * Purpose: - * Arguments: - * Returns: - *-------------------------------------------------------------------- - */ - /* *-------------------------------------------------------------------- * Method: VMachine() @@ -100,7 +85,6 @@ VMachine::VMachine(string romfname, string ramfname) */ VMachine::~VMachine() { - //delete mpDisp; delete mpCPU; delete mpROM; delete mpRAM; @@ -145,11 +129,6 @@ void VMachine::InitVM() if (NULL == mpCPU) { throw MKGenException("Unable to initialize VM (CPU)."); } - /* - mpDisp = new Display(); - if (NULL == mpDisp) { - throw MKGenException("Unable to initialize VM (Display)."); - } */ mpConIO = new ConsoleIO(); if (NULL == mpConIO) { throw MKGenException("Unable to initialize VM (ConsoleIO)"); @@ -279,6 +258,7 @@ Regs *VMachine::Run() AddDebugTrace("Running code at: $" + Addr2HexStr(mRunAddr)); mOpInterrupt = false; + mpConIO->InitCursesScr(); ClearScreen(); ShowDisp(); mPerfStats.cycles = 0; @@ -293,6 +273,7 @@ Regs *VMachine::Run() CalcCurrPerf(); ShowDisp(); + mpConIO->CloseCursesScr(); return cpureg; } @@ -327,6 +308,7 @@ Regs *VMachine::Exec() AddDebugTrace("Executing code at: $" + Addr2HexStr(mRunAddr)); mOpInterrupt = false; + mpConIO->InitCursesScr(); ClearScreen(); ShowDisp(); mPerfStats.cycles = 0; @@ -340,16 +322,17 @@ Regs *VMachine::Exec() CalcCurrPerf(); ShowDisp(); + mpConIO->CloseCursesScr(); return cpureg; } /* *-------------------------------------------------------------------- - * Method: - * Purpose: + * Method: GetPerfStats() + * Purpose: Get performance stats data. * Arguments: - * Returns: + * Returns: struct PerfStats *-------------------------------------------------------------------- */ PerfStats VMachine::GetPerfStats() @@ -1526,7 +1509,7 @@ bool VMachine::IsAutoReset() /* *-------------------------------------------------------------------- - * Method: + * Method: EnableROM() * Purpose: * Arguments: * Returns: @@ -1540,7 +1523,7 @@ void VMachine::EnableROM() /* *-------------------------------------------------------------------- - * Method: + * Method: DisableROM() * Purpose: * Arguments: * Returns: @@ -1554,7 +1537,7 @@ void VMachine::DisableROM() /* *-------------------------------------------------------------------- - * Method: + * Method: SetROM() * Purpose: * Arguments: * Returns: @@ -1593,7 +1576,7 @@ void VMachine::EnableROM(unsigned short start, unsigned short end) /* *-------------------------------------------------------------------- - * Method: + * Method: GetROMBegin() * Purpose: * Arguments: * Returns: @@ -1606,7 +1589,7 @@ unsigned short VMachine::GetROMBegin() /* *-------------------------------------------------------------------- - * Method: + * Method: GetROMEnd() * Purpose: * Arguments: * Returns: @@ -1619,7 +1602,7 @@ unsigned short VMachine::GetROMEnd() /* *-------------------------------------------------------------------- - * Method: + * Method: IsROMEnabled() * Purpose: * Arguments: * Returns: @@ -1632,7 +1615,7 @@ bool VMachine::IsROMEnabled() /* *-------------------------------------------------------------------- - * Method: + * Method: GetRunAddr() * Purpose: * Arguments: * Returns: @@ -1745,7 +1728,7 @@ int VMachine::GetLastError() /* *-------------------------------------------------------------------- - * Method: + * Method: EnableExecHistory() * Purpose: * Arguments: * Returns: @@ -1765,7 +1748,7 @@ void VMachine::EnableExecHistory(bool enexehist) /* *-------------------------------------------------------------------- - * Method: + * Method: IsExecHistoryActive() * Purpose: * Arguments: * Returns: @@ -1778,7 +1761,7 @@ bool VMachine::IsExecHistoryActive() /* *-------------------------------------------------------------------- - * Method: + * Method: EnableDebugTrace() * Purpose: * Arguments: * Returns: @@ -1794,7 +1777,7 @@ void VMachine::EnableDebugTrace() /* *-------------------------------------------------------------------- - * Method: + * Method: DisableDebugTrace() * Purpose: * Arguments: * Returns: @@ -1807,7 +1790,7 @@ void VMachine::DisableDebugTrace() /* *-------------------------------------------------------------------- - * Method: + * Method: IsDebugTraceActive() * Purpose: * Arguments: * Returns: @@ -1820,7 +1803,7 @@ bool VMachine::IsDebugTraceActive() /* *-------------------------------------------------------------------- - * Method: + * Method: GetDebugTraces() * Purpose: * Arguments: * Returns: @@ -1833,7 +1816,7 @@ queue VMachine::GetDebugTraces() /* *-------------------------------------------------------------------- - * Method: + * Method: EnablePerfStats() * Purpose: * Arguments: * Returns: @@ -1852,7 +1835,7 @@ void VMachine::EnablePerfStats() } /* *-------------------------------------------------------------------- - * Method: + * Method: DisablePerfStats() * Purpose: * Arguments: * Returns: @@ -1866,7 +1849,7 @@ void VMachine::DisablePerfStats() /* *-------------------------------------------------------------------- - * Method: + * Method: IsPerfStatsActive() * Purpose: * Arguments: * Returns: diff --git a/c64_char.dat b/c64_char.dat new file mode 100644 index 0000000..40956b7 --- /dev/null +++ b/c64_char.dat @@ -0,0 +1,268 @@ +ADDR +$b000 +; Created with BIN2HEX (C) Marek Karcz 2016. All rights reserved. +; 09/08/16 13:19:24 +; This is the character ROM dump of C64. +; C64 char ROM begins @$D000 and takes 4 kB ($1000): $D000..$DFFF. +; This image loads to address $B000 so I can use it with EhBASIC. +; Use EhBASIC with modified RAM Top @$B000. +; +ORG +$b000 +$3c $66 $6e $6e $60 $62 $3c $00 $18 $3c $66 $7e $66 $66 $66 $00 +$7c $66 $66 $7c $66 $66 $7c $00 $3c $66 $60 $60 $60 $66 $3c $00 +$78 $6c $66 $66 $66 $6c $78 $00 $7e $60 $60 $78 $60 $60 $7e $00 +$7e $60 $60 $78 $60 $60 $60 $00 $3c $66 $60 $6e $66 $66 $3c $00 +$66 $66 $66 $7e $66 $66 $66 $00 $3c $18 $18 $18 $18 $18 $3c $00 +$1e $0c $0c $0c $0c $6c $38 $00 $66 $6c $78 $70 $78 $6c $66 $00 +$60 $60 $60 $60 $60 $60 $7e $00 $63 $77 $7f $6b $63 $63 $63 $00 +$66 $76 $7e $7e $6e $66 $66 $00 $3c $66 $66 $66 $66 $66 $3c $00 +$7c $66 $66 $7c $60 $60 $60 $00 $3c $66 $66 $66 $66 $3c $0e $00 +$7c $66 $66 $7c $78 $6c $66 $00 $3c $66 $60 $3c $06 $66 $3c $00 +$7e $18 $18 $18 $18 $18 $18 $00 $66 $66 $66 $66 $66 $66 $3c $00 +$66 $66 $66 $66 $66 $3c $18 $00 $63 $63 $63 $6b $7f $77 $63 $00 +$66 $66 $3c $18 $3c $66 $66 $00 $66 $66 $66 $3c $18 $18 $18 $00 +$7e $06 $0c $18 $30 $60 $7e $00 $3c $30 $30 $30 $30 $30 $3c $00 +$0c $12 $30 $7c $30 $62 $fc $00 $3c $0c $0c $0c $0c $0c $3c $00 +$00 $18 $3c $7e $18 $18 $18 $18 $00 $10 $30 $7f $7f $30 $10 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $18 $18 $18 $18 $00 $00 $18 $00 +$66 $66 $66 $00 $00 $00 $00 $00 $66 $66 $ff $66 $ff $66 $66 $00 +$18 $3e $60 $3c $06 $7c $18 $00 $62 $66 $0c $18 $30 $66 $46 $00 +$3c $66 $3c $38 $67 $66 $3f $00 $06 $0c $18 $00 $00 $00 $00 $00 +$0c $18 $30 $30 $30 $18 $0c $00 $30 $18 $0c $0c $0c $18 $30 $00 +$00 $66 $3c $ff $3c $66 $00 $00 $00 $18 $18 $7e $18 $18 $00 $00 +$00 $00 $00 $00 $00 $18 $18 $30 $00 $00 $00 $7e $00 $00 $00 $00 +$00 $00 $00 $00 $00 $18 $18 $00 $00 $03 $06 $0c $18 $30 $60 $00 +$3c $66 $6e $76 $66 $66 $3c $00 $18 $18 $38 $18 $18 $18 $7e $00 +$3c $66 $06 $0c $30 $60 $7e $00 $3c $66 $06 $1c $06 $66 $3c $00 +$06 $0e $1e $66 $7f $06 $06 $00 $7e $60 $7c $06 $06 $66 $3c $00 +$3c $66 $60 $7c $66 $66 $3c $00 $7e $66 $0c $18 $18 $18 $18 $00 +$3c $66 $66 $3c $66 $66 $3c $00 $3c $66 $66 $3e $06 $66 $3c $00 +$00 $00 $18 $00 $00 $18 $00 $00 $00 $00 $18 $00 $00 $18 $18 $30 +$0e $18 $30 $60 $30 $18 $0e $00 $00 $00 $7e $00 $7e $00 $00 $00 +$70 $18 $0c $06 $0c $18 $70 $00 $3c $66 $06 $0c $18 $00 $18 $00 +$00 $00 $00 $ff $ff $00 $00 $00 $08 $1c $3e $7f $7f $1c $3e $00 +$18 $18 $18 $18 $18 $18 $18 $18 $00 $00 $00 $ff $ff $00 $00 $00 +$00 $00 $ff $ff $00 $00 $00 $00 $00 $ff $ff $00 $00 $00 $00 $00 +$00 $00 $00 $00 $ff $ff $00 $00 $30 $30 $30 $30 $30 $30 $30 $30 +$0c $0c $0c $0c $0c $0c $0c $0c $00 $00 $00 $e0 $f0 $38 $18 $18 +$18 $18 $1c $0f $07 $00 $00 $00 $18 $18 $38 $f0 $e0 $00 $00 $00 +$c0 $c0 $c0 $c0 $c0 $c0 $ff $ff $c0 $e0 $70 $38 $1c $0e $07 $03 +$03 $07 $0e $1c $38 $70 $e0 $c0 $ff $ff $c0 $c0 $c0 $c0 $c0 $c0 +$ff $ff $03 $03 $03 $03 $03 $03 $00 $3c $7e $7e $7e $7e $3c $00 +$00 $00 $00 $00 $00 $ff $ff $00 $36 $7f $7f $7f $3e $1c $08 $00 +$60 $60 $60 $60 $60 $60 $60 $60 $00 $00 $00 $07 $0f $1c $18 $18 +$c3 $e7 $7e $3c $3c $7e $e7 $c3 $00 $3c $7e $66 $66 $7e $3c $00 +$18 $18 $66 $66 $18 $18 $3c $00 $06 $06 $06 $06 $06 $06 $06 $06 +$08 $1c $3e $7f $3e $1c $08 $00 $18 $18 $18 $ff $ff $18 $18 $18 +$c0 $c0 $30 $30 $c0 $c0 $30 $30 $18 $18 $18 $18 $18 $18 $18 $18 +$00 $00 $03 $3e $76 $36 $36 $00 $ff $7f $3f $1f $0f $07 $03 $01 +$00 $00 $00 $00 $00 $00 $00 $00 $f0 $f0 $f0 $f0 $f0 $f0 $f0 $f0 +$00 $00 $00 $00 $ff $ff $ff $ff $ff $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $ff $c0 $c0 $c0 $c0 $c0 $c0 $c0 $c0 +$cc $cc $33 $33 $cc $cc $33 $33 $03 $03 $03 $03 $03 $03 $03 $03 +$00 $00 $00 $00 $cc $cc $33 $33 $ff $fe $fc $f8 $f0 $e0 $c0 $80 +$03 $03 $03 $03 $03 $03 $03 $03 $18 $18 $18 $1f $1f $18 $18 $18 +$00 $00 $00 $00 $0f $0f $0f $0f $18 $18 $18 $1f $1f $00 $00 $00 +$00 $00 $00 $f8 $f8 $18 $18 $18 $00 $00 $00 $00 $00 $00 $ff $ff +$00 $00 $00 $1f $1f $18 $18 $18 $18 $18 $18 $ff $ff $00 $00 $00 +$00 $00 $00 $ff $ff $18 $18 $18 $18 $18 $18 $f8 $f8 $18 $18 $18 +$c0 $c0 $c0 $c0 $c0 $c0 $c0 $c0 $e0 $e0 $e0 $e0 $e0 $e0 $e0 $e0 +$07 $07 $07 $07 $07 $07 $07 $07 $ff $ff $00 $00 $00 $00 $00 $00 +$ff $ff $ff $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $ff $ff $ff +$03 $03 $03 $03 $03 $03 $ff $ff $00 $00 $00 $00 $f0 $f0 $f0 $f0 +$0f $0f $0f $0f $00 $00 $00 $00 $18 $18 $18 $f8 $f8 $00 $00 $00 +$f0 $f0 $f0 $f0 $00 $00 $00 $00 $f0 $f0 $f0 $f0 $0f $0f $0f $0f +$c3 $99 $91 $91 $9f $99 $c3 $ff $e7 $c3 $99 $81 $99 $99 $99 $ff +$83 $99 $99 $83 $99 $99 $83 $ff $c3 $99 $9f $9f $9f $99 $c3 $ff +$87 $93 $99 $99 $99 $93 $87 $ff $81 $9f $9f $87 $9f $9f $81 $ff +$81 $9f $9f $87 $9f $9f $9f $ff $c3 $99 $9f $91 $99 $99 $c3 $ff +$99 $99 $99 $81 $99 $99 $99 $ff $c3 $e7 $e7 $e7 $e7 $e7 $c3 $ff +$e1 $f3 $f3 $f3 $f3 $93 $c7 $ff $99 $93 $87 $8f $87 $93 $99 $ff +$9f $9f $9f $9f $9f $9f $81 $ff $9c $88 $80 $94 $9c $9c $9c $ff +$99 $89 $81 $81 $91 $99 $99 $ff $c3 $99 $99 $99 $99 $99 $c3 $ff +$83 $99 $99 $83 $9f $9f $9f $ff $c3 $99 $99 $99 $99 $c3 $f1 $ff +$83 $99 $99 $83 $87 $93 $99 $ff $c3 $99 $9f $c3 $f9 $99 $c3 $ff +$81 $e7 $e7 $e7 $e7 $e7 $e7 $ff $99 $99 $99 $99 $99 $99 $c3 $ff +$99 $99 $99 $99 $99 $c3 $e7 $ff $9c $9c $9c $94 $80 $88 $9c $ff +$99 $99 $c3 $e7 $c3 $99 $99 $ff $99 $99 $99 $c3 $e7 $e7 $e7 $ff +$81 $f9 $f3 $e7 $cf $9f $81 $ff $c3 $cf $cf $cf $cf $cf $c3 $ff +$f3 $ed $cf $83 $cf $9d $03 $ff $c3 $f3 $f3 $f3 $f3 $f3 $c3 $ff +$ff $e7 $c3 $81 $e7 $e7 $e7 $e7 $ff $ef $cf $80 $80 $cf $ef $ff +$ff $ff $ff $ff $ff $ff $ff $ff $e7 $e7 $e7 $e7 $ff $ff $e7 $ff +$99 $99 $99 $ff $ff $ff $ff $ff $99 $99 $00 $99 $00 $99 $99 $ff +$e7 $c1 $9f $c3 $f9 $83 $e7 $ff $9d $99 $f3 $e7 $cf $99 $b9 $ff +$c3 $99 $c3 $c7 $98 $99 $c0 $ff $f9 $f3 $e7 $ff $ff $ff $ff $ff +$f3 $e7 $cf $cf $cf $e7 $f3 $ff $cf $e7 $f3 $f3 $f3 $e7 $cf $ff +$ff $99 $c3 $00 $c3 $99 $ff $ff $ff $e7 $e7 $81 $e7 $e7 $ff $ff +$ff $ff $ff $ff $ff $e7 $e7 $cf $ff $ff $ff $81 $ff $ff $ff $ff +$ff $ff $ff $ff $ff $e7 $e7 $ff $ff $fc $f9 $f3 $e7 $cf $9f $ff +$c3 $99 $91 $89 $99 $99 $c3 $ff $e7 $e7 $c7 $e7 $e7 $e7 $81 $ff +$c3 $99 $f9 $f3 $cf $9f $81 $ff $c3 $99 $f9 $e3 $f9 $99 $c3 $ff +$f9 $f1 $e1 $99 $80 $f9 $f9 $ff $81 $9f $83 $f9 $f9 $99 $c3 $ff +$c3 $99 $9f $83 $99 $99 $c3 $ff $81 $99 $f3 $e7 $e7 $e7 $e7 $ff +$c3 $99 $99 $c3 $99 $99 $c3 $ff $c3 $99 $99 $c1 $f9 $99 $c3 $ff +$ff $ff $e7 $ff $ff $e7 $ff $ff $ff $ff $e7 $ff $ff $e7 $e7 $cf +$f1 $e7 $cf $9f $cf $e7 $f1 $ff $ff $ff $81 $ff $81 $ff $ff $ff +$8f $e7 $f3 $f9 $f3 $e7 $8f $ff $c3 $99 $f9 $f3 $e7 $ff $e7 $ff +$ff $ff $ff $00 $00 $ff $ff $ff $f7 $e3 $c1 $80 $80 $e3 $c1 $ff +$e7 $e7 $e7 $e7 $e7 $e7 $e7 $e7 $ff $ff $ff $00 $00 $ff $ff $ff +$ff $ff $00 $00 $ff $ff $ff $ff $ff $00 $00 $ff $ff $ff $ff $ff +$ff $ff $ff $ff $00 $00 $ff $ff $cf $cf $cf $cf $cf $cf $cf $cf +$f3 $f3 $f3 $f3 $f3 $f3 $f3 $f3 $ff $ff $ff $1f $0f $c7 $e7 $e7 +$e7 $e7 $e3 $f0 $f8 $ff $ff $ff $e7 $e7 $c7 $0f $1f $ff $ff $ff +$3f $3f $3f $3f $3f $3f $00 $00 $3f $1f $8f $c7 $e3 $f1 $f8 $fc +$fc $f8 $f1 $e3 $c7 $8f $1f $3f $00 $00 $3f $3f $3f $3f $3f $3f +$00 $00 $fc $fc $fc $fc $fc $fc $ff $c3 $81 $81 $81 $81 $c3 $ff +$ff $ff $ff $ff $ff $00 $00 $ff $c9 $80 $80 $80 $c1 $e3 $f7 $ff +$9f $9f $9f $9f $9f $9f $9f $9f $ff $ff $ff $f8 $f0 $e3 $e7 $e7 +$3c $18 $81 $c3 $c3 $81 $18 $3c $ff $c3 $81 $99 $99 $81 $c3 $ff +$e7 $e7 $99 $99 $e7 $e7 $c3 $ff $f9 $f9 $f9 $f9 $f9 $f9 $f9 $f9 +$f7 $e3 $c1 $80 $c1 $e3 $f7 $ff $e7 $e7 $e7 $00 $00 $e7 $e7 $e7 +$3f $3f $cf $cf $3f $3f $cf $cf $e7 $e7 $e7 $e7 $e7 $e7 $e7 $e7 +$ff $ff $fc $c1 $89 $c9 $c9 $ff $00 $80 $c0 $e0 $f0 $f8 $fc $fe +$ff $ff $ff $ff $ff $ff $ff $ff $0f $0f $0f $0f $0f $0f $0f $0f +$ff $ff $ff $ff $00 $00 $00 $00 $00 $ff $ff $ff $ff $ff $ff $ff +$ff $ff $ff $ff $ff $ff $ff $00 $3f $3f $3f $3f $3f $3f $3f $3f +$33 $33 $cc $cc $33 $33 $cc $cc $fc $fc $fc $fc $fc $fc $fc $fc +$ff $ff $ff $ff $33 $33 $cc $cc $00 $01 $03 $07 $0f $1f $3f $7f +$fc $fc $fc $fc $fc $fc $fc $fc $e7 $e7 $e7 $e0 $e0 $e7 $e7 $e7 +$ff $ff $ff $ff $f0 $f0 $f0 $f0 $e7 $e7 $e7 $e0 $e0 $ff $ff $ff +$ff $ff $ff $07 $07 $e7 $e7 $e7 $ff $ff $ff $ff $ff $ff $00 $00 +$ff $ff $ff $e0 $e0 $e7 $e7 $e7 $e7 $e7 $e7 $00 $00 $ff $ff $ff +$ff $ff $ff $00 $00 $e7 $e7 $e7 $e7 $e7 $e7 $07 $07 $e7 $e7 $e7 +$3f $3f $3f $3f $3f $3f $3f $3f $1f $1f $1f $1f $1f $1f $1f $1f +$f8 $f8 $f8 $f8 $f8 $f8 $f8 $f8 $00 $00 $ff $ff $ff $ff $ff $ff +$00 $00 $00 $ff $ff $ff $ff $ff $ff $ff $ff $ff $ff $00 $00 $00 +$fc $fc $fc $fc $fc $fc $00 $00 $ff $ff $ff $ff $0f $0f $0f $0f +$f0 $f0 $f0 $f0 $ff $ff $ff $ff $e7 $e7 $e7 $07 $07 $ff $ff $ff +$0f $0f $0f $0f $ff $ff $ff $ff $0f $0f $0f $0f $f0 $f0 $f0 $f0 +$3c $66 $6e $6e $60 $62 $3c $00 $00 $00 $3c $06 $3e $66 $3e $00 +$00 $60 $60 $7c $66 $66 $7c $00 $00 $00 $3c $60 $60 $60 $3c $00 +$00 $06 $06 $3e $66 $66 $3e $00 $00 $00 $3c $66 $7e $60 $3c $00 +$00 $0e $18 $3e $18 $18 $18 $00 $00 $00 $3e $66 $66 $3e $06 $7c +$00 $60 $60 $7c $66 $66 $66 $00 $00 $18 $00 $38 $18 $18 $3c $00 +$00 $06 $00 $06 $06 $06 $06 $3c $00 $60 $60 $6c $78 $6c $66 $00 +$00 $38 $18 $18 $18 $18 $3c $00 $00 $00 $66 $7f $7f $6b $63 $00 +$00 $00 $7c $66 $66 $66 $66 $00 $00 $00 $3c $66 $66 $66 $3c $00 +$00 $00 $7c $66 $66 $7c $60 $60 $00 $00 $3e $66 $66 $3e $06 $06 +$00 $00 $7c $66 $60 $60 $60 $00 $00 $00 $3e $60 $3c $06 $7c $00 +$00 $18 $7e $18 $18 $18 $0e $00 $00 $00 $66 $66 $66 $66 $3e $00 +$00 $00 $66 $66 $66 $3c $18 $00 $00 $00 $63 $6b $7f $3e $36 $00 +$00 $00 $66 $3c $18 $3c $66 $00 $00 $00 $66 $66 $66 $3e $0c $78 +$00 $00 $7e $0c $18 $30 $7e $00 $3c $30 $30 $30 $30 $30 $3c $00 +$0c $12 $30 $7c $30 $62 $fc $00 $3c $0c $0c $0c $0c $0c $3c $00 +$00 $18 $3c $7e $18 $18 $18 $18 $00 $10 $30 $7f $7f $30 $10 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $18 $18 $18 $18 $00 $00 $18 $00 +$66 $66 $66 $00 $00 $00 $00 $00 $66 $66 $ff $66 $ff $66 $66 $00 +$18 $3e $60 $3c $06 $7c $18 $00 $62 $66 $0c $18 $30 $66 $46 $00 +$3c $66 $3c $38 $67 $66 $3f $00 $06 $0c $18 $00 $00 $00 $00 $00 +$0c $18 $30 $30 $30 $18 $0c $00 $30 $18 $0c $0c $0c $18 $30 $00 +$00 $66 $3c $ff $3c $66 $00 $00 $00 $18 $18 $7e $18 $18 $00 $00 +$00 $00 $00 $00 $00 $18 $18 $30 $00 $00 $00 $7e $00 $00 $00 $00 +$00 $00 $00 $00 $00 $18 $18 $00 $00 $03 $06 $0c $18 $30 $60 $00 +$3c $66 $6e $76 $66 $66 $3c $00 $18 $18 $38 $18 $18 $18 $7e $00 +$3c $66 $06 $0c $30 $60 $7e $00 $3c $66 $06 $1c $06 $66 $3c $00 +$06 $0e $1e $66 $7f $06 $06 $00 $7e $60 $7c $06 $06 $66 $3c $00 +$3c $66 $60 $7c $66 $66 $3c $00 $7e $66 $0c $18 $18 $18 $18 $00 +$3c $66 $66 $3c $66 $66 $3c $00 $3c $66 $66 $3e $06 $66 $3c $00 +$00 $00 $18 $00 $00 $18 $00 $00 $00 $00 $18 $00 $00 $18 $18 $30 +$0e $18 $30 $60 $30 $18 $0e $00 $00 $00 $7e $00 $7e $00 $00 $00 +$70 $18 $0c $06 $0c $18 $70 $00 $3c $66 $06 $0c $18 $00 $18 $00 +$00 $00 $00 $ff $ff $00 $00 $00 $18 $3c $66 $7e $66 $66 $66 $00 +$7c $66 $66 $7c $66 $66 $7c $00 $3c $66 $60 $60 $60 $66 $3c $00 +$78 $6c $66 $66 $66 $6c $78 $00 $7e $60 $60 $78 $60 $60 $7e $00 +$7e $60 $60 $78 $60 $60 $60 $00 $3c $66 $60 $6e $66 $66 $3c $00 +$66 $66 $66 $7e $66 $66 $66 $00 $3c $18 $18 $18 $18 $18 $3c $00 +$1e $0c $0c $0c $0c $6c $38 $00 $66 $6c $78 $70 $78 $6c $66 $00 +$60 $60 $60 $60 $60 $60 $7e $00 $63 $77 $7f $6b $63 $63 $63 $00 +$66 $76 $7e $7e $6e $66 $66 $00 $3c $66 $66 $66 $66 $66 $3c $00 +$7c $66 $66 $7c $60 $60 $60 $00 $3c $66 $66 $66 $66 $3c $0e $00 +$7c $66 $66 $7c $78 $6c $66 $00 $3c $66 $60 $3c $06 $66 $3c $00 +$7e $18 $18 $18 $18 $18 $18 $00 $66 $66 $66 $66 $66 $66 $3c $00 +$66 $66 $66 $66 $66 $3c $18 $00 $63 $63 $63 $6b $7f $77 $63 $00 +$66 $66 $3c $18 $3c $66 $66 $00 $66 $66 $66 $3c $18 $18 $18 $00 +$7e $06 $0c $18 $30 $60 $7e $00 $18 $18 $18 $ff $ff $18 $18 $18 +$c0 $c0 $30 $30 $c0 $c0 $30 $30 $18 $18 $18 $18 $18 $18 $18 $18 +$33 $33 $cc $cc $33 $33 $cc $cc $33 $99 $cc $66 $33 $99 $cc $66 +$00 $00 $00 $00 $00 $00 $00 $00 $f0 $f0 $f0 $f0 $f0 $f0 $f0 $f0 +$00 $00 $00 $00 $ff $ff $ff $ff $ff $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $ff $c0 $c0 $c0 $c0 $c0 $c0 $c0 $c0 +$cc $cc $33 $33 $cc $cc $33 $33 $03 $03 $03 $03 $03 $03 $03 $03 +$00 $00 $00 $00 $cc $cc $33 $33 $cc $99 $33 $66 $cc $99 $33 $66 +$03 $03 $03 $03 $03 $03 $03 $03 $18 $18 $18 $1f $1f $18 $18 $18 +$00 $00 $00 $00 $0f $0f $0f $0f $18 $18 $18 $1f $1f $00 $00 $00 +$00 $00 $00 $f8 $f8 $18 $18 $18 $00 $00 $00 $00 $00 $00 $ff $ff +$00 $00 $00 $1f $1f $18 $18 $18 $18 $18 $18 $ff $ff $00 $00 $00 +$00 $00 $00 $ff $ff $18 $18 $18 $18 $18 $18 $f8 $f8 $18 $18 $18 +$c0 $c0 $c0 $c0 $c0 $c0 $c0 $c0 $e0 $e0 $e0 $e0 $e0 $e0 $e0 $e0 +$07 $07 $07 $07 $07 $07 $07 $07 $ff $ff $00 $00 $00 $00 $00 $00 +$ff $ff $ff $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $ff $ff $ff +$01 $03 $06 $6c $78 $70 $60 $00 $00 $00 $00 $00 $f0 $f0 $f0 $f0 +$0f $0f $0f $0f $00 $00 $00 $00 $18 $18 $18 $f8 $f8 $00 $00 $00 +$f0 $f0 $f0 $f0 $00 $00 $00 $00 $f0 $f0 $f0 $f0 $0f $0f $0f $0f +$c3 $99 $91 $91 $9f $99 $c3 $ff $ff $ff $c3 $f9 $c1 $99 $c1 $ff +$ff $9f $9f $83 $99 $99 $83 $ff $ff $ff $c3 $9f $9f $9f $c3 $ff +$ff $f9 $f9 $c1 $99 $99 $c1 $ff $ff $ff $c3 $99 $81 $9f $c3 $ff +$ff $f1 $e7 $c1 $e7 $e7 $e7 $ff $ff $ff $c1 $99 $99 $c1 $f9 $83 +$ff $9f $9f $83 $99 $99 $99 $ff $ff $e7 $ff $c7 $e7 $e7 $c3 $ff +$ff $f9 $ff $f9 $f9 $f9 $f9 $c3 $ff $9f $9f $93 $87 $93 $99 $ff +$ff $c7 $e7 $e7 $e7 $e7 $c3 $ff $ff $ff $99 $80 $80 $94 $9c $ff +$ff $ff $83 $99 $99 $99 $99 $ff $ff $ff $c3 $99 $99 $99 $c3 $ff +$ff $ff $83 $99 $99 $83 $9f $9f $ff $ff $c1 $99 $99 $c1 $f9 $f9 +$ff $ff $83 $99 $9f $9f $9f $ff $ff $ff $c1 $9f $c3 $f9 $83 $ff +$ff $e7 $81 $e7 $e7 $e7 $f1 $ff $ff $ff $99 $99 $99 $99 $c1 $ff +$ff $ff $99 $99 $99 $c3 $e7 $ff $ff $ff $9c $94 $80 $c1 $c9 $ff +$ff $ff $99 $c3 $e7 $c3 $99 $ff $ff $ff $99 $99 $99 $c1 $f3 $87 +$ff $ff $81 $f3 $e7 $cf $81 $ff $c3 $cf $cf $cf $cf $cf $c3 $ff +$f3 $ed $cf $83 $cf $9d $03 $ff $c3 $f3 $f3 $f3 $f3 $f3 $c3 $ff +$ff $e7 $c3 $81 $e7 $e7 $e7 $e7 $ff $ef $cf $80 $80 $cf $ef $ff +$ff $ff $ff $ff $ff $ff $ff $ff $e7 $e7 $e7 $e7 $ff $ff $e7 $ff +$99 $99 $99 $ff $ff $ff $ff $ff $99 $99 $00 $99 $00 $99 $99 $ff +$e7 $c1 $9f $c3 $f9 $83 $e7 $ff $9d $99 $f3 $e7 $cf $99 $b9 $ff +$c3 $99 $c3 $c7 $98 $99 $c0 $ff $f9 $f3 $e7 $ff $ff $ff $ff $ff +$f3 $e7 $cf $cf $cf $e7 $f3 $ff $cf $e7 $f3 $f3 $f3 $e7 $cf $ff +$ff $99 $c3 $00 $c3 $99 $ff $ff $ff $e7 $e7 $81 $e7 $e7 $ff $ff +$ff $ff $ff $ff $ff $e7 $e7 $cf $ff $ff $ff $81 $ff $ff $ff $ff +$ff $ff $ff $ff $ff $e7 $e7 $ff $ff $fc $f9 $f3 $e7 $cf $9f $ff +$c3 $99 $91 $89 $99 $99 $c3 $ff $e7 $e7 $c7 $e7 $e7 $e7 $81 $ff +$c3 $99 $f9 $f3 $cf $9f $81 $ff $c3 $99 $f9 $e3 $f9 $99 $c3 $ff +$f9 $f1 $e1 $99 $80 $f9 $f9 $ff $81 $9f $83 $f9 $f9 $99 $c3 $ff +$c3 $99 $9f $83 $99 $99 $c3 $ff $81 $99 $f3 $e7 $e7 $e7 $e7 $ff +$c3 $99 $99 $c3 $99 $99 $c3 $ff $c3 $99 $99 $c1 $f9 $99 $c3 $ff +$ff $ff $e7 $ff $ff $e7 $ff $ff $ff $ff $e7 $ff $ff $e7 $e7 $cf +$f1 $e7 $cf $9f $cf $e7 $f1 $ff $ff $ff $81 $ff $81 $ff $ff $ff +$8f $e7 $f3 $f9 $f3 $e7 $8f $ff $c3 $99 $f9 $f3 $e7 $ff $e7 $ff +$ff $ff $ff $00 $00 $ff $ff $ff $e7 $c3 $99 $81 $99 $99 $99 $ff +$83 $99 $99 $83 $99 $99 $83 $ff $c3 $99 $9f $9f $9f $99 $c3 $ff +$87 $93 $99 $99 $99 $93 $87 $ff $81 $9f $9f $87 $9f $9f $81 $ff +$81 $9f $9f $87 $9f $9f $9f $ff $c3 $99 $9f $91 $99 $99 $c3 $ff +$99 $99 $99 $81 $99 $99 $99 $ff $c3 $e7 $e7 $e7 $e7 $e7 $c3 $ff +$e1 $f3 $f3 $f3 $f3 $93 $c7 $ff $99 $93 $87 $8f $87 $93 $99 $ff +$9f $9f $9f $9f $9f $9f $81 $ff $9c $88 $80 $94 $9c $9c $9c $ff +$99 $89 $81 $81 $91 $99 $99 $ff $c3 $99 $99 $99 $99 $99 $c3 $ff +$83 $99 $99 $83 $9f $9f $9f $ff $c3 $99 $99 $99 $99 $c3 $f1 $ff +$83 $99 $99 $83 $87 $93 $99 $ff $c3 $99 $9f $c3 $f9 $99 $c3 $ff +$81 $e7 $e7 $e7 $e7 $e7 $e7 $ff $99 $99 $99 $99 $99 $99 $c3 $ff +$99 $99 $99 $99 $99 $c3 $e7 $ff $9c $9c $9c $94 $80 $88 $9c $ff +$99 $99 $c3 $e7 $c3 $99 $99 $ff $99 $99 $99 $c3 $e7 $e7 $e7 $ff +$81 $f9 $f3 $e7 $cf $9f $81 $ff $e7 $e7 $e7 $00 $00 $e7 $e7 $e7 +$3f $3f $cf $cf $3f $3f $cf $cf $e7 $e7 $e7 $e7 $e7 $e7 $e7 $e7 +$cc $cc $33 $33 $cc $cc $33 $33 $cc $66 $33 $99 $cc $66 $33 $99 +$ff $ff $ff $ff $ff $ff $ff $ff $0f $0f $0f $0f $0f $0f $0f $0f +$ff $ff $ff $ff $00 $00 $00 $00 $00 $ff $ff $ff $ff $ff $ff $ff +$ff $ff $ff $ff $ff $ff $ff $00 $3f $3f $3f $3f $3f $3f $3f $3f +$33 $33 $cc $cc $33 $33 $cc $cc $fc $fc $fc $fc $fc $fc $fc $fc +$ff $ff $ff $ff $33 $33 $cc $cc $33 $66 $cc $99 $33 $66 $cc $99 +$fc $fc $fc $fc $fc $fc $fc $fc $e7 $e7 $e7 $e0 $e0 $e7 $e7 $e7 +$ff $ff $ff $ff $f0 $f0 $f0 $f0 $e7 $e7 $e7 $e0 $e0 $ff $ff $ff +$ff $ff $ff $07 $07 $e7 $e7 $e7 $ff $ff $ff $ff $ff $ff $00 $00 +$ff $ff $ff $e0 $e0 $e7 $e7 $e7 $e7 $e7 $e7 $00 $00 $ff $ff $ff +$ff $ff $ff $00 $00 $e7 $e7 $e7 $e7 $e7 $e7 $07 $07 $e7 $e7 $e7 +$3f $3f $3f $3f $3f $3f $3f $3f $1f $1f $1f $1f $1f $1f $1f $1f +$f8 $f8 $f8 $f8 $f8 $f8 $f8 $f8 $00 $00 $ff $ff $ff $ff $ff $ff +$00 $00 $00 $ff $ff $ff $ff $ff $ff $ff $ff $ff $ff $00 $00 $00 +$fe $fc $f9 $93 $87 $8f $9f $ff $ff $ff $ff $ff $0f $0f $0f $0f +$f0 $f0 $f0 $f0 $ff $ff $ff $ff $e7 $e7 $e7 $07 $07 $ff $ff $ff +$0f $0f $0f $0f $ff $ff $ff $ff $0f $0f $0f $0f $f0 $f0 $f0 $f0 +;$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 diff --git a/eh_basic.asm b/eh_basic.asm index b8796ad..36bab1f 100644 --- a/eh_basic.asm +++ b/eh_basic.asm @@ -1,8723 +1,8723 @@ -; The code below was copied and adapted from Lee Davison’s -; code of EhBasic to be ran in MKBASIC (VM65) 6502 emulator. -; Original comments and credits follow: -; -; Enhanced BASIC to assemble under 6502 simulator, $ver 2.22 - -; $E7E1 $E7CF $E7C6 $E7D3 $E7D1 $E7D5 $E7CF $E81E $E825 - -; 2.00 new revision numbers start here -; 2.01 fixed LCASE$() and UCASE$() -; 2.02 new get value routine done -; 2.03 changed RND() to galoise method -; 2.04 fixed SPC() -; 2.05 new get value routine fixed -; 2.06 changed USR() code -; 2.07 fixed STR$() -; 2.08 changed INPUT and READ to remove need for $00 start to input buffer -; 2.09 fixed RND() -; 2.10 integrated missed changes from an earlier version -; 2.20 added ELSE to IF .. THEN and fixed IF .. GOTO to cause error -; 2.21 fixed IF .. THEN RETURN to not cause error -; 2.22 fixed RND() breaking the get byte routine - -; zero page use .. - -LAB_WARM = $00 ; BASIC warm start entry point -Wrmjpl = LAB_WARM+1; BASIC warm start vector jump low byte -Wrmjph = LAB_WARM+2; BASIC warm start vector jump high byte - -Usrjmp = $0A ; USR function JMP address -Usrjpl = Usrjmp+1 ; USR function JMP vector low byte -Usrjph = Usrjmp+2 ; USR function JMP vector high byte -Nullct = $0D ; nulls output after each line -TPos = $0E ; BASIC terminal position byte -TWidth = $0F ; BASIC terminal width byte -Iclim = $10 ; input column limit -Itempl = $11 ; temporary integer low byte -Itemph = Itempl+1 ; temporary integer high byte - -nums_1 = Itempl ; number to bin/hex string convert MSB -nums_2 = nums_1+1 ; number to bin/hex string convert -nums_3 = nums_1+2 ; number to bin/hex string convert LSB - -Srchc = $5B ; search character -Temp3 = Srchc ; temp byte used in number routines -Scnquo = $5C ; scan-between-quotes flag -Asrch = Scnquo ; alt search character - -XOAw_l = Srchc ; eXclusive OR, OR and AND word low byte -XOAw_h = Scnquo ; eXclusive OR, OR and AND word high byte - -Ibptr = $5D ; input buffer pointer -Dimcnt = Ibptr ; # of dimensions -Tindx = Ibptr ; token index - -Defdim = $5E ; default DIM flag -Dtypef = $5F ; data type flag, $FF=string, $00=numeric -Oquote = $60 ; open quote flag (b7) (Flag: DATA scan; LIST quote; memory) -Gclctd = $60 ; garbage collected flag -Sufnxf = $61 ; subscript/FNX flag, 1xxx xxx = FN(0xxx xxx) -Imode = $62 ; input mode flag, $00=INPUT, $80=READ - -Cflag = $63 ; comparison evaluation flag - -TabSiz = $64 ; TAB step size (was input flag) - -next_s = $65 ; next descriptor stack address - - ; these two bytes form a word pointer to the item - ; currently on top of the descriptor stack -last_sl = $66 ; last descriptor stack address low byte -last_sh = $67 ; last descriptor stack address high byte (always $00) - -des_sk = $68 ; descriptor stack start address (temp strings) - -; = $70 ; End of descriptor stack - -ut1_pl = $71 ; utility pointer 1 low byte -ut1_ph = ut1_pl+1 ; utility pointer 1 high byte -ut2_pl = $73 ; utility pointer 2 low byte -ut2_ph = ut2_pl+1 ; utility pointer 2 high byte - -Temp_2 = ut1_pl ; temp byte for block move - -FACt_1 = $75 ; FAC temp mantissa1 -FACt_2 = FACt_1+1 ; FAC temp mantissa2 -FACt_3 = FACt_2+1 ; FAC temp mantissa3 - -dims_l = FACt_2 ; array dimension size low byte -dims_h = FACt_3 ; array dimension size high byte - -TempB = $78 ; temp page 0 byte - -Smeml = $79 ; start of mem low byte (Start-of-Basic) -Smemh = Smeml+1 ; start of mem high byte (Start-of-Basic) -Svarl = $7B ; start of vars low byte (Start-of-Variables) -Svarh = Svarl+1 ; start of vars high byte (Start-of-Variables) -Sarryl = $7D ; var mem end low byte (Start-of-Arrays) -Sarryh = Sarryl+1 ; var mem end high byte (Start-of-Arrays) -Earryl = $7F ; array mem end low byte (End-of-Arrays) -Earryh = Earryl+1 ; array mem end high byte (End-of-Arrays) -Sstorl = $81 ; string storage low byte (String storage (moving down)) -Sstorh = Sstorl+1 ; string storage high byte (String storage (moving down)) -Sutill = $83 ; string utility ptr low byte -Sutilh = Sutill+1 ; string utility ptr high byte -Ememl = $85 ; end of mem low byte (Limit-of-memory) -Ememh = Ememl+1 ; end of mem high byte (Limit-of-memory) -Clinel = $87 ; current line low byte (Basic line number) -Clineh = Clinel+1 ; current line high byte (Basic line number) -Blinel = $89 ; break line low byte (Previous Basic line number) -Blineh = Blinel+1 ; break line high byte (Previous Basic line number) - -Cpntrl = $8B ; continue pointer low byte -Cpntrh = Cpntrl+1 ; continue pointer high byte - -Dlinel = $8D ; current DATA line low byte -Dlineh = Dlinel+1 ; current DATA line high byte - -Dptrl = $8F ; DATA pointer low byte -Dptrh = Dptrl+1 ; DATA pointer high byte - -Rdptrl = $91 ; read pointer low byte -Rdptrh = Rdptrl+1 ; read pointer high byte - -Varnm1 = $93 ; current var name 1st byte -Varnm2 = Varnm1+1 ; current var name 2nd byte - -Cvaral = $95 ; current var address low byte -Cvarah = Cvaral+1 ; current var address high byte - -Frnxtl = $97 ; var pointer for FOR/NEXT low byte -Frnxth = Frnxtl+1 ; var pointer for FOR/NEXT high byte - -Tidx1 = Frnxtl ; temp line index - -Lvarpl = Frnxtl ; let var pointer low byte -Lvarph = Frnxth ; let var pointer high byte - -prstk = $99 ; precedence stacked flag - -comp_f = $9B ; compare function flag, bits 0,1 and 2 used - ; bit 2 set if > - ; bit 1 set if = - ; bit 0 set if < - -func_l = $9C ; function pointer low byte -func_h = func_l+1 ; function pointer high byte - -garb_l = func_l ; garbage collection working pointer low byte -garb_h = func_h ; garbage collection working pointer high byte - -des_2l = $9E ; string descriptor_2 pointer low byte -des_2h = des_2l+1 ; string descriptor_2 pointer high byte - -g_step = $A0 ; garbage collect step size - -Fnxjmp = $A1 ; jump vector for functions -Fnxjpl = Fnxjmp+1 ; functions jump vector low byte -Fnxjph = Fnxjmp+2 ; functions jump vector high byte - -g_indx = Fnxjpl ; garbage collect temp index - -FAC2_r = $A3 ; FAC2 rounding byte - -Adatal = $A4 ; array data pointer low byte -Adatah = Adatal+1 ; array data pointer high byte - -Nbendl = Adatal ; new block end pointer low byte -Nbendh = Adatah ; new block end pointer high byte - -Obendl = $A6 ; old block end pointer low byte -Obendh = Obendl+1 ; old block end pointer high byte - -numexp = $A8 ; string to float number exponent count -expcnt = $A9 ; string to float exponent count - -numbit = numexp ; bit count for array element calculations - -numdpf = $AA ; string to float decimal point flag -expneg = $AB ; string to float eval exponent -ve flag - -Astrtl = numdpf ; array start pointer low byte -Astrth = expneg ; array start pointer high byte - -Histrl = numdpf ; highest string low byte -Histrh = expneg ; highest string high byte - -Baslnl = numdpf ; BASIC search line pointer low byte -Baslnh = expneg ; BASIC search line pointer high byte - -Fvar_l = numdpf ; find/found variable pointer low byte -Fvar_h = expneg ; find/found variable pointer high byte - -Ostrtl = numdpf ; old block start pointer low byte -Ostrth = expneg ; old block start pointer high byte - -Vrschl = numdpf ; variable search pointer low byte -Vrschh = expneg ; variable search pointer high byte - -FAC1_e = $AC ; FAC1 exponent -FAC1_1 = FAC1_e+1 ; FAC1 mantissa1 -FAC1_2 = FAC1_e+2 ; FAC1 mantissa2 -FAC1_3 = FAC1_e+3 ; FAC1 mantissa3 -FAC1_s = FAC1_e+4 ; FAC1 sign (b7) - -str_ln = FAC1_e ; string length -str_pl = FAC1_1 ; string pointer low byte -str_ph = FAC1_2 ; string pointer high byte - -des_pl = FAC1_2 ; string descriptor pointer low byte -des_ph = FAC1_3 ; string descriptor pointer high byte - -mids_l = FAC1_3 ; MID$ string temp length byte - -negnum = $B1 ; string to float eval -ve flag -numcon = $B1 ; series evaluation constant count - -FAC1_o = $B2 ; FAC1 overflow byte - -FAC2_e = $B3 ; FAC2 exponent -FAC2_1 = FAC2_e+1 ; FAC2 mantissa1 -FAC2_2 = FAC2_e+2 ; FAC2 mantissa2 -FAC2_3 = FAC2_e+3 ; FAC2 mantissa3 -FAC2_s = FAC2_e+4 ; FAC2 sign (b7) - -FAC_sc = $B8 ; FAC sign comparison, Acc#1 vs #2 -FAC1_r = $B9 ; FAC1 rounding byte - -ssptr_l = FAC_sc ; string start pointer low byte -ssptr_h = FAC1_r ; string start pointer high byte - -sdescr = FAC_sc ; string descriptor pointer - -csidx = $BA ; line crunch save index -Asptl = csidx ; array size/pointer low byte -Aspth = $BB ; array size/pointer high byte - -Btmpl = Asptl ; BASIC pointer temp low byte -Btmph = Aspth ; BASIC pointer temp low byte - -Cptrl = Asptl ; BASIC pointer temp low byte -Cptrh = Aspth ; BASIC pointer temp low byte - -Sendl = Asptl ; BASIC pointer temp low byte -Sendh = Aspth ; BASIC pointer temp low byte - -LAB_IGBY = $BC ; get next BASIC byte subroutine - -LAB_GBYT = $C2 ; get current BASIC byte subroutine -Bpntrl = $C3 ; BASIC execute (get byte) pointer low byte -Bpntrh = Bpntrl+1 ; BASIC execute (get byte) pointer high byte - -; = $D7 ; end of get BASIC char subroutine - -Rbyte4 = $D8 ; extra PRNG byte -Rbyte1 = Rbyte4+1 ; most significant PRNG byte -Rbyte2 = Rbyte4+2 ; middle PRNG byte -Rbyte3 = Rbyte4+3 ; least significant PRNG byte - -NmiBase = $DC ; NMI handler enabled/setup/triggered flags - ; bit function - ; === ======== - ; 7 interrupt enabled - ; 6 interrupt setup - ; 5 interrupt happened -; = $DD ; NMI handler addr low byte -; = $DE ; NMI handler addr high byte -IrqBase = $DF ; IRQ handler enabled/setup/triggered flags -; = $E0 ; IRQ handler addr low byte -; = $E1 ; IRQ handler addr high byte - -; = $DE ; unused -; = $DF ; unused -; = $E0 ; unused -; = $E1 ; unused -; = $E2 ; unused -; = $E3 ; unused -; = $E4 ; unused -; = $E5 ; unused -; = $E6 ; unused -; = $E7 ; unused -; = $E8 ; unused -; = $E9 ; unused -; = $EA ; unused -; = $EB ; unused -; = $EC ; unused -; = $ED ; unused -; = $EE ; unused - -Decss = $EF ; number to decimal string start -Decssp1 = Decss+1 ; number to decimal string start - -; = $FF ; decimal string end - -; token values needed for BASIC - -; primary command tokens (can start a statement) - -TK_END = $80 ; END token -TK_FOR = TK_END+1 ; FOR token -TK_NEXT = TK_FOR+1 ; NEXT token -TK_DATA = TK_NEXT+1 ; DATA token -TK_INPUT = TK_DATA+1 ; INPUT token -TK_DIM = TK_INPUT+1 ; DIM token -TK_READ = TK_DIM+1 ; READ token -TK_LET = TK_READ+1 ; LET token -TK_DEC = TK_LET+1 ; DEC token -TK_GOTO = TK_DEC+1 ; GOTO token -TK_RUN = TK_GOTO+1 ; RUN token -TK_IF = TK_RUN+1 ; IF token -TK_RESTORE = TK_IF+1 ; RESTORE token -TK_GOSUB = TK_RESTORE+1 ; GOSUB token -TK_RETIRQ = TK_GOSUB+1 ; RETIRQ token -TK_RETNMI = TK_RETIRQ+1 ; RETNMI token -TK_RETURN = TK_RETNMI+1 ; RETURN token -TK_REM = TK_RETURN+1 ; REM token -TK_STOP = TK_REM+1 ; STOP token -TK_ON = TK_STOP+1 ; ON token -TK_NULL = TK_ON+1 ; NULL token -TK_INC = TK_NULL+1 ; INC token -TK_WAIT = TK_INC+1 ; WAIT token -TK_LOAD = TK_WAIT+1 ; LOAD token -TK_SAVE = TK_LOAD+1 ; SAVE token -TK_DEF = TK_SAVE+1 ; DEF token -TK_POKE = TK_DEF+1 ; POKE token -TK_DOKE = TK_POKE+1 ; DOKE token -TK_CALL = TK_DOKE+1 ; CALL token -TK_DO = TK_CALL+1 ; DO token -TK_LOOP = TK_DO+1 ; LOOP token -TK_PRINT = TK_LOOP+1 ; PRINT token -TK_CONT = TK_PRINT+1 ; CONT token -TK_LIST = TK_CONT+1 ; LIST token -TK_CLEAR = TK_LIST+1 ; CLEAR token -TK_NEW = TK_CLEAR+1 ; NEW token -TK_WIDTH = TK_NEW+1 ; WIDTH token -TK_GET = TK_WIDTH+1 ; GET token -TK_SWAP = TK_GET+1 ; SWAP token -TK_BITSET = TK_SWAP+1 ; BITSET token -TK_BITCLR = TK_BITSET+1 ; BITCLR token -TK_IRQ = TK_BITCLR+1 ; IRQ token -TK_NMI = TK_IRQ+1 ; NMI token - -; secondary command tokens, can't start a statement - -TK_TAB = TK_NMI+1 ; TAB token -TK_ELSE = TK_TAB+1 ; ELSE token -TK_TO = TK_ELSE+1 ; TO token -TK_FN = TK_TO+1 ; FN token -TK_SPC = TK_FN+1 ; SPC token -TK_THEN = TK_SPC+1 ; THEN token -TK_NOT = TK_THEN+1 ; NOT token -TK_STEP = TK_NOT+1 ; STEP token -TK_UNTIL = TK_STEP+1 ; UNTIL token -TK_WHILE = TK_UNTIL+1 ; WHILE token -TK_OFF = TK_WHILE+1 ; OFF token - -; opperator tokens - -TK_PLUS = TK_OFF+1 ; + token -TK_MINUS = TK_PLUS+1 ; - token -TK_MUL = TK_MINUS+1 ; * token -TK_DIV = TK_MUL+1 ; / token -TK_POWER = TK_DIV+1 ; ^ token -TK_AND = TK_POWER+1 ; AND token -TK_EOR = TK_AND+1 ; EOR token -TK_OR = TK_EOR+1 ; OR token -TK_RSHIFT = TK_OR+1 ; RSHIFT token -TK_LSHIFT = TK_RSHIFT+1 ; LSHIFT token -TK_GT = TK_LSHIFT+1 ; > token -TK_EQUAL = TK_GT+1 ; = token -TK_LT = TK_EQUAL+1 ; < token - -; functions tokens - -TK_SGN = TK_LT+1 ; SGN token -TK_INT = TK_SGN+1 ; INT token -TK_ABS = TK_INT+1 ; ABS token -TK_USR = TK_ABS+1 ; USR token -TK_FRE = TK_USR+1 ; FRE token -TK_POS = TK_FRE+1 ; POS token -TK_SQR = TK_POS+1 ; SQR token -TK_RND = TK_SQR+1 ; RND token -TK_LOG = TK_RND+1 ; LOG token -TK_EXP = TK_LOG+1 ; EXP token -TK_COS = TK_EXP+1 ; COS token -TK_SIN = TK_COS+1 ; SIN token -TK_TAN = TK_SIN+1 ; TAN token -TK_ATN = TK_TAN+1 ; ATN token -TK_PEEK = TK_ATN+1 ; PEEK token -TK_DEEK = TK_PEEK+1 ; DEEK token -TK_SADD = TK_DEEK+1 ; SADD token -TK_LEN = TK_SADD+1 ; LEN token -TK_STRS = TK_LEN+1 ; STR$ token -TK_VAL = TK_STRS+1 ; VAL token -TK_ASC = TK_VAL+1 ; ASC token -TK_UCASES = TK_ASC+1 ; UCASE$ token -TK_LCASES = TK_UCASES+1 ; LCASE$ token -TK_CHRS = TK_LCASES+1 ; CHR$ token -TK_HEXS = TK_CHRS+1 ; HEX$ token -TK_BINS = TK_HEXS+1 ; BIN$ token -TK_BITTST = TK_BINS+1 ; BITTST token -TK_MAX = TK_BITTST+1 ; MAX token -TK_MIN = TK_MAX+1 ; MIN token -TK_PI = TK_MIN+1 ; PI token -TK_TWOPI = TK_PI+1 ; TWOPI token -TK_VPTR = TK_TWOPI+1 ; VARPTR token -TK_LEFTS = TK_VPTR+1 ; LEFT$ token -TK_RIGHTS = TK_LEFTS+1 ; RIGHT$ token -TK_MIDS = TK_RIGHTS+1 ; MID$ token - -; offsets from a base of X or Y - -PLUS_0 = $00 ; X or Y plus 0 -PLUS_1 = $01 ; X or Y plus 1 -PLUS_2 = $02 ; X or Y plus 2 -PLUS_3 = $03 ; X or Y plus 3 - -LAB_STAK = $0100 ; stack bottom, no offset - -LAB_SKFE = LAB_STAK+$FE - ; flushed stack address -LAB_SKFF = LAB_STAK+$FF - ; flushed stack address - -ccflag = $0200 ; BASIC CTRL-C flag, 00 = enabled, 01 = dis -ccbyte = ccflag+1 ; BASIC CTRL-C byte -ccnull = ccbyte+1 ; BASIC CTRL-C byte timeout - -VEC_CC = ccnull+1 ; ctrl c check vector - -VEC_IN = VEC_CC+2 ; input vector -VEC_OUT = VEC_IN+2 ; output vector -VEC_LD = VEC_OUT+2 ; load vector -VEC_SV = VEC_LD+2 ; save vector - -; Ibuffs can now be anywhere in RAM, ensure that the max length is < $80 - -IRQ_vec = VEC_SV+2 - -Ibuffs = IRQ_vec+$14 ; start of input buffer after IRQ/NMI code -Ibuffe = Ibuffs+$47 ; end of input buffer - - .ORG $FFC0 - -; I/O routines for MKBASIC (V65) emulator. - -CHRIN - LDA $FFE1 ; Read from char IO address, non-blocking - BEQ ECHRIN ; if null, assume no character in buffer - CMP #'a' ; < 'a'? - BCC DCHRIN ; yes, done - CMP #'{' ; >= '{'? - BCS DCHRIN ; yes, done - AND #$5F ; no, convert to upper case -DCHRIN - SEC ; These is character waiting, set CARRY flag - RTS -ECHRIN - CLC ; no character in buffer, clear CARRY - RTS - -CHROUT - STA $FFE0 ; write to char IO address - AND #$FF ; set flags - RTS - - -Ram_base = $0300 ; start of user RAM (set as needed, should be page aligned) -Ram_top = $C000 ; end of user RAM+1 (set as needed, should be page aligned) - -; This start can be changed to suit your system - - *= $C000 - -; BASIC cold start entry point - -; new page 2 initialisation, copy block to ccflag on - -LAB_COLD - CLD - LDY #PG2_TABE-PG2_TABS-1 - ; byte count-1 -LAB_2D13 - LDA PG2_TABS,Y ; get byte - STA ccflag,Y ; store in page 2 - DEY ; decrement count - BPL LAB_2D13 ; loop if not done - - LDX #$FF ; set byte - STX Ibuffs - STX Clineh ; set current line high byte (set immediate mode) - TXS ; reset stack pointer - - LDA #$4C ; code for JMP - STA Fnxjmp ; save for jump vector for functions - -; copy block from LAB_2CEE to $00BC - $00D3 - - LDX #StrTab-LAB_2CEE ; set byte count -LAB_2D4E - LDA LAB_2CEE-1,X ; get byte from table - STA LAB_IGBY-1,X ; save byte in page zero - DEX ; decrement count - BNE LAB_2D4E ; loop if not all done - -; copy block from StrTab to $0000 - $0012 - -LAB_GMEM - LDX #EndTab-StrTab-1 ; set byte count-1 -TabLoop - LDA StrTab,X ; get byte from table - STA PLUS_0,X ; save byte in page zero - DEX ; decrement count - BPL TabLoop ; loop if not all done - -; set-up start values - - LDA #$00 ; clear A - STA NmiBase ; clear NMI handler enabled flag - STA IrqBase ; clear IRQ handler enabled flag - STA FAC1_o ; clear FAC1 overflow byte - STA last_sh ; clear descriptor stack top item pointer high byte - - LDA #$0E ; set default tab size - STA TabSiz ; save it - LDA #$03 ; set garbage collect step size for descriptor stack - STA g_step ; save it - LDX #des_sk ; descriptor stack start - STX next_s ; set descriptor stack pointer - JSR LAB_CRLF ; print CR/LF - LDA #LAB_MSZM ; point to memory size message (high addr) - JSR LAB_18C3 ; print null terminated string from memory - JSR LAB_INLN ; print "? " and get BASIC input - STX Bpntrl ; set BASIC execute pointer low byte - STY Bpntrh ; set BASIC execute pointer high byte - JSR LAB_GBYT ; get last byte back - - BNE LAB_2DAA ; branch if not null (user typed something) - - LDY #$00 ; else clear Y - ; character was null so get memory size the hard way - ; we get here with Y=0 and Itempl/h = Ram_base -LAB_2D93 - INC Itempl ; increment temporary integer low byte - BNE LAB_2D99 ; branch if no overflow - - INC Itemph ; increment temporary integer high byte - LDA Itemph ; get high byte - CMP #>Ram_top ; compare with top of RAM+1 - BEQ LAB_2DB6 ; branch if match (end of user RAM) - -LAB_2D99 - LDA #$55 ; set test byte - STA (Itempl),Y ; save via temporary integer - CMP (Itempl),Y ; compare via temporary integer - BNE LAB_2DB6 ; branch if fail - - ASL ; shift test byte left (now $AA) - STA (Itempl),Y ; save via temporary integer - CMP (Itempl),Y ; compare via temporary integer - BEQ LAB_2D93 ; if ok go do next byte - - BNE LAB_2DB6 ; branch if fail - -LAB_2DAA - JSR LAB_2887 ; get FAC1 from string - LDA FAC1_e ; get FAC1 exponent - CMP #$98 ; compare with exponent = 2^24 - BCS LAB_GMEM ; if too large go try again - - JSR LAB_F2FU ; save integer part of FAC1 in temporary integer - ; (no range check) - -LAB_2DB6 - LDA Itempl ; get temporary integer low byte - LDY Itemph ; get temporary integer high byte - CPY #Ram_top ; compare with top of RAM high byte -; BCC MEM_OK ; branch if < RAM top - -; BNE LAB_GMEM ; if too large go try again - ; else was = so compare low bytes -; CMP #Ram_base ; set start addr high byte - STY Smeml ; save start of mem low byte - STX Smemh ; save start of mem high byte - -; this line is only needed if Ram_base is not $xx00 - -; LDY #$00 ; clear Y - TYA ; clear A - STA (Smeml),Y ; clear first byte - INC Smeml ; increment start of mem low byte - -; these two lines are only needed if Ram_base is $xxFF - -; BNE LAB_2E05 ; branch if no rollover - -; INC Smemh ; increment start of mem high byte -LAB_2E05 - JSR LAB_CRLF ; print CR/LF - JSR LAB_1463 ; do "NEW" and "CLEAR" - LDA Ememl ; get end of mem low byte - SEC ; set carry for subtract - SBC Smeml ; subtract start of mem low byte - TAX ; copy to X - LDA Ememh ; get end of mem high byte - SBC Smemh ; subtract start of mem high byte - JSR LAB_295E ; print XA as unsigned integer (bytes free) - LDA #LAB_SMSG ; point to sign-on message (high addr) - JSR LAB_18C3 ; print null terminated string from memory - LDA #LAB_1274 ; warm start vector high byte - STA Wrmjpl ; save warm start vector low byte - STY Wrmjph ; save warm start vector high byte - JMP (Wrmjpl) ; go do warm start - -; open up space in memory -; move (Ostrtl)-(Obendl) to new block ending at (Nbendl) - -; Nbendl,Nbendh - new block end address (A/Y) -; Obendl,Obendh - old block end address -; Ostrtl,Ostrth - old block start address - -; returns with .. - -; Nbendl,Nbendh - new block start address (high byte - $100) -; Obendl,Obendh - old block start address (high byte - $100) -; Ostrtl,Ostrth - old block start address (unchanged) - -LAB_11CF - JSR LAB_121F ; check available memory, "Out of memory" error if no room - ; addr to check is in AY (low/high) - STA Earryl ; save new array mem end low byte - STY Earryh ; save new array mem end high byte - -; open up space in memory -; move (Ostrtl)-(Obendl) to new block ending at (Nbendl) -; don't set array end - -LAB_11D6 - SEC ; set carry for subtract - LDA Obendl ; get block end low byte - SBC Ostrtl ; subtract block start low byte - TAY ; copy MOD(block length/$100) byte to Y - LDA Obendh ; get block end high byte - SBC Ostrth ; subtract block start high byte - TAX ; copy block length high byte to X - INX ; +1 to allow for count=0 exit - TYA ; copy block length low byte to A - BEQ LAB_120A ; branch if length low byte=0 - - ; block is (X-1)*256+Y bytes, do the Y bytes first - - SEC ; set carry for add + 1, two's complement - EOR #$FF ; invert low byte for subtract - ADC Obendl ; add block end low byte - - STA Obendl ; save corrected old block end low byte - BCS LAB_11F3 ; branch if no underflow - - DEC Obendh ; else decrement block end high byte - SEC ; set carry for add + 1, two's complement -LAB_11F3 - TYA ; get MOD(block length/$100) byte - EOR #$FF ; invert low byte for subtract - ADC Nbendl ; add destination end low byte - STA Nbendl ; save modified new block end low byte - BCS LAB_1203 ; branch if no underflow - - DEC Nbendh ; else decrement block end high byte - BCC LAB_1203 ; branch always - -LAB_11FF - LDA (Obendl),Y ; get byte from source - STA (Nbendl),Y ; copy byte to destination -LAB_1203 - DEY ; decrement index - BNE LAB_11FF ; loop until Y=0 - - ; now do Y=0 indexed byte - LDA (Obendl),Y ; get byte from source - STA (Nbendl),Y ; save byte to destination -LAB_120A - DEC Obendh ; decrement source pointer high byte - DEC Nbendh ; decrement destination pointer high byte - DEX ; decrement block count - BNE LAB_1203 ; loop until count = $0 - - RTS - -; check room on stack for A bytes -; stack too deep? do OM error - -LAB_1212 - STA TempB ; save result in temp byte - TSX ; copy stack - CPX TempB ; compare new "limit" with stack - BCC LAB_OMER ; if stack < limit do "Out of memory" error then warm start - - RTS - -; check available memory, "Out of memory" error if no room -; addr to check is in AY (low/high) - -LAB_121F - CPY Sstorh ; compare bottom of string mem high byte - BCC LAB_124B ; if less then exit (is ok) - - BNE LAB_1229 ; skip next test if greater (tested <) - - ; high byte was =, now do low byte - CMP Sstorl ; compare with bottom of string mem low byte - BCC LAB_124B ; if less then exit (is ok) - - ; addr is > string storage ptr (oops!) -LAB_1229 - PHA ; push addr low byte - LDX #$08 ; set index to save Adatal to expneg inclusive - TYA ; copy addr high byte (to push on stack) - - ; save misc numeric work area -LAB_122D - PHA ; push byte - LDA Adatal-1,X ; get byte from Adatal to expneg ( ,$00 not pushed) - DEX ; decrement index - BPL LAB_122D ; loop until all done - - JSR LAB_GARB ; garbage collection routine - - ; restore misc numeric work area - LDX #$00 ; clear the index to restore bytes -LAB_1238 - PLA ; pop byte - STA Adatal,X ; save byte to Adatal to expneg - INX ; increment index - CPX #$08 ; compare with end + 1 - BMI LAB_1238 ; loop if more to do - - PLA ; pop addr high byte - TAY ; copy back to Y - PLA ; pop addr low byte - CPY Sstorh ; compare bottom of string mem high byte - BCC LAB_124B ; if less then exit (is ok) - - BNE LAB_OMER ; if greater do "Out of memory" error then warm start - - ; high byte was =, now do low byte - CMP Sstorl ; compare with bottom of string mem low byte - BCS LAB_OMER ; if >= do "Out of memory" error then warm start - - ; ok exit, carry clear -LAB_124B - RTS - -; do "Out of memory" error then warm start - -LAB_OMER - LDX #$0C ; error code $0C ("Out of memory" error) - -; do error #X, then warm start - -LAB_XERR - JSR LAB_CRLF ; print CR/LF - - LDA LAB_BAER,X ; get error message pointer low byte - LDY LAB_BAER+1,X ; get error message pointer high byte - JSR LAB_18C3 ; print null terminated string from memory - - JSR LAB_1491 ; flush stack and clear continue flag - LDA #LAB_EMSG ; point to " Error" high addr -LAB_1269 - JSR LAB_18C3 ; print null terminated string from memory - LDY Clineh ; get current line high byte - INY ; increment it - BEQ LAB_1274 ; go do warm start (was immediate mode) - - ; else print line number - JSR LAB_2953 ; print " in line [LINE #]" - -; BASIC warm start entry point -; wait for Basic command - -LAB_1274 - ; clear ON IRQ/NMI bytes - LDA #$00 ; clear A - STA IrqBase ; clear enabled byte - STA NmiBase ; clear enabled byte - LDA #LAB_RMSG ; point to "Ready" message high byte - - JSR LAB_18C3 ; go do print string - CLC - -; wait for Basic command (no "Ready") - -LAB_127D - JSR LAB_1357 ; call for BASIC input -LAB_1280 - STX Bpntrl ; set BASIC execute pointer low byte - STY Bpntrh ; set BASIC execute pointer high byte - JSR LAB_GBYT ; scan memory - BEQ LAB_127D ; loop while null - -; got to interpret input line now .. - - LDX #$FF ; current line to null value - STX Clineh ; set current line high byte - BCC LAB_1295 ; branch if numeric character (handle new BASIC line) - - ; no line number .. immediate mode - JSR LAB_13A6 ; crunch keywords into Basic tokens - JMP LAB_15F6 ; go scan and interpret code - -; handle new BASIC line - -LAB_1295 - JSR LAB_GFPN ; get fixed-point number into temp integer - JSR LAB_13A6 ; crunch keywords into Basic tokens - STY Ibptr ; save index pointer to end of crunched line - JSR LAB_SSLN ; search BASIC for temp integer line number - BCC LAB_12E6 ; branch if not found - - ; aroooogah! line # already exists! delete it - LDY #$01 ; set index to next line pointer high byte - LDA (Baslnl),Y ; get next line pointer high byte - STA ut1_ph ; save it - LDA Svarl ; get start of vars low byte - STA ut1_pl ; save it - LDA Baslnh ; get found line pointer high byte - STA ut2_ph ; save it - LDA Baslnl ; get found line pointer low byte - DEY ; decrement index - SBC (Baslnl),Y ; subtract next line pointer low byte - CLC ; clear carry for add - ADC Svarl ; add start of vars low byte - STA Svarl ; save new start of vars low byte - STA ut2_pl ; save destination pointer low byte - LDA Svarh ; get start of vars high byte - ADC #$FF ; -1 + carry - STA Svarh ; save start of vars high byte - SBC Baslnh ; subtract found line pointer high byte - TAX ; copy to block count - SEC ; set carry for subtract - LDA Baslnl ; get found line pointer low byte - SBC Svarl ; subtract start of vars low byte - TAY ; copy to bytes in first block count - BCS LAB_12D0 ; branch if overflow - - INX ; increment block count (correct for =0 loop exit) - DEC ut2_ph ; decrement destination high byte -LAB_12D0 - CLC ; clear carry for add - ADC ut1_pl ; add source pointer low byte - BCC LAB_12D8 ; branch if no overflow - - DEC ut1_ph ; else decrement source pointer high byte - CLC ; clear carry - - ; close up memory to delete old line -LAB_12D8 - LDA (ut1_pl),Y ; get byte from source - STA (ut2_pl),Y ; copy to destination - INY ; increment index - BNE LAB_12D8 ; while <> 0 do this block - - INC ut1_ph ; increment source pointer high byte - INC ut2_ph ; increment destination pointer high byte - DEX ; decrement block count - BNE LAB_12D8 ; loop until all done - - ; got new line in buffer and no existing same # -LAB_12E6 - LDA Ibuffs ; get byte from start of input buffer - BEQ LAB_1319 ; if null line just go flush stack/vars and exit - - ; got new line and it isn't empty line - LDA Ememl ; get end of mem low byte - LDY Ememh ; get end of mem high byte - STA Sstorl ; set bottom of string space low byte - STY Sstorh ; set bottom of string space high byte - LDA Svarl ; get start of vars low byte (end of BASIC) - STA Obendl ; save old block end low byte - LDY Svarh ; get start of vars high byte (end of BASIC) - STY Obendh ; save old block end high byte - ADC Ibptr ; add input buffer pointer (also buffer length) - BCC LAB_1301 ; branch if no overflow from add - - INY ; else increment high byte -LAB_1301 - STA Nbendl ; save new block end low byte (move to, low byte) - STY Nbendh ; save new block end high byte - JSR LAB_11CF ; open up space in memory - ; old start pointer Ostrtl,Ostrth set by the find line call - LDA Earryl ; get array mem end low byte - LDY Earryh ; get array mem end high byte - STA Svarl ; save start of vars low byte - STY Svarh ; save start of vars high byte - LDY Ibptr ; get input buffer pointer (also buffer length) - DEY ; adjust for loop type -LAB_1311 - LDA Ibuffs-4,Y ; get byte from crunched line - STA (Baslnl),Y ; save it to program memory - DEY ; decrement count - CPY #$03 ; compare with first byte-1 - BNE LAB_1311 ; continue while count <> 3 - - LDA Itemph ; get line # high byte - STA (Baslnl),Y ; save it to program memory - DEY ; decrement count - LDA Itempl ; get line # low byte - STA (Baslnl),Y ; save it to program memory - DEY ; decrement count - LDA #$FF ; set byte to allow chain rebuild. if you didn't set this - ; byte then a zero already here would stop the chain rebuild - ; as it would think it was the [EOT] marker. - STA (Baslnl),Y ; save it to program memory - -LAB_1319 - JSR LAB_1477 ; reset execution to start, clear vars and flush stack - LDX Smeml ; get start of mem low byte - LDA Smemh ; get start of mem high byte - LDY #$01 ; index to high byte of next line pointer -LAB_1325 - STX ut1_pl ; set line start pointer low byte - STA ut1_ph ; set line start pointer high byte - LDA (ut1_pl),Y ; get it - BEQ LAB_133E ; exit if end of program - -; rebuild chaining of Basic lines - - LDY #$04 ; point to first code byte of line - ; there is always 1 byte + [EOL] as null entries are deleted -LAB_1330 - INY ; next code byte - LDA (ut1_pl),Y ; get byte - BNE LAB_1330 ; loop if not [EOL] - - SEC ; set carry for add + 1 - TYA ; copy end index - ADC ut1_pl ; add to line start pointer low byte - TAX ; copy to X - LDY #$00 ; clear index, point to this line's next line pointer - STA (ut1_pl),Y ; set next line pointer low byte - TYA ; clear A - ADC ut1_ph ; add line start pointer high byte + carry - INY ; increment index to high byte - STA (ut1_pl),Y ; save next line pointer low byte - BCC LAB_1325 ; go do next line, branch always, carry clear - - -LAB_133E - JMP LAB_127D ; else we just wait for Basic command, no "Ready" - -; print "? " and get BASIC input - -LAB_INLN - JSR LAB_18E3 ; print "?" character - JSR LAB_18E0 ; print " " - BNE LAB_1357 ; call for BASIC input and return - -; receive line from keyboard - - ; $08 as delete key (BACKSPACE on standard keyboard) -LAB_134B - JSR LAB_PRNA ; go print the character - DEX ; decrement the buffer counter (delete) - .byte $2C ; make LDX into BIT abs - -; call for BASIC input (main entry point) - -LAB_1357 - LDX #$00 ; clear BASIC line buffer pointer -LAB_1359 - JSR V_INPT ; call scan input device - BCC LAB_1359 ; loop if no byte - - BEQ LAB_1359 ; loop until valid input (ignore NULLs) - - CMP #$07 ; compare with [BELL] - BEQ LAB_1378 ; branch if [BELL] - - CMP #$0D ; compare with [CR] - BEQ LAB_1384 ; do CR/LF exit if [CR] - - CPX #$00 ; compare pointer with $00 - BNE LAB_1374 ; branch if not empty - -; next two lines ignore any non print character and [SPACE] if input buffer empty - - CMP #$21 ; compare with [SP]+1 - BCC LAB_1359 ; if < ignore character - -LAB_1374 - CMP #$08 ; compare with [BACKSPACE] (delete last character) - BEQ LAB_134B ; go delete last character - -LAB_1378 - CPX #Ibuffe-Ibuffs ; compare character count with max - BCS LAB_138E ; skip store and do [BELL] if buffer full - - STA Ibuffs,X ; else store in buffer - INX ; increment pointer -LAB_137F - JSR LAB_PRNA ; go print the character - BNE LAB_1359 ; always loop for next character - -LAB_1384 - JMP LAB_1866 ; do CR/LF exit to BASIC - -; announce buffer full - -LAB_138E - LDA #$07 ; [BELL] character into A - BNE LAB_137F ; go print the [BELL] but ignore input character - ; branch always - -; crunch keywords into Basic tokens -; position independent buffer version .. -; faster, dictionary search version .... - -LAB_13A6 - LDY #$FF ; set save index (makes for easy math later) - - SEC ; set carry for subtract - LDA Bpntrl ; get basic execute pointer low byte - SBC #= go save byte then continue crunching - - CMP #'<' ; compare with "<" - BCS LAB_13CC ; if >= go crunch now - - CMP #'0' ; compare with "0" - BCS LAB_13EC ; if >= go save byte then continue crunching - - STA Scnquo ; save buffer byte as search character - CMP #$22 ; is it quote character? - BEQ LAB_1410 ; branch if so (copy quoted string) - - CMP #'*' ; compare with "*" - BCC LAB_13EC ; if < go save byte then continue crunching - - ; else crunch now -LAB_13CC - BIT Oquote ; get open quote/DATA token flag - BVS LAB_13EC ; branch if b6 of Oquote set (was DATA) - ; go save byte then continue crunching - - STX TempB ; save buffer read index - STY csidx ; copy buffer save index - LDY #TAB_1STC ; get keyword first character table high address - STY ut2_ph ; save pointer high byte - LDY #$00 ; clear table pointer - -LAB_13D0 - CMP (ut2_pl),Y ; compare with keyword first character table byte - BEQ LAB_13D1 ; go do word_table_chr if match - - BCC LAB_13EA ; if < keyword first character table byte go restore - ; Y and save to crunched - - INY ; else increment pointer - BNE LAB_13D0 ; and loop (branch always) - -; have matched first character of some keyword - -LAB_13D1 - TYA ; copy matching index - ASL ; *2 (bytes per pointer) - TAX ; copy to new index - LDA TAB_CHRT,X ; get keyword table pointer low byte - STA ut2_pl ; save pointer low byte - LDA TAB_CHRT+1,X ; get keyword table pointer high byte - STA ut2_ph ; save pointer high byte - - LDY #$FF ; clear table pointer (make -1 for start) - - LDX TempB ; restore buffer read index - -LAB_13D6 - INY ; next table byte - LDA (ut2_pl),Y ; get byte from table -LAB_13D8 - BMI LAB_13EA ; all bytes matched so go save token - - INX ; next buffer byte - CMP Ibuffs,X ; compare with byte from input buffer - BEQ LAB_13D6 ; go compare next if match - - BNE LAB_1417 ; branch if >< (not found keyword) - -LAB_13EA - LDY csidx ; restore save index - - ; save crunched to output -LAB_13EC - INX ; increment buffer index (to next input byte) - INY ; increment save index (to next output byte) - STA Ibuffs,Y ; save byte to output - CMP #$00 ; set the flags, set carry - BEQ LAB_142A ; do exit if was null [EOL] - - ; A holds token or byte here - SBC #':' ; subtract ":" (carry set by CMP #00) - BEQ LAB_13FF ; branch if it was ":" (is now $00) - - ; A now holds token-$3A - CMP #TK_DATA-$3A ; compare with DATA token - $3A - BNE LAB_1401 ; branch if not DATA - - ; token was : or DATA -LAB_13FF - STA Oquote ; save token-$3A (clear for ":", TK_DATA-$3A for DATA) -LAB_1401 - EOR #TK_REM-$3A ; effectively subtract REM token offset - BNE LAB_13AC ; If wasn't REM then go crunch rest of line - - STA Asrch ; else was REM so set search for [EOL] - - ; loop for REM, "..." etc. -LAB_1408 - LDA Ibuffs,X ; get byte from input buffer - BEQ LAB_13EC ; branch if null [EOL] - - CMP Asrch ; compare with stored character - BEQ LAB_13EC ; branch if match (end quote) - - ; entry for copy string in quotes, don't crunch -LAB_1410 - INY ; increment buffer save index - STA Ibuffs,Y ; save byte to output - INX ; increment buffer read index - BNE LAB_1408 ; loop while <> 0 (should never be 0!) - - ; not found keyword this go -LAB_1417 - LDX TempB ; compare has failed, restore buffer index (start byte!) - - ; now find the end of this word in the table -LAB_141B - LDA (ut2_pl),Y ; get table byte - PHP ; save status - INY ; increment table index - PLP ; restore byte status - BPL LAB_141B ; if not end of keyword go do next - - LDA (ut2_pl),Y ; get byte from keyword table - BNE LAB_13D8 ; go test next word if not zero byte (end of table) - - ; reached end of table with no match - LDA Ibuffs,X ; restore byte from input buffer - BPL LAB_13EA ; branch always (all bytes in buffer are $00-$7F) - ; go save byte in output and continue crunching - - ; reached [EOL] -LAB_142A - INY ; increment pointer - INY ; increment pointer (makes it next line pointer high byte) - STA Ibuffs,Y ; save [EOL] (marks [EOT] in immediate mode) - INY ; adjust for line copy - INY ; adjust for line copy - INY ; adjust for line copy - DEC Bpntrl ; allow for increment (change if buffer starts at $xxFF) - RTS - -; search Basic for temp integer line number from start of mem - -LAB_SSLN - LDA Smeml ; get start of mem low byte - LDX Smemh ; get start of mem high byte - -; search Basic for temp integer line number from AX -; returns carry set if found -; returns Baslnl/Baslnh pointer to found or next higher (not found) line - -; old 541 new 507 - -LAB_SHLN - LDY #$01 ; set index - STA Baslnl ; save low byte as current - STX Baslnh ; save high byte as current - LDA (Baslnl),Y ; get pointer high byte from addr - BEQ LAB_145F ; pointer was zero so we're done, do 'not found' exit - - LDY #$03 ; set index to line # high byte - LDA (Baslnl),Y ; get line # high byte - DEY ; decrement index (point to low byte) - CMP Itemph ; compare with temporary integer high byte - BNE LAB_1455 ; if <> skip low byte check - - LDA (Baslnl),Y ; get line # low byte - CMP Itempl ; compare with temporary integer low byte -LAB_1455 - BCS LAB_145E ; else if temp < this line, exit (passed line#) - -LAB_1456 - DEY ; decrement index to next line ptr high byte - LDA (Baslnl),Y ; get next line pointer high byte - TAX ; copy to X - DEY ; decrement index to next line ptr low byte - LDA (Baslnl),Y ; get next line pointer low byte - BCC LAB_SHLN ; go search for line # in temp (Itempl/Itemph) from AX - ; (carry always clear) - -LAB_145E - BEQ LAB_1460 ; exit if temp = found line #, carry is set - -LAB_145F - CLC ; clear found flag -LAB_1460 - RTS - -; perform NEW - -LAB_NEW - BNE LAB_1460 ; exit if not end of statement (to do syntax error) - -LAB_1463 - LDA #$00 ; clear A - TAY ; clear Y - STA (Smeml),Y ; clear first line, next line pointer, low byte - INY ; increment index - STA (Smeml),Y ; clear first line, next line pointer, high byte - CLC ; clear carry - LDA Smeml ; get start of mem low byte - ADC #$02 ; calculate end of BASIC low byte - STA Svarl ; save start of vars low byte - LDA Smemh ; get start of mem high byte - ADC #$00 ; add any carry - STA Svarh ; save start of vars high byte - -; reset execution to start, clear vars and flush stack - -LAB_1477 - CLC ; clear carry - LDA Smeml ; get start of mem low byte - ADC #$FF ; -1 - STA Bpntrl ; save BASIC execute pointer low byte - LDA Smemh ; get start of mem high byte - ADC #$FF ; -1+carry - STA Bpntrh ; save BASIC execute pointer high byte - -; "CLEAR" command gets here - -LAB_147A - LDA Ememl ; get end of mem low byte - LDY Ememh ; get end of mem high byte - STA Sstorl ; set bottom of string space low byte - STY Sstorh ; set bottom of string space high byte - LDA Svarl ; get start of vars low byte - LDY Svarh ; get start of vars high byte - STA Sarryl ; save var mem end low byte - STY Sarryh ; save var mem end high byte - STA Earryl ; save array mem end low byte - STY Earryh ; save array mem end high byte - JSR LAB_161A ; perform RESTORE command - -; flush stack and clear continue flag - -LAB_1491 - LDX #des_sk ; set descriptor stack pointer - STX next_s ; save descriptor stack pointer - PLA ; pull return address low byte - TAX ; copy return address low byte - PLA ; pull return address high byte - STX LAB_SKFE ; save to cleared stack - STA LAB_SKFF ; save to cleared stack - LDX #$FD ; new stack pointer - TXS ; reset stack - LDA #$00 ; clear byte - STA Cpntrh ; clear continue pointer high byte - STA Sufnxf ; clear subscript/FNX flag -LAB_14A6 - RTS - -; perform CLEAR - -LAB_CLEAR - BEQ LAB_147A ; if no following token go do "CLEAR" - - ; else there was a following token (go do syntax error) - RTS - -; perform LIST [n][-m] -; bigger, faster version (a _lot_ faster) - -LAB_LIST - BCC LAB_14BD ; branch if next character numeric (LIST n..) - - BEQ LAB_14BD ; branch if next character [NULL] (LIST) - - CMP #TK_MINUS ; compare with token for - - BNE LAB_14A6 ; exit if not - (LIST -m) - - ; LIST [[n][-m]] - ; this bit sets the n , if present, as the start and end -LAB_14BD - JSR LAB_GFPN ; get fixed-point number into temp integer - JSR LAB_SSLN ; search BASIC for temp integer line number - ; (pointer in Baslnl/Baslnh) - JSR LAB_GBYT ; scan memory - BEQ LAB_14D4 ; branch if no more characters - - ; this bit checks the - is present - CMP #TK_MINUS ; compare with token for - - BNE LAB_1460 ; return if not "-" (will be Syntax error) - - ; LIST [n]-m - ; the - was there so set m as the end value - JSR LAB_IGBY ; increment and scan memory - JSR LAB_GFPN ; get fixed-point number into temp integer - BNE LAB_1460 ; exit if not ok - -LAB_14D4 - LDA Itempl ; get temporary integer low byte - ORA Itemph ; OR temporary integer high byte - BNE LAB_14E2 ; branch if start set - - LDA #$FF ; set for -1 - STA Itempl ; set temporary integer low byte - STA Itemph ; set temporary integer high byte -LAB_14E2 - LDY #$01 ; set index for line - STY Oquote ; clear open quote flag - JSR LAB_CRLF ; print CR/LF - LDA (Baslnl),Y ; get next line pointer high byte - ; pointer initially set by search at LAB_14BD - BEQ LAB_152B ; if null all done so exit - JSR LAB_1629 ; do CRTL-C check vector - - INY ; increment index for line - LDA (Baslnl),Y ; get line # low byte - TAX ; copy to X - INY ; increment index - LDA (Baslnl),Y ; get line # high byte - CMP Itemph ; compare with temporary integer high byte - BNE LAB_14FF ; branch if no high byte match - - CPX Itempl ; compare with temporary integer low byte - BEQ LAB_1501 ; branch if = last line to do (< will pass next branch) - -LAB_14FF ; else .. - BCS LAB_152B ; if greater all done so exit - -LAB_1501 - STY Tidx1 ; save index for line - JSR LAB_295E ; print XA as unsigned integer - LDA #$20 ; space is the next character -LAB_1508 - LDY Tidx1 ; get index for line - AND #$7F ; mask top out bit of character -LAB_150C - JSR LAB_PRNA ; go print the character - CMP #$22 ; was it " character - BNE LAB_1519 ; branch if not - - ; we are either entering or leaving a pair of quotes - LDA Oquote ; get open quote flag - EOR #$FF ; toggle it - STA Oquote ; save it back -LAB_1519 - INY ; increment index - LDA (Baslnl),Y ; get next byte - BNE LAB_152E ; branch if not [EOL] (go print character) - TAY ; else clear index - LDA (Baslnl),Y ; get next line pointer low byte - TAX ; copy to X - INY ; increment index - LDA (Baslnl),Y ; get next line pointer high byte - STX Baslnl ; set pointer to line low byte - STA Baslnh ; set pointer to line high byte - BNE LAB_14E2 ; go do next line if not [EOT] - ; else .. -LAB_152B - RTS - -LAB_152E - BPL LAB_150C ; just go print it if not token byte - - ; else was token byte so uncrunch it (maybe) - BIT Oquote ; test the open quote flag - BMI LAB_150C ; just go print character if open quote set - - LDX #>LAB_KEYT ; get table address high byte - ASL ; *2 - ASL ; *4 - BCC LAB_152F ; branch if no carry - - INX ; else increment high byte - CLC ; clear carry for add -LAB_152F - ADC #LAB_159F ; set return address high byte - STA ut1_pl ; save return address low byte - STY ut1_ph ; save return address high byte - JMP LAB_1B66 ; round FAC1 and put on stack (returns to next instruction) - -LAB_159F - LDA #LAB_259C ; set 1 pointer high addr - JSR LAB_UFAC ; unpack memory (AY) into FAC1 - JSR LAB_GBYT ; scan memory - CMP #TK_STEP ; compare with STEP token - BNE LAB_15B3 ; jump if not "STEP" - - ;.was step so .. - JSR LAB_IGBY ; increment and scan memory - JSR LAB_EVNM ; evaluate expression and check is numeric, - ; else do type mismatch -LAB_15B3 - JSR LAB_27CA ; return A=FF,C=1/-ve A=01,C=0/+ve - STA FAC1_s ; set FAC1 sign (b7) - ; this is +1 for +ve step and -1 for -ve step, in NEXT we - ; compare the FOR value and the TO value and return +1 if - ; FOR > TO, 0 if FOR = TO and -1 if FOR < TO. the value - ; here (+/-1) is then compared to that result and if they - ; are the same (+ve and FOR > TO or -ve and FOR < TO) then - ; the loop is done - JSR LAB_1B5B ; push sign, round FAC1 and put on stack - LDA Frnxth ; get var pointer for FOR/NEXT high byte - PHA ; push on stack - LDA Frnxtl ; get var pointer for FOR/NEXT low byte - PHA ; push on stack - LDA #TK_FOR ; get FOR token - PHA ; push on stack - -; interpreter inner loop - -LAB_15C2 - JSR LAB_1629 ; do CRTL-C check vector - LDA Bpntrl ; get BASIC execute pointer low byte - LDY Bpntrh ; get BASIC execute pointer high byte - - LDX Clineh ; continue line is $FFxx for immediate mode - ; ($00xx for RUN from immediate mode) - INX ; increment it (now $00 if immediate mode) - BEQ LAB_15D1 ; branch if null (immediate mode) - - STA Cpntrl ; save continue pointer low byte - STY Cpntrh ; save continue pointer high byte -LAB_15D1 - LDY #$00 ; clear index - LDA (Bpntrl),Y ; get next byte - BEQ LAB_15DC ; branch if null [EOL] - - CMP #':' ; compare with ":" - BEQ LAB_15F6 ; branch if = (statement separator) - -LAB_15D9 - JMP LAB_SNER ; else syntax error then warm start - - ; have reached [EOL] -LAB_15DC - LDY #$02 ; set index - LDA (Bpntrl),Y ; get next line pointer high byte - CLC ; clear carry for no "BREAK" message - BEQ LAB_1651 ; if null go to immediate mode (was immediate or [EOT] - ; marker) - - INY ; increment index - LDA (Bpntrl),Y ; get line # low byte - STA Clinel ; save current line low byte - INY ; increment index - LDA (Bpntrl),Y ; get line # high byte - STA Clineh ; save current line high byte - TYA ; A now = 4 - ADC Bpntrl ; add BASIC execute pointer low byte - STA Bpntrl ; save BASIC execute pointer low byte - BCC LAB_15F6 ; branch if no overflow - - INC Bpntrh ; else increment BASIC execute pointer high byte -LAB_15F6 - JSR LAB_IGBY ; increment and scan memory - -LAB_15F9 - JSR LAB_15FF ; go interpret BASIC code from (Bpntrl) - -LAB_15FC - JMP LAB_15C2 ; loop - -; interpret BASIC code from (Bpntrl) - -LAB_15FF - BEQ LAB_1628 ; exit if zero [EOL] - -LAB_1602 - ASL ; *2 bytes per vector and normalise token - BCS LAB_1609 ; branch if was token - - JMP LAB_LET ; else go do implied LET - -LAB_1609 - CMP #[TK_TAB-$80]*2 ; compare normalised token * 2 with TAB - BCS LAB_15D9 ; branch if A>=TAB (do syntax error then warm start) - ; only tokens before TAB can start a line - TAY ; copy to index - LDA LAB_CTBL+1,Y ; get vector high byte - PHA ; onto stack - LDA LAB_CTBL,Y ; get vector low byte - PHA ; onto stack - JMP LAB_IGBY ; jump to increment and scan memory - ; then "return" to vector - -; CTRL-C check jump. this is called as a subroutine but exits back via a jump if a -; key press is detected. - -LAB_1629 - JMP (VEC_CC) ; ctrl c check vector - -; if there was a key press it gets back here .. - -LAB_1636 - CMP #$03 ; compare with CTRL-C - -; perform STOP - -LAB_STOP - BCS LAB_163B ; branch if token follows STOP - ; else just END -; END - -LAB_END - CLC ; clear the carry, indicate a normal program end -LAB_163B - BNE LAB_167A ; if wasn't CTRL-C or there is a following byte return - - LDA Bpntrh ; get the BASIC execute pointer high byte - EOR #>Ibuffs ; compare with buffer address high byte (Cb unchanged) - BEQ LAB_164F ; branch if the BASIC pointer is in the input buffer - ; (can't continue in immediate mode) - - ; else .. - EOR #>Ibuffs ; correct the bits - LDY Bpntrl ; get BASIC execute pointer low byte - STY Cpntrl ; save continue pointer low byte - STA Cpntrh ; save continue pointer high byte -LAB_1647 - LDA Clinel ; get current line low byte - LDY Clineh ; get current line high byte - STA Blinel ; save break line low byte - STY Blineh ; save break line high byte -LAB_164F - PLA ; pull return address low - PLA ; pull return address high -LAB_1651 - BCC LAB_165E ; if was program end just do warm start - - ; else .. - LDA #LAB_BMSG ; point to "Break" high byte - JMP LAB_1269 ; print "Break" and do warm start - -LAB_165E - JMP LAB_1274 ; go do warm start - -; perform RESTORE - -LAB_RESTORE - BNE LAB_RESTOREn ; branch if next character not null (RESTORE n) - -LAB_161A - SEC ; set carry for subtract - LDA Smeml ; get start of mem low byte - SBC #$01 ; -1 - LDY Smemh ; get start of mem high byte - BCS LAB_1624 ; branch if no underflow - -LAB_uflow - DEY ; else decrement high byte -LAB_1624 - STA Dptrl ; save DATA pointer low byte - STY Dptrh ; save DATA pointer high byte -LAB_1628 - RTS - - ; is RESTORE n -LAB_RESTOREn - JSR LAB_GFPN ; get fixed-point number into temp integer - JSR LAB_SNBL ; scan for next BASIC line - LDA Clineh ; get current line high byte - CMP Itemph ; compare with temporary integer high byte - BCS LAB_reset_search ; branch if >= (start search from beginning) - - TYA ; else copy line index to A - SEC ; set carry (+1) - ADC Bpntrl ; add BASIC execute pointer low byte - LDX Bpntrh ; get BASIC execute pointer high byte - BCC LAB_go_search ; branch if no overflow to high byte - - INX ; increment high byte - BCS LAB_go_search ; branch always (can never be carry clear) - -; search for line # in temp (Itempl/Itemph) from start of mem pointer (Smeml) - -LAB_reset_search - LDA Smeml ; get start of mem low byte - LDX Smemh ; get start of mem high byte - -; search for line # in temp (Itempl/Itemph) from (AX) - -LAB_go_search - - JSR LAB_SHLN ; search Basic for temp integer line number from AX - BCS LAB_line_found ; if carry set go set pointer - - JMP LAB_16F7 ; else go do "Undefined statement" error - -LAB_line_found - ; carry already set for subtract - LDA Baslnl ; get pointer low byte - SBC #$01 ; -1 - LDY Baslnh ; get pointer high byte - BCS LAB_1624 ; branch if no underflow (save DATA pointer and return) - - BCC LAB_uflow ; else decrement high byte then save DATA pointer and - ; return (branch always) - -; perform NULL - -LAB_NULL - JSR LAB_GTBY ; get byte parameter - STX Nullct ; save new NULL count -LAB_167A - RTS - -; perform CONT - -LAB_CONT - BNE LAB_167A ; if following byte exit to do syntax error - - LDY Cpntrh ; get continue pointer high byte - BNE LAB_166C ; go do continue if we can - - LDX #$1E ; error code $1E ("Can't continue" error) - JMP LAB_XERR ; do error #X, then warm start - - ; we can continue so .. -LAB_166C - LDA #TK_ON ; set token for ON - JSR LAB_IRQ ; set IRQ flags - LDA #TK_ON ; set token for ON - JSR LAB_NMI ; set NMI flags - - STY Bpntrh ; save BASIC execute pointer high byte - LDA Cpntrl ; get continue pointer low byte - STA Bpntrl ; save BASIC execute pointer low byte - LDA Blinel ; get break line low byte - LDY Blineh ; get break line high byte - STA Clinel ; set current line low byte - STY Clineh ; set current line high byte - RTS - -; perform RUN - -LAB_RUN - BNE LAB_1696 ; branch if RUN n - JMP LAB_1477 ; reset execution to start, clear variables, flush stack and - ; return - -; does RUN n - -LAB_1696 - JSR LAB_147A ; go do "CLEAR" - BEQ LAB_16B0 ; get n and do GOTO n (branch always as CLEAR sets Z=1) - -; perform DO - -LAB_DO - LDA #$05 ; need 5 bytes for DO - JSR LAB_1212 ; check room on stack for A bytes - LDA Bpntrh ; get BASIC execute pointer high byte - PHA ; push on stack - LDA Bpntrl ; get BASIC execute pointer low byte - PHA ; push on stack - LDA Clineh ; get current line high byte - PHA ; push on stack - LDA Clinel ; get current line low byte - PHA ; push on stack - LDA #TK_DO ; token for DO - PHA ; push on stack - JSR LAB_GBYT ; scan memory - JMP LAB_15C2 ; go do interpreter inner loop - -; perform GOSUB - -LAB_GOSUB - LDA #$05 ; need 5 bytes for GOSUB - JSR LAB_1212 ; check room on stack for A bytes - LDA Bpntrh ; get BASIC execute pointer high byte - PHA ; push on stack - LDA Bpntrl ; get BASIC execute pointer low byte - PHA ; push on stack - LDA Clineh ; get current line high byte - PHA ; push on stack - LDA Clinel ; get current line low byte - PHA ; push on stack - LDA #TK_GOSUB ; token for GOSUB - PHA ; push on stack -LAB_16B0 - JSR LAB_GBYT ; scan memory - JSR LAB_GOTO ; perform GOTO n - JMP LAB_15C2 ; go do interpreter inner loop - ; (can't RTS, we used the stack!) - -; perform GOTO - -LAB_GOTO - JSR LAB_GFPN ; get fixed-point number into temp integer - JSR LAB_SNBL ; scan for next BASIC line - LDA Clineh ; get current line high byte - CMP Itemph ; compare with temporary integer high byte - BCS LAB_16D0 ; branch if >= (start search from beginning) - - TYA ; else copy line index to A - SEC ; set carry (+1) - ADC Bpntrl ; add BASIC execute pointer low byte - LDX Bpntrh ; get BASIC execute pointer high byte - BCC LAB_16D4 ; branch if no overflow to high byte - - INX ; increment high byte - BCS LAB_16D4 ; branch always (can never be carry) - -; search for line # in temp (Itempl/Itemph) from start of mem pointer (Smeml) - -LAB_16D0 - LDA Smeml ; get start of mem low byte - LDX Smemh ; get start of mem high byte - -; search for line # in temp (Itempl/Itemph) from (AX) - -LAB_16D4 - JSR LAB_SHLN ; search Basic for temp integer line number from AX - BCC LAB_16F7 ; if carry clear go do "Undefined statement" error - ; (unspecified statement) - - ; carry already set for subtract - LDA Baslnl ; get pointer low byte - SBC #$01 ; -1 - STA Bpntrl ; save BASIC execute pointer low byte - LDA Baslnh ; get pointer high byte - SBC #$00 ; subtract carry - STA Bpntrh ; save BASIC execute pointer high byte -LAB_16E5 - RTS - -LAB_DONOK - LDX #$22 ; error code $22 ("LOOP without DO" error) - JMP LAB_XERR ; do error #X, then warm start - -; perform LOOP - -LAB_LOOP - TAY ; save following token - TSX ; copy stack pointer - LDA LAB_STAK+3,X ; get token byte from stack - CMP #TK_DO ; compare with DO token - BNE LAB_DONOK ; branch if no matching DO - - INX ; dump calling routine return address - INX ; dump calling routine return address - TXS ; correct stack - TYA ; get saved following token back - BEQ LoopAlways ; if no following token loop forever - ; (stack pointer in X) - - CMP #':' ; could be ':' - BEQ LoopAlways ; if :... loop forever - - SBC #TK_UNTIL ; subtract token for UNTIL, we know carry is set here - TAX ; copy to X (if it was UNTIL then Y will be correct) - BEQ DoRest ; branch if was UNTIL - - DEX ; decrement result - BNE LAB_16FC ; if not WHILE go do syntax error and warm start - ; only if the token was WHILE will this fail - - DEX ; set invert result byte -DoRest - STX Frnxth ; save invert result byte - JSR LAB_IGBY ; increment and scan memory - JSR LAB_EVEX ; evaluate expression - LDA FAC1_e ; get FAC1 exponent - BEQ DoCmp ; if =0 go do straight compare - - LDA #$FF ; else set all bits -DoCmp - TSX ; copy stack pointer - EOR Frnxth ; EOR with invert byte - BNE LoopDone ; if <> 0 clear stack and back to interpreter loop - - ; loop condition wasn't met so do it again -LoopAlways - LDA LAB_STAK+2,X ; get current line low byte - STA Clinel ; save current line low byte - LDA LAB_STAK+3,X ; get current line high byte - STA Clineh ; save current line high byte - LDA LAB_STAK+4,X ; get BASIC execute pointer low byte - STA Bpntrl ; save BASIC execute pointer low byte - LDA LAB_STAK+5,X ; get BASIC execute pointer high byte - STA Bpntrh ; save BASIC execute pointer high byte - JSR LAB_GBYT ; scan memory - JMP LAB_15C2 ; go do interpreter inner loop - - ; clear stack and back to interpreter loop -LoopDone - INX ; dump DO token - INX ; dump current line low byte - INX ; dump current line high byte - INX ; dump BASIC execute pointer low byte - INX ; dump BASIC execute pointer high byte - TXS ; correct stack - JMP LAB_DATA ; go perform DATA (find : or [EOL]) - -; do the return without gosub error - -LAB_16F4 - LDX #$04 ; error code $04 ("RETURN without GOSUB" error) - .byte $2C ; makes next line BIT LAB_0EA2 - -LAB_16F7 ; do undefined statement error - LDX #$0E ; error code $0E ("Undefined statement" error) - JMP LAB_XERR ; do error #X, then warm start - -; perform RETURN - -LAB_RETURN - BNE LAB_16E5 ; exit if following token (to allow syntax error) - -LAB_16E8 - PLA ; dump calling routine return address - PLA ; dump calling routine return address - PLA ; pull token - CMP #TK_GOSUB ; compare with GOSUB token - BNE LAB_16F4 ; branch if no matching GOSUB - -LAB_16FF - PLA ; pull current line low byte - STA Clinel ; save current line low byte - PLA ; pull current line high byte - STA Clineh ; save current line high byte - PLA ; pull BASIC execute pointer low byte - STA Bpntrl ; save BASIC execute pointer low byte - PLA ; pull BASIC execute pointer high byte - STA Bpntrh ; save BASIC execute pointer high byte - - ; now do the DATA statement as we could be returning into - ; the middle of an ON GOSUB n,m,p,q line - ; (the return address used by the DATA statement is the one - ; pushed before the GOSUB was executed!) - -; perform DATA - -LAB_DATA - JSR LAB_SNBS ; scan for next BASIC statement ([:] or [EOL]) - - ; set BASIC execute pointer -LAB_170F - TYA ; copy index to A - CLC ; clear carry for add - ADC Bpntrl ; add BASIC execute pointer low byte - STA Bpntrl ; save BASIC execute pointer low byte - BCC LAB_1719 ; skip next if no carry - - INC Bpntrh ; else increment BASIC execute pointer high byte -LAB_1719 - RTS - -LAB_16FC - JMP LAB_SNER ; do syntax error then warm start - -; scan for next BASIC statement ([:] or [EOL]) -; returns Y as index to [:] or [EOL] - -LAB_SNBS - LDX #':' ; set look for character = ":" - .byte $2C ; makes next line BIT $00A2 - -; scan for next BASIC line -; returns Y as index to [EOL] - -LAB_SNBL - LDX #$00 ; set alt search character = [EOL] - LDY #$00 ; set search character = [EOL] - STY Asrch ; store search character -LAB_1725 - TXA ; get alt search character - EOR Asrch ; toggle search character, effectively swap with $00 - STA Asrch ; save swapped search character -LAB_172D - LDA (Bpntrl),Y ; get next byte - BEQ LAB_1719 ; exit if null [EOL] - - CMP Asrch ; compare with search character - BEQ LAB_1719 ; exit if found - - INY ; increment index - CMP #$22 ; compare current character with open quote - BNE LAB_172D ; if not open quote go get next character - - BEQ LAB_1725 ; if found go swap search character for alt search character - -; perform IF - -LAB_IF - JSR LAB_EVEX ; evaluate the expression - JSR LAB_GBYT ; scan memory - CMP #TK_THEN ; compare with THEN token - BEQ LAB_174B ; if it was THEN go do IF - - ; wasn't IF .. THEN so must be IF .. GOTO - CMP #TK_GOTO ; compare with GOTO token - BNE LAB_16FC ; if it wasn't GOTO go do syntax error - - LDX Bpntrl ; save the basic pointer low byte - LDY Bpntrh ; save the basic pointer high byte - JSR LAB_IGBY ; increment and scan memory - BCS LAB_16FC ; if not numeric go do syntax error - - STX Bpntrl ; restore the basic pointer low byte - STY Bpntrh ; restore the basic pointer high byte -LAB_174B - LDA FAC1_e ; get FAC1 exponent - BEQ LAB_174E ; if the result was zero go look for an ELSE - - JSR LAB_IGBY ; else increment and scan memory - BCS LAB_174D ; if not numeric go do var or keyword - -LAB_174C - JMP LAB_GOTO ; else was numeric so do GOTO n - - ; is var or keyword -LAB_174D - CMP #TK_RETURN ; compare the byte with the token for RETURN - BNE LAB_174G ; if it wasn't RETURN go interpret BASIC code from (Bpntrl) - ; and return to this code to process any following code - - JMP LAB_1602 ; else it was RETURN so interpret BASIC code from (Bpntrl) - ; but don't return here - -LAB_174G - JSR LAB_15FF ; interpret BASIC code from (Bpntrl) - -; the IF was executed and there may be a following ELSE so the code needs to return -; here to check and ignore the ELSE if present - - LDY #$00 ; clear the index - LDA (Bpntrl),Y ; get the next BASIC byte - CMP #TK_ELSE ; compare it with the token for ELSE - BEQ LAB_DATA ; if ELSE ignore the following statement - -; there was no ELSE so continue execution of IF THEN [: ]. any -; following ELSE will, correctly, cause a syntax error - - RTS ; else return to the interpreter inner loop - -; perform ELSE after IF - -LAB_174E - LDY #$00 ; clear the BASIC byte index - LDX #$01 ; clear the nesting depth -LAB_1750 - INY ; increment the BASIC byte index - LDA (Bpntrl),Y ; get the next BASIC byte - BEQ LAB_1753 ; if EOL go add the pointer and return - - CMP #TK_IF ; compare the byte with the token for IF - BNE LAB_1752 ; if not IF token skip the depth increment - - INX ; else increment the nesting depth .. - BNE LAB_1750 ; .. and continue looking - -LAB_1752 - CMP #TK_ELSE ; compare the byte with the token for ELSE - BNE LAB_1750 ; if not ELSE token continue looking - - DEX ; was ELSE so decrement the nesting depth - BNE LAB_1750 ; loop if still nested - - INY ; increment the BASIC byte index past the ELSE - -; found the matching ELSE, now do <{n|statement}> - -LAB_1753 - TYA ; else copy line index to A - CLC ; clear carry for add - ADC Bpntrl ; add the BASIC execute pointer low byte - STA Bpntrl ; save the BASIC execute pointer low byte - BCC LAB_1754 ; branch if no overflow to high byte - - INC Bpntrh ; else increment the BASIC execute pointer high byte -LAB_1754 - JSR LAB_GBYT ; scan memory - BCC LAB_174C ; if numeric do GOTO n - ; the code will return to the interpreter loop at the - ; tail end of the GOTO - - JMP LAB_15FF ; interpret BASIC code from (Bpntrl) - ; the code will return to the interpreter loop at the - ; tail end of the - -; perform REM, skip (rest of) line - -LAB_REM - JSR LAB_SNBL ; scan for next BASIC line - JMP LAB_170F ; go set BASIC execute pointer and return, branch always - -LAB_16FD - JMP LAB_SNER ; do syntax error then warm start - -; perform ON - -LAB_ON - CMP #TK_IRQ ; was it IRQ token ? - BNE LAB_NOIN ; if not go check NMI - - JMP LAB_SIRQ ; else go set-up IRQ - -LAB_NOIN - CMP #TK_NMI ; was it NMI token ? - BNE LAB_NONM ; if not go do normal ON command - - JMP LAB_SNMI ; else go set-up NMI - -LAB_NONM - JSR LAB_GTBY ; get byte parameter - PHA ; push GOTO/GOSUB token - CMP #TK_GOSUB ; compare with GOSUB token - BEQ LAB_176B ; branch if GOSUB - - CMP #TK_GOTO ; compare with GOTO token -LAB_1767 - BNE LAB_16FD ; if not GOTO do syntax error then warm start - - -; next character was GOTO or GOSUB - -LAB_176B - DEC FAC1_3 ; decrement index (byte value) - BNE LAB_1773 ; branch if not zero - - PLA ; pull GOTO/GOSUB token - JMP LAB_1602 ; go execute it - -LAB_1773 - JSR LAB_IGBY ; increment and scan memory - JSR LAB_GFPN ; get fixed-point number into temp integer (skip this n) - ; (we could LDX #',' and JSR LAB_SNBL+2, then we - ; just BNE LAB_176B for the loop. should be quicker .. - ; no we can't, what if we meet a colon or [EOL]?) - CMP #$2C ; compare next character with "," - BEQ LAB_176B ; loop if "," - -LAB_177E - PLA ; else pull keyword token (run out of options) - ; also dump +/-1 pointer low byte and exit -LAB_177F - RTS - -; takes n * 106 + 11 cycles where n is the number of digits - -; get fixed-point number into temp integer - -LAB_GFPN - LDX #$00 ; clear reg - STX Itempl ; clear temporary integer low byte -LAB_1785 - STX Itemph ; save temporary integer high byte - BCS LAB_177F ; return if carry set, end of scan, character was - ; not 0-9 - - CPX #$19 ; compare high byte with $19 - TAY ; ensure Zb = 0 if the branch is taken - BCS LAB_1767 ; branch if >=, makes max line # 63999 because next - ; bit does *$0A, = 64000, compare at target will fail - ; and do syntax error - - SBC #'0'-1 ; subtract "0", $2F + carry, from byte - TAY ; copy binary digit - LDA Itempl ; get temporary integer low byte - ASL ; *2 low byte - ROL Itemph ; *2 high byte - ASL ; *2 low byte - ROL Itemph ; *2 high byte, *4 - ADC Itempl ; + low byte, *5 - STA Itempl ; save it - TXA ; get high byte copy to A - ADC Itemph ; + high byte, *5 - ASL Itempl ; *2 low byte, *10d - ROL ; *2 high byte, *10d - TAX ; copy high byte back to X - TYA ; get binary digit back - ADC Itempl ; add number low byte - STA Itempl ; save number low byte - BCC LAB_17B3 ; if no overflow to high byte get next character - - INX ; else increment high byte -LAB_17B3 - JSR LAB_IGBY ; increment and scan memory - JMP LAB_1785 ; loop for next character - -; perform DEC - -LAB_DEC - LDA #LAB_259C ; set +/-1 pointer high byte (both the same) - JSR LAB_246C ; add (AY) to FAC1 - JSR LAB_PFAC ; pack FAC1 into variable (Lvarpl) - - JSR LAB_GBYT ; scan memory - CMP #',' ; compare with "," - BNE LAB_177E ; exit if not "," (either end or error) - - ; was "," so another INCR variable to do - JSR LAB_IGBY ; increment and scan memory - JMP LAB_17B7 ; go do next var - -IncrErr - JMP LAB_1ABC ; do "Type mismatch" error then warm start - -; perform LET - -LAB_LET - JSR LAB_GVAR ; get var address - STA Lvarpl ; save var address low byte - STY Lvarph ; save var address high byte - LDA #TK_EQUAL ; get = token - JSR LAB_SCCA ; scan for CHR$(A), else do syntax error then warm start - LDA Dtypef ; get data type flag, $FF=string, $00=numeric - PHA ; push data type flag - JSR LAB_EVEX ; evaluate expression - PLA ; pop data type flag - ROL ; set carry if type = string - JSR LAB_CKTM ; type match check, set C for string - BNE LAB_17D5 ; branch if string - - JMP LAB_PFAC ; pack FAC1 into variable (Lvarpl) and return - -; string LET - -LAB_17D5 - LDY #$02 ; set index to pointer high byte - LDA (des_pl),Y ; get string pointer high byte - CMP Sstorh ; compare bottom of string space high byte - BCC LAB_17F4 ; if less assign value and exit (was in program memory) - - BNE LAB_17E6 ; branch if > - ; else was equal so compare low bytes - DEY ; decrement index - LDA (des_pl),Y ; get pointer low byte - CMP Sstorl ; compare bottom of string space low byte - BCC LAB_17F4 ; if less assign value and exit (was in program memory) - - ; pointer was >= to bottom of string space pointer -LAB_17E6 - LDY des_ph ; get descriptor pointer high byte - CPY Svarh ; compare start of vars high byte - BCC LAB_17F4 ; branch if less (descriptor is on stack) - - BNE LAB_17FB ; branch if greater (descriptor is not on stack) - - ; else high bytes were equal so .. - LDA des_pl ; get descriptor pointer low byte - CMP Svarl ; compare start of vars low byte - BCS LAB_17FB ; branch if >= (descriptor is not on stack) - -LAB_17F4 - LDA des_pl ; get descriptor pointer low byte - LDY des_ph ; get descriptor pointer high byte - JMP LAB_1811 ; clean stack, copy descriptor to variable and return - - ; make space and copy string -LAB_17FB - LDY #$00 ; index to length - LDA (des_pl),Y ; get string length - JSR LAB_209C ; copy string - LDA des_2l ; get descriptor pointer low byte - LDY des_2h ; get descriptor pointer high byte - STA ssptr_l ; save descriptor pointer low byte - STY ssptr_h ; save descriptor pointer high byte - JSR LAB_228A ; copy string from descriptor (sdescr) to (Sutill) - LDA #FAC1_e ; get descriptor pointer high byte - - ; clean stack and assign value to string variable -LAB_1811 - STA des_2l ; save descriptor_2 pointer low byte - STY des_2h ; save descriptor_2 pointer high byte - JSR LAB_22EB ; clean descriptor stack, YA = pointer - LDY #$00 ; index to length - LDA (des_2l),Y ; get string length - STA (Lvarpl),Y ; copy to let string variable - INY ; index to string pointer low byte - LDA (des_2l),Y ; get string pointer low byte - STA (Lvarpl),Y ; copy to let string variable - INY ; index to string pointer high byte - LDA (des_2l),Y ; get string pointer high byte - STA (Lvarpl),Y ; copy to let string variable - RTS - -; perform GET - -LAB_GET - JSR LAB_GVAR ; get var address - STA Lvarpl ; save var address low byte - STY Lvarph ; save var address high byte - JSR INGET ; get input byte - LDX Dtypef ; get data type flag, $FF=string, $00=numeric - BMI LAB_GETS ; go get string character - - ; was numeric get - TAY ; copy character to Y - JSR LAB_1FD0 ; convert Y to byte in FAC1 - JMP LAB_PFAC ; pack FAC1 into variable (Lvarpl) and return - -LAB_GETS - PHA ; save character - LDA #$01 ; string is single byte - BCS LAB_IsByte ; branch if byte received - - PLA ; string is null -LAB_IsByte - JSR LAB_MSSP ; make string space A bytes long A=$AC=length, - ; X=$AD=Sutill=ptr low byte, Y=$AE=Sutilh=ptr high byte - BEQ LAB_NoSt ; skip store if null string - - PLA ; get character back - LDY #$00 ; clear index - STA (str_pl),Y ; save byte in string (byte IS string!) -LAB_NoSt - JSR LAB_RTST ; check for space on descriptor stack then put address - ; and length on descriptor stack and update stack pointers - - JMP LAB_17D5 ; do string LET and return - -; perform PRINT - -LAB_1829 - JSR LAB_18C6 ; print string from Sutill/Sutilh -LAB_182C - JSR LAB_GBYT ; scan memory - -; PRINT - -LAB_PRINT - BEQ LAB_CRLF ; if nothing following just print CR/LF - -LAB_1831 - CMP #TK_TAB ; compare with TAB( token - BEQ LAB_18A2 ; go do TAB/SPC - - CMP #TK_SPC ; compare with SPC( token - BEQ LAB_18A2 ; go do TAB/SPC - - CMP #',' ; compare with "," - BEQ LAB_188B ; go do move to next TAB mark - - CMP #';' ; compare with ";" - BEQ LAB_18BD ; if ";" continue with PRINT processing - - JSR LAB_EVEX ; evaluate expression - BIT Dtypef ; test data type flag, $FF=string, $00=numeric - BMI LAB_1829 ; branch if string - - JSR LAB_296E ; convert FAC1 to string - JSR LAB_20AE ; print " terminated string to Sutill/Sutilh - LDY #$00 ; clear index - -; don't check fit if terminal width byte is zero - - LDA TWidth ; get terminal width byte - BEQ LAB_185E ; skip check if zero - - SEC ; set carry for subtract - SBC TPos ; subtract terminal position - SBC (des_pl),Y ; subtract string length - BCS LAB_185E ; branch if less than terminal width - - JSR LAB_CRLF ; else print CR/LF -LAB_185E - JSR LAB_18C6 ; print string from Sutill/Sutilh - BEQ LAB_182C ; always go continue processing line - -; CR/LF return to BASIC from BASIC input handler - -LAB_1866 - LDA #$00 ; clear byte - STA Ibuffs,X ; null terminate input - LDX #Ibuffs ; set Y to buffer start-1 high byte - -; print CR/LF - -LAB_CRLF - LDA #$0D ; load [CR] - JSR LAB_PRNA ; go print the character - LDA #$0A ; load [LF] - BNE LAB_PRNA ; go print the character and return, branch always - -LAB_188B - LDA TPos ; get terminal position - CMP Iclim ; compare with input column limit - BCC LAB_1897 ; branch if less - - JSR LAB_CRLF ; else print CR/LF (next line) - BNE LAB_18BD ; continue with PRINT processing (branch always) - -LAB_1897 - SEC ; set carry for subtract -LAB_1898 - SBC TabSiz ; subtract TAB size - BCS LAB_1898 ; loop if result was +ve - - EOR #$FF ; complement it - ADC #$01 ; +1 (twos complement) - BNE LAB_18B6 ; always print A spaces (result is never $00) - - ; do TAB/SPC -LAB_18A2 - PHA ; save token - JSR LAB_SGBY ; scan and get byte parameter - CMP #$29 ; is next character ) - BNE LAB_1910 ; if not do syntax error then warm start - - PLA ; get token back - CMP #TK_TAB ; was it TAB ? - BNE LAB_18B7 ; if not go do SPC - - ; calculate TAB offset - TXA ; copy integer value to A - SBC TPos ; subtract terminal position - BCC LAB_18BD ; branch if result was < 0 (can't TAB backwards) - - ; print A spaces -LAB_18B6 - TAX ; copy result to X -LAB_18B7 - TXA ; set flags on size for SPC - BEQ LAB_18BD ; branch if result was = $0, already here - - ; print X spaces -LAB_18BA - JSR LAB_18E0 ; print " " - DEX ; decrement count - BNE LAB_18BA ; loop if not all done - - ; continue with PRINT processing -LAB_18BD - JSR LAB_IGBY ; increment and scan memory - BNE LAB_1831 ; if more to print go do it - - RTS - -; print null terminated string from memory - -LAB_18C3 - JSR LAB_20AE ; print " terminated string to Sutill/Sutilh - -; print string from Sutill/Sutilh - -LAB_18C6 - JSR LAB_22B6 ; pop string off descriptor stack, or from top of string - ; space returns with A = length, X=$71=pointer low byte, - ; Y=$72=pointer high byte - LDY #$00 ; reset index - TAX ; copy length to X - BEQ LAB_188C ; exit (RTS) if null string - -LAB_18CD - - LDA (ut1_pl),Y ; get next byte - JSR LAB_PRNA ; go print the character - INY ; increment index - DEX ; decrement count - BNE LAB_18CD ; loop if not done yet - - RTS - - ; Print single format character -; print " " - -LAB_18E0 - LDA #$20 ; load " " - .byte $2C ; change next line to BIT LAB_3FA9 - -; print "?" character - -LAB_18E3 - LDA #$3F ; load "?" character - -; print character in A -; now includes the null handler -; also includes infinite line length code -; note! some routines expect this one to exit with Zb=0 - -LAB_PRNA - CMP #' ' ; compare with " " - BCC LAB_18F9 ; branch if less (non printing) - - ; else printable character - PHA ; save the character - -; don't check fit if terminal width byte is zero - - LDA TWidth ; get terminal width - BNE LAB_18F0 ; branch if not zero (not infinite length) - -; is "infinite line" so check TAB position - - LDA TPos ; get position - SBC TabSiz ; subtract TAB size, carry set by CMP #$20 above - BNE LAB_18F7 ; skip reset if different - - STA TPos ; else reset position - BEQ LAB_18F7 ; go print character - -LAB_18F0 - CMP TPos ; compare with terminal character position - BNE LAB_18F7 ; branch if not at end of line - - JSR LAB_CRLF ; else print CR/LF -LAB_18F7 - INC TPos ; increment terminal position - PLA ; get character back -LAB_18F9 - JSR V_OUTP ; output byte via output vector - CMP #$0D ; compare with [CR] - BNE LAB_188A ; branch if not [CR] - - ; else print nullct nulls after the [CR] - STX TempB ; save buffer index - LDX Nullct ; get null count - BEQ LAB_1886 ; branch if no nulls - - LDA #$00 ; load [NULL] -LAB_1880 - JSR LAB_PRNA ; go print the character - DEX ; decrement count - BNE LAB_1880 ; loop if not all done - - LDA #$0D ; restore the character (and set the flags) -LAB_1886 - STX TPos ; clear terminal position (X always = zero when we get here) - LDX TempB ; restore buffer index -LAB_188A - AND #$FF ; set the flags -LAB_188C - RTS - -; handle bad input data - -LAB_1904 - LDA Imode ; get input mode flag, $00=INPUT, $00=READ - BPL LAB_1913 ; branch if INPUT (go do redo) - - LDA Dlinel ; get current DATA line low byte - LDY Dlineh ; get current DATA line high byte - STA Clinel ; save current line low byte - STY Clineh ; save current line high byte -LAB_1910 - JMP LAB_SNER ; do syntax error then warm start - - ; mode was INPUT -LAB_1913 - LDA #LAB_REDO ; point to redo message (high addr) - JSR LAB_18C3 ; print null terminated string from memory - LDA Cpntrl ; get continue pointer low byte - LDY Cpntrh ; get continue pointer high byte - STA Bpntrl ; save BASIC execute pointer low byte - STY Bpntrh ; save BASIC execute pointer high byte - RTS - -; perform INPUT - -LAB_INPUT - CMP #$22 ; compare next byte with open quote - BNE LAB_1934 ; branch if no prompt string - - JSR LAB_1BC1 ; print "..." string - LDA #$3B ; load A with ";" - JSR LAB_SCCA ; scan for CHR$(A), else do syntax error then warm start - JSR LAB_18C6 ; print string from Sutill/Sutilh - - ; done with prompt, now get data -LAB_1934 - JSR LAB_CKRN ; check not Direct, back here if ok - JSR LAB_INLN ; print "? " and get BASIC input - LDA #$00 ; set mode = INPUT - CMP Ibuffs ; test first byte in buffer - BNE LAB_1953 ; branch if not null input - - CLC ; was null input so clear carry to exit program - JMP LAB_1647 ; go do BREAK exit - -; perform READ - -LAB_READ - LDX Dptrl ; get DATA pointer low byte - LDY Dptrh ; get DATA pointer high byte - LDA #$80 ; set mode = READ - -LAB_1953 - STA Imode ; set input mode flag, $00=INPUT, $80=READ - STX Rdptrl ; save READ pointer low byte - STY Rdptrh ; save READ pointer high byte - - ; READ or INPUT next variable from list -LAB_195B - JSR LAB_GVAR ; get (var) address - STA Lvarpl ; save address low byte - STY Lvarph ; save address high byte - LDA Bpntrl ; get BASIC execute pointer low byte - LDY Bpntrh ; get BASIC execute pointer high byte - STA Itempl ; save as temporary integer low byte - STY Itemph ; save as temporary integer high byte - LDX Rdptrl ; get READ pointer low byte - LDY Rdptrh ; get READ pointer high byte - STX Bpntrl ; set BASIC execute pointer low byte - STY Bpntrh ; set BASIC execute pointer high byte - JSR LAB_GBYT ; scan memory - BNE LAB_1988 ; branch if not null - - ; pointer was to null entry - BIT Imode ; test input mode flag, $00=INPUT, $80=READ - BMI LAB_19DD ; branch if READ - - ; mode was INPUT - JSR LAB_18E3 ; print "?" character (double ? for extended input) - JSR LAB_INLN ; print "? " and get BASIC input - STX Bpntrl ; set BASIC execute pointer low byte - STY Bpntrh ; set BASIC execute pointer high byte -LAB_1985 - JSR LAB_GBYT ; scan memory -LAB_1988 - BIT Dtypef ; test data type flag, $FF=string, $00=numeric - BPL LAB_19B0 ; branch if numeric - - ; else get string - STA Srchc ; save search character - CMP #$22 ; was it " ? - BEQ LAB_1999 ; branch if so - - LDA #':' ; else search character is ":" - STA Srchc ; set new search character - LDA #',' ; other search character is "," - CLC ; clear carry for add -LAB_1999 - STA Asrch ; set second search character - LDA Bpntrl ; get BASIC execute pointer low byte - LDY Bpntrh ; get BASIC execute pointer high byte - - ADC #$00 ; c is =1 if we came via the BEQ LAB_1999, else =0 - BCC LAB_19A4 ; branch if no execute pointer low byte rollover - - INY ; else increment high byte -LAB_19A4 - JSR LAB_20B4 ; print Srchc or Asrch terminated string to Sutill/Sutilh - JSR LAB_23F3 ; restore BASIC execute pointer from temp (Btmpl/Btmph) - JSR LAB_17D5 ; go do string LET - JMP LAB_19B6 ; go check string terminator - - ; get numeric INPUT -LAB_19B0 - JSR LAB_2887 ; get FAC1 from string - JSR LAB_PFAC ; pack FAC1 into (Lvarpl) -LAB_19B6 - JSR LAB_GBYT ; scan memory - BEQ LAB_19C5 ; branch if null (last entry) - - CMP #',' ; else compare with "," - BEQ LAB_19C2 ; branch if "," - - JMP LAB_1904 ; else go handle bad input data - - ; got good input data -LAB_19C2 - JSR LAB_IGBY ; increment and scan memory -LAB_19C5 - LDA Bpntrl ; get BASIC execute pointer low byte (temp READ/INPUT ptr) - LDY Bpntrh ; get BASIC execute pointer high byte (temp READ/INPUT ptr) - STA Rdptrl ; save for now - STY Rdptrh ; save for now - LDA Itempl ; get temporary integer low byte (temp BASIC execute ptr) - LDY Itemph ; get temporary integer high byte (temp BASIC execute ptr) - STA Bpntrl ; set BASIC execute pointer low byte - STY Bpntrh ; set BASIC execute pointer high byte - JSR LAB_GBYT ; scan memory - BEQ LAB_1A03 ; if null go do extra ignored message - - JSR LAB_1C01 ; else scan for "," , else do syntax error then warm start - JMP LAB_195B ; go INPUT next variable from list - - ; find next DATA statement or do "Out of DATA" error -LAB_19DD - JSR LAB_SNBS ; scan for next BASIC statement ([:] or [EOL]) - INY ; increment index - TAX ; copy character ([:] or [EOL]) - BNE LAB_19F6 ; branch if [:] - - LDX #$06 ; set for "Out of DATA" error - INY ; increment index, now points to next line pointer high byte - LDA (Bpntrl),Y ; get next line pointer high byte - BEQ LAB_1A54 ; branch if end (eventually does error X) - - INY ; increment index - LDA (Bpntrl),Y ; get next line # low byte - STA Dlinel ; save current DATA line low byte - INY ; increment index - LDA (Bpntrl),Y ; get next line # high byte - INY ; increment index - STA Dlineh ; save current DATA line high byte -LAB_19F6 - LDA (Bpntrl),Y ; get byte - INY ; increment index - TAX ; copy to X - JSR LAB_170F ; set BASIC execute pointer - CPX #TK_DATA ; compare with "DATA" token - BEQ LAB_1985 ; was "DATA" so go do next READ - - BNE LAB_19DD ; go find next statement if not "DATA" - -; end of INPUT/READ routine - -LAB_1A03 - LDA Rdptrl ; get temp READ pointer low byte - LDY Rdptrh ; get temp READ pointer high byte - LDX Imode ; get input mode flag, $00=INPUT, $80=READ - BPL LAB_1A0E ; branch if INPUT - - JMP LAB_1624 ; save AY as DATA pointer and return - - ; we were getting INPUT -LAB_1A0E - LDY #$00 ; clear index - LDA (Rdptrl),Y ; get next byte - BNE LAB_1A1B ; error if not end of INPUT - - RTS - - ; user typed too much -LAB_1A1B - LDA #LAB_IMSG ; point to extra ignored message (high addr) - JMP LAB_18C3 ; print null terminated string from memory and return - -; search the stack for FOR activity -; exit with z=1 if FOR else exit with z=0 - -LAB_11A1 - TSX ; copy stack pointer - INX ; +1 pass return address - INX ; +2 pass return address - INX ; +3 pass calling routine return address - INX ; +4 pass calling routine return address -LAB_11A6 - LDA LAB_STAK+1,X ; get token byte from stack - CMP #TK_FOR ; is it FOR token - BNE LAB_11CE ; exit if not FOR token - - ; was FOR token - LDA Frnxth ; get var pointer for FOR/NEXT high byte - BNE LAB_11BB ; branch if not null - - LDA LAB_STAK+2,X ; get FOR variable pointer low byte - STA Frnxtl ; save var pointer for FOR/NEXT low byte - LDA LAB_STAK+3,X ; get FOR variable pointer high byte - STA Frnxth ; save var pointer for FOR/NEXT high byte -LAB_11BB - CMP LAB_STAK+3,X ; compare var pointer with stacked var pointer (high byte) - BNE LAB_11C7 ; branch if no match - - LDA Frnxtl ; get var pointer for FOR/NEXT low byte - CMP LAB_STAK+2,X ; compare var pointer with stacked var pointer (low byte) - BEQ LAB_11CE ; exit if match found - -LAB_11C7 - TXA ; copy index - CLC ; clear carry for add - ADC #$10 ; add FOR stack use size - TAX ; copy back to index - BNE LAB_11A6 ; loop if not at start of stack - -LAB_11CE - RTS - -; perform NEXT - -LAB_NEXT - BNE LAB_1A46 ; branch if NEXT var - - LDY #$00 ; else clear Y - BEQ LAB_1A49 ; branch always (no variable to search for) - -; NEXT var - -LAB_1A46 - JSR LAB_GVAR ; get variable address -LAB_1A49 - STA Frnxtl ; store variable pointer low byte - STY Frnxth ; store variable pointer high byte - ; (both cleared if no variable defined) - JSR LAB_11A1 ; search the stack for FOR activity - BEQ LAB_1A56 ; branch if found - - LDX #$00 ; else set error $00 ("NEXT without FOR" error) -LAB_1A54 - BEQ LAB_1ABE ; do error #X, then warm start - -LAB_1A56 - TXS ; set stack pointer, X set by search, dumps return addresses - - TXA ; copy stack pointer - SEC ; set carry for subtract - SBC #$F7 ; point to TO var - STA ut2_pl ; save pointer to TO var for compare - ADC #$FB ; point to STEP var - - LDY #>LAB_STAK ; point to stack page high byte - JSR LAB_UFAC ; unpack memory (STEP value) into FAC1 - TSX ; get stack pointer back - LDA LAB_STAK+8,X ; get step sign - STA FAC1_s ; save FAC1 sign (b7) - LDA Frnxtl ; get FOR variable pointer low byte - LDY Frnxth ; get FOR variable pointer high byte - JSR LAB_246C ; add (FOR variable) to FAC1 - JSR LAB_PFAC ; pack FAC1 into (FOR variable) - LDY #>LAB_STAK ; point to stack page high byte - JSR LAB_27FA ; compare FAC1 with (Y,ut2_pl) (TO value) - TSX ; get stack pointer back - CMP LAB_STAK+8,X ; compare step sign - BEQ LAB_1A9B ; branch if = (loop complete) - - ; loop back and do it all again - LDA LAB_STAK+$0D,X ; get FOR line low byte - STA Clinel ; save current line low byte - LDA LAB_STAK+$0E,X ; get FOR line high byte - STA Clineh ; save current line high byte - LDA LAB_STAK+$10,X ; get BASIC execute pointer low byte - STA Bpntrl ; save BASIC execute pointer low byte - LDA LAB_STAK+$0F,X ; get BASIC execute pointer high byte - STA Bpntrh ; save BASIC execute pointer high byte -LAB_1A98 - JMP LAB_15C2 ; go do interpreter inner loop - - ; loop complete so carry on -LAB_1A9B - TXA ; stack copy to A - ADC #$0F ; add $10 ($0F+carry) to dump FOR structure - TAX ; copy back to index - TXS ; copy to stack pointer - JSR LAB_GBYT ; scan memory - CMP #',' ; compare with "," - BNE LAB_1A98 ; branch if not "," (go do interpreter inner loop) - - ; was "," so another NEXT variable to do - JSR LAB_IGBY ; else increment and scan memory - JSR LAB_1A46 ; do NEXT (var) - -; evaluate expression and check is numeric, else do type mismatch - -LAB_EVNM - JSR LAB_EVEX ; evaluate expression - -; check if source is numeric, else do type mismatch - -LAB_CTNM - CLC ; destination is numeric - .byte $24 ; makes next line BIT $38 - -; check if source is string, else do type mismatch - -LAB_CTST - SEC ; required type is string - -; type match check, set C for string, clear C for numeric - -LAB_CKTM - BIT Dtypef ; test data type flag, $FF=string, $00=numeric - BMI LAB_1ABA ; branch if data type is string - - ; else data type was numeric - BCS LAB_1ABC ; if required type is string do type mismatch error -LAB_1AB9 - RTS - - ; data type was string, now check required type -LAB_1ABA - BCS LAB_1AB9 ; exit if required type is string - - ; else do type mismatch error -LAB_1ABC - LDX #$18 ; error code $18 ("Type mismatch" error) -LAB_1ABE - JMP LAB_XERR ; do error #X, then warm start - -; evaluate expression - -LAB_EVEX - LDX Bpntrl ; get BASIC execute pointer low byte - BNE LAB_1AC7 ; skip next if not zero - - DEC Bpntrh ; else decrement BASIC execute pointer high byte -LAB_1AC7 - DEC Bpntrl ; decrement BASIC execute pointer low byte - -LAB_EVEZ - LDA #$00 ; set null precedence (flag done) -LAB_1ACC - PHA ; push precedence byte - LDA #$02 ; 2 bytes - JSR LAB_1212 ; check room on stack for A bytes - JSR LAB_GVAL ; get value from line - LDA #$00 ; clear A - STA comp_f ; clear compare function flag -LAB_1ADB - JSR LAB_GBYT ; scan memory -LAB_1ADE - SEC ; set carry for subtract - SBC #TK_GT ; subtract token for > (lowest comparison function) - BCC LAB_1AFA ; branch if < TK_GT - - CMP #$03 ; compare with ">" to "<" tokens - BCS LAB_1AFA ; branch if >= TK_SGN (highest evaluation function +1) - - ; was token for > = or < (A = 0, 1 or 2) - CMP #$01 ; compare with token for = - ROL ; *2, b0 = carry (=1 if token was = or <) - ; (A = 0, 3 or 5) - EOR #$01 ; toggle b0 - ; (A = 1, 2 or 4. 1 if >, 2 if =, 4 if <) - EOR comp_f ; EOR with compare function flag bits - CMP comp_f ; compare with compare function flag - BCC LAB_1B53 ; if <(comp_f) do syntax error then warm start - ; was more than one <, = or >) - - STA comp_f ; save new compare function flag - JSR LAB_IGBY ; increment and scan memory - JMP LAB_1ADE ; go do next character - - ; token is < ">" or > "<" tokens -LAB_1AFA - LDX comp_f ; get compare function flag - BNE LAB_1B2A ; branch if compare function - - BCS LAB_1B78 ; go do functions - - ; else was < TK_GT so is operator or lower - ADC #TK_GT-TK_PLUS ; add # of operators (+, -, *, /, ^, AND, OR or EOR) - BCC LAB_1B78 ; branch if < + operator - - ; carry was set so token was +, -, *, /, ^, AND, OR or EOR - BNE LAB_1B0B ; branch if not + token - - BIT Dtypef ; test data type flag, $FF=string, $00=numeric - BPL LAB_1B0B ; branch if not string - - ; will only be $00 if type is string and token was + - JMP LAB_224D ; add strings, string 1 is in descriptor des_pl, string 2 - ; is in line, and return - -LAB_1B0B - STA ut1_pl ; save it - ASL ; *2 - ADC ut1_pl ; *3 - TAY ; copy to index -LAB_1B13 - PLA ; pull previous precedence - CMP LAB_OPPT,Y ; compare with precedence byte - BCS LAB_1B7D ; branch if A >= - - JSR LAB_CTNM ; check if source is numeric, else do type mismatch -LAB_1B1C - PHA ; save precedence -LAB_1B1D - JSR LAB_1B43 ; get vector, execute function then continue evaluation - PLA ; restore precedence - LDY prstk ; get precedence stacked flag - BPL LAB_1B3C ; branch if stacked values - - TAX ; copy precedence (set flags) - BEQ LAB_1B9D ; exit if done - - BNE LAB_1B86 ; else pop FAC2 and return, branch always - -LAB_1B2A - ROL Dtypef ; shift data type flag into Cb - TXA ; copy compare function flag - STA Dtypef ; clear data type flag, X is 0xxx xxxx - ROL ; shift data type into compare function byte b0 - LDX Bpntrl ; get BASIC execute pointer low byte - BNE LAB_1B34 ; branch if no underflow - - DEC Bpntrh ; else decrement BASIC execute pointer high byte -LAB_1B34 - DEC Bpntrl ; decrement BASIC execute pointer low byte -TK_LT_PLUS = TK_LT-TK_PLUS - LDY #TK_LT_PLUS*3 ; set offset to last operator entry - STA comp_f ; save new compare function flag - BNE LAB_1B13 ; branch always - -LAB_1B3C - CMP LAB_OPPT,Y ;.compare with stacked function precedence - BCS LAB_1B86 ; branch if A >=, pop FAC2 and return - - BCC LAB_1B1C ; branch always - -;.get vector, execute function then continue evaluation - -LAB_1B43 - LDA LAB_OPPT+2,Y ; get function vector high byte - PHA ; onto stack - LDA LAB_OPPT+1,Y ; get function vector low byte - PHA ; onto stack - ; now push sign, round FAC1 and put on stack - JSR LAB_1B5B ; function will return here, then the next RTS will call - ; the function - LDA comp_f ; get compare function flag - PHA ; push compare evaluation byte - LDA LAB_OPPT,Y ; get precedence byte - JMP LAB_1ACC ; continue evaluating expression - -LAB_1B53 - JMP LAB_SNER ; do syntax error then warm start - -; push sign, round FAC1 and put on stack - -LAB_1B5B - PLA ; get return addr low byte - STA ut1_pl ; save it - INC ut1_pl ; increment it (was ret-1 pushed? yes!) - ; note! no check is made on the high byte! if the calling - ; routine assembles to a page edge then this all goes - ; horribly wrong !!! - PLA ; get return addr high byte - STA ut1_ph ; save it - LDA FAC1_s ; get FAC1 sign (b7) - PHA ; push sign - -; round FAC1 and put on stack - -LAB_1B66 - JSR LAB_27BA ; round FAC1 - LDA FAC1_3 ; get FAC1 mantissa3 - PHA ; push on stack - LDA FAC1_2 ; get FAC1 mantissa2 - PHA ; push on stack - LDA FAC1_1 ; get FAC1 mantissa1 - PHA ; push on stack - LDA FAC1_e ; get FAC1 exponent - PHA ; push on stack - JMP (ut1_pl) ; return, sort of - -; do functions - -LAB_1B78 - LDY #$FF ; flag function - PLA ; pull precedence byte -LAB_1B7B - BEQ LAB_1B9D ; exit if done - -LAB_1B7D - CMP #$64 ; compare previous precedence with $64 - BEQ LAB_1B84 ; branch if was $64 (< function) - - JSR LAB_CTNM ; check if source is numeric, else do type mismatch -LAB_1B84 - STY prstk ; save precedence stacked flag - - ; pop FAC2 and return -LAB_1B86 - PLA ; pop byte - LSR ; shift out comparison evaluation lowest bit - STA Cflag ; save comparison evaluation flag - PLA ; pop exponent - STA FAC2_e ; save FAC2 exponent - PLA ; pop mantissa1 - STA FAC2_1 ; save FAC2 mantissa1 - PLA ; pop mantissa2 - STA FAC2_2 ; save FAC2 mantissa2 - PLA ; pop mantissa3 - STA FAC2_3 ; save FAC2 mantissa3 - PLA ; pop sign - STA FAC2_s ; save FAC2 sign (b7) - EOR FAC1_s ; EOR FAC1 sign (b7) - STA FAC_sc ; save sign compare (FAC1 EOR FAC2) -LAB_1B9D - LDA FAC1_e ; get FAC1 exponent - RTS - -; print "..." string to string util area - -LAB_1BC1 - LDA Bpntrl ; get BASIC execute pointer low byte - LDY Bpntrh ; get BASIC execute pointer high byte - ADC #$00 ; add carry to low byte - BCC LAB_1BCA ; branch if no overflow - - INY ; increment high byte -LAB_1BCA - JSR LAB_20AE ; print " terminated string to Sutill/Sutilh - JMP LAB_23F3 ; restore BASIC execute pointer from temp and return - -; get value from line - -LAB_GVAL - JSR LAB_IGBY ; increment and scan memory - BCS LAB_1BAC ; branch if not numeric character - - ; else numeric string found (e.g. 123) -LAB_1BA9 - JMP LAB_2887 ; get FAC1 from string and return - -; get value from line .. continued - - ; wasn't a number so .. -LAB_1BAC - TAX ; set the flags - BMI LAB_1BD0 ; if -ve go test token values - - ; else it is either a string, number, variable or () - CMP #'$' ; compare with "$" - BEQ LAB_1BA9 ; branch if "$", hex number - - CMP #'%' ; else compare with "%" - BEQ LAB_1BA9 ; branch if "%", binary number - - CMP #'.' ; compare with "." - BEQ LAB_1BA9 ; if so get FAC1 from string and return (e.g. was .123) - - ; it wasn't any sort of number so .. - CMP #$22 ; compare with " - BEQ LAB_1BC1 ; branch if open quote - - ; wasn't any sort of number so .. - -; evaluate expression within parentheses - - CMP #'(' ; compare with "(" - BNE LAB_1C18 ; if not "(" get (var), return value in FAC1 and $ flag - -LAB_1BF7 - JSR LAB_EVEZ ; evaluate expression, no decrement - -; all the 'scan for' routines return the character after the sought character - -; scan for ")" , else do syntax error then warm start - -LAB_1BFB - LDA #$29 ; load A with ")" - -; scan for CHR$(A) , else do syntax error then warm start - -LAB_SCCA - LDY #$00 ; clear index - CMP (Bpntrl),Y ; check next byte is = A - BNE LAB_SNER ; if not do syntax error then warm start - - JMP LAB_IGBY ; increment and scan memory then return - -; scan for "(" , else do syntax error then warm start - -LAB_1BFE - LDA #$28 ; load A with "(" - BNE LAB_SCCA ; scan for CHR$(A), else do syntax error then warm start - ; (branch always) - -; scan for "," , else do syntax error then warm start - -LAB_1C01 - LDA #$2C ; load A with "," - BNE LAB_SCCA ; scan for CHR$(A), else do syntax error then warm start - ; (branch always) - -; syntax error then warm start - -LAB_SNER - LDX #$02 ; error code $02 ("Syntax" error) - JMP LAB_XERR ; do error #X, then warm start - -; get value from line .. continued -; do tokens - -LAB_1BD0 - CMP #TK_MINUS ; compare with token for - - BEQ LAB_1C11 ; branch if - token (do set-up for functions) - - ; wasn't -n so .. - CMP #TK_PLUS ; compare with token for + - BEQ LAB_GVAL ; branch if + token (+n = n so ignore leading +) - - CMP #TK_NOT ; compare with token for NOT - BNE LAB_1BE7 ; branch if not token for NOT - - ; was NOT token -TK_EQUAL_PLUS = TK_EQUAL-TK_PLUS - LDY #TK_EQUAL_PLUS*3 ; offset to NOT function - BNE LAB_1C13 ; do set-up for function then execute (branch always) - -; do = compare - -LAB_EQUAL - JSR LAB_EVIR ; evaluate integer expression (no sign check) - LDA FAC1_3 ; get FAC1 mantissa3 - EOR #$FF ; invert it - TAY ; copy it - LDA FAC1_2 ; get FAC1 mantissa2 - EOR #$FF ; invert it - JMP LAB_AYFC ; save and convert integer AY to FAC1 and return - -; get value from line .. continued - - ; wasn't +, -, or NOT so .. -LAB_1BE7 - CMP #TK_FN ; compare with token for FN - BNE LAB_1BEE ; branch if not token for FN - - JMP LAB_201E ; go evaluate FNx - -; get value from line .. continued - - ; wasn't +, -, NOT or FN so .. -LAB_1BEE - SBC #TK_SGN ; subtract with token for SGN - BCS LAB_1C27 ; if a function token go do it - - JMP LAB_SNER ; else do syntax error - -; set-up for functions - -LAB_1C11 -TK_GT_PLUS = TK_GT-TK_PLUS - LDY #TK_GT_PLUS*3 ; set offset from base to > operator -LAB_1C13 - PLA ; dump return address low byte - PLA ; dump return address high byte - JMP LAB_1B1D ; execute function then continue evaluation - -; variable name set-up -; get (var), return value in FAC_1 and $ flag - -LAB_1C18 - JSR LAB_GVAR ; get (var) address - STA FAC1_2 ; save address low byte in FAC1 mantissa2 - STY FAC1_3 ; save address high byte in FAC1 mantissa3 - LDX Dtypef ; get data type flag, $FF=string, $00=numeric - BMI LAB_1C25 ; if string then return (does RTS) - -LAB_1C24 - JMP LAB_UFAC ; unpack memory (AY) into FAC1 - -LAB_1C25 - RTS - -; get value from line .. continued -; only functions left so .. - -; set up function references - -; new for V2.0+ this replaces a lot of IF .. THEN .. ELSEIF .. THEN .. that was needed -; to process function calls. now the function vector is computed and pushed on the stack -; and the preprocess offset is read. if the preprocess offset is non zero then the vector -; is calculated and the routine called, if not this routine just does RTS. whichever -; happens the RTS at the end of this routine, or the end of the preprocess routine, calls -; the function code - -; this also removes some less than elegant code that was used to bypass type checking -; for functions that returned strings - -LAB_1C27 - ASL ; *2 (2 bytes per function address) - TAY ; copy to index - - LDA LAB_FTBM,Y ; get function jump vector high byte - PHA ; push functions jump vector high byte - LDA LAB_FTBL,Y ; get function jump vector low byte - PHA ; push functions jump vector low byte - - LDA LAB_FTPM,Y ; get function pre process vector high byte - BEQ LAB_1C56 ; skip pre process if null vector - - PHA ; push functions pre process vector high byte - LDA LAB_FTPL,Y ; get function pre process vector low byte - PHA ; push functions pre process vector low byte - -LAB_1C56 - RTS ; do function, or pre process, call - -; process string expression in parenthesis - -LAB_PPFS - JSR LAB_1BF7 ; process expression in parenthesis - JMP LAB_CTST ; check if source is string then do function, - ; else do type mismatch - -; process numeric expression in parenthesis - -LAB_PPFN - JSR LAB_1BF7 ; process expression in parenthesis - JMP LAB_CTNM ; check if source is numeric then do function, - ; else do type mismatch - -; set numeric data type and increment BASIC execute pointer - -LAB_PPBI - LSR Dtypef ; clear data type flag, $FF=string, $00=numeric - JMP LAB_IGBY ; increment and scan memory then do function - -; process string for LEFT$, RIGHT$ or MID$ - -LAB_LRMS - JSR LAB_EVEZ ; evaluate (should be string) expression - JSR LAB_1C01 ; scan for ",", else do syntax error then warm start - JSR LAB_CTST ; check if source is string, else do type mismatch - - PLA ; get function jump vector low byte - TAX ; save functions jump vector low byte - PLA ; get function jump vector high byte - TAY ; save functions jump vector high byte - LDA des_ph ; get descriptor pointer high byte - PHA ; push string pointer high byte - LDA des_pl ; get descriptor pointer low byte - PHA ; push string pointer low byte - TYA ; get function jump vector high byte back - PHA ; save functions jump vector high byte - TXA ; get function jump vector low byte back - PHA ; save functions jump vector low byte - JSR LAB_GTBY ; get byte parameter - TXA ; copy byte parameter to A - RTS ; go do function - -; process numeric expression(s) for BIN$ or HEX$ - -LAB_BHSS - JSR LAB_EVEZ ; process expression - JSR LAB_CTNM ; check if source is numeric, else do type mismatch - LDA FAC1_e ; get FAC1 exponent - CMP #$98 ; compare with exponent = 2^24 - BCS LAB_BHER ; branch if n>=2^24 (is too big) - - JSR LAB_2831 ; convert FAC1 floating-to-fixed - LDX #$02 ; 3 bytes to do -LAB_CFAC - LDA FAC1_1,X ; get byte from FAC1 - STA nums_1,X ; save byte to temp - DEX ; decrement index - BPL LAB_CFAC ; copy FAC1 mantissa to temp - - JSR LAB_GBYT ; get next BASIC byte - LDX #$00 ; set default to no leading "0"s - CMP #')' ; compare with close bracket - BEQ LAB_1C54 ; if ")" go do rest of function - - JSR LAB_SCGB ; scan for "," and get byte - JSR LAB_GBYT ; get last byte back - CMP #')' ; is next character ) - BNE LAB_BHER ; if not ")" go do error - -LAB_1C54 - RTS ; else do function - -LAB_BHER - JMP LAB_FCER ; do function call error then warm start - -; perform EOR - -; added operator format is the same as AND or OR, precedence is the same as OR - -; this bit worked first time but it took a while to sort out the operator table -; pointers and offsets afterwards! - -LAB_EOR - JSR GetFirst ; get first integer expression (no sign check) - EOR XOAw_l ; EOR with expression 1 low byte - TAY ; save in Y - LDA FAC1_2 ; get FAC1 mantissa2 - EOR XOAw_h ; EOR with expression 1 high byte - JMP LAB_AYFC ; save and convert integer AY to FAC1 and return - -; perform OR - -LAB_OR - JSR GetFirst ; get first integer expression (no sign check) - ORA XOAw_l ; OR with expression 1 low byte - TAY ; save in Y - LDA FAC1_2 ; get FAC1 mantissa2 - ORA XOAw_h ; OR with expression 1 high byte - JMP LAB_AYFC ; save and convert integer AY to FAC1 and return - -; perform AND - -LAB_AND - JSR GetFirst ; get first integer expression (no sign check) - AND XOAw_l ; AND with expression 1 low byte - TAY ; save in Y - LDA FAC1_2 ; get FAC1 mantissa2 - AND XOAw_h ; AND with expression 1 high byte - JMP LAB_AYFC ; save and convert integer AY to FAC1 and return - -; get first value for OR, AND or EOR - -GetFirst - JSR LAB_EVIR ; evaluate integer expression (no sign check) - LDA FAC1_2 ; get FAC1 mantissa2 - STA XOAw_h ; save it - LDA FAC1_3 ; get FAC1 mantissa3 - STA XOAw_l ; save it - JSR LAB_279B ; copy FAC2 to FAC1 (get 2nd value in expression) - JSR LAB_EVIR ; evaluate integer expression (no sign check) - LDA FAC1_3 ; get FAC1 mantissa3 -LAB_1C95 - RTS - -; perform comparisons - -; do < compare - -LAB_LTHAN - JSR LAB_CKTM ; type match check, set C for string - BCS LAB_1CAE ; branch if string - - ; do numeric < compare - LDA FAC2_s ; get FAC2 sign (b7) - ORA #$7F ; set all non sign bits - AND FAC2_1 ; and FAC2 mantissa1 (AND in sign bit) - STA FAC2_1 ; save FAC2 mantissa1 - LDA #FAC2_e ; set pointer high byte to FAC2 - JSR LAB_27F8 ; compare FAC1 with FAC2 (AY) - TAX ; copy result - JMP LAB_1CE1 ; go evaluate result - - ; do string < compare -LAB_1CAE - LSR Dtypef ; clear data type flag, $FF=string, $00=numeric - DEC comp_f ; clear < bit in compare function flag - JSR LAB_22B6 ; pop string off descriptor stack, or from top of string - ; space returns with A = length, X=pointer low byte, - ; Y=pointer high byte - STA str_ln ; save length - STX str_pl ; save string pointer low byte - STY str_ph ; save string pointer high byte - LDA FAC2_2 ; get descriptor pointer low byte - LDY FAC2_3 ; get descriptor pointer high byte - JSR LAB_22BA ; pop (YA) descriptor off stack or from top of string space - ; returns with A = length, X=pointer low byte, - ; Y=pointer high byte - STX FAC2_2 ; save string pointer low byte - STY FAC2_3 ; save string pointer high byte - TAX ; copy length - SEC ; set carry for subtract - SBC str_ln ; subtract string 1 length - BEQ LAB_1CD6 ; branch if str 1 length = string 2 length - - LDA #$01 ; set str 1 length > string 2 length - BCC LAB_1CD6 ; branch if so - - LDX str_ln ; get string 1 length - LDA #$FF ; set str 1 length < string 2 length -LAB_1CD6 - STA FAC1_s ; save length compare - LDY #$FF ; set index - INX ; adjust for loop -LAB_1CDB - INY ; increment index - DEX ; decrement count - BNE LAB_1CE6 ; branch if still bytes to do - - LDX FAC1_s ; get length compare back -LAB_1CE1 - BMI LAB_1CF2 ; branch if str 1 < str 2 - - CLC ; flag str 1 <= str 2 - BCC LAB_1CF2 ; go evaluate result - -LAB_1CE6 - LDA (FAC2_2),Y ; get string 2 byte - CMP (FAC1_1),Y ; compare with string 1 byte - BEQ LAB_1CDB ; loop if bytes = - - LDX #$FF ; set str 1 < string 2 - BCS LAB_1CF2 ; branch if so - - LDX #$01 ; set str 1 > string 2 -LAB_1CF2 - INX ; x = 0, 1 or 2 - TXA ; copy to A - ROL ; *2 (1, 2 or 4) - AND Cflag ; AND with comparison evaluation flag - BEQ LAB_1CFB ; branch if 0 (compare is false) - - LDA #$FF ; else set result true -LAB_1CFB - JMP LAB_27DB ; save A as integer byte and return - -LAB_1CFE - JSR LAB_1C01 ; scan for ",", else do syntax error then warm start - -; perform DIM - -LAB_DIM - TAX ; copy "DIM" flag to X - JSR LAB_1D10 ; search for variable - JSR LAB_GBYT ; scan memory - BNE LAB_1CFE ; scan for "," and loop if not null - - RTS - -; perform << (left shift) - -LAB_LSHIFT - JSR GetPair ; get integer expression and byte (no sign check) - LDA FAC1_2 ; get expression high byte - LDX TempB ; get shift count - BEQ NoShift ; branch if zero - - CPX #$10 ; compare bit count with 16d - BCS TooBig ; branch if >= - -Ls_loop - ASL FAC1_3 ; shift low byte - ROL ; shift high byte - DEX ; decrement bit count - BNE Ls_loop ; loop if shift not complete - - LDY FAC1_3 ; get expression low byte - JMP LAB_AYFC ; save and convert integer AY to FAC1 and return - -; perform >> (right shift) - -LAB_RSHIFT - JSR GetPair ; get integer expression and byte (no sign check) - LDA FAC1_2 ; get expression high byte - LDX TempB ; get shift count - BEQ NoShift ; branch if zero - - CPX #$10 ; compare bit count with 16d - BCS TooBig ; branch if >= - -Rs_loop - LSR ; shift high byte - ROR FAC1_3 ; shift low byte - DEX ; decrement bit count - BNE Rs_loop ; loop if shift not complete - -NoShift - LDY FAC1_3 ; get expression low byte - JMP LAB_AYFC ; save and convert integer AY to FAC1 and return - -TooBig - LDA #$00 ; clear high byte - TAY ; copy to low byte - JMP LAB_AYFC ; save and convert integer AY to FAC1 and return - -GetPair - JSR LAB_EVBY ; evaluate byte expression, result in X - STX TempB ; save it - JSR LAB_279B ; copy FAC2 to FAC1 (get 2nd value in expression) - JMP LAB_EVIR ; evaluate integer expression (no sign check) - -; search for variable - -; return pointer to variable in Cvaral/Cvarah - -LAB_GVAR - LDX #$00 ; set DIM flag = $00 - JSR LAB_GBYT ; scan memory (1st character) -LAB_1D10 - STX Defdim ; save DIM flag -LAB_1D12 - STA Varnm1 ; save 1st character - AND #$7F ; clear FN flag bit - JSR LAB_CASC ; check byte, return C=0 if<"A" or >"Z" - BCS LAB_1D1F ; branch if ok - - JMP LAB_SNER ; else syntax error then warm start - - ; was variable name so .. -LAB_1D1F - LDX #$00 ; clear 2nd character temp - STX Dtypef ; clear data type flag, $FF=string, $00=numeric - JSR LAB_IGBY ; increment and scan memory (2nd character) - BCC LAB_1D2D ; branch if character = "0"-"9" (ok) - - ; 2nd character wasn't "0" to "9" so .. - JSR LAB_CASC ; check byte, return C=0 if<"A" or >"Z" - BCC LAB_1D38 ; branch if <"A" or >"Z" (go check if string) - -LAB_1D2D - TAX ; copy 2nd character - - ; ignore further (valid) characters in the variable name -LAB_1D2E - JSR LAB_IGBY ; increment and scan memory (3rd character) - BCC LAB_1D2E ; loop if character = "0"-"9" (ignore) - - JSR LAB_CASC ; check byte, return C=0 if<"A" or >"Z" - BCS LAB_1D2E ; loop if character = "A"-"Z" (ignore) - - ; check if string variable -LAB_1D38 - CMP #'$' ; compare with "$" - BNE LAB_1D47 ; branch if not string - -; to introduce a new variable type (% suffix for integers say) then this branch -; will need to go to that check and then that branch, if it fails, go to LAB_1D47 - - ; type is string - LDA #$FF ; set data type = string - STA Dtypef ; set data type flag, $FF=string, $00=numeric - TXA ; get 2nd character back - ORA #$80 ; set top bit (indicate string var) - TAX ; copy back to 2nd character temp - JSR LAB_IGBY ; increment and scan memory - -; after we have determined the variable type we need to come back here to determine -; if it's an array of type. this would plug in a%(b[,c[,d]])) integer arrays nicely - - -LAB_1D47 ; gets here with character after var name in A - STX Varnm2 ; save 2nd character - ORA Sufnxf ; or with subscript/FNX flag (or FN name) - CMP #'(' ; compare with "(" - BNE LAB_1D53 ; branch if not "(" - - JMP LAB_1E17 ; go find, or make, array - -; either find or create var -; var name (1st two characters only!) is in Varnm1,Varnm2 - - ; variable name wasn't var(... so look for plain var -LAB_1D53 - LDA #$00 ; clear A - STA Sufnxf ; clear subscript/FNX flag - LDA Svarl ; get start of vars low byte - LDX Svarh ; get start of vars high byte - LDY #$00 ; clear index -LAB_1D5D - STX Vrschh ; save search address high byte -LAB_1D5F - STA Vrschl ; save search address low byte - CPX Sarryh ; compare high address with var space end - BNE LAB_1D69 ; skip next compare if <> - - ; high addresses were = so compare low addresses - CMP Sarryl ; compare low address with var space end - BEQ LAB_1D8B ; if not found go make new var - -LAB_1D69 - LDA Varnm1 ; get 1st character of var to find - CMP (Vrschl),Y ; compare with variable name 1st character - BNE LAB_1D77 ; branch if no match - - ; 1st characters match so compare 2nd characters - LDA Varnm2 ; get 2nd character of var to find - INY ; index to point to variable name 2nd character - CMP (Vrschl),Y ; compare with variable name 2nd character - BEQ LAB_1DD7 ; branch if match (found var) - - DEY ; else decrement index (now = $00) -LAB_1D77 - CLC ; clear carry for add - LDA Vrschl ; get search address low byte - ADC #$06 ; +6 (offset to next var name) - BCC LAB_1D5F ; loop if no overflow to high byte - - INX ; else increment high byte - BNE LAB_1D5D ; loop always (RAM doesn't extend to $FFFF !) - -; check byte, return C=0 if<"A" or >"Z" or "a" to "z" - -LAB_CASC - CMP #'a' ; compare with "a" - BCS LAB_1D83 ; go check <"z"+1 - -; check byte, return C=0 if<"A" or >"Z" - -LAB_1D82 - CMP #'A' ; compare with "A" - BCC LAB_1D8A ; exit if less - - ; carry is set - SBC #$5B ; subtract "Z"+1 - SEC ; set carry - SBC #$A5 ; subtract $A5 (restore byte) - ; carry clear if byte>$5A -LAB_1D8A - RTS - -LAB_1D83 - SBC #$7B ; subtract "z"+1 - SEC ; set carry - SBC #$85 ; subtract $85 (restore byte) - ; carry clear if byte>$7A - RTS - - ; reached end of variable mem without match - ; .. so create new variable -LAB_1D8B - PLA ; pop return address low byte - PHA ; push return address low byte -LAB_1C18p2 = LAB_1C18+2 - CMP #LAB_1D96 ; high byte point to $00,$00 - RTS - - ; create new numeric variable -LAB_1D98 - LDA Sarryl ; get var mem end low byte - LDY Sarryh ; get var mem end high byte - STA Ostrtl ; save old block start low byte - STY Ostrth ; save old block start high byte - LDA Earryl ; get array mem end low byte - LDY Earryh ; get array mem end high byte - STA Obendl ; save old block end low byte - STY Obendh ; save old block end high byte - CLC ; clear carry for add - ADC #$06 ; +6 (space for one var) - BCC LAB_1DAE ; branch if no overflow to high byte - - INY ; else increment high byte -LAB_1DAE - STA Nbendl ; set new block end low byte - STY Nbendh ; set new block end high byte - JSR LAB_11CF ; open up space in memory - LDA Nbendl ; get new start low byte - LDY Nbendh ; get new start high byte (-$100) - INY ; correct high byte - STA Sarryl ; save new var mem end low byte - STY Sarryh ; save new var mem end high byte - LDY #$00 ; clear index - LDA Varnm1 ; get var name 1st character - STA (Vrschl),Y ; save var name 1st character - INY ; increment index - LDA Varnm2 ; get var name 2nd character - STA (Vrschl),Y ; save var name 2nd character - LDA #$00 ; clear A - INY ; increment index - STA (Vrschl),Y ; initialise var byte - INY ; increment index - STA (Vrschl),Y ; initialise var byte - INY ; increment index - STA (Vrschl),Y ; initialise var byte - INY ; increment index - STA (Vrschl),Y ; initialise var byte - - ; found a match for var ((Vrschl) = ptr) -LAB_1DD7 - LDA Vrschl ; get var address low byte - CLC ; clear carry for add - ADC #$02 ; +2 (offset past var name bytes) - LDY Vrschh ; get var address high byte - BCC LAB_1DE1 ; branch if no overflow from add - - INY ; else increment high byte -LAB_1DE1 - STA Cvaral ; save current var address low byte - STY Cvarah ; save current var address high byte - RTS - -; set-up array pointer (Adatal/h) to first element in array -; set Adatal,Adatah to Astrtl,Astrth+2*Dimcnt+#$05 - -LAB_1DE6 - LDA Dimcnt ; get # of dimensions (1, 2 or 3) - ASL ; *2 (also clears the carry !) - ADC #$05 ; +5 (result is 7, 9 or 11 here) - ADC Astrtl ; add array start pointer low byte - LDY Astrth ; get array pointer high byte - BCC LAB_1DF2 ; branch if no overflow - - INY ; else increment high byte -LAB_1DF2 - STA Adatal ; save array data pointer low byte - STY Adatah ; save array data pointer high byte - RTS - -; evaluate integer expression - -LAB_EVIN - JSR LAB_IGBY ; increment and scan memory - JSR LAB_EVNM ; evaluate expression and check is numeric, - ; else do type mismatch - -; evaluate integer expression (no check) - -LAB_EVPI - LDA FAC1_s ; get FAC1 sign (b7) - BMI LAB_1E12 ; do function call error if -ve - -; evaluate integer expression (no sign check) - -LAB_EVIR - LDA FAC1_e ; get FAC1 exponent - CMP #$90 ; compare with exponent = 2^16 (n>2^15) - BCC LAB_1E14 ; branch if n<2^16 (is ok) - - LDA #LAB_1DF7 ; set pointer high byte to -32768 - JSR LAB_27F8 ; compare FAC1 with (AY) -LAB_1E12 - BNE LAB_FCER ; if <> do function call error then warm start - -LAB_1E14 - JMP LAB_2831 ; convert FAC1 floating-to-fixed and return - -; find or make array - -LAB_1E17 - LDA Defdim ; get DIM flag - PHA ; push it - LDA Dtypef ; get data type flag, $FF=string, $00=numeric - PHA ; push it - LDY #$00 ; clear dimensions count - -; now get the array dimension(s) and stack it (them) before the data type and DIM flag - -LAB_1E1F - TYA ; copy dimensions count - PHA ; save it - LDA Varnm2 ; get array name 2nd byte - PHA ; save it - LDA Varnm1 ; get array name 1st byte - PHA ; save it - JSR LAB_EVIN ; evaluate integer expression - PLA ; pull array name 1st byte - STA Varnm1 ; restore array name 1st byte - PLA ; pull array name 2nd byte - STA Varnm2 ; restore array name 2nd byte - PLA ; pull dimensions count - TAY ; restore it - TSX ; copy stack pointer - LDA LAB_STAK+2,X ; get DIM flag - PHA ; push it - LDA LAB_STAK+1,X ; get data type flag - PHA ; push it - LDA FAC1_2 ; get this dimension size high byte - STA LAB_STAK+2,X ; stack before flag bytes - LDA FAC1_3 ; get this dimension size low byte - STA LAB_STAK+1,X ; stack before flag bytes - INY ; increment dimensions count - JSR LAB_GBYT ; scan memory - CMP #',' ; compare with "," - BEQ LAB_1E1F ; if found go do next dimension - - STY Dimcnt ; store dimensions count - JSR LAB_1BFB ; scan for ")" , else do syntax error then warm start - PLA ; pull data type flag - STA Dtypef ; restore data type flag, $FF=string, $00=numeric - PLA ; pull DIM flag - STA Defdim ; restore DIM flag - LDX Sarryl ; get array mem start low byte - LDA Sarryh ; get array mem start high byte - -; now check to see if we are at the end of array memory (we would be if there were -; no arrays). - -LAB_1E5C - STX Astrtl ; save as array start pointer low byte - STA Astrth ; save as array start pointer high byte - CMP Earryh ; compare with array mem end high byte - BNE LAB_1E68 ; branch if not reached array mem end - - CPX Earryl ; else compare with array mem end low byte - BEQ LAB_1EA1 ; go build array if not found - - ; search for array -LAB_1E68 - LDY #$00 ; clear index - LDA (Astrtl),Y ; get array name first byte - INY ; increment index to second name byte - CMP Varnm1 ; compare with this array name first byte - BNE LAB_1E77 ; branch if no match - - LDA Varnm2 ; else get this array name second byte - CMP (Astrtl),Y ; compare with array name second byte - BEQ LAB_1E8D ; array found so branch - - ; no match -LAB_1E77 - INY ; increment index - LDA (Astrtl),Y ; get array size low byte - CLC ; clear carry for add - ADC Astrtl ; add array start pointer low byte - TAX ; copy low byte to X - INY ; increment index - LDA (Astrtl),Y ; get array size high byte - ADC Astrth ; add array mem pointer high byte - BCC LAB_1E5C ; if no overflow go check next array - -; do array bounds error - -LAB_1E85 - LDX #$10 ; error code $10 ("Array bounds" error) - .byte $2C ; makes next bit BIT LAB_08A2 - -; do function call error - -LAB_FCER - LDX #$08 ; error code $08 ("Function call" error) -LAB_1E8A - JMP LAB_XERR ; do error #X, then warm start - - ; found array, are we trying to dimension it? -LAB_1E8D - LDX #$12 ; set error $12 ("Double dimension" error) - LDA Defdim ; get DIM flag - BNE LAB_1E8A ; if we are trying to dimension it do error #X, then warm - ; start - -; found the array and we're not dimensioning it so we must find an element in it - - JSR LAB_1DE6 ; set-up array pointer (Adatal/h) to first element in array - ; (Astrtl,Astrth points to start of array) - LDA Dimcnt ; get dimensions count - LDY #$04 ; set index to array's # of dimensions - CMP (Astrtl),Y ; compare with no of dimensions - BNE LAB_1E85 ; if wrong do array bounds error, could do "Wrong - ; dimensions" error here .. if we want a different - ; error message - - JMP LAB_1F28 ; found array so go get element - ; (could jump to LAB_1F28 as all LAB_1F24 does is take - ; Dimcnt and save it at (Astrtl),Y which is already the - ; same or we would have taken the BNE) - - ; array not found, so build it -LAB_1EA1 - JSR LAB_1DE6 ; set-up array pointer (Adatal/h) to first element in array - ; (Astrtl,Astrth points to start of array) - JSR LAB_121F ; check available memory, "Out of memory" error if no room - ; addr to check is in AY (low/high) - LDY #$00 ; clear Y (don't need to clear A) - STY Aspth ; clear array data size high byte - LDA Varnm1 ; get variable name 1st byte - STA (Astrtl),Y ; save array name 1st byte - INY ; increment index - LDA Varnm2 ; get variable name 2nd byte - STA (Astrtl),Y ; save array name 2nd byte - LDA Dimcnt ; get dimensions count - LDY #$04 ; index to dimension count - STY Asptl ; set array data size low byte (four bytes per element) - STA (Astrtl),Y ; set array's dimensions count - - ; now calculate the size of the data space for the array - CLC ; clear carry for add (clear on subsequent loops) -LAB_1EC0 - LDX #$0B ; set default dimension value low byte - LDA #$00 ; set default dimension value high byte - BIT Defdim ; test default DIM flag - BVC LAB_1ED0 ; branch if b6 of Defdim is clear - - PLA ; else pull dimension value low byte - ADC #$01 ; +1 (allow for zeroeth element) - TAX ; copy low byte to X - PLA ; pull dimension value high byte - ADC #$00 ; add carry from low byte - -LAB_1ED0 - INY ; index to dimension value high byte - STA (Astrtl),Y ; save dimension value high byte - INY ; index to dimension value high byte - TXA ; get dimension value low byte - STA (Astrtl),Y ; save dimension value low byte - JSR LAB_1F7C ; does XY = (Astrtl),Y * (Asptl) - STX Asptl ; save array data size low byte - STA Aspth ; save array data size high byte - LDY ut1_pl ; restore index (saved by subroutine) - DEC Dimcnt ; decrement dimensions count - BNE LAB_1EC0 ; loop while not = 0 - - ADC Adatah ; add size high byte to first element high byte - ; (carry is always clear here) - BCS LAB_1F45 ; if overflow go do "Out of memory" error - - STA Adatah ; save end of array high byte - TAY ; copy end high byte to Y - TXA ; get array size low byte - ADC Adatal ; add array start low byte - BCC LAB_1EF3 ; branch if no carry - - INY ; else increment end of array high byte - BEQ LAB_1F45 ; if overflow go do "Out of memory" error - - ; set-up mostly complete, now zero the array -LAB_1EF3 - JSR LAB_121F ; check available memory, "Out of memory" error if no room - ; addr to check is in AY (low/high) - STA Earryl ; save array mem end low byte - STY Earryh ; save array mem end high byte - LDA #$00 ; clear byte for array clear - INC Aspth ; increment array size high byte (now block count) - LDY Asptl ; get array size low byte (now index to block) - BEQ LAB_1F07 ; branch if low byte = $00 - -LAB_1F02 - DEY ; decrement index (do 0 to n-1) - STA (Adatal),Y ; zero byte - BNE LAB_1F02 ; loop until this block done - -LAB_1F07 - DEC Adatah ; decrement array pointer high byte - DEC Aspth ; decrement block count high byte - BNE LAB_1F02 ; loop until all blocks done - - INC Adatah ; correct for last loop - SEC ; set carry for subtract - LDY #$02 ; index to array size low byte - LDA Earryl ; get array mem end low byte - SBC Astrtl ; subtract array start low byte - STA (Astrtl),Y ; save array size low byte - INY ; index to array size high byte - LDA Earryh ; get array mem end high byte - SBC Astrth ; subtract array start high byte - STA (Astrtl),Y ; save array size high byte - LDA Defdim ; get default DIM flag - BNE LAB_1F7B ; exit (RET) if this was a DIM command - - ; else, find element - INY ; index to # of dimensions - -LAB_1F24 - LDA (Astrtl),Y ; get array's dimension count - STA Dimcnt ; save it - -; we have found, or built, the array. now we need to find the element - -LAB_1F28 - LDA #$00 ; clear byte - STA Asptl ; clear array data pointer low byte -LAB_1F2C - STA Aspth ; save array data pointer high byte - INY ; increment index (point to array bound high byte) - PLA ; pull array index low byte - TAX ; copy to X - STA FAC1_2 ; save index low byte to FAC1 mantissa2 - PLA ; pull array index high byte - STA FAC1_3 ; save index high byte to FAC1 mantissa3 - CMP (Astrtl),Y ; compare with array bound high byte - BCC LAB_1F48 ; branch if within bounds - - BNE LAB_1F42 ; if outside bounds do array bounds error - - ; else high byte was = so test low bytes - INY ; index to array bound low byte - TXA ; get array index low byte - CMP (Astrtl),Y ; compare with array bound low byte - BCC LAB_1F49 ; branch if within bounds - -LAB_1F42 - JMP LAB_1E85 ; else do array bounds error - -LAB_1F45 - JMP LAB_OMER ; do "Out of memory" error then warm start - -LAB_1F48 - INY ; index to array bound low byte -LAB_1F49 - LDA Aspth ; get array data pointer high byte - ORA Asptl ; OR with array data pointer low byte - BEQ LAB_1F5A ; branch if array data pointer = null (skip multiply) - - JSR LAB_1F7C ; does XY = (Astrtl),Y * (Asptl) - TXA ; get result low byte - ADC FAC1_2 ; add index low byte from FAC1 mantissa2 - TAX ; save result low byte - TYA ; get result high byte - LDY ut1_pl ; restore index -LAB_1F5A - ADC FAC1_3 ; add index high byte from FAC1 mantissa3 - STX Asptl ; save array data pointer low byte - DEC Dimcnt ; decrement dimensions count - BNE LAB_1F2C ; loop if dimensions still to do - - ASL Asptl ; array data pointer low byte * 2 - ROL ; array data pointer high byte * 2 - ASL Asptl ; array data pointer low byte * 4 - ROL ; array data pointer high byte * 4 - TAY ; copy high byte - LDA Asptl ; get low byte - ADC Adatal ; add array data start pointer low byte - STA Cvaral ; save as current var address low byte - TYA ; get high byte back - ADC Adatah ; add array data start pointer high byte - STA Cvarah ; save as current var address high byte - TAY ; copy high byte to Y - LDA Cvaral ; get current var address low byte -LAB_1F7B - RTS - -; does XY = (Astrtl),Y * (Asptl) - -LAB_1F7C - STY ut1_pl ; save index - LDA (Astrtl),Y ; get dimension size low byte - STA dims_l ; save dimension size low byte - DEY ; decrement index - LDA (Astrtl),Y ; get dimension size high byte - STA dims_h ; save dimension size high byte - - LDA #$10 ; count = $10 (16 bit multiply) - STA numbit ; save bit count - LDX #$00 ; clear result low byte - LDY #$00 ; clear result high byte -LAB_1F8F - TXA ; get result low byte - ASL ; *2 - TAX ; save result low byte - TYA ; get result high byte - ROL ; *2 - TAY ; save result high byte - BCS LAB_1F45 ; if overflow go do "Out of memory" error - - ASL Asptl ; shift multiplier low byte - ROL Aspth ; shift multiplier high byte - BCC LAB_1FA8 ; skip add if no carry - - CLC ; else clear carry for add - TXA ; get result low byte - ADC dims_l ; add dimension size low byte - TAX ; save result low byte - TYA ; get result high byte - ADC dims_h ; add dimension size high byte - TAY ; save result high byte - BCS LAB_1F45 ; if overflow go do "Out of memory" error - -LAB_1FA8 - DEC numbit ; decrement bit count - BNE LAB_1F8F ; loop until all done - - RTS - -; perform FRE() - -LAB_FRE - LDA Dtypef ; get data type flag, $FF=string, $00=numeric - BPL LAB_1FB4 ; branch if numeric - - JSR LAB_22B6 ; pop string off descriptor stack, or from top of string - ; space returns with A = length, X=$71=pointer low byte, - ; Y=$72=pointer high byte - - ; FRE(n) was numeric so do this -LAB_1FB4 - JSR LAB_GARB ; go do garbage collection - SEC ; set carry for subtract - LDA Sstorl ; get bottom of string space low byte - SBC Earryl ; subtract array mem end low byte - TAY ; copy result to Y - LDA Sstorh ; get bottom of string space high byte - SBC Earryh ; subtract array mem end high byte - -; save and convert integer AY to FAC1 - -LAB_AYFC - LSR Dtypef ; clear data type flag, $FF=string, $00=numeric - STA FAC1_1 ; save FAC1 mantissa1 - STY FAC1_2 ; save FAC1 mantissa2 - LDX #$90 ; set exponent=2^16 (integer) - JMP LAB_27E3 ; set exp=X, clear FAC1_3, normalise and return - -; perform POS() - -LAB_POS - LDY TPos ; get terminal position - -; convert Y to byte in FAC1 - -LAB_1FD0 - LDA #$00 ; clear high byte - BEQ LAB_AYFC ; always save and convert integer AY to FAC1 and return - -; check not Direct (used by DEF and INPUT) - -LAB_CKRN - LDX Clineh ; get current line high byte - INX ; increment it - BNE LAB_1F7B ; return if can continue not direct mode - - ; else do illegal direct error -LAB_1FD9 - LDX #$16 ; error code $16 ("Illegal direct" error) -LAB_1FDB - JMP LAB_XERR ; go do error #X, then warm start - -; perform DEF - -LAB_DEF - JSR LAB_200B ; check FNx syntax - STA func_l ; save function pointer low byte - STY func_h ; save function pointer high byte - JSR LAB_CKRN ; check not Direct (back here if ok) - JSR LAB_1BFE ; scan for "(" , else do syntax error then warm start - LDA #$80 ; set flag for FNx - STA Sufnxf ; save subscript/FNx flag - JSR LAB_GVAR ; get (var) address - JSR LAB_CTNM ; check if source is numeric, else do type mismatch - JSR LAB_1BFB ; scan for ")" , else do syntax error then warm start - LDA #TK_EQUAL ; get = token - JSR LAB_SCCA ; scan for CHR$(A), else do syntax error then warm start - LDA Cvarah ; get current var address high byte - PHA ; push it - LDA Cvaral ; get current var address low byte - PHA ; push it - LDA Bpntrh ; get BASIC execute pointer high byte - PHA ; push it - LDA Bpntrl ; get BASIC execute pointer low byte - PHA ; push it - JSR LAB_DATA ; go perform DATA - JMP LAB_207A ; put execute pointer and variable pointer into function - ; and return - -; check FNx syntax - -LAB_200B - LDA #TK_FN ; get FN" token - JSR LAB_SCCA ; scan for CHR$(A) , else do syntax error then warm start - ; return character after A - ORA #$80 ; set FN flag bit - STA Sufnxf ; save FN flag so array variable test fails - JSR LAB_1D12 ; search for FN variable - JMP LAB_CTNM ; check if source is numeric and return, else do type - ; mismatch - - ; Evaluate FNx -LAB_201E - JSR LAB_200B ; check FNx syntax - PHA ; push function pointer low byte - TYA ; copy function pointer high byte - PHA ; push function pointer high byte - JSR LAB_1BFE ; scan for "(", else do syntax error then warm start - JSR LAB_EVEX ; evaluate expression - JSR LAB_1BFB ; scan for ")", else do syntax error then warm start - JSR LAB_CTNM ; check if source is numeric, else do type mismatch - PLA ; pop function pointer high byte - STA func_h ; restore it - PLA ; pop function pointer low byte - STA func_l ; restore it - LDX #$20 ; error code $20 ("Undefined function" error) - LDY #$03 ; index to variable pointer high byte - LDA (func_l),Y ; get variable pointer high byte - BEQ LAB_1FDB ; if zero go do undefined function error - - STA Cvarah ; save variable address high byte - DEY ; index to variable address low byte - LDA (func_l),Y ; get variable address low byte - STA Cvaral ; save variable address low byte - TAX ; copy address low byte - - ; now stack the function variable value before use - INY ; index to mantissa_3 -LAB_2043 - LDA (Cvaral),Y ; get byte from variable - PHA ; stack it - DEY ; decrement index - BPL LAB_2043 ; loop until variable stacked - - LDY Cvarah ; get variable address high byte - JSR LAB_2778 ; pack FAC1 (function expression value) into (XY) - ; (function variable), return Y=0, always - LDA Bpntrh ; get BASIC execute pointer high byte - PHA ; push it - LDA Bpntrl ; get BASIC execute pointer low byte - PHA ; push it - LDA (func_l),Y ; get function execute pointer low byte - STA Bpntrl ; save as BASIC execute pointer low byte - INY ; index to high byte - LDA (func_l),Y ; get function execute pointer high byte - STA Bpntrh ; save as BASIC execute pointer high byte - LDA Cvarah ; get variable address high byte - PHA ; push it - LDA Cvaral ; get variable address low byte - PHA ; push it - JSR LAB_EVNM ; evaluate expression and check is numeric, - ; else do type mismatch - PLA ; pull variable address low byte - STA func_l ; save variable address low byte - PLA ; pull variable address high byte - STA func_h ; save variable address high byte - JSR LAB_GBYT ; scan memory - BEQ LAB_2074 ; branch if null (should be [EOL] marker) - - JMP LAB_SNER ; else syntax error then warm start - -; restore Bpntrl,Bpntrh and function variable from stack - -LAB_2074 - PLA ; pull BASIC execute pointer low byte - STA Bpntrl ; restore BASIC execute pointer low byte - PLA ; pull BASIC execute pointer high byte - STA Bpntrh ; restore BASIC execute pointer high byte - -; put execute pointer and variable pointer into function - -LAB_207A - LDY #$00 ; clear index - PLA ; pull BASIC execute pointer low byte - STA (func_l),Y ; save to function - INY ; increment index - PLA ; pull BASIC execute pointer high byte - STA (func_l),Y ; save to function - INY ; increment index - PLA ; pull current var address low byte - STA (func_l),Y ; save to function - INY ; increment index - PLA ; pull current var address high byte - STA (func_l),Y ; save to function - RTS - -; perform STR$() - -LAB_STRS - JSR LAB_CTNM ; check if source is numeric, else do type mismatch - JSR LAB_296E ; convert FAC1 to string - LDA #Decssp1 ; set result string high pointer - BEQ LAB_20AE ; print null terminated string to Sutill/Sutilh - -; Do string vector -; copy des_pl/h to des_2l/h and make string space A bytes long - -LAB_209C - LDX des_pl ; get descriptor pointer low byte - LDY des_ph ; get descriptor pointer high byte - STX des_2l ; save descriptor pointer low byte - STY des_2h ; save descriptor pointer high byte - -; make string space A bytes long -; A=length, X=Sutill=ptr low byte, Y=Sutilh=ptr high byte - -LAB_MSSP - JSR LAB_2115 ; make space in string memory for string A long - ; return X=Sutill=ptr low byte, Y=Sutilh=ptr high byte - STX str_pl ; save string pointer low byte - STY str_ph ; save string pointer high byte - STA str_ln ; save length - RTS - -; Scan, set up string -; print " terminated string to Sutill/Sutilh - -LAB_20AE - LDX #$22 ; set terminator to " - STX Srchc ; set search character (terminator 1) - STX Asrch ; set terminator 2 - -; print [Srchc] or [Asrch] terminated string to Sutill/Sutilh -; source is AY - -LAB_20B4 - STA ssptr_l ; store string start low byte - STY ssptr_h ; store string start high byte - STA str_pl ; save string pointer low byte - STY str_ph ; save string pointer high byte - LDY #$FF ; set length to -1 -LAB_20BE - INY ; increment length - LDA (ssptr_l),Y ; get byte from string - BEQ LAB_20CF ; exit loop if null byte [EOS] - - CMP Srchc ; compare with search character (terminator 1) - BEQ LAB_20CB ; branch if terminator - - CMP Asrch ; compare with terminator 2 - BNE LAB_20BE ; loop if not terminator 2 - -LAB_20CB - CMP #$22 ; compare with " - BEQ LAB_20D0 ; branch if " (carry set if = !) - -LAB_20CF - CLC ; clear carry for add (only if [EOL] terminated string) -LAB_20D0 - STY str_ln ; save length in FAC1 exponent - TYA ; copy length to A - ADC ssptr_l ; add string start low byte - STA Sendl ; save string end low byte - LDX ssptr_h ; get string start high byte - BCC LAB_20DC ; branch if no low byte overflow - - INX ; else increment high byte -LAB_20DC - STX Sendh ; save string end high byte - LDA ssptr_h ; get string start high byte - CMP #>Ram_base ; compare with start of program memory - BCS LAB_RTST ; branch if not in utility area - - ; string in utility area, move to string memory - TYA ; copy length to A - JSR LAB_209C ; copy des_pl/h to des_2l/h and make string space A bytes - ; long - LDX ssptr_l ; get string start low byte - LDY ssptr_h ; get string start high byte - JSR LAB_2298 ; store string A bytes long from XY to (Sutill) - -; check for space on descriptor stack then .. -; put string address and length on descriptor stack and update stack pointers - -LAB_RTST - LDX next_s ; get string stack pointer - CPX #des_sk+$09 ; compare with max+1 - BNE LAB_20F8 ; branch if space on string stack - - ; else do string too complex error - LDX #$1C ; error code $1C ("String too complex" error) -LAB_20F5 - JMP LAB_XERR ; do error #X, then warm start - -; put string address and length on descriptor stack and update stack pointers - -LAB_20F8 - LDA str_ln ; get string length - STA PLUS_0,X ; put on string stack - LDA str_pl ; get string pointer low byte - STA PLUS_1,X ; put on string stack - LDA str_ph ; get string pointer high byte - STA PLUS_2,X ; put on string stack - LDY #$00 ; clear Y - STX des_pl ; save string descriptor pointer low byte - STY des_ph ; save string descriptor pointer high byte (always $00) - DEY ; Y = $FF - STY Dtypef ; save data type flag, $FF=string - STX last_sl ; save old stack pointer (current top item) - INX ; update stack pointer - INX ; update stack pointer - INX ; update stack pointer - STX next_s ; save new top item value - RTS - -; Build descriptor -; make space in string memory for string A long -; return X=Sutill=ptr low byte, Y=Sutill=ptr high byte - -LAB_2115 - LSR Gclctd ; clear garbage collected flag (b7) - - ; make space for string A long -LAB_2117 - PHA ; save string length - EOR #$FF ; complement it - SEC ; set carry for subtract (twos comp add) - ADC Sstorl ; add bottom of string space low byte (subtract length) - LDY Sstorh ; get bottom of string space high byte - BCS LAB_2122 ; skip decrement if no underflow - - DEY ; decrement bottom of string space high byte -LAB_2122 - CPY Earryh ; compare with array mem end high byte - BCC LAB_2137 ; do out of memory error if less - - BNE LAB_212C ; if not = skip next test - - CMP Earryl ; compare with array mem end low byte - BCC LAB_2137 ; do out of memory error if less - -LAB_212C - STA Sstorl ; save bottom of string space low byte - STY Sstorh ; save bottom of string space high byte - STA Sutill ; save string utility ptr low byte - STY Sutilh ; save string utility ptr high byte - TAX ; copy low byte to X - PLA ; get string length back - RTS - -LAB_2137 - LDX #$0C ; error code $0C ("Out of memory" error) - LDA Gclctd ; get garbage collected flag - BMI LAB_20F5 ; if set then do error code X - - JSR LAB_GARB ; else go do garbage collection - LDA #$80 ; flag for garbage collected - STA Gclctd ; set garbage collected flag - PLA ; pull length - BNE LAB_2117 ; go try again (loop always, length should never be = $00) - -; garbage collection routine - -LAB_GARB - LDX Ememl ; get end of mem low byte - LDA Ememh ; get end of mem high byte - -; re-run routine from last ending - -LAB_214B - STX Sstorl ; set string storage low byte - STA Sstorh ; set string storage high byte - LDY #$00 ; clear index - STY garb_h ; clear working pointer high byte (flag no strings to move) - LDA Earryl ; get array mem end low byte - LDX Earryh ; get array mem end high byte - STA Histrl ; save as highest string low byte - STX Histrh ; save as highest string high byte - LDA #des_sk ; set descriptor stack pointer - STA ut1_pl ; save descriptor stack pointer low byte - STY ut1_ph ; save descriptor stack pointer high byte ($00) -LAB_2161 - CMP next_s ; compare with descriptor stack pointer - BEQ LAB_216A ; branch if = - - JSR LAB_21D7 ; go garbage collect descriptor stack - BEQ LAB_2161 ; loop always - - ; done stacked strings, now do string vars -LAB_216A - ASL g_step ; set step size = $06 - LDA Svarl ; get start of vars low byte - LDX Svarh ; get start of vars high byte - STA ut1_pl ; save as pointer low byte - STX ut1_ph ; save as pointer high byte -LAB_2176 - CPX Sarryh ; compare start of arrays high byte - BNE LAB_217E ; branch if no high byte match - - CMP Sarryl ; else compare start of arrays low byte - BEQ LAB_2183 ; branch if = var mem end - -LAB_217E - JSR LAB_21D1 ; go garbage collect strings - BEQ LAB_2176 ; loop always - - ; done string vars, now do string arrays -LAB_2183 - STA Nbendl ; save start of arrays low byte as working pointer - STX Nbendh ; save start of arrays high byte as working pointer - LDA #$04 ; set step size - STA g_step ; save step size -LAB_218B - LDA Nbendl ; get pointer low byte - LDX Nbendh ; get pointer high byte -LAB_218F - CPX Earryh ; compare with array mem end high byte - BNE LAB_219A ; branch if not at end - - CMP Earryl ; else compare with array mem end low byte - BEQ LAB_2216 ; tidy up and exit if at end - -LAB_219A - STA ut1_pl ; save pointer low byte - STX ut1_ph ; save pointer high byte - LDY #$02 ; set index - LDA (ut1_pl),Y ; get array size low byte - ADC Nbendl ; add start of this array low byte - STA Nbendl ; save start of next array low byte - INY ; increment index - LDA (ut1_pl),Y ; get array size high byte - ADC Nbendh ; add start of this array high byte - STA Nbendh ; save start of next array high byte - LDY #$01 ; set index - LDA (ut1_pl),Y ; get name second byte - BPL LAB_218B ; skip if not string array - -; was string array so .. - - LDY #$04 ; set index - LDA (ut1_pl),Y ; get # of dimensions - ASL ; *2 - ADC #$05 ; +5 (array header size) - JSR LAB_2208 ; go set up for first element -LAB_21C4 - CPX Nbendh ; compare with start of next array high byte - BNE LAB_21CC ; branch if <> (go do this array) - - CMP Nbendl ; else compare element pointer low byte with next array - ; low byte - BEQ LAB_218F ; if equal then go do next array - -LAB_21CC - JSR LAB_21D7 ; go defrag array strings - BEQ LAB_21C4 ; go do next array string (loop always) - -; defrag string variables -; enter with XA = variable pointer -; return with XA = next variable pointer - -LAB_21D1 - INY ; increment index (Y was $00) - LDA (ut1_pl),Y ; get var name byte 2 - BPL LAB_2206 ; if not string, step pointer to next var and return - - INY ; else increment index -LAB_21D7 - LDA (ut1_pl),Y ; get string length - BEQ LAB_2206 ; if null, step pointer to next string and return - - INY ; else increment index - LDA (ut1_pl),Y ; get string pointer low byte - TAX ; copy to X - INY ; increment index - LDA (ut1_pl),Y ; get string pointer high byte - CMP Sstorh ; compare bottom of string space high byte - BCC LAB_21EC ; branch if less - - BNE LAB_2206 ; if greater, step pointer to next string and return - - ; high bytes were = so compare low bytes - CPX Sstorl ; compare bottom of string space low byte - BCS LAB_2206 ; if >=, step pointer to next string and return - - ; string pointer is < string storage pointer (pos in mem) -LAB_21EC - CMP Histrh ; compare to highest string high byte - BCC LAB_2207 ; if <, step pointer to next string and return - - BNE LAB_21F6 ; if > update pointers, step to next and return - - ; high bytes were = so compare low bytes - CPX Histrl ; compare to highest string low byte - BCC LAB_2207 ; if <, step pointer to next string and return - - ; string is in string memory space -LAB_21F6 - STX Histrl ; save as new highest string low byte - STA Histrh ; save as new highest string high byte - LDA ut1_pl ; get start of vars(descriptors) low byte - LDX ut1_ph ; get start of vars(descriptors) high byte - STA garb_l ; save as working pointer low byte - STX garb_h ; save as working pointer high byte - DEY ; decrement index DIFFERS - DEY ; decrement index (should point to descriptor start) - STY g_indx ; save index pointer - - ; step pointer to next string -LAB_2206 - CLC ; clear carry for add -LAB_2207 - LDA g_step ; get step size -LAB_2208 - ADC ut1_pl ; add pointer low byte - STA ut1_pl ; save pointer low byte - BCC LAB_2211 ; branch if no overflow - - INC ut1_ph ; else increment high byte -LAB_2211 - LDX ut1_ph ; get pointer high byte - LDY #$00 ; clear Y - RTS - -; search complete, now either exit or set-up and move string - -LAB_2216 - DEC g_step ; decrement step size (now $03 for descriptor stack) - LDX garb_h ; get string to move high byte - BEQ LAB_2211 ; exit if nothing to move - - LDY g_indx ; get index byte back (points to descriptor) - CLC ; clear carry for add - LDA (garb_l),Y ; get string length - ADC Histrl ; add highest string low byte - STA Obendl ; save old block end low pointer - LDA Histrh ; get highest string high byte - ADC #$00 ; add any carry - STA Obendh ; save old block end high byte - LDA Sstorl ; get bottom of string space low byte - LDX Sstorh ; get bottom of string space high byte - STA Nbendl ; save new block end low byte - STX Nbendh ; save new block end high byte - JSR LAB_11D6 ; open up space in memory, don't set array end - LDY g_indx ; get index byte - INY ; point to descriptor low byte - LDA Nbendl ; get string pointer low byte - STA (garb_l),Y ; save new string pointer low byte - TAX ; copy string pointer low byte - INC Nbendh ; correct high byte (move sets high byte -1) - LDA Nbendh ; get new string pointer high byte - INY ; point to descriptor high byte - STA (garb_l),Y ; save new string pointer high byte - JMP LAB_214B ; re-run routine from last ending - ; (but don't collect this string) - -; concatenate -; add strings, string 1 is in descriptor des_pl, string 2 is in line - -LAB_224D - LDA des_ph ; get descriptor pointer high byte - PHA ; put on stack - LDA des_pl ; get descriptor pointer low byte - PHA ; put on stack - JSR LAB_GVAL ; get value from line - JSR LAB_CTST ; check if source is string, else do type mismatch - PLA ; get descriptor pointer low byte back - STA ssptr_l ; set pointer low byte - PLA ; get descriptor pointer high byte back - STA ssptr_h ; set pointer high byte - LDY #$00 ; clear index - LDA (ssptr_l),Y ; get length_1 from descriptor - CLC ; clear carry for add - ADC (des_pl),Y ; add length_2 - BCC LAB_226D ; branch if no overflow - - LDX #$1A ; else set error code $1A ("String too long" error) - JMP LAB_XERR ; do error #X, then warm start - -LAB_226D - JSR LAB_209C ; copy des_pl/h to des_2l/h and make string space A bytes - ; long - JSR LAB_228A ; copy string from descriptor (sdescr) to (Sutill) - LDA des_2l ; get descriptor pointer low byte - LDY des_2h ; get descriptor pointer high byte - JSR LAB_22BA ; pop (YA) descriptor off stack or from top of string space - ; returns with A = length, ut1_pl = pointer low byte, - ; ut1_ph = pointer high byte - JSR LAB_229C ; store string A bytes long from (ut1_pl) to (Sutill) - LDA ssptr_l ;.set descriptor pointer low byte - LDY ssptr_h ;.set descriptor pointer high byte - JSR LAB_22BA ; pop (YA) descriptor off stack or from top of string space - ; returns with A = length, X=ut1_pl=pointer low byte, - ; Y=ut1_ph=pointer high byte - JSR LAB_RTST ; check for space on descriptor stack then put string - ; address and length on descriptor stack and update stack - ; pointers - JMP LAB_1ADB ;.continue evaluation - -; copy string from descriptor (sdescr) to (Sutill) - -LAB_228A - LDY #$00 ; clear index - LDA (sdescr),Y ; get string length - PHA ; save on stack - INY ; increment index - LDA (sdescr),Y ; get source string pointer low byte - TAX ; copy to X - INY ; increment index - LDA (sdescr),Y ; get source string pointer high byte - TAY ; copy to Y - PLA ; get length back - -; store string A bytes long from YX to (Sutill) - -LAB_2298 - STX ut1_pl ; save source string pointer low byte - STY ut1_ph ; save source string pointer high byte - -; store string A bytes long from (ut1_pl) to (Sutill) - -LAB_229C - TAX ; copy length to index (don't count with Y) - BEQ LAB_22B2 ; branch if = $0 (null string) no need to add zero length - - LDY #$00 ; zero pointer (copy forward) -LAB_22A0 - LDA (ut1_pl),Y ; get source byte - STA (Sutill),Y ; save destination byte - - INY ; increment index - DEX ; decrement counter - BNE LAB_22A0 ; loop while <> 0 - - TYA ; restore length from Y -LAB_22A9 - CLC ; clear carry for add - ADC Sutill ; add string utility ptr low byte - STA Sutill ; save string utility ptr low byte - BCC LAB_22B2 ; branch if no carry - - INC Sutilh ; else increment string utility ptr high byte -LAB_22B2 - RTS - -; evaluate string - -LAB_EVST - JSR LAB_CTST ; check if source is string, else do type mismatch - -; pop string off descriptor stack, or from top of string space -; returns with A = length, X=pointer low byte, Y=pointer high byte - -LAB_22B6 - LDA des_pl ; get descriptor pointer low byte - LDY des_ph ; get descriptor pointer high byte - -; pop (YA) descriptor off stack or from top of string space -; returns with A = length, X=ut1_pl=pointer low byte, Y=ut1_ph=pointer high byte - -LAB_22BA - STA ut1_pl ; save descriptor pointer low byte - STY ut1_ph ; save descriptor pointer high byte - JSR LAB_22EB ; clean descriptor stack, YA = pointer - PHP ; save status flags - LDY #$00 ; clear index - LDA (ut1_pl),Y ; get length from string descriptor - PHA ; put on stack - INY ; increment index - LDA (ut1_pl),Y ; get string pointer low byte from descriptor - TAX ; copy to X - INY ; increment index - LDA (ut1_pl),Y ; get string pointer high byte from descriptor - TAY ; copy to Y - PLA ; get string length back - PLP ; restore status - BNE LAB_22E6 ; branch if pointer <> last_sl,last_sh - - CPY Sstorh ; compare bottom of string space high byte - BNE LAB_22E6 ; branch if <> - - CPX Sstorl ; else compare bottom of string space low byte - BNE LAB_22E6 ; branch if <> - - PHA ; save string length - CLC ; clear carry for add - ADC Sstorl ; add bottom of string space low byte - STA Sstorl ; save bottom of string space low byte - BCC LAB_22E5 ; skip increment if no overflow - - INC Sstorh ; increment bottom of string space high byte -LAB_22E5 - PLA ; restore string length -LAB_22E6 - STX ut1_pl ; save string pointer low byte - STY ut1_ph ; save string pointer high byte - RTS - -; clean descriptor stack, YA = pointer -; checks if AY is on the descriptor stack, if so does a stack discard - -LAB_22EB - CPY last_sh ; compare pointer high byte - BNE LAB_22FB ; exit if <> - - CMP last_sl ; compare pointer low byte - BNE LAB_22FB ; exit if <> - - STA next_s ; save descriptor stack pointer - SBC #$03 ; -3 - STA last_sl ; save low byte -3 - LDY #$00 ; clear high byte -LAB_22FB - RTS - -; perform CHR$() - -LAB_CHRS - JSR LAB_EVBY ; evaluate byte expression, result in X - TXA ; copy to A - PHA ; save character - LDA #$01 ; string is single byte - JSR LAB_MSSP ; make string space A bytes long A=$AC=length, - ; X=$AD=Sutill=ptr low byte, Y=$AE=Sutilh=ptr high byte - PLA ; get character back - LDY #$00 ; clear index - STA (str_pl),Y ; save byte in string (byte IS string!) - JMP LAB_RTST ; check for space on descriptor stack then put string - ; address and length on descriptor stack and update stack - ; pointers - -; perform LEFT$() - -LAB_LEFT - PHA ; push byte parameter - JSR LAB_236F ; pull string data and byte parameter from stack - ; return pointer in des_2l/h, byte in A (and X), Y=0 - CMP (des_2l),Y ; compare byte parameter with string length - TYA ; clear A - BEQ LAB_2316 ; go do string copy (branch always) - -; perform RIGHT$() - -LAB_RIGHT - PHA ; push byte parameter - JSR LAB_236F ; pull string data and byte parameter from stack - ; return pointer in des_2l/h, byte in A (and X), Y=0 - CLC ; clear carry for add-1 - SBC (des_2l),Y ; subtract string length - EOR #$FF ; invert it (A=LEN(expression$)-l) - -LAB_2316 - BCC LAB_231C ; branch if string length > byte parameter - - LDA (des_2l),Y ; else make parameter = length - TAX ; copy to byte parameter copy - TYA ; clear string start offset -LAB_231C - PHA ; save string start offset -LAB_231D - TXA ; copy byte parameter (or string length if <) -LAB_231E - PHA ; save string length - JSR LAB_MSSP ; make string space A bytes long A=$AC=length, - ; X=$AD=Sutill=ptr low byte, Y=$AE=Sutilh=ptr high byte - LDA des_2l ; get descriptor pointer low byte - LDY des_2h ; get descriptor pointer high byte - JSR LAB_22BA ; pop (YA) descriptor off stack or from top of string space - ; returns with A = length, X=ut1_pl=pointer low byte, - ; Y=ut1_ph=pointer high byte - PLA ; get string length back - TAY ; copy length to Y - PLA ; get string start offset back - CLC ; clear carry for add - ADC ut1_pl ; add start offset to string start pointer low byte - STA ut1_pl ; save string start pointer low byte - BCC LAB_2335 ; branch if no overflow - - INC ut1_ph ; else increment string start pointer high byte -LAB_2335 - TYA ; copy length to A - JSR LAB_229C ; store string A bytes long from (ut1_pl) to (Sutill) - JMP LAB_RTST ; check for space on descriptor stack then put string - ; address and length on descriptor stack and update stack - ; pointers - -; perform MID$() - -LAB_MIDS - PHA ; push byte parameter - LDA #$FF ; set default length = 255 - STA mids_l ; save default length - JSR LAB_GBYT ; scan memory - CMP #')' ; compare with ")" - BEQ LAB_2358 ; branch if = ")" (skip second byte get) - - JSR LAB_1C01 ; scan for "," , else do syntax error then warm start - JSR LAB_GTBY ; get byte parameter (use copy in mids_l) -LAB_2358 - JSR LAB_236F ; pull string data and byte parameter from stack - ; return pointer in des_2l/h, byte in A (and X), Y=0 - DEX ; decrement start index - TXA ; copy to A - PHA ; save string start offset - CLC ; clear carry for sub-1 - LDX #$00 ; clear output string length - SBC (des_2l),Y ; subtract string length - BCS LAB_231D ; if start>string length go do null string - - EOR #$FF ; complement -length - CMP mids_l ; compare byte parameter - BCC LAB_231E ; if length>remaining string go do RIGHT$ - - LDA mids_l ; get length byte - BCS LAB_231E ; go do string copy (branch always) - -; pull string data and byte parameter from stack -; return pointer in des_2l/h, byte in A (and X), Y=0 - -LAB_236F - JSR LAB_1BFB ; scan for ")" , else do syntax error then warm start - PLA ; pull return address low byte (return address) - STA Fnxjpl ; save functions jump vector low byte - PLA ; pull return address high byte (return address) - STA Fnxjph ; save functions jump vector high byte - PLA ; pull byte parameter - TAX ; copy byte parameter to X - PLA ; pull string pointer low byte - STA des_2l ; save it - PLA ; pull string pointer high byte - STA des_2h ; save it - LDY #$00 ; clear index - TXA ; copy byte parameter - BEQ LAB_23A8 ; if null do function call error then warm start - - INC Fnxjpl ; increment function jump vector low byte - ; (JSR pushes return addr-1. this is all very nice - ; but will go tits up if either call is on a page - ; boundary!) - JMP (Fnxjpl) ; in effect, RTS - -; perform LCASE$() - -LAB_LCASE - JSR LAB_EVST ; evaluate string - STA str_ln ; set string length - TAY ; copy length to Y - BEQ NoString ; branch if null string - - JSR LAB_MSSP ; make string space A bytes long A=length, - ; X=Sutill=ptr low byte, Y=Sutilh=ptr high byte - STX str_pl ; save string pointer low byte - STY str_ph ; save string pointer high byte - TAY ; get string length back - -LC_loop - DEY ; decrement index - LDA (ut1_pl),Y ; get byte from string - JSR LAB_1D82 ; is character "A" to "Z" - BCC NoUcase ; branch if not upper case alpha - - ORA #$20 ; convert upper to lower case -NoUcase - STA (Sutill),Y ; save byte back to string - TYA ; test index - BNE LC_loop ; loop if not all done - - BEQ NoString ; tidy up and exit, branch always - -; perform UCASE$() - -LAB_UCASE - JSR LAB_EVST ; evaluate string - STA str_ln ; set string length - TAY ; copy length to Y - BEQ NoString ; branch if null string - - JSR LAB_MSSP ; make string space A bytes long A=length, - ; X=Sutill=ptr low byte, Y=Sutilh=ptr high byte - STX str_pl ; save string pointer low byte - STY str_ph ; save string pointer high byte - TAY ; get string length back - -UC_loop - DEY ; decrement index - LDA (ut1_pl),Y ; get byte from string - JSR LAB_CASC ; is character "a" to "z" (or "A" to "Z") - BCC NoLcase ; branch if not alpha - - AND #$DF ; convert lower to upper case -NoLcase - STA (Sutill),Y ; save byte back to string - TYA ; test index - BNE UC_loop ; loop if not all done - -NoString - JMP LAB_RTST ; check for space on descriptor stack then put string - ; address and length on descriptor stack and update stack - ; pointers - -; perform SADD() - -LAB_SADD - JSR LAB_IGBY ; increment and scan memory - JSR LAB_GVAR ; get var address - - JSR LAB_1BFB ; scan for ")", else do syntax error then warm start - JSR LAB_CTST ; check if source is string, else do type mismatch - - LDY #$02 ; index to string pointer high byte - LDA (Cvaral),Y ; get string pointer high byte - TAX ; copy string pointer high byte to X - DEY ; index to string pointer low byte - LDA (Cvaral),Y ; get string pointer low byte - TAY ; copy string pointer low byte to Y - TXA ; copy string pointer high byte to A - JMP LAB_AYFC ; save and convert integer AY to FAC1 and return - -; perform LEN() - -LAB_LENS - JSR LAB_ESGL ; evaluate string, get length in A (and Y) - JMP LAB_1FD0 ; convert Y to byte in FAC1 and return - -; evaluate string, get length in Y - -LAB_ESGL - JSR LAB_EVST ; evaluate string - TAY ; copy length to Y - RTS - -; perform ASC() - -LAB_ASC - JSR LAB_ESGL ; evaluate string, get length in A (and Y) - BEQ LAB_23A8 ; if null do function call error then warm start - - LDY #$00 ; set index to first character - LDA (ut1_pl),Y ; get byte - TAY ; copy to Y - JMP LAB_1FD0 ; convert Y to byte in FAC1 and return - -; do function call error then warm start - -LAB_23A8 - JMP LAB_FCER ; do function call error then warm start - -; scan and get byte parameter - -LAB_SGBY - JSR LAB_IGBY ; increment and scan memory - -; get byte parameter - -LAB_GTBY - JSR LAB_EVNM ; evaluate expression and check is numeric, - ; else do type mismatch - -; evaluate byte expression, result in X - -LAB_EVBY - JSR LAB_EVPI ; evaluate integer expression (no check) - - LDY FAC1_2 ; get FAC1 mantissa2 - BNE LAB_23A8 ; if top byte <> 0 do function call error then warm start - - LDX FAC1_3 ; get FAC1 mantissa3 - JMP LAB_GBYT ; scan memory and return - -; perform VAL() - -LAB_VAL - JSR LAB_ESGL ; evaluate string, get length in A (and Y) - BNE LAB_23C5 ; branch if not null string - - ; string was null so set result = $00 - JMP LAB_24F1 ; clear FAC1 exponent and sign and return - -LAB_23C5 - LDX Bpntrl ; get BASIC execute pointer low byte - LDY Bpntrh ; get BASIC execute pointer high byte - STX Btmpl ; save BASIC execute pointer low byte - STY Btmph ; save BASIC execute pointer high byte - LDX ut1_pl ; get string pointer low byte - STX Bpntrl ; save as BASIC execute pointer low byte - CLC ; clear carry - ADC ut1_pl ; add string length - STA ut2_pl ; save string end low byte - LDA ut1_ph ; get string pointer high byte - STA Bpntrh ; save as BASIC execute pointer high byte - ADC #$00 ; add carry to high byte - STA ut2_ph ; save string end high byte - LDY #$00 ; set index to $00 - LDA (ut2_pl),Y ; get string end +1 byte - PHA ; push it - TYA ; clear A - STA (ut2_pl),Y ; terminate string with $00 - JSR LAB_GBYT ; scan memory - JSR LAB_2887 ; get FAC1 from string - PLA ; restore string end +1 byte - LDY #$00 ; set index to zero - STA (ut2_pl),Y ; put string end byte back - -; restore BASIC execute pointer from temp (Btmpl/Btmph) - -LAB_23F3 - LDX Btmpl ; get BASIC execute pointer low byte back - LDY Btmph ; get BASIC execute pointer high byte back - STX Bpntrl ; save BASIC execute pointer low byte - STY Bpntrh ; save BASIC execute pointer high byte - RTS - -; get two parameters for POKE or WAIT - -LAB_GADB - JSR LAB_EVNM ; evaluate expression and check is numeric, - ; else do type mismatch - JSR LAB_F2FX ; save integer part of FAC1 in temporary integer - -; scan for "," and get byte, else do Syntax error then warm start - -LAB_SCGB - JSR LAB_1C01 ; scan for "," , else do syntax error then warm start - LDA Itemph ; save temporary integer high byte - PHA ; on stack - LDA Itempl ; save temporary integer low byte - PHA ; on stack - JSR LAB_GTBY ; get byte parameter - PLA ; pull low byte - STA Itempl ; restore temporary integer low byte - PLA ; pull high byte - STA Itemph ; restore temporary integer high byte - RTS - -; convert float to fixed routine. accepts any value that fits in 24 bits, +ve or -; -ve and converts it into a right truncated integer in Itempl and Itemph - -; save unsigned 16 bit integer part of FAC1 in temporary integer - -LAB_F2FX - LDA FAC1_e ; get FAC1 exponent - CMP #$98 ; compare with exponent = 2^24 - BCS LAB_23A8 ; if >= do function call error then warm start - -LAB_F2FU - JSR LAB_2831 ; convert FAC1 floating-to-fixed - LDA FAC1_2 ; get FAC1 mantissa2 - LDY FAC1_3 ; get FAC1 mantissa3 - STY Itempl ; save temporary integer low byte - STA Itemph ; save temporary integer high byte - RTS - -; perform PEEK() - -LAB_PEEK - JSR LAB_F2FX ; save integer part of FAC1 in temporary integer - LDX #$00 ; clear index - LDA (Itempl,X) ; get byte via temporary integer (addr) - TAY ; copy byte to Y - JMP LAB_1FD0 ; convert Y to byte in FAC1 and return - -; perform POKE - -LAB_POKE - JSR LAB_GADB ; get two parameters for POKE or WAIT - TXA ; copy byte argument to A - LDX #$00 ; clear index - STA (Itempl,X) ; save byte via temporary integer (addr) - RTS - -; perform DEEK() - -LAB_DEEK - JSR LAB_F2FX ; save integer part of FAC1 in temporary integer - LDX #$00 ; clear index - LDA (Itempl,X) ; PEEK low byte - TAY ; copy to Y - INC Itempl ; increment pointer low byte - BNE Deekh ; skip high increment if no rollover - - INC Itemph ; increment pointer high byte -Deekh - LDA (Itempl,X) ; PEEK high byte - JMP LAB_AYFC ; save and convert integer AY to FAC1 and return - -; perform DOKE - -LAB_DOKE - JSR LAB_EVNM ; evaluate expression and check is numeric, - ; else do type mismatch - JSR LAB_F2FX ; convert floating-to-fixed - - STY Frnxtl ; save pointer low byte (float to fixed returns word in AY) - STA Frnxth ; save pointer high byte - - JSR LAB_1C01 ; scan for "," , else do syntax error then warm start - JSR LAB_EVNM ; evaluate expression and check is numeric, - ; else do type mismatch - JSR LAB_F2FX ; convert floating-to-fixed - - TYA ; copy value low byte (float to fixed returns word in AY) - LDX #$00 ; clear index - STA (Frnxtl,X) ; POKE low byte - INC Frnxtl ; increment pointer low byte - BNE Dokeh ; skip high increment if no rollover - - INC Frnxth ; increment pointer high byte -Dokeh - LDA Itemph ; get value high byte - STA (Frnxtl,X) ; POKE high byte - JMP LAB_GBYT ; scan memory and return - -; perform SWAP - -LAB_SWAP - JSR LAB_GVAR ; get var1 address - STA Lvarpl ; save var1 address low byte - STY Lvarph ; save var1 address high byte - LDA Dtypef ; get data type flag, $FF=string, $00=numeric - PHA ; save data type flag - - JSR LAB_1C01 ; scan for "," , else do syntax error then warm start - JSR LAB_GVAR ; get var2 address (pointer in Cvaral/h) - PLA ; pull var1 data type flag - EOR Dtypef ; compare with var2 data type - BPL SwapErr ; exit if not both the same type - - LDY #$03 ; four bytes to swap (either value or descriptor+1) -SwapLp - LDA (Lvarpl),Y ; get byte from var1 - TAX ; save var1 byte - LDA (Cvaral),Y ; get byte from var2 - STA (Lvarpl),Y ; save byte to var1 - TXA ; restore var1 byte - STA (Cvaral),Y ; save byte to var2 - DEY ; decrement index - BPL SwapLp ; loop until done - - RTS - -SwapErr - JMP LAB_1ABC ; do "Type mismatch" error then warm start - -; perform CALL - -LAB_CALL - JSR LAB_EVNM ; evaluate expression and check is numeric, - ; else do type mismatch - JSR LAB_F2FX ; convert floating-to-fixed - LDA #>CallExit ; set return address high byte - PHA ; put on stack - LDA #8 shifts) - BCC LAB_24A8 ;.go subtract mantissas - -; add 0.5 to FAC1 - -LAB_244E - LDA #LAB_2A96 ; set 0.5 pointer high byte - -; add (AY) to FAC1 - -LAB_246C - JSR LAB_264D ; unpack memory (AY) into FAC2 - -; add FAC2 to FAC1 - -LAB_ADD - BNE LAB_2474 ; branch if FAC1 was not zero - -; copy FAC2 to FAC1 - -LAB_279B - LDA FAC2_s ; get FAC2 sign (b7) - -; save FAC1 sign and copy ABS(FAC2) to FAC1 - -LAB_279D - STA FAC1_s ; save FAC1 sign (b7) - LDX #$04 ; 4 bytes to copy -LAB_27A1 - LDA FAC1_o,X ; get byte from FAC2,X - STA FAC1_e-1,X ; save byte at FAC1,X - DEX ; decrement count - BNE LAB_27A1 ; loop if not all done - - STX FAC1_r ; clear FAC1 rounding byte - RTS - - ; FAC1 is non zero -LAB_2474 - LDX FAC1_r ; get FAC1 rounding byte - STX FAC2_r ; save as FAC2 rounding byte - LDX #FAC2_e ; set index to FAC2 exponent addr - LDA FAC2_e ; get FAC2 exponent -LAB_247C - TAY ; copy exponent - BEQ LAB_244D ; exit if zero - - SEC ; set carry for subtract - SBC FAC1_e ; subtract FAC1 exponent - BEQ LAB_24A8 ; branch if = (go add mantissa) - - BCC LAB_2498 ; branch if < - - ; FAC2>FAC1 - STY FAC1_e ; save FAC1 exponent - LDY FAC2_s ; get FAC2 sign (b7) - STY FAC1_s ; save FAC1 sign (b7) - EOR #$FF ; complement A - ADC #$00 ; +1 (twos complement, carry is set) - LDY #$00 ; clear Y - STY FAC2_r ; clear FAC2 rounding byte - LDX #FAC1_e ; set index to FAC1 exponent addr - BNE LAB_249C ; branch always - -LAB_2498 - LDY #$00 ; clear Y - STY FAC1_r ; clear FAC1 rounding byte -LAB_249C - CMP #$F9 ; compare exponent diff with $F9 - BMI LAB_2467 ; branch if range $79-$F8 - - TAY ; copy exponent difference to Y - LDA FAC1_r ; get FAC1 rounding byte - LSR PLUS_1,X ; shift FAC? mantissa1 - JSR LAB_2592 ; shift FACX Y times right - - ; exponents are equal now do mantissa subtract -LAB_24A8 - BIT FAC_sc ; test sign compare (FAC1 EOR FAC2) - BPL LAB_24F8 ; if = add FAC2 mantissa to FAC1 mantissa and return - - LDY #FAC1_e ; set index to FAC1 exponent addr - CPX #FAC2_e ; compare X to FAC2 exponent addr - BEQ LAB_24B4 ; branch if = - - LDY #FAC2_e ; else set index to FAC2 exponent addr - - ; subtract smaller from bigger (take sign of bigger) -LAB_24B4 - SEC ; set carry for subtract - EOR #$FF ; ones complement A - ADC FAC2_r ; add FAC2 rounding byte - STA FAC1_r ; save FAC1 rounding byte - LDA PLUS_3,Y ; get FACY mantissa3 - SBC PLUS_3,X ; subtract FACX mantissa3 - STA FAC1_3 ; save FAC1 mantissa3 - LDA PLUS_2,Y ; get FACY mantissa2 - SBC PLUS_2,X ; subtract FACX mantissa2 - STA FAC1_2 ; save FAC1 mantissa2 - LDA PLUS_1,Y ; get FACY mantissa1 - SBC PLUS_1,X ; subtract FACX mantissa1 - STA FAC1_1 ; save FAC1 mantissa1 - -; do ABS and normalise FAC1 - -LAB_24D0 - BCS LAB_24D5 ; branch if number is +ve - - JSR LAB_2537 ; negate FAC1 - -; normalise FAC1 - -LAB_24D5 - LDY #$00 ; clear Y - TYA ; clear A - CLC ; clear carry for add -LAB_24D9 - LDX FAC1_1 ; get FAC1 mantissa1 - BNE LAB_251B ; if not zero normalise FAC1 - - LDX FAC1_2 ; get FAC1 mantissa2 - STX FAC1_1 ; save FAC1 mantissa1 - LDX FAC1_3 ; get FAC1 mantissa3 - STX FAC1_2 ; save FAC1 mantissa2 - LDX FAC1_r ; get FAC1 rounding byte - STX FAC1_3 ; save FAC1 mantissa3 - STY FAC1_r ; clear FAC1 rounding byte - ADC #$08 ; add x to exponent offset - CMP #$18 ; compare with $18 (max offset, all bits would be =0) - BNE LAB_24D9 ; loop if not max - -; clear FAC1 exponent and sign - -LAB_24F1 - LDA #$00 ; clear A -LAB_24F3 - STA FAC1_e ; set FAC1 exponent - -; save FAC1 sign - -LAB_24F5 - STA FAC1_s ; save FAC1 sign (b7) - RTS - -; add FAC2 mantissa to FAC1 mantissa - -LAB_24F8 - ADC FAC2_r ; add FAC2 rounding byte - STA FAC1_r ; save FAC1 rounding byte - LDA FAC1_3 ; get FAC1 mantissa3 - ADC FAC2_3 ; add FAC2 mantissa3 - STA FAC1_3 ; save FAC1 mantissa3 - LDA FAC1_2 ; get FAC1 mantissa2 - ADC FAC2_2 ; add FAC2 mantissa2 - STA FAC1_2 ; save FAC1 mantissa2 - LDA FAC1_1 ; get FAC1 mantissa1 - ADC FAC2_1 ; add FAC2 mantissa1 - STA FAC1_1 ; save FAC1 mantissa1 - BCS LAB_252A ; if carry then normalise FAC1 for C=1 - - RTS ; else just exit - -LAB_2511 - ADC #$01 ; add 1 to exponent offset - ASL FAC1_r ; shift FAC1 rounding byte - ROL FAC1_3 ; shift FAC1 mantissa3 - ROL FAC1_2 ; shift FAC1 mantissa2 - ROL FAC1_1 ; shift FAC1 mantissa1 - -; normalise FAC1 - -LAB_251B - BPL LAB_2511 ; loop if not normalised - - SEC ; set carry for subtract - SBC FAC1_e ; subtract FAC1 exponent - BCS LAB_24F1 ; branch if underflow (set result = $0) - - EOR #$FF ; complement exponent - ADC #$01 ; +1 (twos complement) - STA FAC1_e ; save FAC1 exponent - -; test and normalise FAC1 for C=0/1 - -LAB_2528 - BCC LAB_2536 ; exit if no overflow - -; normalise FAC1 for C=1 - -LAB_252A - INC FAC1_e ; increment FAC1 exponent - BEQ LAB_2564 ; if zero do overflow error and warm start - - ROR FAC1_1 ; shift FAC1 mantissa1 - ROR FAC1_2 ; shift FAC1 mantissa2 - ROR FAC1_3 ; shift FAC1 mantissa3 - ROR FAC1_r ; shift FAC1 rounding byte -LAB_2536 - RTS - -; negate FAC1 - -LAB_2537 - LDA FAC1_s ; get FAC1 sign (b7) - EOR #$FF ; complement it - STA FAC1_s ; save FAC1 sign (b7) - -; twos complement FAC1 mantissa - -LAB_253D - LDA FAC1_1 ; get FAC1 mantissa1 - EOR #$FF ; complement it - STA FAC1_1 ; save FAC1 mantissa1 - LDA FAC1_2 ; get FAC1 mantissa2 - EOR #$FF ; complement it - STA FAC1_2 ; save FAC1 mantissa2 - LDA FAC1_3 ; get FAC1 mantissa3 - EOR #$FF ; complement it - STA FAC1_3 ; save FAC1 mantissa3 - LDA FAC1_r ; get FAC1 rounding byte - EOR #$FF ; complement it - STA FAC1_r ; save FAC1 rounding byte - INC FAC1_r ; increment FAC1 rounding byte - BNE LAB_2563 ; exit if no overflow - -; increment FAC1 mantissa - -LAB_2559 - INC FAC1_3 ; increment FAC1 mantissa3 - BNE LAB_2563 ; finished if no rollover - - INC FAC1_2 ; increment FAC1 mantissa2 - BNE LAB_2563 ; finished if no rollover - - INC FAC1_1 ; increment FAC1 mantissa1 -LAB_2563 - RTS - -; do overflow error (overflow exit) - -LAB_2564 - LDX #$0A ; error code $0A ("Overflow" error) - JMP LAB_XERR ; do error #X, then warm start - -; shift FCAtemp << A+8 times - -LAB_2569 - LDX #FACt_1-1 ; set offset to FACtemp -LAB_256B - LDY PLUS_3,X ; get FACX mantissa3 - STY FAC1_r ; save as FAC1 rounding byte - LDY PLUS_2,X ; get FACX mantissa2 - STY PLUS_3,X ; save FACX mantissa3 - LDY PLUS_1,X ; get FACX mantissa1 - STY PLUS_2,X ; save FACX mantissa2 - LDY FAC1_o ; get FAC1 overflow byte - STY PLUS_1,X ; save FACX mantissa1 - -; shift FACX -A times right (> 8 shifts) - -LAB_257B - ADC #$08 ; add 8 to shift count - BMI LAB_256B ; go do 8 shift if still -ve - - BEQ LAB_256B ; go do 8 shift if zero - - SBC #$08 ; else subtract 8 again - TAY ; save count to Y - LDA FAC1_r ; get FAC1 rounding byte - BCS LAB_259A ;. - -LAB_2588 - ASL PLUS_1,X ; shift FACX mantissa1 - BCC LAB_258E ; branch if +ve - - INC PLUS_1,X ; this sets b7 eventually -LAB_258E - ROR PLUS_1,X ; shift FACX mantissa1 (correct for ASL) - ROR PLUS_1,X ; shift FACX mantissa1 (put carry in b7) - -; shift FACX Y times right - -LAB_2592 - ROR PLUS_2,X ; shift FACX mantissa2 - ROR PLUS_3,X ; shift FACX mantissa3 - ROR ; shift FACX rounding byte - INY ; increment exponent diff - BNE LAB_2588 ; branch if range adjust not complete - -LAB_259A - CLC ; just clear it - RTS - -; perform LOG() - -LAB_LOG - JSR LAB_27CA ; test sign and zero - BEQ LAB_25C4 ; if zero do function call error then warm start - - BPL LAB_25C7 ; skip error if +ve - -LAB_25C4 - JMP LAB_FCER ; do function call error then warm start (-ve) - -LAB_25C7 - LDA FAC1_e ; get FAC1 exponent - SBC #$7F ; normalise it - PHA ; save it - LDA #$80 ; set exponent to zero - STA FAC1_e ; save FAC1 exponent - LDA #LAB_25AD ; set 1/root2 pointer high byte - JSR LAB_246C ; add (AY) to FAC1 (1/root2) - LDA #LAB_25B1 ; set root2 pointer high byte - JSR LAB_26CA ; convert AY and do (AY)/FAC1 (root2/(x+(1/root2))) - LDA #LAB_259C ; set 1 pointer high byte - JSR LAB_2455 ; subtract (AY) from FAC1 ((root2/(x+(1/root2)))-1) - LDA #LAB_25A0 ; set pointer high byte to counter - JSR LAB_2B6E ; ^2 then series evaluation - LDA #LAB_25B5 ; set -0.5 pointer high byte - JSR LAB_246C ; add (AY) to FAC1 - PLA ; restore FAC1 exponent - JSR LAB_2912 ; evaluate new ASCII digit - LDA #LAB_25B9 ; set LOG(2) pointer high byte - -; do convert AY, FCA1*(AY) - -LAB_25FB - JSR LAB_264D ; unpack memory (AY) into FAC2 -LAB_MULTIPLY - BEQ LAB_264C ; exit if zero - - JSR LAB_2673 ; test and adjust accumulators - LDA #$00 ; clear A - STA FACt_1 ; clear temp mantissa1 - STA FACt_2 ; clear temp mantissa2 - STA FACt_3 ; clear temp mantissa3 - LDA FAC1_r ; get FAC1 rounding byte - JSR LAB_2622 ; go do shift/add FAC2 - LDA FAC1_3 ; get FAC1 mantissa3 - JSR LAB_2622 ; go do shift/add FAC2 - LDA FAC1_2 ; get FAC1 mantissa2 - JSR LAB_2622 ; go do shift/add FAC2 - LDA FAC1_1 ; get FAC1 mantissa1 - JSR LAB_2627 ; go do shift/add FAC2 - JMP LAB_273C ; copy temp to FAC1, normalise and return - -LAB_2622 - BNE LAB_2627 ; branch if byte <> zero - - JMP LAB_2569 ; shift FCAtemp << A+8 times - - ; else do shift and add -LAB_2627 - LSR ; shift byte - ORA #$80 ; set top bit (mark for 8 times) -LAB_262A - TAY ; copy result - BCC LAB_2640 ; skip next if bit was zero - - CLC ; clear carry for add - LDA FACt_3 ; get temp mantissa3 - ADC FAC2_3 ; add FAC2 mantissa3 - STA FACt_3 ; save temp mantissa3 - LDA FACt_2 ; get temp mantissa2 - ADC FAC2_2 ; add FAC2 mantissa2 - STA FACt_2 ; save temp mantissa2 - LDA FACt_1 ; get temp mantissa1 - ADC FAC2_1 ; add FAC2 mantissa1 - STA FACt_1 ; save temp mantissa1 -LAB_2640 - ROR FACt_1 ; shift temp mantissa1 - ROR FACt_2 ; shift temp mantissa2 - ROR FACt_3 ; shift temp mantissa3 - ROR FAC1_r ; shift temp rounding byte - TYA ; get byte back - LSR ; shift byte - BNE LAB_262A ; loop if all bits not done - -LAB_264C - RTS - -; unpack memory (AY) into FAC2 - -LAB_264D - STA ut1_pl ; save pointer low byte - STY ut1_ph ; save pointer high byte - LDY #$03 ; 4 bytes to get (0-3) - LDA (ut1_pl),Y ; get mantissa3 - STA FAC2_3 ; save FAC2 mantissa3 - DEY ; decrement index - LDA (ut1_pl),Y ; get mantissa2 - STA FAC2_2 ; save FAC2 mantissa2 - DEY ; decrement index - LDA (ut1_pl),Y ; get mantissa1+sign - STA FAC2_s ; save FAC2 sign (b7) - EOR FAC1_s ; EOR with FAC1 sign (b7) - STA FAC_sc ; save sign compare (FAC1 EOR FAC2) - LDA FAC2_s ; recover FAC2 sign (b7) - ORA #$80 ; set 1xxx xxx (set normal bit) - STA FAC2_1 ; save FAC2 mantissa1 - DEY ; decrement index - LDA (ut1_pl),Y ; get exponent byte - STA FAC2_e ; save FAC2 exponent - LDA FAC1_e ; get FAC1 exponent - RTS - -; test and adjust accumulators - -LAB_2673 - LDA FAC2_e ; get FAC2 exponent -LAB_2675 - BEQ LAB_2696 ; branch if FAC2 = $00 (handle underflow) - - CLC ; clear carry for add - ADC FAC1_e ; add FAC1 exponent - BCC LAB_2680 ; branch if sum of exponents <$0100 - - BMI LAB_269B ; do overflow error - - CLC ; clear carry for the add - .byte $2C ; makes next line BIT $1410 -LAB_2680 - BPL LAB_2696 ; if +ve go handle underflow - - ADC #$80 ; adjust exponent - STA FAC1_e ; save FAC1 exponent - BNE LAB_268B ; branch if not zero - - JMP LAB_24F5 ; save FAC1 sign and return - -LAB_268B - LDA FAC_sc ; get sign compare (FAC1 EOR FAC2) - STA FAC1_s ; save FAC1 sign (b7) -LAB_268F - RTS - -; handle overflow and underflow - -LAB_2690 - LDA FAC1_s ; get FAC1 sign (b7) - BPL LAB_269B ; do overflow error - - ; handle underflow -LAB_2696 - PLA ; pop return address low byte - PLA ; pop return address high byte - JMP LAB_24F1 ; clear FAC1 exponent and sign and return - -; multiply by 10 - -LAB_269E - JSR LAB_27AB ; round and copy FAC1 to FAC2 - TAX ; copy exponent (set the flags) - BEQ LAB_268F ; exit if zero - - CLC ; clear carry for add - ADC #$02 ; add two to exponent (*4) - BCS LAB_269B ; do overflow error if > $FF - - LDX #$00 ; clear byte - STX FAC_sc ; clear sign compare (FAC1 EOR FAC2) - JSR LAB_247C ; add FAC2 to FAC1 (*5) - INC FAC1_e ; increment FAC1 exponent (*10) - BNE LAB_268F ; if non zero just do RTS - -LAB_269B - JMP LAB_2564 ; do overflow error and warm start - -; divide by 10 - -LAB_26B9 - JSR LAB_27AB ; round and copy FAC1 to FAC2 - LDA #LAB_26B5 ; set pointer to 10d high addr - LDX #$00 ; clear sign - -; divide by (AY) (X=sign) - -LAB_26C2 - STX FAC_sc ; save sign compare (FAC1 EOR FAC2) - JSR LAB_UFAC ; unpack memory (AY) into FAC1 - JMP LAB_DIVIDE ; do FAC2/FAC1 - - ; Perform divide-by -; convert AY and do (AY)/FAC1 - -LAB_26CA - JSR LAB_264D ; unpack memory (AY) into FAC2 - - ; Perform divide-into -LAB_DIVIDE - BEQ LAB_2737 ; if zero go do /0 error - - JSR LAB_27BA ; round FAC1 - LDA #$00 ; clear A - SEC ; set carry for subtract - SBC FAC1_e ; subtract FAC1 exponent (2s complement) - STA FAC1_e ; save FAC1 exponent - JSR LAB_2673 ; test and adjust accumulators - INC FAC1_e ; increment FAC1 exponent - BEQ LAB_269B ; if zero do overflow error - - LDX #$FF ; set index for pre increment - LDA #$01 ; set bit to flag byte save -LAB_26E4 - LDY FAC2_1 ; get FAC2 mantissa1 - CPY FAC1_1 ; compare FAC1 mantissa1 - BNE LAB_26F4 ; branch if <> - - LDY FAC2_2 ; get FAC2 mantissa2 - CPY FAC1_2 ; compare FAC1 mantissa2 - BNE LAB_26F4 ; branch if <> - - LDY FAC2_3 ; get FAC2 mantissa3 - CPY FAC1_3 ; compare FAC1 mantissa3 -LAB_26F4 - PHP ; save FAC2-FAC1 compare status - ROL ; shift the result byte - BCC LAB_2702 ; if no carry skip the byte save - - LDY #$01 ; set bit to flag byte save - INX ; else increment the index to FACt - CPX #$02 ; compare with the index to FACt_3 - BMI LAB_2701 ; if not last byte just go save it - - BNE LAB_272B ; if all done go save FAC1 rounding byte, normalise and - ; return - - LDY #$40 ; set bit to flag byte save for the rounding byte -LAB_2701 - STA FACt_1,X ; write result byte to FACt_1 + index - TYA ; copy the next save byte flag -LAB_2702 - PLP ; restore FAC2-FAC1 compare status - BCC LAB_2704 ; if FAC2 < FAC1 then skip the subtract - - TAY ; save FAC2-FAC1 compare status - LDA FAC2_3 ; get FAC2 mantissa3 - SBC FAC1_3 ; subtract FAC1 mantissa3 - STA FAC2_3 ; save FAC2 mantissa3 - LDA FAC2_2 ; get FAC2 mantissa2 - SBC FAC1_2 ; subtract FAC1 mantissa2 - STA FAC2_2 ; save FAC2 mantissa2 - LDA FAC2_1 ; get FAC2 mantissa1 - SBC FAC1_1 ; subtract FAC1 mantissa1 - STA FAC2_1 ; save FAC2 mantissa1 - TYA ; restore FAC2-FAC1 compare status - - ; FAC2 = FAC2*2 -LAB_2704 - ASL FAC2_3 ; shift FAC2 mantissa3 - ROL FAC2_2 ; shift FAC2 mantissa2 - ROL FAC2_1 ; shift FAC2 mantissa1 - BCS LAB_26F4 ; loop with no compare - - BMI LAB_26E4 ; loop with compare - - BPL LAB_26F4 ; loop always with no compare - -; do A<<6, save as FAC1 rounding byte, normalise and return - -LAB_272B - LSR ; shift b1 - b0 .. - ROR ; .. - ROR ; .. to b7 - b6 - STA FAC1_r ; save FAC1 rounding byte - PLP ; dump FAC2-FAC1 compare status - JMP LAB_273C ; copy temp to FAC1, normalise and return - -; do "Divide by zero" error - -LAB_2737 - LDX #$14 ; error code $14 ("Divide by zero" error) - JMP LAB_XERR ; do error #X, then warm start - -; copy temp to FAC1 and normalise - -LAB_273C - LDA FACt_1 ; get temp mantissa1 - STA FAC1_1 ; save FAC1 mantissa1 - LDA FACt_2 ; get temp mantissa2 - STA FAC1_2 ; save FAC1 mantissa2 - LDA FACt_3 ; get temp mantissa3 - STA FAC1_3 ; save FAC1 mantissa3 - JMP LAB_24D5 ; normalise FAC1 and return - -; unpack memory (AY) into FAC1 - -LAB_UFAC - STA ut1_pl ; save pointer low byte - STY ut1_ph ; save pointer high byte - LDY #$03 ; 4 bytes to do - LDA (ut1_pl),Y ; get last byte - STA FAC1_3 ; save FAC1 mantissa3 - DEY ; decrement index - LDA (ut1_pl),Y ; get last-1 byte - STA FAC1_2 ; save FAC1 mantissa2 - DEY ; decrement index - LDA (ut1_pl),Y ; get second byte - STA FAC1_s ; save FAC1 sign (b7) - ORA #$80 ; set 1xxx xxxx (add normal bit) - STA FAC1_1 ; save FAC1 mantissa1 - DEY ; decrement index - LDA (ut1_pl),Y ; get first byte (exponent) - STA FAC1_e ; save FAC1 exponent - STY FAC1_r ; clear FAC1 rounding byte - RTS - -; pack FAC1 into Adatal - -LAB_276E - LDX #Adatal ; set pointer high byte - BEQ LAB_2778 ; pack FAC1 into (XY) and return - -; pack FAC1 into (Lvarpl) - -LAB_PFAC - LDX Lvarpl ; get destination pointer low byte - LDY Lvarph ; get destination pointer high byte - -; pack FAC1 into (XY) - -LAB_2778 - JSR LAB_27BA ; round FAC1 - STX ut1_pl ; save pointer low byte - STY ut1_ph ; save pointer high byte - LDY #$03 ; set index - LDA FAC1_3 ; get FAC1 mantissa3 - STA (ut1_pl),Y ; store in destination - DEY ; decrement index - LDA FAC1_2 ; get FAC1 mantissa2 - STA (ut1_pl),Y ; store in destination - DEY ; decrement index - LDA FAC1_s ; get FAC1 sign (b7) - ORA #$7F ; set bits x111 1111 - AND FAC1_1 ; AND in FAC1 mantissa1 - STA (ut1_pl),Y ; store in destination - DEY ; decrement index - LDA FAC1_e ; get FAC1 exponent - STA (ut1_pl),Y ; store in destination - STY FAC1_r ; clear FAC1 rounding byte - RTS - -; round and copy FAC1 to FAC2 - -LAB_27AB - JSR LAB_27BA ; round FAC1 - -; copy FAC1 to FAC2 - -LAB_27AE - LDX #$05 ; 5 bytes to copy -LAB_27B0 - LDA FAC1_e-1,X ; get byte from FAC1,X - STA FAC1_o,X ; save byte at FAC2,X - DEX ; decrement count - BNE LAB_27B0 ; loop if not all done - - STX FAC1_r ; clear FAC1 rounding byte -LAB_27B9 - RTS - -; round FAC1 - -LAB_27BA - LDA FAC1_e ; get FAC1 exponent - BEQ LAB_27B9 ; exit if zero - - ASL FAC1_r ; shift FAC1 rounding byte - BCC LAB_27B9 ; exit if no overflow - -; round FAC1 (no check) - -LAB_27C2 - JSR LAB_2559 ; increment FAC1 mantissa - BNE LAB_27B9 ; branch if no overflow - - JMP LAB_252A ; normalise FAC1 for C=1 and return - -; get FAC1 sign -; return A=FF,C=1/-ve A=01,C=0/+ve - -LAB_27CA - LDA FAC1_e ; get FAC1 exponent - BEQ LAB_27D7 ; exit if zero (already correct SGN(0)=0) - -; return A=FF,C=1/-ve A=01,C=0/+ve -; no = 0 check - -LAB_27CE - LDA FAC1_s ; else get FAC1 sign (b7) - -; return A=FF,C=1/-ve A=01,C=0/+ve -; no = 0 check, sign in A - -LAB_27D0 - ROL ; move sign bit to carry - LDA #$FF ; set byte for -ve result - BCS LAB_27D7 ; return if sign was set (-ve) - - LDA #$01 ; else set byte for +ve result -LAB_27D7 - RTS - -; perform SGN() - -LAB_SGN - JSR LAB_27CA ; get FAC1 sign - ; return A=$FF/-ve A=$01/+ve -; save A as integer byte - -LAB_27DB - STA FAC1_1 ; save FAC1 mantissa1 - LDA #$00 ; clear A - STA FAC1_2 ; clear FAC1 mantissa2 - LDX #$88 ; set exponent - -; set exp=X, clearFAC1 mantissa3 and normalise - -LAB_27E3 - LDA FAC1_1 ; get FAC1 mantissa1 - EOR #$FF ; complement it - ROL ; sign bit into carry - -; set exp=X, clearFAC1 mantissa3 and normalise - -LAB_STFA - LDA #$00 ; clear A - STA FAC1_3 ; clear FAC1 mantissa3 - STX FAC1_e ; set FAC1 exponent - STA FAC1_r ; clear FAC1 rounding byte - STA FAC1_s ; clear FAC1 sign (b7) - JMP LAB_24D0 ; do ABS and normalise FAC1 - -; perform ABS() - -LAB_ABS - LSR FAC1_s ; clear FAC1 sign (put zero in b7) - RTS - -; compare FAC1 with (AY) -; returns A=$00 if FAC1 = (AY) -; returns A=$01 if FAC1 > (AY) -; returns A=$FF if FAC1 < (AY) - -LAB_27F8 - STA ut2_pl ; save pointer low byte -LAB_27FA - STY ut2_ph ; save pointer high byte - LDY #$00 ; clear index - LDA (ut2_pl),Y ; get exponent - INY ; increment index - TAX ; copy (AY) exponent to X - BEQ LAB_27CA ; branch if (AY) exponent=0 and get FAC1 sign - ; A=FF,C=1/-ve A=01,C=0/+ve - - LDA (ut2_pl),Y ; get (AY) mantissa1 (with sign) - EOR FAC1_s ; EOR FAC1 sign (b7) - BMI LAB_27CE ; if signs <> do return A=FF,C=1/-ve - ; A=01,C=0/+ve and return - - CPX FAC1_e ; compare (AY) exponent with FAC1 exponent - BNE LAB_2828 ; branch if different - - LDA (ut2_pl),Y ; get (AY) mantissa1 (with sign) - ORA #$80 ; normalise top bit - CMP FAC1_1 ; compare with FAC1 mantissa1 - BNE LAB_2828 ; branch if different - - INY ; increment index - LDA (ut2_pl),Y ; get mantissa2 - CMP FAC1_2 ; compare with FAC1 mantissa2 - BNE LAB_2828 ; branch if different - - INY ; increment index - LDA #$7F ; set for 1/2 value rounding byte - CMP FAC1_r ; compare with FAC1 rounding byte (set carry) - LDA (ut2_pl),Y ; get mantissa3 - SBC FAC1_3 ; subtract FAC1 mantissa3 - BEQ LAB_2850 ; exit if mantissa3 equal - -; gets here if number <> FAC1 - -LAB_2828 - LDA FAC1_s ; get FAC1 sign (b7) - BCC LAB_282E ; branch if FAC1 > (AY) - - EOR #$FF ; else toggle FAC1 sign -LAB_282E - JMP LAB_27D0 ; return A=FF,C=1/-ve A=01,C=0/+ve - -; convert FAC1 floating-to-fixed - -LAB_2831 - LDA FAC1_e ; get FAC1 exponent - BEQ LAB_287F ; if zero go clear FAC1 and return - - SEC ; set carry for subtract - SBC #$98 ; subtract maximum integer range exponent - BIT FAC1_s ; test FAC1 sign (b7) - BPL LAB_2845 ; branch if FAC1 +ve - - ; FAC1 was -ve - TAX ; copy subtracted exponent - LDA #$FF ; overflow for -ve number - STA FAC1_o ; set FAC1 overflow byte - JSR LAB_253D ; twos complement FAC1 mantissa - TXA ; restore subtracted exponent -LAB_2845 - LDX #FAC1_e ; set index to FAC1 - CMP #$F9 ; compare exponent result - BPL LAB_2851 ; if < 8 shifts shift FAC1 A times right and return - - JSR LAB_257B ; shift FAC1 A times right (> 8 shifts) - STY FAC1_o ; clear FAC1 overflow byte -LAB_2850 - RTS - -; shift FAC1 A times right - -LAB_2851 - TAY ; copy shift count - LDA FAC1_s ; get FAC1 sign (b7) - AND #$80 ; mask sign bit only (x000 0000) - LSR FAC1_1 ; shift FAC1 mantissa1 - ORA FAC1_1 ; OR sign in b7 FAC1 mantissa1 - STA FAC1_1 ; save FAC1 mantissa1 - JSR LAB_2592 ; shift FAC1 Y times right - STY FAC1_o ; clear FAC1 overflow byte - RTS - -; perform INT() - -LAB_INT - LDA FAC1_e ; get FAC1 exponent - CMP #$98 ; compare with max int - BCS LAB_2886 ; exit if >= (already int, too big for fractional part!) - - JSR LAB_2831 ; convert FAC1 floating-to-fixed - STY FAC1_r ; save FAC1 rounding byte - LDA FAC1_s ; get FAC1 sign (b7) - STY FAC1_s ; save FAC1 sign (b7) - EOR #$80 ; toggle FAC1 sign - ROL ; shift into carry - LDA #$98 ; set new exponent - STA FAC1_e ; save FAC1 exponent - LDA FAC1_3 ; get FAC1 mantissa3 - STA Temp3 ; save for EXP() function - JMP LAB_24D0 ; do ABS and normalise FAC1 - -; clear FAC1 and return - -LAB_287F - STA FAC1_1 ; clear FAC1 mantissa1 - STA FAC1_2 ; clear FAC1 mantissa2 - STA FAC1_3 ; clear FAC1 mantissa3 - TAY ; clear Y -LAB_2886 - RTS - -; get FAC1 from string -; this routine now handles hex and binary values from strings -; starting with "$" and "%" respectively - -LAB_2887 - LDY #$00 ; clear Y - STY Dtypef ; clear data type flag, $FF=string, $00=numeric - LDX #$09 ; set index -LAB_288B - STY numexp,X ; clear byte - DEX ; decrement index - BPL LAB_288B ; loop until numexp to negnum (and FAC1) = $00 - - BCC LAB_28FE ; branch if 1st character numeric - -; get FAC1 from string .. first character wasn't numeric - - CMP #'-' ; else compare with "-" - BNE LAB_289A ; branch if not "-" - - STX negnum ; set flag for -ve number (X = $FF) - BEQ LAB_289C ; branch always (go scan and check for hex/bin) - -; get FAC1 from string .. first character wasn't numeric or - - -LAB_289A - CMP #'+' ; else compare with "+" - BNE LAB_289D ; branch if not "+" (go check for hex/bin) - -; was "+" or "-" to start, so get next character - -LAB_289C - JSR LAB_IGBY ; increment and scan memory - BCC LAB_28FE ; branch if numeric character - -; code here for hex and binary numbers - -LAB_289D - CMP #'$' ; else compare with "$" - BNE LAB_NHEX ; branch if not "$" - - JMP LAB_CHEX ; branch if "$" - -LAB_NHEX - CMP #'%' ; else compare with "%" - BNE LAB_28A3 ; branch if not "%" (continue original code) - - JMP LAB_CBIN ; branch if "%" - -LAB_289E - JSR LAB_IGBY ; increment and scan memory (ignore + or get next number) -LAB_28A1 - BCC LAB_28FE ; branch if numeric character - -; get FAC1 from string .. character wasn't numeric, -, +, hex or binary - -LAB_28A3 - CMP #'.' ; else compare with "." - BEQ LAB_28D5 ; branch if "." - -; get FAC1 from string .. character wasn't numeric, -, + or . - - CMP #'E' ; else compare with "E" - BNE LAB_28DB ; branch if not "E" - - ; was "E" so evaluate exponential part - JSR LAB_IGBY ; increment and scan memory - BCC LAB_28C7 ; branch if numeric character - - CMP #TK_MINUS ; else compare with token for - - BEQ LAB_28C2 ; branch if token for - - - CMP #'-' ; else compare with "-" - BEQ LAB_28C2 ; branch if "-" - - CMP #TK_PLUS ; else compare with token for + - BEQ LAB_28C4 ; branch if token for + - - CMP #'+' ; else compare with "+" - BEQ LAB_28C4 ; branch if "+" - - BNE LAB_28C9 ; branch always - -LAB_28C2 - ROR expneg ; set exponent -ve flag (C, which=1, into b7) -LAB_28C4 - JSR LAB_IGBY ; increment and scan memory -LAB_28C7 - BCC LAB_2925 ; branch if numeric character - -LAB_28C9 - BIT expneg ; test exponent -ve flag - BPL LAB_28DB ; if +ve go evaluate exponent - - ; else do exponent = -exponent - LDA #$00 ; clear result - SEC ; set carry for subtract - SBC expcnt ; subtract exponent byte - JMP LAB_28DD ; go evaluate exponent - -LAB_28D5 - ROR numdpf ; set decimal point flag - BIT numdpf ; test decimal point flag - BVC LAB_289E ; branch if only one decimal point so far - - ; evaluate exponent -LAB_28DB - LDA expcnt ; get exponent count byte -LAB_28DD - SEC ; set carry for subtract - SBC numexp ; subtract numerator exponent - STA expcnt ; save exponent count byte - BEQ LAB_28F6 ; branch if no adjustment - - BPL LAB_28EF ; else if +ve go do FAC1*10^expcnt - - ; else go do FAC1/10^(0-expcnt) -LAB_28E6 - JSR LAB_26B9 ; divide by 10 - INC expcnt ; increment exponent count byte - BNE LAB_28E6 ; loop until all done - - BEQ LAB_28F6 ; branch always - -LAB_28EF - JSR LAB_269E ; multiply by 10 - DEC expcnt ; decrement exponent count byte - BNE LAB_28EF ; loop until all done - -LAB_28F6 - LDA negnum ; get -ve flag - BMI LAB_28FB ; if -ve do - FAC1 and return - - RTS - -; do - FAC1 and return - -LAB_28FB - JMP LAB_GTHAN ; do - FAC1 and return - -; do unsigned FAC1*10+number - -LAB_28FE - PHA ; save character - BIT numdpf ; test decimal point flag - BPL LAB_2905 ; skip exponent increment if not set - - INC numexp ; else increment number exponent -LAB_2905 - JSR LAB_269E ; multiply FAC1 by 10 - PLA ; restore character - AND #$0F ; convert to binary - JSR LAB_2912 ; evaluate new ASCII digit - JMP LAB_289E ; go do next character - -; evaluate new ASCII digit - -LAB_2912 - PHA ; save digit - JSR LAB_27AB ; round and copy FAC1 to FAC2 - PLA ; restore digit - JSR LAB_27DB ; save A as integer byte - LDA FAC2_s ; get FAC2 sign (b7) - EOR FAC1_s ; toggle with FAC1 sign (b7) - STA FAC_sc ; save sign compare (FAC1 EOR FAC2) - LDX FAC1_e ; get FAC1 exponent - JMP LAB_ADD ; add FAC2 to FAC1 and return - -; evaluate next character of exponential part of number - -LAB_2925 - LDA expcnt ; get exponent count byte - CMP #$0A ; compare with 10 decimal - BCC LAB_2934 ; branch if less - - LDA #$64 ; make all -ve exponents = -100 decimal (causes underflow) - BIT expneg ; test exponent -ve flag - BMI LAB_2942 ; branch if -ve - - JMP LAB_2564 ; else do overflow error - -LAB_2934 - ASL ; * 2 - ASL ; * 4 - ADC expcnt ; * 5 - ASL ; * 10 - LDY #$00 ; set index - ADC (Bpntrl),Y ; add character (will be $30 too much!) - SBC #'0'-1 ; convert character to binary -LAB_2942 - STA expcnt ; save exponent count byte - JMP LAB_28C4 ; go get next character - -; print " in line [LINE #]" - -LAB_2953 - LDA #LAB_LMSG ; point to " in line " message high byte - JSR LAB_18C3 ; print null terminated string from memory - - ; print Basic line # - LDA Clineh ; get current line high byte - LDX Clinel ; get current line low byte - -; print XA as unsigned integer - -LAB_295E - STA FAC1_1 ; save low byte as FAC1 mantissa1 - STX FAC1_2 ; save high byte as FAC1 mantissa2 - LDX #$90 ; set exponent to 16d bits - SEC ; set integer is +ve flag - JSR LAB_STFA ; set exp=X, clearFAC1 mantissa3 and normalise - LDY #$00 ; clear index - TYA ; clear A - JSR LAB_297B ; convert FAC1 to string, skip sign character save - JMP LAB_18C3 ; print null terminated string from memory and return - -; convert FAC1 to ASCII string result in (AY) -; not any more, moved scratchpad to page 0 - -LAB_296E - LDY #$01 ; set index = 1 - LDA #$20 ; character = " " (assume +ve) - BIT FAC1_s ; test FAC1 sign (b7) - BPL LAB_2978 ; branch if +ve - - LDA #$2D ; else character = "-" -LAB_2978 - STA Decss,Y ; save leading character (" " or "-") -LAB_297B - STA FAC1_s ; clear FAC1 sign (b7) - STY Sendl ; save index - INY ; increment index - LDX FAC1_e ; get FAC1 exponent - BNE LAB_2989 ; branch if FAC1<>0 - - ; exponent was $00 so FAC1 is 0 - LDA #'0' ; set character = "0" - JMP LAB_2A89 ; save last character, [EOT] and exit - - ; FAC1 is some non zero value -LAB_2989 - LDA #$00 ; clear (number exponent count) - CPX #$81 ; compare FAC1 exponent with $81 (>1.00000) - - BCS LAB_299A ; branch if FAC1=>1 - - ; FAC1<1 - LDA #LAB_294F ; set pointer high byte to 1,000,000 - JSR LAB_25FB ; do convert AY, FCA1*(AY) - LDA #$FA ; set number exponent count (-6) -LAB_299A - STA numexp ; save number exponent count -LAB_299C - LDA #LAB_294B ; set pointer high byte to 999999.4375 - JSR LAB_27F8 ; compare FAC1 with (AY) - BEQ LAB_29C3 ; exit if FAC1 = (AY) - - BPL LAB_29B9 ; go do /10 if FAC1 > (AY) - - ; FAC1 < (AY) -LAB_29A7 - LDA #LAB_2947 ; set pointer high byte to 99999.9375 - JSR LAB_27F8 ; compare FAC1 with (AY) - BEQ LAB_29B2 ; branch if FAC1 = (AY) (allow decimal places) - - BPL LAB_29C0 ; branch if FAC1 > (AY) (no decimal places) - - ; FAC1 <= (AY) -LAB_29B2 - JSR LAB_269E ; multiply by 10 - DEC numexp ; decrement number exponent count - BNE LAB_29A7 ; go test again (branch always) - -LAB_29B9 - JSR LAB_26B9 ; divide by 10 - INC numexp ; increment number exponent count - BNE LAB_299C ; go test again (branch always) - -; now we have just the digits to do - -LAB_29C0 - JSR LAB_244E ; add 0.5 to FAC1 (round FAC1) -LAB_29C3 - JSR LAB_2831 ; convert FAC1 floating-to-fixed - LDX #$01 ; set default digits before dp = 1 - LDA numexp ; get number exponent count - CLC ; clear carry for add - ADC #$07 ; up to 6 digits before point - BMI LAB_29D8 ; if -ve then 1 digit before dp - - CMP #$08 ; A>=8 if n>=1E6 - BCS LAB_29D9 ; branch if >= $08 - - ; carry is clear - ADC #$FF ; take 1 from digit count - TAX ; copy to A - LDA #$02 ;.set exponent adjust -LAB_29D8 - SEC ; set carry for subtract -LAB_29D9 - SBC #$02 ; -2 - STA expcnt ;.save exponent adjust - STX numexp ; save digits before dp count - TXA ; copy to A - BEQ LAB_29E4 ; branch if no digits before dp - - BPL LAB_29F7 ; branch if digits before dp - -LAB_29E4 - LDY Sendl ; get output string index - LDA #$2E ; character "." - INY ; increment index - STA Decss,Y ; save to output string - TXA ;. - BEQ LAB_29F5 ;. - - LDA #'0' ; character "0" - INY ; increment index - STA Decss,Y ; save to output string -LAB_29F5 - STY Sendl ; save output string index -LAB_29F7 - LDY #$00 ; clear index (point to 100,000) - LDX #$80 ; -LAB_29FB - LDA FAC1_3 ; get FAC1 mantissa3 - CLC ; clear carry for add - ADC LAB_2A9C,Y ; add -ve LSB - STA FAC1_3 ; save FAC1 mantissa3 - LDA FAC1_2 ; get FAC1 mantissa2 - ADC LAB_2A9B,Y ; add -ve NMSB - STA FAC1_2 ; save FAC1 mantissa2 - LDA FAC1_1 ; get FAC1 mantissa1 - ADC LAB_2A9A,Y ; add -ve MSB - STA FAC1_1 ; save FAC1 mantissa1 - INX ; - BCS LAB_2A18 ; - - BPL LAB_29FB ; not -ve so try again - - BMI LAB_2A1A ; - -LAB_2A18 - BMI LAB_29FB ; - -LAB_2A1A - TXA ; - BCC LAB_2A21 ; - - EOR #$FF ; - ADC #$0A ; -LAB_2A21 - ADC #'0'-1 ; add "0"-1 to result - INY ; increment index .. - INY ; .. to next less .. - INY ; .. power of ten - STY Cvaral ; save as current var address low byte - LDY Sendl ; get output string index - INY ; increment output string index - TAX ; copy character to X - AND #$7F ; mask out top bit - STA Decss,Y ; save to output string - DEC numexp ; decrement # of characters before the dp - BNE LAB_2A3B ; branch if still characters to do - - ; else output the point - LDA #$2E ; character "." - INY ; increment output string index - STA Decss,Y ; save to output string -LAB_2A3B - STY Sendl ; save output string index - LDY Cvaral ; get current var address low byte - TXA ; get character back - EOR #$FF ; - AND #$80 ; - TAX ; - CPY #$12 ; compare index with max - BNE LAB_29FB ; loop if not max - - ; now remove trailing zeroes - LDY Sendl ; get output string index -LAB_2A4B - LDA Decss,Y ; get character from output string - DEY ; decrement output string index - CMP #'0' ; compare with "0" - BEQ LAB_2A4B ; loop until non "0" character found - - CMP #'.' ; compare with "." - BEQ LAB_2A58 ; branch if was dp - - ; restore last character - INY ; increment output string index -LAB_2A58 - LDA #$2B ; character "+" - LDX expcnt ; get exponent count - BEQ LAB_2A8C ; if zero go set null terminator and exit - - ; exponent isn't zero so write exponent - BPL LAB_2A68 ; branch if exponent count +ve - - LDA #$00 ; clear A - SEC ; set carry for subtract - SBC expcnt ; subtract exponent count adjust (convert -ve to +ve) - TAX ; copy exponent count to X - LDA #'-' ; character "-" -LAB_2A68 - STA Decss+2,Y ; save to output string - LDA #$45 ; character "E" - STA Decss+1,Y ; save exponent sign to output string - TXA ; get exponent count back - LDX #'0'-1 ; one less than "0" character - SEC ; set carry for subtract -LAB_2A74 - INX ; increment 10's character - SBC #$0A ;.subtract 10 from exponent count - BCS LAB_2A74 ; loop while still >= 0 - - ADC #':' ; add character ":" ($30+$0A, result is 10 less that value) - STA Decss+4,Y ; save to output string - TXA ; copy 10's character - STA Decss+3,Y ; save to output string - LDA #$00 ; set null terminator - STA Decss+5,Y ; save to output string - BEQ LAB_2A91 ; go set string pointer (AY) and exit (branch always) - - ; save last character, [EOT] and exit -LAB_2A89 - STA Decss,Y ; save last character to output string - - ; set null terminator and exit -LAB_2A8C - LDA #$00 ; set null terminator - STA Decss+1,Y ; save after last character - - ; set string pointer (AY) and exit -LAB_2A91 - LDA #Decssp1 ; set result string high pointer - RTS - -; perform power function - -LAB_POWER - BEQ LAB_EXP ; go do EXP() - - LDA FAC2_e ; get FAC2 exponent - BNE LAB_2ABF ; branch if FAC2<>0 - - JMP LAB_24F3 ; clear FAC1 exponent and sign and return - -LAB_2ABF - LDX #func_l ; set destination pointer high byte - JSR LAB_2778 ; pack FAC1 into (XY) - LDA FAC2_s ; get FAC2 sign (b7) - BPL LAB_2AD9 ; branch if FAC2>0 - - ; else FAC2 is -ve and can only be raised to an - ; integer power which gives an x +j0 result - JSR LAB_INT ; perform INT - LDA #func_l ; set source pointer high byte - JSR LAB_27F8 ; compare FAC1 with (AY) - BNE LAB_2AD9 ; branch if FAC1 <> (AY) to allow Function Call error - ; this will leave FAC1 -ve and cause a Function Call - ; error when LOG() is called - - TYA ; clear sign b7 - LDY Temp3 ; save mantissa 3 from INT() function as sign in Y - ; for possible later negation, b0 -LAB_2AD9 - JSR LAB_279D ; save FAC1 sign and copy ABS(FAC2) to FAC1 - TYA ; copy sign back .. - PHA ; .. and save it - JSR LAB_LOG ; do LOG(n) - LDA #garb_l ; set pointer high byte - JSR LAB_25FB ; do convert AY, FCA1*(AY) (square the value) - JSR LAB_EXP ; go do EXP(n) - PLA ; pull sign from stack - LSR ; b0 is to be tested, shift to Cb - BCC LAB_2AF9 ; if no bit then exit - - ; Perform negation -; do - FAC1 - -LAB_GTHAN - LDA FAC1_e ; get FAC1 exponent - BEQ LAB_2AF9 ; exit if FAC1_e = $00 - - LDA FAC1_s ; get FAC1 sign (b7) - EOR #$FF ; complement it - STA FAC1_s ; save FAC1 sign (b7) -LAB_2AF9 - RTS - -; perform EXP() (x^e) - -LAB_EXP - LDA #LAB_2AFA ; set 1.443 pointer high byte - JSR LAB_25FB ; do convert AY, FCA1*(AY) - LDA FAC1_r ; get FAC1 rounding byte - ADC #$50 ; +$50/$100 - BCC LAB_2B2B ; skip rounding if no carry - - JSR LAB_27C2 ; round FAC1 (no check) -LAB_2B2B - STA FAC2_r ; save FAC2 rounding byte - JSR LAB_27AE ; copy FAC1 to FAC2 - LDA FAC1_e ; get FAC1 exponent - CMP #$88 ; compare with EXP limit (256d) - BCC LAB_2B39 ; branch if less - -LAB_2B36 - JSR LAB_2690 ; handle overflow and underflow -LAB_2B39 - JSR LAB_INT ; perform INT - LDA Temp3 ; get mantissa 3 from INT() function - CLC ; clear carry for add - ADC #$81 ; normalise +1 - BEQ LAB_2B36 ; if $00 go handle overflow - - SEC ; set carry for subtract - SBC #$01 ; now correct for exponent - PHA ; save FAC2 exponent - - ; swap FAC1 and FAC2 - LDX #$04 ; 4 bytes to do -LAB_2B49 - LDA FAC2_e,X ; get FAC2,X - LDY FAC1_e,X ; get FAC1,X - STA FAC1_e,X ; save FAC1,X - STY FAC2_e,X ; save FAC2,X - DEX ; decrement count/index - BPL LAB_2B49 ; loop if not all done - - LDA FAC2_r ; get FAC2 rounding byte - STA FAC1_r ; save as FAC1 rounding byte - JSR LAB_SUBTRACT ; perform subtraction, FAC2 from FAC1 - JSR LAB_GTHAN ; do - FAC1 - LDA #LAB_2AFE ; set counter pointer high byte - JSR LAB_2B84 ; go do series evaluation - LDA #$00 ; clear A - STA FAC_sc ; clear sign compare (FAC1 EOR FAC2) - PLA ;.get saved FAC2 exponent - JMP LAB_2675 ; test and adjust accumulators and return - -; ^2 then series evaluation - -LAB_2B6E - STA Cptrl ; save count pointer low byte - STY Cptrh ; save count pointer high byte - JSR LAB_276E ; pack FAC1 into Adatal - LDA #Adatal ; pointer to original # high byte - JMP LAB_25FB ; do convert AY, FCA1*(AY) and return - -; series evaluation - -LAB_2B84 - STA Cptrl ; save count pointer low byte - STY Cptrh ; save count pointer high byte -LAB_2B88 - LDX #numexp ; set pointer high byte to partial @ numexp - DEC numcon ; decrement constants count - BNE LAB_2B9B ; loop until all done - - RTS - -; RND(n), 32 bit Galoise version. make n=0 for 19th next number in sequence or n<>0 -; to get 19th next number in sequence after seed n. This version of the PRNG uses -; the Galois method and a sample of 65536 bytes produced gives the following values. - -; Entropy = 7.997442 bits per byte -; Optimum compression would reduce these 65536 bytes by 0 percent - -; Chi square distribution for 65536 samples is 232.01, and -; randomly would exceed this value 75.00 percent of the time - -; Arithmetic mean value of data bytes is 127.6724, 127.5 would be random -; Monte Carlo value for Pi is 3.122871269, error 0.60 percent -; Serial correlation coefficient is -0.000370, totally uncorrelated would be 0.0 - -LAB_RND - LDA FAC1_e ; get FAC1 exponent - BEQ NextPRN ; do next random # if zero - - ; else get seed into random number store - LDX #Rbyte4 ; set PRNG pointer low byte - LDY #$00 ; set PRNG pointer high byte - JSR LAB_2778 ; pack FAC1 into (XY) -NextPRN - LDX #$AF ; set EOR byte - LDY #$13 ; do this nineteen times -LoopPRN - ASL Rbyte1 ; shift PRNG most significant byte - ROL Rbyte2 ; shift PRNG middle byte - ROL Rbyte3 ; shift PRNG least significant byte - ROL Rbyte4 ; shift PRNG extra byte - BCC Ninc1 ; branch if bit 32 clear - - TXA ; set EOR byte - EOR Rbyte1 ; EOR PRNG extra byte - STA Rbyte1 ; save new PRNG extra byte -Ninc1 - DEY ; decrement loop count - BNE LoopPRN ; loop if not all done - - LDX #$02 ; three bytes to copy -CopyPRNG - LDA Rbyte1,X ; get PRNG byte - STA FAC1_1,X ; save FAC1 byte - DEX - BPL CopyPRNG ; loop if not complete - - LDA #$80 ; set the exponent - STA FAC1_e ; save FAC1 exponent - - ASL ; clear A - STA FAC1_s ; save FAC1 sign - - JMP LAB_24D5 ; normalise FAC1 and return - -; perform COS() - -LAB_COS - LDA #LAB_2C78 ; set (pi/2) pointer high byte - JSR LAB_246C ; add (AY) to FAC1 - -; perform SIN() - -LAB_SIN - JSR LAB_27AB ; round and copy FAC1 to FAC2 - LDA #LAB_2C7C ; set (2*pi) pointer high byte - LDX FAC2_s ; get FAC2 sign (b7) - JSR LAB_26C2 ; divide by (AY) (X=sign) - JSR LAB_27AB ; round and copy FAC1 to FAC2 - JSR LAB_INT ; perform INT - LDA #$00 ; clear byte - STA FAC_sc ; clear sign compare (FAC1 EOR FAC2) - JSR LAB_SUBTRACT ; perform subtraction, FAC2 from FAC1 - LDA #LAB_2C80 ; set 0.25 pointer high byte - JSR LAB_2455 ; perform subtraction, (AY) from FAC1 - LDA FAC1_s ; get FAC1 sign (b7) - PHA ; save FAC1 sign - BPL LAB_2C35 ; branch if +ve - - ; FAC1 sign was -ve - JSR LAB_244E ; add 0.5 to FAC1 - LDA FAC1_s ; get FAC1 sign (b7) - BMI LAB_2C38 ; branch if -ve - - LDA Cflag ; get comparison evaluation flag - EOR #$FF ; toggle flag - STA Cflag ; save comparison evaluation flag -LAB_2C35 - JSR LAB_GTHAN ; do - FAC1 -LAB_2C38 - LDA #LAB_2C80 ; set 0.25 pointer high byte - JSR LAB_246C ; add (AY) to FAC1 - PLA ; restore FAC1 sign - BPL LAB_2C45 ; branch if was +ve - - ; else correct FAC1 - JSR LAB_GTHAN ; do - FAC1 -LAB_2C45 - LDA #LAB_2C84 ; set pointer high byte to counter - JMP LAB_2B6E ; ^2 then series evaluation and return - -; perform TAN() - -LAB_TAN - JSR LAB_276E ; pack FAC1 into Adatal - LDA #$00 ; clear byte - STA Cflag ; clear comparison evaluation flag - JSR LAB_SIN ; go do SIN(n) - LDX #func_l ; set sin(n) pointer high byte - JSR LAB_2778 ; pack FAC1 into (XY) - LDA #Adatal ; set n pointer high addr - JSR LAB_UFAC ; unpack memory (AY) into FAC1 - LDA #$00 ; clear byte - STA FAC1_s ; clear FAC1 sign (b7) - LDA Cflag ; get comparison evaluation flag - JSR LAB_2C74 ; save flag and go do series evaluation - - LDA #func_l ; set sin(n) pointer high byte - JMP LAB_26CA ; convert AY and do (AY)/FAC1 - -LAB_2C74 - PHA ; save comparison evaluation flag - JMP LAB_2C35 ; go do series evaluation - -; perform USR() - -LAB_USR - JSR Usrjmp ; call user code - JMP LAB_1BFB ; scan for ")", else do syntax error then warm start - -; perform ATN() - -LAB_ATN - LDA FAC1_s ; get FAC1 sign (b7) - PHA ; save sign - BPL LAB_2CA1 ; branch if +ve - - JSR LAB_GTHAN ; else do - FAC1 -LAB_2CA1 - LDA FAC1_e ; get FAC1 exponent - PHA ; push exponent - CMP #$81 ; compare with 1 - BCC LAB_2CAF ; branch if FAC1<1 - - LDA #LAB_259C ; set 1 pointer high byte - JSR LAB_26CA ; convert AY and do (AY)/FAC1 -LAB_2CAF - LDA #LAB_2CC9 ; set pointer high byte to counter - JSR LAB_2B6E ; ^2 then series evaluation - PLA ; restore old FAC1 exponent - CMP #$81 ; compare with 1 - BCC LAB_2CC2 ; branch if FAC1<1 - - LDA #LAB_2C78 ; set (pi/2) pointer high byte - JSR LAB_2455 ; perform subtraction, (AY) from FAC1 -LAB_2CC2 - PLA ; restore FAC1 sign - BPL LAB_2D04 ; exit if was +ve - - JMP LAB_GTHAN ; else do - FAC1 and return - -; perform BITSET - -LAB_BITSET - JSR LAB_GADB ; get two parameters for POKE or WAIT - CPX #$08 ; only 0 to 7 are allowed - BCS FCError ; branch if > 7 - - LDA #$00 ; clear A - SEC ; set the carry -S_Bits - ROL ; shift bit - DEX ; decrement bit number - BPL S_Bits ; loop if still +ve - - INX ; make X = $00 - ORA (Itempl,X) ; or with byte via temporary integer (addr) - STA (Itempl,X) ; save byte via temporary integer (addr) -LAB_2D04 - RTS - -; perform BITCLR - -LAB_BITCLR - JSR LAB_GADB ; get two parameters for POKE or WAIT - CPX #$08 ; only 0 to 7 are allowed - BCS FCError ; branch if > 7 - - LDA #$FF ; set A -S_Bitc - ROL ; shift bit - DEX ; decrement bit number - BPL S_Bitc ; loop if still +ve - - INX ; make X = $00 - AND (Itempl,X) ; and with byte via temporary integer (addr) - STA (Itempl,X) ; save byte via temporary integer (addr) - RTS - -FCError - JMP LAB_FCER ; do function call error then warm start - -; perform BITTST() - -LAB_BTST - JSR LAB_IGBY ; increment BASIC pointer - JSR LAB_GADB ; get two parameters for POKE or WAIT - CPX #$08 ; only 0 to 7 are allowed - BCS FCError ; branch if > 7 - - JSR LAB_GBYT ; get next BASIC byte - CMP #')' ; is next character ")" - BEQ TST_OK ; if ")" go do rest of function - - JMP LAB_SNER ; do syntax error then warm start - -TST_OK - JSR LAB_IGBY ; update BASIC execute pointer (to character past ")") - LDA #$00 ; clear A - SEC ; set the carry -T_Bits - ROL ; shift bit - DEX ; decrement bit number - BPL T_Bits ; loop if still +ve - - INX ; make X = $00 - AND (Itempl,X) ; AND with byte via temporary integer (addr) - BEQ LAB_NOTT ; branch if zero (already correct) - - LDA #$FF ; set for -1 result -LAB_NOTT - JMP LAB_27DB ; go do SGN tail - -; perform BIN$() - -LAB_BINS - CPX #$19 ; max + 1 - BCS BinFErr ; exit if too big ( > or = ) - - STX TempB ; save # of characters ($00 = leading zero remove) - LDA #$18 ; need A byte long space - JSR LAB_MSSP ; make string space A bytes long - LDY #$17 ; set index - LDX #$18 ; character count -NextB1 - LSR nums_1 ; shift highest byte - ROR nums_2 ; shift middle byte - ROR nums_3 ; shift lowest byte bit 0 to carry - TXA ; load with "0"/2 - ROL ; shift in carry - STA (str_pl),Y ; save to temp string + index - DEY ; decrement index - BPL NextB1 ; loop if not done - - LDA TempB ; get # of characters - BEQ EndBHS ; branch if truncate - - TAX ; copy length to X - SEC ; set carry for add ! - EOR #$FF ; 1's complement - ADC #$18 ; add 24d - BEQ GoPr2 ; if zero print whole string - - BNE GoPr1 ; else go make output string - -; this is the exit code and is also used by HEX$() -; truncate string to remove leading "0"s - -EndBHS - TAY ; clear index (A=0, X=length here) -NextB2 - LDA (str_pl),Y ; get character from string - CMP #'0' ; compare with "0" - BNE GoPr ; if not "0" then go print string from here - - DEX ; decrement character count - BEQ GoPr3 ; if zero then end of string so go print it - - INY ; else increment index - BPL NextB2 ; loop always - -; make fixed length output string - ignore overflows! - -GoPr3 - INX ; need at least 1 character -GoPr - TYA ; copy result -GoPr1 - CLC ; clear carry for add - ADC str_pl ; add low address - STA str_pl ; save low address - LDA #$00 ; do high byte - ADC str_ph ; add high address - STA str_ph ; save high address -GoPr2 - STX str_ln ; X holds string length - JSR LAB_IGBY ; update BASIC execute pointer (to character past ")") - JMP LAB_RTST ; check for space on descriptor stack then put address - ; and length on descriptor stack and update stack pointers - -BinFErr - JMP LAB_FCER ; do function call error then warm start - -; perform HEX$() - -LAB_HEXS - CPX #$07 ; max + 1 - BCS BinFErr ; exit if too big ( > or = ) - - STX TempB ; save # of characters - - LDA #$06 ; need 6 bytes for string - JSR LAB_MSSP ; make string space A bytes long - LDY #$05 ; set string index - - SED ; need decimal mode for nibble convert - LDA nums_3 ; get lowest byte - JSR LAB_A2HX ; convert A to ASCII hex byte and output - LDA nums_2 ; get middle byte - JSR LAB_A2HX ; convert A to ASCII hex byte and output - LDA nums_1 ; get highest byte - JSR LAB_A2HX ; convert A to ASCII hex byte and output - CLD ; back to binary - - LDX #$06 ; character count - LDA TempB ; get # of characters - BEQ EndBHS ; branch if truncate - - TAX ; copy length to X - SEC ; set carry for add ! - EOR #$FF ; 1's complement - ADC #$06 ; add 6d - BEQ GoPr2 ; if zero print whole string - - BNE GoPr1 ; else go make output string (branch always) - -; convert A to ASCII hex byte and output .. note set decimal mode before calling - -LAB_A2HX - TAX ; save byte - AND #$0F ; mask off top bits - JSR LAB_AL2X ; convert low nibble to ASCII and output - TXA ; get byte back - LSR ; /2 shift high nibble to low nibble - LSR ; /4 - LSR ; /8 - LSR ; /16 -LAB_AL2X - CMP #$0A ; set carry for +1 if >9 - ADC #'0' ; add ASCII "0" - STA (str_pl),Y ; save to temp string - DEY ; decrement counter - RTS - -LAB_NLTO - STA FAC1_e ; save FAC1 exponent - LDA #$00 ; clear sign compare -LAB_MLTE - STA FAC_sc ; save sign compare (FAC1 EOR FAC2) - TXA ; restore character - JSR LAB_2912 ; evaluate new ASCII digit - -; gets here if the first character was "$" for hex -; get hex number - -LAB_CHEX - JSR LAB_IGBY ; increment and scan memory - BCC LAB_ISHN ; branch if numeric character - - ORA #$20 ; case convert, allow "A" to "F" and "a" to "f" - SBC #'a' ; subtract "a" (carry set here) - CMP #$06 ; compare normalised with $06 (max+1) - BCS LAB_EXCH ; exit if >"f" or <"0" - - ADC #$0A ; convert to nibble -LAB_ISHN - AND #$0F ; convert to binary - TAX ; save nibble - LDA FAC1_e ; get FAC1 exponent - BEQ LAB_MLTE ; skip multiply if zero - - ADC #$04 ; add four to exponent (*16 - carry clear here) - BCC LAB_NLTO ; if no overflow do evaluate digit - -LAB_MLTO - JMP LAB_2564 ; do overflow error and warm start - -LAB_NXCH - TAX ; save bit - LDA FAC1_e ; get FAC1 exponent - BEQ LAB_MLBT ; skip multiply if zero - - INC FAC1_e ; increment FAC1 exponent (*2) - BEQ LAB_MLTO ; do overflow error if = $00 - - LDA #$00 ; clear sign compare -LAB_MLBT - STA FAC_sc ; save sign compare (FAC1 EOR FAC2) - TXA ; restore bit - JSR LAB_2912 ; evaluate new ASCII digit - -; gets here if the first character was "%" for binary -; get binary number - -LAB_CBIN - JSR LAB_IGBY ; increment and scan memory - EOR #'0' ; convert "0" to 0 etc. - CMP #$02 ; compare with max+1 - BCC LAB_NXCH ; branch exit if < 2 - -LAB_EXCH - JMP LAB_28F6 ; evaluate -ve flag and return - -; ctrl-c check routine. includes limited "life" byte save for INGET routine -; now also the code that checks to see if an interrupt has occurred - -CTRLC - LDA ccflag ; get [CTRL-C] check flag - BNE LAB_FBA2 ; exit if inhibited - - JSR V_INPT ; scan input device - BCC LAB_FBA0 ; exit if buffer empty - - STA ccbyte ; save received byte - LDX #$20 ; "life" timer for bytes - STX ccnull ; set countdown - JMP LAB_1636 ; return to BASIC - -LAB_FBA0 - LDX ccnull ; get countdown byte - BEQ LAB_FBA2 ; exit if finished - - DEC ccnull ; else decrement countdown -LAB_FBA2 - LDX #NmiBase ; set pointer to NMI values - JSR LAB_CKIN ; go check interrupt - LDX #IrqBase ; set pointer to IRQ values - JSR LAB_CKIN ; go check interrupt -LAB_CRTS - RTS - -; check whichever interrupt is indexed by X - -LAB_CKIN - LDA PLUS_0,X ; get interrupt flag byte - BPL LAB_CRTS ; branch if interrupt not enabled - -; we disable the interrupt here and make two new commands RETIRQ and RETNMI to -; automatically enable the interrupt when we exit - - ASL ; move happened bit to setup bit - AND #$40 ; mask happened bits - BEQ LAB_CRTS ; if no interrupt then exit - - STA PLUS_0,X ; save interrupt flag byte - - TXA ; copy index .. - TAY ; .. to Y - - PLA ; dump return address low byte, call from CTRL-C - PLA ; dump return address high byte - - LDA #$05 ; need 5 bytes for GOSUB - JSR LAB_1212 ; check room on stack for A bytes - LDA Bpntrh ; get BASIC execute pointer high byte - PHA ; push on stack - LDA Bpntrl ; get BASIC execute pointer low byte - PHA ; push on stack - LDA Clineh ; get current line high byte - PHA ; push on stack - LDA Clinel ; get current line low byte - PHA ; push on stack - LDA #TK_GOSUB ; token for GOSUB - PHA ; push on stack - - LDA PLUS_1,Y ; get interrupt code pointer low byte - STA Bpntrl ; save as BASIC execute pointer low byte - LDA PLUS_2,Y ; get interrupt code pointer high byte - STA Bpntrh ; save as BASIC execute pointer high byte - - JMP LAB_15C2 ; go do interpreter inner loop - ; can't RTS, we used the stack! the RTS from the ctrl-c - ; check will be taken when the RETIRQ/RETNMI/RETURN is - ; executed at the end of the subroutine - -; get byte from input device, no waiting -; returns with carry set if byte in A - -INGET - JSR V_INPT ; call scan input device - BCS LAB_FB95 ; if byte go reset timer - - LDA ccnull ; get countdown - BEQ LAB_FB96 ; exit if empty - - LDA ccbyte ; get last received byte - SEC ; flag we got a byte -LAB_FB95 - LDX #$00 ; clear X - STX ccnull ; clear timer because we got a byte -LAB_FB96 - RTS - -; these routines only enable the interrupts if the set-up flag is set -; if not they have no effect - -; perform IRQ {ON|OFF|CLEAR} - -LAB_IRQ - LDX #IrqBase ; set pointer to IRQ values - .byte $2C ; make next line BIT abs. - -; perform NMI {ON|OFF|CLEAR} - -LAB_NMI - LDX #NmiBase ; set pointer to NMI values - CMP #TK_ON ; compare with token for ON - BEQ LAB_INON ; go turn on interrupt - - CMP #TK_OFF ; compare with token for OFF - BEQ LAB_IOFF ; go turn off interrupt - - EOR #TK_CLEAR ; compare with token for CLEAR, A = $00 if = TK_CLEAR - BEQ LAB_INEX ; go clear interrupt flags and return - - JMP LAB_SNER ; do syntax error then warm start - -LAB_IOFF - LDA #$7F ; clear A - AND PLUS_0,X ; AND with interrupt setup flag - BPL LAB_INEX ; go clear interrupt enabled flag and return - -LAB_INON - LDA PLUS_0,X ; get interrupt setup flag - ASL ; Shift bit to enabled flag - ORA PLUS_0,X ; OR with flag byte -LAB_INEX - STA PLUS_0,X ; save interrupt flag byte - JMP LAB_IGBY ; update BASIC execute pointer and return - -; these routines set up the pointers and flags for the interrupt routines -; note that the interrupts are also enabled by these commands - -; perform ON IRQ - -LAB_SIRQ - CLI ; enable interrupts - LDX #IrqBase ; set pointer to IRQ values - .byte $2C ; make next line BIT abs. - -; perform ON NMI - -LAB_SNMI - LDX #NmiBase ; set pointer to NMI values - - STX TempB ; save interrupt pointer - JSR LAB_IGBY ; increment and scan memory (past token) - JSR LAB_GFPN ; get fixed-point number into temp integer - LDA Smeml ; get start of mem low byte - LDX Smemh ; get start of mem high byte - JSR LAB_SHLN ; search Basic for temp integer line number from AX - BCS LAB_LFND ; if carry set go set-up interrupt - - JMP LAB_16F7 ; else go do "Undefined statement" error and warm start - -LAB_LFND - LDX TempB ; get interrupt pointer - LDA Baslnl ; get pointer low byte - SBC #$01 ; -1 (carry already set for subtract) - STA PLUS_1,X ; save as interrupt pointer low byte - LDA Baslnh ; get pointer high byte - SBC #$00 ; subtract carry - STA PLUS_2,X ; save as interrupt pointer high byte - - LDA #$C0 ; set interrupt enabled/setup bits - STA PLUS_0,X ; set interrupt flags -LAB_IRTS - RTS - -; return from IRQ service, restores the enabled flag. - -; perform RETIRQ - -LAB_RETIRQ - BNE LAB_IRTS ; exit if following token (to allow syntax error) - - LDA IrqBase ; get interrupt flags - ASL ; copy setup to enabled (b7) - ORA IrqBase ; OR in setup flag - STA IrqBase ; save enabled flag - JMP LAB_16E8 ; go do rest of RETURN - -; return from NMI service, restores the enabled flag. - -; perform RETNMI - -LAB_RETNMI - BNE LAB_IRTS ; exit if following token (to allow syntax error) - - LDA NmiBase ; get set-up flag - ASL ; copy setup to enabled (b7) - ORA NmiBase ; OR in setup flag - STA NmiBase ; save enabled flag - JMP LAB_16E8 ; go do rest of RETURN - -; MAX() MIN() pre process - -LAB_MMPP - JSR LAB_EVEZ ; process expression - JMP LAB_CTNM ; check if source is numeric, else do type mismatch - -; perform MAX() - -LAB_MAX - JSR LAB_PHFA ; push FAC1, evaluate expression, - ; pull FAC2 and compare with FAC1 - BPL LAB_MAX ; branch if no swap to do - - LDA FAC2_1 ; get FAC2 mantissa1 - ORA #$80 ; set top bit (clear sign from compare) - STA FAC2_1 ; save FAC2 mantissa1 - JSR LAB_279B ; copy FAC2 to FAC1 - BEQ LAB_MAX ; go do next (branch always) - -; perform MIN() - -LAB_MIN - JSR LAB_PHFA ; push FAC1, evaluate expression, - ; pull FAC2 and compare with FAC1 - BMI LAB_MIN ; branch if no swap to do - - BEQ LAB_MIN ; branch if no swap to do - - LDA FAC2_1 ; get FAC2 mantissa1 - ORA #$80 ; set top bit (clear sign from compare) - STA FAC2_1 ; save FAC2 mantissa1 - JSR LAB_279B ; copy FAC2 to FAC1 - BEQ LAB_MIN ; go do next (branch always) - -; exit routine. don't bother returning to the loop code -; check for correct exit, else so syntax error - -LAB_MMEC - CMP #')' ; is it end of function? - BNE LAB_MMSE ; if not do MAX MIN syntax error - - PLA ; dump return address low byte - PLA ; dump return address high byte - JMP LAB_IGBY ; update BASIC execute pointer (to chr past ")") - -LAB_MMSE - JMP LAB_SNER ; do syntax error then warm start - -; check for next, evaluate and return or exit -; this is the routine that does most of the work - -LAB_PHFA - JSR LAB_GBYT ; get next BASIC byte - CMP #',' ; is there more ? - BNE LAB_MMEC ; if not go do end check - - ; push FAC1 - JSR LAB_27BA ; round FAC1 - LDA FAC1_s ; get FAC1 sign - ORA #$7F ; set all non sign bits - AND FAC1_1 ; AND FAC1 mantissa1 (AND in sign bit) - PHA ; push on stack - LDA FAC1_2 ; get FAC1 mantissa2 - PHA ; push on stack - LDA FAC1_3 ; get FAC1 mantissa3 - PHA ; push on stack - LDA FAC1_e ; get FAC1 exponent - PHA ; push on stack - - JSR LAB_IGBY ; scan and get next BASIC byte (after ",") - JSR LAB_EVNM ; evaluate expression and check is numeric, - ; else do type mismatch - - ; pop FAC2 (MAX/MIN expression so far) - PLA ; pop exponent - STA FAC2_e ; save FAC2 exponent - PLA ; pop mantissa3 - STA FAC2_3 ; save FAC2 mantissa3 - PLA ; pop mantissa1 - STA FAC2_2 ; save FAC2 mantissa2 - PLA ; pop sign/mantissa1 - STA FAC2_1 ; save FAC2 sign/mantissa1 - STA FAC2_s ; save FAC2 sign - - ; compare FAC1 with (packed) FAC2 - LDA #FAC2_e ; set pointer high byte to FAC2 - JMP LAB_27F8 ; compare FAC1 with FAC2 (AY) and return - ; returns A=$00 if FAC1 = (AY) - ; returns A=$01 if FAC1 > (AY) - ; returns A=$FF if FAC1 < (AY) - -; perform WIDTH - -LAB_WDTH - CMP #',' ; is next byte "," - BEQ LAB_TBSZ ; if so do tab size - - JSR LAB_GTBY ; get byte parameter - TXA ; copy width to A - BEQ LAB_NSTT ; branch if set for infinite line - - CPX #$10 ; else make min width = 16d - BCC TabErr ; if less do function call error and exit - -; this next compare ensures that we can't exit WIDTH via an error leaving the -; tab size greater than the line length. - - CPX TabSiz ; compare with tab size - BCS LAB_NSTT ; branch if >= tab size - - STX TabSiz ; else make tab size = terminal width -LAB_NSTT - STX TWidth ; set the terminal width - JSR LAB_GBYT ; get BASIC byte back - BEQ WExit ; exit if no following - - CMP #',' ; else is it "," - BNE LAB_MMSE ; if not do syntax error - -LAB_TBSZ - JSR LAB_SGBY ; scan and get byte parameter - TXA ; copy TAB size - BMI TabErr ; if >127 do function call error and exit - - CPX #$01 ; compare with min-1 - BCC TabErr ; if <=1 do function call error and exit - - LDA TWidth ; set flags for width - BEQ LAB_SVTB ; skip check if infinite line - - CPX TWidth ; compare TAB with width - BEQ LAB_SVTB ; ok if = - - BCS TabErr ; branch if too big - -LAB_SVTB - STX TabSiz ; save TAB size - -; calculate tab column limit from TAB size. The Iclim is set to the last tab -; position on a line that still has at least one whole tab width between it -; and the end of the line. - -WExit - LDA TWidth ; get width - BEQ LAB_SULP ; branch if infinite line - - CMP TabSiz ; compare with tab size - BCS LAB_WDLP ; branch if >= tab size - - STA TabSiz ; else make tab size = terminal width -LAB_SULP - SEC ; set carry for subtract -LAB_WDLP - SBC TabSiz ; subtract tab size - BCS LAB_WDLP ; loop while no borrow - - ADC TabSiz ; add tab size back - CLC ; clear carry for add - ADC TabSiz ; add tab size back again - STA Iclim ; save for now - LDA TWidth ; get width back - SEC ; set carry for subtract - SBC Iclim ; subtract remainder - STA Iclim ; save tab column limit -LAB_NOSQ - RTS - -TabErr - JMP LAB_FCER ; do function call error then warm start - -; perform SQR() - -LAB_SQR - LDA FAC1_s ; get FAC1 sign - BMI TabErr ; if -ve do function call error - - LDA FAC1_e ; get exponent - BEQ LAB_NOSQ ; if zero just return - - ; else do root - JSR LAB_27AB ; round and copy FAC1 to FAC2 - LDA #$00 ; clear A - - STA FACt_3 ; clear remainder - STA FACt_2 ; .. - STA FACt_1 ; .. - STA TempB ; .. - - STA FAC1_3 ; clear root - STA FAC1_2 ; .. - STA FAC1_1 ; .. - - LDX #$18 ; 24 pairs of bits to do - LDA FAC2_e ; get exponent - LSR ; check odd/even - BCS LAB_SQE2 ; if odd only 1 shift first time - -LAB_SQE1 - ASL FAC2_3 ; shift highest bit of number .. - ROL FAC2_2 ; .. - ROL FAC2_1 ; .. - ROL FACt_3 ; .. into remainder - ROL FACt_2 ; .. - ROL FACt_1 ; .. - ROL TempB ; .. never overflows -LAB_SQE2 - ASL FAC2_3 ; shift highest bit of number .. - ROL FAC2_2 ; .. - ROL FAC2_1 ; .. - ROL FACt_3 ; .. into remainder - ROL FACt_2 ; .. - ROL FACt_1 ; .. - ROL TempB ; .. never overflows - - ASL FAC1_3 ; root = root * 2 - ROL FAC1_2 ; .. - ROL FAC1_1 ; .. never overflows - - LDA FAC1_3 ; get root low byte - ROL ; *2 - STA Temp3 ; save partial low byte - LDA FAC1_2 ; get root low mid byte - ROL ; *2 - STA Temp3+1 ; save partial low mid byte - LDA FAC1_1 ; get root high mid byte - ROL ; *2 - STA Temp3+2 ; save partial high mid byte - LDA #$00 ; get root high byte (always $00) - ROL ; *2 - STA Temp3+3 ; save partial high byte - - ; carry clear for subtract +1 - LDA FACt_3 ; get remainder low byte - SBC Temp3 ; subtract partial low byte - STA Temp3 ; save partial low byte - - LDA FACt_2 ; get remainder low mid byte - SBC Temp3+1 ; subtract partial low mid byte - STA Temp3+1 ; save partial low mid byte - - LDA FACt_1 ; get remainder high mid byte - SBC Temp3+2 ; subtract partial high mid byte - TAY ; copy partial high mid byte - - LDA TempB ; get remainder high byte - SBC Temp3+3 ; subtract partial high byte - BCC LAB_SQNS ; skip sub if remainder smaller - - STA TempB ; save remainder high byte - - STY FACt_1 ; save remainder high mid byte - - LDA Temp3+1 ; get remainder low mid byte - STA FACt_2 ; save remainder low mid byte - - LDA Temp3 ; get partial low byte - STA FACt_3 ; save remainder low byte - - INC FAC1_3 ; increment root low byte (never any rollover) -LAB_SQNS - DEX ; decrement bit pair count - BNE LAB_SQE1 ; loop if not all done - - SEC ; set carry for subtract - LDA FAC2_e ; get exponent - SBC #$80 ; normalise - ROR ; /2 and re-bias to $80 - ADC #$00 ; add bit zero back in (allow for half shift) - STA FAC1_e ; save it - JMP LAB_24D5 ; normalise FAC1 and return - -; perform VARPTR() - -LAB_VARPTR - JSR LAB_IGBY ; increment and scan memory - JSR LAB_GVAR ; get var address - JSR LAB_1BFB ; scan for ")" , else do syntax error then warm start - LDY Cvaral ; get var address low byte - LDA Cvarah ; get var address high byte - JMP LAB_AYFC ; save and convert integer AY to FAC1 and return - -; perform PI - -LAB_PI - LDA #LAB_2C7C ; set (2*pi) pointer high byte - JSR LAB_UFAC ; unpack memory (AY) into FAC1 - DEC FAC1_e ; make result = PI - RTS - -; perform TWOPI - -LAB_TWOPI - LDA #LAB_2C7C ; set (2*pi) pointer high byte - JMP LAB_UFAC ; unpack memory (AY) into FAC1 and return - -; system dependant i/o vectors -; these are in RAM and are set by the monitor at start-up - -V_INPT - JMP (VEC_IN) ; non halting scan input device -V_OUTP - JMP (VEC_OUT) ; send byte to output device -V_LOAD - JMP (VEC_LD) ; load BASIC program -V_SAVE - JMP (VEC_SV) ; save BASIC program - -; The rest are tables messages and code for RAM - -; the rest of the code is tables and BASIC start-up code - -PG2_TABS - .byte $FF ; ctrl-c flag - $00 = enabled - .byte $00 ; ctrl-c byte - GET needs this - .byte $00 ; ctrl-c byte timeout - GET needs this - .word CTRLC ; ctrl c check vector - .word CHRIN ; non halting key input - monitor to set this - .word CHROUT ; output vector - monitor to set this -; .word xxxx ; load vector - monitor to set this -; .word xxxx ; save vector - monitor to set this -PG2_TABE - -; character get subroutine for zero page - -; For a 1.8432MHz 6502 including the JSR and RTS -; fastest (>=":") = 29 cycles = 15.7uS -; slowest (<":") = 40 cycles = 21.7uS -; space skip = +21 cycles = +11.4uS -; inc across page = +4 cycles = +2.2uS - -; the target address for the LDA at LAB_2CF4 becomes the BASIC execute pointer once the -; block is copied to it's destination, any non zero page address will do at assembly -; time, to assemble a three byte instruction. - -; page 0 initialisation table from $BC -; increment and scan memory - -LAB_2CEE - INC Bpntrl ; increment BASIC execute pointer low byte - BNE LAB_2CF4 ; branch if no carry - ; else - INC Bpntrh ; increment BASIC execute pointer high byte - -; page 0 initialisation table from $C2 -; scan memory - -LAB_2CF4 - LDA $FFFF ; get byte to scan (addr set by call routine) - CMP #TK_ELSE ; compare with the token for ELSE - BEQ LAB_2D05 ; exit if ELSE, not numeric, carry set - - CMP #':' ; compare with ":" - BCS LAB_2D05 ; exit if >= ":", not numeric, carry set - - CMP #' ' ; compare with " " - BEQ LAB_2CEE ; if " " go do next - - SEC ; set carry for SBC - SBC #'0' ; subtract "0" - SEC ; set carry for SBC - SBC #$D0 ; subtract -"0" - ; clear carry if byte = "0"-"9" -LAB_2D05 - RTS - -; page zero initialisation table $00-$12 inclusive - -StrTab - .byte $4C ; JMP opcode - .word LAB_COLD ; initial warm start vector (cold start) - - .byte $00 ; these bytes are not used by BASIC - .word $0000 ; - .word $0000 ; - .word $0000 ; - - .byte $4C ; JMP opcode - .word LAB_FCER ; initial user function vector ("Function call" error) - .byte $00 ; default NULL count - .byte $00 ; clear terminal position - .byte $00 ; default terminal width byte - .byte $F2 ; default limit for TAB = 14 - .word Ram_base ; start of user RAM -EndTab - -LAB_MSZM - .byte $0D,$0A,"Memory size ",$00 - -LAB_SMSG - .byte " Bytes free",$0D,$0A,$0A - .byte "Enhanced BASIC 2.22",$0A,$00 - -; numeric constants and series - - ; constants and series for LOG(n) -LAB_25A0 - .byte $02 ; counter - .byte $80,$19,$56,$62 ; 0.59898 - .byte $80,$76,$22,$F3 ; 0.96147 -;## .byte $80,$76,$22,$F1 ; 0.96147 - .byte $82,$38,$AA,$40 ; 2.88539 -;## .byte $82,$38,$AA,$45 ; 2.88539 - -LAB_25AD - .byte $80,$35,$04,$F3 ; 0.70711 1/root 2 -LAB_25B1 - .byte $81,$35,$04,$F3 ; 1.41421 root 2 -LAB_25B5 - .byte $80,$80,$00,$00 ; -0.5 -LAB_25B9 - .byte $80,$31,$72,$18 ; 0.69315 LOG(2) - - ; numeric PRINT constants -LAB_2947 - .byte $91,$43,$4F,$F8 ; 99999.9375 (max value with at least one decimal) -LAB_294B - .byte $94,$74,$23,$F7 ; 999999.4375 (max value before scientific notation) -LAB_294F - .byte $94,$74,$24,$00 ; 1000000 - - ; EXP(n) constants and series -LAB_2AFA - .byte $81,$38,$AA,$3B ; 1.4427 (1/LOG base 2 e) -LAB_2AFE - .byte $06 ; counter - .byte $74,$63,$90,$8C ; 2.17023e-4 - .byte $77,$23,$0C,$AB ; 0.00124 - .byte $7A,$1E,$94,$00 ; 0.00968 - .byte $7C,$63,$42,$80 ; 0.05548 - .byte $7E,$75,$FE,$D0 ; 0.24023 - .byte $80,$31,$72,$15 ; 0.69315 - .byte $81,$00,$00,$00 ; 1.00000 - -;## .byte $07 ; counter -;## .byte $74,$94,$2E,$40 ; -1/7! (-1/5040) -;## .byte $77,$2E,$4F,$70 ; 1/6! ( 1/720) -;## .byte $7A,$88,$02,$6E ; -1/5! (-1/120) -;## .byte $7C,$2A,$A0,$E6 ; 1/4! ( 1/24) -;## .byte $7E,$AA,$AA,$50 ; -1/3! (-1/6) -;## .byte $7F,$7F,$FF,$FF ; 1/2! ( 1/2) -;## .byte $81,$80,$00,$00 ; -1/1! (-1/1) -;## .byte $81,$00,$00,$00 ; 1/0! ( 1/1) - - ; trigonometric constants and series -LAB_2C78 - .byte $81,$49,$0F,$DB ; 1.570796371 (pi/2) as floating # -LAB_2C84 - .byte $04 ; counter - .byte $86,$1E,$D7,$FB ; 39.7109 -;## .byte $86,$1E,$D7,$BA ; 39.7109 - .byte $87,$99,$26,$65 ;-76.575 -;## .byte $87,$99,$26,$64 ;-76.575 - .byte $87,$23,$34,$58 ; 81.6022 - .byte $86,$A5,$5D,$E1 ;-41.3417 -;## .byte $86,$A5,$5D,$E0 ;-41.3417 -LAB_2C7C - .byte $83,$49,$0F,$DB ; 6.28319 (2*pi) as floating # -;## .byte $83,$49,$0F,$DA ; 6.28319 (2*pi) as floating # - -LAB_2CC9 - .byte $08 ; counter - .byte $78,$3A,$C5,$37 ; 0.00285 - .byte $7B,$83,$A2,$5C ;-0.0160686 - .byte $7C,$2E,$DD,$4D ; 0.0426915 - .byte $7D,$99,$B0,$1E ;-0.0750429 - .byte $7D,$59,$ED,$24 ; 0.106409 - .byte $7E,$91,$72,$00 ;-0.142036 - .byte $7E,$4C,$B9,$73 ; 0.199926 - .byte $7F,$AA,$AA,$53 ;-0.333331 - -;## .byte $08 ; counter -;## .byte $78,$3B,$D7,$4A ; 1/17 -;## .byte $7B,$84,$6E,$02 ;-1/15 -;## .byte $7C,$2F,$C1,$FE ; 1/13 -;## .byte $7D,$9A,$31,$74 ;-1/11 -;## .byte $7D,$5A,$3D,$84 ; 1/9 -;## .byte $7E,$91,$7F,$C8 ;-1/7 -;## .byte $7E,$4C,$BB,$E4 ; 1/5 -;## .byte $7F,$AA,$AA,$6C ;-1/3 - -LAB_1D96 = *+1 ; $00,$00 used for undefined variables -LAB_259C - .byte $81,$00,$00,$00 ; 1.000000, used for INC -LAB_2AFD - .byte $81,$80,$00,$00 ; -1.00000, used for DEC. must be on the same page as +1.00 - - ; misc constants -LAB_1DF7 - .byte $90 ;-32768 (uses first three bytes from 0.5) -LAB_2A96 - .byte $80,$00,$00,$00 ; 0.5 -LAB_2C80 - .byte $7F,$00,$00,$00 ; 0.25 -LAB_26B5 - .byte $84,$20,$00,$00 ; 10.0000 divide by 10 constant - -; This table is used in converting numbers to ASCII. - -LAB_2A9A -LAB_2A9B = LAB_2A9A+1 -LAB_2A9C = LAB_2A9B+1 - .byte $FE,$79,$60 ; -100000 - .byte $00,$27,$10 ; 10000 - .byte $FF,$FC,$18 ; -1000 - .byte $00,$00,$64 ; 100 - .byte $FF,$FF,$F6 ; -10 - .byte $00,$00,$01 ; 1 - -LAB_CTBL - .word LAB_END-1 ; END - .word LAB_FOR-1 ; FOR - .word LAB_NEXT-1 ; NEXT - .word LAB_DATA-1 ; DATA - .word LAB_INPUT-1 ; INPUT - .word LAB_DIM-1 ; DIM - .word LAB_READ-1 ; READ - .word LAB_LET-1 ; LET - .word LAB_DEC-1 ; DEC new command - .word LAB_GOTO-1 ; GOTO - .word LAB_RUN-1 ; RUN - .word LAB_IF-1 ; IF - .word LAB_RESTORE-1 ; RESTORE modified command - .word LAB_GOSUB-1 ; GOSUB - .word LAB_RETIRQ-1 ; RETIRQ new command - .word LAB_RETNMI-1 ; RETNMI new command - .word LAB_RETURN-1 ; RETURN - .word LAB_REM-1 ; REM - .word LAB_STOP-1 ; STOP - .word LAB_ON-1 ; ON modified command - .word LAB_NULL-1 ; NULL modified command - .word LAB_INC-1 ; INC new command - .word LAB_WAIT-1 ; WAIT - .word V_LOAD-1 ; LOAD - .word V_SAVE-1 ; SAVE - .word LAB_DEF-1 ; DEF - .word LAB_POKE-1 ; POKE - .word LAB_DOKE-1 ; DOKE new command - .word LAB_CALL-1 ; CALL new command - .word LAB_DO-1 ; DO new command - .word LAB_LOOP-1 ; LOOP new command - .word LAB_PRINT-1 ; PRINT - .word LAB_CONT-1 ; CONT - .word LAB_LIST-1 ; LIST - .word LAB_CLEAR-1 ; CLEAR - .word LAB_NEW-1 ; NEW - .word LAB_WDTH-1 ; WIDTH new command - .word LAB_GET-1 ; GET new command - .word LAB_SWAP-1 ; SWAP new command - .word LAB_BITSET-1 ; BITSET new command - .word LAB_BITCLR-1 ; BITCLR new command - .word LAB_IRQ-1 ; IRQ new command - .word LAB_NMI-1 ; NMI new command - -; function pre process routine table - -LAB_FTPL -LAB_FTPM = LAB_FTPL+$01 - .word LAB_PPFN-1 ; SGN(n) process numeric expression in () - .word LAB_PPFN-1 ; INT(n) " - .word LAB_PPFN-1 ; ABS(n) " - .word LAB_EVEZ-1 ; USR(x) process any expression - .word LAB_1BF7-1 ; FRE(x) " - .word LAB_1BF7-1 ; POS(x) " - .word LAB_PPFN-1 ; SQR(n) process numeric expression in () - .word LAB_PPFN-1 ; RND(n) " - .word LAB_PPFN-1 ; LOG(n) " - .word LAB_PPFN-1 ; EXP(n) " - .word LAB_PPFN-1 ; COS(n) " - .word LAB_PPFN-1 ; SIN(n) " - .word LAB_PPFN-1 ; TAN(n) " - .word LAB_PPFN-1 ; ATN(n) " - .word LAB_PPFN-1 ; PEEK(n) " - .word LAB_PPFN-1 ; DEEK(n) " - .word $0000 ; SADD() none - .word LAB_PPFS-1 ; LEN($) process string expression in () - .word LAB_PPFN-1 ; STR$(n) process numeric expression in () - .word LAB_PPFS-1 ; VAL($) process string expression in () - .word LAB_PPFS-1 ; ASC($) " - .word LAB_PPFS-1 ; UCASE$($) " - .word LAB_PPFS-1 ; LCASE$($) " - .word LAB_PPFN-1 ; CHR$(n) process numeric expression in () - .word LAB_BHSS-1 ; HEX$(n) " - .word LAB_BHSS-1 ; BIN$(n) " - .word $0000 ; BITTST() none - .word LAB_MMPP-1 ; MAX() process numeric expression - .word LAB_MMPP-1 ; MIN() " - .word LAB_PPBI-1 ; PI advance pointer - .word LAB_PPBI-1 ; TWOPI " - .word $0000 ; VARPTR() none - .word LAB_LRMS-1 ; LEFT$() process string expression - .word LAB_LRMS-1 ; RIGHT$() " - .word LAB_LRMS-1 ; MID$() " - -; action addresses for functions - -LAB_FTBL -LAB_FTBM = LAB_FTBL+$01 - .word LAB_SGN-1 ; SGN() - .word LAB_INT-1 ; INT() - .word LAB_ABS-1 ; ABS() - .word LAB_USR-1 ; USR() - .word LAB_FRE-1 ; FRE() - .word LAB_POS-1 ; POS() - .word LAB_SQR-1 ; SQR() - .word LAB_RND-1 ; RND() modified function - .word LAB_LOG-1 ; LOG() - .word LAB_EXP-1 ; EXP() - .word LAB_COS-1 ; COS() - .word LAB_SIN-1 ; SIN() - .word LAB_TAN-1 ; TAN() - .word LAB_ATN-1 ; ATN() - .word LAB_PEEK-1 ; PEEK() - .word LAB_DEEK-1 ; DEEK() new function - .word LAB_SADD-1 ; SADD() new function - .word LAB_LENS-1 ; LEN() - .word LAB_STRS-1 ; STR$() - .word LAB_VAL-1 ; VAL() - .word LAB_ASC-1 ; ASC() - .word LAB_UCASE-1 ; UCASE$() new function - .word LAB_LCASE-1 ; LCASE$() new function - .word LAB_CHRS-1 ; CHR$() - .word LAB_HEXS-1 ; HEX$() new function - .word LAB_BINS-1 ; BIN$() new function - .word LAB_BTST-1 ; BITTST() new function - .word LAB_MAX-1 ; MAX() new function - .word LAB_MIN-1 ; MIN() new function - .word LAB_PI-1 ; PI new function - .word LAB_TWOPI-1 ; TWOPI new function - .word LAB_VARPTR-1 ; VARPTR() new function - .word LAB_LEFT-1 ; LEFT$() - .word LAB_RIGHT-1 ; RIGHT$() - .word LAB_MIDS-1 ; MID$() - -; hierarchy and action addresses for operator - -LAB_OPPT - .byte $79 ; + - .word LAB_ADD-1 - .byte $79 ; - - .word LAB_SUBTRACT-1 - .byte $7B ; * - .word LAB_MULTIPLY-1 - .byte $7B ; / - .word LAB_DIVIDE-1 - .byte $7F ; ^ - .word LAB_POWER-1 - .byte $50 ; AND - .word LAB_AND-1 - .byte $46 ; EOR new operator - .word LAB_EOR-1 - .byte $46 ; OR - .word LAB_OR-1 - .byte $56 ; >> new operator - .word LAB_RSHIFT-1 - .byte $56 ; << new operator - .word LAB_LSHIFT-1 - .byte $7D ; > - .word LAB_GTHAN-1 - .byte $5A ; = - .word LAB_EQUAL-1 - .byte $64 ; < - .word LAB_LTHAN-1 - -; keywords start with .. -; this is the first character table and must be in alphabetic order - -TAB_1STC - .byte "*" - .byte "+" - .byte "-" - .byte "/" - .byte "<" - .byte "=" - .byte ">" - .byte "?" - .byte "A" - .byte "B" - .byte "C" - .byte "D" - .byte "E" - .byte "F" - .byte "G" - .byte "H" - .byte "I" - .byte "L" - .byte "M" - .byte "N" - .byte "O" - .byte "P" - .byte "R" - .byte "S" - .byte "T" - .byte "U" - .byte "V" - .byte "W" - .byte "^" - .byte $00 ; table terminator - -; pointers to keyword tables - -TAB_CHRT - .word TAB_STAR ; table for "*" - .word TAB_PLUS ; table for "+" - .word TAB_MNUS ; table for "-" - .word TAB_SLAS ; table for "/" - .word TAB_LESS ; table for "<" - .word TAB_EQUL ; table for "=" - .word TAB_MORE ; table for ">" - .word TAB_QEST ; table for "?" - .word TAB_ASCA ; table for "A" - .word TAB_ASCB ; table for "B" - .word TAB_ASCC ; table for "C" - .word TAB_ASCD ; table for "D" - .word TAB_ASCE ; table for "E" - .word TAB_ASCF ; table for "F" - .word TAB_ASCG ; table for "G" - .word TAB_ASCH ; table for "H" - .word TAB_ASCI ; table for "I" - .word TAB_ASCL ; table for "L" - .word TAB_ASCM ; table for "M" - .word TAB_ASCN ; table for "N" - .word TAB_ASCO ; table for "O" - .word TAB_ASCP ; table for "P" - .word TAB_ASCR ; table for "R" - .word TAB_ASCS ; table for "S" - .word TAB_ASCT ; table for "T" - .word TAB_ASCU ; table for "U" - .word TAB_ASCV ; table for "V" - .word TAB_ASCW ; table for "W" - .word TAB_POWR ; table for "^" - -; tables for each start character, note if a longer keyword with the same start -; letters as a shorter one exists then it must come first, else the list is in -; alphabetical order as follows .. - -; [keyword,token -; [keyword,token]] -; end marker (#$00) - -TAB_STAR - .byte TK_MUL,$00 ; * -TAB_PLUS - .byte TK_PLUS,$00 ; + -TAB_MNUS - .byte TK_MINUS,$00 ; - -TAB_SLAS - .byte TK_DIV,$00 ; / -TAB_LESS -LBB_LSHIFT - .byte "<",TK_LSHIFT ; << note - "<<" must come before "<" - .byte TK_LT ; < - .byte $00 -TAB_EQUL - .byte TK_EQUAL,$00 ; = -TAB_MORE -LBB_RSHIFT - .byte ">",TK_RSHIFT ; >> note - ">>" must come before ">" - .byte TK_GT ; > - .byte $00 -TAB_QEST - .byte TK_PRINT,$00 ; ? -TAB_ASCA -LBB_ABS - .byte "BS(",TK_ABS ; ABS( -LBB_AND - .byte "ND",TK_AND ; AND -LBB_ASC - .byte "SC(",TK_ASC ; ASC( -LBB_ATN - .byte "TN(",TK_ATN ; ATN( - .byte $00 -TAB_ASCB -LBB_BINS - .byte "IN$(",TK_BINS ; BIN$( -LBB_BITCLR - .byte "ITCLR",TK_BITCLR ; BITCLR -LBB_BITSET - .byte "ITSET",TK_BITSET ; BITSET -LBB_BITTST - .byte "ITTST(",TK_BITTST - ; BITTST( - .byte $00 -TAB_ASCC -LBB_CALL - .byte "ALL",TK_CALL ; CALL -LBB_CHRS - .byte "HR$(",TK_CHRS ; CHR$( -LBB_CLEAR - .byte "LEAR",TK_CLEAR ; CLEAR -LBB_CONT - .byte "ONT",TK_CONT ; CONT -LBB_COS - .byte "OS(",TK_COS ; COS( - .byte $00 -TAB_ASCD -LBB_DATA - .byte "ATA",TK_DATA ; DATA -LBB_DEC - .byte "EC",TK_DEC ; DEC -LBB_DEEK - .byte "EEK(",TK_DEEK ; DEEK( -LBB_DEF - .byte "EF",TK_DEF ; DEF -LBB_DIM - .byte "IM",TK_DIM ; DIM -LBB_DOKE - .byte "OKE",TK_DOKE ; DOKE note - "DOKE" must come before "DO" -LBB_DO - .byte "O",TK_DO ; DO - .byte $00 -TAB_ASCE -LBB_ELSE - .byte "LSE",TK_ELSE ; ELSE -LBB_END - .byte "ND",TK_END ; END -LBB_EOR - .byte "OR",TK_EOR ; EOR -LBB_EXP - .byte "XP(",TK_EXP ; EXP( - .byte $00 -TAB_ASCF -LBB_FN - .byte "N",TK_FN ; FN -LBB_FOR - .byte "OR",TK_FOR ; FOR -LBB_FRE - .byte "RE(",TK_FRE ; FRE( - .byte $00 -TAB_ASCG -LBB_GET - .byte "ET",TK_GET ; GET -LBB_GOSUB - .byte "OSUB",TK_GOSUB ; GOSUB -LBB_GOTO - .byte "OTO",TK_GOTO ; GOTO - .byte $00 -TAB_ASCH -LBB_HEXS - .byte "EX$(",TK_HEXS ; HEX$( - .byte $00 -TAB_ASCI -LBB_IF - .byte "F",TK_IF ; IF -LBB_INC - .byte "NC",TK_INC ; INC -LBB_INPUT - .byte "NPUT",TK_INPUT ; INPUT -LBB_INT - .byte "NT(",TK_INT ; INT( -LBB_IRQ - .byte "RQ",TK_IRQ ; IRQ - .byte $00 -TAB_ASCL -LBB_LCASES - .byte "CASE$(",TK_LCASES - ; LCASE$( -LBB_LEFTS - .byte "EFT$(",TK_LEFTS ; LEFT$( -LBB_LEN - .byte "EN(",TK_LEN ; LEN( -LBB_LET - .byte "ET",TK_LET ; LET -LBB_LIST - .byte "IST",TK_LIST ; LIST -LBB_LOAD - .byte "OAD",TK_LOAD ; LOAD -LBB_LOG - .byte "OG(",TK_LOG ; LOG( -LBB_LOOP - .byte "OOP",TK_LOOP ; LOOP - .byte $00 -TAB_ASCM -LBB_MAX - .byte "AX(",TK_MAX ; MAX( -LBB_MIDS - .byte "ID$(",TK_MIDS ; MID$( -LBB_MIN - .byte "IN(",TK_MIN ; MIN( - .byte $00 -TAB_ASCN -LBB_NEW - .byte "EW",TK_NEW ; NEW -LBB_NEXT - .byte "EXT",TK_NEXT ; NEXT -LBB_NMI - .byte "MI",TK_NMI ; NMI -LBB_NOT - .byte "OT",TK_NOT ; NOT -LBB_NULL - .byte "ULL",TK_NULL ; NULL - .byte $00 -TAB_ASCO -LBB_OFF - .byte "FF",TK_OFF ; OFF -LBB_ON - .byte "N",TK_ON ; ON -LBB_OR - .byte "R",TK_OR ; OR - .byte $00 -TAB_ASCP -LBB_PEEK - .byte "EEK(",TK_PEEK ; PEEK( -LBB_PI - .byte "I",TK_PI ; PI -LBB_POKE - .byte "OKE",TK_POKE ; POKE -LBB_POS - .byte "OS(",TK_POS ; POS( -LBB_PRINT - .byte "RINT",TK_PRINT ; PRINT - .byte $00 -TAB_ASCR -LBB_READ - .byte "EAD",TK_READ ; READ -LBB_REM - .byte "EM",TK_REM ; REM -LBB_RESTORE - .byte "ESTORE",TK_RESTORE - ; RESTORE -LBB_RETIRQ - .byte "ETIRQ",TK_RETIRQ ; RETIRQ -LBB_RETNMI - .byte "ETNMI",TK_RETNMI ; RETNMI -LBB_RETURN - .byte "ETURN",TK_RETURN ; RETURN -LBB_RIGHTS - .byte "IGHT$(",TK_RIGHTS - ; RIGHT$( -LBB_RND - .byte "ND(",TK_RND ; RND( -LBB_RUN - .byte "UN",TK_RUN ; RUN - .byte $00 -TAB_ASCS -LBB_SADD - .byte "ADD(",TK_SADD ; SADD( -LBB_SAVE - .byte "AVE",TK_SAVE ; SAVE -LBB_SGN - .byte "GN(",TK_SGN ; SGN( -LBB_SIN - .byte "IN(",TK_SIN ; SIN( -LBB_SPC - .byte "PC(",TK_SPC ; SPC( -LBB_SQR - .byte "QR(",TK_SQR ; SQR( -LBB_STEP - .byte "TEP",TK_STEP ; STEP -LBB_STOP - .byte "TOP",TK_STOP ; STOP -LBB_STRS - .byte "TR$(",TK_STRS ; STR$( -LBB_SWAP - .byte "WAP",TK_SWAP ; SWAP - .byte $00 -TAB_ASCT -LBB_TAB - .byte "AB(",TK_TAB ; TAB( -LBB_TAN - .byte "AN(",TK_TAN ; TAN( -LBB_THEN - .byte "HEN",TK_THEN ; THEN -LBB_TO - .byte "O",TK_TO ; TO -LBB_TWOPI - .byte "WOPI",TK_TWOPI ; TWOPI - .byte $00 -TAB_ASCU -LBB_UCASES - .byte "CASE$(",TK_UCASES - ; UCASE$( -LBB_UNTIL - .byte "NTIL",TK_UNTIL ; UNTIL -LBB_USR - .byte "SR(",TK_USR ; USR( - .byte $00 -TAB_ASCV -LBB_VAL - .byte "AL(",TK_VAL ; VAL( -LBB_VPTR - .byte "ARPTR(",TK_VPTR ; VARPTR( - .byte $00 -TAB_ASCW -LBB_WAIT - .byte "AIT",TK_WAIT ; WAIT -LBB_WHILE - .byte "HILE",TK_WHILE ; WHILE -LBB_WIDTH - .byte "IDTH",TK_WIDTH ; WIDTH - .byte $00 -TAB_POWR - .byte TK_POWER,$00 ; ^ - -; new decode table for LIST -; Table is .. -; byte - keyword length, keyword first character -; word - pointer to rest of keyword from dictionary - -; note if length is 1 then the pointer is ignored - -LAB_KEYT - .byte 3,'E' - .word LBB_END ; END - .byte 3,'F' - .word LBB_FOR ; FOR - .byte 4,'N' - .word LBB_NEXT ; NEXT - .byte 4,'D' - .word LBB_DATA ; DATA - .byte 5,'I' - .word LBB_INPUT ; INPUT - .byte 3,'D' - .word LBB_DIM ; DIM - .byte 4,'R' - .word LBB_READ ; READ - .byte 3,'L' - .word LBB_LET ; LET - .byte 3,'D' - .word LBB_DEC ; DEC - .byte 4,'G' - .word LBB_GOTO ; GOTO - .byte 3,'R' - .word LBB_RUN ; RUN - .byte 2,'I' - .word LBB_IF ; IF - .byte 7,'R' - .word LBB_RESTORE ; RESTORE - .byte 5,'G' - .word LBB_GOSUB ; GOSUB - .byte 6,'R' - .word LBB_RETIRQ ; RETIRQ - .byte 6,'R' - .word LBB_RETNMI ; RETNMI - .byte 6,'R' - .word LBB_RETURN ; RETURN - .byte 3,'R' - .word LBB_REM ; REM - .byte 4,'S' - .word LBB_STOP ; STOP - .byte 2,'O' - .word LBB_ON ; ON - .byte 4,'N' - .word LBB_NULL ; NULL - .byte 3,'I' - .word LBB_INC ; INC - .byte 4,'W' - .word LBB_WAIT ; WAIT - .byte 4,'L' - .word LBB_LOAD ; LOAD - .byte 4,'S' - .word LBB_SAVE ; SAVE - .byte 3,'D' - .word LBB_DEF ; DEF - .byte 4,'P' - .word LBB_POKE ; POKE - .byte 4,'D' - .word LBB_DOKE ; DOKE - .byte 4,'C' - .word LBB_CALL ; CALL - .byte 2,'D' - .word LBB_DO ; DO - .byte 4,'L' - .word LBB_LOOP ; LOOP - .byte 5,'P' - .word LBB_PRINT ; PRINT - .byte 4,'C' - .word LBB_CONT ; CONT - .byte 4,'L' - .word LBB_LIST ; LIST - .byte 5,'C' - .word LBB_CLEAR ; CLEAR - .byte 3,'N' - .word LBB_NEW ; NEW - .byte 5,'W' - .word LBB_WIDTH ; WIDTH - .byte 3,'G' - .word LBB_GET ; GET - .byte 4,'S' - .word LBB_SWAP ; SWAP - .byte 6,'B' - .word LBB_BITSET ; BITSET - .byte 6,'B' - .word LBB_BITCLR ; BITCLR - .byte 3,'I' - .word LBB_IRQ ; IRQ - .byte 3,'N' - .word LBB_NMI ; NMI - -; secondary commands (can't start a statement) - - .byte 4,'T' - .word LBB_TAB ; TAB - .byte 4,'E' - .word LBB_ELSE ; ELSE - .byte 2,'T' - .word LBB_TO ; TO - .byte 2,'F' - .word LBB_FN ; FN - .byte 4,'S' - .word LBB_SPC ; SPC - .byte 4,'T' - .word LBB_THEN ; THEN - .byte 3,'N' - .word LBB_NOT ; NOT - .byte 4,'S' - .word LBB_STEP ; STEP - .byte 5,'U' - .word LBB_UNTIL ; UNTIL - .byte 5,'W' - .word LBB_WHILE ; WHILE - .byte 3,'O' - .word LBB_OFF ; OFF - -; opperators - - .byte 1,'+' - .word $0000 ; + - .byte 1,'-' - .word $0000 ; - - .byte 1,'*' - .word $0000 ; * - .byte 1,'/' - .word $0000 ; / - .byte 1,'^' - .word $0000 ; ^ - .byte 3,'A' - .word LBB_AND ; AND - .byte 3,'E' - .word LBB_EOR ; EOR - .byte 2,'O' - .word LBB_OR ; OR - .byte 2,'>' - .word LBB_RSHIFT ; >> - .byte 2,'<' - .word LBB_LSHIFT ; << - .byte 1,'>' - .word $0000 ; > - .byte 1,'=' - .word $0000 ; = - .byte 1,'<' - .word $0000 ; < - -; functions - - .byte 4,'S' ; - .word LBB_SGN ; SGN - .byte 4,'I' ; - .word LBB_INT ; INT - .byte 4,'A' ; - .word LBB_ABS ; ABS - .byte 4,'U' ; - .word LBB_USR ; USR - .byte 4,'F' ; - .word LBB_FRE ; FRE - .byte 4,'P' ; - .word LBB_POS ; POS - .byte 4,'S' ; - .word LBB_SQR ; SQR - .byte 4,'R' ; - .word LBB_RND ; RND - .byte 4,'L' ; - .word LBB_LOG ; LOG - .byte 4,'E' ; - .word LBB_EXP ; EXP - .byte 4,'C' ; - .word LBB_COS ; COS - .byte 4,'S' ; - .word LBB_SIN ; SIN - .byte 4,'T' ; - .word LBB_TAN ; TAN - .byte 4,'A' ; - .word LBB_ATN ; ATN - .byte 5,'P' ; - .word LBB_PEEK ; PEEK - .byte 5,'D' ; - .word LBB_DEEK ; DEEK - .byte 5,'S' ; - .word LBB_SADD ; SADD - .byte 4,'L' ; - .word LBB_LEN ; LEN - .byte 5,'S' ; - .word LBB_STRS ; STR$ - .byte 4,'V' ; - .word LBB_VAL ; VAL - .byte 4,'A' ; - .word LBB_ASC ; ASC - .byte 7,'U' ; - .word LBB_UCASES ; UCASE$ - .byte 7,'L' ; - .word LBB_LCASES ; LCASE$ - .byte 5,'C' ; - .word LBB_CHRS ; CHR$ - .byte 5,'H' ; - .word LBB_HEXS ; HEX$ - .byte 5,'B' ; - .word LBB_BINS ; BIN$ - .byte 7,'B' ; - .word LBB_BITTST ; BITTST - .byte 4,'M' ; - .word LBB_MAX ; MAX - .byte 4,'M' ; - .word LBB_MIN ; MIN - .byte 2,'P' ; - .word LBB_PI ; PI - .byte 5,'T' ; - .word LBB_TWOPI ; TWOPI - .byte 7,'V' ; - .word LBB_VPTR ; VARPTR - .byte 6,'L' ; - .word LBB_LEFTS ; LEFT$ - .byte 7,'R' ; - .word LBB_RIGHTS ; RIGHT$ - .byte 5,'M' ; - .word LBB_MIDS ; MID$ - -; BASIC messages, mostly error messages - -LAB_BAER - .word ERR_NF ;$00 NEXT without FOR - .word ERR_SN ;$02 syntax - .word ERR_RG ;$04 RETURN without GOSUB - .word ERR_OD ;$06 out of data - .word ERR_FC ;$08 function call - .word ERR_OV ;$0A overflow - .word ERR_OM ;$0C out of memory - .word ERR_US ;$0E undefined statement - .word ERR_BS ;$10 array bounds - .word ERR_DD ;$12 double dimension array - .word ERR_D0 ;$14 divide by 0 - .word ERR_ID ;$16 illegal direct - .word ERR_TM ;$18 type mismatch - .word ERR_LS ;$1A long string - .word ERR_ST ;$1C string too complex - .word ERR_CN ;$1E continue error - .word ERR_UF ;$20 undefined function - .word ERR_LD ;$22 LOOP without DO - -; I may implement these two errors to force definition of variables and -; dimensioning of arrays before use. - -; .word ERR_UV ;$24 undefined variable - -; the above error has been tested and works (see code and comments below LAB_1D8B) - -; .word ERR_UA ;$26 undimensioned array - -ERR_NF .byte "NEXT without FOR",$00 -ERR_SN .byte "Syntax",$00 -ERR_RG .byte "RETURN without GOSUB",$00 -ERR_OD .byte "Out of DATA",$00 -ERR_FC .byte "Function call",$00 -ERR_OV .byte "Overflow",$00 -ERR_OM .byte "Out of memory",$00 -ERR_US .byte "Undefined statement",$00 -ERR_BS .byte "Array bounds",$00 -ERR_DD .byte "Double dimension",$00 -ERR_D0 .byte "Divide by zero",$00 -ERR_ID .byte "Illegal direct",$00 -ERR_TM .byte "Type mismatch",$00 -ERR_LS .byte "String too long",$00 -ERR_ST .byte "String too complex",$00 -ERR_CN .byte "Can't continue",$00 -ERR_UF .byte "Undefined function",$00 -ERR_LD .byte "LOOP without DO",$00 - -;ERR_UV .byte "Undefined variable",$00 - -; the above error has been tested and works (see code and comments below LAB_1D8B) - -;ERR_UA .byte "Undimensioned array",$00 - -LAB_BMSG .byte $0D,$0A,"Break",$00 -LAB_EMSG .byte " Error",$00 -LAB_LMSG .byte " in line ",$00 -LAB_RMSG .byte $0D,$0A,"Ready",$0D,$0A,$00 - -LAB_IMSG .byte " Extra ignored",$0D,$0A,$00 -LAB_REDO .byte " Redo from start",$0D,$0A,$00 - -AA_end_basic +; The code below was copied and adapted from Lee Davison’s +; code of EhBasic to be ran in MKBASIC (VM65) 6502 emulator. +; Original comments and credits follow: +; +; Enhanced BASIC to assemble under 6502 simulator, $ver 2.22 + +; $E7E1 $E7CF $E7C6 $E7D3 $E7D1 $E7D5 $E7CF $E81E $E825 + +; 2.00 new revision numbers start here +; 2.01 fixed LCASE$() and UCASE$() +; 2.02 new get value routine done +; 2.03 changed RND() to galoise method +; 2.04 fixed SPC() +; 2.05 new get value routine fixed +; 2.06 changed USR() code +; 2.07 fixed STR$() +; 2.08 changed INPUT and READ to remove need for $00 start to input buffer +; 2.09 fixed RND() +; 2.10 integrated missed changes from an earlier version +; 2.20 added ELSE to IF .. THEN and fixed IF .. GOTO to cause error +; 2.21 fixed IF .. THEN RETURN to not cause error +; 2.22 fixed RND() breaking the get byte routine + +; zero page use .. + +LAB_WARM = $00 ; BASIC warm start entry point +Wrmjpl = LAB_WARM+1; BASIC warm start vector jump low byte +Wrmjph = LAB_WARM+2; BASIC warm start vector jump high byte + +Usrjmp = $0A ; USR function JMP address +Usrjpl = Usrjmp+1 ; USR function JMP vector low byte +Usrjph = Usrjmp+2 ; USR function JMP vector high byte +Nullct = $0D ; nulls output after each line +TPos = $0E ; BASIC terminal position byte +TWidth = $0F ; BASIC terminal width byte +Iclim = $10 ; input column limit +Itempl = $11 ; temporary integer low byte +Itemph = Itempl+1 ; temporary integer high byte + +nums_1 = Itempl ; number to bin/hex string convert MSB +nums_2 = nums_1+1 ; number to bin/hex string convert +nums_3 = nums_1+2 ; number to bin/hex string convert LSB + +Srchc = $5B ; search character +Temp3 = Srchc ; temp byte used in number routines +Scnquo = $5C ; scan-between-quotes flag +Asrch = Scnquo ; alt search character + +XOAw_l = Srchc ; eXclusive OR, OR and AND word low byte +XOAw_h = Scnquo ; eXclusive OR, OR and AND word high byte + +Ibptr = $5D ; input buffer pointer +Dimcnt = Ibptr ; # of dimensions +Tindx = Ibptr ; token index + +Defdim = $5E ; default DIM flag +Dtypef = $5F ; data type flag, $FF=string, $00=numeric +Oquote = $60 ; open quote flag (b7) (Flag: DATA scan; LIST quote; memory) +Gclctd = $60 ; garbage collected flag +Sufnxf = $61 ; subscript/FNX flag, 1xxx xxx = FN(0xxx xxx) +Imode = $62 ; input mode flag, $00=INPUT, $80=READ + +Cflag = $63 ; comparison evaluation flag + +TabSiz = $64 ; TAB step size (was input flag) + +next_s = $65 ; next descriptor stack address + + ; these two bytes form a word pointer to the item + ; currently on top of the descriptor stack +last_sl = $66 ; last descriptor stack address low byte +last_sh = $67 ; last descriptor stack address high byte (always $00) + +des_sk = $68 ; descriptor stack start address (temp strings) + +; = $70 ; End of descriptor stack + +ut1_pl = $71 ; utility pointer 1 low byte +ut1_ph = ut1_pl+1 ; utility pointer 1 high byte +ut2_pl = $73 ; utility pointer 2 low byte +ut2_ph = ut2_pl+1 ; utility pointer 2 high byte + +Temp_2 = ut1_pl ; temp byte for block move + +FACt_1 = $75 ; FAC temp mantissa1 +FACt_2 = FACt_1+1 ; FAC temp mantissa2 +FACt_3 = FACt_2+1 ; FAC temp mantissa3 + +dims_l = FACt_2 ; array dimension size low byte +dims_h = FACt_3 ; array dimension size high byte + +TempB = $78 ; temp page 0 byte + +Smeml = $79 ; start of mem low byte (Start-of-Basic) +Smemh = Smeml+1 ; start of mem high byte (Start-of-Basic) +Svarl = $7B ; start of vars low byte (Start-of-Variables) +Svarh = Svarl+1 ; start of vars high byte (Start-of-Variables) +Sarryl = $7D ; var mem end low byte (Start-of-Arrays) +Sarryh = Sarryl+1 ; var mem end high byte (Start-of-Arrays) +Earryl = $7F ; array mem end low byte (End-of-Arrays) +Earryh = Earryl+1 ; array mem end high byte (End-of-Arrays) +Sstorl = $81 ; string storage low byte (String storage (moving down)) +Sstorh = Sstorl+1 ; string storage high byte (String storage (moving down)) +Sutill = $83 ; string utility ptr low byte +Sutilh = Sutill+1 ; string utility ptr high byte +Ememl = $85 ; end of mem low byte (Limit-of-memory) +Ememh = Ememl+1 ; end of mem high byte (Limit-of-memory) +Clinel = $87 ; current line low byte (Basic line number) +Clineh = Clinel+1 ; current line high byte (Basic line number) +Blinel = $89 ; break line low byte (Previous Basic line number) +Blineh = Blinel+1 ; break line high byte (Previous Basic line number) + +Cpntrl = $8B ; continue pointer low byte +Cpntrh = Cpntrl+1 ; continue pointer high byte + +Dlinel = $8D ; current DATA line low byte +Dlineh = Dlinel+1 ; current DATA line high byte + +Dptrl = $8F ; DATA pointer low byte +Dptrh = Dptrl+1 ; DATA pointer high byte + +Rdptrl = $91 ; read pointer low byte +Rdptrh = Rdptrl+1 ; read pointer high byte + +Varnm1 = $93 ; current var name 1st byte +Varnm2 = Varnm1+1 ; current var name 2nd byte + +Cvaral = $95 ; current var address low byte +Cvarah = Cvaral+1 ; current var address high byte + +Frnxtl = $97 ; var pointer for FOR/NEXT low byte +Frnxth = Frnxtl+1 ; var pointer for FOR/NEXT high byte + +Tidx1 = Frnxtl ; temp line index + +Lvarpl = Frnxtl ; let var pointer low byte +Lvarph = Frnxth ; let var pointer high byte + +prstk = $99 ; precedence stacked flag + +comp_f = $9B ; compare function flag, bits 0,1 and 2 used + ; bit 2 set if > + ; bit 1 set if = + ; bit 0 set if < + +func_l = $9C ; function pointer low byte +func_h = func_l+1 ; function pointer high byte + +garb_l = func_l ; garbage collection working pointer low byte +garb_h = func_h ; garbage collection working pointer high byte + +des_2l = $9E ; string descriptor_2 pointer low byte +des_2h = des_2l+1 ; string descriptor_2 pointer high byte + +g_step = $A0 ; garbage collect step size + +Fnxjmp = $A1 ; jump vector for functions +Fnxjpl = Fnxjmp+1 ; functions jump vector low byte +Fnxjph = Fnxjmp+2 ; functions jump vector high byte + +g_indx = Fnxjpl ; garbage collect temp index + +FAC2_r = $A3 ; FAC2 rounding byte + +Adatal = $A4 ; array data pointer low byte +Adatah = Adatal+1 ; array data pointer high byte + +Nbendl = Adatal ; new block end pointer low byte +Nbendh = Adatah ; new block end pointer high byte + +Obendl = $A6 ; old block end pointer low byte +Obendh = Obendl+1 ; old block end pointer high byte + +numexp = $A8 ; string to float number exponent count +expcnt = $A9 ; string to float exponent count + +numbit = numexp ; bit count for array element calculations + +numdpf = $AA ; string to float decimal point flag +expneg = $AB ; string to float eval exponent -ve flag + +Astrtl = numdpf ; array start pointer low byte +Astrth = expneg ; array start pointer high byte + +Histrl = numdpf ; highest string low byte +Histrh = expneg ; highest string high byte + +Baslnl = numdpf ; BASIC search line pointer low byte +Baslnh = expneg ; BASIC search line pointer high byte + +Fvar_l = numdpf ; find/found variable pointer low byte +Fvar_h = expneg ; find/found variable pointer high byte + +Ostrtl = numdpf ; old block start pointer low byte +Ostrth = expneg ; old block start pointer high byte + +Vrschl = numdpf ; variable search pointer low byte +Vrschh = expneg ; variable search pointer high byte + +FAC1_e = $AC ; FAC1 exponent +FAC1_1 = FAC1_e+1 ; FAC1 mantissa1 +FAC1_2 = FAC1_e+2 ; FAC1 mantissa2 +FAC1_3 = FAC1_e+3 ; FAC1 mantissa3 +FAC1_s = FAC1_e+4 ; FAC1 sign (b7) + +str_ln = FAC1_e ; string length +str_pl = FAC1_1 ; string pointer low byte +str_ph = FAC1_2 ; string pointer high byte + +des_pl = FAC1_2 ; string descriptor pointer low byte +des_ph = FAC1_3 ; string descriptor pointer high byte + +mids_l = FAC1_3 ; MID$ string temp length byte + +negnum = $B1 ; string to float eval -ve flag +numcon = $B1 ; series evaluation constant count + +FAC1_o = $B2 ; FAC1 overflow byte + +FAC2_e = $B3 ; FAC2 exponent +FAC2_1 = FAC2_e+1 ; FAC2 mantissa1 +FAC2_2 = FAC2_e+2 ; FAC2 mantissa2 +FAC2_3 = FAC2_e+3 ; FAC2 mantissa3 +FAC2_s = FAC2_e+4 ; FAC2 sign (b7) + +FAC_sc = $B8 ; FAC sign comparison, Acc#1 vs #2 +FAC1_r = $B9 ; FAC1 rounding byte + +ssptr_l = FAC_sc ; string start pointer low byte +ssptr_h = FAC1_r ; string start pointer high byte + +sdescr = FAC_sc ; string descriptor pointer + +csidx = $BA ; line crunch save index +Asptl = csidx ; array size/pointer low byte +Aspth = $BB ; array size/pointer high byte + +Btmpl = Asptl ; BASIC pointer temp low byte +Btmph = Aspth ; BASIC pointer temp low byte + +Cptrl = Asptl ; BASIC pointer temp low byte +Cptrh = Aspth ; BASIC pointer temp low byte + +Sendl = Asptl ; BASIC pointer temp low byte +Sendh = Aspth ; BASIC pointer temp low byte + +LAB_IGBY = $BC ; get next BASIC byte subroutine + +LAB_GBYT = $C2 ; get current BASIC byte subroutine +Bpntrl = $C3 ; BASIC execute (get byte) pointer low byte +Bpntrh = Bpntrl+1 ; BASIC execute (get byte) pointer high byte + +; = $D7 ; end of get BASIC char subroutine + +Rbyte4 = $D8 ; extra PRNG byte +Rbyte1 = Rbyte4+1 ; most significant PRNG byte +Rbyte2 = Rbyte4+2 ; middle PRNG byte +Rbyte3 = Rbyte4+3 ; least significant PRNG byte + +NmiBase = $DC ; NMI handler enabled/setup/triggered flags + ; bit function + ; === ======== + ; 7 interrupt enabled + ; 6 interrupt setup + ; 5 interrupt happened +; = $DD ; NMI handler addr low byte +; = $DE ; NMI handler addr high byte +IrqBase = $DF ; IRQ handler enabled/setup/triggered flags +; = $E0 ; IRQ handler addr low byte +; = $E1 ; IRQ handler addr high byte + +; = $DE ; unused +; = $DF ; unused +; = $E0 ; unused +; = $E1 ; unused +; = $E2 ; unused +; = $E3 ; unused +; = $E4 ; unused +; = $E5 ; unused +; = $E6 ; unused +; = $E7 ; unused +; = $E8 ; unused +; = $E9 ; unused +; = $EA ; unused +; = $EB ; unused +; = $EC ; unused +; = $ED ; unused +; = $EE ; unused + +Decss = $EF ; number to decimal string start +Decssp1 = Decss+1 ; number to decimal string start + +; = $FF ; decimal string end + +; token values needed for BASIC + +; primary command tokens (can start a statement) + +TK_END = $80 ; END token +TK_FOR = TK_END+1 ; FOR token +TK_NEXT = TK_FOR+1 ; NEXT token +TK_DATA = TK_NEXT+1 ; DATA token +TK_INPUT = TK_DATA+1 ; INPUT token +TK_DIM = TK_INPUT+1 ; DIM token +TK_READ = TK_DIM+1 ; READ token +TK_LET = TK_READ+1 ; LET token +TK_DEC = TK_LET+1 ; DEC token +TK_GOTO = TK_DEC+1 ; GOTO token +TK_RUN = TK_GOTO+1 ; RUN token +TK_IF = TK_RUN+1 ; IF token +TK_RESTORE = TK_IF+1 ; RESTORE token +TK_GOSUB = TK_RESTORE+1 ; GOSUB token +TK_RETIRQ = TK_GOSUB+1 ; RETIRQ token +TK_RETNMI = TK_RETIRQ+1 ; RETNMI token +TK_RETURN = TK_RETNMI+1 ; RETURN token +TK_REM = TK_RETURN+1 ; REM token +TK_STOP = TK_REM+1 ; STOP token +TK_ON = TK_STOP+1 ; ON token +TK_NULL = TK_ON+1 ; NULL token +TK_INC = TK_NULL+1 ; INC token +TK_WAIT = TK_INC+1 ; WAIT token +TK_LOAD = TK_WAIT+1 ; LOAD token +TK_SAVE = TK_LOAD+1 ; SAVE token +TK_DEF = TK_SAVE+1 ; DEF token +TK_POKE = TK_DEF+1 ; POKE token +TK_DOKE = TK_POKE+1 ; DOKE token +TK_CALL = TK_DOKE+1 ; CALL token +TK_DO = TK_CALL+1 ; DO token +TK_LOOP = TK_DO+1 ; LOOP token +TK_PRINT = TK_LOOP+1 ; PRINT token +TK_CONT = TK_PRINT+1 ; CONT token +TK_LIST = TK_CONT+1 ; LIST token +TK_CLEAR = TK_LIST+1 ; CLEAR token +TK_NEW = TK_CLEAR+1 ; NEW token +TK_WIDTH = TK_NEW+1 ; WIDTH token +TK_GET = TK_WIDTH+1 ; GET token +TK_SWAP = TK_GET+1 ; SWAP token +TK_BITSET = TK_SWAP+1 ; BITSET token +TK_BITCLR = TK_BITSET+1 ; BITCLR token +TK_IRQ = TK_BITCLR+1 ; IRQ token +TK_NMI = TK_IRQ+1 ; NMI token + +; secondary command tokens, can't start a statement + +TK_TAB = TK_NMI+1 ; TAB token +TK_ELSE = TK_TAB+1 ; ELSE token +TK_TO = TK_ELSE+1 ; TO token +TK_FN = TK_TO+1 ; FN token +TK_SPC = TK_FN+1 ; SPC token +TK_THEN = TK_SPC+1 ; THEN token +TK_NOT = TK_THEN+1 ; NOT token +TK_STEP = TK_NOT+1 ; STEP token +TK_UNTIL = TK_STEP+1 ; UNTIL token +TK_WHILE = TK_UNTIL+1 ; WHILE token +TK_OFF = TK_WHILE+1 ; OFF token + +; opperator tokens + +TK_PLUS = TK_OFF+1 ; + token +TK_MINUS = TK_PLUS+1 ; - token +TK_MUL = TK_MINUS+1 ; * token +TK_DIV = TK_MUL+1 ; / token +TK_POWER = TK_DIV+1 ; ^ token +TK_AND = TK_POWER+1 ; AND token +TK_EOR = TK_AND+1 ; EOR token +TK_OR = TK_EOR+1 ; OR token +TK_RSHIFT = TK_OR+1 ; RSHIFT token +TK_LSHIFT = TK_RSHIFT+1 ; LSHIFT token +TK_GT = TK_LSHIFT+1 ; > token +TK_EQUAL = TK_GT+1 ; = token +TK_LT = TK_EQUAL+1 ; < token + +; functions tokens + +TK_SGN = TK_LT+1 ; SGN token +TK_INT = TK_SGN+1 ; INT token +TK_ABS = TK_INT+1 ; ABS token +TK_USR = TK_ABS+1 ; USR token +TK_FRE = TK_USR+1 ; FRE token +TK_POS = TK_FRE+1 ; POS token +TK_SQR = TK_POS+1 ; SQR token +TK_RND = TK_SQR+1 ; RND token +TK_LOG = TK_RND+1 ; LOG token +TK_EXP = TK_LOG+1 ; EXP token +TK_COS = TK_EXP+1 ; COS token +TK_SIN = TK_COS+1 ; SIN token +TK_TAN = TK_SIN+1 ; TAN token +TK_ATN = TK_TAN+1 ; ATN token +TK_PEEK = TK_ATN+1 ; PEEK token +TK_DEEK = TK_PEEK+1 ; DEEK token +TK_SADD = TK_DEEK+1 ; SADD token +TK_LEN = TK_SADD+1 ; LEN token +TK_STRS = TK_LEN+1 ; STR$ token +TK_VAL = TK_STRS+1 ; VAL token +TK_ASC = TK_VAL+1 ; ASC token +TK_UCASES = TK_ASC+1 ; UCASE$ token +TK_LCASES = TK_UCASES+1 ; LCASE$ token +TK_CHRS = TK_LCASES+1 ; CHR$ token +TK_HEXS = TK_CHRS+1 ; HEX$ token +TK_BINS = TK_HEXS+1 ; BIN$ token +TK_BITTST = TK_BINS+1 ; BITTST token +TK_MAX = TK_BITTST+1 ; MAX token +TK_MIN = TK_MAX+1 ; MIN token +TK_PI = TK_MIN+1 ; PI token +TK_TWOPI = TK_PI+1 ; TWOPI token +TK_VPTR = TK_TWOPI+1 ; VARPTR token +TK_LEFTS = TK_VPTR+1 ; LEFT$ token +TK_RIGHTS = TK_LEFTS+1 ; RIGHT$ token +TK_MIDS = TK_RIGHTS+1 ; MID$ token + +; offsets from a base of X or Y + +PLUS_0 = $00 ; X or Y plus 0 +PLUS_1 = $01 ; X or Y plus 1 +PLUS_2 = $02 ; X or Y plus 2 +PLUS_3 = $03 ; X or Y plus 3 + +LAB_STAK = $0100 ; stack bottom, no offset + +LAB_SKFE = LAB_STAK+$FE + ; flushed stack address +LAB_SKFF = LAB_STAK+$FF + ; flushed stack address + +ccflag = $0200 ; BASIC CTRL-C flag, 00 = enabled, 01 = dis +ccbyte = ccflag+1 ; BASIC CTRL-C byte +ccnull = ccbyte+1 ; BASIC CTRL-C byte timeout + +VEC_CC = ccnull+1 ; ctrl c check vector + +VEC_IN = VEC_CC+2 ; input vector +VEC_OUT = VEC_IN+2 ; output vector +VEC_LD = VEC_OUT+2 ; load vector +VEC_SV = VEC_LD+2 ; save vector + +; Ibuffs can now be anywhere in RAM, ensure that the max length is < $80 + +IRQ_vec = VEC_SV+2 + +Ibuffs = IRQ_vec+$14 ; start of input buffer after IRQ/NMI code +Ibuffe = Ibuffs+$47 ; end of input buffer + + .ORG $FFC0 + +; I/O routines for MKBASIC (V65) emulator. + +CHRIN + LDA $FFE1 ; Read from char IO address, non-blocking + BEQ ECHRIN ; if null, assume no character in buffer + CMP #'a' ; < 'a'? + BCC DCHRIN ; yes, done + CMP #'{' ; >= '{'? + BCS DCHRIN ; yes, done + AND #$5F ; no, convert to upper case +DCHRIN + SEC ; There is character waiting, set CARRY flag + RTS +ECHRIN + CLC ; no character in buffer, clear CARRY + RTS + +CHROUT + STA $FFE0 ; write to char IO address + AND #$FF ; set flags + RTS + + +Ram_base = $0300 ; start of user RAM (set as needed, should be page aligned) +Ram_top = $C000 ; end of user RAM+1 (set as needed, should be page aligned) + +; This start can be changed to suit your system + + *= $C000 + +; BASIC cold start entry point + +; new page 2 initialisation, copy block to ccflag on + +LAB_COLD + CLD + LDY #PG2_TABE-PG2_TABS-1 + ; byte count-1 +LAB_2D13 + LDA PG2_TABS,Y ; get byte + STA ccflag,Y ; store in page 2 + DEY ; decrement count + BPL LAB_2D13 ; loop if not done + + LDX #$FF ; set byte + STX Ibuffs + STX Clineh ; set current line high byte (set immediate mode) + TXS ; reset stack pointer + + LDA #$4C ; code for JMP + STA Fnxjmp ; save for jump vector for functions + +; copy block from LAB_2CEE to $00BC - $00D3 + + LDX #StrTab-LAB_2CEE ; set byte count +LAB_2D4E + LDA LAB_2CEE-1,X ; get byte from table + STA LAB_IGBY-1,X ; save byte in page zero + DEX ; decrement count + BNE LAB_2D4E ; loop if not all done + +; copy block from StrTab to $0000 - $0012 + +LAB_GMEM + LDX #EndTab-StrTab-1 ; set byte count-1 +TabLoop + LDA StrTab,X ; get byte from table + STA PLUS_0,X ; save byte in page zero + DEX ; decrement count + BPL TabLoop ; loop if not all done + +; set-up start values + + LDA #$00 ; clear A + STA NmiBase ; clear NMI handler enabled flag + STA IrqBase ; clear IRQ handler enabled flag + STA FAC1_o ; clear FAC1 overflow byte + STA last_sh ; clear descriptor stack top item pointer high byte + + LDA #$0E ; set default tab size + STA TabSiz ; save it + LDA #$03 ; set garbage collect step size for descriptor stack + STA g_step ; save it + LDX #des_sk ; descriptor stack start + STX next_s ; set descriptor stack pointer + JSR LAB_CRLF ; print CR/LF + LDA #LAB_MSZM ; point to memory size message (high addr) + JSR LAB_18C3 ; print null terminated string from memory + JSR LAB_INLN ; print "? " and get BASIC input + STX Bpntrl ; set BASIC execute pointer low byte + STY Bpntrh ; set BASIC execute pointer high byte + JSR LAB_GBYT ; get last byte back + + BNE LAB_2DAA ; branch if not null (user typed something) + + LDY #$00 ; else clear Y + ; character was null so get memory size the hard way + ; we get here with Y=0 and Itempl/h = Ram_base +LAB_2D93 + INC Itempl ; increment temporary integer low byte + BNE LAB_2D99 ; branch if no overflow + + INC Itemph ; increment temporary integer high byte + LDA Itemph ; get high byte + CMP #>Ram_top ; compare with top of RAM+1 + BEQ LAB_2DB6 ; branch if match (end of user RAM) + +LAB_2D99 + LDA #$55 ; set test byte + STA (Itempl),Y ; save via temporary integer + CMP (Itempl),Y ; compare via temporary integer + BNE LAB_2DB6 ; branch if fail + + ASL ; shift test byte left (now $AA) + STA (Itempl),Y ; save via temporary integer + CMP (Itempl),Y ; compare via temporary integer + BEQ LAB_2D93 ; if ok go do next byte + + BNE LAB_2DB6 ; branch if fail + +LAB_2DAA + JSR LAB_2887 ; get FAC1 from string + LDA FAC1_e ; get FAC1 exponent + CMP #$98 ; compare with exponent = 2^24 + BCS LAB_GMEM ; if too large go try again + + JSR LAB_F2FU ; save integer part of FAC1 in temporary integer + ; (no range check) + +LAB_2DB6 + LDA Itempl ; get temporary integer low byte + LDY Itemph ; get temporary integer high byte + CPY #Ram_top ; compare with top of RAM high byte +; BCC MEM_OK ; branch if < RAM top + +; BNE LAB_GMEM ; if too large go try again + ; else was = so compare low bytes +; CMP #Ram_base ; set start addr high byte + STY Smeml ; save start of mem low byte + STX Smemh ; save start of mem high byte + +; this line is only needed if Ram_base is not $xx00 + +; LDY #$00 ; clear Y + TYA ; clear A + STA (Smeml),Y ; clear first byte + INC Smeml ; increment start of mem low byte + +; these two lines are only needed if Ram_base is $xxFF + +; BNE LAB_2E05 ; branch if no rollover + +; INC Smemh ; increment start of mem high byte +LAB_2E05 + JSR LAB_CRLF ; print CR/LF + JSR LAB_1463 ; do "NEW" and "CLEAR" + LDA Ememl ; get end of mem low byte + SEC ; set carry for subtract + SBC Smeml ; subtract start of mem low byte + TAX ; copy to X + LDA Ememh ; get end of mem high byte + SBC Smemh ; subtract start of mem high byte + JSR LAB_295E ; print XA as unsigned integer (bytes free) + LDA #LAB_SMSG ; point to sign-on message (high addr) + JSR LAB_18C3 ; print null terminated string from memory + LDA #LAB_1274 ; warm start vector high byte + STA Wrmjpl ; save warm start vector low byte + STY Wrmjph ; save warm start vector high byte + JMP (Wrmjpl) ; go do warm start + +; open up space in memory +; move (Ostrtl)-(Obendl) to new block ending at (Nbendl) + +; Nbendl,Nbendh - new block end address (A/Y) +; Obendl,Obendh - old block end address +; Ostrtl,Ostrth - old block start address + +; returns with .. + +; Nbendl,Nbendh - new block start address (high byte - $100) +; Obendl,Obendh - old block start address (high byte - $100) +; Ostrtl,Ostrth - old block start address (unchanged) + +LAB_11CF + JSR LAB_121F ; check available memory, "Out of memory" error if no room + ; addr to check is in AY (low/high) + STA Earryl ; save new array mem end low byte + STY Earryh ; save new array mem end high byte + +; open up space in memory +; move (Ostrtl)-(Obendl) to new block ending at (Nbendl) +; don't set array end + +LAB_11D6 + SEC ; set carry for subtract + LDA Obendl ; get block end low byte + SBC Ostrtl ; subtract block start low byte + TAY ; copy MOD(block length/$100) byte to Y + LDA Obendh ; get block end high byte + SBC Ostrth ; subtract block start high byte + TAX ; copy block length high byte to X + INX ; +1 to allow for count=0 exit + TYA ; copy block length low byte to A + BEQ LAB_120A ; branch if length low byte=0 + + ; block is (X-1)*256+Y bytes, do the Y bytes first + + SEC ; set carry for add + 1, two's complement + EOR #$FF ; invert low byte for subtract + ADC Obendl ; add block end low byte + + STA Obendl ; save corrected old block end low byte + BCS LAB_11F3 ; branch if no underflow + + DEC Obendh ; else decrement block end high byte + SEC ; set carry for add + 1, two's complement +LAB_11F3 + TYA ; get MOD(block length/$100) byte + EOR #$FF ; invert low byte for subtract + ADC Nbendl ; add destination end low byte + STA Nbendl ; save modified new block end low byte + BCS LAB_1203 ; branch if no underflow + + DEC Nbendh ; else decrement block end high byte + BCC LAB_1203 ; branch always + +LAB_11FF + LDA (Obendl),Y ; get byte from source + STA (Nbendl),Y ; copy byte to destination +LAB_1203 + DEY ; decrement index + BNE LAB_11FF ; loop until Y=0 + + ; now do Y=0 indexed byte + LDA (Obendl),Y ; get byte from source + STA (Nbendl),Y ; save byte to destination +LAB_120A + DEC Obendh ; decrement source pointer high byte + DEC Nbendh ; decrement destination pointer high byte + DEX ; decrement block count + BNE LAB_1203 ; loop until count = $0 + + RTS + +; check room on stack for A bytes +; stack too deep? do OM error + +LAB_1212 + STA TempB ; save result in temp byte + TSX ; copy stack + CPX TempB ; compare new "limit" with stack + BCC LAB_OMER ; if stack < limit do "Out of memory" error then warm start + + RTS + +; check available memory, "Out of memory" error if no room +; addr to check is in AY (low/high) + +LAB_121F + CPY Sstorh ; compare bottom of string mem high byte + BCC LAB_124B ; if less then exit (is ok) + + BNE LAB_1229 ; skip next test if greater (tested <) + + ; high byte was =, now do low byte + CMP Sstorl ; compare with bottom of string mem low byte + BCC LAB_124B ; if less then exit (is ok) + + ; addr is > string storage ptr (oops!) +LAB_1229 + PHA ; push addr low byte + LDX #$08 ; set index to save Adatal to expneg inclusive + TYA ; copy addr high byte (to push on stack) + + ; save misc numeric work area +LAB_122D + PHA ; push byte + LDA Adatal-1,X ; get byte from Adatal to expneg ( ,$00 not pushed) + DEX ; decrement index + BPL LAB_122D ; loop until all done + + JSR LAB_GARB ; garbage collection routine + + ; restore misc numeric work area + LDX #$00 ; clear the index to restore bytes +LAB_1238 + PLA ; pop byte + STA Adatal,X ; save byte to Adatal to expneg + INX ; increment index + CPX #$08 ; compare with end + 1 + BMI LAB_1238 ; loop if more to do + + PLA ; pop addr high byte + TAY ; copy back to Y + PLA ; pop addr low byte + CPY Sstorh ; compare bottom of string mem high byte + BCC LAB_124B ; if less then exit (is ok) + + BNE LAB_OMER ; if greater do "Out of memory" error then warm start + + ; high byte was =, now do low byte + CMP Sstorl ; compare with bottom of string mem low byte + BCS LAB_OMER ; if >= do "Out of memory" error then warm start + + ; ok exit, carry clear +LAB_124B + RTS + +; do "Out of memory" error then warm start + +LAB_OMER + LDX #$0C ; error code $0C ("Out of memory" error) + +; do error #X, then warm start + +LAB_XERR + JSR LAB_CRLF ; print CR/LF + + LDA LAB_BAER,X ; get error message pointer low byte + LDY LAB_BAER+1,X ; get error message pointer high byte + JSR LAB_18C3 ; print null terminated string from memory + + JSR LAB_1491 ; flush stack and clear continue flag + LDA #LAB_EMSG ; point to " Error" high addr +LAB_1269 + JSR LAB_18C3 ; print null terminated string from memory + LDY Clineh ; get current line high byte + INY ; increment it + BEQ LAB_1274 ; go do warm start (was immediate mode) + + ; else print line number + JSR LAB_2953 ; print " in line [LINE #]" + +; BASIC warm start entry point +; wait for Basic command + +LAB_1274 + ; clear ON IRQ/NMI bytes + LDA #$00 ; clear A + STA IrqBase ; clear enabled byte + STA NmiBase ; clear enabled byte + LDA #LAB_RMSG ; point to "Ready" message high byte + + JSR LAB_18C3 ; go do print string + CLC + +; wait for Basic command (no "Ready") + +LAB_127D + JSR LAB_1357 ; call for BASIC input +LAB_1280 + STX Bpntrl ; set BASIC execute pointer low byte + STY Bpntrh ; set BASIC execute pointer high byte + JSR LAB_GBYT ; scan memory + BEQ LAB_127D ; loop while null + +; got to interpret input line now .. + + LDX #$FF ; current line to null value + STX Clineh ; set current line high byte + BCC LAB_1295 ; branch if numeric character (handle new BASIC line) + + ; no line number .. immediate mode + JSR LAB_13A6 ; crunch keywords into Basic tokens + JMP LAB_15F6 ; go scan and interpret code + +; handle new BASIC line + +LAB_1295 + JSR LAB_GFPN ; get fixed-point number into temp integer + JSR LAB_13A6 ; crunch keywords into Basic tokens + STY Ibptr ; save index pointer to end of crunched line + JSR LAB_SSLN ; search BASIC for temp integer line number + BCC LAB_12E6 ; branch if not found + + ; aroooogah! line # already exists! delete it + LDY #$01 ; set index to next line pointer high byte + LDA (Baslnl),Y ; get next line pointer high byte + STA ut1_ph ; save it + LDA Svarl ; get start of vars low byte + STA ut1_pl ; save it + LDA Baslnh ; get found line pointer high byte + STA ut2_ph ; save it + LDA Baslnl ; get found line pointer low byte + DEY ; decrement index + SBC (Baslnl),Y ; subtract next line pointer low byte + CLC ; clear carry for add + ADC Svarl ; add start of vars low byte + STA Svarl ; save new start of vars low byte + STA ut2_pl ; save destination pointer low byte + LDA Svarh ; get start of vars high byte + ADC #$FF ; -1 + carry + STA Svarh ; save start of vars high byte + SBC Baslnh ; subtract found line pointer high byte + TAX ; copy to block count + SEC ; set carry for subtract + LDA Baslnl ; get found line pointer low byte + SBC Svarl ; subtract start of vars low byte + TAY ; copy to bytes in first block count + BCS LAB_12D0 ; branch if overflow + + INX ; increment block count (correct for =0 loop exit) + DEC ut2_ph ; decrement destination high byte +LAB_12D0 + CLC ; clear carry for add + ADC ut1_pl ; add source pointer low byte + BCC LAB_12D8 ; branch if no overflow + + DEC ut1_ph ; else decrement source pointer high byte + CLC ; clear carry + + ; close up memory to delete old line +LAB_12D8 + LDA (ut1_pl),Y ; get byte from source + STA (ut2_pl),Y ; copy to destination + INY ; increment index + BNE LAB_12D8 ; while <> 0 do this block + + INC ut1_ph ; increment source pointer high byte + INC ut2_ph ; increment destination pointer high byte + DEX ; decrement block count + BNE LAB_12D8 ; loop until all done + + ; got new line in buffer and no existing same # +LAB_12E6 + LDA Ibuffs ; get byte from start of input buffer + BEQ LAB_1319 ; if null line just go flush stack/vars and exit + + ; got new line and it isn't empty line + LDA Ememl ; get end of mem low byte + LDY Ememh ; get end of mem high byte + STA Sstorl ; set bottom of string space low byte + STY Sstorh ; set bottom of string space high byte + LDA Svarl ; get start of vars low byte (end of BASIC) + STA Obendl ; save old block end low byte + LDY Svarh ; get start of vars high byte (end of BASIC) + STY Obendh ; save old block end high byte + ADC Ibptr ; add input buffer pointer (also buffer length) + BCC LAB_1301 ; branch if no overflow from add + + INY ; else increment high byte +LAB_1301 + STA Nbendl ; save new block end low byte (move to, low byte) + STY Nbendh ; save new block end high byte + JSR LAB_11CF ; open up space in memory + ; old start pointer Ostrtl,Ostrth set by the find line call + LDA Earryl ; get array mem end low byte + LDY Earryh ; get array mem end high byte + STA Svarl ; save start of vars low byte + STY Svarh ; save start of vars high byte + LDY Ibptr ; get input buffer pointer (also buffer length) + DEY ; adjust for loop type +LAB_1311 + LDA Ibuffs-4,Y ; get byte from crunched line + STA (Baslnl),Y ; save it to program memory + DEY ; decrement count + CPY #$03 ; compare with first byte-1 + BNE LAB_1311 ; continue while count <> 3 + + LDA Itemph ; get line # high byte + STA (Baslnl),Y ; save it to program memory + DEY ; decrement count + LDA Itempl ; get line # low byte + STA (Baslnl),Y ; save it to program memory + DEY ; decrement count + LDA #$FF ; set byte to allow chain rebuild. if you didn't set this + ; byte then a zero already here would stop the chain rebuild + ; as it would think it was the [EOT] marker. + STA (Baslnl),Y ; save it to program memory + +LAB_1319 + JSR LAB_1477 ; reset execution to start, clear vars and flush stack + LDX Smeml ; get start of mem low byte + LDA Smemh ; get start of mem high byte + LDY #$01 ; index to high byte of next line pointer +LAB_1325 + STX ut1_pl ; set line start pointer low byte + STA ut1_ph ; set line start pointer high byte + LDA (ut1_pl),Y ; get it + BEQ LAB_133E ; exit if end of program + +; rebuild chaining of Basic lines + + LDY #$04 ; point to first code byte of line + ; there is always 1 byte + [EOL] as null entries are deleted +LAB_1330 + INY ; next code byte + LDA (ut1_pl),Y ; get byte + BNE LAB_1330 ; loop if not [EOL] + + SEC ; set carry for add + 1 + TYA ; copy end index + ADC ut1_pl ; add to line start pointer low byte + TAX ; copy to X + LDY #$00 ; clear index, point to this line's next line pointer + STA (ut1_pl),Y ; set next line pointer low byte + TYA ; clear A + ADC ut1_ph ; add line start pointer high byte + carry + INY ; increment index to high byte + STA (ut1_pl),Y ; save next line pointer low byte + BCC LAB_1325 ; go do next line, branch always, carry clear + + +LAB_133E + JMP LAB_127D ; else we just wait for Basic command, no "Ready" + +; print "? " and get BASIC input + +LAB_INLN + JSR LAB_18E3 ; print "?" character + JSR LAB_18E0 ; print " " + BNE LAB_1357 ; call for BASIC input and return + +; receive line from keyboard + + ; $08 as delete key (BACKSPACE on standard keyboard) +LAB_134B + JSR LAB_PRNA ; go print the character + DEX ; decrement the buffer counter (delete) + .byte $2C ; make LDX into BIT abs + +; call for BASIC input (main entry point) + +LAB_1357 + LDX #$00 ; clear BASIC line buffer pointer +LAB_1359 + JSR V_INPT ; call scan input device + BCC LAB_1359 ; loop if no byte + + BEQ LAB_1359 ; loop until valid input (ignore NULLs) + + CMP #$07 ; compare with [BELL] + BEQ LAB_1378 ; branch if [BELL] + + CMP #$0D ; compare with [CR] + BEQ LAB_1384 ; do CR/LF exit if [CR] + + CPX #$00 ; compare pointer with $00 + BNE LAB_1374 ; branch if not empty + +; next two lines ignore any non print character and [SPACE] if input buffer empty + + CMP #$21 ; compare with [SP]+1 + BCC LAB_1359 ; if < ignore character + +LAB_1374 + CMP #$08 ; compare with [BACKSPACE] (delete last character) + BEQ LAB_134B ; go delete last character + +LAB_1378 + CPX #Ibuffe-Ibuffs ; compare character count with max + BCS LAB_138E ; skip store and do [BELL] if buffer full + + STA Ibuffs,X ; else store in buffer + INX ; increment pointer +LAB_137F + JSR LAB_PRNA ; go print the character + BNE LAB_1359 ; always loop for next character + +LAB_1384 + JMP LAB_1866 ; do CR/LF exit to BASIC + +; announce buffer full + +LAB_138E + LDA #$07 ; [BELL] character into A + BNE LAB_137F ; go print the [BELL] but ignore input character + ; branch always + +; crunch keywords into Basic tokens +; position independent buffer version .. +; faster, dictionary search version .... + +LAB_13A6 + LDY #$FF ; set save index (makes for easy math later) + + SEC ; set carry for subtract + LDA Bpntrl ; get basic execute pointer low byte + SBC #= go save byte then continue crunching + + CMP #'<' ; compare with "<" + BCS LAB_13CC ; if >= go crunch now + + CMP #'0' ; compare with "0" + BCS LAB_13EC ; if >= go save byte then continue crunching + + STA Scnquo ; save buffer byte as search character + CMP #$22 ; is it quote character? + BEQ LAB_1410 ; branch if so (copy quoted string) + + CMP #'*' ; compare with "*" + BCC LAB_13EC ; if < go save byte then continue crunching + + ; else crunch now +LAB_13CC + BIT Oquote ; get open quote/DATA token flag + BVS LAB_13EC ; branch if b6 of Oquote set (was DATA) + ; go save byte then continue crunching + + STX TempB ; save buffer read index + STY csidx ; copy buffer save index + LDY #TAB_1STC ; get keyword first character table high address + STY ut2_ph ; save pointer high byte + LDY #$00 ; clear table pointer + +LAB_13D0 + CMP (ut2_pl),Y ; compare with keyword first character table byte + BEQ LAB_13D1 ; go do word_table_chr if match + + BCC LAB_13EA ; if < keyword first character table byte go restore + ; Y and save to crunched + + INY ; else increment pointer + BNE LAB_13D0 ; and loop (branch always) + +; have matched first character of some keyword + +LAB_13D1 + TYA ; copy matching index + ASL ; *2 (bytes per pointer) + TAX ; copy to new index + LDA TAB_CHRT,X ; get keyword table pointer low byte + STA ut2_pl ; save pointer low byte + LDA TAB_CHRT+1,X ; get keyword table pointer high byte + STA ut2_ph ; save pointer high byte + + LDY #$FF ; clear table pointer (make -1 for start) + + LDX TempB ; restore buffer read index + +LAB_13D6 + INY ; next table byte + LDA (ut2_pl),Y ; get byte from table +LAB_13D8 + BMI LAB_13EA ; all bytes matched so go save token + + INX ; next buffer byte + CMP Ibuffs,X ; compare with byte from input buffer + BEQ LAB_13D6 ; go compare next if match + + BNE LAB_1417 ; branch if >< (not found keyword) + +LAB_13EA + LDY csidx ; restore save index + + ; save crunched to output +LAB_13EC + INX ; increment buffer index (to next input byte) + INY ; increment save index (to next output byte) + STA Ibuffs,Y ; save byte to output + CMP #$00 ; set the flags, set carry + BEQ LAB_142A ; do exit if was null [EOL] + + ; A holds token or byte here + SBC #':' ; subtract ":" (carry set by CMP #00) + BEQ LAB_13FF ; branch if it was ":" (is now $00) + + ; A now holds token-$3A + CMP #TK_DATA-$3A ; compare with DATA token - $3A + BNE LAB_1401 ; branch if not DATA + + ; token was : or DATA +LAB_13FF + STA Oquote ; save token-$3A (clear for ":", TK_DATA-$3A for DATA) +LAB_1401 + EOR #TK_REM-$3A ; effectively subtract REM token offset + BNE LAB_13AC ; If wasn't REM then go crunch rest of line + + STA Asrch ; else was REM so set search for [EOL] + + ; loop for REM, "..." etc. +LAB_1408 + LDA Ibuffs,X ; get byte from input buffer + BEQ LAB_13EC ; branch if null [EOL] + + CMP Asrch ; compare with stored character + BEQ LAB_13EC ; branch if match (end quote) + + ; entry for copy string in quotes, don't crunch +LAB_1410 + INY ; increment buffer save index + STA Ibuffs,Y ; save byte to output + INX ; increment buffer read index + BNE LAB_1408 ; loop while <> 0 (should never be 0!) + + ; not found keyword this go +LAB_1417 + LDX TempB ; compare has failed, restore buffer index (start byte!) + + ; now find the end of this word in the table +LAB_141B + LDA (ut2_pl),Y ; get table byte + PHP ; save status + INY ; increment table index + PLP ; restore byte status + BPL LAB_141B ; if not end of keyword go do next + + LDA (ut2_pl),Y ; get byte from keyword table + BNE LAB_13D8 ; go test next word if not zero byte (end of table) + + ; reached end of table with no match + LDA Ibuffs,X ; restore byte from input buffer + BPL LAB_13EA ; branch always (all bytes in buffer are $00-$7F) + ; go save byte in output and continue crunching + + ; reached [EOL] +LAB_142A + INY ; increment pointer + INY ; increment pointer (makes it next line pointer high byte) + STA Ibuffs,Y ; save [EOL] (marks [EOT] in immediate mode) + INY ; adjust for line copy + INY ; adjust for line copy + INY ; adjust for line copy + DEC Bpntrl ; allow for increment (change if buffer starts at $xxFF) + RTS + +; search Basic for temp integer line number from start of mem + +LAB_SSLN + LDA Smeml ; get start of mem low byte + LDX Smemh ; get start of mem high byte + +; search Basic for temp integer line number from AX +; returns carry set if found +; returns Baslnl/Baslnh pointer to found or next higher (not found) line + +; old 541 new 507 + +LAB_SHLN + LDY #$01 ; set index + STA Baslnl ; save low byte as current + STX Baslnh ; save high byte as current + LDA (Baslnl),Y ; get pointer high byte from addr + BEQ LAB_145F ; pointer was zero so we're done, do 'not found' exit + + LDY #$03 ; set index to line # high byte + LDA (Baslnl),Y ; get line # high byte + DEY ; decrement index (point to low byte) + CMP Itemph ; compare with temporary integer high byte + BNE LAB_1455 ; if <> skip low byte check + + LDA (Baslnl),Y ; get line # low byte + CMP Itempl ; compare with temporary integer low byte +LAB_1455 + BCS LAB_145E ; else if temp < this line, exit (passed line#) + +LAB_1456 + DEY ; decrement index to next line ptr high byte + LDA (Baslnl),Y ; get next line pointer high byte + TAX ; copy to X + DEY ; decrement index to next line ptr low byte + LDA (Baslnl),Y ; get next line pointer low byte + BCC LAB_SHLN ; go search for line # in temp (Itempl/Itemph) from AX + ; (carry always clear) + +LAB_145E + BEQ LAB_1460 ; exit if temp = found line #, carry is set + +LAB_145F + CLC ; clear found flag +LAB_1460 + RTS + +; perform NEW + +LAB_NEW + BNE LAB_1460 ; exit if not end of statement (to do syntax error) + +LAB_1463 + LDA #$00 ; clear A + TAY ; clear Y + STA (Smeml),Y ; clear first line, next line pointer, low byte + INY ; increment index + STA (Smeml),Y ; clear first line, next line pointer, high byte + CLC ; clear carry + LDA Smeml ; get start of mem low byte + ADC #$02 ; calculate end of BASIC low byte + STA Svarl ; save start of vars low byte + LDA Smemh ; get start of mem high byte + ADC #$00 ; add any carry + STA Svarh ; save start of vars high byte + +; reset execution to start, clear vars and flush stack + +LAB_1477 + CLC ; clear carry + LDA Smeml ; get start of mem low byte + ADC #$FF ; -1 + STA Bpntrl ; save BASIC execute pointer low byte + LDA Smemh ; get start of mem high byte + ADC #$FF ; -1+carry + STA Bpntrh ; save BASIC execute pointer high byte + +; "CLEAR" command gets here + +LAB_147A + LDA Ememl ; get end of mem low byte + LDY Ememh ; get end of mem high byte + STA Sstorl ; set bottom of string space low byte + STY Sstorh ; set bottom of string space high byte + LDA Svarl ; get start of vars low byte + LDY Svarh ; get start of vars high byte + STA Sarryl ; save var mem end low byte + STY Sarryh ; save var mem end high byte + STA Earryl ; save array mem end low byte + STY Earryh ; save array mem end high byte + JSR LAB_161A ; perform RESTORE command + +; flush stack and clear continue flag + +LAB_1491 + LDX #des_sk ; set descriptor stack pointer + STX next_s ; save descriptor stack pointer + PLA ; pull return address low byte + TAX ; copy return address low byte + PLA ; pull return address high byte + STX LAB_SKFE ; save to cleared stack + STA LAB_SKFF ; save to cleared stack + LDX #$FD ; new stack pointer + TXS ; reset stack + LDA #$00 ; clear byte + STA Cpntrh ; clear continue pointer high byte + STA Sufnxf ; clear subscript/FNX flag +LAB_14A6 + RTS + +; perform CLEAR + +LAB_CLEAR + BEQ LAB_147A ; if no following token go do "CLEAR" + + ; else there was a following token (go do syntax error) + RTS + +; perform LIST [n][-m] +; bigger, faster version (a _lot_ faster) + +LAB_LIST + BCC LAB_14BD ; branch if next character numeric (LIST n..) + + BEQ LAB_14BD ; branch if next character [NULL] (LIST) + + CMP #TK_MINUS ; compare with token for - + BNE LAB_14A6 ; exit if not - (LIST -m) + + ; LIST [[n][-m]] + ; this bit sets the n , if present, as the start and end +LAB_14BD + JSR LAB_GFPN ; get fixed-point number into temp integer + JSR LAB_SSLN ; search BASIC for temp integer line number + ; (pointer in Baslnl/Baslnh) + JSR LAB_GBYT ; scan memory + BEQ LAB_14D4 ; branch if no more characters + + ; this bit checks the - is present + CMP #TK_MINUS ; compare with token for - + BNE LAB_1460 ; return if not "-" (will be Syntax error) + + ; LIST [n]-m + ; the - was there so set m as the end value + JSR LAB_IGBY ; increment and scan memory + JSR LAB_GFPN ; get fixed-point number into temp integer + BNE LAB_1460 ; exit if not ok + +LAB_14D4 + LDA Itempl ; get temporary integer low byte + ORA Itemph ; OR temporary integer high byte + BNE LAB_14E2 ; branch if start set + + LDA #$FF ; set for -1 + STA Itempl ; set temporary integer low byte + STA Itemph ; set temporary integer high byte +LAB_14E2 + LDY #$01 ; set index for line + STY Oquote ; clear open quote flag + JSR LAB_CRLF ; print CR/LF + LDA (Baslnl),Y ; get next line pointer high byte + ; pointer initially set by search at LAB_14BD + BEQ LAB_152B ; if null all done so exit + JSR LAB_1629 ; do CRTL-C check vector + + INY ; increment index for line + LDA (Baslnl),Y ; get line # low byte + TAX ; copy to X + INY ; increment index + LDA (Baslnl),Y ; get line # high byte + CMP Itemph ; compare with temporary integer high byte + BNE LAB_14FF ; branch if no high byte match + + CPX Itempl ; compare with temporary integer low byte + BEQ LAB_1501 ; branch if = last line to do (< will pass next branch) + +LAB_14FF ; else .. + BCS LAB_152B ; if greater all done so exit + +LAB_1501 + STY Tidx1 ; save index for line + JSR LAB_295E ; print XA as unsigned integer + LDA #$20 ; space is the next character +LAB_1508 + LDY Tidx1 ; get index for line + AND #$7F ; mask top out bit of character +LAB_150C + JSR LAB_PRNA ; go print the character + CMP #$22 ; was it " character + BNE LAB_1519 ; branch if not + + ; we are either entering or leaving a pair of quotes + LDA Oquote ; get open quote flag + EOR #$FF ; toggle it + STA Oquote ; save it back +LAB_1519 + INY ; increment index + LDA (Baslnl),Y ; get next byte + BNE LAB_152E ; branch if not [EOL] (go print character) + TAY ; else clear index + LDA (Baslnl),Y ; get next line pointer low byte + TAX ; copy to X + INY ; increment index + LDA (Baslnl),Y ; get next line pointer high byte + STX Baslnl ; set pointer to line low byte + STA Baslnh ; set pointer to line high byte + BNE LAB_14E2 ; go do next line if not [EOT] + ; else .. +LAB_152B + RTS + +LAB_152E + BPL LAB_150C ; just go print it if not token byte + + ; else was token byte so uncrunch it (maybe) + BIT Oquote ; test the open quote flag + BMI LAB_150C ; just go print character if open quote set + + LDX #>LAB_KEYT ; get table address high byte + ASL ; *2 + ASL ; *4 + BCC LAB_152F ; branch if no carry + + INX ; else increment high byte + CLC ; clear carry for add +LAB_152F + ADC #LAB_159F ; set return address high byte + STA ut1_pl ; save return address low byte + STY ut1_ph ; save return address high byte + JMP LAB_1B66 ; round FAC1 and put on stack (returns to next instruction) + +LAB_159F + LDA #LAB_259C ; set 1 pointer high addr + JSR LAB_UFAC ; unpack memory (AY) into FAC1 + JSR LAB_GBYT ; scan memory + CMP #TK_STEP ; compare with STEP token + BNE LAB_15B3 ; jump if not "STEP" + + ;.was step so .. + JSR LAB_IGBY ; increment and scan memory + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch +LAB_15B3 + JSR LAB_27CA ; return A=FF,C=1/-ve A=01,C=0/+ve + STA FAC1_s ; set FAC1 sign (b7) + ; this is +1 for +ve step and -1 for -ve step, in NEXT we + ; compare the FOR value and the TO value and return +1 if + ; FOR > TO, 0 if FOR = TO and -1 if FOR < TO. the value + ; here (+/-1) is then compared to that result and if they + ; are the same (+ve and FOR > TO or -ve and FOR < TO) then + ; the loop is done + JSR LAB_1B5B ; push sign, round FAC1 and put on stack + LDA Frnxth ; get var pointer for FOR/NEXT high byte + PHA ; push on stack + LDA Frnxtl ; get var pointer for FOR/NEXT low byte + PHA ; push on stack + LDA #TK_FOR ; get FOR token + PHA ; push on stack + +; interpreter inner loop + +LAB_15C2 + JSR LAB_1629 ; do CRTL-C check vector + LDA Bpntrl ; get BASIC execute pointer low byte + LDY Bpntrh ; get BASIC execute pointer high byte + + LDX Clineh ; continue line is $FFxx for immediate mode + ; ($00xx for RUN from immediate mode) + INX ; increment it (now $00 if immediate mode) + BEQ LAB_15D1 ; branch if null (immediate mode) + + STA Cpntrl ; save continue pointer low byte + STY Cpntrh ; save continue pointer high byte +LAB_15D1 + LDY #$00 ; clear index + LDA (Bpntrl),Y ; get next byte + BEQ LAB_15DC ; branch if null [EOL] + + CMP #':' ; compare with ":" + BEQ LAB_15F6 ; branch if = (statement separator) + +LAB_15D9 + JMP LAB_SNER ; else syntax error then warm start + + ; have reached [EOL] +LAB_15DC + LDY #$02 ; set index + LDA (Bpntrl),Y ; get next line pointer high byte + CLC ; clear carry for no "BREAK" message + BEQ LAB_1651 ; if null go to immediate mode (was immediate or [EOT] + ; marker) + + INY ; increment index + LDA (Bpntrl),Y ; get line # low byte + STA Clinel ; save current line low byte + INY ; increment index + LDA (Bpntrl),Y ; get line # high byte + STA Clineh ; save current line high byte + TYA ; A now = 4 + ADC Bpntrl ; add BASIC execute pointer low byte + STA Bpntrl ; save BASIC execute pointer low byte + BCC LAB_15F6 ; branch if no overflow + + INC Bpntrh ; else increment BASIC execute pointer high byte +LAB_15F6 + JSR LAB_IGBY ; increment and scan memory + +LAB_15F9 + JSR LAB_15FF ; go interpret BASIC code from (Bpntrl) + +LAB_15FC + JMP LAB_15C2 ; loop + +; interpret BASIC code from (Bpntrl) + +LAB_15FF + BEQ LAB_1628 ; exit if zero [EOL] + +LAB_1602 + ASL ; *2 bytes per vector and normalise token + BCS LAB_1609 ; branch if was token + + JMP LAB_LET ; else go do implied LET + +LAB_1609 + CMP #[TK_TAB-$80]*2 ; compare normalised token * 2 with TAB + BCS LAB_15D9 ; branch if A>=TAB (do syntax error then warm start) + ; only tokens before TAB can start a line + TAY ; copy to index + LDA LAB_CTBL+1,Y ; get vector high byte + PHA ; onto stack + LDA LAB_CTBL,Y ; get vector low byte + PHA ; onto stack + JMP LAB_IGBY ; jump to increment and scan memory + ; then "return" to vector + +; CTRL-C check jump. this is called as a subroutine but exits back via a jump if a +; key press is detected. + +LAB_1629 + JMP (VEC_CC) ; ctrl c check vector + +; if there was a key press it gets back here .. + +LAB_1636 + CMP #$03 ; compare with CTRL-C + +; perform STOP + +LAB_STOP + BCS LAB_163B ; branch if token follows STOP + ; else just END +; END + +LAB_END + CLC ; clear the carry, indicate a normal program end +LAB_163B + BNE LAB_167A ; if wasn't CTRL-C or there is a following byte return + + LDA Bpntrh ; get the BASIC execute pointer high byte + EOR #>Ibuffs ; compare with buffer address high byte (Cb unchanged) + BEQ LAB_164F ; branch if the BASIC pointer is in the input buffer + ; (can't continue in immediate mode) + + ; else .. + EOR #>Ibuffs ; correct the bits + LDY Bpntrl ; get BASIC execute pointer low byte + STY Cpntrl ; save continue pointer low byte + STA Cpntrh ; save continue pointer high byte +LAB_1647 + LDA Clinel ; get current line low byte + LDY Clineh ; get current line high byte + STA Blinel ; save break line low byte + STY Blineh ; save break line high byte +LAB_164F + PLA ; pull return address low + PLA ; pull return address high +LAB_1651 + BCC LAB_165E ; if was program end just do warm start + + ; else .. + LDA #LAB_BMSG ; point to "Break" high byte + JMP LAB_1269 ; print "Break" and do warm start + +LAB_165E + JMP LAB_1274 ; go do warm start + +; perform RESTORE + +LAB_RESTORE + BNE LAB_RESTOREn ; branch if next character not null (RESTORE n) + +LAB_161A + SEC ; set carry for subtract + LDA Smeml ; get start of mem low byte + SBC #$01 ; -1 + LDY Smemh ; get start of mem high byte + BCS LAB_1624 ; branch if no underflow + +LAB_uflow + DEY ; else decrement high byte +LAB_1624 + STA Dptrl ; save DATA pointer low byte + STY Dptrh ; save DATA pointer high byte +LAB_1628 + RTS + + ; is RESTORE n +LAB_RESTOREn + JSR LAB_GFPN ; get fixed-point number into temp integer + JSR LAB_SNBL ; scan for next BASIC line + LDA Clineh ; get current line high byte + CMP Itemph ; compare with temporary integer high byte + BCS LAB_reset_search ; branch if >= (start search from beginning) + + TYA ; else copy line index to A + SEC ; set carry (+1) + ADC Bpntrl ; add BASIC execute pointer low byte + LDX Bpntrh ; get BASIC execute pointer high byte + BCC LAB_go_search ; branch if no overflow to high byte + + INX ; increment high byte + BCS LAB_go_search ; branch always (can never be carry clear) + +; search for line # in temp (Itempl/Itemph) from start of mem pointer (Smeml) + +LAB_reset_search + LDA Smeml ; get start of mem low byte + LDX Smemh ; get start of mem high byte + +; search for line # in temp (Itempl/Itemph) from (AX) + +LAB_go_search + + JSR LAB_SHLN ; search Basic for temp integer line number from AX + BCS LAB_line_found ; if carry set go set pointer + + JMP LAB_16F7 ; else go do "Undefined statement" error + +LAB_line_found + ; carry already set for subtract + LDA Baslnl ; get pointer low byte + SBC #$01 ; -1 + LDY Baslnh ; get pointer high byte + BCS LAB_1624 ; branch if no underflow (save DATA pointer and return) + + BCC LAB_uflow ; else decrement high byte then save DATA pointer and + ; return (branch always) + +; perform NULL + +LAB_NULL + JSR LAB_GTBY ; get byte parameter + STX Nullct ; save new NULL count +LAB_167A + RTS + +; perform CONT + +LAB_CONT + BNE LAB_167A ; if following byte exit to do syntax error + + LDY Cpntrh ; get continue pointer high byte + BNE LAB_166C ; go do continue if we can + + LDX #$1E ; error code $1E ("Can't continue" error) + JMP LAB_XERR ; do error #X, then warm start + + ; we can continue so .. +LAB_166C + LDA #TK_ON ; set token for ON + JSR LAB_IRQ ; set IRQ flags + LDA #TK_ON ; set token for ON + JSR LAB_NMI ; set NMI flags + + STY Bpntrh ; save BASIC execute pointer high byte + LDA Cpntrl ; get continue pointer low byte + STA Bpntrl ; save BASIC execute pointer low byte + LDA Blinel ; get break line low byte + LDY Blineh ; get break line high byte + STA Clinel ; set current line low byte + STY Clineh ; set current line high byte + RTS + +; perform RUN + +LAB_RUN + BNE LAB_1696 ; branch if RUN n + JMP LAB_1477 ; reset execution to start, clear variables, flush stack and + ; return + +; does RUN n + +LAB_1696 + JSR LAB_147A ; go do "CLEAR" + BEQ LAB_16B0 ; get n and do GOTO n (branch always as CLEAR sets Z=1) + +; perform DO + +LAB_DO + LDA #$05 ; need 5 bytes for DO + JSR LAB_1212 ; check room on stack for A bytes + LDA Bpntrh ; get BASIC execute pointer high byte + PHA ; push on stack + LDA Bpntrl ; get BASIC execute pointer low byte + PHA ; push on stack + LDA Clineh ; get current line high byte + PHA ; push on stack + LDA Clinel ; get current line low byte + PHA ; push on stack + LDA #TK_DO ; token for DO + PHA ; push on stack + JSR LAB_GBYT ; scan memory + JMP LAB_15C2 ; go do interpreter inner loop + +; perform GOSUB + +LAB_GOSUB + LDA #$05 ; need 5 bytes for GOSUB + JSR LAB_1212 ; check room on stack for A bytes + LDA Bpntrh ; get BASIC execute pointer high byte + PHA ; push on stack + LDA Bpntrl ; get BASIC execute pointer low byte + PHA ; push on stack + LDA Clineh ; get current line high byte + PHA ; push on stack + LDA Clinel ; get current line low byte + PHA ; push on stack + LDA #TK_GOSUB ; token for GOSUB + PHA ; push on stack +LAB_16B0 + JSR LAB_GBYT ; scan memory + JSR LAB_GOTO ; perform GOTO n + JMP LAB_15C2 ; go do interpreter inner loop + ; (can't RTS, we used the stack!) + +; perform GOTO + +LAB_GOTO + JSR LAB_GFPN ; get fixed-point number into temp integer + JSR LAB_SNBL ; scan for next BASIC line + LDA Clineh ; get current line high byte + CMP Itemph ; compare with temporary integer high byte + BCS LAB_16D0 ; branch if >= (start search from beginning) + + TYA ; else copy line index to A + SEC ; set carry (+1) + ADC Bpntrl ; add BASIC execute pointer low byte + LDX Bpntrh ; get BASIC execute pointer high byte + BCC LAB_16D4 ; branch if no overflow to high byte + + INX ; increment high byte + BCS LAB_16D4 ; branch always (can never be carry) + +; search for line # in temp (Itempl/Itemph) from start of mem pointer (Smeml) + +LAB_16D0 + LDA Smeml ; get start of mem low byte + LDX Smemh ; get start of mem high byte + +; search for line # in temp (Itempl/Itemph) from (AX) + +LAB_16D4 + JSR LAB_SHLN ; search Basic for temp integer line number from AX + BCC LAB_16F7 ; if carry clear go do "Undefined statement" error + ; (unspecified statement) + + ; carry already set for subtract + LDA Baslnl ; get pointer low byte + SBC #$01 ; -1 + STA Bpntrl ; save BASIC execute pointer low byte + LDA Baslnh ; get pointer high byte + SBC #$00 ; subtract carry + STA Bpntrh ; save BASIC execute pointer high byte +LAB_16E5 + RTS + +LAB_DONOK + LDX #$22 ; error code $22 ("LOOP without DO" error) + JMP LAB_XERR ; do error #X, then warm start + +; perform LOOP + +LAB_LOOP + TAY ; save following token + TSX ; copy stack pointer + LDA LAB_STAK+3,X ; get token byte from stack + CMP #TK_DO ; compare with DO token + BNE LAB_DONOK ; branch if no matching DO + + INX ; dump calling routine return address + INX ; dump calling routine return address + TXS ; correct stack + TYA ; get saved following token back + BEQ LoopAlways ; if no following token loop forever + ; (stack pointer in X) + + CMP #':' ; could be ':' + BEQ LoopAlways ; if :... loop forever + + SBC #TK_UNTIL ; subtract token for UNTIL, we know carry is set here + TAX ; copy to X (if it was UNTIL then Y will be correct) + BEQ DoRest ; branch if was UNTIL + + DEX ; decrement result + BNE LAB_16FC ; if not WHILE go do syntax error and warm start + ; only if the token was WHILE will this fail + + DEX ; set invert result byte +DoRest + STX Frnxth ; save invert result byte + JSR LAB_IGBY ; increment and scan memory + JSR LAB_EVEX ; evaluate expression + LDA FAC1_e ; get FAC1 exponent + BEQ DoCmp ; if =0 go do straight compare + + LDA #$FF ; else set all bits +DoCmp + TSX ; copy stack pointer + EOR Frnxth ; EOR with invert byte + BNE LoopDone ; if <> 0 clear stack and back to interpreter loop + + ; loop condition wasn't met so do it again +LoopAlways + LDA LAB_STAK+2,X ; get current line low byte + STA Clinel ; save current line low byte + LDA LAB_STAK+3,X ; get current line high byte + STA Clineh ; save current line high byte + LDA LAB_STAK+4,X ; get BASIC execute pointer low byte + STA Bpntrl ; save BASIC execute pointer low byte + LDA LAB_STAK+5,X ; get BASIC execute pointer high byte + STA Bpntrh ; save BASIC execute pointer high byte + JSR LAB_GBYT ; scan memory + JMP LAB_15C2 ; go do interpreter inner loop + + ; clear stack and back to interpreter loop +LoopDone + INX ; dump DO token + INX ; dump current line low byte + INX ; dump current line high byte + INX ; dump BASIC execute pointer low byte + INX ; dump BASIC execute pointer high byte + TXS ; correct stack + JMP LAB_DATA ; go perform DATA (find : or [EOL]) + +; do the return without gosub error + +LAB_16F4 + LDX #$04 ; error code $04 ("RETURN without GOSUB" error) + .byte $2C ; makes next line BIT LAB_0EA2 + +LAB_16F7 ; do undefined statement error + LDX #$0E ; error code $0E ("Undefined statement" error) + JMP LAB_XERR ; do error #X, then warm start + +; perform RETURN + +LAB_RETURN + BNE LAB_16E5 ; exit if following token (to allow syntax error) + +LAB_16E8 + PLA ; dump calling routine return address + PLA ; dump calling routine return address + PLA ; pull token + CMP #TK_GOSUB ; compare with GOSUB token + BNE LAB_16F4 ; branch if no matching GOSUB + +LAB_16FF + PLA ; pull current line low byte + STA Clinel ; save current line low byte + PLA ; pull current line high byte + STA Clineh ; save current line high byte + PLA ; pull BASIC execute pointer low byte + STA Bpntrl ; save BASIC execute pointer low byte + PLA ; pull BASIC execute pointer high byte + STA Bpntrh ; save BASIC execute pointer high byte + + ; now do the DATA statement as we could be returning into + ; the middle of an ON GOSUB n,m,p,q line + ; (the return address used by the DATA statement is the one + ; pushed before the GOSUB was executed!) + +; perform DATA + +LAB_DATA + JSR LAB_SNBS ; scan for next BASIC statement ([:] or [EOL]) + + ; set BASIC execute pointer +LAB_170F + TYA ; copy index to A + CLC ; clear carry for add + ADC Bpntrl ; add BASIC execute pointer low byte + STA Bpntrl ; save BASIC execute pointer low byte + BCC LAB_1719 ; skip next if no carry + + INC Bpntrh ; else increment BASIC execute pointer high byte +LAB_1719 + RTS + +LAB_16FC + JMP LAB_SNER ; do syntax error then warm start + +; scan for next BASIC statement ([:] or [EOL]) +; returns Y as index to [:] or [EOL] + +LAB_SNBS + LDX #':' ; set look for character = ":" + .byte $2C ; makes next line BIT $00A2 + +; scan for next BASIC line +; returns Y as index to [EOL] + +LAB_SNBL + LDX #$00 ; set alt search character = [EOL] + LDY #$00 ; set search character = [EOL] + STY Asrch ; store search character +LAB_1725 + TXA ; get alt search character + EOR Asrch ; toggle search character, effectively swap with $00 + STA Asrch ; save swapped search character +LAB_172D + LDA (Bpntrl),Y ; get next byte + BEQ LAB_1719 ; exit if null [EOL] + + CMP Asrch ; compare with search character + BEQ LAB_1719 ; exit if found + + INY ; increment index + CMP #$22 ; compare current character with open quote + BNE LAB_172D ; if not open quote go get next character + + BEQ LAB_1725 ; if found go swap search character for alt search character + +; perform IF + +LAB_IF + JSR LAB_EVEX ; evaluate the expression + JSR LAB_GBYT ; scan memory + CMP #TK_THEN ; compare with THEN token + BEQ LAB_174B ; if it was THEN go do IF + + ; wasn't IF .. THEN so must be IF .. GOTO + CMP #TK_GOTO ; compare with GOTO token + BNE LAB_16FC ; if it wasn't GOTO go do syntax error + + LDX Bpntrl ; save the basic pointer low byte + LDY Bpntrh ; save the basic pointer high byte + JSR LAB_IGBY ; increment and scan memory + BCS LAB_16FC ; if not numeric go do syntax error + + STX Bpntrl ; restore the basic pointer low byte + STY Bpntrh ; restore the basic pointer high byte +LAB_174B + LDA FAC1_e ; get FAC1 exponent + BEQ LAB_174E ; if the result was zero go look for an ELSE + + JSR LAB_IGBY ; else increment and scan memory + BCS LAB_174D ; if not numeric go do var or keyword + +LAB_174C + JMP LAB_GOTO ; else was numeric so do GOTO n + + ; is var or keyword +LAB_174D + CMP #TK_RETURN ; compare the byte with the token for RETURN + BNE LAB_174G ; if it wasn't RETURN go interpret BASIC code from (Bpntrl) + ; and return to this code to process any following code + + JMP LAB_1602 ; else it was RETURN so interpret BASIC code from (Bpntrl) + ; but don't return here + +LAB_174G + JSR LAB_15FF ; interpret BASIC code from (Bpntrl) + +; the IF was executed and there may be a following ELSE so the code needs to return +; here to check and ignore the ELSE if present + + LDY #$00 ; clear the index + LDA (Bpntrl),Y ; get the next BASIC byte + CMP #TK_ELSE ; compare it with the token for ELSE + BEQ LAB_DATA ; if ELSE ignore the following statement + +; there was no ELSE so continue execution of IF THEN [: ]. any +; following ELSE will, correctly, cause a syntax error + + RTS ; else return to the interpreter inner loop + +; perform ELSE after IF + +LAB_174E + LDY #$00 ; clear the BASIC byte index + LDX #$01 ; clear the nesting depth +LAB_1750 + INY ; increment the BASIC byte index + LDA (Bpntrl),Y ; get the next BASIC byte + BEQ LAB_1753 ; if EOL go add the pointer and return + + CMP #TK_IF ; compare the byte with the token for IF + BNE LAB_1752 ; if not IF token skip the depth increment + + INX ; else increment the nesting depth .. + BNE LAB_1750 ; .. and continue looking + +LAB_1752 + CMP #TK_ELSE ; compare the byte with the token for ELSE + BNE LAB_1750 ; if not ELSE token continue looking + + DEX ; was ELSE so decrement the nesting depth + BNE LAB_1750 ; loop if still nested + + INY ; increment the BASIC byte index past the ELSE + +; found the matching ELSE, now do <{n|statement}> + +LAB_1753 + TYA ; else copy line index to A + CLC ; clear carry for add + ADC Bpntrl ; add the BASIC execute pointer low byte + STA Bpntrl ; save the BASIC execute pointer low byte + BCC LAB_1754 ; branch if no overflow to high byte + + INC Bpntrh ; else increment the BASIC execute pointer high byte +LAB_1754 + JSR LAB_GBYT ; scan memory + BCC LAB_174C ; if numeric do GOTO n + ; the code will return to the interpreter loop at the + ; tail end of the GOTO + + JMP LAB_15FF ; interpret BASIC code from (Bpntrl) + ; the code will return to the interpreter loop at the + ; tail end of the + +; perform REM, skip (rest of) line + +LAB_REM + JSR LAB_SNBL ; scan for next BASIC line + JMP LAB_170F ; go set BASIC execute pointer and return, branch always + +LAB_16FD + JMP LAB_SNER ; do syntax error then warm start + +; perform ON + +LAB_ON + CMP #TK_IRQ ; was it IRQ token ? + BNE LAB_NOIN ; if not go check NMI + + JMP LAB_SIRQ ; else go set-up IRQ + +LAB_NOIN + CMP #TK_NMI ; was it NMI token ? + BNE LAB_NONM ; if not go do normal ON command + + JMP LAB_SNMI ; else go set-up NMI + +LAB_NONM + JSR LAB_GTBY ; get byte parameter + PHA ; push GOTO/GOSUB token + CMP #TK_GOSUB ; compare with GOSUB token + BEQ LAB_176B ; branch if GOSUB + + CMP #TK_GOTO ; compare with GOTO token +LAB_1767 + BNE LAB_16FD ; if not GOTO do syntax error then warm start + + +; next character was GOTO or GOSUB + +LAB_176B + DEC FAC1_3 ; decrement index (byte value) + BNE LAB_1773 ; branch if not zero + + PLA ; pull GOTO/GOSUB token + JMP LAB_1602 ; go execute it + +LAB_1773 + JSR LAB_IGBY ; increment and scan memory + JSR LAB_GFPN ; get fixed-point number into temp integer (skip this n) + ; (we could LDX #',' and JSR LAB_SNBL+2, then we + ; just BNE LAB_176B for the loop. should be quicker .. + ; no we can't, what if we meet a colon or [EOL]?) + CMP #$2C ; compare next character with "," + BEQ LAB_176B ; loop if "," + +LAB_177E + PLA ; else pull keyword token (run out of options) + ; also dump +/-1 pointer low byte and exit +LAB_177F + RTS + +; takes n * 106 + 11 cycles where n is the number of digits + +; get fixed-point number into temp integer + +LAB_GFPN + LDX #$00 ; clear reg + STX Itempl ; clear temporary integer low byte +LAB_1785 + STX Itemph ; save temporary integer high byte + BCS LAB_177F ; return if carry set, end of scan, character was + ; not 0-9 + + CPX #$19 ; compare high byte with $19 + TAY ; ensure Zb = 0 if the branch is taken + BCS LAB_1767 ; branch if >=, makes max line # 63999 because next + ; bit does *$0A, = 64000, compare at target will fail + ; and do syntax error + + SBC #'0'-1 ; subtract "0", $2F + carry, from byte + TAY ; copy binary digit + LDA Itempl ; get temporary integer low byte + ASL ; *2 low byte + ROL Itemph ; *2 high byte + ASL ; *2 low byte + ROL Itemph ; *2 high byte, *4 + ADC Itempl ; + low byte, *5 + STA Itempl ; save it + TXA ; get high byte copy to A + ADC Itemph ; + high byte, *5 + ASL Itempl ; *2 low byte, *10d + ROL ; *2 high byte, *10d + TAX ; copy high byte back to X + TYA ; get binary digit back + ADC Itempl ; add number low byte + STA Itempl ; save number low byte + BCC LAB_17B3 ; if no overflow to high byte get next character + + INX ; else increment high byte +LAB_17B3 + JSR LAB_IGBY ; increment and scan memory + JMP LAB_1785 ; loop for next character + +; perform DEC + +LAB_DEC + LDA #LAB_259C ; set +/-1 pointer high byte (both the same) + JSR LAB_246C ; add (AY) to FAC1 + JSR LAB_PFAC ; pack FAC1 into variable (Lvarpl) + + JSR LAB_GBYT ; scan memory + CMP #',' ; compare with "," + BNE LAB_177E ; exit if not "," (either end or error) + + ; was "," so another INCR variable to do + JSR LAB_IGBY ; increment and scan memory + JMP LAB_17B7 ; go do next var + +IncrErr + JMP LAB_1ABC ; do "Type mismatch" error then warm start + +; perform LET + +LAB_LET + JSR LAB_GVAR ; get var address + STA Lvarpl ; save var address low byte + STY Lvarph ; save var address high byte + LDA #TK_EQUAL ; get = token + JSR LAB_SCCA ; scan for CHR$(A), else do syntax error then warm start + LDA Dtypef ; get data type flag, $FF=string, $00=numeric + PHA ; push data type flag + JSR LAB_EVEX ; evaluate expression + PLA ; pop data type flag + ROL ; set carry if type = string + JSR LAB_CKTM ; type match check, set C for string + BNE LAB_17D5 ; branch if string + + JMP LAB_PFAC ; pack FAC1 into variable (Lvarpl) and return + +; string LET + +LAB_17D5 + LDY #$02 ; set index to pointer high byte + LDA (des_pl),Y ; get string pointer high byte + CMP Sstorh ; compare bottom of string space high byte + BCC LAB_17F4 ; if less assign value and exit (was in program memory) + + BNE LAB_17E6 ; branch if > + ; else was equal so compare low bytes + DEY ; decrement index + LDA (des_pl),Y ; get pointer low byte + CMP Sstorl ; compare bottom of string space low byte + BCC LAB_17F4 ; if less assign value and exit (was in program memory) + + ; pointer was >= to bottom of string space pointer +LAB_17E6 + LDY des_ph ; get descriptor pointer high byte + CPY Svarh ; compare start of vars high byte + BCC LAB_17F4 ; branch if less (descriptor is on stack) + + BNE LAB_17FB ; branch if greater (descriptor is not on stack) + + ; else high bytes were equal so .. + LDA des_pl ; get descriptor pointer low byte + CMP Svarl ; compare start of vars low byte + BCS LAB_17FB ; branch if >= (descriptor is not on stack) + +LAB_17F4 + LDA des_pl ; get descriptor pointer low byte + LDY des_ph ; get descriptor pointer high byte + JMP LAB_1811 ; clean stack, copy descriptor to variable and return + + ; make space and copy string +LAB_17FB + LDY #$00 ; index to length + LDA (des_pl),Y ; get string length + JSR LAB_209C ; copy string + LDA des_2l ; get descriptor pointer low byte + LDY des_2h ; get descriptor pointer high byte + STA ssptr_l ; save descriptor pointer low byte + STY ssptr_h ; save descriptor pointer high byte + JSR LAB_228A ; copy string from descriptor (sdescr) to (Sutill) + LDA #FAC1_e ; get descriptor pointer high byte + + ; clean stack and assign value to string variable +LAB_1811 + STA des_2l ; save descriptor_2 pointer low byte + STY des_2h ; save descriptor_2 pointer high byte + JSR LAB_22EB ; clean descriptor stack, YA = pointer + LDY #$00 ; index to length + LDA (des_2l),Y ; get string length + STA (Lvarpl),Y ; copy to let string variable + INY ; index to string pointer low byte + LDA (des_2l),Y ; get string pointer low byte + STA (Lvarpl),Y ; copy to let string variable + INY ; index to string pointer high byte + LDA (des_2l),Y ; get string pointer high byte + STA (Lvarpl),Y ; copy to let string variable + RTS + +; perform GET + +LAB_GET + JSR LAB_GVAR ; get var address + STA Lvarpl ; save var address low byte + STY Lvarph ; save var address high byte + JSR INGET ; get input byte + LDX Dtypef ; get data type flag, $FF=string, $00=numeric + BMI LAB_GETS ; go get string character + + ; was numeric get + TAY ; copy character to Y + JSR LAB_1FD0 ; convert Y to byte in FAC1 + JMP LAB_PFAC ; pack FAC1 into variable (Lvarpl) and return + +LAB_GETS + PHA ; save character + LDA #$01 ; string is single byte + BCS LAB_IsByte ; branch if byte received + + PLA ; string is null +LAB_IsByte + JSR LAB_MSSP ; make string space A bytes long A=$AC=length, + ; X=$AD=Sutill=ptr low byte, Y=$AE=Sutilh=ptr high byte + BEQ LAB_NoSt ; skip store if null string + + PLA ; get character back + LDY #$00 ; clear index + STA (str_pl),Y ; save byte in string (byte IS string!) +LAB_NoSt + JSR LAB_RTST ; check for space on descriptor stack then put address + ; and length on descriptor stack and update stack pointers + + JMP LAB_17D5 ; do string LET and return + +; perform PRINT + +LAB_1829 + JSR LAB_18C6 ; print string from Sutill/Sutilh +LAB_182C + JSR LAB_GBYT ; scan memory + +; PRINT + +LAB_PRINT + BEQ LAB_CRLF ; if nothing following just print CR/LF + +LAB_1831 + CMP #TK_TAB ; compare with TAB( token + BEQ LAB_18A2 ; go do TAB/SPC + + CMP #TK_SPC ; compare with SPC( token + BEQ LAB_18A2 ; go do TAB/SPC + + CMP #',' ; compare with "," + BEQ LAB_188B ; go do move to next TAB mark + + CMP #';' ; compare with ";" + BEQ LAB_18BD ; if ";" continue with PRINT processing + + JSR LAB_EVEX ; evaluate expression + BIT Dtypef ; test data type flag, $FF=string, $00=numeric + BMI LAB_1829 ; branch if string + + JSR LAB_296E ; convert FAC1 to string + JSR LAB_20AE ; print " terminated string to Sutill/Sutilh + LDY #$00 ; clear index + +; don't check fit if terminal width byte is zero + + LDA TWidth ; get terminal width byte + BEQ LAB_185E ; skip check if zero + + SEC ; set carry for subtract + SBC TPos ; subtract terminal position + SBC (des_pl),Y ; subtract string length + BCS LAB_185E ; branch if less than terminal width + + JSR LAB_CRLF ; else print CR/LF +LAB_185E + JSR LAB_18C6 ; print string from Sutill/Sutilh + BEQ LAB_182C ; always go continue processing line + +; CR/LF return to BASIC from BASIC input handler + +LAB_1866 + LDA #$00 ; clear byte + STA Ibuffs,X ; null terminate input + LDX #Ibuffs ; set Y to buffer start-1 high byte + +; print CR/LF + +LAB_CRLF + LDA #$0D ; load [CR] + JSR LAB_PRNA ; go print the character + LDA #$0A ; load [LF] + BNE LAB_PRNA ; go print the character and return, branch always + +LAB_188B + LDA TPos ; get terminal position + CMP Iclim ; compare with input column limit + BCC LAB_1897 ; branch if less + + JSR LAB_CRLF ; else print CR/LF (next line) + BNE LAB_18BD ; continue with PRINT processing (branch always) + +LAB_1897 + SEC ; set carry for subtract +LAB_1898 + SBC TabSiz ; subtract TAB size + BCS LAB_1898 ; loop if result was +ve + + EOR #$FF ; complement it + ADC #$01 ; +1 (twos complement) + BNE LAB_18B6 ; always print A spaces (result is never $00) + + ; do TAB/SPC +LAB_18A2 + PHA ; save token + JSR LAB_SGBY ; scan and get byte parameter + CMP #$29 ; is next character ) + BNE LAB_1910 ; if not do syntax error then warm start + + PLA ; get token back + CMP #TK_TAB ; was it TAB ? + BNE LAB_18B7 ; if not go do SPC + + ; calculate TAB offset + TXA ; copy integer value to A + SBC TPos ; subtract terminal position + BCC LAB_18BD ; branch if result was < 0 (can't TAB backwards) + + ; print A spaces +LAB_18B6 + TAX ; copy result to X +LAB_18B7 + TXA ; set flags on size for SPC + BEQ LAB_18BD ; branch if result was = $0, already here + + ; print X spaces +LAB_18BA + JSR LAB_18E0 ; print " " + DEX ; decrement count + BNE LAB_18BA ; loop if not all done + + ; continue with PRINT processing +LAB_18BD + JSR LAB_IGBY ; increment and scan memory + BNE LAB_1831 ; if more to print go do it + + RTS + +; print null terminated string from memory + +LAB_18C3 + JSR LAB_20AE ; print " terminated string to Sutill/Sutilh + +; print string from Sutill/Sutilh + +LAB_18C6 + JSR LAB_22B6 ; pop string off descriptor stack, or from top of string + ; space returns with A = length, X=$71=pointer low byte, + ; Y=$72=pointer high byte + LDY #$00 ; reset index + TAX ; copy length to X + BEQ LAB_188C ; exit (RTS) if null string + +LAB_18CD + + LDA (ut1_pl),Y ; get next byte + JSR LAB_PRNA ; go print the character + INY ; increment index + DEX ; decrement count + BNE LAB_18CD ; loop if not done yet + + RTS + + ; Print single format character +; print " " + +LAB_18E0 + LDA #$20 ; load " " + .byte $2C ; change next line to BIT LAB_3FA9 + +; print "?" character + +LAB_18E3 + LDA #$3F ; load "?" character + +; print character in A +; now includes the null handler +; also includes infinite line length code +; note! some routines expect this one to exit with Zb=0 + +LAB_PRNA + CMP #' ' ; compare with " " + BCC LAB_18F9 ; branch if less (non printing) + + ; else printable character + PHA ; save the character + +; don't check fit if terminal width byte is zero + + LDA TWidth ; get terminal width + BNE LAB_18F0 ; branch if not zero (not infinite length) + +; is "infinite line" so check TAB position + + LDA TPos ; get position + SBC TabSiz ; subtract TAB size, carry set by CMP #$20 above + BNE LAB_18F7 ; skip reset if different + + STA TPos ; else reset position + BEQ LAB_18F7 ; go print character + +LAB_18F0 + CMP TPos ; compare with terminal character position + BNE LAB_18F7 ; branch if not at end of line + + JSR LAB_CRLF ; else print CR/LF +LAB_18F7 + INC TPos ; increment terminal position + PLA ; get character back +LAB_18F9 + JSR V_OUTP ; output byte via output vector + CMP #$0D ; compare with [CR] + BNE LAB_188A ; branch if not [CR] + + ; else print nullct nulls after the [CR] + STX TempB ; save buffer index + LDX Nullct ; get null count + BEQ LAB_1886 ; branch if no nulls + + LDA #$00 ; load [NULL] +LAB_1880 + JSR LAB_PRNA ; go print the character + DEX ; decrement count + BNE LAB_1880 ; loop if not all done + + LDA #$0D ; restore the character (and set the flags) +LAB_1886 + STX TPos ; clear terminal position (X always = zero when we get here) + LDX TempB ; restore buffer index +LAB_188A + AND #$FF ; set the flags +LAB_188C + RTS + +; handle bad input data + +LAB_1904 + LDA Imode ; get input mode flag, $00=INPUT, $00=READ + BPL LAB_1913 ; branch if INPUT (go do redo) + + LDA Dlinel ; get current DATA line low byte + LDY Dlineh ; get current DATA line high byte + STA Clinel ; save current line low byte + STY Clineh ; save current line high byte +LAB_1910 + JMP LAB_SNER ; do syntax error then warm start + + ; mode was INPUT +LAB_1913 + LDA #LAB_REDO ; point to redo message (high addr) + JSR LAB_18C3 ; print null terminated string from memory + LDA Cpntrl ; get continue pointer low byte + LDY Cpntrh ; get continue pointer high byte + STA Bpntrl ; save BASIC execute pointer low byte + STY Bpntrh ; save BASIC execute pointer high byte + RTS + +; perform INPUT + +LAB_INPUT + CMP #$22 ; compare next byte with open quote + BNE LAB_1934 ; branch if no prompt string + + JSR LAB_1BC1 ; print "..." string + LDA #$3B ; load A with ";" + JSR LAB_SCCA ; scan for CHR$(A), else do syntax error then warm start + JSR LAB_18C6 ; print string from Sutill/Sutilh + + ; done with prompt, now get data +LAB_1934 + JSR LAB_CKRN ; check not Direct, back here if ok + JSR LAB_INLN ; print "? " and get BASIC input + LDA #$00 ; set mode = INPUT + CMP Ibuffs ; test first byte in buffer + BNE LAB_1953 ; branch if not null input + + CLC ; was null input so clear carry to exit program + JMP LAB_1647 ; go do BREAK exit + +; perform READ + +LAB_READ + LDX Dptrl ; get DATA pointer low byte + LDY Dptrh ; get DATA pointer high byte + LDA #$80 ; set mode = READ + +LAB_1953 + STA Imode ; set input mode flag, $00=INPUT, $80=READ + STX Rdptrl ; save READ pointer low byte + STY Rdptrh ; save READ pointer high byte + + ; READ or INPUT next variable from list +LAB_195B + JSR LAB_GVAR ; get (var) address + STA Lvarpl ; save address low byte + STY Lvarph ; save address high byte + LDA Bpntrl ; get BASIC execute pointer low byte + LDY Bpntrh ; get BASIC execute pointer high byte + STA Itempl ; save as temporary integer low byte + STY Itemph ; save as temporary integer high byte + LDX Rdptrl ; get READ pointer low byte + LDY Rdptrh ; get READ pointer high byte + STX Bpntrl ; set BASIC execute pointer low byte + STY Bpntrh ; set BASIC execute pointer high byte + JSR LAB_GBYT ; scan memory + BNE LAB_1988 ; branch if not null + + ; pointer was to null entry + BIT Imode ; test input mode flag, $00=INPUT, $80=READ + BMI LAB_19DD ; branch if READ + + ; mode was INPUT + JSR LAB_18E3 ; print "?" character (double ? for extended input) + JSR LAB_INLN ; print "? " and get BASIC input + STX Bpntrl ; set BASIC execute pointer low byte + STY Bpntrh ; set BASIC execute pointer high byte +LAB_1985 + JSR LAB_GBYT ; scan memory +LAB_1988 + BIT Dtypef ; test data type flag, $FF=string, $00=numeric + BPL LAB_19B0 ; branch if numeric + + ; else get string + STA Srchc ; save search character + CMP #$22 ; was it " ? + BEQ LAB_1999 ; branch if so + + LDA #':' ; else search character is ":" + STA Srchc ; set new search character + LDA #',' ; other search character is "," + CLC ; clear carry for add +LAB_1999 + STA Asrch ; set second search character + LDA Bpntrl ; get BASIC execute pointer low byte + LDY Bpntrh ; get BASIC execute pointer high byte + + ADC #$00 ; c is =1 if we came via the BEQ LAB_1999, else =0 + BCC LAB_19A4 ; branch if no execute pointer low byte rollover + + INY ; else increment high byte +LAB_19A4 + JSR LAB_20B4 ; print Srchc or Asrch terminated string to Sutill/Sutilh + JSR LAB_23F3 ; restore BASIC execute pointer from temp (Btmpl/Btmph) + JSR LAB_17D5 ; go do string LET + JMP LAB_19B6 ; go check string terminator + + ; get numeric INPUT +LAB_19B0 + JSR LAB_2887 ; get FAC1 from string + JSR LAB_PFAC ; pack FAC1 into (Lvarpl) +LAB_19B6 + JSR LAB_GBYT ; scan memory + BEQ LAB_19C5 ; branch if null (last entry) + + CMP #',' ; else compare with "," + BEQ LAB_19C2 ; branch if "," + + JMP LAB_1904 ; else go handle bad input data + + ; got good input data +LAB_19C2 + JSR LAB_IGBY ; increment and scan memory +LAB_19C5 + LDA Bpntrl ; get BASIC execute pointer low byte (temp READ/INPUT ptr) + LDY Bpntrh ; get BASIC execute pointer high byte (temp READ/INPUT ptr) + STA Rdptrl ; save for now + STY Rdptrh ; save for now + LDA Itempl ; get temporary integer low byte (temp BASIC execute ptr) + LDY Itemph ; get temporary integer high byte (temp BASIC execute ptr) + STA Bpntrl ; set BASIC execute pointer low byte + STY Bpntrh ; set BASIC execute pointer high byte + JSR LAB_GBYT ; scan memory + BEQ LAB_1A03 ; if null go do extra ignored message + + JSR LAB_1C01 ; else scan for "," , else do syntax error then warm start + JMP LAB_195B ; go INPUT next variable from list + + ; find next DATA statement or do "Out of DATA" error +LAB_19DD + JSR LAB_SNBS ; scan for next BASIC statement ([:] or [EOL]) + INY ; increment index + TAX ; copy character ([:] or [EOL]) + BNE LAB_19F6 ; branch if [:] + + LDX #$06 ; set for "Out of DATA" error + INY ; increment index, now points to next line pointer high byte + LDA (Bpntrl),Y ; get next line pointer high byte + BEQ LAB_1A54 ; branch if end (eventually does error X) + + INY ; increment index + LDA (Bpntrl),Y ; get next line # low byte + STA Dlinel ; save current DATA line low byte + INY ; increment index + LDA (Bpntrl),Y ; get next line # high byte + INY ; increment index + STA Dlineh ; save current DATA line high byte +LAB_19F6 + LDA (Bpntrl),Y ; get byte + INY ; increment index + TAX ; copy to X + JSR LAB_170F ; set BASIC execute pointer + CPX #TK_DATA ; compare with "DATA" token + BEQ LAB_1985 ; was "DATA" so go do next READ + + BNE LAB_19DD ; go find next statement if not "DATA" + +; end of INPUT/READ routine + +LAB_1A03 + LDA Rdptrl ; get temp READ pointer low byte + LDY Rdptrh ; get temp READ pointer high byte + LDX Imode ; get input mode flag, $00=INPUT, $80=READ + BPL LAB_1A0E ; branch if INPUT + + JMP LAB_1624 ; save AY as DATA pointer and return + + ; we were getting INPUT +LAB_1A0E + LDY #$00 ; clear index + LDA (Rdptrl),Y ; get next byte + BNE LAB_1A1B ; error if not end of INPUT + + RTS + + ; user typed too much +LAB_1A1B + LDA #LAB_IMSG ; point to extra ignored message (high addr) + JMP LAB_18C3 ; print null terminated string from memory and return + +; search the stack for FOR activity +; exit with z=1 if FOR else exit with z=0 + +LAB_11A1 + TSX ; copy stack pointer + INX ; +1 pass return address + INX ; +2 pass return address + INX ; +3 pass calling routine return address + INX ; +4 pass calling routine return address +LAB_11A6 + LDA LAB_STAK+1,X ; get token byte from stack + CMP #TK_FOR ; is it FOR token + BNE LAB_11CE ; exit if not FOR token + + ; was FOR token + LDA Frnxth ; get var pointer for FOR/NEXT high byte + BNE LAB_11BB ; branch if not null + + LDA LAB_STAK+2,X ; get FOR variable pointer low byte + STA Frnxtl ; save var pointer for FOR/NEXT low byte + LDA LAB_STAK+3,X ; get FOR variable pointer high byte + STA Frnxth ; save var pointer for FOR/NEXT high byte +LAB_11BB + CMP LAB_STAK+3,X ; compare var pointer with stacked var pointer (high byte) + BNE LAB_11C7 ; branch if no match + + LDA Frnxtl ; get var pointer for FOR/NEXT low byte + CMP LAB_STAK+2,X ; compare var pointer with stacked var pointer (low byte) + BEQ LAB_11CE ; exit if match found + +LAB_11C7 + TXA ; copy index + CLC ; clear carry for add + ADC #$10 ; add FOR stack use size + TAX ; copy back to index + BNE LAB_11A6 ; loop if not at start of stack + +LAB_11CE + RTS + +; perform NEXT + +LAB_NEXT + BNE LAB_1A46 ; branch if NEXT var + + LDY #$00 ; else clear Y + BEQ LAB_1A49 ; branch always (no variable to search for) + +; NEXT var + +LAB_1A46 + JSR LAB_GVAR ; get variable address +LAB_1A49 + STA Frnxtl ; store variable pointer low byte + STY Frnxth ; store variable pointer high byte + ; (both cleared if no variable defined) + JSR LAB_11A1 ; search the stack for FOR activity + BEQ LAB_1A56 ; branch if found + + LDX #$00 ; else set error $00 ("NEXT without FOR" error) +LAB_1A54 + BEQ LAB_1ABE ; do error #X, then warm start + +LAB_1A56 + TXS ; set stack pointer, X set by search, dumps return addresses + + TXA ; copy stack pointer + SEC ; set carry for subtract + SBC #$F7 ; point to TO var + STA ut2_pl ; save pointer to TO var for compare + ADC #$FB ; point to STEP var + + LDY #>LAB_STAK ; point to stack page high byte + JSR LAB_UFAC ; unpack memory (STEP value) into FAC1 + TSX ; get stack pointer back + LDA LAB_STAK+8,X ; get step sign + STA FAC1_s ; save FAC1 sign (b7) + LDA Frnxtl ; get FOR variable pointer low byte + LDY Frnxth ; get FOR variable pointer high byte + JSR LAB_246C ; add (FOR variable) to FAC1 + JSR LAB_PFAC ; pack FAC1 into (FOR variable) + LDY #>LAB_STAK ; point to stack page high byte + JSR LAB_27FA ; compare FAC1 with (Y,ut2_pl) (TO value) + TSX ; get stack pointer back + CMP LAB_STAK+8,X ; compare step sign + BEQ LAB_1A9B ; branch if = (loop complete) + + ; loop back and do it all again + LDA LAB_STAK+$0D,X ; get FOR line low byte + STA Clinel ; save current line low byte + LDA LAB_STAK+$0E,X ; get FOR line high byte + STA Clineh ; save current line high byte + LDA LAB_STAK+$10,X ; get BASIC execute pointer low byte + STA Bpntrl ; save BASIC execute pointer low byte + LDA LAB_STAK+$0F,X ; get BASIC execute pointer high byte + STA Bpntrh ; save BASIC execute pointer high byte +LAB_1A98 + JMP LAB_15C2 ; go do interpreter inner loop + + ; loop complete so carry on +LAB_1A9B + TXA ; stack copy to A + ADC #$0F ; add $10 ($0F+carry) to dump FOR structure + TAX ; copy back to index + TXS ; copy to stack pointer + JSR LAB_GBYT ; scan memory + CMP #',' ; compare with "," + BNE LAB_1A98 ; branch if not "," (go do interpreter inner loop) + + ; was "," so another NEXT variable to do + JSR LAB_IGBY ; else increment and scan memory + JSR LAB_1A46 ; do NEXT (var) + +; evaluate expression and check is numeric, else do type mismatch + +LAB_EVNM + JSR LAB_EVEX ; evaluate expression + +; check if source is numeric, else do type mismatch + +LAB_CTNM + CLC ; destination is numeric + .byte $24 ; makes next line BIT $38 + +; check if source is string, else do type mismatch + +LAB_CTST + SEC ; required type is string + +; type match check, set C for string, clear C for numeric + +LAB_CKTM + BIT Dtypef ; test data type flag, $FF=string, $00=numeric + BMI LAB_1ABA ; branch if data type is string + + ; else data type was numeric + BCS LAB_1ABC ; if required type is string do type mismatch error +LAB_1AB9 + RTS + + ; data type was string, now check required type +LAB_1ABA + BCS LAB_1AB9 ; exit if required type is string + + ; else do type mismatch error +LAB_1ABC + LDX #$18 ; error code $18 ("Type mismatch" error) +LAB_1ABE + JMP LAB_XERR ; do error #X, then warm start + +; evaluate expression + +LAB_EVEX + LDX Bpntrl ; get BASIC execute pointer low byte + BNE LAB_1AC7 ; skip next if not zero + + DEC Bpntrh ; else decrement BASIC execute pointer high byte +LAB_1AC7 + DEC Bpntrl ; decrement BASIC execute pointer low byte + +LAB_EVEZ + LDA #$00 ; set null precedence (flag done) +LAB_1ACC + PHA ; push precedence byte + LDA #$02 ; 2 bytes + JSR LAB_1212 ; check room on stack for A bytes + JSR LAB_GVAL ; get value from line + LDA #$00 ; clear A + STA comp_f ; clear compare function flag +LAB_1ADB + JSR LAB_GBYT ; scan memory +LAB_1ADE + SEC ; set carry for subtract + SBC #TK_GT ; subtract token for > (lowest comparison function) + BCC LAB_1AFA ; branch if < TK_GT + + CMP #$03 ; compare with ">" to "<" tokens + BCS LAB_1AFA ; branch if >= TK_SGN (highest evaluation function +1) + + ; was token for > = or < (A = 0, 1 or 2) + CMP #$01 ; compare with token for = + ROL ; *2, b0 = carry (=1 if token was = or <) + ; (A = 0, 3 or 5) + EOR #$01 ; toggle b0 + ; (A = 1, 2 or 4. 1 if >, 2 if =, 4 if <) + EOR comp_f ; EOR with compare function flag bits + CMP comp_f ; compare with compare function flag + BCC LAB_1B53 ; if <(comp_f) do syntax error then warm start + ; was more than one <, = or >) + + STA comp_f ; save new compare function flag + JSR LAB_IGBY ; increment and scan memory + JMP LAB_1ADE ; go do next character + + ; token is < ">" or > "<" tokens +LAB_1AFA + LDX comp_f ; get compare function flag + BNE LAB_1B2A ; branch if compare function + + BCS LAB_1B78 ; go do functions + + ; else was < TK_GT so is operator or lower + ADC #TK_GT-TK_PLUS ; add # of operators (+, -, *, /, ^, AND, OR or EOR) + BCC LAB_1B78 ; branch if < + operator + + ; carry was set so token was +, -, *, /, ^, AND, OR or EOR + BNE LAB_1B0B ; branch if not + token + + BIT Dtypef ; test data type flag, $FF=string, $00=numeric + BPL LAB_1B0B ; branch if not string + + ; will only be $00 if type is string and token was + + JMP LAB_224D ; add strings, string 1 is in descriptor des_pl, string 2 + ; is in line, and return + +LAB_1B0B + STA ut1_pl ; save it + ASL ; *2 + ADC ut1_pl ; *3 + TAY ; copy to index +LAB_1B13 + PLA ; pull previous precedence + CMP LAB_OPPT,Y ; compare with precedence byte + BCS LAB_1B7D ; branch if A >= + + JSR LAB_CTNM ; check if source is numeric, else do type mismatch +LAB_1B1C + PHA ; save precedence +LAB_1B1D + JSR LAB_1B43 ; get vector, execute function then continue evaluation + PLA ; restore precedence + LDY prstk ; get precedence stacked flag + BPL LAB_1B3C ; branch if stacked values + + TAX ; copy precedence (set flags) + BEQ LAB_1B9D ; exit if done + + BNE LAB_1B86 ; else pop FAC2 and return, branch always + +LAB_1B2A + ROL Dtypef ; shift data type flag into Cb + TXA ; copy compare function flag + STA Dtypef ; clear data type flag, X is 0xxx xxxx + ROL ; shift data type into compare function byte b0 + LDX Bpntrl ; get BASIC execute pointer low byte + BNE LAB_1B34 ; branch if no underflow + + DEC Bpntrh ; else decrement BASIC execute pointer high byte +LAB_1B34 + DEC Bpntrl ; decrement BASIC execute pointer low byte +TK_LT_PLUS = TK_LT-TK_PLUS + LDY #TK_LT_PLUS*3 ; set offset to last operator entry + STA comp_f ; save new compare function flag + BNE LAB_1B13 ; branch always + +LAB_1B3C + CMP LAB_OPPT,Y ;.compare with stacked function precedence + BCS LAB_1B86 ; branch if A >=, pop FAC2 and return + + BCC LAB_1B1C ; branch always + +;.get vector, execute function then continue evaluation + +LAB_1B43 + LDA LAB_OPPT+2,Y ; get function vector high byte + PHA ; onto stack + LDA LAB_OPPT+1,Y ; get function vector low byte + PHA ; onto stack + ; now push sign, round FAC1 and put on stack + JSR LAB_1B5B ; function will return here, then the next RTS will call + ; the function + LDA comp_f ; get compare function flag + PHA ; push compare evaluation byte + LDA LAB_OPPT,Y ; get precedence byte + JMP LAB_1ACC ; continue evaluating expression + +LAB_1B53 + JMP LAB_SNER ; do syntax error then warm start + +; push sign, round FAC1 and put on stack + +LAB_1B5B + PLA ; get return addr low byte + STA ut1_pl ; save it + INC ut1_pl ; increment it (was ret-1 pushed? yes!) + ; note! no check is made on the high byte! if the calling + ; routine assembles to a page edge then this all goes + ; horribly wrong !!! + PLA ; get return addr high byte + STA ut1_ph ; save it + LDA FAC1_s ; get FAC1 sign (b7) + PHA ; push sign + +; round FAC1 and put on stack + +LAB_1B66 + JSR LAB_27BA ; round FAC1 + LDA FAC1_3 ; get FAC1 mantissa3 + PHA ; push on stack + LDA FAC1_2 ; get FAC1 mantissa2 + PHA ; push on stack + LDA FAC1_1 ; get FAC1 mantissa1 + PHA ; push on stack + LDA FAC1_e ; get FAC1 exponent + PHA ; push on stack + JMP (ut1_pl) ; return, sort of + +; do functions + +LAB_1B78 + LDY #$FF ; flag function + PLA ; pull precedence byte +LAB_1B7B + BEQ LAB_1B9D ; exit if done + +LAB_1B7D + CMP #$64 ; compare previous precedence with $64 + BEQ LAB_1B84 ; branch if was $64 (< function) + + JSR LAB_CTNM ; check if source is numeric, else do type mismatch +LAB_1B84 + STY prstk ; save precedence stacked flag + + ; pop FAC2 and return +LAB_1B86 + PLA ; pop byte + LSR ; shift out comparison evaluation lowest bit + STA Cflag ; save comparison evaluation flag + PLA ; pop exponent + STA FAC2_e ; save FAC2 exponent + PLA ; pop mantissa1 + STA FAC2_1 ; save FAC2 mantissa1 + PLA ; pop mantissa2 + STA FAC2_2 ; save FAC2 mantissa2 + PLA ; pop mantissa3 + STA FAC2_3 ; save FAC2 mantissa3 + PLA ; pop sign + STA FAC2_s ; save FAC2 sign (b7) + EOR FAC1_s ; EOR FAC1 sign (b7) + STA FAC_sc ; save sign compare (FAC1 EOR FAC2) +LAB_1B9D + LDA FAC1_e ; get FAC1 exponent + RTS + +; print "..." string to string util area + +LAB_1BC1 + LDA Bpntrl ; get BASIC execute pointer low byte + LDY Bpntrh ; get BASIC execute pointer high byte + ADC #$00 ; add carry to low byte + BCC LAB_1BCA ; branch if no overflow + + INY ; increment high byte +LAB_1BCA + JSR LAB_20AE ; print " terminated string to Sutill/Sutilh + JMP LAB_23F3 ; restore BASIC execute pointer from temp and return + +; get value from line + +LAB_GVAL + JSR LAB_IGBY ; increment and scan memory + BCS LAB_1BAC ; branch if not numeric character + + ; else numeric string found (e.g. 123) +LAB_1BA9 + JMP LAB_2887 ; get FAC1 from string and return + +; get value from line .. continued + + ; wasn't a number so .. +LAB_1BAC + TAX ; set the flags + BMI LAB_1BD0 ; if -ve go test token values + + ; else it is either a string, number, variable or () + CMP #'$' ; compare with "$" + BEQ LAB_1BA9 ; branch if "$", hex number + + CMP #'%' ; else compare with "%" + BEQ LAB_1BA9 ; branch if "%", binary number + + CMP #'.' ; compare with "." + BEQ LAB_1BA9 ; if so get FAC1 from string and return (e.g. was .123) + + ; it wasn't any sort of number so .. + CMP #$22 ; compare with " + BEQ LAB_1BC1 ; branch if open quote + + ; wasn't any sort of number so .. + +; evaluate expression within parentheses + + CMP #'(' ; compare with "(" + BNE LAB_1C18 ; if not "(" get (var), return value in FAC1 and $ flag + +LAB_1BF7 + JSR LAB_EVEZ ; evaluate expression, no decrement + +; all the 'scan for' routines return the character after the sought character + +; scan for ")" , else do syntax error then warm start + +LAB_1BFB + LDA #$29 ; load A with ")" + +; scan for CHR$(A) , else do syntax error then warm start + +LAB_SCCA + LDY #$00 ; clear index + CMP (Bpntrl),Y ; check next byte is = A + BNE LAB_SNER ; if not do syntax error then warm start + + JMP LAB_IGBY ; increment and scan memory then return + +; scan for "(" , else do syntax error then warm start + +LAB_1BFE + LDA #$28 ; load A with "(" + BNE LAB_SCCA ; scan for CHR$(A), else do syntax error then warm start + ; (branch always) + +; scan for "," , else do syntax error then warm start + +LAB_1C01 + LDA #$2C ; load A with "," + BNE LAB_SCCA ; scan for CHR$(A), else do syntax error then warm start + ; (branch always) + +; syntax error then warm start + +LAB_SNER + LDX #$02 ; error code $02 ("Syntax" error) + JMP LAB_XERR ; do error #X, then warm start + +; get value from line .. continued +; do tokens + +LAB_1BD0 + CMP #TK_MINUS ; compare with token for - + BEQ LAB_1C11 ; branch if - token (do set-up for functions) + + ; wasn't -n so .. + CMP #TK_PLUS ; compare with token for + + BEQ LAB_GVAL ; branch if + token (+n = n so ignore leading +) + + CMP #TK_NOT ; compare with token for NOT + BNE LAB_1BE7 ; branch if not token for NOT + + ; was NOT token +TK_EQUAL_PLUS = TK_EQUAL-TK_PLUS + LDY #TK_EQUAL_PLUS*3 ; offset to NOT function + BNE LAB_1C13 ; do set-up for function then execute (branch always) + +; do = compare + +LAB_EQUAL + JSR LAB_EVIR ; evaluate integer expression (no sign check) + LDA FAC1_3 ; get FAC1 mantissa3 + EOR #$FF ; invert it + TAY ; copy it + LDA FAC1_2 ; get FAC1 mantissa2 + EOR #$FF ; invert it + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +; get value from line .. continued + + ; wasn't +, -, or NOT so .. +LAB_1BE7 + CMP #TK_FN ; compare with token for FN + BNE LAB_1BEE ; branch if not token for FN + + JMP LAB_201E ; go evaluate FNx + +; get value from line .. continued + + ; wasn't +, -, NOT or FN so .. +LAB_1BEE + SBC #TK_SGN ; subtract with token for SGN + BCS LAB_1C27 ; if a function token go do it + + JMP LAB_SNER ; else do syntax error + +; set-up for functions + +LAB_1C11 +TK_GT_PLUS = TK_GT-TK_PLUS + LDY #TK_GT_PLUS*3 ; set offset from base to > operator +LAB_1C13 + PLA ; dump return address low byte + PLA ; dump return address high byte + JMP LAB_1B1D ; execute function then continue evaluation + +; variable name set-up +; get (var), return value in FAC_1 and $ flag + +LAB_1C18 + JSR LAB_GVAR ; get (var) address + STA FAC1_2 ; save address low byte in FAC1 mantissa2 + STY FAC1_3 ; save address high byte in FAC1 mantissa3 + LDX Dtypef ; get data type flag, $FF=string, $00=numeric + BMI LAB_1C25 ; if string then return (does RTS) + +LAB_1C24 + JMP LAB_UFAC ; unpack memory (AY) into FAC1 + +LAB_1C25 + RTS + +; get value from line .. continued +; only functions left so .. + +; set up function references + +; new for V2.0+ this replaces a lot of IF .. THEN .. ELSEIF .. THEN .. that was needed +; to process function calls. now the function vector is computed and pushed on the stack +; and the preprocess offset is read. if the preprocess offset is non zero then the vector +; is calculated and the routine called, if not this routine just does RTS. whichever +; happens the RTS at the end of this routine, or the end of the preprocess routine, calls +; the function code + +; this also removes some less than elegant code that was used to bypass type checking +; for functions that returned strings + +LAB_1C27 + ASL ; *2 (2 bytes per function address) + TAY ; copy to index + + LDA LAB_FTBM,Y ; get function jump vector high byte + PHA ; push functions jump vector high byte + LDA LAB_FTBL,Y ; get function jump vector low byte + PHA ; push functions jump vector low byte + + LDA LAB_FTPM,Y ; get function pre process vector high byte + BEQ LAB_1C56 ; skip pre process if null vector + + PHA ; push functions pre process vector high byte + LDA LAB_FTPL,Y ; get function pre process vector low byte + PHA ; push functions pre process vector low byte + +LAB_1C56 + RTS ; do function, or pre process, call + +; process string expression in parenthesis + +LAB_PPFS + JSR LAB_1BF7 ; process expression in parenthesis + JMP LAB_CTST ; check if source is string then do function, + ; else do type mismatch + +; process numeric expression in parenthesis + +LAB_PPFN + JSR LAB_1BF7 ; process expression in parenthesis + JMP LAB_CTNM ; check if source is numeric then do function, + ; else do type mismatch + +; set numeric data type and increment BASIC execute pointer + +LAB_PPBI + LSR Dtypef ; clear data type flag, $FF=string, $00=numeric + JMP LAB_IGBY ; increment and scan memory then do function + +; process string for LEFT$, RIGHT$ or MID$ + +LAB_LRMS + JSR LAB_EVEZ ; evaluate (should be string) expression + JSR LAB_1C01 ; scan for ",", else do syntax error then warm start + JSR LAB_CTST ; check if source is string, else do type mismatch + + PLA ; get function jump vector low byte + TAX ; save functions jump vector low byte + PLA ; get function jump vector high byte + TAY ; save functions jump vector high byte + LDA des_ph ; get descriptor pointer high byte + PHA ; push string pointer high byte + LDA des_pl ; get descriptor pointer low byte + PHA ; push string pointer low byte + TYA ; get function jump vector high byte back + PHA ; save functions jump vector high byte + TXA ; get function jump vector low byte back + PHA ; save functions jump vector low byte + JSR LAB_GTBY ; get byte parameter + TXA ; copy byte parameter to A + RTS ; go do function + +; process numeric expression(s) for BIN$ or HEX$ + +LAB_BHSS + JSR LAB_EVEZ ; process expression + JSR LAB_CTNM ; check if source is numeric, else do type mismatch + LDA FAC1_e ; get FAC1 exponent + CMP #$98 ; compare with exponent = 2^24 + BCS LAB_BHER ; branch if n>=2^24 (is too big) + + JSR LAB_2831 ; convert FAC1 floating-to-fixed + LDX #$02 ; 3 bytes to do +LAB_CFAC + LDA FAC1_1,X ; get byte from FAC1 + STA nums_1,X ; save byte to temp + DEX ; decrement index + BPL LAB_CFAC ; copy FAC1 mantissa to temp + + JSR LAB_GBYT ; get next BASIC byte + LDX #$00 ; set default to no leading "0"s + CMP #')' ; compare with close bracket + BEQ LAB_1C54 ; if ")" go do rest of function + + JSR LAB_SCGB ; scan for "," and get byte + JSR LAB_GBYT ; get last byte back + CMP #')' ; is next character ) + BNE LAB_BHER ; if not ")" go do error + +LAB_1C54 + RTS ; else do function + +LAB_BHER + JMP LAB_FCER ; do function call error then warm start + +; perform EOR + +; added operator format is the same as AND or OR, precedence is the same as OR + +; this bit worked first time but it took a while to sort out the operator table +; pointers and offsets afterwards! + +LAB_EOR + JSR GetFirst ; get first integer expression (no sign check) + EOR XOAw_l ; EOR with expression 1 low byte + TAY ; save in Y + LDA FAC1_2 ; get FAC1 mantissa2 + EOR XOAw_h ; EOR with expression 1 high byte + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +; perform OR + +LAB_OR + JSR GetFirst ; get first integer expression (no sign check) + ORA XOAw_l ; OR with expression 1 low byte + TAY ; save in Y + LDA FAC1_2 ; get FAC1 mantissa2 + ORA XOAw_h ; OR with expression 1 high byte + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +; perform AND + +LAB_AND + JSR GetFirst ; get first integer expression (no sign check) + AND XOAw_l ; AND with expression 1 low byte + TAY ; save in Y + LDA FAC1_2 ; get FAC1 mantissa2 + AND XOAw_h ; AND with expression 1 high byte + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +; get first value for OR, AND or EOR + +GetFirst + JSR LAB_EVIR ; evaluate integer expression (no sign check) + LDA FAC1_2 ; get FAC1 mantissa2 + STA XOAw_h ; save it + LDA FAC1_3 ; get FAC1 mantissa3 + STA XOAw_l ; save it + JSR LAB_279B ; copy FAC2 to FAC1 (get 2nd value in expression) + JSR LAB_EVIR ; evaluate integer expression (no sign check) + LDA FAC1_3 ; get FAC1 mantissa3 +LAB_1C95 + RTS + +; perform comparisons + +; do < compare + +LAB_LTHAN + JSR LAB_CKTM ; type match check, set C for string + BCS LAB_1CAE ; branch if string + + ; do numeric < compare + LDA FAC2_s ; get FAC2 sign (b7) + ORA #$7F ; set all non sign bits + AND FAC2_1 ; and FAC2 mantissa1 (AND in sign bit) + STA FAC2_1 ; save FAC2 mantissa1 + LDA #FAC2_e ; set pointer high byte to FAC2 + JSR LAB_27F8 ; compare FAC1 with FAC2 (AY) + TAX ; copy result + JMP LAB_1CE1 ; go evaluate result + + ; do string < compare +LAB_1CAE + LSR Dtypef ; clear data type flag, $FF=string, $00=numeric + DEC comp_f ; clear < bit in compare function flag + JSR LAB_22B6 ; pop string off descriptor stack, or from top of string + ; space returns with A = length, X=pointer low byte, + ; Y=pointer high byte + STA str_ln ; save length + STX str_pl ; save string pointer low byte + STY str_ph ; save string pointer high byte + LDA FAC2_2 ; get descriptor pointer low byte + LDY FAC2_3 ; get descriptor pointer high byte + JSR LAB_22BA ; pop (YA) descriptor off stack or from top of string space + ; returns with A = length, X=pointer low byte, + ; Y=pointer high byte + STX FAC2_2 ; save string pointer low byte + STY FAC2_3 ; save string pointer high byte + TAX ; copy length + SEC ; set carry for subtract + SBC str_ln ; subtract string 1 length + BEQ LAB_1CD6 ; branch if str 1 length = string 2 length + + LDA #$01 ; set str 1 length > string 2 length + BCC LAB_1CD6 ; branch if so + + LDX str_ln ; get string 1 length + LDA #$FF ; set str 1 length < string 2 length +LAB_1CD6 + STA FAC1_s ; save length compare + LDY #$FF ; set index + INX ; adjust for loop +LAB_1CDB + INY ; increment index + DEX ; decrement count + BNE LAB_1CE6 ; branch if still bytes to do + + LDX FAC1_s ; get length compare back +LAB_1CE1 + BMI LAB_1CF2 ; branch if str 1 < str 2 + + CLC ; flag str 1 <= str 2 + BCC LAB_1CF2 ; go evaluate result + +LAB_1CE6 + LDA (FAC2_2),Y ; get string 2 byte + CMP (FAC1_1),Y ; compare with string 1 byte + BEQ LAB_1CDB ; loop if bytes = + + LDX #$FF ; set str 1 < string 2 + BCS LAB_1CF2 ; branch if so + + LDX #$01 ; set str 1 > string 2 +LAB_1CF2 + INX ; x = 0, 1 or 2 + TXA ; copy to A + ROL ; *2 (1, 2 or 4) + AND Cflag ; AND with comparison evaluation flag + BEQ LAB_1CFB ; branch if 0 (compare is false) + + LDA #$FF ; else set result true +LAB_1CFB + JMP LAB_27DB ; save A as integer byte and return + +LAB_1CFE + JSR LAB_1C01 ; scan for ",", else do syntax error then warm start + +; perform DIM + +LAB_DIM + TAX ; copy "DIM" flag to X + JSR LAB_1D10 ; search for variable + JSR LAB_GBYT ; scan memory + BNE LAB_1CFE ; scan for "," and loop if not null + + RTS + +; perform << (left shift) + +LAB_LSHIFT + JSR GetPair ; get integer expression and byte (no sign check) + LDA FAC1_2 ; get expression high byte + LDX TempB ; get shift count + BEQ NoShift ; branch if zero + + CPX #$10 ; compare bit count with 16d + BCS TooBig ; branch if >= + +Ls_loop + ASL FAC1_3 ; shift low byte + ROL ; shift high byte + DEX ; decrement bit count + BNE Ls_loop ; loop if shift not complete + + LDY FAC1_3 ; get expression low byte + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +; perform >> (right shift) + +LAB_RSHIFT + JSR GetPair ; get integer expression and byte (no sign check) + LDA FAC1_2 ; get expression high byte + LDX TempB ; get shift count + BEQ NoShift ; branch if zero + + CPX #$10 ; compare bit count with 16d + BCS TooBig ; branch if >= + +Rs_loop + LSR ; shift high byte + ROR FAC1_3 ; shift low byte + DEX ; decrement bit count + BNE Rs_loop ; loop if shift not complete + +NoShift + LDY FAC1_3 ; get expression low byte + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +TooBig + LDA #$00 ; clear high byte + TAY ; copy to low byte + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +GetPair + JSR LAB_EVBY ; evaluate byte expression, result in X + STX TempB ; save it + JSR LAB_279B ; copy FAC2 to FAC1 (get 2nd value in expression) + JMP LAB_EVIR ; evaluate integer expression (no sign check) + +; search for variable + +; return pointer to variable in Cvaral/Cvarah + +LAB_GVAR + LDX #$00 ; set DIM flag = $00 + JSR LAB_GBYT ; scan memory (1st character) +LAB_1D10 + STX Defdim ; save DIM flag +LAB_1D12 + STA Varnm1 ; save 1st character + AND #$7F ; clear FN flag bit + JSR LAB_CASC ; check byte, return C=0 if<"A" or >"Z" + BCS LAB_1D1F ; branch if ok + + JMP LAB_SNER ; else syntax error then warm start + + ; was variable name so .. +LAB_1D1F + LDX #$00 ; clear 2nd character temp + STX Dtypef ; clear data type flag, $FF=string, $00=numeric + JSR LAB_IGBY ; increment and scan memory (2nd character) + BCC LAB_1D2D ; branch if character = "0"-"9" (ok) + + ; 2nd character wasn't "0" to "9" so .. + JSR LAB_CASC ; check byte, return C=0 if<"A" or >"Z" + BCC LAB_1D38 ; branch if <"A" or >"Z" (go check if string) + +LAB_1D2D + TAX ; copy 2nd character + + ; ignore further (valid) characters in the variable name +LAB_1D2E + JSR LAB_IGBY ; increment and scan memory (3rd character) + BCC LAB_1D2E ; loop if character = "0"-"9" (ignore) + + JSR LAB_CASC ; check byte, return C=0 if<"A" or >"Z" + BCS LAB_1D2E ; loop if character = "A"-"Z" (ignore) + + ; check if string variable +LAB_1D38 + CMP #'$' ; compare with "$" + BNE LAB_1D47 ; branch if not string + +; to introduce a new variable type (% suffix for integers say) then this branch +; will need to go to that check and then that branch, if it fails, go to LAB_1D47 + + ; type is string + LDA #$FF ; set data type = string + STA Dtypef ; set data type flag, $FF=string, $00=numeric + TXA ; get 2nd character back + ORA #$80 ; set top bit (indicate string var) + TAX ; copy back to 2nd character temp + JSR LAB_IGBY ; increment and scan memory + +; after we have determined the variable type we need to come back here to determine +; if it's an array of type. this would plug in a%(b[,c[,d]])) integer arrays nicely + + +LAB_1D47 ; gets here with character after var name in A + STX Varnm2 ; save 2nd character + ORA Sufnxf ; or with subscript/FNX flag (or FN name) + CMP #'(' ; compare with "(" + BNE LAB_1D53 ; branch if not "(" + + JMP LAB_1E17 ; go find, or make, array + +; either find or create var +; var name (1st two characters only!) is in Varnm1,Varnm2 + + ; variable name wasn't var(... so look for plain var +LAB_1D53 + LDA #$00 ; clear A + STA Sufnxf ; clear subscript/FNX flag + LDA Svarl ; get start of vars low byte + LDX Svarh ; get start of vars high byte + LDY #$00 ; clear index +LAB_1D5D + STX Vrschh ; save search address high byte +LAB_1D5F + STA Vrschl ; save search address low byte + CPX Sarryh ; compare high address with var space end + BNE LAB_1D69 ; skip next compare if <> + + ; high addresses were = so compare low addresses + CMP Sarryl ; compare low address with var space end + BEQ LAB_1D8B ; if not found go make new var + +LAB_1D69 + LDA Varnm1 ; get 1st character of var to find + CMP (Vrschl),Y ; compare with variable name 1st character + BNE LAB_1D77 ; branch if no match + + ; 1st characters match so compare 2nd characters + LDA Varnm2 ; get 2nd character of var to find + INY ; index to point to variable name 2nd character + CMP (Vrschl),Y ; compare with variable name 2nd character + BEQ LAB_1DD7 ; branch if match (found var) + + DEY ; else decrement index (now = $00) +LAB_1D77 + CLC ; clear carry for add + LDA Vrschl ; get search address low byte + ADC #$06 ; +6 (offset to next var name) + BCC LAB_1D5F ; loop if no overflow to high byte + + INX ; else increment high byte + BNE LAB_1D5D ; loop always (RAM doesn't extend to $FFFF !) + +; check byte, return C=0 if<"A" or >"Z" or "a" to "z" + +LAB_CASC + CMP #'a' ; compare with "a" + BCS LAB_1D83 ; go check <"z"+1 + +; check byte, return C=0 if<"A" or >"Z" + +LAB_1D82 + CMP #'A' ; compare with "A" + BCC LAB_1D8A ; exit if less + + ; carry is set + SBC #$5B ; subtract "Z"+1 + SEC ; set carry + SBC #$A5 ; subtract $A5 (restore byte) + ; carry clear if byte>$5A +LAB_1D8A + RTS + +LAB_1D83 + SBC #$7B ; subtract "z"+1 + SEC ; set carry + SBC #$85 ; subtract $85 (restore byte) + ; carry clear if byte>$7A + RTS + + ; reached end of variable mem without match + ; .. so create new variable +LAB_1D8B + PLA ; pop return address low byte + PHA ; push return address low byte +LAB_1C18p2 = LAB_1C18+2 + CMP #LAB_1D96 ; high byte point to $00,$00 + RTS + + ; create new numeric variable +LAB_1D98 + LDA Sarryl ; get var mem end low byte + LDY Sarryh ; get var mem end high byte + STA Ostrtl ; save old block start low byte + STY Ostrth ; save old block start high byte + LDA Earryl ; get array mem end low byte + LDY Earryh ; get array mem end high byte + STA Obendl ; save old block end low byte + STY Obendh ; save old block end high byte + CLC ; clear carry for add + ADC #$06 ; +6 (space for one var) + BCC LAB_1DAE ; branch if no overflow to high byte + + INY ; else increment high byte +LAB_1DAE + STA Nbendl ; set new block end low byte + STY Nbendh ; set new block end high byte + JSR LAB_11CF ; open up space in memory + LDA Nbendl ; get new start low byte + LDY Nbendh ; get new start high byte (-$100) + INY ; correct high byte + STA Sarryl ; save new var mem end low byte + STY Sarryh ; save new var mem end high byte + LDY #$00 ; clear index + LDA Varnm1 ; get var name 1st character + STA (Vrschl),Y ; save var name 1st character + INY ; increment index + LDA Varnm2 ; get var name 2nd character + STA (Vrschl),Y ; save var name 2nd character + LDA #$00 ; clear A + INY ; increment index + STA (Vrschl),Y ; initialise var byte + INY ; increment index + STA (Vrschl),Y ; initialise var byte + INY ; increment index + STA (Vrschl),Y ; initialise var byte + INY ; increment index + STA (Vrschl),Y ; initialise var byte + + ; found a match for var ((Vrschl) = ptr) +LAB_1DD7 + LDA Vrschl ; get var address low byte + CLC ; clear carry for add + ADC #$02 ; +2 (offset past var name bytes) + LDY Vrschh ; get var address high byte + BCC LAB_1DE1 ; branch if no overflow from add + + INY ; else increment high byte +LAB_1DE1 + STA Cvaral ; save current var address low byte + STY Cvarah ; save current var address high byte + RTS + +; set-up array pointer (Adatal/h) to first element in array +; set Adatal,Adatah to Astrtl,Astrth+2*Dimcnt+#$05 + +LAB_1DE6 + LDA Dimcnt ; get # of dimensions (1, 2 or 3) + ASL ; *2 (also clears the carry !) + ADC #$05 ; +5 (result is 7, 9 or 11 here) + ADC Astrtl ; add array start pointer low byte + LDY Astrth ; get array pointer high byte + BCC LAB_1DF2 ; branch if no overflow + + INY ; else increment high byte +LAB_1DF2 + STA Adatal ; save array data pointer low byte + STY Adatah ; save array data pointer high byte + RTS + +; evaluate integer expression + +LAB_EVIN + JSR LAB_IGBY ; increment and scan memory + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch + +; evaluate integer expression (no check) + +LAB_EVPI + LDA FAC1_s ; get FAC1 sign (b7) + BMI LAB_1E12 ; do function call error if -ve + +; evaluate integer expression (no sign check) + +LAB_EVIR + LDA FAC1_e ; get FAC1 exponent + CMP #$90 ; compare with exponent = 2^16 (n>2^15) + BCC LAB_1E14 ; branch if n<2^16 (is ok) + + LDA #LAB_1DF7 ; set pointer high byte to -32768 + JSR LAB_27F8 ; compare FAC1 with (AY) +LAB_1E12 + BNE LAB_FCER ; if <> do function call error then warm start + +LAB_1E14 + JMP LAB_2831 ; convert FAC1 floating-to-fixed and return + +; find or make array + +LAB_1E17 + LDA Defdim ; get DIM flag + PHA ; push it + LDA Dtypef ; get data type flag, $FF=string, $00=numeric + PHA ; push it + LDY #$00 ; clear dimensions count + +; now get the array dimension(s) and stack it (them) before the data type and DIM flag + +LAB_1E1F + TYA ; copy dimensions count + PHA ; save it + LDA Varnm2 ; get array name 2nd byte + PHA ; save it + LDA Varnm1 ; get array name 1st byte + PHA ; save it + JSR LAB_EVIN ; evaluate integer expression + PLA ; pull array name 1st byte + STA Varnm1 ; restore array name 1st byte + PLA ; pull array name 2nd byte + STA Varnm2 ; restore array name 2nd byte + PLA ; pull dimensions count + TAY ; restore it + TSX ; copy stack pointer + LDA LAB_STAK+2,X ; get DIM flag + PHA ; push it + LDA LAB_STAK+1,X ; get data type flag + PHA ; push it + LDA FAC1_2 ; get this dimension size high byte + STA LAB_STAK+2,X ; stack before flag bytes + LDA FAC1_3 ; get this dimension size low byte + STA LAB_STAK+1,X ; stack before flag bytes + INY ; increment dimensions count + JSR LAB_GBYT ; scan memory + CMP #',' ; compare with "," + BEQ LAB_1E1F ; if found go do next dimension + + STY Dimcnt ; store dimensions count + JSR LAB_1BFB ; scan for ")" , else do syntax error then warm start + PLA ; pull data type flag + STA Dtypef ; restore data type flag, $FF=string, $00=numeric + PLA ; pull DIM flag + STA Defdim ; restore DIM flag + LDX Sarryl ; get array mem start low byte + LDA Sarryh ; get array mem start high byte + +; now check to see if we are at the end of array memory (we would be if there were +; no arrays). + +LAB_1E5C + STX Astrtl ; save as array start pointer low byte + STA Astrth ; save as array start pointer high byte + CMP Earryh ; compare with array mem end high byte + BNE LAB_1E68 ; branch if not reached array mem end + + CPX Earryl ; else compare with array mem end low byte + BEQ LAB_1EA1 ; go build array if not found + + ; search for array +LAB_1E68 + LDY #$00 ; clear index + LDA (Astrtl),Y ; get array name first byte + INY ; increment index to second name byte + CMP Varnm1 ; compare with this array name first byte + BNE LAB_1E77 ; branch if no match + + LDA Varnm2 ; else get this array name second byte + CMP (Astrtl),Y ; compare with array name second byte + BEQ LAB_1E8D ; array found so branch + + ; no match +LAB_1E77 + INY ; increment index + LDA (Astrtl),Y ; get array size low byte + CLC ; clear carry for add + ADC Astrtl ; add array start pointer low byte + TAX ; copy low byte to X + INY ; increment index + LDA (Astrtl),Y ; get array size high byte + ADC Astrth ; add array mem pointer high byte + BCC LAB_1E5C ; if no overflow go check next array + +; do array bounds error + +LAB_1E85 + LDX #$10 ; error code $10 ("Array bounds" error) + .byte $2C ; makes next bit BIT LAB_08A2 + +; do function call error + +LAB_FCER + LDX #$08 ; error code $08 ("Function call" error) +LAB_1E8A + JMP LAB_XERR ; do error #X, then warm start + + ; found array, are we trying to dimension it? +LAB_1E8D + LDX #$12 ; set error $12 ("Double dimension" error) + LDA Defdim ; get DIM flag + BNE LAB_1E8A ; if we are trying to dimension it do error #X, then warm + ; start + +; found the array and we're not dimensioning it so we must find an element in it + + JSR LAB_1DE6 ; set-up array pointer (Adatal/h) to first element in array + ; (Astrtl,Astrth points to start of array) + LDA Dimcnt ; get dimensions count + LDY #$04 ; set index to array's # of dimensions + CMP (Astrtl),Y ; compare with no of dimensions + BNE LAB_1E85 ; if wrong do array bounds error, could do "Wrong + ; dimensions" error here .. if we want a different + ; error message + + JMP LAB_1F28 ; found array so go get element + ; (could jump to LAB_1F28 as all LAB_1F24 does is take + ; Dimcnt and save it at (Astrtl),Y which is already the + ; same or we would have taken the BNE) + + ; array not found, so build it +LAB_1EA1 + JSR LAB_1DE6 ; set-up array pointer (Adatal/h) to first element in array + ; (Astrtl,Astrth points to start of array) + JSR LAB_121F ; check available memory, "Out of memory" error if no room + ; addr to check is in AY (low/high) + LDY #$00 ; clear Y (don't need to clear A) + STY Aspth ; clear array data size high byte + LDA Varnm1 ; get variable name 1st byte + STA (Astrtl),Y ; save array name 1st byte + INY ; increment index + LDA Varnm2 ; get variable name 2nd byte + STA (Astrtl),Y ; save array name 2nd byte + LDA Dimcnt ; get dimensions count + LDY #$04 ; index to dimension count + STY Asptl ; set array data size low byte (four bytes per element) + STA (Astrtl),Y ; set array's dimensions count + + ; now calculate the size of the data space for the array + CLC ; clear carry for add (clear on subsequent loops) +LAB_1EC0 + LDX #$0B ; set default dimension value low byte + LDA #$00 ; set default dimension value high byte + BIT Defdim ; test default DIM flag + BVC LAB_1ED0 ; branch if b6 of Defdim is clear + + PLA ; else pull dimension value low byte + ADC #$01 ; +1 (allow for zeroeth element) + TAX ; copy low byte to X + PLA ; pull dimension value high byte + ADC #$00 ; add carry from low byte + +LAB_1ED0 + INY ; index to dimension value high byte + STA (Astrtl),Y ; save dimension value high byte + INY ; index to dimension value high byte + TXA ; get dimension value low byte + STA (Astrtl),Y ; save dimension value low byte + JSR LAB_1F7C ; does XY = (Astrtl),Y * (Asptl) + STX Asptl ; save array data size low byte + STA Aspth ; save array data size high byte + LDY ut1_pl ; restore index (saved by subroutine) + DEC Dimcnt ; decrement dimensions count + BNE LAB_1EC0 ; loop while not = 0 + + ADC Adatah ; add size high byte to first element high byte + ; (carry is always clear here) + BCS LAB_1F45 ; if overflow go do "Out of memory" error + + STA Adatah ; save end of array high byte + TAY ; copy end high byte to Y + TXA ; get array size low byte + ADC Adatal ; add array start low byte + BCC LAB_1EF3 ; branch if no carry + + INY ; else increment end of array high byte + BEQ LAB_1F45 ; if overflow go do "Out of memory" error + + ; set-up mostly complete, now zero the array +LAB_1EF3 + JSR LAB_121F ; check available memory, "Out of memory" error if no room + ; addr to check is in AY (low/high) + STA Earryl ; save array mem end low byte + STY Earryh ; save array mem end high byte + LDA #$00 ; clear byte for array clear + INC Aspth ; increment array size high byte (now block count) + LDY Asptl ; get array size low byte (now index to block) + BEQ LAB_1F07 ; branch if low byte = $00 + +LAB_1F02 + DEY ; decrement index (do 0 to n-1) + STA (Adatal),Y ; zero byte + BNE LAB_1F02 ; loop until this block done + +LAB_1F07 + DEC Adatah ; decrement array pointer high byte + DEC Aspth ; decrement block count high byte + BNE LAB_1F02 ; loop until all blocks done + + INC Adatah ; correct for last loop + SEC ; set carry for subtract + LDY #$02 ; index to array size low byte + LDA Earryl ; get array mem end low byte + SBC Astrtl ; subtract array start low byte + STA (Astrtl),Y ; save array size low byte + INY ; index to array size high byte + LDA Earryh ; get array mem end high byte + SBC Astrth ; subtract array start high byte + STA (Astrtl),Y ; save array size high byte + LDA Defdim ; get default DIM flag + BNE LAB_1F7B ; exit (RET) if this was a DIM command + + ; else, find element + INY ; index to # of dimensions + +LAB_1F24 + LDA (Astrtl),Y ; get array's dimension count + STA Dimcnt ; save it + +; we have found, or built, the array. now we need to find the element + +LAB_1F28 + LDA #$00 ; clear byte + STA Asptl ; clear array data pointer low byte +LAB_1F2C + STA Aspth ; save array data pointer high byte + INY ; increment index (point to array bound high byte) + PLA ; pull array index low byte + TAX ; copy to X + STA FAC1_2 ; save index low byte to FAC1 mantissa2 + PLA ; pull array index high byte + STA FAC1_3 ; save index high byte to FAC1 mantissa3 + CMP (Astrtl),Y ; compare with array bound high byte + BCC LAB_1F48 ; branch if within bounds + + BNE LAB_1F42 ; if outside bounds do array bounds error + + ; else high byte was = so test low bytes + INY ; index to array bound low byte + TXA ; get array index low byte + CMP (Astrtl),Y ; compare with array bound low byte + BCC LAB_1F49 ; branch if within bounds + +LAB_1F42 + JMP LAB_1E85 ; else do array bounds error + +LAB_1F45 + JMP LAB_OMER ; do "Out of memory" error then warm start + +LAB_1F48 + INY ; index to array bound low byte +LAB_1F49 + LDA Aspth ; get array data pointer high byte + ORA Asptl ; OR with array data pointer low byte + BEQ LAB_1F5A ; branch if array data pointer = null (skip multiply) + + JSR LAB_1F7C ; does XY = (Astrtl),Y * (Asptl) + TXA ; get result low byte + ADC FAC1_2 ; add index low byte from FAC1 mantissa2 + TAX ; save result low byte + TYA ; get result high byte + LDY ut1_pl ; restore index +LAB_1F5A + ADC FAC1_3 ; add index high byte from FAC1 mantissa3 + STX Asptl ; save array data pointer low byte + DEC Dimcnt ; decrement dimensions count + BNE LAB_1F2C ; loop if dimensions still to do + + ASL Asptl ; array data pointer low byte * 2 + ROL ; array data pointer high byte * 2 + ASL Asptl ; array data pointer low byte * 4 + ROL ; array data pointer high byte * 4 + TAY ; copy high byte + LDA Asptl ; get low byte + ADC Adatal ; add array data start pointer low byte + STA Cvaral ; save as current var address low byte + TYA ; get high byte back + ADC Adatah ; add array data start pointer high byte + STA Cvarah ; save as current var address high byte + TAY ; copy high byte to Y + LDA Cvaral ; get current var address low byte +LAB_1F7B + RTS + +; does XY = (Astrtl),Y * (Asptl) + +LAB_1F7C + STY ut1_pl ; save index + LDA (Astrtl),Y ; get dimension size low byte + STA dims_l ; save dimension size low byte + DEY ; decrement index + LDA (Astrtl),Y ; get dimension size high byte + STA dims_h ; save dimension size high byte + + LDA #$10 ; count = $10 (16 bit multiply) + STA numbit ; save bit count + LDX #$00 ; clear result low byte + LDY #$00 ; clear result high byte +LAB_1F8F + TXA ; get result low byte + ASL ; *2 + TAX ; save result low byte + TYA ; get result high byte + ROL ; *2 + TAY ; save result high byte + BCS LAB_1F45 ; if overflow go do "Out of memory" error + + ASL Asptl ; shift multiplier low byte + ROL Aspth ; shift multiplier high byte + BCC LAB_1FA8 ; skip add if no carry + + CLC ; else clear carry for add + TXA ; get result low byte + ADC dims_l ; add dimension size low byte + TAX ; save result low byte + TYA ; get result high byte + ADC dims_h ; add dimension size high byte + TAY ; save result high byte + BCS LAB_1F45 ; if overflow go do "Out of memory" error + +LAB_1FA8 + DEC numbit ; decrement bit count + BNE LAB_1F8F ; loop until all done + + RTS + +; perform FRE() + +LAB_FRE + LDA Dtypef ; get data type flag, $FF=string, $00=numeric + BPL LAB_1FB4 ; branch if numeric + + JSR LAB_22B6 ; pop string off descriptor stack, or from top of string + ; space returns with A = length, X=$71=pointer low byte, + ; Y=$72=pointer high byte + + ; FRE(n) was numeric so do this +LAB_1FB4 + JSR LAB_GARB ; go do garbage collection + SEC ; set carry for subtract + LDA Sstorl ; get bottom of string space low byte + SBC Earryl ; subtract array mem end low byte + TAY ; copy result to Y + LDA Sstorh ; get bottom of string space high byte + SBC Earryh ; subtract array mem end high byte + +; save and convert integer AY to FAC1 + +LAB_AYFC + LSR Dtypef ; clear data type flag, $FF=string, $00=numeric + STA FAC1_1 ; save FAC1 mantissa1 + STY FAC1_2 ; save FAC1 mantissa2 + LDX #$90 ; set exponent=2^16 (integer) + JMP LAB_27E3 ; set exp=X, clear FAC1_3, normalise and return + +; perform POS() + +LAB_POS + LDY TPos ; get terminal position + +; convert Y to byte in FAC1 + +LAB_1FD0 + LDA #$00 ; clear high byte + BEQ LAB_AYFC ; always save and convert integer AY to FAC1 and return + +; check not Direct (used by DEF and INPUT) + +LAB_CKRN + LDX Clineh ; get current line high byte + INX ; increment it + BNE LAB_1F7B ; return if can continue not direct mode + + ; else do illegal direct error +LAB_1FD9 + LDX #$16 ; error code $16 ("Illegal direct" error) +LAB_1FDB + JMP LAB_XERR ; go do error #X, then warm start + +; perform DEF + +LAB_DEF + JSR LAB_200B ; check FNx syntax + STA func_l ; save function pointer low byte + STY func_h ; save function pointer high byte + JSR LAB_CKRN ; check not Direct (back here if ok) + JSR LAB_1BFE ; scan for "(" , else do syntax error then warm start + LDA #$80 ; set flag for FNx + STA Sufnxf ; save subscript/FNx flag + JSR LAB_GVAR ; get (var) address + JSR LAB_CTNM ; check if source is numeric, else do type mismatch + JSR LAB_1BFB ; scan for ")" , else do syntax error then warm start + LDA #TK_EQUAL ; get = token + JSR LAB_SCCA ; scan for CHR$(A), else do syntax error then warm start + LDA Cvarah ; get current var address high byte + PHA ; push it + LDA Cvaral ; get current var address low byte + PHA ; push it + LDA Bpntrh ; get BASIC execute pointer high byte + PHA ; push it + LDA Bpntrl ; get BASIC execute pointer low byte + PHA ; push it + JSR LAB_DATA ; go perform DATA + JMP LAB_207A ; put execute pointer and variable pointer into function + ; and return + +; check FNx syntax + +LAB_200B + LDA #TK_FN ; get FN" token + JSR LAB_SCCA ; scan for CHR$(A) , else do syntax error then warm start + ; return character after A + ORA #$80 ; set FN flag bit + STA Sufnxf ; save FN flag so array variable test fails + JSR LAB_1D12 ; search for FN variable + JMP LAB_CTNM ; check if source is numeric and return, else do type + ; mismatch + + ; Evaluate FNx +LAB_201E + JSR LAB_200B ; check FNx syntax + PHA ; push function pointer low byte + TYA ; copy function pointer high byte + PHA ; push function pointer high byte + JSR LAB_1BFE ; scan for "(", else do syntax error then warm start + JSR LAB_EVEX ; evaluate expression + JSR LAB_1BFB ; scan for ")", else do syntax error then warm start + JSR LAB_CTNM ; check if source is numeric, else do type mismatch + PLA ; pop function pointer high byte + STA func_h ; restore it + PLA ; pop function pointer low byte + STA func_l ; restore it + LDX #$20 ; error code $20 ("Undefined function" error) + LDY #$03 ; index to variable pointer high byte + LDA (func_l),Y ; get variable pointer high byte + BEQ LAB_1FDB ; if zero go do undefined function error + + STA Cvarah ; save variable address high byte + DEY ; index to variable address low byte + LDA (func_l),Y ; get variable address low byte + STA Cvaral ; save variable address low byte + TAX ; copy address low byte + + ; now stack the function variable value before use + INY ; index to mantissa_3 +LAB_2043 + LDA (Cvaral),Y ; get byte from variable + PHA ; stack it + DEY ; decrement index + BPL LAB_2043 ; loop until variable stacked + + LDY Cvarah ; get variable address high byte + JSR LAB_2778 ; pack FAC1 (function expression value) into (XY) + ; (function variable), return Y=0, always + LDA Bpntrh ; get BASIC execute pointer high byte + PHA ; push it + LDA Bpntrl ; get BASIC execute pointer low byte + PHA ; push it + LDA (func_l),Y ; get function execute pointer low byte + STA Bpntrl ; save as BASIC execute pointer low byte + INY ; index to high byte + LDA (func_l),Y ; get function execute pointer high byte + STA Bpntrh ; save as BASIC execute pointer high byte + LDA Cvarah ; get variable address high byte + PHA ; push it + LDA Cvaral ; get variable address low byte + PHA ; push it + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch + PLA ; pull variable address low byte + STA func_l ; save variable address low byte + PLA ; pull variable address high byte + STA func_h ; save variable address high byte + JSR LAB_GBYT ; scan memory + BEQ LAB_2074 ; branch if null (should be [EOL] marker) + + JMP LAB_SNER ; else syntax error then warm start + +; restore Bpntrl,Bpntrh and function variable from stack + +LAB_2074 + PLA ; pull BASIC execute pointer low byte + STA Bpntrl ; restore BASIC execute pointer low byte + PLA ; pull BASIC execute pointer high byte + STA Bpntrh ; restore BASIC execute pointer high byte + +; put execute pointer and variable pointer into function + +LAB_207A + LDY #$00 ; clear index + PLA ; pull BASIC execute pointer low byte + STA (func_l),Y ; save to function + INY ; increment index + PLA ; pull BASIC execute pointer high byte + STA (func_l),Y ; save to function + INY ; increment index + PLA ; pull current var address low byte + STA (func_l),Y ; save to function + INY ; increment index + PLA ; pull current var address high byte + STA (func_l),Y ; save to function + RTS + +; perform STR$() + +LAB_STRS + JSR LAB_CTNM ; check if source is numeric, else do type mismatch + JSR LAB_296E ; convert FAC1 to string + LDA #Decssp1 ; set result string high pointer + BEQ LAB_20AE ; print null terminated string to Sutill/Sutilh + +; Do string vector +; copy des_pl/h to des_2l/h and make string space A bytes long + +LAB_209C + LDX des_pl ; get descriptor pointer low byte + LDY des_ph ; get descriptor pointer high byte + STX des_2l ; save descriptor pointer low byte + STY des_2h ; save descriptor pointer high byte + +; make string space A bytes long +; A=length, X=Sutill=ptr low byte, Y=Sutilh=ptr high byte + +LAB_MSSP + JSR LAB_2115 ; make space in string memory for string A long + ; return X=Sutill=ptr low byte, Y=Sutilh=ptr high byte + STX str_pl ; save string pointer low byte + STY str_ph ; save string pointer high byte + STA str_ln ; save length + RTS + +; Scan, set up string +; print " terminated string to Sutill/Sutilh + +LAB_20AE + LDX #$22 ; set terminator to " + STX Srchc ; set search character (terminator 1) + STX Asrch ; set terminator 2 + +; print [Srchc] or [Asrch] terminated string to Sutill/Sutilh +; source is AY + +LAB_20B4 + STA ssptr_l ; store string start low byte + STY ssptr_h ; store string start high byte + STA str_pl ; save string pointer low byte + STY str_ph ; save string pointer high byte + LDY #$FF ; set length to -1 +LAB_20BE + INY ; increment length + LDA (ssptr_l),Y ; get byte from string + BEQ LAB_20CF ; exit loop if null byte [EOS] + + CMP Srchc ; compare with search character (terminator 1) + BEQ LAB_20CB ; branch if terminator + + CMP Asrch ; compare with terminator 2 + BNE LAB_20BE ; loop if not terminator 2 + +LAB_20CB + CMP #$22 ; compare with " + BEQ LAB_20D0 ; branch if " (carry set if = !) + +LAB_20CF + CLC ; clear carry for add (only if [EOL] terminated string) +LAB_20D0 + STY str_ln ; save length in FAC1 exponent + TYA ; copy length to A + ADC ssptr_l ; add string start low byte + STA Sendl ; save string end low byte + LDX ssptr_h ; get string start high byte + BCC LAB_20DC ; branch if no low byte overflow + + INX ; else increment high byte +LAB_20DC + STX Sendh ; save string end high byte + LDA ssptr_h ; get string start high byte + CMP #>Ram_base ; compare with start of program memory + BCS LAB_RTST ; branch if not in utility area + + ; string in utility area, move to string memory + TYA ; copy length to A + JSR LAB_209C ; copy des_pl/h to des_2l/h and make string space A bytes + ; long + LDX ssptr_l ; get string start low byte + LDY ssptr_h ; get string start high byte + JSR LAB_2298 ; store string A bytes long from XY to (Sutill) + +; check for space on descriptor stack then .. +; put string address and length on descriptor stack and update stack pointers + +LAB_RTST + LDX next_s ; get string stack pointer + CPX #des_sk+$09 ; compare with max+1 + BNE LAB_20F8 ; branch if space on string stack + + ; else do string too complex error + LDX #$1C ; error code $1C ("String too complex" error) +LAB_20F5 + JMP LAB_XERR ; do error #X, then warm start + +; put string address and length on descriptor stack and update stack pointers + +LAB_20F8 + LDA str_ln ; get string length + STA PLUS_0,X ; put on string stack + LDA str_pl ; get string pointer low byte + STA PLUS_1,X ; put on string stack + LDA str_ph ; get string pointer high byte + STA PLUS_2,X ; put on string stack + LDY #$00 ; clear Y + STX des_pl ; save string descriptor pointer low byte + STY des_ph ; save string descriptor pointer high byte (always $00) + DEY ; Y = $FF + STY Dtypef ; save data type flag, $FF=string + STX last_sl ; save old stack pointer (current top item) + INX ; update stack pointer + INX ; update stack pointer + INX ; update stack pointer + STX next_s ; save new top item value + RTS + +; Build descriptor +; make space in string memory for string A long +; return X=Sutill=ptr low byte, Y=Sutill=ptr high byte + +LAB_2115 + LSR Gclctd ; clear garbage collected flag (b7) + + ; make space for string A long +LAB_2117 + PHA ; save string length + EOR #$FF ; complement it + SEC ; set carry for subtract (twos comp add) + ADC Sstorl ; add bottom of string space low byte (subtract length) + LDY Sstorh ; get bottom of string space high byte + BCS LAB_2122 ; skip decrement if no underflow + + DEY ; decrement bottom of string space high byte +LAB_2122 + CPY Earryh ; compare with array mem end high byte + BCC LAB_2137 ; do out of memory error if less + + BNE LAB_212C ; if not = skip next test + + CMP Earryl ; compare with array mem end low byte + BCC LAB_2137 ; do out of memory error if less + +LAB_212C + STA Sstorl ; save bottom of string space low byte + STY Sstorh ; save bottom of string space high byte + STA Sutill ; save string utility ptr low byte + STY Sutilh ; save string utility ptr high byte + TAX ; copy low byte to X + PLA ; get string length back + RTS + +LAB_2137 + LDX #$0C ; error code $0C ("Out of memory" error) + LDA Gclctd ; get garbage collected flag + BMI LAB_20F5 ; if set then do error code X + + JSR LAB_GARB ; else go do garbage collection + LDA #$80 ; flag for garbage collected + STA Gclctd ; set garbage collected flag + PLA ; pull length + BNE LAB_2117 ; go try again (loop always, length should never be = $00) + +; garbage collection routine + +LAB_GARB + LDX Ememl ; get end of mem low byte + LDA Ememh ; get end of mem high byte + +; re-run routine from last ending + +LAB_214B + STX Sstorl ; set string storage low byte + STA Sstorh ; set string storage high byte + LDY #$00 ; clear index + STY garb_h ; clear working pointer high byte (flag no strings to move) + LDA Earryl ; get array mem end low byte + LDX Earryh ; get array mem end high byte + STA Histrl ; save as highest string low byte + STX Histrh ; save as highest string high byte + LDA #des_sk ; set descriptor stack pointer + STA ut1_pl ; save descriptor stack pointer low byte + STY ut1_ph ; save descriptor stack pointer high byte ($00) +LAB_2161 + CMP next_s ; compare with descriptor stack pointer + BEQ LAB_216A ; branch if = + + JSR LAB_21D7 ; go garbage collect descriptor stack + BEQ LAB_2161 ; loop always + + ; done stacked strings, now do string vars +LAB_216A + ASL g_step ; set step size = $06 + LDA Svarl ; get start of vars low byte + LDX Svarh ; get start of vars high byte + STA ut1_pl ; save as pointer low byte + STX ut1_ph ; save as pointer high byte +LAB_2176 + CPX Sarryh ; compare start of arrays high byte + BNE LAB_217E ; branch if no high byte match + + CMP Sarryl ; else compare start of arrays low byte + BEQ LAB_2183 ; branch if = var mem end + +LAB_217E + JSR LAB_21D1 ; go garbage collect strings + BEQ LAB_2176 ; loop always + + ; done string vars, now do string arrays +LAB_2183 + STA Nbendl ; save start of arrays low byte as working pointer + STX Nbendh ; save start of arrays high byte as working pointer + LDA #$04 ; set step size + STA g_step ; save step size +LAB_218B + LDA Nbendl ; get pointer low byte + LDX Nbendh ; get pointer high byte +LAB_218F + CPX Earryh ; compare with array mem end high byte + BNE LAB_219A ; branch if not at end + + CMP Earryl ; else compare with array mem end low byte + BEQ LAB_2216 ; tidy up and exit if at end + +LAB_219A + STA ut1_pl ; save pointer low byte + STX ut1_ph ; save pointer high byte + LDY #$02 ; set index + LDA (ut1_pl),Y ; get array size low byte + ADC Nbendl ; add start of this array low byte + STA Nbendl ; save start of next array low byte + INY ; increment index + LDA (ut1_pl),Y ; get array size high byte + ADC Nbendh ; add start of this array high byte + STA Nbendh ; save start of next array high byte + LDY #$01 ; set index + LDA (ut1_pl),Y ; get name second byte + BPL LAB_218B ; skip if not string array + +; was string array so .. + + LDY #$04 ; set index + LDA (ut1_pl),Y ; get # of dimensions + ASL ; *2 + ADC #$05 ; +5 (array header size) + JSR LAB_2208 ; go set up for first element +LAB_21C4 + CPX Nbendh ; compare with start of next array high byte + BNE LAB_21CC ; branch if <> (go do this array) + + CMP Nbendl ; else compare element pointer low byte with next array + ; low byte + BEQ LAB_218F ; if equal then go do next array + +LAB_21CC + JSR LAB_21D7 ; go defrag array strings + BEQ LAB_21C4 ; go do next array string (loop always) + +; defrag string variables +; enter with XA = variable pointer +; return with XA = next variable pointer + +LAB_21D1 + INY ; increment index (Y was $00) + LDA (ut1_pl),Y ; get var name byte 2 + BPL LAB_2206 ; if not string, step pointer to next var and return + + INY ; else increment index +LAB_21D7 + LDA (ut1_pl),Y ; get string length + BEQ LAB_2206 ; if null, step pointer to next string and return + + INY ; else increment index + LDA (ut1_pl),Y ; get string pointer low byte + TAX ; copy to X + INY ; increment index + LDA (ut1_pl),Y ; get string pointer high byte + CMP Sstorh ; compare bottom of string space high byte + BCC LAB_21EC ; branch if less + + BNE LAB_2206 ; if greater, step pointer to next string and return + + ; high bytes were = so compare low bytes + CPX Sstorl ; compare bottom of string space low byte + BCS LAB_2206 ; if >=, step pointer to next string and return + + ; string pointer is < string storage pointer (pos in mem) +LAB_21EC + CMP Histrh ; compare to highest string high byte + BCC LAB_2207 ; if <, step pointer to next string and return + + BNE LAB_21F6 ; if > update pointers, step to next and return + + ; high bytes were = so compare low bytes + CPX Histrl ; compare to highest string low byte + BCC LAB_2207 ; if <, step pointer to next string and return + + ; string is in string memory space +LAB_21F6 + STX Histrl ; save as new highest string low byte + STA Histrh ; save as new highest string high byte + LDA ut1_pl ; get start of vars(descriptors) low byte + LDX ut1_ph ; get start of vars(descriptors) high byte + STA garb_l ; save as working pointer low byte + STX garb_h ; save as working pointer high byte + DEY ; decrement index DIFFERS + DEY ; decrement index (should point to descriptor start) + STY g_indx ; save index pointer + + ; step pointer to next string +LAB_2206 + CLC ; clear carry for add +LAB_2207 + LDA g_step ; get step size +LAB_2208 + ADC ut1_pl ; add pointer low byte + STA ut1_pl ; save pointer low byte + BCC LAB_2211 ; branch if no overflow + + INC ut1_ph ; else increment high byte +LAB_2211 + LDX ut1_ph ; get pointer high byte + LDY #$00 ; clear Y + RTS + +; search complete, now either exit or set-up and move string + +LAB_2216 + DEC g_step ; decrement step size (now $03 for descriptor stack) + LDX garb_h ; get string to move high byte + BEQ LAB_2211 ; exit if nothing to move + + LDY g_indx ; get index byte back (points to descriptor) + CLC ; clear carry for add + LDA (garb_l),Y ; get string length + ADC Histrl ; add highest string low byte + STA Obendl ; save old block end low pointer + LDA Histrh ; get highest string high byte + ADC #$00 ; add any carry + STA Obendh ; save old block end high byte + LDA Sstorl ; get bottom of string space low byte + LDX Sstorh ; get bottom of string space high byte + STA Nbendl ; save new block end low byte + STX Nbendh ; save new block end high byte + JSR LAB_11D6 ; open up space in memory, don't set array end + LDY g_indx ; get index byte + INY ; point to descriptor low byte + LDA Nbendl ; get string pointer low byte + STA (garb_l),Y ; save new string pointer low byte + TAX ; copy string pointer low byte + INC Nbendh ; correct high byte (move sets high byte -1) + LDA Nbendh ; get new string pointer high byte + INY ; point to descriptor high byte + STA (garb_l),Y ; save new string pointer high byte + JMP LAB_214B ; re-run routine from last ending + ; (but don't collect this string) + +; concatenate +; add strings, string 1 is in descriptor des_pl, string 2 is in line + +LAB_224D + LDA des_ph ; get descriptor pointer high byte + PHA ; put on stack + LDA des_pl ; get descriptor pointer low byte + PHA ; put on stack + JSR LAB_GVAL ; get value from line + JSR LAB_CTST ; check if source is string, else do type mismatch + PLA ; get descriptor pointer low byte back + STA ssptr_l ; set pointer low byte + PLA ; get descriptor pointer high byte back + STA ssptr_h ; set pointer high byte + LDY #$00 ; clear index + LDA (ssptr_l),Y ; get length_1 from descriptor + CLC ; clear carry for add + ADC (des_pl),Y ; add length_2 + BCC LAB_226D ; branch if no overflow + + LDX #$1A ; else set error code $1A ("String too long" error) + JMP LAB_XERR ; do error #X, then warm start + +LAB_226D + JSR LAB_209C ; copy des_pl/h to des_2l/h and make string space A bytes + ; long + JSR LAB_228A ; copy string from descriptor (sdescr) to (Sutill) + LDA des_2l ; get descriptor pointer low byte + LDY des_2h ; get descriptor pointer high byte + JSR LAB_22BA ; pop (YA) descriptor off stack or from top of string space + ; returns with A = length, ut1_pl = pointer low byte, + ; ut1_ph = pointer high byte + JSR LAB_229C ; store string A bytes long from (ut1_pl) to (Sutill) + LDA ssptr_l ;.set descriptor pointer low byte + LDY ssptr_h ;.set descriptor pointer high byte + JSR LAB_22BA ; pop (YA) descriptor off stack or from top of string space + ; returns with A = length, X=ut1_pl=pointer low byte, + ; Y=ut1_ph=pointer high byte + JSR LAB_RTST ; check for space on descriptor stack then put string + ; address and length on descriptor stack and update stack + ; pointers + JMP LAB_1ADB ;.continue evaluation + +; copy string from descriptor (sdescr) to (Sutill) + +LAB_228A + LDY #$00 ; clear index + LDA (sdescr),Y ; get string length + PHA ; save on stack + INY ; increment index + LDA (sdescr),Y ; get source string pointer low byte + TAX ; copy to X + INY ; increment index + LDA (sdescr),Y ; get source string pointer high byte + TAY ; copy to Y + PLA ; get length back + +; store string A bytes long from YX to (Sutill) + +LAB_2298 + STX ut1_pl ; save source string pointer low byte + STY ut1_ph ; save source string pointer high byte + +; store string A bytes long from (ut1_pl) to (Sutill) + +LAB_229C + TAX ; copy length to index (don't count with Y) + BEQ LAB_22B2 ; branch if = $0 (null string) no need to add zero length + + LDY #$00 ; zero pointer (copy forward) +LAB_22A0 + LDA (ut1_pl),Y ; get source byte + STA (Sutill),Y ; save destination byte + + INY ; increment index + DEX ; decrement counter + BNE LAB_22A0 ; loop while <> 0 + + TYA ; restore length from Y +LAB_22A9 + CLC ; clear carry for add + ADC Sutill ; add string utility ptr low byte + STA Sutill ; save string utility ptr low byte + BCC LAB_22B2 ; branch if no carry + + INC Sutilh ; else increment string utility ptr high byte +LAB_22B2 + RTS + +; evaluate string + +LAB_EVST + JSR LAB_CTST ; check if source is string, else do type mismatch + +; pop string off descriptor stack, or from top of string space +; returns with A = length, X=pointer low byte, Y=pointer high byte + +LAB_22B6 + LDA des_pl ; get descriptor pointer low byte + LDY des_ph ; get descriptor pointer high byte + +; pop (YA) descriptor off stack or from top of string space +; returns with A = length, X=ut1_pl=pointer low byte, Y=ut1_ph=pointer high byte + +LAB_22BA + STA ut1_pl ; save descriptor pointer low byte + STY ut1_ph ; save descriptor pointer high byte + JSR LAB_22EB ; clean descriptor stack, YA = pointer + PHP ; save status flags + LDY #$00 ; clear index + LDA (ut1_pl),Y ; get length from string descriptor + PHA ; put on stack + INY ; increment index + LDA (ut1_pl),Y ; get string pointer low byte from descriptor + TAX ; copy to X + INY ; increment index + LDA (ut1_pl),Y ; get string pointer high byte from descriptor + TAY ; copy to Y + PLA ; get string length back + PLP ; restore status + BNE LAB_22E6 ; branch if pointer <> last_sl,last_sh + + CPY Sstorh ; compare bottom of string space high byte + BNE LAB_22E6 ; branch if <> + + CPX Sstorl ; else compare bottom of string space low byte + BNE LAB_22E6 ; branch if <> + + PHA ; save string length + CLC ; clear carry for add + ADC Sstorl ; add bottom of string space low byte + STA Sstorl ; save bottom of string space low byte + BCC LAB_22E5 ; skip increment if no overflow + + INC Sstorh ; increment bottom of string space high byte +LAB_22E5 + PLA ; restore string length +LAB_22E6 + STX ut1_pl ; save string pointer low byte + STY ut1_ph ; save string pointer high byte + RTS + +; clean descriptor stack, YA = pointer +; checks if AY is on the descriptor stack, if so does a stack discard + +LAB_22EB + CPY last_sh ; compare pointer high byte + BNE LAB_22FB ; exit if <> + + CMP last_sl ; compare pointer low byte + BNE LAB_22FB ; exit if <> + + STA next_s ; save descriptor stack pointer + SBC #$03 ; -3 + STA last_sl ; save low byte -3 + LDY #$00 ; clear high byte +LAB_22FB + RTS + +; perform CHR$() + +LAB_CHRS + JSR LAB_EVBY ; evaluate byte expression, result in X + TXA ; copy to A + PHA ; save character + LDA #$01 ; string is single byte + JSR LAB_MSSP ; make string space A bytes long A=$AC=length, + ; X=$AD=Sutill=ptr low byte, Y=$AE=Sutilh=ptr high byte + PLA ; get character back + LDY #$00 ; clear index + STA (str_pl),Y ; save byte in string (byte IS string!) + JMP LAB_RTST ; check for space on descriptor stack then put string + ; address and length on descriptor stack and update stack + ; pointers + +; perform LEFT$() + +LAB_LEFT + PHA ; push byte parameter + JSR LAB_236F ; pull string data and byte parameter from stack + ; return pointer in des_2l/h, byte in A (and X), Y=0 + CMP (des_2l),Y ; compare byte parameter with string length + TYA ; clear A + BEQ LAB_2316 ; go do string copy (branch always) + +; perform RIGHT$() + +LAB_RIGHT + PHA ; push byte parameter + JSR LAB_236F ; pull string data and byte parameter from stack + ; return pointer in des_2l/h, byte in A (and X), Y=0 + CLC ; clear carry for add-1 + SBC (des_2l),Y ; subtract string length + EOR #$FF ; invert it (A=LEN(expression$)-l) + +LAB_2316 + BCC LAB_231C ; branch if string length > byte parameter + + LDA (des_2l),Y ; else make parameter = length + TAX ; copy to byte parameter copy + TYA ; clear string start offset +LAB_231C + PHA ; save string start offset +LAB_231D + TXA ; copy byte parameter (or string length if <) +LAB_231E + PHA ; save string length + JSR LAB_MSSP ; make string space A bytes long A=$AC=length, + ; X=$AD=Sutill=ptr low byte, Y=$AE=Sutilh=ptr high byte + LDA des_2l ; get descriptor pointer low byte + LDY des_2h ; get descriptor pointer high byte + JSR LAB_22BA ; pop (YA) descriptor off stack or from top of string space + ; returns with A = length, X=ut1_pl=pointer low byte, + ; Y=ut1_ph=pointer high byte + PLA ; get string length back + TAY ; copy length to Y + PLA ; get string start offset back + CLC ; clear carry for add + ADC ut1_pl ; add start offset to string start pointer low byte + STA ut1_pl ; save string start pointer low byte + BCC LAB_2335 ; branch if no overflow + + INC ut1_ph ; else increment string start pointer high byte +LAB_2335 + TYA ; copy length to A + JSR LAB_229C ; store string A bytes long from (ut1_pl) to (Sutill) + JMP LAB_RTST ; check for space on descriptor stack then put string + ; address and length on descriptor stack and update stack + ; pointers + +; perform MID$() + +LAB_MIDS + PHA ; push byte parameter + LDA #$FF ; set default length = 255 + STA mids_l ; save default length + JSR LAB_GBYT ; scan memory + CMP #')' ; compare with ")" + BEQ LAB_2358 ; branch if = ")" (skip second byte get) + + JSR LAB_1C01 ; scan for "," , else do syntax error then warm start + JSR LAB_GTBY ; get byte parameter (use copy in mids_l) +LAB_2358 + JSR LAB_236F ; pull string data and byte parameter from stack + ; return pointer in des_2l/h, byte in A (and X), Y=0 + DEX ; decrement start index + TXA ; copy to A + PHA ; save string start offset + CLC ; clear carry for sub-1 + LDX #$00 ; clear output string length + SBC (des_2l),Y ; subtract string length + BCS LAB_231D ; if start>string length go do null string + + EOR #$FF ; complement -length + CMP mids_l ; compare byte parameter + BCC LAB_231E ; if length>remaining string go do RIGHT$ + + LDA mids_l ; get length byte + BCS LAB_231E ; go do string copy (branch always) + +; pull string data and byte parameter from stack +; return pointer in des_2l/h, byte in A (and X), Y=0 + +LAB_236F + JSR LAB_1BFB ; scan for ")" , else do syntax error then warm start + PLA ; pull return address low byte (return address) + STA Fnxjpl ; save functions jump vector low byte + PLA ; pull return address high byte (return address) + STA Fnxjph ; save functions jump vector high byte + PLA ; pull byte parameter + TAX ; copy byte parameter to X + PLA ; pull string pointer low byte + STA des_2l ; save it + PLA ; pull string pointer high byte + STA des_2h ; save it + LDY #$00 ; clear index + TXA ; copy byte parameter + BEQ LAB_23A8 ; if null do function call error then warm start + + INC Fnxjpl ; increment function jump vector low byte + ; (JSR pushes return addr-1. this is all very nice + ; but will go tits up if either call is on a page + ; boundary!) + JMP (Fnxjpl) ; in effect, RTS + +; perform LCASE$() + +LAB_LCASE + JSR LAB_EVST ; evaluate string + STA str_ln ; set string length + TAY ; copy length to Y + BEQ NoString ; branch if null string + + JSR LAB_MSSP ; make string space A bytes long A=length, + ; X=Sutill=ptr low byte, Y=Sutilh=ptr high byte + STX str_pl ; save string pointer low byte + STY str_ph ; save string pointer high byte + TAY ; get string length back + +LC_loop + DEY ; decrement index + LDA (ut1_pl),Y ; get byte from string + JSR LAB_1D82 ; is character "A" to "Z" + BCC NoUcase ; branch if not upper case alpha + + ORA #$20 ; convert upper to lower case +NoUcase + STA (Sutill),Y ; save byte back to string + TYA ; test index + BNE LC_loop ; loop if not all done + + BEQ NoString ; tidy up and exit, branch always + +; perform UCASE$() + +LAB_UCASE + JSR LAB_EVST ; evaluate string + STA str_ln ; set string length + TAY ; copy length to Y + BEQ NoString ; branch if null string + + JSR LAB_MSSP ; make string space A bytes long A=length, + ; X=Sutill=ptr low byte, Y=Sutilh=ptr high byte + STX str_pl ; save string pointer low byte + STY str_ph ; save string pointer high byte + TAY ; get string length back + +UC_loop + DEY ; decrement index + LDA (ut1_pl),Y ; get byte from string + JSR LAB_CASC ; is character "a" to "z" (or "A" to "Z") + BCC NoLcase ; branch if not alpha + + AND #$DF ; convert lower to upper case +NoLcase + STA (Sutill),Y ; save byte back to string + TYA ; test index + BNE UC_loop ; loop if not all done + +NoString + JMP LAB_RTST ; check for space on descriptor stack then put string + ; address and length on descriptor stack and update stack + ; pointers + +; perform SADD() + +LAB_SADD + JSR LAB_IGBY ; increment and scan memory + JSR LAB_GVAR ; get var address + + JSR LAB_1BFB ; scan for ")", else do syntax error then warm start + JSR LAB_CTST ; check if source is string, else do type mismatch + + LDY #$02 ; index to string pointer high byte + LDA (Cvaral),Y ; get string pointer high byte + TAX ; copy string pointer high byte to X + DEY ; index to string pointer low byte + LDA (Cvaral),Y ; get string pointer low byte + TAY ; copy string pointer low byte to Y + TXA ; copy string pointer high byte to A + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +; perform LEN() + +LAB_LENS + JSR LAB_ESGL ; evaluate string, get length in A (and Y) + JMP LAB_1FD0 ; convert Y to byte in FAC1 and return + +; evaluate string, get length in Y + +LAB_ESGL + JSR LAB_EVST ; evaluate string + TAY ; copy length to Y + RTS + +; perform ASC() + +LAB_ASC + JSR LAB_ESGL ; evaluate string, get length in A (and Y) + BEQ LAB_23A8 ; if null do function call error then warm start + + LDY #$00 ; set index to first character + LDA (ut1_pl),Y ; get byte + TAY ; copy to Y + JMP LAB_1FD0 ; convert Y to byte in FAC1 and return + +; do function call error then warm start + +LAB_23A8 + JMP LAB_FCER ; do function call error then warm start + +; scan and get byte parameter + +LAB_SGBY + JSR LAB_IGBY ; increment and scan memory + +; get byte parameter + +LAB_GTBY + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch + +; evaluate byte expression, result in X + +LAB_EVBY + JSR LAB_EVPI ; evaluate integer expression (no check) + + LDY FAC1_2 ; get FAC1 mantissa2 + BNE LAB_23A8 ; if top byte <> 0 do function call error then warm start + + LDX FAC1_3 ; get FAC1 mantissa3 + JMP LAB_GBYT ; scan memory and return + +; perform VAL() + +LAB_VAL + JSR LAB_ESGL ; evaluate string, get length in A (and Y) + BNE LAB_23C5 ; branch if not null string + + ; string was null so set result = $00 + JMP LAB_24F1 ; clear FAC1 exponent and sign and return + +LAB_23C5 + LDX Bpntrl ; get BASIC execute pointer low byte + LDY Bpntrh ; get BASIC execute pointer high byte + STX Btmpl ; save BASIC execute pointer low byte + STY Btmph ; save BASIC execute pointer high byte + LDX ut1_pl ; get string pointer low byte + STX Bpntrl ; save as BASIC execute pointer low byte + CLC ; clear carry + ADC ut1_pl ; add string length + STA ut2_pl ; save string end low byte + LDA ut1_ph ; get string pointer high byte + STA Bpntrh ; save as BASIC execute pointer high byte + ADC #$00 ; add carry to high byte + STA ut2_ph ; save string end high byte + LDY #$00 ; set index to $00 + LDA (ut2_pl),Y ; get string end +1 byte + PHA ; push it + TYA ; clear A + STA (ut2_pl),Y ; terminate string with $00 + JSR LAB_GBYT ; scan memory + JSR LAB_2887 ; get FAC1 from string + PLA ; restore string end +1 byte + LDY #$00 ; set index to zero + STA (ut2_pl),Y ; put string end byte back + +; restore BASIC execute pointer from temp (Btmpl/Btmph) + +LAB_23F3 + LDX Btmpl ; get BASIC execute pointer low byte back + LDY Btmph ; get BASIC execute pointer high byte back + STX Bpntrl ; save BASIC execute pointer low byte + STY Bpntrh ; save BASIC execute pointer high byte + RTS + +; get two parameters for POKE or WAIT + +LAB_GADB + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch + JSR LAB_F2FX ; save integer part of FAC1 in temporary integer + +; scan for "," and get byte, else do Syntax error then warm start + +LAB_SCGB + JSR LAB_1C01 ; scan for "," , else do syntax error then warm start + LDA Itemph ; save temporary integer high byte + PHA ; on stack + LDA Itempl ; save temporary integer low byte + PHA ; on stack + JSR LAB_GTBY ; get byte parameter + PLA ; pull low byte + STA Itempl ; restore temporary integer low byte + PLA ; pull high byte + STA Itemph ; restore temporary integer high byte + RTS + +; convert float to fixed routine. accepts any value that fits in 24 bits, +ve or +; -ve and converts it into a right truncated integer in Itempl and Itemph + +; save unsigned 16 bit integer part of FAC1 in temporary integer + +LAB_F2FX + LDA FAC1_e ; get FAC1 exponent + CMP #$98 ; compare with exponent = 2^24 + BCS LAB_23A8 ; if >= do function call error then warm start + +LAB_F2FU + JSR LAB_2831 ; convert FAC1 floating-to-fixed + LDA FAC1_2 ; get FAC1 mantissa2 + LDY FAC1_3 ; get FAC1 mantissa3 + STY Itempl ; save temporary integer low byte + STA Itemph ; save temporary integer high byte + RTS + +; perform PEEK() + +LAB_PEEK + JSR LAB_F2FX ; save integer part of FAC1 in temporary integer + LDX #$00 ; clear index + LDA (Itempl,X) ; get byte via temporary integer (addr) + TAY ; copy byte to Y + JMP LAB_1FD0 ; convert Y to byte in FAC1 and return + +; perform POKE + +LAB_POKE + JSR LAB_GADB ; get two parameters for POKE or WAIT + TXA ; copy byte argument to A + LDX #$00 ; clear index + STA (Itempl,X) ; save byte via temporary integer (addr) + RTS + +; perform DEEK() + +LAB_DEEK + JSR LAB_F2FX ; save integer part of FAC1 in temporary integer + LDX #$00 ; clear index + LDA (Itempl,X) ; PEEK low byte + TAY ; copy to Y + INC Itempl ; increment pointer low byte + BNE Deekh ; skip high increment if no rollover + + INC Itemph ; increment pointer high byte +Deekh + LDA (Itempl,X) ; PEEK high byte + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +; perform DOKE + +LAB_DOKE + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch + JSR LAB_F2FX ; convert floating-to-fixed + + STY Frnxtl ; save pointer low byte (float to fixed returns word in AY) + STA Frnxth ; save pointer high byte + + JSR LAB_1C01 ; scan for "," , else do syntax error then warm start + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch + JSR LAB_F2FX ; convert floating-to-fixed + + TYA ; copy value low byte (float to fixed returns word in AY) + LDX #$00 ; clear index + STA (Frnxtl,X) ; POKE low byte + INC Frnxtl ; increment pointer low byte + BNE Dokeh ; skip high increment if no rollover + + INC Frnxth ; increment pointer high byte +Dokeh + LDA Itemph ; get value high byte + STA (Frnxtl,X) ; POKE high byte + JMP LAB_GBYT ; scan memory and return + +; perform SWAP + +LAB_SWAP + JSR LAB_GVAR ; get var1 address + STA Lvarpl ; save var1 address low byte + STY Lvarph ; save var1 address high byte + LDA Dtypef ; get data type flag, $FF=string, $00=numeric + PHA ; save data type flag + + JSR LAB_1C01 ; scan for "," , else do syntax error then warm start + JSR LAB_GVAR ; get var2 address (pointer in Cvaral/h) + PLA ; pull var1 data type flag + EOR Dtypef ; compare with var2 data type + BPL SwapErr ; exit if not both the same type + + LDY #$03 ; four bytes to swap (either value or descriptor+1) +SwapLp + LDA (Lvarpl),Y ; get byte from var1 + TAX ; save var1 byte + LDA (Cvaral),Y ; get byte from var2 + STA (Lvarpl),Y ; save byte to var1 + TXA ; restore var1 byte + STA (Cvaral),Y ; save byte to var2 + DEY ; decrement index + BPL SwapLp ; loop until done + + RTS + +SwapErr + JMP LAB_1ABC ; do "Type mismatch" error then warm start + +; perform CALL + +LAB_CALL + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch + JSR LAB_F2FX ; convert floating-to-fixed + LDA #>CallExit ; set return address high byte + PHA ; put on stack + LDA #8 shifts) + BCC LAB_24A8 ;.go subtract mantissas + +; add 0.5 to FAC1 + +LAB_244E + LDA #LAB_2A96 ; set 0.5 pointer high byte + +; add (AY) to FAC1 + +LAB_246C + JSR LAB_264D ; unpack memory (AY) into FAC2 + +; add FAC2 to FAC1 + +LAB_ADD + BNE LAB_2474 ; branch if FAC1 was not zero + +; copy FAC2 to FAC1 + +LAB_279B + LDA FAC2_s ; get FAC2 sign (b7) + +; save FAC1 sign and copy ABS(FAC2) to FAC1 + +LAB_279D + STA FAC1_s ; save FAC1 sign (b7) + LDX #$04 ; 4 bytes to copy +LAB_27A1 + LDA FAC1_o,X ; get byte from FAC2,X + STA FAC1_e-1,X ; save byte at FAC1,X + DEX ; decrement count + BNE LAB_27A1 ; loop if not all done + + STX FAC1_r ; clear FAC1 rounding byte + RTS + + ; FAC1 is non zero +LAB_2474 + LDX FAC1_r ; get FAC1 rounding byte + STX FAC2_r ; save as FAC2 rounding byte + LDX #FAC2_e ; set index to FAC2 exponent addr + LDA FAC2_e ; get FAC2 exponent +LAB_247C + TAY ; copy exponent + BEQ LAB_244D ; exit if zero + + SEC ; set carry for subtract + SBC FAC1_e ; subtract FAC1 exponent + BEQ LAB_24A8 ; branch if = (go add mantissa) + + BCC LAB_2498 ; branch if < + + ; FAC2>FAC1 + STY FAC1_e ; save FAC1 exponent + LDY FAC2_s ; get FAC2 sign (b7) + STY FAC1_s ; save FAC1 sign (b7) + EOR #$FF ; complement A + ADC #$00 ; +1 (twos complement, carry is set) + LDY #$00 ; clear Y + STY FAC2_r ; clear FAC2 rounding byte + LDX #FAC1_e ; set index to FAC1 exponent addr + BNE LAB_249C ; branch always + +LAB_2498 + LDY #$00 ; clear Y + STY FAC1_r ; clear FAC1 rounding byte +LAB_249C + CMP #$F9 ; compare exponent diff with $F9 + BMI LAB_2467 ; branch if range $79-$F8 + + TAY ; copy exponent difference to Y + LDA FAC1_r ; get FAC1 rounding byte + LSR PLUS_1,X ; shift FAC? mantissa1 + JSR LAB_2592 ; shift FACX Y times right + + ; exponents are equal now do mantissa subtract +LAB_24A8 + BIT FAC_sc ; test sign compare (FAC1 EOR FAC2) + BPL LAB_24F8 ; if = add FAC2 mantissa to FAC1 mantissa and return + + LDY #FAC1_e ; set index to FAC1 exponent addr + CPX #FAC2_e ; compare X to FAC2 exponent addr + BEQ LAB_24B4 ; branch if = + + LDY #FAC2_e ; else set index to FAC2 exponent addr + + ; subtract smaller from bigger (take sign of bigger) +LAB_24B4 + SEC ; set carry for subtract + EOR #$FF ; ones complement A + ADC FAC2_r ; add FAC2 rounding byte + STA FAC1_r ; save FAC1 rounding byte + LDA PLUS_3,Y ; get FACY mantissa3 + SBC PLUS_3,X ; subtract FACX mantissa3 + STA FAC1_3 ; save FAC1 mantissa3 + LDA PLUS_2,Y ; get FACY mantissa2 + SBC PLUS_2,X ; subtract FACX mantissa2 + STA FAC1_2 ; save FAC1 mantissa2 + LDA PLUS_1,Y ; get FACY mantissa1 + SBC PLUS_1,X ; subtract FACX mantissa1 + STA FAC1_1 ; save FAC1 mantissa1 + +; do ABS and normalise FAC1 + +LAB_24D0 + BCS LAB_24D5 ; branch if number is +ve + + JSR LAB_2537 ; negate FAC1 + +; normalise FAC1 + +LAB_24D5 + LDY #$00 ; clear Y + TYA ; clear A + CLC ; clear carry for add +LAB_24D9 + LDX FAC1_1 ; get FAC1 mantissa1 + BNE LAB_251B ; if not zero normalise FAC1 + + LDX FAC1_2 ; get FAC1 mantissa2 + STX FAC1_1 ; save FAC1 mantissa1 + LDX FAC1_3 ; get FAC1 mantissa3 + STX FAC1_2 ; save FAC1 mantissa2 + LDX FAC1_r ; get FAC1 rounding byte + STX FAC1_3 ; save FAC1 mantissa3 + STY FAC1_r ; clear FAC1 rounding byte + ADC #$08 ; add x to exponent offset + CMP #$18 ; compare with $18 (max offset, all bits would be =0) + BNE LAB_24D9 ; loop if not max + +; clear FAC1 exponent and sign + +LAB_24F1 + LDA #$00 ; clear A +LAB_24F3 + STA FAC1_e ; set FAC1 exponent + +; save FAC1 sign + +LAB_24F5 + STA FAC1_s ; save FAC1 sign (b7) + RTS + +; add FAC2 mantissa to FAC1 mantissa + +LAB_24F8 + ADC FAC2_r ; add FAC2 rounding byte + STA FAC1_r ; save FAC1 rounding byte + LDA FAC1_3 ; get FAC1 mantissa3 + ADC FAC2_3 ; add FAC2 mantissa3 + STA FAC1_3 ; save FAC1 mantissa3 + LDA FAC1_2 ; get FAC1 mantissa2 + ADC FAC2_2 ; add FAC2 mantissa2 + STA FAC1_2 ; save FAC1 mantissa2 + LDA FAC1_1 ; get FAC1 mantissa1 + ADC FAC2_1 ; add FAC2 mantissa1 + STA FAC1_1 ; save FAC1 mantissa1 + BCS LAB_252A ; if carry then normalise FAC1 for C=1 + + RTS ; else just exit + +LAB_2511 + ADC #$01 ; add 1 to exponent offset + ASL FAC1_r ; shift FAC1 rounding byte + ROL FAC1_3 ; shift FAC1 mantissa3 + ROL FAC1_2 ; shift FAC1 mantissa2 + ROL FAC1_1 ; shift FAC1 mantissa1 + +; normalise FAC1 + +LAB_251B + BPL LAB_2511 ; loop if not normalised + + SEC ; set carry for subtract + SBC FAC1_e ; subtract FAC1 exponent + BCS LAB_24F1 ; branch if underflow (set result = $0) + + EOR #$FF ; complement exponent + ADC #$01 ; +1 (twos complement) + STA FAC1_e ; save FAC1 exponent + +; test and normalise FAC1 for C=0/1 + +LAB_2528 + BCC LAB_2536 ; exit if no overflow + +; normalise FAC1 for C=1 + +LAB_252A + INC FAC1_e ; increment FAC1 exponent + BEQ LAB_2564 ; if zero do overflow error and warm start + + ROR FAC1_1 ; shift FAC1 mantissa1 + ROR FAC1_2 ; shift FAC1 mantissa2 + ROR FAC1_3 ; shift FAC1 mantissa3 + ROR FAC1_r ; shift FAC1 rounding byte +LAB_2536 + RTS + +; negate FAC1 + +LAB_2537 + LDA FAC1_s ; get FAC1 sign (b7) + EOR #$FF ; complement it + STA FAC1_s ; save FAC1 sign (b7) + +; twos complement FAC1 mantissa + +LAB_253D + LDA FAC1_1 ; get FAC1 mantissa1 + EOR #$FF ; complement it + STA FAC1_1 ; save FAC1 mantissa1 + LDA FAC1_2 ; get FAC1 mantissa2 + EOR #$FF ; complement it + STA FAC1_2 ; save FAC1 mantissa2 + LDA FAC1_3 ; get FAC1 mantissa3 + EOR #$FF ; complement it + STA FAC1_3 ; save FAC1 mantissa3 + LDA FAC1_r ; get FAC1 rounding byte + EOR #$FF ; complement it + STA FAC1_r ; save FAC1 rounding byte + INC FAC1_r ; increment FAC1 rounding byte + BNE LAB_2563 ; exit if no overflow + +; increment FAC1 mantissa + +LAB_2559 + INC FAC1_3 ; increment FAC1 mantissa3 + BNE LAB_2563 ; finished if no rollover + + INC FAC1_2 ; increment FAC1 mantissa2 + BNE LAB_2563 ; finished if no rollover + + INC FAC1_1 ; increment FAC1 mantissa1 +LAB_2563 + RTS + +; do overflow error (overflow exit) + +LAB_2564 + LDX #$0A ; error code $0A ("Overflow" error) + JMP LAB_XERR ; do error #X, then warm start + +; shift FCAtemp << A+8 times + +LAB_2569 + LDX #FACt_1-1 ; set offset to FACtemp +LAB_256B + LDY PLUS_3,X ; get FACX mantissa3 + STY FAC1_r ; save as FAC1 rounding byte + LDY PLUS_2,X ; get FACX mantissa2 + STY PLUS_3,X ; save FACX mantissa3 + LDY PLUS_1,X ; get FACX mantissa1 + STY PLUS_2,X ; save FACX mantissa2 + LDY FAC1_o ; get FAC1 overflow byte + STY PLUS_1,X ; save FACX mantissa1 + +; shift FACX -A times right (> 8 shifts) + +LAB_257B + ADC #$08 ; add 8 to shift count + BMI LAB_256B ; go do 8 shift if still -ve + + BEQ LAB_256B ; go do 8 shift if zero + + SBC #$08 ; else subtract 8 again + TAY ; save count to Y + LDA FAC1_r ; get FAC1 rounding byte + BCS LAB_259A ;. + +LAB_2588 + ASL PLUS_1,X ; shift FACX mantissa1 + BCC LAB_258E ; branch if +ve + + INC PLUS_1,X ; this sets b7 eventually +LAB_258E + ROR PLUS_1,X ; shift FACX mantissa1 (correct for ASL) + ROR PLUS_1,X ; shift FACX mantissa1 (put carry in b7) + +; shift FACX Y times right + +LAB_2592 + ROR PLUS_2,X ; shift FACX mantissa2 + ROR PLUS_3,X ; shift FACX mantissa3 + ROR ; shift FACX rounding byte + INY ; increment exponent diff + BNE LAB_2588 ; branch if range adjust not complete + +LAB_259A + CLC ; just clear it + RTS + +; perform LOG() + +LAB_LOG + JSR LAB_27CA ; test sign and zero + BEQ LAB_25C4 ; if zero do function call error then warm start + + BPL LAB_25C7 ; skip error if +ve + +LAB_25C4 + JMP LAB_FCER ; do function call error then warm start (-ve) + +LAB_25C7 + LDA FAC1_e ; get FAC1 exponent + SBC #$7F ; normalise it + PHA ; save it + LDA #$80 ; set exponent to zero + STA FAC1_e ; save FAC1 exponent + LDA #LAB_25AD ; set 1/root2 pointer high byte + JSR LAB_246C ; add (AY) to FAC1 (1/root2) + LDA #LAB_25B1 ; set root2 pointer high byte + JSR LAB_26CA ; convert AY and do (AY)/FAC1 (root2/(x+(1/root2))) + LDA #LAB_259C ; set 1 pointer high byte + JSR LAB_2455 ; subtract (AY) from FAC1 ((root2/(x+(1/root2)))-1) + LDA #LAB_25A0 ; set pointer high byte to counter + JSR LAB_2B6E ; ^2 then series evaluation + LDA #LAB_25B5 ; set -0.5 pointer high byte + JSR LAB_246C ; add (AY) to FAC1 + PLA ; restore FAC1 exponent + JSR LAB_2912 ; evaluate new ASCII digit + LDA #LAB_25B9 ; set LOG(2) pointer high byte + +; do convert AY, FCA1*(AY) + +LAB_25FB + JSR LAB_264D ; unpack memory (AY) into FAC2 +LAB_MULTIPLY + BEQ LAB_264C ; exit if zero + + JSR LAB_2673 ; test and adjust accumulators + LDA #$00 ; clear A + STA FACt_1 ; clear temp mantissa1 + STA FACt_2 ; clear temp mantissa2 + STA FACt_3 ; clear temp mantissa3 + LDA FAC1_r ; get FAC1 rounding byte + JSR LAB_2622 ; go do shift/add FAC2 + LDA FAC1_3 ; get FAC1 mantissa3 + JSR LAB_2622 ; go do shift/add FAC2 + LDA FAC1_2 ; get FAC1 mantissa2 + JSR LAB_2622 ; go do shift/add FAC2 + LDA FAC1_1 ; get FAC1 mantissa1 + JSR LAB_2627 ; go do shift/add FAC2 + JMP LAB_273C ; copy temp to FAC1, normalise and return + +LAB_2622 + BNE LAB_2627 ; branch if byte <> zero + + JMP LAB_2569 ; shift FCAtemp << A+8 times + + ; else do shift and add +LAB_2627 + LSR ; shift byte + ORA #$80 ; set top bit (mark for 8 times) +LAB_262A + TAY ; copy result + BCC LAB_2640 ; skip next if bit was zero + + CLC ; clear carry for add + LDA FACt_3 ; get temp mantissa3 + ADC FAC2_3 ; add FAC2 mantissa3 + STA FACt_3 ; save temp mantissa3 + LDA FACt_2 ; get temp mantissa2 + ADC FAC2_2 ; add FAC2 mantissa2 + STA FACt_2 ; save temp mantissa2 + LDA FACt_1 ; get temp mantissa1 + ADC FAC2_1 ; add FAC2 mantissa1 + STA FACt_1 ; save temp mantissa1 +LAB_2640 + ROR FACt_1 ; shift temp mantissa1 + ROR FACt_2 ; shift temp mantissa2 + ROR FACt_3 ; shift temp mantissa3 + ROR FAC1_r ; shift temp rounding byte + TYA ; get byte back + LSR ; shift byte + BNE LAB_262A ; loop if all bits not done + +LAB_264C + RTS + +; unpack memory (AY) into FAC2 + +LAB_264D + STA ut1_pl ; save pointer low byte + STY ut1_ph ; save pointer high byte + LDY #$03 ; 4 bytes to get (0-3) + LDA (ut1_pl),Y ; get mantissa3 + STA FAC2_3 ; save FAC2 mantissa3 + DEY ; decrement index + LDA (ut1_pl),Y ; get mantissa2 + STA FAC2_2 ; save FAC2 mantissa2 + DEY ; decrement index + LDA (ut1_pl),Y ; get mantissa1+sign + STA FAC2_s ; save FAC2 sign (b7) + EOR FAC1_s ; EOR with FAC1 sign (b7) + STA FAC_sc ; save sign compare (FAC1 EOR FAC2) + LDA FAC2_s ; recover FAC2 sign (b7) + ORA #$80 ; set 1xxx xxx (set normal bit) + STA FAC2_1 ; save FAC2 mantissa1 + DEY ; decrement index + LDA (ut1_pl),Y ; get exponent byte + STA FAC2_e ; save FAC2 exponent + LDA FAC1_e ; get FAC1 exponent + RTS + +; test and adjust accumulators + +LAB_2673 + LDA FAC2_e ; get FAC2 exponent +LAB_2675 + BEQ LAB_2696 ; branch if FAC2 = $00 (handle underflow) + + CLC ; clear carry for add + ADC FAC1_e ; add FAC1 exponent + BCC LAB_2680 ; branch if sum of exponents <$0100 + + BMI LAB_269B ; do overflow error + + CLC ; clear carry for the add + .byte $2C ; makes next line BIT $1410 +LAB_2680 + BPL LAB_2696 ; if +ve go handle underflow + + ADC #$80 ; adjust exponent + STA FAC1_e ; save FAC1 exponent + BNE LAB_268B ; branch if not zero + + JMP LAB_24F5 ; save FAC1 sign and return + +LAB_268B + LDA FAC_sc ; get sign compare (FAC1 EOR FAC2) + STA FAC1_s ; save FAC1 sign (b7) +LAB_268F + RTS + +; handle overflow and underflow + +LAB_2690 + LDA FAC1_s ; get FAC1 sign (b7) + BPL LAB_269B ; do overflow error + + ; handle underflow +LAB_2696 + PLA ; pop return address low byte + PLA ; pop return address high byte + JMP LAB_24F1 ; clear FAC1 exponent and sign and return + +; multiply by 10 + +LAB_269E + JSR LAB_27AB ; round and copy FAC1 to FAC2 + TAX ; copy exponent (set the flags) + BEQ LAB_268F ; exit if zero + + CLC ; clear carry for add + ADC #$02 ; add two to exponent (*4) + BCS LAB_269B ; do overflow error if > $FF + + LDX #$00 ; clear byte + STX FAC_sc ; clear sign compare (FAC1 EOR FAC2) + JSR LAB_247C ; add FAC2 to FAC1 (*5) + INC FAC1_e ; increment FAC1 exponent (*10) + BNE LAB_268F ; if non zero just do RTS + +LAB_269B + JMP LAB_2564 ; do overflow error and warm start + +; divide by 10 + +LAB_26B9 + JSR LAB_27AB ; round and copy FAC1 to FAC2 + LDA #LAB_26B5 ; set pointer to 10d high addr + LDX #$00 ; clear sign + +; divide by (AY) (X=sign) + +LAB_26C2 + STX FAC_sc ; save sign compare (FAC1 EOR FAC2) + JSR LAB_UFAC ; unpack memory (AY) into FAC1 + JMP LAB_DIVIDE ; do FAC2/FAC1 + + ; Perform divide-by +; convert AY and do (AY)/FAC1 + +LAB_26CA + JSR LAB_264D ; unpack memory (AY) into FAC2 + + ; Perform divide-into +LAB_DIVIDE + BEQ LAB_2737 ; if zero go do /0 error + + JSR LAB_27BA ; round FAC1 + LDA #$00 ; clear A + SEC ; set carry for subtract + SBC FAC1_e ; subtract FAC1 exponent (2s complement) + STA FAC1_e ; save FAC1 exponent + JSR LAB_2673 ; test and adjust accumulators + INC FAC1_e ; increment FAC1 exponent + BEQ LAB_269B ; if zero do overflow error + + LDX #$FF ; set index for pre increment + LDA #$01 ; set bit to flag byte save +LAB_26E4 + LDY FAC2_1 ; get FAC2 mantissa1 + CPY FAC1_1 ; compare FAC1 mantissa1 + BNE LAB_26F4 ; branch if <> + + LDY FAC2_2 ; get FAC2 mantissa2 + CPY FAC1_2 ; compare FAC1 mantissa2 + BNE LAB_26F4 ; branch if <> + + LDY FAC2_3 ; get FAC2 mantissa3 + CPY FAC1_3 ; compare FAC1 mantissa3 +LAB_26F4 + PHP ; save FAC2-FAC1 compare status + ROL ; shift the result byte + BCC LAB_2702 ; if no carry skip the byte save + + LDY #$01 ; set bit to flag byte save + INX ; else increment the index to FACt + CPX #$02 ; compare with the index to FACt_3 + BMI LAB_2701 ; if not last byte just go save it + + BNE LAB_272B ; if all done go save FAC1 rounding byte, normalise and + ; return + + LDY #$40 ; set bit to flag byte save for the rounding byte +LAB_2701 + STA FACt_1,X ; write result byte to FACt_1 + index + TYA ; copy the next save byte flag +LAB_2702 + PLP ; restore FAC2-FAC1 compare status + BCC LAB_2704 ; if FAC2 < FAC1 then skip the subtract + + TAY ; save FAC2-FAC1 compare status + LDA FAC2_3 ; get FAC2 mantissa3 + SBC FAC1_3 ; subtract FAC1 mantissa3 + STA FAC2_3 ; save FAC2 mantissa3 + LDA FAC2_2 ; get FAC2 mantissa2 + SBC FAC1_2 ; subtract FAC1 mantissa2 + STA FAC2_2 ; save FAC2 mantissa2 + LDA FAC2_1 ; get FAC2 mantissa1 + SBC FAC1_1 ; subtract FAC1 mantissa1 + STA FAC2_1 ; save FAC2 mantissa1 + TYA ; restore FAC2-FAC1 compare status + + ; FAC2 = FAC2*2 +LAB_2704 + ASL FAC2_3 ; shift FAC2 mantissa3 + ROL FAC2_2 ; shift FAC2 mantissa2 + ROL FAC2_1 ; shift FAC2 mantissa1 + BCS LAB_26F4 ; loop with no compare + + BMI LAB_26E4 ; loop with compare + + BPL LAB_26F4 ; loop always with no compare + +; do A<<6, save as FAC1 rounding byte, normalise and return + +LAB_272B + LSR ; shift b1 - b0 .. + ROR ; .. + ROR ; .. to b7 - b6 + STA FAC1_r ; save FAC1 rounding byte + PLP ; dump FAC2-FAC1 compare status + JMP LAB_273C ; copy temp to FAC1, normalise and return + +; do "Divide by zero" error + +LAB_2737 + LDX #$14 ; error code $14 ("Divide by zero" error) + JMP LAB_XERR ; do error #X, then warm start + +; copy temp to FAC1 and normalise + +LAB_273C + LDA FACt_1 ; get temp mantissa1 + STA FAC1_1 ; save FAC1 mantissa1 + LDA FACt_2 ; get temp mantissa2 + STA FAC1_2 ; save FAC1 mantissa2 + LDA FACt_3 ; get temp mantissa3 + STA FAC1_3 ; save FAC1 mantissa3 + JMP LAB_24D5 ; normalise FAC1 and return + +; unpack memory (AY) into FAC1 + +LAB_UFAC + STA ut1_pl ; save pointer low byte + STY ut1_ph ; save pointer high byte + LDY #$03 ; 4 bytes to do + LDA (ut1_pl),Y ; get last byte + STA FAC1_3 ; save FAC1 mantissa3 + DEY ; decrement index + LDA (ut1_pl),Y ; get last-1 byte + STA FAC1_2 ; save FAC1 mantissa2 + DEY ; decrement index + LDA (ut1_pl),Y ; get second byte + STA FAC1_s ; save FAC1 sign (b7) + ORA #$80 ; set 1xxx xxxx (add normal bit) + STA FAC1_1 ; save FAC1 mantissa1 + DEY ; decrement index + LDA (ut1_pl),Y ; get first byte (exponent) + STA FAC1_e ; save FAC1 exponent + STY FAC1_r ; clear FAC1 rounding byte + RTS + +; pack FAC1 into Adatal + +LAB_276E + LDX #Adatal ; set pointer high byte + BEQ LAB_2778 ; pack FAC1 into (XY) and return + +; pack FAC1 into (Lvarpl) + +LAB_PFAC + LDX Lvarpl ; get destination pointer low byte + LDY Lvarph ; get destination pointer high byte + +; pack FAC1 into (XY) + +LAB_2778 + JSR LAB_27BA ; round FAC1 + STX ut1_pl ; save pointer low byte + STY ut1_ph ; save pointer high byte + LDY #$03 ; set index + LDA FAC1_3 ; get FAC1 mantissa3 + STA (ut1_pl),Y ; store in destination + DEY ; decrement index + LDA FAC1_2 ; get FAC1 mantissa2 + STA (ut1_pl),Y ; store in destination + DEY ; decrement index + LDA FAC1_s ; get FAC1 sign (b7) + ORA #$7F ; set bits x111 1111 + AND FAC1_1 ; AND in FAC1 mantissa1 + STA (ut1_pl),Y ; store in destination + DEY ; decrement index + LDA FAC1_e ; get FAC1 exponent + STA (ut1_pl),Y ; store in destination + STY FAC1_r ; clear FAC1 rounding byte + RTS + +; round and copy FAC1 to FAC2 + +LAB_27AB + JSR LAB_27BA ; round FAC1 + +; copy FAC1 to FAC2 + +LAB_27AE + LDX #$05 ; 5 bytes to copy +LAB_27B0 + LDA FAC1_e-1,X ; get byte from FAC1,X + STA FAC1_o,X ; save byte at FAC2,X + DEX ; decrement count + BNE LAB_27B0 ; loop if not all done + + STX FAC1_r ; clear FAC1 rounding byte +LAB_27B9 + RTS + +; round FAC1 + +LAB_27BA + LDA FAC1_e ; get FAC1 exponent + BEQ LAB_27B9 ; exit if zero + + ASL FAC1_r ; shift FAC1 rounding byte + BCC LAB_27B9 ; exit if no overflow + +; round FAC1 (no check) + +LAB_27C2 + JSR LAB_2559 ; increment FAC1 mantissa + BNE LAB_27B9 ; branch if no overflow + + JMP LAB_252A ; normalise FAC1 for C=1 and return + +; get FAC1 sign +; return A=FF,C=1/-ve A=01,C=0/+ve + +LAB_27CA + LDA FAC1_e ; get FAC1 exponent + BEQ LAB_27D7 ; exit if zero (already correct SGN(0)=0) + +; return A=FF,C=1/-ve A=01,C=0/+ve +; no = 0 check + +LAB_27CE + LDA FAC1_s ; else get FAC1 sign (b7) + +; return A=FF,C=1/-ve A=01,C=0/+ve +; no = 0 check, sign in A + +LAB_27D0 + ROL ; move sign bit to carry + LDA #$FF ; set byte for -ve result + BCS LAB_27D7 ; return if sign was set (-ve) + + LDA #$01 ; else set byte for +ve result +LAB_27D7 + RTS + +; perform SGN() + +LAB_SGN + JSR LAB_27CA ; get FAC1 sign + ; return A=$FF/-ve A=$01/+ve +; save A as integer byte + +LAB_27DB + STA FAC1_1 ; save FAC1 mantissa1 + LDA #$00 ; clear A + STA FAC1_2 ; clear FAC1 mantissa2 + LDX #$88 ; set exponent + +; set exp=X, clearFAC1 mantissa3 and normalise + +LAB_27E3 + LDA FAC1_1 ; get FAC1 mantissa1 + EOR #$FF ; complement it + ROL ; sign bit into carry + +; set exp=X, clearFAC1 mantissa3 and normalise + +LAB_STFA + LDA #$00 ; clear A + STA FAC1_3 ; clear FAC1 mantissa3 + STX FAC1_e ; set FAC1 exponent + STA FAC1_r ; clear FAC1 rounding byte + STA FAC1_s ; clear FAC1 sign (b7) + JMP LAB_24D0 ; do ABS and normalise FAC1 + +; perform ABS() + +LAB_ABS + LSR FAC1_s ; clear FAC1 sign (put zero in b7) + RTS + +; compare FAC1 with (AY) +; returns A=$00 if FAC1 = (AY) +; returns A=$01 if FAC1 > (AY) +; returns A=$FF if FAC1 < (AY) + +LAB_27F8 + STA ut2_pl ; save pointer low byte +LAB_27FA + STY ut2_ph ; save pointer high byte + LDY #$00 ; clear index + LDA (ut2_pl),Y ; get exponent + INY ; increment index + TAX ; copy (AY) exponent to X + BEQ LAB_27CA ; branch if (AY) exponent=0 and get FAC1 sign + ; A=FF,C=1/-ve A=01,C=0/+ve + + LDA (ut2_pl),Y ; get (AY) mantissa1 (with sign) + EOR FAC1_s ; EOR FAC1 sign (b7) + BMI LAB_27CE ; if signs <> do return A=FF,C=1/-ve + ; A=01,C=0/+ve and return + + CPX FAC1_e ; compare (AY) exponent with FAC1 exponent + BNE LAB_2828 ; branch if different + + LDA (ut2_pl),Y ; get (AY) mantissa1 (with sign) + ORA #$80 ; normalise top bit + CMP FAC1_1 ; compare with FAC1 mantissa1 + BNE LAB_2828 ; branch if different + + INY ; increment index + LDA (ut2_pl),Y ; get mantissa2 + CMP FAC1_2 ; compare with FAC1 mantissa2 + BNE LAB_2828 ; branch if different + + INY ; increment index + LDA #$7F ; set for 1/2 value rounding byte + CMP FAC1_r ; compare with FAC1 rounding byte (set carry) + LDA (ut2_pl),Y ; get mantissa3 + SBC FAC1_3 ; subtract FAC1 mantissa3 + BEQ LAB_2850 ; exit if mantissa3 equal + +; gets here if number <> FAC1 + +LAB_2828 + LDA FAC1_s ; get FAC1 sign (b7) + BCC LAB_282E ; branch if FAC1 > (AY) + + EOR #$FF ; else toggle FAC1 sign +LAB_282E + JMP LAB_27D0 ; return A=FF,C=1/-ve A=01,C=0/+ve + +; convert FAC1 floating-to-fixed + +LAB_2831 + LDA FAC1_e ; get FAC1 exponent + BEQ LAB_287F ; if zero go clear FAC1 and return + + SEC ; set carry for subtract + SBC #$98 ; subtract maximum integer range exponent + BIT FAC1_s ; test FAC1 sign (b7) + BPL LAB_2845 ; branch if FAC1 +ve + + ; FAC1 was -ve + TAX ; copy subtracted exponent + LDA #$FF ; overflow for -ve number + STA FAC1_o ; set FAC1 overflow byte + JSR LAB_253D ; twos complement FAC1 mantissa + TXA ; restore subtracted exponent +LAB_2845 + LDX #FAC1_e ; set index to FAC1 + CMP #$F9 ; compare exponent result + BPL LAB_2851 ; if < 8 shifts shift FAC1 A times right and return + + JSR LAB_257B ; shift FAC1 A times right (> 8 shifts) + STY FAC1_o ; clear FAC1 overflow byte +LAB_2850 + RTS + +; shift FAC1 A times right + +LAB_2851 + TAY ; copy shift count + LDA FAC1_s ; get FAC1 sign (b7) + AND #$80 ; mask sign bit only (x000 0000) + LSR FAC1_1 ; shift FAC1 mantissa1 + ORA FAC1_1 ; OR sign in b7 FAC1 mantissa1 + STA FAC1_1 ; save FAC1 mantissa1 + JSR LAB_2592 ; shift FAC1 Y times right + STY FAC1_o ; clear FAC1 overflow byte + RTS + +; perform INT() + +LAB_INT + LDA FAC1_e ; get FAC1 exponent + CMP #$98 ; compare with max int + BCS LAB_2886 ; exit if >= (already int, too big for fractional part!) + + JSR LAB_2831 ; convert FAC1 floating-to-fixed + STY FAC1_r ; save FAC1 rounding byte + LDA FAC1_s ; get FAC1 sign (b7) + STY FAC1_s ; save FAC1 sign (b7) + EOR #$80 ; toggle FAC1 sign + ROL ; shift into carry + LDA #$98 ; set new exponent + STA FAC1_e ; save FAC1 exponent + LDA FAC1_3 ; get FAC1 mantissa3 + STA Temp3 ; save for EXP() function + JMP LAB_24D0 ; do ABS and normalise FAC1 + +; clear FAC1 and return + +LAB_287F + STA FAC1_1 ; clear FAC1 mantissa1 + STA FAC1_2 ; clear FAC1 mantissa2 + STA FAC1_3 ; clear FAC1 mantissa3 + TAY ; clear Y +LAB_2886 + RTS + +; get FAC1 from string +; this routine now handles hex and binary values from strings +; starting with "$" and "%" respectively + +LAB_2887 + LDY #$00 ; clear Y + STY Dtypef ; clear data type flag, $FF=string, $00=numeric + LDX #$09 ; set index +LAB_288B + STY numexp,X ; clear byte + DEX ; decrement index + BPL LAB_288B ; loop until numexp to negnum (and FAC1) = $00 + + BCC LAB_28FE ; branch if 1st character numeric + +; get FAC1 from string .. first character wasn't numeric + + CMP #'-' ; else compare with "-" + BNE LAB_289A ; branch if not "-" + + STX negnum ; set flag for -ve number (X = $FF) + BEQ LAB_289C ; branch always (go scan and check for hex/bin) + +; get FAC1 from string .. first character wasn't numeric or - + +LAB_289A + CMP #'+' ; else compare with "+" + BNE LAB_289D ; branch if not "+" (go check for hex/bin) + +; was "+" or "-" to start, so get next character + +LAB_289C + JSR LAB_IGBY ; increment and scan memory + BCC LAB_28FE ; branch if numeric character + +; code here for hex and binary numbers + +LAB_289D + CMP #'$' ; else compare with "$" + BNE LAB_NHEX ; branch if not "$" + + JMP LAB_CHEX ; branch if "$" + +LAB_NHEX + CMP #'%' ; else compare with "%" + BNE LAB_28A3 ; branch if not "%" (continue original code) + + JMP LAB_CBIN ; branch if "%" + +LAB_289E + JSR LAB_IGBY ; increment and scan memory (ignore + or get next number) +LAB_28A1 + BCC LAB_28FE ; branch if numeric character + +; get FAC1 from string .. character wasn't numeric, -, +, hex or binary + +LAB_28A3 + CMP #'.' ; else compare with "." + BEQ LAB_28D5 ; branch if "." + +; get FAC1 from string .. character wasn't numeric, -, + or . + + CMP #'E' ; else compare with "E" + BNE LAB_28DB ; branch if not "E" + + ; was "E" so evaluate exponential part + JSR LAB_IGBY ; increment and scan memory + BCC LAB_28C7 ; branch if numeric character + + CMP #TK_MINUS ; else compare with token for - + BEQ LAB_28C2 ; branch if token for - + + CMP #'-' ; else compare with "-" + BEQ LAB_28C2 ; branch if "-" + + CMP #TK_PLUS ; else compare with token for + + BEQ LAB_28C4 ; branch if token for + + + CMP #'+' ; else compare with "+" + BEQ LAB_28C4 ; branch if "+" + + BNE LAB_28C9 ; branch always + +LAB_28C2 + ROR expneg ; set exponent -ve flag (C, which=1, into b7) +LAB_28C4 + JSR LAB_IGBY ; increment and scan memory +LAB_28C7 + BCC LAB_2925 ; branch if numeric character + +LAB_28C9 + BIT expneg ; test exponent -ve flag + BPL LAB_28DB ; if +ve go evaluate exponent + + ; else do exponent = -exponent + LDA #$00 ; clear result + SEC ; set carry for subtract + SBC expcnt ; subtract exponent byte + JMP LAB_28DD ; go evaluate exponent + +LAB_28D5 + ROR numdpf ; set decimal point flag + BIT numdpf ; test decimal point flag + BVC LAB_289E ; branch if only one decimal point so far + + ; evaluate exponent +LAB_28DB + LDA expcnt ; get exponent count byte +LAB_28DD + SEC ; set carry for subtract + SBC numexp ; subtract numerator exponent + STA expcnt ; save exponent count byte + BEQ LAB_28F6 ; branch if no adjustment + + BPL LAB_28EF ; else if +ve go do FAC1*10^expcnt + + ; else go do FAC1/10^(0-expcnt) +LAB_28E6 + JSR LAB_26B9 ; divide by 10 + INC expcnt ; increment exponent count byte + BNE LAB_28E6 ; loop until all done + + BEQ LAB_28F6 ; branch always + +LAB_28EF + JSR LAB_269E ; multiply by 10 + DEC expcnt ; decrement exponent count byte + BNE LAB_28EF ; loop until all done + +LAB_28F6 + LDA negnum ; get -ve flag + BMI LAB_28FB ; if -ve do - FAC1 and return + + RTS + +; do - FAC1 and return + +LAB_28FB + JMP LAB_GTHAN ; do - FAC1 and return + +; do unsigned FAC1*10+number + +LAB_28FE + PHA ; save character + BIT numdpf ; test decimal point flag + BPL LAB_2905 ; skip exponent increment if not set + + INC numexp ; else increment number exponent +LAB_2905 + JSR LAB_269E ; multiply FAC1 by 10 + PLA ; restore character + AND #$0F ; convert to binary + JSR LAB_2912 ; evaluate new ASCII digit + JMP LAB_289E ; go do next character + +; evaluate new ASCII digit + +LAB_2912 + PHA ; save digit + JSR LAB_27AB ; round and copy FAC1 to FAC2 + PLA ; restore digit + JSR LAB_27DB ; save A as integer byte + LDA FAC2_s ; get FAC2 sign (b7) + EOR FAC1_s ; toggle with FAC1 sign (b7) + STA FAC_sc ; save sign compare (FAC1 EOR FAC2) + LDX FAC1_e ; get FAC1 exponent + JMP LAB_ADD ; add FAC2 to FAC1 and return + +; evaluate next character of exponential part of number + +LAB_2925 + LDA expcnt ; get exponent count byte + CMP #$0A ; compare with 10 decimal + BCC LAB_2934 ; branch if less + + LDA #$64 ; make all -ve exponents = -100 decimal (causes underflow) + BIT expneg ; test exponent -ve flag + BMI LAB_2942 ; branch if -ve + + JMP LAB_2564 ; else do overflow error + +LAB_2934 + ASL ; * 2 + ASL ; * 4 + ADC expcnt ; * 5 + ASL ; * 10 + LDY #$00 ; set index + ADC (Bpntrl),Y ; add character (will be $30 too much!) + SBC #'0'-1 ; convert character to binary +LAB_2942 + STA expcnt ; save exponent count byte + JMP LAB_28C4 ; go get next character + +; print " in line [LINE #]" + +LAB_2953 + LDA #LAB_LMSG ; point to " in line " message high byte + JSR LAB_18C3 ; print null terminated string from memory + + ; print Basic line # + LDA Clineh ; get current line high byte + LDX Clinel ; get current line low byte + +; print XA as unsigned integer + +LAB_295E + STA FAC1_1 ; save low byte as FAC1 mantissa1 + STX FAC1_2 ; save high byte as FAC1 mantissa2 + LDX #$90 ; set exponent to 16d bits + SEC ; set integer is +ve flag + JSR LAB_STFA ; set exp=X, clearFAC1 mantissa3 and normalise + LDY #$00 ; clear index + TYA ; clear A + JSR LAB_297B ; convert FAC1 to string, skip sign character save + JMP LAB_18C3 ; print null terminated string from memory and return + +; convert FAC1 to ASCII string result in (AY) +; not any more, moved scratchpad to page 0 + +LAB_296E + LDY #$01 ; set index = 1 + LDA #$20 ; character = " " (assume +ve) + BIT FAC1_s ; test FAC1 sign (b7) + BPL LAB_2978 ; branch if +ve + + LDA #$2D ; else character = "-" +LAB_2978 + STA Decss,Y ; save leading character (" " or "-") +LAB_297B + STA FAC1_s ; clear FAC1 sign (b7) + STY Sendl ; save index + INY ; increment index + LDX FAC1_e ; get FAC1 exponent + BNE LAB_2989 ; branch if FAC1<>0 + + ; exponent was $00 so FAC1 is 0 + LDA #'0' ; set character = "0" + JMP LAB_2A89 ; save last character, [EOT] and exit + + ; FAC1 is some non zero value +LAB_2989 + LDA #$00 ; clear (number exponent count) + CPX #$81 ; compare FAC1 exponent with $81 (>1.00000) + + BCS LAB_299A ; branch if FAC1=>1 + + ; FAC1<1 + LDA #LAB_294F ; set pointer high byte to 1,000,000 + JSR LAB_25FB ; do convert AY, FCA1*(AY) + LDA #$FA ; set number exponent count (-6) +LAB_299A + STA numexp ; save number exponent count +LAB_299C + LDA #LAB_294B ; set pointer high byte to 999999.4375 + JSR LAB_27F8 ; compare FAC1 with (AY) + BEQ LAB_29C3 ; exit if FAC1 = (AY) + + BPL LAB_29B9 ; go do /10 if FAC1 > (AY) + + ; FAC1 < (AY) +LAB_29A7 + LDA #LAB_2947 ; set pointer high byte to 99999.9375 + JSR LAB_27F8 ; compare FAC1 with (AY) + BEQ LAB_29B2 ; branch if FAC1 = (AY) (allow decimal places) + + BPL LAB_29C0 ; branch if FAC1 > (AY) (no decimal places) + + ; FAC1 <= (AY) +LAB_29B2 + JSR LAB_269E ; multiply by 10 + DEC numexp ; decrement number exponent count + BNE LAB_29A7 ; go test again (branch always) + +LAB_29B9 + JSR LAB_26B9 ; divide by 10 + INC numexp ; increment number exponent count + BNE LAB_299C ; go test again (branch always) + +; now we have just the digits to do + +LAB_29C0 + JSR LAB_244E ; add 0.5 to FAC1 (round FAC1) +LAB_29C3 + JSR LAB_2831 ; convert FAC1 floating-to-fixed + LDX #$01 ; set default digits before dp = 1 + LDA numexp ; get number exponent count + CLC ; clear carry for add + ADC #$07 ; up to 6 digits before point + BMI LAB_29D8 ; if -ve then 1 digit before dp + + CMP #$08 ; A>=8 if n>=1E6 + BCS LAB_29D9 ; branch if >= $08 + + ; carry is clear + ADC #$FF ; take 1 from digit count + TAX ; copy to A + LDA #$02 ;.set exponent adjust +LAB_29D8 + SEC ; set carry for subtract +LAB_29D9 + SBC #$02 ; -2 + STA expcnt ;.save exponent adjust + STX numexp ; save digits before dp count + TXA ; copy to A + BEQ LAB_29E4 ; branch if no digits before dp + + BPL LAB_29F7 ; branch if digits before dp + +LAB_29E4 + LDY Sendl ; get output string index + LDA #$2E ; character "." + INY ; increment index + STA Decss,Y ; save to output string + TXA ;. + BEQ LAB_29F5 ;. + + LDA #'0' ; character "0" + INY ; increment index + STA Decss,Y ; save to output string +LAB_29F5 + STY Sendl ; save output string index +LAB_29F7 + LDY #$00 ; clear index (point to 100,000) + LDX #$80 ; +LAB_29FB + LDA FAC1_3 ; get FAC1 mantissa3 + CLC ; clear carry for add + ADC LAB_2A9C,Y ; add -ve LSB + STA FAC1_3 ; save FAC1 mantissa3 + LDA FAC1_2 ; get FAC1 mantissa2 + ADC LAB_2A9B,Y ; add -ve NMSB + STA FAC1_2 ; save FAC1 mantissa2 + LDA FAC1_1 ; get FAC1 mantissa1 + ADC LAB_2A9A,Y ; add -ve MSB + STA FAC1_1 ; save FAC1 mantissa1 + INX ; + BCS LAB_2A18 ; + + BPL LAB_29FB ; not -ve so try again + + BMI LAB_2A1A ; + +LAB_2A18 + BMI LAB_29FB ; + +LAB_2A1A + TXA ; + BCC LAB_2A21 ; + + EOR #$FF ; + ADC #$0A ; +LAB_2A21 + ADC #'0'-1 ; add "0"-1 to result + INY ; increment index .. + INY ; .. to next less .. + INY ; .. power of ten + STY Cvaral ; save as current var address low byte + LDY Sendl ; get output string index + INY ; increment output string index + TAX ; copy character to X + AND #$7F ; mask out top bit + STA Decss,Y ; save to output string + DEC numexp ; decrement # of characters before the dp + BNE LAB_2A3B ; branch if still characters to do + + ; else output the point + LDA #$2E ; character "." + INY ; increment output string index + STA Decss,Y ; save to output string +LAB_2A3B + STY Sendl ; save output string index + LDY Cvaral ; get current var address low byte + TXA ; get character back + EOR #$FF ; + AND #$80 ; + TAX ; + CPY #$12 ; compare index with max + BNE LAB_29FB ; loop if not max + + ; now remove trailing zeroes + LDY Sendl ; get output string index +LAB_2A4B + LDA Decss,Y ; get character from output string + DEY ; decrement output string index + CMP #'0' ; compare with "0" + BEQ LAB_2A4B ; loop until non "0" character found + + CMP #'.' ; compare with "." + BEQ LAB_2A58 ; branch if was dp + + ; restore last character + INY ; increment output string index +LAB_2A58 + LDA #$2B ; character "+" + LDX expcnt ; get exponent count + BEQ LAB_2A8C ; if zero go set null terminator and exit + + ; exponent isn't zero so write exponent + BPL LAB_2A68 ; branch if exponent count +ve + + LDA #$00 ; clear A + SEC ; set carry for subtract + SBC expcnt ; subtract exponent count adjust (convert -ve to +ve) + TAX ; copy exponent count to X + LDA #'-' ; character "-" +LAB_2A68 + STA Decss+2,Y ; save to output string + LDA #$45 ; character "E" + STA Decss+1,Y ; save exponent sign to output string + TXA ; get exponent count back + LDX #'0'-1 ; one less than "0" character + SEC ; set carry for subtract +LAB_2A74 + INX ; increment 10's character + SBC #$0A ;.subtract 10 from exponent count + BCS LAB_2A74 ; loop while still >= 0 + + ADC #':' ; add character ":" ($30+$0A, result is 10 less that value) + STA Decss+4,Y ; save to output string + TXA ; copy 10's character + STA Decss+3,Y ; save to output string + LDA #$00 ; set null terminator + STA Decss+5,Y ; save to output string + BEQ LAB_2A91 ; go set string pointer (AY) and exit (branch always) + + ; save last character, [EOT] and exit +LAB_2A89 + STA Decss,Y ; save last character to output string + + ; set null terminator and exit +LAB_2A8C + LDA #$00 ; set null terminator + STA Decss+1,Y ; save after last character + + ; set string pointer (AY) and exit +LAB_2A91 + LDA #Decssp1 ; set result string high pointer + RTS + +; perform power function + +LAB_POWER + BEQ LAB_EXP ; go do EXP() + + LDA FAC2_e ; get FAC2 exponent + BNE LAB_2ABF ; branch if FAC2<>0 + + JMP LAB_24F3 ; clear FAC1 exponent and sign and return + +LAB_2ABF + LDX #func_l ; set destination pointer high byte + JSR LAB_2778 ; pack FAC1 into (XY) + LDA FAC2_s ; get FAC2 sign (b7) + BPL LAB_2AD9 ; branch if FAC2>0 + + ; else FAC2 is -ve and can only be raised to an + ; integer power which gives an x +j0 result + JSR LAB_INT ; perform INT + LDA #func_l ; set source pointer high byte + JSR LAB_27F8 ; compare FAC1 with (AY) + BNE LAB_2AD9 ; branch if FAC1 <> (AY) to allow Function Call error + ; this will leave FAC1 -ve and cause a Function Call + ; error when LOG() is called + + TYA ; clear sign b7 + LDY Temp3 ; save mantissa 3 from INT() function as sign in Y + ; for possible later negation, b0 +LAB_2AD9 + JSR LAB_279D ; save FAC1 sign and copy ABS(FAC2) to FAC1 + TYA ; copy sign back .. + PHA ; .. and save it + JSR LAB_LOG ; do LOG(n) + LDA #garb_l ; set pointer high byte + JSR LAB_25FB ; do convert AY, FCA1*(AY) (square the value) + JSR LAB_EXP ; go do EXP(n) + PLA ; pull sign from stack + LSR ; b0 is to be tested, shift to Cb + BCC LAB_2AF9 ; if no bit then exit + + ; Perform negation +; do - FAC1 + +LAB_GTHAN + LDA FAC1_e ; get FAC1 exponent + BEQ LAB_2AF9 ; exit if FAC1_e = $00 + + LDA FAC1_s ; get FAC1 sign (b7) + EOR #$FF ; complement it + STA FAC1_s ; save FAC1 sign (b7) +LAB_2AF9 + RTS + +; perform EXP() (x^e) + +LAB_EXP + LDA #LAB_2AFA ; set 1.443 pointer high byte + JSR LAB_25FB ; do convert AY, FCA1*(AY) + LDA FAC1_r ; get FAC1 rounding byte + ADC #$50 ; +$50/$100 + BCC LAB_2B2B ; skip rounding if no carry + + JSR LAB_27C2 ; round FAC1 (no check) +LAB_2B2B + STA FAC2_r ; save FAC2 rounding byte + JSR LAB_27AE ; copy FAC1 to FAC2 + LDA FAC1_e ; get FAC1 exponent + CMP #$88 ; compare with EXP limit (256d) + BCC LAB_2B39 ; branch if less + +LAB_2B36 + JSR LAB_2690 ; handle overflow and underflow +LAB_2B39 + JSR LAB_INT ; perform INT + LDA Temp3 ; get mantissa 3 from INT() function + CLC ; clear carry for add + ADC #$81 ; normalise +1 + BEQ LAB_2B36 ; if $00 go handle overflow + + SEC ; set carry for subtract + SBC #$01 ; now correct for exponent + PHA ; save FAC2 exponent + + ; swap FAC1 and FAC2 + LDX #$04 ; 4 bytes to do +LAB_2B49 + LDA FAC2_e,X ; get FAC2,X + LDY FAC1_e,X ; get FAC1,X + STA FAC1_e,X ; save FAC1,X + STY FAC2_e,X ; save FAC2,X + DEX ; decrement count/index + BPL LAB_2B49 ; loop if not all done + + LDA FAC2_r ; get FAC2 rounding byte + STA FAC1_r ; save as FAC1 rounding byte + JSR LAB_SUBTRACT ; perform subtraction, FAC2 from FAC1 + JSR LAB_GTHAN ; do - FAC1 + LDA #LAB_2AFE ; set counter pointer high byte + JSR LAB_2B84 ; go do series evaluation + LDA #$00 ; clear A + STA FAC_sc ; clear sign compare (FAC1 EOR FAC2) + PLA ;.get saved FAC2 exponent + JMP LAB_2675 ; test and adjust accumulators and return + +; ^2 then series evaluation + +LAB_2B6E + STA Cptrl ; save count pointer low byte + STY Cptrh ; save count pointer high byte + JSR LAB_276E ; pack FAC1 into Adatal + LDA #Adatal ; pointer to original # high byte + JMP LAB_25FB ; do convert AY, FCA1*(AY) and return + +; series evaluation + +LAB_2B84 + STA Cptrl ; save count pointer low byte + STY Cptrh ; save count pointer high byte +LAB_2B88 + LDX #numexp ; set pointer high byte to partial @ numexp + DEC numcon ; decrement constants count + BNE LAB_2B9B ; loop until all done + + RTS + +; RND(n), 32 bit Galoise version. make n=0 for 19th next number in sequence or n<>0 +; to get 19th next number in sequence after seed n. This version of the PRNG uses +; the Galois method and a sample of 65536 bytes produced gives the following values. + +; Entropy = 7.997442 bits per byte +; Optimum compression would reduce these 65536 bytes by 0 percent + +; Chi square distribution for 65536 samples is 232.01, and +; randomly would exceed this value 75.00 percent of the time + +; Arithmetic mean value of data bytes is 127.6724, 127.5 would be random +; Monte Carlo value for Pi is 3.122871269, error 0.60 percent +; Serial correlation coefficient is -0.000370, totally uncorrelated would be 0.0 + +LAB_RND + LDA FAC1_e ; get FAC1 exponent + BEQ NextPRN ; do next random # if zero + + ; else get seed into random number store + LDX #Rbyte4 ; set PRNG pointer low byte + LDY #$00 ; set PRNG pointer high byte + JSR LAB_2778 ; pack FAC1 into (XY) +NextPRN + LDX #$AF ; set EOR byte + LDY #$13 ; do this nineteen times +LoopPRN + ASL Rbyte1 ; shift PRNG most significant byte + ROL Rbyte2 ; shift PRNG middle byte + ROL Rbyte3 ; shift PRNG least significant byte + ROL Rbyte4 ; shift PRNG extra byte + BCC Ninc1 ; branch if bit 32 clear + + TXA ; set EOR byte + EOR Rbyte1 ; EOR PRNG extra byte + STA Rbyte1 ; save new PRNG extra byte +Ninc1 + DEY ; decrement loop count + BNE LoopPRN ; loop if not all done + + LDX #$02 ; three bytes to copy +CopyPRNG + LDA Rbyte1,X ; get PRNG byte + STA FAC1_1,X ; save FAC1 byte + DEX + BPL CopyPRNG ; loop if not complete + + LDA #$80 ; set the exponent + STA FAC1_e ; save FAC1 exponent + + ASL ; clear A + STA FAC1_s ; save FAC1 sign + + JMP LAB_24D5 ; normalise FAC1 and return + +; perform COS() + +LAB_COS + LDA #LAB_2C78 ; set (pi/2) pointer high byte + JSR LAB_246C ; add (AY) to FAC1 + +; perform SIN() + +LAB_SIN + JSR LAB_27AB ; round and copy FAC1 to FAC2 + LDA #LAB_2C7C ; set (2*pi) pointer high byte + LDX FAC2_s ; get FAC2 sign (b7) + JSR LAB_26C2 ; divide by (AY) (X=sign) + JSR LAB_27AB ; round and copy FAC1 to FAC2 + JSR LAB_INT ; perform INT + LDA #$00 ; clear byte + STA FAC_sc ; clear sign compare (FAC1 EOR FAC2) + JSR LAB_SUBTRACT ; perform subtraction, FAC2 from FAC1 + LDA #LAB_2C80 ; set 0.25 pointer high byte + JSR LAB_2455 ; perform subtraction, (AY) from FAC1 + LDA FAC1_s ; get FAC1 sign (b7) + PHA ; save FAC1 sign + BPL LAB_2C35 ; branch if +ve + + ; FAC1 sign was -ve + JSR LAB_244E ; add 0.5 to FAC1 + LDA FAC1_s ; get FAC1 sign (b7) + BMI LAB_2C38 ; branch if -ve + + LDA Cflag ; get comparison evaluation flag + EOR #$FF ; toggle flag + STA Cflag ; save comparison evaluation flag +LAB_2C35 + JSR LAB_GTHAN ; do - FAC1 +LAB_2C38 + LDA #LAB_2C80 ; set 0.25 pointer high byte + JSR LAB_246C ; add (AY) to FAC1 + PLA ; restore FAC1 sign + BPL LAB_2C45 ; branch if was +ve + + ; else correct FAC1 + JSR LAB_GTHAN ; do - FAC1 +LAB_2C45 + LDA #LAB_2C84 ; set pointer high byte to counter + JMP LAB_2B6E ; ^2 then series evaluation and return + +; perform TAN() + +LAB_TAN + JSR LAB_276E ; pack FAC1 into Adatal + LDA #$00 ; clear byte + STA Cflag ; clear comparison evaluation flag + JSR LAB_SIN ; go do SIN(n) + LDX #func_l ; set sin(n) pointer high byte + JSR LAB_2778 ; pack FAC1 into (XY) + LDA #Adatal ; set n pointer high addr + JSR LAB_UFAC ; unpack memory (AY) into FAC1 + LDA #$00 ; clear byte + STA FAC1_s ; clear FAC1 sign (b7) + LDA Cflag ; get comparison evaluation flag + JSR LAB_2C74 ; save flag and go do series evaluation + + LDA #func_l ; set sin(n) pointer high byte + JMP LAB_26CA ; convert AY and do (AY)/FAC1 + +LAB_2C74 + PHA ; save comparison evaluation flag + JMP LAB_2C35 ; go do series evaluation + +; perform USR() + +LAB_USR + JSR Usrjmp ; call user code + JMP LAB_1BFB ; scan for ")", else do syntax error then warm start + +; perform ATN() + +LAB_ATN + LDA FAC1_s ; get FAC1 sign (b7) + PHA ; save sign + BPL LAB_2CA1 ; branch if +ve + + JSR LAB_GTHAN ; else do - FAC1 +LAB_2CA1 + LDA FAC1_e ; get FAC1 exponent + PHA ; push exponent + CMP #$81 ; compare with 1 + BCC LAB_2CAF ; branch if FAC1<1 + + LDA #LAB_259C ; set 1 pointer high byte + JSR LAB_26CA ; convert AY and do (AY)/FAC1 +LAB_2CAF + LDA #LAB_2CC9 ; set pointer high byte to counter + JSR LAB_2B6E ; ^2 then series evaluation + PLA ; restore old FAC1 exponent + CMP #$81 ; compare with 1 + BCC LAB_2CC2 ; branch if FAC1<1 + + LDA #LAB_2C78 ; set (pi/2) pointer high byte + JSR LAB_2455 ; perform subtraction, (AY) from FAC1 +LAB_2CC2 + PLA ; restore FAC1 sign + BPL LAB_2D04 ; exit if was +ve + + JMP LAB_GTHAN ; else do - FAC1 and return + +; perform BITSET + +LAB_BITSET + JSR LAB_GADB ; get two parameters for POKE or WAIT + CPX #$08 ; only 0 to 7 are allowed + BCS FCError ; branch if > 7 + + LDA #$00 ; clear A + SEC ; set the carry +S_Bits + ROL ; shift bit + DEX ; decrement bit number + BPL S_Bits ; loop if still +ve + + INX ; make X = $00 + ORA (Itempl,X) ; or with byte via temporary integer (addr) + STA (Itempl,X) ; save byte via temporary integer (addr) +LAB_2D04 + RTS + +; perform BITCLR + +LAB_BITCLR + JSR LAB_GADB ; get two parameters for POKE or WAIT + CPX #$08 ; only 0 to 7 are allowed + BCS FCError ; branch if > 7 + + LDA #$FF ; set A +S_Bitc + ROL ; shift bit + DEX ; decrement bit number + BPL S_Bitc ; loop if still +ve + + INX ; make X = $00 + AND (Itempl,X) ; and with byte via temporary integer (addr) + STA (Itempl,X) ; save byte via temporary integer (addr) + RTS + +FCError + JMP LAB_FCER ; do function call error then warm start + +; perform BITTST() + +LAB_BTST + JSR LAB_IGBY ; increment BASIC pointer + JSR LAB_GADB ; get two parameters for POKE or WAIT + CPX #$08 ; only 0 to 7 are allowed + BCS FCError ; branch if > 7 + + JSR LAB_GBYT ; get next BASIC byte + CMP #')' ; is next character ")" + BEQ TST_OK ; if ")" go do rest of function + + JMP LAB_SNER ; do syntax error then warm start + +TST_OK + JSR LAB_IGBY ; update BASIC execute pointer (to character past ")") + LDA #$00 ; clear A + SEC ; set the carry +T_Bits + ROL ; shift bit + DEX ; decrement bit number + BPL T_Bits ; loop if still +ve + + INX ; make X = $00 + AND (Itempl,X) ; AND with byte via temporary integer (addr) + BEQ LAB_NOTT ; branch if zero (already correct) + + LDA #$FF ; set for -1 result +LAB_NOTT + JMP LAB_27DB ; go do SGN tail + +; perform BIN$() + +LAB_BINS + CPX #$19 ; max + 1 + BCS BinFErr ; exit if too big ( > or = ) + + STX TempB ; save # of characters ($00 = leading zero remove) + LDA #$18 ; need A byte long space + JSR LAB_MSSP ; make string space A bytes long + LDY #$17 ; set index + LDX #$18 ; character count +NextB1 + LSR nums_1 ; shift highest byte + ROR nums_2 ; shift middle byte + ROR nums_3 ; shift lowest byte bit 0 to carry + TXA ; load with "0"/2 + ROL ; shift in carry + STA (str_pl),Y ; save to temp string + index + DEY ; decrement index + BPL NextB1 ; loop if not done + + LDA TempB ; get # of characters + BEQ EndBHS ; branch if truncate + + TAX ; copy length to X + SEC ; set carry for add ! + EOR #$FF ; 1's complement + ADC #$18 ; add 24d + BEQ GoPr2 ; if zero print whole string + + BNE GoPr1 ; else go make output string + +; this is the exit code and is also used by HEX$() +; truncate string to remove leading "0"s + +EndBHS + TAY ; clear index (A=0, X=length here) +NextB2 + LDA (str_pl),Y ; get character from string + CMP #'0' ; compare with "0" + BNE GoPr ; if not "0" then go print string from here + + DEX ; decrement character count + BEQ GoPr3 ; if zero then end of string so go print it + + INY ; else increment index + BPL NextB2 ; loop always + +; make fixed length output string - ignore overflows! + +GoPr3 + INX ; need at least 1 character +GoPr + TYA ; copy result +GoPr1 + CLC ; clear carry for add + ADC str_pl ; add low address + STA str_pl ; save low address + LDA #$00 ; do high byte + ADC str_ph ; add high address + STA str_ph ; save high address +GoPr2 + STX str_ln ; X holds string length + JSR LAB_IGBY ; update BASIC execute pointer (to character past ")") + JMP LAB_RTST ; check for space on descriptor stack then put address + ; and length on descriptor stack and update stack pointers + +BinFErr + JMP LAB_FCER ; do function call error then warm start + +; perform HEX$() + +LAB_HEXS + CPX #$07 ; max + 1 + BCS BinFErr ; exit if too big ( > or = ) + + STX TempB ; save # of characters + + LDA #$06 ; need 6 bytes for string + JSR LAB_MSSP ; make string space A bytes long + LDY #$05 ; set string index + + SED ; need decimal mode for nibble convert + LDA nums_3 ; get lowest byte + JSR LAB_A2HX ; convert A to ASCII hex byte and output + LDA nums_2 ; get middle byte + JSR LAB_A2HX ; convert A to ASCII hex byte and output + LDA nums_1 ; get highest byte + JSR LAB_A2HX ; convert A to ASCII hex byte and output + CLD ; back to binary + + LDX #$06 ; character count + LDA TempB ; get # of characters + BEQ EndBHS ; branch if truncate + + TAX ; copy length to X + SEC ; set carry for add ! + EOR #$FF ; 1's complement + ADC #$06 ; add 6d + BEQ GoPr2 ; if zero print whole string + + BNE GoPr1 ; else go make output string (branch always) + +; convert A to ASCII hex byte and output .. note set decimal mode before calling + +LAB_A2HX + TAX ; save byte + AND #$0F ; mask off top bits + JSR LAB_AL2X ; convert low nibble to ASCII and output + TXA ; get byte back + LSR ; /2 shift high nibble to low nibble + LSR ; /4 + LSR ; /8 + LSR ; /16 +LAB_AL2X + CMP #$0A ; set carry for +1 if >9 + ADC #'0' ; add ASCII "0" + STA (str_pl),Y ; save to temp string + DEY ; decrement counter + RTS + +LAB_NLTO + STA FAC1_e ; save FAC1 exponent + LDA #$00 ; clear sign compare +LAB_MLTE + STA FAC_sc ; save sign compare (FAC1 EOR FAC2) + TXA ; restore character + JSR LAB_2912 ; evaluate new ASCII digit + +; gets here if the first character was "$" for hex +; get hex number + +LAB_CHEX + JSR LAB_IGBY ; increment and scan memory + BCC LAB_ISHN ; branch if numeric character + + ORA #$20 ; case convert, allow "A" to "F" and "a" to "f" + SBC #'a' ; subtract "a" (carry set here) + CMP #$06 ; compare normalised with $06 (max+1) + BCS LAB_EXCH ; exit if >"f" or <"0" + + ADC #$0A ; convert to nibble +LAB_ISHN + AND #$0F ; convert to binary + TAX ; save nibble + LDA FAC1_e ; get FAC1 exponent + BEQ LAB_MLTE ; skip multiply if zero + + ADC #$04 ; add four to exponent (*16 - carry clear here) + BCC LAB_NLTO ; if no overflow do evaluate digit + +LAB_MLTO + JMP LAB_2564 ; do overflow error and warm start + +LAB_NXCH + TAX ; save bit + LDA FAC1_e ; get FAC1 exponent + BEQ LAB_MLBT ; skip multiply if zero + + INC FAC1_e ; increment FAC1 exponent (*2) + BEQ LAB_MLTO ; do overflow error if = $00 + + LDA #$00 ; clear sign compare +LAB_MLBT + STA FAC_sc ; save sign compare (FAC1 EOR FAC2) + TXA ; restore bit + JSR LAB_2912 ; evaluate new ASCII digit + +; gets here if the first character was "%" for binary +; get binary number + +LAB_CBIN + JSR LAB_IGBY ; increment and scan memory + EOR #'0' ; convert "0" to 0 etc. + CMP #$02 ; compare with max+1 + BCC LAB_NXCH ; branch exit if < 2 + +LAB_EXCH + JMP LAB_28F6 ; evaluate -ve flag and return + +; ctrl-c check routine. includes limited "life" byte save for INGET routine +; now also the code that checks to see if an interrupt has occurred + +CTRLC + LDA ccflag ; get [CTRL-C] check flag + BNE LAB_FBA2 ; exit if inhibited + + JSR V_INPT ; scan input device + BCC LAB_FBA0 ; exit if buffer empty + + STA ccbyte ; save received byte + LDX #$20 ; "life" timer for bytes + STX ccnull ; set countdown + JMP LAB_1636 ; return to BASIC + +LAB_FBA0 + LDX ccnull ; get countdown byte + BEQ LAB_FBA2 ; exit if finished + + DEC ccnull ; else decrement countdown +LAB_FBA2 + LDX #NmiBase ; set pointer to NMI values + JSR LAB_CKIN ; go check interrupt + LDX #IrqBase ; set pointer to IRQ values + JSR LAB_CKIN ; go check interrupt +LAB_CRTS + RTS + +; check whichever interrupt is indexed by X + +LAB_CKIN + LDA PLUS_0,X ; get interrupt flag byte + BPL LAB_CRTS ; branch if interrupt not enabled + +; we disable the interrupt here and make two new commands RETIRQ and RETNMI to +; automatically enable the interrupt when we exit + + ASL ; move happened bit to setup bit + AND #$40 ; mask happened bits + BEQ LAB_CRTS ; if no interrupt then exit + + STA PLUS_0,X ; save interrupt flag byte + + TXA ; copy index .. + TAY ; .. to Y + + PLA ; dump return address low byte, call from CTRL-C + PLA ; dump return address high byte + + LDA #$05 ; need 5 bytes for GOSUB + JSR LAB_1212 ; check room on stack for A bytes + LDA Bpntrh ; get BASIC execute pointer high byte + PHA ; push on stack + LDA Bpntrl ; get BASIC execute pointer low byte + PHA ; push on stack + LDA Clineh ; get current line high byte + PHA ; push on stack + LDA Clinel ; get current line low byte + PHA ; push on stack + LDA #TK_GOSUB ; token for GOSUB + PHA ; push on stack + + LDA PLUS_1,Y ; get interrupt code pointer low byte + STA Bpntrl ; save as BASIC execute pointer low byte + LDA PLUS_2,Y ; get interrupt code pointer high byte + STA Bpntrh ; save as BASIC execute pointer high byte + + JMP LAB_15C2 ; go do interpreter inner loop + ; can't RTS, we used the stack! the RTS from the ctrl-c + ; check will be taken when the RETIRQ/RETNMI/RETURN is + ; executed at the end of the subroutine + +; get byte from input device, no waiting +; returns with carry set if byte in A + +INGET + JSR V_INPT ; call scan input device + BCS LAB_FB95 ; if byte go reset timer + + LDA ccnull ; get countdown + BEQ LAB_FB96 ; exit if empty + + LDA ccbyte ; get last received byte + SEC ; flag we got a byte +LAB_FB95 + LDX #$00 ; clear X + STX ccnull ; clear timer because we got a byte +LAB_FB96 + RTS + +; these routines only enable the interrupts if the set-up flag is set +; if not they have no effect + +; perform IRQ {ON|OFF|CLEAR} + +LAB_IRQ + LDX #IrqBase ; set pointer to IRQ values + .byte $2C ; make next line BIT abs. + +; perform NMI {ON|OFF|CLEAR} + +LAB_NMI + LDX #NmiBase ; set pointer to NMI values + CMP #TK_ON ; compare with token for ON + BEQ LAB_INON ; go turn on interrupt + + CMP #TK_OFF ; compare with token for OFF + BEQ LAB_IOFF ; go turn off interrupt + + EOR #TK_CLEAR ; compare with token for CLEAR, A = $00 if = TK_CLEAR + BEQ LAB_INEX ; go clear interrupt flags and return + + JMP LAB_SNER ; do syntax error then warm start + +LAB_IOFF + LDA #$7F ; clear A + AND PLUS_0,X ; AND with interrupt setup flag + BPL LAB_INEX ; go clear interrupt enabled flag and return + +LAB_INON + LDA PLUS_0,X ; get interrupt setup flag + ASL ; Shift bit to enabled flag + ORA PLUS_0,X ; OR with flag byte +LAB_INEX + STA PLUS_0,X ; save interrupt flag byte + JMP LAB_IGBY ; update BASIC execute pointer and return + +; these routines set up the pointers and flags for the interrupt routines +; note that the interrupts are also enabled by these commands + +; perform ON IRQ + +LAB_SIRQ + CLI ; enable interrupts + LDX #IrqBase ; set pointer to IRQ values + .byte $2C ; make next line BIT abs. + +; perform ON NMI + +LAB_SNMI + LDX #NmiBase ; set pointer to NMI values + + STX TempB ; save interrupt pointer + JSR LAB_IGBY ; increment and scan memory (past token) + JSR LAB_GFPN ; get fixed-point number into temp integer + LDA Smeml ; get start of mem low byte + LDX Smemh ; get start of mem high byte + JSR LAB_SHLN ; search Basic for temp integer line number from AX + BCS LAB_LFND ; if carry set go set-up interrupt + + JMP LAB_16F7 ; else go do "Undefined statement" error and warm start + +LAB_LFND + LDX TempB ; get interrupt pointer + LDA Baslnl ; get pointer low byte + SBC #$01 ; -1 (carry already set for subtract) + STA PLUS_1,X ; save as interrupt pointer low byte + LDA Baslnh ; get pointer high byte + SBC #$00 ; subtract carry + STA PLUS_2,X ; save as interrupt pointer high byte + + LDA #$C0 ; set interrupt enabled/setup bits + STA PLUS_0,X ; set interrupt flags +LAB_IRTS + RTS + +; return from IRQ service, restores the enabled flag. + +; perform RETIRQ + +LAB_RETIRQ + BNE LAB_IRTS ; exit if following token (to allow syntax error) + + LDA IrqBase ; get interrupt flags + ASL ; copy setup to enabled (b7) + ORA IrqBase ; OR in setup flag + STA IrqBase ; save enabled flag + JMP LAB_16E8 ; go do rest of RETURN + +; return from NMI service, restores the enabled flag. + +; perform RETNMI + +LAB_RETNMI + BNE LAB_IRTS ; exit if following token (to allow syntax error) + + LDA NmiBase ; get set-up flag + ASL ; copy setup to enabled (b7) + ORA NmiBase ; OR in setup flag + STA NmiBase ; save enabled flag + JMP LAB_16E8 ; go do rest of RETURN + +; MAX() MIN() pre process + +LAB_MMPP + JSR LAB_EVEZ ; process expression + JMP LAB_CTNM ; check if source is numeric, else do type mismatch + +; perform MAX() + +LAB_MAX + JSR LAB_PHFA ; push FAC1, evaluate expression, + ; pull FAC2 and compare with FAC1 + BPL LAB_MAX ; branch if no swap to do + + LDA FAC2_1 ; get FAC2 mantissa1 + ORA #$80 ; set top bit (clear sign from compare) + STA FAC2_1 ; save FAC2 mantissa1 + JSR LAB_279B ; copy FAC2 to FAC1 + BEQ LAB_MAX ; go do next (branch always) + +; perform MIN() + +LAB_MIN + JSR LAB_PHFA ; push FAC1, evaluate expression, + ; pull FAC2 and compare with FAC1 + BMI LAB_MIN ; branch if no swap to do + + BEQ LAB_MIN ; branch if no swap to do + + LDA FAC2_1 ; get FAC2 mantissa1 + ORA #$80 ; set top bit (clear sign from compare) + STA FAC2_1 ; save FAC2 mantissa1 + JSR LAB_279B ; copy FAC2 to FAC1 + BEQ LAB_MIN ; go do next (branch always) + +; exit routine. don't bother returning to the loop code +; check for correct exit, else so syntax error + +LAB_MMEC + CMP #')' ; is it end of function? + BNE LAB_MMSE ; if not do MAX MIN syntax error + + PLA ; dump return address low byte + PLA ; dump return address high byte + JMP LAB_IGBY ; update BASIC execute pointer (to chr past ")") + +LAB_MMSE + JMP LAB_SNER ; do syntax error then warm start + +; check for next, evaluate and return or exit +; this is the routine that does most of the work + +LAB_PHFA + JSR LAB_GBYT ; get next BASIC byte + CMP #',' ; is there more ? + BNE LAB_MMEC ; if not go do end check + + ; push FAC1 + JSR LAB_27BA ; round FAC1 + LDA FAC1_s ; get FAC1 sign + ORA #$7F ; set all non sign bits + AND FAC1_1 ; AND FAC1 mantissa1 (AND in sign bit) + PHA ; push on stack + LDA FAC1_2 ; get FAC1 mantissa2 + PHA ; push on stack + LDA FAC1_3 ; get FAC1 mantissa3 + PHA ; push on stack + LDA FAC1_e ; get FAC1 exponent + PHA ; push on stack + + JSR LAB_IGBY ; scan and get next BASIC byte (after ",") + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch + + ; pop FAC2 (MAX/MIN expression so far) + PLA ; pop exponent + STA FAC2_e ; save FAC2 exponent + PLA ; pop mantissa3 + STA FAC2_3 ; save FAC2 mantissa3 + PLA ; pop mantissa1 + STA FAC2_2 ; save FAC2 mantissa2 + PLA ; pop sign/mantissa1 + STA FAC2_1 ; save FAC2 sign/mantissa1 + STA FAC2_s ; save FAC2 sign + + ; compare FAC1 with (packed) FAC2 + LDA #FAC2_e ; set pointer high byte to FAC2 + JMP LAB_27F8 ; compare FAC1 with FAC2 (AY) and return + ; returns A=$00 if FAC1 = (AY) + ; returns A=$01 if FAC1 > (AY) + ; returns A=$FF if FAC1 < (AY) + +; perform WIDTH + +LAB_WDTH + CMP #',' ; is next byte "," + BEQ LAB_TBSZ ; if so do tab size + + JSR LAB_GTBY ; get byte parameter + TXA ; copy width to A + BEQ LAB_NSTT ; branch if set for infinite line + + CPX #$10 ; else make min width = 16d + BCC TabErr ; if less do function call error and exit + +; this next compare ensures that we can't exit WIDTH via an error leaving the +; tab size greater than the line length. + + CPX TabSiz ; compare with tab size + BCS LAB_NSTT ; branch if >= tab size + + STX TabSiz ; else make tab size = terminal width +LAB_NSTT + STX TWidth ; set the terminal width + JSR LAB_GBYT ; get BASIC byte back + BEQ WExit ; exit if no following + + CMP #',' ; else is it "," + BNE LAB_MMSE ; if not do syntax error + +LAB_TBSZ + JSR LAB_SGBY ; scan and get byte parameter + TXA ; copy TAB size + BMI TabErr ; if >127 do function call error and exit + + CPX #$01 ; compare with min-1 + BCC TabErr ; if <=1 do function call error and exit + + LDA TWidth ; set flags for width + BEQ LAB_SVTB ; skip check if infinite line + + CPX TWidth ; compare TAB with width + BEQ LAB_SVTB ; ok if = + + BCS TabErr ; branch if too big + +LAB_SVTB + STX TabSiz ; save TAB size + +; calculate tab column limit from TAB size. The Iclim is set to the last tab +; position on a line that still has at least one whole tab width between it +; and the end of the line. + +WExit + LDA TWidth ; get width + BEQ LAB_SULP ; branch if infinite line + + CMP TabSiz ; compare with tab size + BCS LAB_WDLP ; branch if >= tab size + + STA TabSiz ; else make tab size = terminal width +LAB_SULP + SEC ; set carry for subtract +LAB_WDLP + SBC TabSiz ; subtract tab size + BCS LAB_WDLP ; loop while no borrow + + ADC TabSiz ; add tab size back + CLC ; clear carry for add + ADC TabSiz ; add tab size back again + STA Iclim ; save for now + LDA TWidth ; get width back + SEC ; set carry for subtract + SBC Iclim ; subtract remainder + STA Iclim ; save tab column limit +LAB_NOSQ + RTS + +TabErr + JMP LAB_FCER ; do function call error then warm start + +; perform SQR() + +LAB_SQR + LDA FAC1_s ; get FAC1 sign + BMI TabErr ; if -ve do function call error + + LDA FAC1_e ; get exponent + BEQ LAB_NOSQ ; if zero just return + + ; else do root + JSR LAB_27AB ; round and copy FAC1 to FAC2 + LDA #$00 ; clear A + + STA FACt_3 ; clear remainder + STA FACt_2 ; .. + STA FACt_1 ; .. + STA TempB ; .. + + STA FAC1_3 ; clear root + STA FAC1_2 ; .. + STA FAC1_1 ; .. + + LDX #$18 ; 24 pairs of bits to do + LDA FAC2_e ; get exponent + LSR ; check odd/even + BCS LAB_SQE2 ; if odd only 1 shift first time + +LAB_SQE1 + ASL FAC2_3 ; shift highest bit of number .. + ROL FAC2_2 ; .. + ROL FAC2_1 ; .. + ROL FACt_3 ; .. into remainder + ROL FACt_2 ; .. + ROL FACt_1 ; .. + ROL TempB ; .. never overflows +LAB_SQE2 + ASL FAC2_3 ; shift highest bit of number .. + ROL FAC2_2 ; .. + ROL FAC2_1 ; .. + ROL FACt_3 ; .. into remainder + ROL FACt_2 ; .. + ROL FACt_1 ; .. + ROL TempB ; .. never overflows + + ASL FAC1_3 ; root = root * 2 + ROL FAC1_2 ; .. + ROL FAC1_1 ; .. never overflows + + LDA FAC1_3 ; get root low byte + ROL ; *2 + STA Temp3 ; save partial low byte + LDA FAC1_2 ; get root low mid byte + ROL ; *2 + STA Temp3+1 ; save partial low mid byte + LDA FAC1_1 ; get root high mid byte + ROL ; *2 + STA Temp3+2 ; save partial high mid byte + LDA #$00 ; get root high byte (always $00) + ROL ; *2 + STA Temp3+3 ; save partial high byte + + ; carry clear for subtract +1 + LDA FACt_3 ; get remainder low byte + SBC Temp3 ; subtract partial low byte + STA Temp3 ; save partial low byte + + LDA FACt_2 ; get remainder low mid byte + SBC Temp3+1 ; subtract partial low mid byte + STA Temp3+1 ; save partial low mid byte + + LDA FACt_1 ; get remainder high mid byte + SBC Temp3+2 ; subtract partial high mid byte + TAY ; copy partial high mid byte + + LDA TempB ; get remainder high byte + SBC Temp3+3 ; subtract partial high byte + BCC LAB_SQNS ; skip sub if remainder smaller + + STA TempB ; save remainder high byte + + STY FACt_1 ; save remainder high mid byte + + LDA Temp3+1 ; get remainder low mid byte + STA FACt_2 ; save remainder low mid byte + + LDA Temp3 ; get partial low byte + STA FACt_3 ; save remainder low byte + + INC FAC1_3 ; increment root low byte (never any rollover) +LAB_SQNS + DEX ; decrement bit pair count + BNE LAB_SQE1 ; loop if not all done + + SEC ; set carry for subtract + LDA FAC2_e ; get exponent + SBC #$80 ; normalise + ROR ; /2 and re-bias to $80 + ADC #$00 ; add bit zero back in (allow for half shift) + STA FAC1_e ; save it + JMP LAB_24D5 ; normalise FAC1 and return + +; perform VARPTR() + +LAB_VARPTR + JSR LAB_IGBY ; increment and scan memory + JSR LAB_GVAR ; get var address + JSR LAB_1BFB ; scan for ")" , else do syntax error then warm start + LDY Cvaral ; get var address low byte + LDA Cvarah ; get var address high byte + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +; perform PI + +LAB_PI + LDA #LAB_2C7C ; set (2*pi) pointer high byte + JSR LAB_UFAC ; unpack memory (AY) into FAC1 + DEC FAC1_e ; make result = PI + RTS + +; perform TWOPI + +LAB_TWOPI + LDA #LAB_2C7C ; set (2*pi) pointer high byte + JMP LAB_UFAC ; unpack memory (AY) into FAC1 and return + +; system dependant i/o vectors +; these are in RAM and are set by the monitor at start-up + +V_INPT + JMP (VEC_IN) ; non halting scan input device +V_OUTP + JMP (VEC_OUT) ; send byte to output device +V_LOAD + JMP (VEC_LD) ; load BASIC program +V_SAVE + JMP (VEC_SV) ; save BASIC program + +; The rest are tables messages and code for RAM + +; the rest of the code is tables and BASIC start-up code + +PG2_TABS + .byte $FF ; ctrl-c flag - $00 = enabled + .byte $00 ; ctrl-c byte - GET needs this + .byte $00 ; ctrl-c byte timeout - GET needs this + .word CTRLC ; ctrl c check vector + .word CHRIN ; non halting key input - monitor to set this + .word CHROUT ; output vector - monitor to set this +; .word xxxx ; load vector - monitor to set this +; .word xxxx ; save vector - monitor to set this +PG2_TABE + +; character get subroutine for zero page + +; For a 1.8432MHz 6502 including the JSR and RTS +; fastest (>=":") = 29 cycles = 15.7uS +; slowest (<":") = 40 cycles = 21.7uS +; space skip = +21 cycles = +11.4uS +; inc across page = +4 cycles = +2.2uS + +; the target address for the LDA at LAB_2CF4 becomes the BASIC execute pointer once the +; block is copied to it's destination, any non zero page address will do at assembly +; time, to assemble a three byte instruction. + +; page 0 initialisation table from $BC +; increment and scan memory + +LAB_2CEE + INC Bpntrl ; increment BASIC execute pointer low byte + BNE LAB_2CF4 ; branch if no carry + ; else + INC Bpntrh ; increment BASIC execute pointer high byte + +; page 0 initialisation table from $C2 +; scan memory + +LAB_2CF4 + LDA $FFFF ; get byte to scan (addr set by call routine) + CMP #TK_ELSE ; compare with the token for ELSE + BEQ LAB_2D05 ; exit if ELSE, not numeric, carry set + + CMP #':' ; compare with ":" + BCS LAB_2D05 ; exit if >= ":", not numeric, carry set + + CMP #' ' ; compare with " " + BEQ LAB_2CEE ; if " " go do next + + SEC ; set carry for SBC + SBC #'0' ; subtract "0" + SEC ; set carry for SBC + SBC #$D0 ; subtract -"0" + ; clear carry if byte = "0"-"9" +LAB_2D05 + RTS + +; page zero initialisation table $00-$12 inclusive + +StrTab + .byte $4C ; JMP opcode + .word LAB_COLD ; initial warm start vector (cold start) + + .byte $00 ; these bytes are not used by BASIC + .word $0000 ; + .word $0000 ; + .word $0000 ; + + .byte $4C ; JMP opcode + .word LAB_FCER ; initial user function vector ("Function call" error) + .byte $00 ; default NULL count + .byte $00 ; clear terminal position + .byte $00 ; default terminal width byte + .byte $F2 ; default limit for TAB = 14 + .word Ram_base ; start of user RAM +EndTab + +LAB_MSZM + .byte $0D,$0A,"Memory size ",$00 + +LAB_SMSG + .byte " Bytes free",$0D,$0A,$0A + .byte "Enhanced BASIC 2.22",$0A,$00 + +; numeric constants and series + + ; constants and series for LOG(n) +LAB_25A0 + .byte $02 ; counter + .byte $80,$19,$56,$62 ; 0.59898 + .byte $80,$76,$22,$F3 ; 0.96147 +;## .byte $80,$76,$22,$F1 ; 0.96147 + .byte $82,$38,$AA,$40 ; 2.88539 +;## .byte $82,$38,$AA,$45 ; 2.88539 + +LAB_25AD + .byte $80,$35,$04,$F3 ; 0.70711 1/root 2 +LAB_25B1 + .byte $81,$35,$04,$F3 ; 1.41421 root 2 +LAB_25B5 + .byte $80,$80,$00,$00 ; -0.5 +LAB_25B9 + .byte $80,$31,$72,$18 ; 0.69315 LOG(2) + + ; numeric PRINT constants +LAB_2947 + .byte $91,$43,$4F,$F8 ; 99999.9375 (max value with at least one decimal) +LAB_294B + .byte $94,$74,$23,$F7 ; 999999.4375 (max value before scientific notation) +LAB_294F + .byte $94,$74,$24,$00 ; 1000000 + + ; EXP(n) constants and series +LAB_2AFA + .byte $81,$38,$AA,$3B ; 1.4427 (1/LOG base 2 e) +LAB_2AFE + .byte $06 ; counter + .byte $74,$63,$90,$8C ; 2.17023e-4 + .byte $77,$23,$0C,$AB ; 0.00124 + .byte $7A,$1E,$94,$00 ; 0.00968 + .byte $7C,$63,$42,$80 ; 0.05548 + .byte $7E,$75,$FE,$D0 ; 0.24023 + .byte $80,$31,$72,$15 ; 0.69315 + .byte $81,$00,$00,$00 ; 1.00000 + +;## .byte $07 ; counter +;## .byte $74,$94,$2E,$40 ; -1/7! (-1/5040) +;## .byte $77,$2E,$4F,$70 ; 1/6! ( 1/720) +;## .byte $7A,$88,$02,$6E ; -1/5! (-1/120) +;## .byte $7C,$2A,$A0,$E6 ; 1/4! ( 1/24) +;## .byte $7E,$AA,$AA,$50 ; -1/3! (-1/6) +;## .byte $7F,$7F,$FF,$FF ; 1/2! ( 1/2) +;## .byte $81,$80,$00,$00 ; -1/1! (-1/1) +;## .byte $81,$00,$00,$00 ; 1/0! ( 1/1) + + ; trigonometric constants and series +LAB_2C78 + .byte $81,$49,$0F,$DB ; 1.570796371 (pi/2) as floating # +LAB_2C84 + .byte $04 ; counter + .byte $86,$1E,$D7,$FB ; 39.7109 +;## .byte $86,$1E,$D7,$BA ; 39.7109 + .byte $87,$99,$26,$65 ;-76.575 +;## .byte $87,$99,$26,$64 ;-76.575 + .byte $87,$23,$34,$58 ; 81.6022 + .byte $86,$A5,$5D,$E1 ;-41.3417 +;## .byte $86,$A5,$5D,$E0 ;-41.3417 +LAB_2C7C + .byte $83,$49,$0F,$DB ; 6.28319 (2*pi) as floating # +;## .byte $83,$49,$0F,$DA ; 6.28319 (2*pi) as floating # + +LAB_2CC9 + .byte $08 ; counter + .byte $78,$3A,$C5,$37 ; 0.00285 + .byte $7B,$83,$A2,$5C ;-0.0160686 + .byte $7C,$2E,$DD,$4D ; 0.0426915 + .byte $7D,$99,$B0,$1E ;-0.0750429 + .byte $7D,$59,$ED,$24 ; 0.106409 + .byte $7E,$91,$72,$00 ;-0.142036 + .byte $7E,$4C,$B9,$73 ; 0.199926 + .byte $7F,$AA,$AA,$53 ;-0.333331 + +;## .byte $08 ; counter +;## .byte $78,$3B,$D7,$4A ; 1/17 +;## .byte $7B,$84,$6E,$02 ;-1/15 +;## .byte $7C,$2F,$C1,$FE ; 1/13 +;## .byte $7D,$9A,$31,$74 ;-1/11 +;## .byte $7D,$5A,$3D,$84 ; 1/9 +;## .byte $7E,$91,$7F,$C8 ;-1/7 +;## .byte $7E,$4C,$BB,$E4 ; 1/5 +;## .byte $7F,$AA,$AA,$6C ;-1/3 + +LAB_1D96 = *+1 ; $00,$00 used for undefined variables +LAB_259C + .byte $81,$00,$00,$00 ; 1.000000, used for INC +LAB_2AFD + .byte $81,$80,$00,$00 ; -1.00000, used for DEC. must be on the same page as +1.00 + + ; misc constants +LAB_1DF7 + .byte $90 ;-32768 (uses first three bytes from 0.5) +LAB_2A96 + .byte $80,$00,$00,$00 ; 0.5 +LAB_2C80 + .byte $7F,$00,$00,$00 ; 0.25 +LAB_26B5 + .byte $84,$20,$00,$00 ; 10.0000 divide by 10 constant + +; This table is used in converting numbers to ASCII. + +LAB_2A9A +LAB_2A9B = LAB_2A9A+1 +LAB_2A9C = LAB_2A9B+1 + .byte $FE,$79,$60 ; -100000 + .byte $00,$27,$10 ; 10000 + .byte $FF,$FC,$18 ; -1000 + .byte $00,$00,$64 ; 100 + .byte $FF,$FF,$F6 ; -10 + .byte $00,$00,$01 ; 1 + +LAB_CTBL + .word LAB_END-1 ; END + .word LAB_FOR-1 ; FOR + .word LAB_NEXT-1 ; NEXT + .word LAB_DATA-1 ; DATA + .word LAB_INPUT-1 ; INPUT + .word LAB_DIM-1 ; DIM + .word LAB_READ-1 ; READ + .word LAB_LET-1 ; LET + .word LAB_DEC-1 ; DEC new command + .word LAB_GOTO-1 ; GOTO + .word LAB_RUN-1 ; RUN + .word LAB_IF-1 ; IF + .word LAB_RESTORE-1 ; RESTORE modified command + .word LAB_GOSUB-1 ; GOSUB + .word LAB_RETIRQ-1 ; RETIRQ new command + .word LAB_RETNMI-1 ; RETNMI new command + .word LAB_RETURN-1 ; RETURN + .word LAB_REM-1 ; REM + .word LAB_STOP-1 ; STOP + .word LAB_ON-1 ; ON modified command + .word LAB_NULL-1 ; NULL modified command + .word LAB_INC-1 ; INC new command + .word LAB_WAIT-1 ; WAIT + .word V_LOAD-1 ; LOAD + .word V_SAVE-1 ; SAVE + .word LAB_DEF-1 ; DEF + .word LAB_POKE-1 ; POKE + .word LAB_DOKE-1 ; DOKE new command + .word LAB_CALL-1 ; CALL new command + .word LAB_DO-1 ; DO new command + .word LAB_LOOP-1 ; LOOP new command + .word LAB_PRINT-1 ; PRINT + .word LAB_CONT-1 ; CONT + .word LAB_LIST-1 ; LIST + .word LAB_CLEAR-1 ; CLEAR + .word LAB_NEW-1 ; NEW + .word LAB_WDTH-1 ; WIDTH new command + .word LAB_GET-1 ; GET new command + .word LAB_SWAP-1 ; SWAP new command + .word LAB_BITSET-1 ; BITSET new command + .word LAB_BITCLR-1 ; BITCLR new command + .word LAB_IRQ-1 ; IRQ new command + .word LAB_NMI-1 ; NMI new command + +; function pre process routine table + +LAB_FTPL +LAB_FTPM = LAB_FTPL+$01 + .word LAB_PPFN-1 ; SGN(n) process numeric expression in () + .word LAB_PPFN-1 ; INT(n) " + .word LAB_PPFN-1 ; ABS(n) " + .word LAB_EVEZ-1 ; USR(x) process any expression + .word LAB_1BF7-1 ; FRE(x) " + .word LAB_1BF7-1 ; POS(x) " + .word LAB_PPFN-1 ; SQR(n) process numeric expression in () + .word LAB_PPFN-1 ; RND(n) " + .word LAB_PPFN-1 ; LOG(n) " + .word LAB_PPFN-1 ; EXP(n) " + .word LAB_PPFN-1 ; COS(n) " + .word LAB_PPFN-1 ; SIN(n) " + .word LAB_PPFN-1 ; TAN(n) " + .word LAB_PPFN-1 ; ATN(n) " + .word LAB_PPFN-1 ; PEEK(n) " + .word LAB_PPFN-1 ; DEEK(n) " + .word $0000 ; SADD() none + .word LAB_PPFS-1 ; LEN($) process string expression in () + .word LAB_PPFN-1 ; STR$(n) process numeric expression in () + .word LAB_PPFS-1 ; VAL($) process string expression in () + .word LAB_PPFS-1 ; ASC($) " + .word LAB_PPFS-1 ; UCASE$($) " + .word LAB_PPFS-1 ; LCASE$($) " + .word LAB_PPFN-1 ; CHR$(n) process numeric expression in () + .word LAB_BHSS-1 ; HEX$(n) " + .word LAB_BHSS-1 ; BIN$(n) " + .word $0000 ; BITTST() none + .word LAB_MMPP-1 ; MAX() process numeric expression + .word LAB_MMPP-1 ; MIN() " + .word LAB_PPBI-1 ; PI advance pointer + .word LAB_PPBI-1 ; TWOPI " + .word $0000 ; VARPTR() none + .word LAB_LRMS-1 ; LEFT$() process string expression + .word LAB_LRMS-1 ; RIGHT$() " + .word LAB_LRMS-1 ; MID$() " + +; action addresses for functions + +LAB_FTBL +LAB_FTBM = LAB_FTBL+$01 + .word LAB_SGN-1 ; SGN() + .word LAB_INT-1 ; INT() + .word LAB_ABS-1 ; ABS() + .word LAB_USR-1 ; USR() + .word LAB_FRE-1 ; FRE() + .word LAB_POS-1 ; POS() + .word LAB_SQR-1 ; SQR() + .word LAB_RND-1 ; RND() modified function + .word LAB_LOG-1 ; LOG() + .word LAB_EXP-1 ; EXP() + .word LAB_COS-1 ; COS() + .word LAB_SIN-1 ; SIN() + .word LAB_TAN-1 ; TAN() + .word LAB_ATN-1 ; ATN() + .word LAB_PEEK-1 ; PEEK() + .word LAB_DEEK-1 ; DEEK() new function + .word LAB_SADD-1 ; SADD() new function + .word LAB_LENS-1 ; LEN() + .word LAB_STRS-1 ; STR$() + .word LAB_VAL-1 ; VAL() + .word LAB_ASC-1 ; ASC() + .word LAB_UCASE-1 ; UCASE$() new function + .word LAB_LCASE-1 ; LCASE$() new function + .word LAB_CHRS-1 ; CHR$() + .word LAB_HEXS-1 ; HEX$() new function + .word LAB_BINS-1 ; BIN$() new function + .word LAB_BTST-1 ; BITTST() new function + .word LAB_MAX-1 ; MAX() new function + .word LAB_MIN-1 ; MIN() new function + .word LAB_PI-1 ; PI new function + .word LAB_TWOPI-1 ; TWOPI new function + .word LAB_VARPTR-1 ; VARPTR() new function + .word LAB_LEFT-1 ; LEFT$() + .word LAB_RIGHT-1 ; RIGHT$() + .word LAB_MIDS-1 ; MID$() + +; hierarchy and action addresses for operator + +LAB_OPPT + .byte $79 ; + + .word LAB_ADD-1 + .byte $79 ; - + .word LAB_SUBTRACT-1 + .byte $7B ; * + .word LAB_MULTIPLY-1 + .byte $7B ; / + .word LAB_DIVIDE-1 + .byte $7F ; ^ + .word LAB_POWER-1 + .byte $50 ; AND + .word LAB_AND-1 + .byte $46 ; EOR new operator + .word LAB_EOR-1 + .byte $46 ; OR + .word LAB_OR-1 + .byte $56 ; >> new operator + .word LAB_RSHIFT-1 + .byte $56 ; << new operator + .word LAB_LSHIFT-1 + .byte $7D ; > + .word LAB_GTHAN-1 + .byte $5A ; = + .word LAB_EQUAL-1 + .byte $64 ; < + .word LAB_LTHAN-1 + +; keywords start with .. +; this is the first character table and must be in alphabetic order + +TAB_1STC + .byte "*" + .byte "+" + .byte "-" + .byte "/" + .byte "<" + .byte "=" + .byte ">" + .byte "?" + .byte "A" + .byte "B" + .byte "C" + .byte "D" + .byte "E" + .byte "F" + .byte "G" + .byte "H" + .byte "I" + .byte "L" + .byte "M" + .byte "N" + .byte "O" + .byte "P" + .byte "R" + .byte "S" + .byte "T" + .byte "U" + .byte "V" + .byte "W" + .byte "^" + .byte $00 ; table terminator + +; pointers to keyword tables + +TAB_CHRT + .word TAB_STAR ; table for "*" + .word TAB_PLUS ; table for "+" + .word TAB_MNUS ; table for "-" + .word TAB_SLAS ; table for "/" + .word TAB_LESS ; table for "<" + .word TAB_EQUL ; table for "=" + .word TAB_MORE ; table for ">" + .word TAB_QEST ; table for "?" + .word TAB_ASCA ; table for "A" + .word TAB_ASCB ; table for "B" + .word TAB_ASCC ; table for "C" + .word TAB_ASCD ; table for "D" + .word TAB_ASCE ; table for "E" + .word TAB_ASCF ; table for "F" + .word TAB_ASCG ; table for "G" + .word TAB_ASCH ; table for "H" + .word TAB_ASCI ; table for "I" + .word TAB_ASCL ; table for "L" + .word TAB_ASCM ; table for "M" + .word TAB_ASCN ; table for "N" + .word TAB_ASCO ; table for "O" + .word TAB_ASCP ; table for "P" + .word TAB_ASCR ; table for "R" + .word TAB_ASCS ; table for "S" + .word TAB_ASCT ; table for "T" + .word TAB_ASCU ; table for "U" + .word TAB_ASCV ; table for "V" + .word TAB_ASCW ; table for "W" + .word TAB_POWR ; table for "^" + +; tables for each start character, note if a longer keyword with the same start +; letters as a shorter one exists then it must come first, else the list is in +; alphabetical order as follows .. + +; [keyword,token +; [keyword,token]] +; end marker (#$00) + +TAB_STAR + .byte TK_MUL,$00 ; * +TAB_PLUS + .byte TK_PLUS,$00 ; + +TAB_MNUS + .byte TK_MINUS,$00 ; - +TAB_SLAS + .byte TK_DIV,$00 ; / +TAB_LESS +LBB_LSHIFT + .byte "<",TK_LSHIFT ; << note - "<<" must come before "<" + .byte TK_LT ; < + .byte $00 +TAB_EQUL + .byte TK_EQUAL,$00 ; = +TAB_MORE +LBB_RSHIFT + .byte ">",TK_RSHIFT ; >> note - ">>" must come before ">" + .byte TK_GT ; > + .byte $00 +TAB_QEST + .byte TK_PRINT,$00 ; ? +TAB_ASCA +LBB_ABS + .byte "BS(",TK_ABS ; ABS( +LBB_AND + .byte "ND",TK_AND ; AND +LBB_ASC + .byte "SC(",TK_ASC ; ASC( +LBB_ATN + .byte "TN(",TK_ATN ; ATN( + .byte $00 +TAB_ASCB +LBB_BINS + .byte "IN$(",TK_BINS ; BIN$( +LBB_BITCLR + .byte "ITCLR",TK_BITCLR ; BITCLR +LBB_BITSET + .byte "ITSET",TK_BITSET ; BITSET +LBB_BITTST + .byte "ITTST(",TK_BITTST + ; BITTST( + .byte $00 +TAB_ASCC +LBB_CALL + .byte "ALL",TK_CALL ; CALL +LBB_CHRS + .byte "HR$(",TK_CHRS ; CHR$( +LBB_CLEAR + .byte "LEAR",TK_CLEAR ; CLEAR +LBB_CONT + .byte "ONT",TK_CONT ; CONT +LBB_COS + .byte "OS(",TK_COS ; COS( + .byte $00 +TAB_ASCD +LBB_DATA + .byte "ATA",TK_DATA ; DATA +LBB_DEC + .byte "EC",TK_DEC ; DEC +LBB_DEEK + .byte "EEK(",TK_DEEK ; DEEK( +LBB_DEF + .byte "EF",TK_DEF ; DEF +LBB_DIM + .byte "IM",TK_DIM ; DIM +LBB_DOKE + .byte "OKE",TK_DOKE ; DOKE note - "DOKE" must come before "DO" +LBB_DO + .byte "O",TK_DO ; DO + .byte $00 +TAB_ASCE +LBB_ELSE + .byte "LSE",TK_ELSE ; ELSE +LBB_END + .byte "ND",TK_END ; END +LBB_EOR + .byte "OR",TK_EOR ; EOR +LBB_EXP + .byte "XP(",TK_EXP ; EXP( + .byte $00 +TAB_ASCF +LBB_FN + .byte "N",TK_FN ; FN +LBB_FOR + .byte "OR",TK_FOR ; FOR +LBB_FRE + .byte "RE(",TK_FRE ; FRE( + .byte $00 +TAB_ASCG +LBB_GET + .byte "ET",TK_GET ; GET +LBB_GOSUB + .byte "OSUB",TK_GOSUB ; GOSUB +LBB_GOTO + .byte "OTO",TK_GOTO ; GOTO + .byte $00 +TAB_ASCH +LBB_HEXS + .byte "EX$(",TK_HEXS ; HEX$( + .byte $00 +TAB_ASCI +LBB_IF + .byte "F",TK_IF ; IF +LBB_INC + .byte "NC",TK_INC ; INC +LBB_INPUT + .byte "NPUT",TK_INPUT ; INPUT +LBB_INT + .byte "NT(",TK_INT ; INT( +LBB_IRQ + .byte "RQ",TK_IRQ ; IRQ + .byte $00 +TAB_ASCL +LBB_LCASES + .byte "CASE$(",TK_LCASES + ; LCASE$( +LBB_LEFTS + .byte "EFT$(",TK_LEFTS ; LEFT$( +LBB_LEN + .byte "EN(",TK_LEN ; LEN( +LBB_LET + .byte "ET",TK_LET ; LET +LBB_LIST + .byte "IST",TK_LIST ; LIST +LBB_LOAD + .byte "OAD",TK_LOAD ; LOAD +LBB_LOG + .byte "OG(",TK_LOG ; LOG( +LBB_LOOP + .byte "OOP",TK_LOOP ; LOOP + .byte $00 +TAB_ASCM +LBB_MAX + .byte "AX(",TK_MAX ; MAX( +LBB_MIDS + .byte "ID$(",TK_MIDS ; MID$( +LBB_MIN + .byte "IN(",TK_MIN ; MIN( + .byte $00 +TAB_ASCN +LBB_NEW + .byte "EW",TK_NEW ; NEW +LBB_NEXT + .byte "EXT",TK_NEXT ; NEXT +LBB_NMI + .byte "MI",TK_NMI ; NMI +LBB_NOT + .byte "OT",TK_NOT ; NOT +LBB_NULL + .byte "ULL",TK_NULL ; NULL + .byte $00 +TAB_ASCO +LBB_OFF + .byte "FF",TK_OFF ; OFF +LBB_ON + .byte "N",TK_ON ; ON +LBB_OR + .byte "R",TK_OR ; OR + .byte $00 +TAB_ASCP +LBB_PEEK + .byte "EEK(",TK_PEEK ; PEEK( +LBB_PI + .byte "I",TK_PI ; PI +LBB_POKE + .byte "OKE",TK_POKE ; POKE +LBB_POS + .byte "OS(",TK_POS ; POS( +LBB_PRINT + .byte "RINT",TK_PRINT ; PRINT + .byte $00 +TAB_ASCR +LBB_READ + .byte "EAD",TK_READ ; READ +LBB_REM + .byte "EM",TK_REM ; REM +LBB_RESTORE + .byte "ESTORE",TK_RESTORE + ; RESTORE +LBB_RETIRQ + .byte "ETIRQ",TK_RETIRQ ; RETIRQ +LBB_RETNMI + .byte "ETNMI",TK_RETNMI ; RETNMI +LBB_RETURN + .byte "ETURN",TK_RETURN ; RETURN +LBB_RIGHTS + .byte "IGHT$(",TK_RIGHTS + ; RIGHT$( +LBB_RND + .byte "ND(",TK_RND ; RND( +LBB_RUN + .byte "UN",TK_RUN ; RUN + .byte $00 +TAB_ASCS +LBB_SADD + .byte "ADD(",TK_SADD ; SADD( +LBB_SAVE + .byte "AVE",TK_SAVE ; SAVE +LBB_SGN + .byte "GN(",TK_SGN ; SGN( +LBB_SIN + .byte "IN(",TK_SIN ; SIN( +LBB_SPC + .byte "PC(",TK_SPC ; SPC( +LBB_SQR + .byte "QR(",TK_SQR ; SQR( +LBB_STEP + .byte "TEP",TK_STEP ; STEP +LBB_STOP + .byte "TOP",TK_STOP ; STOP +LBB_STRS + .byte "TR$(",TK_STRS ; STR$( +LBB_SWAP + .byte "WAP",TK_SWAP ; SWAP + .byte $00 +TAB_ASCT +LBB_TAB + .byte "AB(",TK_TAB ; TAB( +LBB_TAN + .byte "AN(",TK_TAN ; TAN( +LBB_THEN + .byte "HEN",TK_THEN ; THEN +LBB_TO + .byte "O",TK_TO ; TO +LBB_TWOPI + .byte "WOPI",TK_TWOPI ; TWOPI + .byte $00 +TAB_ASCU +LBB_UCASES + .byte "CASE$(",TK_UCASES + ; UCASE$( +LBB_UNTIL + .byte "NTIL",TK_UNTIL ; UNTIL +LBB_USR + .byte "SR(",TK_USR ; USR( + .byte $00 +TAB_ASCV +LBB_VAL + .byte "AL(",TK_VAL ; VAL( +LBB_VPTR + .byte "ARPTR(",TK_VPTR ; VARPTR( + .byte $00 +TAB_ASCW +LBB_WAIT + .byte "AIT",TK_WAIT ; WAIT +LBB_WHILE + .byte "HILE",TK_WHILE ; WHILE +LBB_WIDTH + .byte "IDTH",TK_WIDTH ; WIDTH + .byte $00 +TAB_POWR + .byte TK_POWER,$00 ; ^ + +; new decode table for LIST +; Table is .. +; byte - keyword length, keyword first character +; word - pointer to rest of keyword from dictionary + +; note if length is 1 then the pointer is ignored + +LAB_KEYT + .byte 3,'E' + .word LBB_END ; END + .byte 3,'F' + .word LBB_FOR ; FOR + .byte 4,'N' + .word LBB_NEXT ; NEXT + .byte 4,'D' + .word LBB_DATA ; DATA + .byte 5,'I' + .word LBB_INPUT ; INPUT + .byte 3,'D' + .word LBB_DIM ; DIM + .byte 4,'R' + .word LBB_READ ; READ + .byte 3,'L' + .word LBB_LET ; LET + .byte 3,'D' + .word LBB_DEC ; DEC + .byte 4,'G' + .word LBB_GOTO ; GOTO + .byte 3,'R' + .word LBB_RUN ; RUN + .byte 2,'I' + .word LBB_IF ; IF + .byte 7,'R' + .word LBB_RESTORE ; RESTORE + .byte 5,'G' + .word LBB_GOSUB ; GOSUB + .byte 6,'R' + .word LBB_RETIRQ ; RETIRQ + .byte 6,'R' + .word LBB_RETNMI ; RETNMI + .byte 6,'R' + .word LBB_RETURN ; RETURN + .byte 3,'R' + .word LBB_REM ; REM + .byte 4,'S' + .word LBB_STOP ; STOP + .byte 2,'O' + .word LBB_ON ; ON + .byte 4,'N' + .word LBB_NULL ; NULL + .byte 3,'I' + .word LBB_INC ; INC + .byte 4,'W' + .word LBB_WAIT ; WAIT + .byte 4,'L' + .word LBB_LOAD ; LOAD + .byte 4,'S' + .word LBB_SAVE ; SAVE + .byte 3,'D' + .word LBB_DEF ; DEF + .byte 4,'P' + .word LBB_POKE ; POKE + .byte 4,'D' + .word LBB_DOKE ; DOKE + .byte 4,'C' + .word LBB_CALL ; CALL + .byte 2,'D' + .word LBB_DO ; DO + .byte 4,'L' + .word LBB_LOOP ; LOOP + .byte 5,'P' + .word LBB_PRINT ; PRINT + .byte 4,'C' + .word LBB_CONT ; CONT + .byte 4,'L' + .word LBB_LIST ; LIST + .byte 5,'C' + .word LBB_CLEAR ; CLEAR + .byte 3,'N' + .word LBB_NEW ; NEW + .byte 5,'W' + .word LBB_WIDTH ; WIDTH + .byte 3,'G' + .word LBB_GET ; GET + .byte 4,'S' + .word LBB_SWAP ; SWAP + .byte 6,'B' + .word LBB_BITSET ; BITSET + .byte 6,'B' + .word LBB_BITCLR ; BITCLR + .byte 3,'I' + .word LBB_IRQ ; IRQ + .byte 3,'N' + .word LBB_NMI ; NMI + +; secondary commands (can't start a statement) + + .byte 4,'T' + .word LBB_TAB ; TAB + .byte 4,'E' + .word LBB_ELSE ; ELSE + .byte 2,'T' + .word LBB_TO ; TO + .byte 2,'F' + .word LBB_FN ; FN + .byte 4,'S' + .word LBB_SPC ; SPC + .byte 4,'T' + .word LBB_THEN ; THEN + .byte 3,'N' + .word LBB_NOT ; NOT + .byte 4,'S' + .word LBB_STEP ; STEP + .byte 5,'U' + .word LBB_UNTIL ; UNTIL + .byte 5,'W' + .word LBB_WHILE ; WHILE + .byte 3,'O' + .word LBB_OFF ; OFF + +; opperators + + .byte 1,'+' + .word $0000 ; + + .byte 1,'-' + .word $0000 ; - + .byte 1,'*' + .word $0000 ; * + .byte 1,'/' + .word $0000 ; / + .byte 1,'^' + .word $0000 ; ^ + .byte 3,'A' + .word LBB_AND ; AND + .byte 3,'E' + .word LBB_EOR ; EOR + .byte 2,'O' + .word LBB_OR ; OR + .byte 2,'>' + .word LBB_RSHIFT ; >> + .byte 2,'<' + .word LBB_LSHIFT ; << + .byte 1,'>' + .word $0000 ; > + .byte 1,'=' + .word $0000 ; = + .byte 1,'<' + .word $0000 ; < + +; functions + + .byte 4,'S' ; + .word LBB_SGN ; SGN + .byte 4,'I' ; + .word LBB_INT ; INT + .byte 4,'A' ; + .word LBB_ABS ; ABS + .byte 4,'U' ; + .word LBB_USR ; USR + .byte 4,'F' ; + .word LBB_FRE ; FRE + .byte 4,'P' ; + .word LBB_POS ; POS + .byte 4,'S' ; + .word LBB_SQR ; SQR + .byte 4,'R' ; + .word LBB_RND ; RND + .byte 4,'L' ; + .word LBB_LOG ; LOG + .byte 4,'E' ; + .word LBB_EXP ; EXP + .byte 4,'C' ; + .word LBB_COS ; COS + .byte 4,'S' ; + .word LBB_SIN ; SIN + .byte 4,'T' ; + .word LBB_TAN ; TAN + .byte 4,'A' ; + .word LBB_ATN ; ATN + .byte 5,'P' ; + .word LBB_PEEK ; PEEK + .byte 5,'D' ; + .word LBB_DEEK ; DEEK + .byte 5,'S' ; + .word LBB_SADD ; SADD + .byte 4,'L' ; + .word LBB_LEN ; LEN + .byte 5,'S' ; + .word LBB_STRS ; STR$ + .byte 4,'V' ; + .word LBB_VAL ; VAL + .byte 4,'A' ; + .word LBB_ASC ; ASC + .byte 7,'U' ; + .word LBB_UCASES ; UCASE$ + .byte 7,'L' ; + .word LBB_LCASES ; LCASE$ + .byte 5,'C' ; + .word LBB_CHRS ; CHR$ + .byte 5,'H' ; + .word LBB_HEXS ; HEX$ + .byte 5,'B' ; + .word LBB_BINS ; BIN$ + .byte 7,'B' ; + .word LBB_BITTST ; BITTST + .byte 4,'M' ; + .word LBB_MAX ; MAX + .byte 4,'M' ; + .word LBB_MIN ; MIN + .byte 2,'P' ; + .word LBB_PI ; PI + .byte 5,'T' ; + .word LBB_TWOPI ; TWOPI + .byte 7,'V' ; + .word LBB_VPTR ; VARPTR + .byte 6,'L' ; + .word LBB_LEFTS ; LEFT$ + .byte 7,'R' ; + .word LBB_RIGHTS ; RIGHT$ + .byte 5,'M' ; + .word LBB_MIDS ; MID$ + +; BASIC messages, mostly error messages + +LAB_BAER + .word ERR_NF ;$00 NEXT without FOR + .word ERR_SN ;$02 syntax + .word ERR_RG ;$04 RETURN without GOSUB + .word ERR_OD ;$06 out of data + .word ERR_FC ;$08 function call + .word ERR_OV ;$0A overflow + .word ERR_OM ;$0C out of memory + .word ERR_US ;$0E undefined statement + .word ERR_BS ;$10 array bounds + .word ERR_DD ;$12 double dimension array + .word ERR_D0 ;$14 divide by 0 + .word ERR_ID ;$16 illegal direct + .word ERR_TM ;$18 type mismatch + .word ERR_LS ;$1A long string + .word ERR_ST ;$1C string too complex + .word ERR_CN ;$1E continue error + .word ERR_UF ;$20 undefined function + .word ERR_LD ;$22 LOOP without DO + +; I may implement these two errors to force definition of variables and +; dimensioning of arrays before use. + +; .word ERR_UV ;$24 undefined variable + +; the above error has been tested and works (see code and comments below LAB_1D8B) + +; .word ERR_UA ;$26 undimensioned array + +ERR_NF .byte "NEXT without FOR",$00 +ERR_SN .byte "Syntax",$00 +ERR_RG .byte "RETURN without GOSUB",$00 +ERR_OD .byte "Out of DATA",$00 +ERR_FC .byte "Function call",$00 +ERR_OV .byte "Overflow",$00 +ERR_OM .byte "Out of memory",$00 +ERR_US .byte "Undefined statement",$00 +ERR_BS .byte "Array bounds",$00 +ERR_DD .byte "Double dimension",$00 +ERR_D0 .byte "Divide by zero",$00 +ERR_ID .byte "Illegal direct",$00 +ERR_TM .byte "Type mismatch",$00 +ERR_LS .byte "String too long",$00 +ERR_ST .byte "String too complex",$00 +ERR_CN .byte "Can't continue",$00 +ERR_UF .byte "Undefined function",$00 +ERR_LD .byte "LOOP without DO",$00 + +;ERR_UV .byte "Undefined variable",$00 + +; the above error has been tested and works (see code and comments below LAB_1D8B) + +;ERR_UA .byte "Undimensioned array",$00 + +LAB_BMSG .byte $0D,$0A,"Break",$00 +LAB_EMSG .byte " Error",$00 +LAB_LMSG .byte " in line ",$00 +LAB_RMSG .byte $0D,$0A,"Ready",$0D,$0A,$00 + +LAB_IMSG .byte " Extra ignored",$0D,$0A,$00 +LAB_REDO .byte " Redo from start",$0D,$0A,$00 + +AA_end_basic diff --git a/eh_basic_mk.asm b/eh_basic_mk.asm new file mode 100644 index 0000000..690d161 --- /dev/null +++ b/eh_basic_mk.asm @@ -0,0 +1,8733 @@ +; The code below was copied and adapted from Lee Davison’s +; code of EhBasic to be ran in MKBASIC (VM65) 6502 emulator. +; Original comments and credits follow: +; +; Enhanced BASIC to assemble under 6502 simulator, $ver 2.22 + +; $E7E1 $E7CF $E7C6 $E7D3 $E7D1 $E7D5 $E7CF $E81E $E825 + +; 2.00 new revision numbers start here +; 2.01 fixed LCASE$() and UCASE$() +; 2.02 new get value routine done +; 2.03 changed RND() to galoise method +; 2.04 fixed SPC() +; 2.05 new get value routine fixed +; 2.06 changed USR() code +; 2.07 fixed STR$() +; 2.08 changed INPUT and READ to remove need for $00 start to input buffer +; 2.09 fixed RND() +; 2.10 integrated missed changes from an earlier version +; 2.20 added ELSE to IF .. THEN and fixed IF .. GOTO to cause error +; 2.21 fixed IF .. THEN RETURN to not cause error +; 2.22 fixed RND() breaking the get byte routine + +;---------------------------------------------------------------------------- +; to assemble run Kowalski's 6502 emulator, assemble code and save as binary +; with no header (65b), from $C000 to $FFFF. +; Then for VM65 emulator, perform conversion to memory image definition: +; bin2hex -f ehbas.65b -o ehbas_xx.dat -w 49152 -x 49152 +; Add IO address and enable IO in DAT configuration part. +; This version has RAM top at $B000-1, so the area from $B000 to $BFFF can +; be used for binary code or data (e.g.: character ROM). +;---------------------------------------------------------------------------- + +; zero page use .. + +LAB_WARM = $00 ; BASIC warm start entry point +Wrmjpl = LAB_WARM+1; BASIC warm start vector jump low byte +Wrmjph = LAB_WARM+2; BASIC warm start vector jump high byte + +Usrjmp = $0A ; USR function JMP address +Usrjpl = Usrjmp+1 ; USR function JMP vector low byte +Usrjph = Usrjmp+2 ; USR function JMP vector high byte +Nullct = $0D ; nulls output after each line +TPos = $0E ; BASIC terminal position byte +TWidth = $0F ; BASIC terminal width byte +Iclim = $10 ; input column limit +Itempl = $11 ; temporary integer low byte +Itemph = Itempl+1 ; temporary integer high byte + +nums_1 = Itempl ; number to bin/hex string convert MSB +nums_2 = nums_1+1 ; number to bin/hex string convert +nums_3 = nums_1+2 ; number to bin/hex string convert LSB + +Srchc = $5B ; search character +Temp3 = Srchc ; temp byte used in number routines +Scnquo = $5C ; scan-between-quotes flag +Asrch = Scnquo ; alt search character + +XOAw_l = Srchc ; eXclusive OR, OR and AND word low byte +XOAw_h = Scnquo ; eXclusive OR, OR and AND word high byte + +Ibptr = $5D ; input buffer pointer +Dimcnt = Ibptr ; # of dimensions +Tindx = Ibptr ; token index + +Defdim = $5E ; default DIM flag +Dtypef = $5F ; data type flag, $FF=string, $00=numeric +Oquote = $60 ; open quote flag (b7) (Flag: DATA scan; LIST quote; memory) +Gclctd = $60 ; garbage collected flag +Sufnxf = $61 ; subscript/FNX flag, 1xxx xxx = FN(0xxx xxx) +Imode = $62 ; input mode flag, $00=INPUT, $80=READ + +Cflag = $63 ; comparison evaluation flag + +TabSiz = $64 ; TAB step size (was input flag) + +next_s = $65 ; next descriptor stack address + + ; these two bytes form a word pointer to the item + ; currently on top of the descriptor stack +last_sl = $66 ; last descriptor stack address low byte +last_sh = $67 ; last descriptor stack address high byte (always $00) + +des_sk = $68 ; descriptor stack start address (temp strings) + +; = $70 ; End of descriptor stack + +ut1_pl = $71 ; utility pointer 1 low byte +ut1_ph = ut1_pl+1 ; utility pointer 1 high byte +ut2_pl = $73 ; utility pointer 2 low byte +ut2_ph = ut2_pl+1 ; utility pointer 2 high byte + +Temp_2 = ut1_pl ; temp byte for block move + +FACt_1 = $75 ; FAC temp mantissa1 +FACt_2 = FACt_1+1 ; FAC temp mantissa2 +FACt_3 = FACt_2+1 ; FAC temp mantissa3 + +dims_l = FACt_2 ; array dimension size low byte +dims_h = FACt_3 ; array dimension size high byte + +TempB = $78 ; temp page 0 byte + +Smeml = $79 ; start of mem low byte (Start-of-Basic) +Smemh = Smeml+1 ; start of mem high byte (Start-of-Basic) +Svarl = $7B ; start of vars low byte (Start-of-Variables) +Svarh = Svarl+1 ; start of vars high byte (Start-of-Variables) +Sarryl = $7D ; var mem end low byte (Start-of-Arrays) +Sarryh = Sarryl+1 ; var mem end high byte (Start-of-Arrays) +Earryl = $7F ; array mem end low byte (End-of-Arrays) +Earryh = Earryl+1 ; array mem end high byte (End-of-Arrays) +Sstorl = $81 ; string storage low byte (String storage (moving down)) +Sstorh = Sstorl+1 ; string storage high byte (String storage (moving down)) +Sutill = $83 ; string utility ptr low byte +Sutilh = Sutill+1 ; string utility ptr high byte +Ememl = $85 ; end of mem low byte (Limit-of-memory) +Ememh = Ememl+1 ; end of mem high byte (Limit-of-memory) +Clinel = $87 ; current line low byte (Basic line number) +Clineh = Clinel+1 ; current line high byte (Basic line number) +Blinel = $89 ; break line low byte (Previous Basic line number) +Blineh = Blinel+1 ; break line high byte (Previous Basic line number) + +Cpntrl = $8B ; continue pointer low byte +Cpntrh = Cpntrl+1 ; continue pointer high byte + +Dlinel = $8D ; current DATA line low byte +Dlineh = Dlinel+1 ; current DATA line high byte + +Dptrl = $8F ; DATA pointer low byte +Dptrh = Dptrl+1 ; DATA pointer high byte + +Rdptrl = $91 ; read pointer low byte +Rdptrh = Rdptrl+1 ; read pointer high byte + +Varnm1 = $93 ; current var name 1st byte +Varnm2 = Varnm1+1 ; current var name 2nd byte + +Cvaral = $95 ; current var address low byte +Cvarah = Cvaral+1 ; current var address high byte + +Frnxtl = $97 ; var pointer for FOR/NEXT low byte +Frnxth = Frnxtl+1 ; var pointer for FOR/NEXT high byte + +Tidx1 = Frnxtl ; temp line index + +Lvarpl = Frnxtl ; let var pointer low byte +Lvarph = Frnxth ; let var pointer high byte + +prstk = $99 ; precedence stacked flag + +comp_f = $9B ; compare function flag, bits 0,1 and 2 used + ; bit 2 set if > + ; bit 1 set if = + ; bit 0 set if < + +func_l = $9C ; function pointer low byte +func_h = func_l+1 ; function pointer high byte + +garb_l = func_l ; garbage collection working pointer low byte +garb_h = func_h ; garbage collection working pointer high byte + +des_2l = $9E ; string descriptor_2 pointer low byte +des_2h = des_2l+1 ; string descriptor_2 pointer high byte + +g_step = $A0 ; garbage collect step size + +Fnxjmp = $A1 ; jump vector for functions +Fnxjpl = Fnxjmp+1 ; functions jump vector low byte +Fnxjph = Fnxjmp+2 ; functions jump vector high byte + +g_indx = Fnxjpl ; garbage collect temp index + +FAC2_r = $A3 ; FAC2 rounding byte + +Adatal = $A4 ; array data pointer low byte +Adatah = Adatal+1 ; array data pointer high byte + +Nbendl = Adatal ; new block end pointer low byte +Nbendh = Adatah ; new block end pointer high byte + +Obendl = $A6 ; old block end pointer low byte +Obendh = Obendl+1 ; old block end pointer high byte + +numexp = $A8 ; string to float number exponent count +expcnt = $A9 ; string to float exponent count + +numbit = numexp ; bit count for array element calculations + +numdpf = $AA ; string to float decimal point flag +expneg = $AB ; string to float eval exponent -ve flag + +Astrtl = numdpf ; array start pointer low byte +Astrth = expneg ; array start pointer high byte + +Histrl = numdpf ; highest string low byte +Histrh = expneg ; highest string high byte + +Baslnl = numdpf ; BASIC search line pointer low byte +Baslnh = expneg ; BASIC search line pointer high byte + +Fvar_l = numdpf ; find/found variable pointer low byte +Fvar_h = expneg ; find/found variable pointer high byte + +Ostrtl = numdpf ; old block start pointer low byte +Ostrth = expneg ; old block start pointer high byte + +Vrschl = numdpf ; variable search pointer low byte +Vrschh = expneg ; variable search pointer high byte + +FAC1_e = $AC ; FAC1 exponent +FAC1_1 = FAC1_e+1 ; FAC1 mantissa1 +FAC1_2 = FAC1_e+2 ; FAC1 mantissa2 +FAC1_3 = FAC1_e+3 ; FAC1 mantissa3 +FAC1_s = FAC1_e+4 ; FAC1 sign (b7) + +str_ln = FAC1_e ; string length +str_pl = FAC1_1 ; string pointer low byte +str_ph = FAC1_2 ; string pointer high byte + +des_pl = FAC1_2 ; string descriptor pointer low byte +des_ph = FAC1_3 ; string descriptor pointer high byte + +mids_l = FAC1_3 ; MID$ string temp length byte + +negnum = $B1 ; string to float eval -ve flag +numcon = $B1 ; series evaluation constant count + +FAC1_o = $B2 ; FAC1 overflow byte + +FAC2_e = $B3 ; FAC2 exponent +FAC2_1 = FAC2_e+1 ; FAC2 mantissa1 +FAC2_2 = FAC2_e+2 ; FAC2 mantissa2 +FAC2_3 = FAC2_e+3 ; FAC2 mantissa3 +FAC2_s = FAC2_e+4 ; FAC2 sign (b7) + +FAC_sc = $B8 ; FAC sign comparison, Acc#1 vs #2 +FAC1_r = $B9 ; FAC1 rounding byte + +ssptr_l = FAC_sc ; string start pointer low byte +ssptr_h = FAC1_r ; string start pointer high byte + +sdescr = FAC_sc ; string descriptor pointer + +csidx = $BA ; line crunch save index +Asptl = csidx ; array size/pointer low byte +Aspth = $BB ; array size/pointer high byte + +Btmpl = Asptl ; BASIC pointer temp low byte +Btmph = Aspth ; BASIC pointer temp low byte + +Cptrl = Asptl ; BASIC pointer temp low byte +Cptrh = Aspth ; BASIC pointer temp low byte + +Sendl = Asptl ; BASIC pointer temp low byte +Sendh = Aspth ; BASIC pointer temp low byte + +LAB_IGBY = $BC ; get next BASIC byte subroutine + +LAB_GBYT = $C2 ; get current BASIC byte subroutine +Bpntrl = $C3 ; BASIC execute (get byte) pointer low byte +Bpntrh = Bpntrl+1 ; BASIC execute (get byte) pointer high byte + +; = $D7 ; end of get BASIC char subroutine + +Rbyte4 = $D8 ; extra PRNG byte +Rbyte1 = Rbyte4+1 ; most significant PRNG byte +Rbyte2 = Rbyte4+2 ; middle PRNG byte +Rbyte3 = Rbyte4+3 ; least significant PRNG byte + +NmiBase = $DC ; NMI handler enabled/setup/triggered flags + ; bit function + ; === ======== + ; 7 interrupt enabled + ; 6 interrupt setup + ; 5 interrupt happened +; = $DD ; NMI handler addr low byte +; = $DE ; NMI handler addr high byte +IrqBase = $DF ; IRQ handler enabled/setup/triggered flags +; = $E0 ; IRQ handler addr low byte +; = $E1 ; IRQ handler addr high byte + +; = $DE ; unused +; = $DF ; unused +; = $E0 ; unused +; = $E1 ; unused +; = $E2 ; unused +; = $E3 ; unused +; = $E4 ; unused +; = $E5 ; unused +; = $E6 ; unused +; = $E7 ; unused +; = $E8 ; unused +; = $E9 ; unused +; = $EA ; unused +; = $EB ; unused +; = $EC ; unused +; = $ED ; unused +; = $EE ; unused + +Decss = $EF ; number to decimal string start +Decssp1 = Decss+1 ; number to decimal string start + +; = $FF ; decimal string end + +; token values needed for BASIC + +; primary command tokens (can start a statement) + +TK_END = $80 ; END token +TK_FOR = TK_END+1 ; FOR token +TK_NEXT = TK_FOR+1 ; NEXT token +TK_DATA = TK_NEXT+1 ; DATA token +TK_INPUT = TK_DATA+1 ; INPUT token +TK_DIM = TK_INPUT+1 ; DIM token +TK_READ = TK_DIM+1 ; READ token +TK_LET = TK_READ+1 ; LET token +TK_DEC = TK_LET+1 ; DEC token +TK_GOTO = TK_DEC+1 ; GOTO token +TK_RUN = TK_GOTO+1 ; RUN token +TK_IF = TK_RUN+1 ; IF token +TK_RESTORE = TK_IF+1 ; RESTORE token +TK_GOSUB = TK_RESTORE+1 ; GOSUB token +TK_RETIRQ = TK_GOSUB+1 ; RETIRQ token +TK_RETNMI = TK_RETIRQ+1 ; RETNMI token +TK_RETURN = TK_RETNMI+1 ; RETURN token +TK_REM = TK_RETURN+1 ; REM token +TK_STOP = TK_REM+1 ; STOP token +TK_ON = TK_STOP+1 ; ON token +TK_NULL = TK_ON+1 ; NULL token +TK_INC = TK_NULL+1 ; INC token +TK_WAIT = TK_INC+1 ; WAIT token +TK_LOAD = TK_WAIT+1 ; LOAD token +TK_SAVE = TK_LOAD+1 ; SAVE token +TK_DEF = TK_SAVE+1 ; DEF token +TK_POKE = TK_DEF+1 ; POKE token +TK_DOKE = TK_POKE+1 ; DOKE token +TK_CALL = TK_DOKE+1 ; CALL token +TK_DO = TK_CALL+1 ; DO token +TK_LOOP = TK_DO+1 ; LOOP token +TK_PRINT = TK_LOOP+1 ; PRINT token +TK_CONT = TK_PRINT+1 ; CONT token +TK_LIST = TK_CONT+1 ; LIST token +TK_CLEAR = TK_LIST+1 ; CLEAR token +TK_NEW = TK_CLEAR+1 ; NEW token +TK_WIDTH = TK_NEW+1 ; WIDTH token +TK_GET = TK_WIDTH+1 ; GET token +TK_SWAP = TK_GET+1 ; SWAP token +TK_BITSET = TK_SWAP+1 ; BITSET token +TK_BITCLR = TK_BITSET+1 ; BITCLR token +TK_IRQ = TK_BITCLR+1 ; IRQ token +TK_NMI = TK_IRQ+1 ; NMI token + +; secondary command tokens, can't start a statement + +TK_TAB = TK_NMI+1 ; TAB token +TK_ELSE = TK_TAB+1 ; ELSE token +TK_TO = TK_ELSE+1 ; TO token +TK_FN = TK_TO+1 ; FN token +TK_SPC = TK_FN+1 ; SPC token +TK_THEN = TK_SPC+1 ; THEN token +TK_NOT = TK_THEN+1 ; NOT token +TK_STEP = TK_NOT+1 ; STEP token +TK_UNTIL = TK_STEP+1 ; UNTIL token +TK_WHILE = TK_UNTIL+1 ; WHILE token +TK_OFF = TK_WHILE+1 ; OFF token + +; opperator tokens + +TK_PLUS = TK_OFF+1 ; + token +TK_MINUS = TK_PLUS+1 ; - token +TK_MUL = TK_MINUS+1 ; * token +TK_DIV = TK_MUL+1 ; / token +TK_POWER = TK_DIV+1 ; ^ token +TK_AND = TK_POWER+1 ; AND token +TK_EOR = TK_AND+1 ; EOR token +TK_OR = TK_EOR+1 ; OR token +TK_RSHIFT = TK_OR+1 ; RSHIFT token +TK_LSHIFT = TK_RSHIFT+1 ; LSHIFT token +TK_GT = TK_LSHIFT+1 ; > token +TK_EQUAL = TK_GT+1 ; = token +TK_LT = TK_EQUAL+1 ; < token + +; functions tokens + +TK_SGN = TK_LT+1 ; SGN token +TK_INT = TK_SGN+1 ; INT token +TK_ABS = TK_INT+1 ; ABS token +TK_USR = TK_ABS+1 ; USR token +TK_FRE = TK_USR+1 ; FRE token +TK_POS = TK_FRE+1 ; POS token +TK_SQR = TK_POS+1 ; SQR token +TK_RND = TK_SQR+1 ; RND token +TK_LOG = TK_RND+1 ; LOG token +TK_EXP = TK_LOG+1 ; EXP token +TK_COS = TK_EXP+1 ; COS token +TK_SIN = TK_COS+1 ; SIN token +TK_TAN = TK_SIN+1 ; TAN token +TK_ATN = TK_TAN+1 ; ATN token +TK_PEEK = TK_ATN+1 ; PEEK token +TK_DEEK = TK_PEEK+1 ; DEEK token +TK_SADD = TK_DEEK+1 ; SADD token +TK_LEN = TK_SADD+1 ; LEN token +TK_STRS = TK_LEN+1 ; STR$ token +TK_VAL = TK_STRS+1 ; VAL token +TK_ASC = TK_VAL+1 ; ASC token +TK_UCASES = TK_ASC+1 ; UCASE$ token +TK_LCASES = TK_UCASES+1 ; LCASE$ token +TK_CHRS = TK_LCASES+1 ; CHR$ token +TK_HEXS = TK_CHRS+1 ; HEX$ token +TK_BINS = TK_HEXS+1 ; BIN$ token +TK_BITTST = TK_BINS+1 ; BITTST token +TK_MAX = TK_BITTST+1 ; MAX token +TK_MIN = TK_MAX+1 ; MIN token +TK_PI = TK_MIN+1 ; PI token +TK_TWOPI = TK_PI+1 ; TWOPI token +TK_VPTR = TK_TWOPI+1 ; VARPTR token +TK_LEFTS = TK_VPTR+1 ; LEFT$ token +TK_RIGHTS = TK_LEFTS+1 ; RIGHT$ token +TK_MIDS = TK_RIGHTS+1 ; MID$ token + +; offsets from a base of X or Y + +PLUS_0 = $00 ; X or Y plus 0 +PLUS_1 = $01 ; X or Y plus 1 +PLUS_2 = $02 ; X or Y plus 2 +PLUS_3 = $03 ; X or Y plus 3 + +LAB_STAK = $0100 ; stack bottom, no offset + +LAB_SKFE = LAB_STAK+$FE + ; flushed stack address +LAB_SKFF = LAB_STAK+$FF + ; flushed stack address + +ccflag = $0200 ; BASIC CTRL-C flag, 00 = enabled, 01 = dis +ccbyte = ccflag+1 ; BASIC CTRL-C byte +ccnull = ccbyte+1 ; BASIC CTRL-C byte timeout + +VEC_CC = ccnull+1 ; ctrl c check vector + +VEC_IN = VEC_CC+2 ; input vector +VEC_OUT = VEC_IN+2 ; output vector +VEC_LD = VEC_OUT+2 ; load vector +VEC_SV = VEC_LD+2 ; save vector + +; Ibuffs can now be anywhere in RAM, ensure that the max length is < $80 + +IRQ_vec = VEC_SV+2 + +Ibuffs = IRQ_vec+$14 ; start of input buffer after IRQ/NMI code +Ibuffe = Ibuffs+$47 ; end of input buffer + + .ORG $FFC0 + +; I/O routines for MKBASIC (V65) emulator. + +CHRIN + LDA $FFE1 ; Read from char IO address, non-blocking + BEQ ECHRIN ; if null, assume no character in buffer + CMP #'a' ; < 'a'? + BCC DCHRIN ; yes, done + CMP #'{' ; >= '{'? + BCS DCHRIN ; yes, done + AND #$5F ; no, convert to upper case +DCHRIN + SEC ; These is character waiting, set CARRY flag + RTS +ECHRIN + CLC ; no character in buffer, clear CARRY + RTS + +CHROUT + STA $FFE0 ; write to char IO address + AND #$FF ; set flags + RTS + + +Ram_base = $0300 ; start of user RAM (set as needed, should be page aligned) +Ram_top = $B000 ; end of user RAM+1 (set as needed, should be page aligned) + +; This start can be changed to suit your system + + *= $C000 + +; BASIC cold start entry point + +; new page 2 initialisation, copy block to ccflag on + +LAB_COLD + CLD + LDY #PG2_TABE-PG2_TABS-1 + ; byte count-1 +LAB_2D13 + LDA PG2_TABS,Y ; get byte + STA ccflag,Y ; store in page 2 + DEY ; decrement count + BPL LAB_2D13 ; loop if not done + + LDX #$FF ; set byte + STX Ibuffs + STX Clineh ; set current line high byte (set immediate mode) + TXS ; reset stack pointer + + LDA #$4C ; code for JMP + STA Fnxjmp ; save for jump vector for functions + +; copy block from LAB_2CEE to $00BC - $00D3 + + LDX #StrTab-LAB_2CEE ; set byte count +LAB_2D4E + LDA LAB_2CEE-1,X ; get byte from table + STA LAB_IGBY-1,X ; save byte in page zero + DEX ; decrement count + BNE LAB_2D4E ; loop if not all done + +; copy block from StrTab to $0000 - $0012 + +LAB_GMEM + LDX #EndTab-StrTab-1 ; set byte count-1 +TabLoop + LDA StrTab,X ; get byte from table + STA PLUS_0,X ; save byte in page zero + DEX ; decrement count + BPL TabLoop ; loop if not all done + +; set-up start values + + LDA #$00 ; clear A + STA NmiBase ; clear NMI handler enabled flag + STA IrqBase ; clear IRQ handler enabled flag + STA FAC1_o ; clear FAC1 overflow byte + STA last_sh ; clear descriptor stack top item pointer high byte + + LDA #$0E ; set default tab size + STA TabSiz ; save it + LDA #$03 ; set garbage collect step size for descriptor stack + STA g_step ; save it + LDX #des_sk ; descriptor stack start + STX next_s ; set descriptor stack pointer + JSR LAB_CRLF ; print CR/LF + LDA #LAB_MSZM ; point to memory size message (high addr) + JSR LAB_18C3 ; print null terminated string from memory + JSR LAB_INLN ; print "? " and get BASIC input + STX Bpntrl ; set BASIC execute pointer low byte + STY Bpntrh ; set BASIC execute pointer high byte + JSR LAB_GBYT ; get last byte back + + BNE LAB_2DAA ; branch if not null (user typed something) + + LDY #$00 ; else clear Y + ; character was null so get memory size the hard way + ; we get here with Y=0 and Itempl/h = Ram_base +LAB_2D93 + INC Itempl ; increment temporary integer low byte + BNE LAB_2D99 ; branch if no overflow + + INC Itemph ; increment temporary integer high byte + LDA Itemph ; get high byte + CMP #>Ram_top ; compare with top of RAM+1 + BEQ LAB_2DB6 ; branch if match (end of user RAM) + +LAB_2D99 + LDA #$55 ; set test byte + STA (Itempl),Y ; save via temporary integer + CMP (Itempl),Y ; compare via temporary integer + BNE LAB_2DB6 ; branch if fail + + ASL ; shift test byte left (now $AA) + STA (Itempl),Y ; save via temporary integer + CMP (Itempl),Y ; compare via temporary integer + BEQ LAB_2D93 ; if ok go do next byte + + BNE LAB_2DB6 ; branch if fail + +LAB_2DAA + JSR LAB_2887 ; get FAC1 from string + LDA FAC1_e ; get FAC1 exponent + CMP #$98 ; compare with exponent = 2^24 + BCS LAB_GMEM ; if too large go try again + + JSR LAB_F2FU ; save integer part of FAC1 in temporary integer + ; (no range check) + +LAB_2DB6 + LDA Itempl ; get temporary integer low byte + LDY Itemph ; get temporary integer high byte + CPY #Ram_top ; compare with top of RAM high byte +; BCC MEM_OK ; branch if < RAM top + +; BNE LAB_GMEM ; if too large go try again + ; else was = so compare low bytes +; CMP #Ram_base ; set start addr high byte + STY Smeml ; save start of mem low byte + STX Smemh ; save start of mem high byte + +; this line is only needed if Ram_base is not $xx00 + +; LDY #$00 ; clear Y + TYA ; clear A + STA (Smeml),Y ; clear first byte + INC Smeml ; increment start of mem low byte + +; these two lines are only needed if Ram_base is $xxFF + +; BNE LAB_2E05 ; branch if no rollover + +; INC Smemh ; increment start of mem high byte +LAB_2E05 + JSR LAB_CRLF ; print CR/LF + JSR LAB_1463 ; do "NEW" and "CLEAR" + LDA Ememl ; get end of mem low byte + SEC ; set carry for subtract + SBC Smeml ; subtract start of mem low byte + TAX ; copy to X + LDA Ememh ; get end of mem high byte + SBC Smemh ; subtract start of mem high byte + JSR LAB_295E ; print XA as unsigned integer (bytes free) + LDA #LAB_SMSG ; point to sign-on message (high addr) + JSR LAB_18C3 ; print null terminated string from memory + LDA #LAB_1274 ; warm start vector high byte + STA Wrmjpl ; save warm start vector low byte + STY Wrmjph ; save warm start vector high byte + JMP (Wrmjpl) ; go do warm start + +; open up space in memory +; move (Ostrtl)-(Obendl) to new block ending at (Nbendl) + +; Nbendl,Nbendh - new block end address (A/Y) +; Obendl,Obendh - old block end address +; Ostrtl,Ostrth - old block start address + +; returns with .. + +; Nbendl,Nbendh - new block start address (high byte - $100) +; Obendl,Obendh - old block start address (high byte - $100) +; Ostrtl,Ostrth - old block start address (unchanged) + +LAB_11CF + JSR LAB_121F ; check available memory, "Out of memory" error if no room + ; addr to check is in AY (low/high) + STA Earryl ; save new array mem end low byte + STY Earryh ; save new array mem end high byte + +; open up space in memory +; move (Ostrtl)-(Obendl) to new block ending at (Nbendl) +; don't set array end + +LAB_11D6 + SEC ; set carry for subtract + LDA Obendl ; get block end low byte + SBC Ostrtl ; subtract block start low byte + TAY ; copy MOD(block length/$100) byte to Y + LDA Obendh ; get block end high byte + SBC Ostrth ; subtract block start high byte + TAX ; copy block length high byte to X + INX ; +1 to allow for count=0 exit + TYA ; copy block length low byte to A + BEQ LAB_120A ; branch if length low byte=0 + + ; block is (X-1)*256+Y bytes, do the Y bytes first + + SEC ; set carry for add + 1, two's complement + EOR #$FF ; invert low byte for subtract + ADC Obendl ; add block end low byte + + STA Obendl ; save corrected old block end low byte + BCS LAB_11F3 ; branch if no underflow + + DEC Obendh ; else decrement block end high byte + SEC ; set carry for add + 1, two's complement +LAB_11F3 + TYA ; get MOD(block length/$100) byte + EOR #$FF ; invert low byte for subtract + ADC Nbendl ; add destination end low byte + STA Nbendl ; save modified new block end low byte + BCS LAB_1203 ; branch if no underflow + + DEC Nbendh ; else decrement block end high byte + BCC LAB_1203 ; branch always + +LAB_11FF + LDA (Obendl),Y ; get byte from source + STA (Nbendl),Y ; copy byte to destination +LAB_1203 + DEY ; decrement index + BNE LAB_11FF ; loop until Y=0 + + ; now do Y=0 indexed byte + LDA (Obendl),Y ; get byte from source + STA (Nbendl),Y ; save byte to destination +LAB_120A + DEC Obendh ; decrement source pointer high byte + DEC Nbendh ; decrement destination pointer high byte + DEX ; decrement block count + BNE LAB_1203 ; loop until count = $0 + + RTS + +; check room on stack for A bytes +; stack too deep? do OM error + +LAB_1212 + STA TempB ; save result in temp byte + TSX ; copy stack + CPX TempB ; compare new "limit" with stack + BCC LAB_OMER ; if stack < limit do "Out of memory" error then warm start + + RTS + +; check available memory, "Out of memory" error if no room +; addr to check is in AY (low/high) + +LAB_121F + CPY Sstorh ; compare bottom of string mem high byte + BCC LAB_124B ; if less then exit (is ok) + + BNE LAB_1229 ; skip next test if greater (tested <) + + ; high byte was =, now do low byte + CMP Sstorl ; compare with bottom of string mem low byte + BCC LAB_124B ; if less then exit (is ok) + + ; addr is > string storage ptr (oops!) +LAB_1229 + PHA ; push addr low byte + LDX #$08 ; set index to save Adatal to expneg inclusive + TYA ; copy addr high byte (to push on stack) + + ; save misc numeric work area +LAB_122D + PHA ; push byte + LDA Adatal-1,X ; get byte from Adatal to expneg ( ,$00 not pushed) + DEX ; decrement index + BPL LAB_122D ; loop until all done + + JSR LAB_GARB ; garbage collection routine + + ; restore misc numeric work area + LDX #$00 ; clear the index to restore bytes +LAB_1238 + PLA ; pop byte + STA Adatal,X ; save byte to Adatal to expneg + INX ; increment index + CPX #$08 ; compare with end + 1 + BMI LAB_1238 ; loop if more to do + + PLA ; pop addr high byte + TAY ; copy back to Y + PLA ; pop addr low byte + CPY Sstorh ; compare bottom of string mem high byte + BCC LAB_124B ; if less then exit (is ok) + + BNE LAB_OMER ; if greater do "Out of memory" error then warm start + + ; high byte was =, now do low byte + CMP Sstorl ; compare with bottom of string mem low byte + BCS LAB_OMER ; if >= do "Out of memory" error then warm start + + ; ok exit, carry clear +LAB_124B + RTS + +; do "Out of memory" error then warm start + +LAB_OMER + LDX #$0C ; error code $0C ("Out of memory" error) + +; do error #X, then warm start + +LAB_XERR + JSR LAB_CRLF ; print CR/LF + + LDA LAB_BAER,X ; get error message pointer low byte + LDY LAB_BAER+1,X ; get error message pointer high byte + JSR LAB_18C3 ; print null terminated string from memory + + JSR LAB_1491 ; flush stack and clear continue flag + LDA #LAB_EMSG ; point to " Error" high addr +LAB_1269 + JSR LAB_18C3 ; print null terminated string from memory + LDY Clineh ; get current line high byte + INY ; increment it + BEQ LAB_1274 ; go do warm start (was immediate mode) + + ; else print line number + JSR LAB_2953 ; print " in line [LINE #]" + +; BASIC warm start entry point +; wait for Basic command + +LAB_1274 + ; clear ON IRQ/NMI bytes + LDA #$00 ; clear A + STA IrqBase ; clear enabled byte + STA NmiBase ; clear enabled byte + LDA #LAB_RMSG ; point to "Ready" message high byte + + JSR LAB_18C3 ; go do print string + CLC + +; wait for Basic command (no "Ready") + +LAB_127D + JSR LAB_1357 ; call for BASIC input +LAB_1280 + STX Bpntrl ; set BASIC execute pointer low byte + STY Bpntrh ; set BASIC execute pointer high byte + JSR LAB_GBYT ; scan memory + BEQ LAB_127D ; loop while null + +; got to interpret input line now .. + + LDX #$FF ; current line to null value + STX Clineh ; set current line high byte + BCC LAB_1295 ; branch if numeric character (handle new BASIC line) + + ; no line number .. immediate mode + JSR LAB_13A6 ; crunch keywords into Basic tokens + JMP LAB_15F6 ; go scan and interpret code + +; handle new BASIC line + +LAB_1295 + JSR LAB_GFPN ; get fixed-point number into temp integer + JSR LAB_13A6 ; crunch keywords into Basic tokens + STY Ibptr ; save index pointer to end of crunched line + JSR LAB_SSLN ; search BASIC for temp integer line number + BCC LAB_12E6 ; branch if not found + + ; aroooogah! line # already exists! delete it + LDY #$01 ; set index to next line pointer high byte + LDA (Baslnl),Y ; get next line pointer high byte + STA ut1_ph ; save it + LDA Svarl ; get start of vars low byte + STA ut1_pl ; save it + LDA Baslnh ; get found line pointer high byte + STA ut2_ph ; save it + LDA Baslnl ; get found line pointer low byte + DEY ; decrement index + SBC (Baslnl),Y ; subtract next line pointer low byte + CLC ; clear carry for add + ADC Svarl ; add start of vars low byte + STA Svarl ; save new start of vars low byte + STA ut2_pl ; save destination pointer low byte + LDA Svarh ; get start of vars high byte + ADC #$FF ; -1 + carry + STA Svarh ; save start of vars high byte + SBC Baslnh ; subtract found line pointer high byte + TAX ; copy to block count + SEC ; set carry for subtract + LDA Baslnl ; get found line pointer low byte + SBC Svarl ; subtract start of vars low byte + TAY ; copy to bytes in first block count + BCS LAB_12D0 ; branch if overflow + + INX ; increment block count (correct for =0 loop exit) + DEC ut2_ph ; decrement destination high byte +LAB_12D0 + CLC ; clear carry for add + ADC ut1_pl ; add source pointer low byte + BCC LAB_12D8 ; branch if no overflow + + DEC ut1_ph ; else decrement source pointer high byte + CLC ; clear carry + + ; close up memory to delete old line +LAB_12D8 + LDA (ut1_pl),Y ; get byte from source + STA (ut2_pl),Y ; copy to destination + INY ; increment index + BNE LAB_12D8 ; while <> 0 do this block + + INC ut1_ph ; increment source pointer high byte + INC ut2_ph ; increment destination pointer high byte + DEX ; decrement block count + BNE LAB_12D8 ; loop until all done + + ; got new line in buffer and no existing same # +LAB_12E6 + LDA Ibuffs ; get byte from start of input buffer + BEQ LAB_1319 ; if null line just go flush stack/vars and exit + + ; got new line and it isn't empty line + LDA Ememl ; get end of mem low byte + LDY Ememh ; get end of mem high byte + STA Sstorl ; set bottom of string space low byte + STY Sstorh ; set bottom of string space high byte + LDA Svarl ; get start of vars low byte (end of BASIC) + STA Obendl ; save old block end low byte + LDY Svarh ; get start of vars high byte (end of BASIC) + STY Obendh ; save old block end high byte + ADC Ibptr ; add input buffer pointer (also buffer length) + BCC LAB_1301 ; branch if no overflow from add + + INY ; else increment high byte +LAB_1301 + STA Nbendl ; save new block end low byte (move to, low byte) + STY Nbendh ; save new block end high byte + JSR LAB_11CF ; open up space in memory + ; old start pointer Ostrtl,Ostrth set by the find line call + LDA Earryl ; get array mem end low byte + LDY Earryh ; get array mem end high byte + STA Svarl ; save start of vars low byte + STY Svarh ; save start of vars high byte + LDY Ibptr ; get input buffer pointer (also buffer length) + DEY ; adjust for loop type +LAB_1311 + LDA Ibuffs-4,Y ; get byte from crunched line + STA (Baslnl),Y ; save it to program memory + DEY ; decrement count + CPY #$03 ; compare with first byte-1 + BNE LAB_1311 ; continue while count <> 3 + + LDA Itemph ; get line # high byte + STA (Baslnl),Y ; save it to program memory + DEY ; decrement count + LDA Itempl ; get line # low byte + STA (Baslnl),Y ; save it to program memory + DEY ; decrement count + LDA #$FF ; set byte to allow chain rebuild. if you didn't set this + ; byte then a zero already here would stop the chain rebuild + ; as it would think it was the [EOT] marker. + STA (Baslnl),Y ; save it to program memory + +LAB_1319 + JSR LAB_1477 ; reset execution to start, clear vars and flush stack + LDX Smeml ; get start of mem low byte + LDA Smemh ; get start of mem high byte + LDY #$01 ; index to high byte of next line pointer +LAB_1325 + STX ut1_pl ; set line start pointer low byte + STA ut1_ph ; set line start pointer high byte + LDA (ut1_pl),Y ; get it + BEQ LAB_133E ; exit if end of program + +; rebuild chaining of Basic lines + + LDY #$04 ; point to first code byte of line + ; there is always 1 byte + [EOL] as null entries are deleted +LAB_1330 + INY ; next code byte + LDA (ut1_pl),Y ; get byte + BNE LAB_1330 ; loop if not [EOL] + + SEC ; set carry for add + 1 + TYA ; copy end index + ADC ut1_pl ; add to line start pointer low byte + TAX ; copy to X + LDY #$00 ; clear index, point to this line's next line pointer + STA (ut1_pl),Y ; set next line pointer low byte + TYA ; clear A + ADC ut1_ph ; add line start pointer high byte + carry + INY ; increment index to high byte + STA (ut1_pl),Y ; save next line pointer low byte + BCC LAB_1325 ; go do next line, branch always, carry clear + + +LAB_133E + JMP LAB_127D ; else we just wait for Basic command, no "Ready" + +; print "? " and get BASIC input + +LAB_INLN + JSR LAB_18E3 ; print "?" character + JSR LAB_18E0 ; print " " + BNE LAB_1357 ; call for BASIC input and return + +; receive line from keyboard + + ; $08 as delete key (BACKSPACE on standard keyboard) +LAB_134B + JSR LAB_PRNA ; go print the character + DEX ; decrement the buffer counter (delete) + .byte $2C ; make LDX into BIT abs + +; call for BASIC input (main entry point) + +LAB_1357 + LDX #$00 ; clear BASIC line buffer pointer +LAB_1359 + JSR V_INPT ; call scan input device + BCC LAB_1359 ; loop if no byte + + BEQ LAB_1359 ; loop until valid input (ignore NULLs) + + CMP #$07 ; compare with [BELL] + BEQ LAB_1378 ; branch if [BELL] + + CMP #$0D ; compare with [CR] + BEQ LAB_1384 ; do CR/LF exit if [CR] + + CPX #$00 ; compare pointer with $00 + BNE LAB_1374 ; branch if not empty + +; next two lines ignore any non print character and [SPACE] if input buffer empty + + CMP #$21 ; compare with [SP]+1 + BCC LAB_1359 ; if < ignore character + +LAB_1374 + CMP #$08 ; compare with [BACKSPACE] (delete last character) + BEQ LAB_134B ; go delete last character + +LAB_1378 + CPX #Ibuffe-Ibuffs ; compare character count with max + BCS LAB_138E ; skip store and do [BELL] if buffer full + + STA Ibuffs,X ; else store in buffer + INX ; increment pointer +LAB_137F + JSR LAB_PRNA ; go print the character + BNE LAB_1359 ; always loop for next character + +LAB_1384 + JMP LAB_1866 ; do CR/LF exit to BASIC + +; announce buffer full + +LAB_138E + LDA #$07 ; [BELL] character into A + BNE LAB_137F ; go print the [BELL] but ignore input character + ; branch always + +; crunch keywords into Basic tokens +; position independent buffer version .. +; faster, dictionary search version .... + +LAB_13A6 + LDY #$FF ; set save index (makes for easy math later) + + SEC ; set carry for subtract + LDA Bpntrl ; get basic execute pointer low byte + SBC #= go save byte then continue crunching + + CMP #'<' ; compare with "<" + BCS LAB_13CC ; if >= go crunch now + + CMP #'0' ; compare with "0" + BCS LAB_13EC ; if >= go save byte then continue crunching + + STA Scnquo ; save buffer byte as search character + CMP #$22 ; is it quote character? + BEQ LAB_1410 ; branch if so (copy quoted string) + + CMP #'*' ; compare with "*" + BCC LAB_13EC ; if < go save byte then continue crunching + + ; else crunch now +LAB_13CC + BIT Oquote ; get open quote/DATA token flag + BVS LAB_13EC ; branch if b6 of Oquote set (was DATA) + ; go save byte then continue crunching + + STX TempB ; save buffer read index + STY csidx ; copy buffer save index + LDY #TAB_1STC ; get keyword first character table high address + STY ut2_ph ; save pointer high byte + LDY #$00 ; clear table pointer + +LAB_13D0 + CMP (ut2_pl),Y ; compare with keyword first character table byte + BEQ LAB_13D1 ; go do word_table_chr if match + + BCC LAB_13EA ; if < keyword first character table byte go restore + ; Y and save to crunched + + INY ; else increment pointer + BNE LAB_13D0 ; and loop (branch always) + +; have matched first character of some keyword + +LAB_13D1 + TYA ; copy matching index + ASL ; *2 (bytes per pointer) + TAX ; copy to new index + LDA TAB_CHRT,X ; get keyword table pointer low byte + STA ut2_pl ; save pointer low byte + LDA TAB_CHRT+1,X ; get keyword table pointer high byte + STA ut2_ph ; save pointer high byte + + LDY #$FF ; clear table pointer (make -1 for start) + + LDX TempB ; restore buffer read index + +LAB_13D6 + INY ; next table byte + LDA (ut2_pl),Y ; get byte from table +LAB_13D8 + BMI LAB_13EA ; all bytes matched so go save token + + INX ; next buffer byte + CMP Ibuffs,X ; compare with byte from input buffer + BEQ LAB_13D6 ; go compare next if match + + BNE LAB_1417 ; branch if >< (not found keyword) + +LAB_13EA + LDY csidx ; restore save index + + ; save crunched to output +LAB_13EC + INX ; increment buffer index (to next input byte) + INY ; increment save index (to next output byte) + STA Ibuffs,Y ; save byte to output + CMP #$00 ; set the flags, set carry + BEQ LAB_142A ; do exit if was null [EOL] + + ; A holds token or byte here + SBC #':' ; subtract ":" (carry set by CMP #00) + BEQ LAB_13FF ; branch if it was ":" (is now $00) + + ; A now holds token-$3A + CMP #TK_DATA-$3A ; compare with DATA token - $3A + BNE LAB_1401 ; branch if not DATA + + ; token was : or DATA +LAB_13FF + STA Oquote ; save token-$3A (clear for ":", TK_DATA-$3A for DATA) +LAB_1401 + EOR #TK_REM-$3A ; effectively subtract REM token offset + BNE LAB_13AC ; If wasn't REM then go crunch rest of line + + STA Asrch ; else was REM so set search for [EOL] + + ; loop for REM, "..." etc. +LAB_1408 + LDA Ibuffs,X ; get byte from input buffer + BEQ LAB_13EC ; branch if null [EOL] + + CMP Asrch ; compare with stored character + BEQ LAB_13EC ; branch if match (end quote) + + ; entry for copy string in quotes, don't crunch +LAB_1410 + INY ; increment buffer save index + STA Ibuffs,Y ; save byte to output + INX ; increment buffer read index + BNE LAB_1408 ; loop while <> 0 (should never be 0!) + + ; not found keyword this go +LAB_1417 + LDX TempB ; compare has failed, restore buffer index (start byte!) + + ; now find the end of this word in the table +LAB_141B + LDA (ut2_pl),Y ; get table byte + PHP ; save status + INY ; increment table index + PLP ; restore byte status + BPL LAB_141B ; if not end of keyword go do next + + LDA (ut2_pl),Y ; get byte from keyword table + BNE LAB_13D8 ; go test next word if not zero byte (end of table) + + ; reached end of table with no match + LDA Ibuffs,X ; restore byte from input buffer + BPL LAB_13EA ; branch always (all bytes in buffer are $00-$7F) + ; go save byte in output and continue crunching + + ; reached [EOL] +LAB_142A + INY ; increment pointer + INY ; increment pointer (makes it next line pointer high byte) + STA Ibuffs,Y ; save [EOL] (marks [EOT] in immediate mode) + INY ; adjust for line copy + INY ; adjust for line copy + INY ; adjust for line copy + DEC Bpntrl ; allow for increment (change if buffer starts at $xxFF) + RTS + +; search Basic for temp integer line number from start of mem + +LAB_SSLN + LDA Smeml ; get start of mem low byte + LDX Smemh ; get start of mem high byte + +; search Basic for temp integer line number from AX +; returns carry set if found +; returns Baslnl/Baslnh pointer to found or next higher (not found) line + +; old 541 new 507 + +LAB_SHLN + LDY #$01 ; set index + STA Baslnl ; save low byte as current + STX Baslnh ; save high byte as current + LDA (Baslnl),Y ; get pointer high byte from addr + BEQ LAB_145F ; pointer was zero so we're done, do 'not found' exit + + LDY #$03 ; set index to line # high byte + LDA (Baslnl),Y ; get line # high byte + DEY ; decrement index (point to low byte) + CMP Itemph ; compare with temporary integer high byte + BNE LAB_1455 ; if <> skip low byte check + + LDA (Baslnl),Y ; get line # low byte + CMP Itempl ; compare with temporary integer low byte +LAB_1455 + BCS LAB_145E ; else if temp < this line, exit (passed line#) + +LAB_1456 + DEY ; decrement index to next line ptr high byte + LDA (Baslnl),Y ; get next line pointer high byte + TAX ; copy to X + DEY ; decrement index to next line ptr low byte + LDA (Baslnl),Y ; get next line pointer low byte + BCC LAB_SHLN ; go search for line # in temp (Itempl/Itemph) from AX + ; (carry always clear) + +LAB_145E + BEQ LAB_1460 ; exit if temp = found line #, carry is set + +LAB_145F + CLC ; clear found flag +LAB_1460 + RTS + +; perform NEW + +LAB_NEW + BNE LAB_1460 ; exit if not end of statement (to do syntax error) + +LAB_1463 + LDA #$00 ; clear A + TAY ; clear Y + STA (Smeml),Y ; clear first line, next line pointer, low byte + INY ; increment index + STA (Smeml),Y ; clear first line, next line pointer, high byte + CLC ; clear carry + LDA Smeml ; get start of mem low byte + ADC #$02 ; calculate end of BASIC low byte + STA Svarl ; save start of vars low byte + LDA Smemh ; get start of mem high byte + ADC #$00 ; add any carry + STA Svarh ; save start of vars high byte + +; reset execution to start, clear vars and flush stack + +LAB_1477 + CLC ; clear carry + LDA Smeml ; get start of mem low byte + ADC #$FF ; -1 + STA Bpntrl ; save BASIC execute pointer low byte + LDA Smemh ; get start of mem high byte + ADC #$FF ; -1+carry + STA Bpntrh ; save BASIC execute pointer high byte + +; "CLEAR" command gets here + +LAB_147A + LDA Ememl ; get end of mem low byte + LDY Ememh ; get end of mem high byte + STA Sstorl ; set bottom of string space low byte + STY Sstorh ; set bottom of string space high byte + LDA Svarl ; get start of vars low byte + LDY Svarh ; get start of vars high byte + STA Sarryl ; save var mem end low byte + STY Sarryh ; save var mem end high byte + STA Earryl ; save array mem end low byte + STY Earryh ; save array mem end high byte + JSR LAB_161A ; perform RESTORE command + +; flush stack and clear continue flag + +LAB_1491 + LDX #des_sk ; set descriptor stack pointer + STX next_s ; save descriptor stack pointer + PLA ; pull return address low byte + TAX ; copy return address low byte + PLA ; pull return address high byte + STX LAB_SKFE ; save to cleared stack + STA LAB_SKFF ; save to cleared stack + LDX #$FD ; new stack pointer + TXS ; reset stack + LDA #$00 ; clear byte + STA Cpntrh ; clear continue pointer high byte + STA Sufnxf ; clear subscript/FNX flag +LAB_14A6 + RTS + +; perform CLEAR + +LAB_CLEAR + BEQ LAB_147A ; if no following token go do "CLEAR" + + ; else there was a following token (go do syntax error) + RTS + +; perform LIST [n][-m] +; bigger, faster version (a _lot_ faster) + +LAB_LIST + BCC LAB_14BD ; branch if next character numeric (LIST n..) + + BEQ LAB_14BD ; branch if next character [NULL] (LIST) + + CMP #TK_MINUS ; compare with token for - + BNE LAB_14A6 ; exit if not - (LIST -m) + + ; LIST [[n][-m]] + ; this bit sets the n , if present, as the start and end +LAB_14BD + JSR LAB_GFPN ; get fixed-point number into temp integer + JSR LAB_SSLN ; search BASIC for temp integer line number + ; (pointer in Baslnl/Baslnh) + JSR LAB_GBYT ; scan memory + BEQ LAB_14D4 ; branch if no more characters + + ; this bit checks the - is present + CMP #TK_MINUS ; compare with token for - + BNE LAB_1460 ; return if not "-" (will be Syntax error) + + ; LIST [n]-m + ; the - was there so set m as the end value + JSR LAB_IGBY ; increment and scan memory + JSR LAB_GFPN ; get fixed-point number into temp integer + BNE LAB_1460 ; exit if not ok + +LAB_14D4 + LDA Itempl ; get temporary integer low byte + ORA Itemph ; OR temporary integer high byte + BNE LAB_14E2 ; branch if start set + + LDA #$FF ; set for -1 + STA Itempl ; set temporary integer low byte + STA Itemph ; set temporary integer high byte +LAB_14E2 + LDY #$01 ; set index for line + STY Oquote ; clear open quote flag + JSR LAB_CRLF ; print CR/LF + LDA (Baslnl),Y ; get next line pointer high byte + ; pointer initially set by search at LAB_14BD + BEQ LAB_152B ; if null all done so exit + JSR LAB_1629 ; do CRTL-C check vector + + INY ; increment index for line + LDA (Baslnl),Y ; get line # low byte + TAX ; copy to X + INY ; increment index + LDA (Baslnl),Y ; get line # high byte + CMP Itemph ; compare with temporary integer high byte + BNE LAB_14FF ; branch if no high byte match + + CPX Itempl ; compare with temporary integer low byte + BEQ LAB_1501 ; branch if = last line to do (< will pass next branch) + +LAB_14FF ; else .. + BCS LAB_152B ; if greater all done so exit + +LAB_1501 + STY Tidx1 ; save index for line + JSR LAB_295E ; print XA as unsigned integer + LDA #$20 ; space is the next character +LAB_1508 + LDY Tidx1 ; get index for line + AND #$7F ; mask top out bit of character +LAB_150C + JSR LAB_PRNA ; go print the character + CMP #$22 ; was it " character + BNE LAB_1519 ; branch if not + + ; we are either entering or leaving a pair of quotes + LDA Oquote ; get open quote flag + EOR #$FF ; toggle it + STA Oquote ; save it back +LAB_1519 + INY ; increment index + LDA (Baslnl),Y ; get next byte + BNE LAB_152E ; branch if not [EOL] (go print character) + TAY ; else clear index + LDA (Baslnl),Y ; get next line pointer low byte + TAX ; copy to X + INY ; increment index + LDA (Baslnl),Y ; get next line pointer high byte + STX Baslnl ; set pointer to line low byte + STA Baslnh ; set pointer to line high byte + BNE LAB_14E2 ; go do next line if not [EOT] + ; else .. +LAB_152B + RTS + +LAB_152E + BPL LAB_150C ; just go print it if not token byte + + ; else was token byte so uncrunch it (maybe) + BIT Oquote ; test the open quote flag + BMI LAB_150C ; just go print character if open quote set + + LDX #>LAB_KEYT ; get table address high byte + ASL ; *2 + ASL ; *4 + BCC LAB_152F ; branch if no carry + + INX ; else increment high byte + CLC ; clear carry for add +LAB_152F + ADC #LAB_159F ; set return address high byte + STA ut1_pl ; save return address low byte + STY ut1_ph ; save return address high byte + JMP LAB_1B66 ; round FAC1 and put on stack (returns to next instruction) + +LAB_159F + LDA #LAB_259C ; set 1 pointer high addr + JSR LAB_UFAC ; unpack memory (AY) into FAC1 + JSR LAB_GBYT ; scan memory + CMP #TK_STEP ; compare with STEP token + BNE LAB_15B3 ; jump if not "STEP" + + ;.was step so .. + JSR LAB_IGBY ; increment and scan memory + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch +LAB_15B3 + JSR LAB_27CA ; return A=FF,C=1/-ve A=01,C=0/+ve + STA FAC1_s ; set FAC1 sign (b7) + ; this is +1 for +ve step and -1 for -ve step, in NEXT we + ; compare the FOR value and the TO value and return +1 if + ; FOR > TO, 0 if FOR = TO and -1 if FOR < TO. the value + ; here (+/-1) is then compared to that result and if they + ; are the same (+ve and FOR > TO or -ve and FOR < TO) then + ; the loop is done + JSR LAB_1B5B ; push sign, round FAC1 and put on stack + LDA Frnxth ; get var pointer for FOR/NEXT high byte + PHA ; push on stack + LDA Frnxtl ; get var pointer for FOR/NEXT low byte + PHA ; push on stack + LDA #TK_FOR ; get FOR token + PHA ; push on stack + +; interpreter inner loop + +LAB_15C2 + JSR LAB_1629 ; do CRTL-C check vector + LDA Bpntrl ; get BASIC execute pointer low byte + LDY Bpntrh ; get BASIC execute pointer high byte + + LDX Clineh ; continue line is $FFxx for immediate mode + ; ($00xx for RUN from immediate mode) + INX ; increment it (now $00 if immediate mode) + BEQ LAB_15D1 ; branch if null (immediate mode) + + STA Cpntrl ; save continue pointer low byte + STY Cpntrh ; save continue pointer high byte +LAB_15D1 + LDY #$00 ; clear index + LDA (Bpntrl),Y ; get next byte + BEQ LAB_15DC ; branch if null [EOL] + + CMP #':' ; compare with ":" + BEQ LAB_15F6 ; branch if = (statement separator) + +LAB_15D9 + JMP LAB_SNER ; else syntax error then warm start + + ; have reached [EOL] +LAB_15DC + LDY #$02 ; set index + LDA (Bpntrl),Y ; get next line pointer high byte + CLC ; clear carry for no "BREAK" message + BEQ LAB_1651 ; if null go to immediate mode (was immediate or [EOT] + ; marker) + + INY ; increment index + LDA (Bpntrl),Y ; get line # low byte + STA Clinel ; save current line low byte + INY ; increment index + LDA (Bpntrl),Y ; get line # high byte + STA Clineh ; save current line high byte + TYA ; A now = 4 + ADC Bpntrl ; add BASIC execute pointer low byte + STA Bpntrl ; save BASIC execute pointer low byte + BCC LAB_15F6 ; branch if no overflow + + INC Bpntrh ; else increment BASIC execute pointer high byte +LAB_15F6 + JSR LAB_IGBY ; increment and scan memory + +LAB_15F9 + JSR LAB_15FF ; go interpret BASIC code from (Bpntrl) + +LAB_15FC + JMP LAB_15C2 ; loop + +; interpret BASIC code from (Bpntrl) + +LAB_15FF + BEQ LAB_1628 ; exit if zero [EOL] + +LAB_1602 + ASL ; *2 bytes per vector and normalise token + BCS LAB_1609 ; branch if was token + + JMP LAB_LET ; else go do implied LET + +LAB_1609 + CMP #[TK_TAB-$80]*2 ; compare normalised token * 2 with TAB + BCS LAB_15D9 ; branch if A>=TAB (do syntax error then warm start) + ; only tokens before TAB can start a line + TAY ; copy to index + LDA LAB_CTBL+1,Y ; get vector high byte + PHA ; onto stack + LDA LAB_CTBL,Y ; get vector low byte + PHA ; onto stack + JMP LAB_IGBY ; jump to increment and scan memory + ; then "return" to vector + +; CTRL-C check jump. this is called as a subroutine but exits back via a jump if a +; key press is detected. + +LAB_1629 + JMP (VEC_CC) ; ctrl c check vector + +; if there was a key press it gets back here .. + +LAB_1636 + CMP #$03 ; compare with CTRL-C + +; perform STOP + +LAB_STOP + BCS LAB_163B ; branch if token follows STOP + ; else just END +; END + +LAB_END + CLC ; clear the carry, indicate a normal program end +LAB_163B + BNE LAB_167A ; if wasn't CTRL-C or there is a following byte return + + LDA Bpntrh ; get the BASIC execute pointer high byte + EOR #>Ibuffs ; compare with buffer address high byte (Cb unchanged) + BEQ LAB_164F ; branch if the BASIC pointer is in the input buffer + ; (can't continue in immediate mode) + + ; else .. + EOR #>Ibuffs ; correct the bits + LDY Bpntrl ; get BASIC execute pointer low byte + STY Cpntrl ; save continue pointer low byte + STA Cpntrh ; save continue pointer high byte +LAB_1647 + LDA Clinel ; get current line low byte + LDY Clineh ; get current line high byte + STA Blinel ; save break line low byte + STY Blineh ; save break line high byte +LAB_164F + PLA ; pull return address low + PLA ; pull return address high +LAB_1651 + BCC LAB_165E ; if was program end just do warm start + + ; else .. + LDA #LAB_BMSG ; point to "Break" high byte + JMP LAB_1269 ; print "Break" and do warm start + +LAB_165E + JMP LAB_1274 ; go do warm start + +; perform RESTORE + +LAB_RESTORE + BNE LAB_RESTOREn ; branch if next character not null (RESTORE n) + +LAB_161A + SEC ; set carry for subtract + LDA Smeml ; get start of mem low byte + SBC #$01 ; -1 + LDY Smemh ; get start of mem high byte + BCS LAB_1624 ; branch if no underflow + +LAB_uflow + DEY ; else decrement high byte +LAB_1624 + STA Dptrl ; save DATA pointer low byte + STY Dptrh ; save DATA pointer high byte +LAB_1628 + RTS + + ; is RESTORE n +LAB_RESTOREn + JSR LAB_GFPN ; get fixed-point number into temp integer + JSR LAB_SNBL ; scan for next BASIC line + LDA Clineh ; get current line high byte + CMP Itemph ; compare with temporary integer high byte + BCS LAB_reset_search ; branch if >= (start search from beginning) + + TYA ; else copy line index to A + SEC ; set carry (+1) + ADC Bpntrl ; add BASIC execute pointer low byte + LDX Bpntrh ; get BASIC execute pointer high byte + BCC LAB_go_search ; branch if no overflow to high byte + + INX ; increment high byte + BCS LAB_go_search ; branch always (can never be carry clear) + +; search for line # in temp (Itempl/Itemph) from start of mem pointer (Smeml) + +LAB_reset_search + LDA Smeml ; get start of mem low byte + LDX Smemh ; get start of mem high byte + +; search for line # in temp (Itempl/Itemph) from (AX) + +LAB_go_search + + JSR LAB_SHLN ; search Basic for temp integer line number from AX + BCS LAB_line_found ; if carry set go set pointer + + JMP LAB_16F7 ; else go do "Undefined statement" error + +LAB_line_found + ; carry already set for subtract + LDA Baslnl ; get pointer low byte + SBC #$01 ; -1 + LDY Baslnh ; get pointer high byte + BCS LAB_1624 ; branch if no underflow (save DATA pointer and return) + + BCC LAB_uflow ; else decrement high byte then save DATA pointer and + ; return (branch always) + +; perform NULL + +LAB_NULL + JSR LAB_GTBY ; get byte parameter + STX Nullct ; save new NULL count +LAB_167A + RTS + +; perform CONT + +LAB_CONT + BNE LAB_167A ; if following byte exit to do syntax error + + LDY Cpntrh ; get continue pointer high byte + BNE LAB_166C ; go do continue if we can + + LDX #$1E ; error code $1E ("Can't continue" error) + JMP LAB_XERR ; do error #X, then warm start + + ; we can continue so .. +LAB_166C + LDA #TK_ON ; set token for ON + JSR LAB_IRQ ; set IRQ flags + LDA #TK_ON ; set token for ON + JSR LAB_NMI ; set NMI flags + + STY Bpntrh ; save BASIC execute pointer high byte + LDA Cpntrl ; get continue pointer low byte + STA Bpntrl ; save BASIC execute pointer low byte + LDA Blinel ; get break line low byte + LDY Blineh ; get break line high byte + STA Clinel ; set current line low byte + STY Clineh ; set current line high byte + RTS + +; perform RUN + +LAB_RUN + BNE LAB_1696 ; branch if RUN n + JMP LAB_1477 ; reset execution to start, clear variables, flush stack and + ; return + +; does RUN n + +LAB_1696 + JSR LAB_147A ; go do "CLEAR" + BEQ LAB_16B0 ; get n and do GOTO n (branch always as CLEAR sets Z=1) + +; perform DO + +LAB_DO + LDA #$05 ; need 5 bytes for DO + JSR LAB_1212 ; check room on stack for A bytes + LDA Bpntrh ; get BASIC execute pointer high byte + PHA ; push on stack + LDA Bpntrl ; get BASIC execute pointer low byte + PHA ; push on stack + LDA Clineh ; get current line high byte + PHA ; push on stack + LDA Clinel ; get current line low byte + PHA ; push on stack + LDA #TK_DO ; token for DO + PHA ; push on stack + JSR LAB_GBYT ; scan memory + JMP LAB_15C2 ; go do interpreter inner loop + +; perform GOSUB + +LAB_GOSUB + LDA #$05 ; need 5 bytes for GOSUB + JSR LAB_1212 ; check room on stack for A bytes + LDA Bpntrh ; get BASIC execute pointer high byte + PHA ; push on stack + LDA Bpntrl ; get BASIC execute pointer low byte + PHA ; push on stack + LDA Clineh ; get current line high byte + PHA ; push on stack + LDA Clinel ; get current line low byte + PHA ; push on stack + LDA #TK_GOSUB ; token for GOSUB + PHA ; push on stack +LAB_16B0 + JSR LAB_GBYT ; scan memory + JSR LAB_GOTO ; perform GOTO n + JMP LAB_15C2 ; go do interpreter inner loop + ; (can't RTS, we used the stack!) + +; perform GOTO + +LAB_GOTO + JSR LAB_GFPN ; get fixed-point number into temp integer + JSR LAB_SNBL ; scan for next BASIC line + LDA Clineh ; get current line high byte + CMP Itemph ; compare with temporary integer high byte + BCS LAB_16D0 ; branch if >= (start search from beginning) + + TYA ; else copy line index to A + SEC ; set carry (+1) + ADC Bpntrl ; add BASIC execute pointer low byte + LDX Bpntrh ; get BASIC execute pointer high byte + BCC LAB_16D4 ; branch if no overflow to high byte + + INX ; increment high byte + BCS LAB_16D4 ; branch always (can never be carry) + +; search for line # in temp (Itempl/Itemph) from start of mem pointer (Smeml) + +LAB_16D0 + LDA Smeml ; get start of mem low byte + LDX Smemh ; get start of mem high byte + +; search for line # in temp (Itempl/Itemph) from (AX) + +LAB_16D4 + JSR LAB_SHLN ; search Basic for temp integer line number from AX + BCC LAB_16F7 ; if carry clear go do "Undefined statement" error + ; (unspecified statement) + + ; carry already set for subtract + LDA Baslnl ; get pointer low byte + SBC #$01 ; -1 + STA Bpntrl ; save BASIC execute pointer low byte + LDA Baslnh ; get pointer high byte + SBC #$00 ; subtract carry + STA Bpntrh ; save BASIC execute pointer high byte +LAB_16E5 + RTS + +LAB_DONOK + LDX #$22 ; error code $22 ("LOOP without DO" error) + JMP LAB_XERR ; do error #X, then warm start + +; perform LOOP + +LAB_LOOP + TAY ; save following token + TSX ; copy stack pointer + LDA LAB_STAK+3,X ; get token byte from stack + CMP #TK_DO ; compare with DO token + BNE LAB_DONOK ; branch if no matching DO + + INX ; dump calling routine return address + INX ; dump calling routine return address + TXS ; correct stack + TYA ; get saved following token back + BEQ LoopAlways ; if no following token loop forever + ; (stack pointer in X) + + CMP #':' ; could be ':' + BEQ LoopAlways ; if :... loop forever + + SBC #TK_UNTIL ; subtract token for UNTIL, we know carry is set here + TAX ; copy to X (if it was UNTIL then Y will be correct) + BEQ DoRest ; branch if was UNTIL + + DEX ; decrement result + BNE LAB_16FC ; if not WHILE go do syntax error and warm start + ; only if the token was WHILE will this fail + + DEX ; set invert result byte +DoRest + STX Frnxth ; save invert result byte + JSR LAB_IGBY ; increment and scan memory + JSR LAB_EVEX ; evaluate expression + LDA FAC1_e ; get FAC1 exponent + BEQ DoCmp ; if =0 go do straight compare + + LDA #$FF ; else set all bits +DoCmp + TSX ; copy stack pointer + EOR Frnxth ; EOR with invert byte + BNE LoopDone ; if <> 0 clear stack and back to interpreter loop + + ; loop condition wasn't met so do it again +LoopAlways + LDA LAB_STAK+2,X ; get current line low byte + STA Clinel ; save current line low byte + LDA LAB_STAK+3,X ; get current line high byte + STA Clineh ; save current line high byte + LDA LAB_STAK+4,X ; get BASIC execute pointer low byte + STA Bpntrl ; save BASIC execute pointer low byte + LDA LAB_STAK+5,X ; get BASIC execute pointer high byte + STA Bpntrh ; save BASIC execute pointer high byte + JSR LAB_GBYT ; scan memory + JMP LAB_15C2 ; go do interpreter inner loop + + ; clear stack and back to interpreter loop +LoopDone + INX ; dump DO token + INX ; dump current line low byte + INX ; dump current line high byte + INX ; dump BASIC execute pointer low byte + INX ; dump BASIC execute pointer high byte + TXS ; correct stack + JMP LAB_DATA ; go perform DATA (find : or [EOL]) + +; do the return without gosub error + +LAB_16F4 + LDX #$04 ; error code $04 ("RETURN without GOSUB" error) + .byte $2C ; makes next line BIT LAB_0EA2 + +LAB_16F7 ; do undefined statement error + LDX #$0E ; error code $0E ("Undefined statement" error) + JMP LAB_XERR ; do error #X, then warm start + +; perform RETURN + +LAB_RETURN + BNE LAB_16E5 ; exit if following token (to allow syntax error) + +LAB_16E8 + PLA ; dump calling routine return address + PLA ; dump calling routine return address + PLA ; pull token + CMP #TK_GOSUB ; compare with GOSUB token + BNE LAB_16F4 ; branch if no matching GOSUB + +LAB_16FF + PLA ; pull current line low byte + STA Clinel ; save current line low byte + PLA ; pull current line high byte + STA Clineh ; save current line high byte + PLA ; pull BASIC execute pointer low byte + STA Bpntrl ; save BASIC execute pointer low byte + PLA ; pull BASIC execute pointer high byte + STA Bpntrh ; save BASIC execute pointer high byte + + ; now do the DATA statement as we could be returning into + ; the middle of an ON GOSUB n,m,p,q line + ; (the return address used by the DATA statement is the one + ; pushed before the GOSUB was executed!) + +; perform DATA + +LAB_DATA + JSR LAB_SNBS ; scan for next BASIC statement ([:] or [EOL]) + + ; set BASIC execute pointer +LAB_170F + TYA ; copy index to A + CLC ; clear carry for add + ADC Bpntrl ; add BASIC execute pointer low byte + STA Bpntrl ; save BASIC execute pointer low byte + BCC LAB_1719 ; skip next if no carry + + INC Bpntrh ; else increment BASIC execute pointer high byte +LAB_1719 + RTS + +LAB_16FC + JMP LAB_SNER ; do syntax error then warm start + +; scan for next BASIC statement ([:] or [EOL]) +; returns Y as index to [:] or [EOL] + +LAB_SNBS + LDX #':' ; set look for character = ":" + .byte $2C ; makes next line BIT $00A2 + +; scan for next BASIC line +; returns Y as index to [EOL] + +LAB_SNBL + LDX #$00 ; set alt search character = [EOL] + LDY #$00 ; set search character = [EOL] + STY Asrch ; store search character +LAB_1725 + TXA ; get alt search character + EOR Asrch ; toggle search character, effectively swap with $00 + STA Asrch ; save swapped search character +LAB_172D + LDA (Bpntrl),Y ; get next byte + BEQ LAB_1719 ; exit if null [EOL] + + CMP Asrch ; compare with search character + BEQ LAB_1719 ; exit if found + + INY ; increment index + CMP #$22 ; compare current character with open quote + BNE LAB_172D ; if not open quote go get next character + + BEQ LAB_1725 ; if found go swap search character for alt search character + +; perform IF + +LAB_IF + JSR LAB_EVEX ; evaluate the expression + JSR LAB_GBYT ; scan memory + CMP #TK_THEN ; compare with THEN token + BEQ LAB_174B ; if it was THEN go do IF + + ; wasn't IF .. THEN so must be IF .. GOTO + CMP #TK_GOTO ; compare with GOTO token + BNE LAB_16FC ; if it wasn't GOTO go do syntax error + + LDX Bpntrl ; save the basic pointer low byte + LDY Bpntrh ; save the basic pointer high byte + JSR LAB_IGBY ; increment and scan memory + BCS LAB_16FC ; if not numeric go do syntax error + + STX Bpntrl ; restore the basic pointer low byte + STY Bpntrh ; restore the basic pointer high byte +LAB_174B + LDA FAC1_e ; get FAC1 exponent + BEQ LAB_174E ; if the result was zero go look for an ELSE + + JSR LAB_IGBY ; else increment and scan memory + BCS LAB_174D ; if not numeric go do var or keyword + +LAB_174C + JMP LAB_GOTO ; else was numeric so do GOTO n + + ; is var or keyword +LAB_174D + CMP #TK_RETURN ; compare the byte with the token for RETURN + BNE LAB_174G ; if it wasn't RETURN go interpret BASIC code from (Bpntrl) + ; and return to this code to process any following code + + JMP LAB_1602 ; else it was RETURN so interpret BASIC code from (Bpntrl) + ; but don't return here + +LAB_174G + JSR LAB_15FF ; interpret BASIC code from (Bpntrl) + +; the IF was executed and there may be a following ELSE so the code needs to return +; here to check and ignore the ELSE if present + + LDY #$00 ; clear the index + LDA (Bpntrl),Y ; get the next BASIC byte + CMP #TK_ELSE ; compare it with the token for ELSE + BEQ LAB_DATA ; if ELSE ignore the following statement + +; there was no ELSE so continue execution of IF THEN [: ]. any +; following ELSE will, correctly, cause a syntax error + + RTS ; else return to the interpreter inner loop + +; perform ELSE after IF + +LAB_174E + LDY #$00 ; clear the BASIC byte index + LDX #$01 ; clear the nesting depth +LAB_1750 + INY ; increment the BASIC byte index + LDA (Bpntrl),Y ; get the next BASIC byte + BEQ LAB_1753 ; if EOL go add the pointer and return + + CMP #TK_IF ; compare the byte with the token for IF + BNE LAB_1752 ; if not IF token skip the depth increment + + INX ; else increment the nesting depth .. + BNE LAB_1750 ; .. and continue looking + +LAB_1752 + CMP #TK_ELSE ; compare the byte with the token for ELSE + BNE LAB_1750 ; if not ELSE token continue looking + + DEX ; was ELSE so decrement the nesting depth + BNE LAB_1750 ; loop if still nested + + INY ; increment the BASIC byte index past the ELSE + +; found the matching ELSE, now do <{n|statement}> + +LAB_1753 + TYA ; else copy line index to A + CLC ; clear carry for add + ADC Bpntrl ; add the BASIC execute pointer low byte + STA Bpntrl ; save the BASIC execute pointer low byte + BCC LAB_1754 ; branch if no overflow to high byte + + INC Bpntrh ; else increment the BASIC execute pointer high byte +LAB_1754 + JSR LAB_GBYT ; scan memory + BCC LAB_174C ; if numeric do GOTO n + ; the code will return to the interpreter loop at the + ; tail end of the GOTO + + JMP LAB_15FF ; interpret BASIC code from (Bpntrl) + ; the code will return to the interpreter loop at the + ; tail end of the + +; perform REM, skip (rest of) line + +LAB_REM + JSR LAB_SNBL ; scan for next BASIC line + JMP LAB_170F ; go set BASIC execute pointer and return, branch always + +LAB_16FD + JMP LAB_SNER ; do syntax error then warm start + +; perform ON + +LAB_ON + CMP #TK_IRQ ; was it IRQ token ? + BNE LAB_NOIN ; if not go check NMI + + JMP LAB_SIRQ ; else go set-up IRQ + +LAB_NOIN + CMP #TK_NMI ; was it NMI token ? + BNE LAB_NONM ; if not go do normal ON command + + JMP LAB_SNMI ; else go set-up NMI + +LAB_NONM + JSR LAB_GTBY ; get byte parameter + PHA ; push GOTO/GOSUB token + CMP #TK_GOSUB ; compare with GOSUB token + BEQ LAB_176B ; branch if GOSUB + + CMP #TK_GOTO ; compare with GOTO token +LAB_1767 + BNE LAB_16FD ; if not GOTO do syntax error then warm start + + +; next character was GOTO or GOSUB + +LAB_176B + DEC FAC1_3 ; decrement index (byte value) + BNE LAB_1773 ; branch if not zero + + PLA ; pull GOTO/GOSUB token + JMP LAB_1602 ; go execute it + +LAB_1773 + JSR LAB_IGBY ; increment and scan memory + JSR LAB_GFPN ; get fixed-point number into temp integer (skip this n) + ; (we could LDX #',' and JSR LAB_SNBL+2, then we + ; just BNE LAB_176B for the loop. should be quicker .. + ; no we can't, what if we meet a colon or [EOL]?) + CMP #$2C ; compare next character with "," + BEQ LAB_176B ; loop if "," + +LAB_177E + PLA ; else pull keyword token (run out of options) + ; also dump +/-1 pointer low byte and exit +LAB_177F + RTS + +; takes n * 106 + 11 cycles where n is the number of digits + +; get fixed-point number into temp integer + +LAB_GFPN + LDX #$00 ; clear reg + STX Itempl ; clear temporary integer low byte +LAB_1785 + STX Itemph ; save temporary integer high byte + BCS LAB_177F ; return if carry set, end of scan, character was + ; not 0-9 + + CPX #$19 ; compare high byte with $19 + TAY ; ensure Zb = 0 if the branch is taken + BCS LAB_1767 ; branch if >=, makes max line # 63999 because next + ; bit does *$0A, = 64000, compare at target will fail + ; and do syntax error + + SBC #'0'-1 ; subtract "0", $2F + carry, from byte + TAY ; copy binary digit + LDA Itempl ; get temporary integer low byte + ASL ; *2 low byte + ROL Itemph ; *2 high byte + ASL ; *2 low byte + ROL Itemph ; *2 high byte, *4 + ADC Itempl ; + low byte, *5 + STA Itempl ; save it + TXA ; get high byte copy to A + ADC Itemph ; + high byte, *5 + ASL Itempl ; *2 low byte, *10d + ROL ; *2 high byte, *10d + TAX ; copy high byte back to X + TYA ; get binary digit back + ADC Itempl ; add number low byte + STA Itempl ; save number low byte + BCC LAB_17B3 ; if no overflow to high byte get next character + + INX ; else increment high byte +LAB_17B3 + JSR LAB_IGBY ; increment and scan memory + JMP LAB_1785 ; loop for next character + +; perform DEC + +LAB_DEC + LDA #LAB_259C ; set +/-1 pointer high byte (both the same) + JSR LAB_246C ; add (AY) to FAC1 + JSR LAB_PFAC ; pack FAC1 into variable (Lvarpl) + + JSR LAB_GBYT ; scan memory + CMP #',' ; compare with "," + BNE LAB_177E ; exit if not "," (either end or error) + + ; was "," so another INCR variable to do + JSR LAB_IGBY ; increment and scan memory + JMP LAB_17B7 ; go do next var + +IncrErr + JMP LAB_1ABC ; do "Type mismatch" error then warm start + +; perform LET + +LAB_LET + JSR LAB_GVAR ; get var address + STA Lvarpl ; save var address low byte + STY Lvarph ; save var address high byte + LDA #TK_EQUAL ; get = token + JSR LAB_SCCA ; scan for CHR$(A), else do syntax error then warm start + LDA Dtypef ; get data type flag, $FF=string, $00=numeric + PHA ; push data type flag + JSR LAB_EVEX ; evaluate expression + PLA ; pop data type flag + ROL ; set carry if type = string + JSR LAB_CKTM ; type match check, set C for string + BNE LAB_17D5 ; branch if string + + JMP LAB_PFAC ; pack FAC1 into variable (Lvarpl) and return + +; string LET + +LAB_17D5 + LDY #$02 ; set index to pointer high byte + LDA (des_pl),Y ; get string pointer high byte + CMP Sstorh ; compare bottom of string space high byte + BCC LAB_17F4 ; if less assign value and exit (was in program memory) + + BNE LAB_17E6 ; branch if > + ; else was equal so compare low bytes + DEY ; decrement index + LDA (des_pl),Y ; get pointer low byte + CMP Sstorl ; compare bottom of string space low byte + BCC LAB_17F4 ; if less assign value and exit (was in program memory) + + ; pointer was >= to bottom of string space pointer +LAB_17E6 + LDY des_ph ; get descriptor pointer high byte + CPY Svarh ; compare start of vars high byte + BCC LAB_17F4 ; branch if less (descriptor is on stack) + + BNE LAB_17FB ; branch if greater (descriptor is not on stack) + + ; else high bytes were equal so .. + LDA des_pl ; get descriptor pointer low byte + CMP Svarl ; compare start of vars low byte + BCS LAB_17FB ; branch if >= (descriptor is not on stack) + +LAB_17F4 + LDA des_pl ; get descriptor pointer low byte + LDY des_ph ; get descriptor pointer high byte + JMP LAB_1811 ; clean stack, copy descriptor to variable and return + + ; make space and copy string +LAB_17FB + LDY #$00 ; index to length + LDA (des_pl),Y ; get string length + JSR LAB_209C ; copy string + LDA des_2l ; get descriptor pointer low byte + LDY des_2h ; get descriptor pointer high byte + STA ssptr_l ; save descriptor pointer low byte + STY ssptr_h ; save descriptor pointer high byte + JSR LAB_228A ; copy string from descriptor (sdescr) to (Sutill) + LDA #FAC1_e ; get descriptor pointer high byte + + ; clean stack and assign value to string variable +LAB_1811 + STA des_2l ; save descriptor_2 pointer low byte + STY des_2h ; save descriptor_2 pointer high byte + JSR LAB_22EB ; clean descriptor stack, YA = pointer + LDY #$00 ; index to length + LDA (des_2l),Y ; get string length + STA (Lvarpl),Y ; copy to let string variable + INY ; index to string pointer low byte + LDA (des_2l),Y ; get string pointer low byte + STA (Lvarpl),Y ; copy to let string variable + INY ; index to string pointer high byte + LDA (des_2l),Y ; get string pointer high byte + STA (Lvarpl),Y ; copy to let string variable + RTS + +; perform GET + +LAB_GET + JSR LAB_GVAR ; get var address + STA Lvarpl ; save var address low byte + STY Lvarph ; save var address high byte + JSR INGET ; get input byte + LDX Dtypef ; get data type flag, $FF=string, $00=numeric + BMI LAB_GETS ; go get string character + + ; was numeric get + TAY ; copy character to Y + JSR LAB_1FD0 ; convert Y to byte in FAC1 + JMP LAB_PFAC ; pack FAC1 into variable (Lvarpl) and return + +LAB_GETS + PHA ; save character + LDA #$01 ; string is single byte + BCS LAB_IsByte ; branch if byte received + + PLA ; string is null +LAB_IsByte + JSR LAB_MSSP ; make string space A bytes long A=$AC=length, + ; X=$AD=Sutill=ptr low byte, Y=$AE=Sutilh=ptr high byte + BEQ LAB_NoSt ; skip store if null string + + PLA ; get character back + LDY #$00 ; clear index + STA (str_pl),Y ; save byte in string (byte IS string!) +LAB_NoSt + JSR LAB_RTST ; check for space on descriptor stack then put address + ; and length on descriptor stack and update stack pointers + + JMP LAB_17D5 ; do string LET and return + +; perform PRINT + +LAB_1829 + JSR LAB_18C6 ; print string from Sutill/Sutilh +LAB_182C + JSR LAB_GBYT ; scan memory + +; PRINT + +LAB_PRINT + BEQ LAB_CRLF ; if nothing following just print CR/LF + +LAB_1831 + CMP #TK_TAB ; compare with TAB( token + BEQ LAB_18A2 ; go do TAB/SPC + + CMP #TK_SPC ; compare with SPC( token + BEQ LAB_18A2 ; go do TAB/SPC + + CMP #',' ; compare with "," + BEQ LAB_188B ; go do move to next TAB mark + + CMP #';' ; compare with ";" + BEQ LAB_18BD ; if ";" continue with PRINT processing + + JSR LAB_EVEX ; evaluate expression + BIT Dtypef ; test data type flag, $FF=string, $00=numeric + BMI LAB_1829 ; branch if string + + JSR LAB_296E ; convert FAC1 to string + JSR LAB_20AE ; print " terminated string to Sutill/Sutilh + LDY #$00 ; clear index + +; don't check fit if terminal width byte is zero + + LDA TWidth ; get terminal width byte + BEQ LAB_185E ; skip check if zero + + SEC ; set carry for subtract + SBC TPos ; subtract terminal position + SBC (des_pl),Y ; subtract string length + BCS LAB_185E ; branch if less than terminal width + + JSR LAB_CRLF ; else print CR/LF +LAB_185E + JSR LAB_18C6 ; print string from Sutill/Sutilh + BEQ LAB_182C ; always go continue processing line + +; CR/LF return to BASIC from BASIC input handler + +LAB_1866 + LDA #$00 ; clear byte + STA Ibuffs,X ; null terminate input + LDX #Ibuffs ; set Y to buffer start-1 high byte + +; print CR/LF + +LAB_CRLF + LDA #$0D ; load [CR] + JSR LAB_PRNA ; go print the character + LDA #$0A ; load [LF] + BNE LAB_PRNA ; go print the character and return, branch always + +LAB_188B + LDA TPos ; get terminal position + CMP Iclim ; compare with input column limit + BCC LAB_1897 ; branch if less + + JSR LAB_CRLF ; else print CR/LF (next line) + BNE LAB_18BD ; continue with PRINT processing (branch always) + +LAB_1897 + SEC ; set carry for subtract +LAB_1898 + SBC TabSiz ; subtract TAB size + BCS LAB_1898 ; loop if result was +ve + + EOR #$FF ; complement it + ADC #$01 ; +1 (twos complement) + BNE LAB_18B6 ; always print A spaces (result is never $00) + + ; do TAB/SPC +LAB_18A2 + PHA ; save token + JSR LAB_SGBY ; scan and get byte parameter + CMP #$29 ; is next character ) + BNE LAB_1910 ; if not do syntax error then warm start + + PLA ; get token back + CMP #TK_TAB ; was it TAB ? + BNE LAB_18B7 ; if not go do SPC + + ; calculate TAB offset + TXA ; copy integer value to A + SBC TPos ; subtract terminal position + BCC LAB_18BD ; branch if result was < 0 (can't TAB backwards) + + ; print A spaces +LAB_18B6 + TAX ; copy result to X +LAB_18B7 + TXA ; set flags on size for SPC + BEQ LAB_18BD ; branch if result was = $0, already here + + ; print X spaces +LAB_18BA + JSR LAB_18E0 ; print " " + DEX ; decrement count + BNE LAB_18BA ; loop if not all done + + ; continue with PRINT processing +LAB_18BD + JSR LAB_IGBY ; increment and scan memory + BNE LAB_1831 ; if more to print go do it + + RTS + +; print null terminated string from memory + +LAB_18C3 + JSR LAB_20AE ; print " terminated string to Sutill/Sutilh + +; print string from Sutill/Sutilh + +LAB_18C6 + JSR LAB_22B6 ; pop string off descriptor stack, or from top of string + ; space returns with A = length, X=$71=pointer low byte, + ; Y=$72=pointer high byte + LDY #$00 ; reset index + TAX ; copy length to X + BEQ LAB_188C ; exit (RTS) if null string + +LAB_18CD + + LDA (ut1_pl),Y ; get next byte + JSR LAB_PRNA ; go print the character + INY ; increment index + DEX ; decrement count + BNE LAB_18CD ; loop if not done yet + + RTS + + ; Print single format character +; print " " + +LAB_18E0 + LDA #$20 ; load " " + .byte $2C ; change next line to BIT LAB_3FA9 + +; print "?" character + +LAB_18E3 + LDA #$3F ; load "?" character + +; print character in A +; now includes the null handler +; also includes infinite line length code +; note! some routines expect this one to exit with Zb=0 + +LAB_PRNA + CMP #' ' ; compare with " " + BCC LAB_18F9 ; branch if less (non printing) + + ; else printable character + PHA ; save the character + +; don't check fit if terminal width byte is zero + + LDA TWidth ; get terminal width + BNE LAB_18F0 ; branch if not zero (not infinite length) + +; is "infinite line" so check TAB position + + LDA TPos ; get position + SBC TabSiz ; subtract TAB size, carry set by CMP #$20 above + BNE LAB_18F7 ; skip reset if different + + STA TPos ; else reset position + BEQ LAB_18F7 ; go print character + +LAB_18F0 + CMP TPos ; compare with terminal character position + BNE LAB_18F7 ; branch if not at end of line + + JSR LAB_CRLF ; else print CR/LF +LAB_18F7 + INC TPos ; increment terminal position + PLA ; get character back +LAB_18F9 + JSR V_OUTP ; output byte via output vector + CMP #$0D ; compare with [CR] + BNE LAB_188A ; branch if not [CR] + + ; else print nullct nulls after the [CR] + STX TempB ; save buffer index + LDX Nullct ; get null count + BEQ LAB_1886 ; branch if no nulls + + LDA #$00 ; load [NULL] +LAB_1880 + JSR LAB_PRNA ; go print the character + DEX ; decrement count + BNE LAB_1880 ; loop if not all done + + LDA #$0D ; restore the character (and set the flags) +LAB_1886 + STX TPos ; clear terminal position (X always = zero when we get here) + LDX TempB ; restore buffer index +LAB_188A + AND #$FF ; set the flags +LAB_188C + RTS + +; handle bad input data + +LAB_1904 + LDA Imode ; get input mode flag, $00=INPUT, $00=READ + BPL LAB_1913 ; branch if INPUT (go do redo) + + LDA Dlinel ; get current DATA line low byte + LDY Dlineh ; get current DATA line high byte + STA Clinel ; save current line low byte + STY Clineh ; save current line high byte +LAB_1910 + JMP LAB_SNER ; do syntax error then warm start + + ; mode was INPUT +LAB_1913 + LDA #LAB_REDO ; point to redo message (high addr) + JSR LAB_18C3 ; print null terminated string from memory + LDA Cpntrl ; get continue pointer low byte + LDY Cpntrh ; get continue pointer high byte + STA Bpntrl ; save BASIC execute pointer low byte + STY Bpntrh ; save BASIC execute pointer high byte + RTS + +; perform INPUT + +LAB_INPUT + CMP #$22 ; compare next byte with open quote + BNE LAB_1934 ; branch if no prompt string + + JSR LAB_1BC1 ; print "..." string + LDA #$3B ; load A with ";" + JSR LAB_SCCA ; scan for CHR$(A), else do syntax error then warm start + JSR LAB_18C6 ; print string from Sutill/Sutilh + + ; done with prompt, now get data +LAB_1934 + JSR LAB_CKRN ; check not Direct, back here if ok + JSR LAB_INLN ; print "? " and get BASIC input + LDA #$00 ; set mode = INPUT + CMP Ibuffs ; test first byte in buffer + BNE LAB_1953 ; branch if not null input + + CLC ; was null input so clear carry to exit program + JMP LAB_1647 ; go do BREAK exit + +; perform READ + +LAB_READ + LDX Dptrl ; get DATA pointer low byte + LDY Dptrh ; get DATA pointer high byte + LDA #$80 ; set mode = READ + +LAB_1953 + STA Imode ; set input mode flag, $00=INPUT, $80=READ + STX Rdptrl ; save READ pointer low byte + STY Rdptrh ; save READ pointer high byte + + ; READ or INPUT next variable from list +LAB_195B + JSR LAB_GVAR ; get (var) address + STA Lvarpl ; save address low byte + STY Lvarph ; save address high byte + LDA Bpntrl ; get BASIC execute pointer low byte + LDY Bpntrh ; get BASIC execute pointer high byte + STA Itempl ; save as temporary integer low byte + STY Itemph ; save as temporary integer high byte + LDX Rdptrl ; get READ pointer low byte + LDY Rdptrh ; get READ pointer high byte + STX Bpntrl ; set BASIC execute pointer low byte + STY Bpntrh ; set BASIC execute pointer high byte + JSR LAB_GBYT ; scan memory + BNE LAB_1988 ; branch if not null + + ; pointer was to null entry + BIT Imode ; test input mode flag, $00=INPUT, $80=READ + BMI LAB_19DD ; branch if READ + + ; mode was INPUT + JSR LAB_18E3 ; print "?" character (double ? for extended input) + JSR LAB_INLN ; print "? " and get BASIC input + STX Bpntrl ; set BASIC execute pointer low byte + STY Bpntrh ; set BASIC execute pointer high byte +LAB_1985 + JSR LAB_GBYT ; scan memory +LAB_1988 + BIT Dtypef ; test data type flag, $FF=string, $00=numeric + BPL LAB_19B0 ; branch if numeric + + ; else get string + STA Srchc ; save search character + CMP #$22 ; was it " ? + BEQ LAB_1999 ; branch if so + + LDA #':' ; else search character is ":" + STA Srchc ; set new search character + LDA #',' ; other search character is "," + CLC ; clear carry for add +LAB_1999 + STA Asrch ; set second search character + LDA Bpntrl ; get BASIC execute pointer low byte + LDY Bpntrh ; get BASIC execute pointer high byte + + ADC #$00 ; c is =1 if we came via the BEQ LAB_1999, else =0 + BCC LAB_19A4 ; branch if no execute pointer low byte rollover + + INY ; else increment high byte +LAB_19A4 + JSR LAB_20B4 ; print Srchc or Asrch terminated string to Sutill/Sutilh + JSR LAB_23F3 ; restore BASIC execute pointer from temp (Btmpl/Btmph) + JSR LAB_17D5 ; go do string LET + JMP LAB_19B6 ; go check string terminator + + ; get numeric INPUT +LAB_19B0 + JSR LAB_2887 ; get FAC1 from string + JSR LAB_PFAC ; pack FAC1 into (Lvarpl) +LAB_19B6 + JSR LAB_GBYT ; scan memory + BEQ LAB_19C5 ; branch if null (last entry) + + CMP #',' ; else compare with "," + BEQ LAB_19C2 ; branch if "," + + JMP LAB_1904 ; else go handle bad input data + + ; got good input data +LAB_19C2 + JSR LAB_IGBY ; increment and scan memory +LAB_19C5 + LDA Bpntrl ; get BASIC execute pointer low byte (temp READ/INPUT ptr) + LDY Bpntrh ; get BASIC execute pointer high byte (temp READ/INPUT ptr) + STA Rdptrl ; save for now + STY Rdptrh ; save for now + LDA Itempl ; get temporary integer low byte (temp BASIC execute ptr) + LDY Itemph ; get temporary integer high byte (temp BASIC execute ptr) + STA Bpntrl ; set BASIC execute pointer low byte + STY Bpntrh ; set BASIC execute pointer high byte + JSR LAB_GBYT ; scan memory + BEQ LAB_1A03 ; if null go do extra ignored message + + JSR LAB_1C01 ; else scan for "," , else do syntax error then warm start + JMP LAB_195B ; go INPUT next variable from list + + ; find next DATA statement or do "Out of DATA" error +LAB_19DD + JSR LAB_SNBS ; scan for next BASIC statement ([:] or [EOL]) + INY ; increment index + TAX ; copy character ([:] or [EOL]) + BNE LAB_19F6 ; branch if [:] + + LDX #$06 ; set for "Out of DATA" error + INY ; increment index, now points to next line pointer high byte + LDA (Bpntrl),Y ; get next line pointer high byte + BEQ LAB_1A54 ; branch if end (eventually does error X) + + INY ; increment index + LDA (Bpntrl),Y ; get next line # low byte + STA Dlinel ; save current DATA line low byte + INY ; increment index + LDA (Bpntrl),Y ; get next line # high byte + INY ; increment index + STA Dlineh ; save current DATA line high byte +LAB_19F6 + LDA (Bpntrl),Y ; get byte + INY ; increment index + TAX ; copy to X + JSR LAB_170F ; set BASIC execute pointer + CPX #TK_DATA ; compare with "DATA" token + BEQ LAB_1985 ; was "DATA" so go do next READ + + BNE LAB_19DD ; go find next statement if not "DATA" + +; end of INPUT/READ routine + +LAB_1A03 + LDA Rdptrl ; get temp READ pointer low byte + LDY Rdptrh ; get temp READ pointer high byte + LDX Imode ; get input mode flag, $00=INPUT, $80=READ + BPL LAB_1A0E ; branch if INPUT + + JMP LAB_1624 ; save AY as DATA pointer and return + + ; we were getting INPUT +LAB_1A0E + LDY #$00 ; clear index + LDA (Rdptrl),Y ; get next byte + BNE LAB_1A1B ; error if not end of INPUT + + RTS + + ; user typed too much +LAB_1A1B + LDA #LAB_IMSG ; point to extra ignored message (high addr) + JMP LAB_18C3 ; print null terminated string from memory and return + +; search the stack for FOR activity +; exit with z=1 if FOR else exit with z=0 + +LAB_11A1 + TSX ; copy stack pointer + INX ; +1 pass return address + INX ; +2 pass return address + INX ; +3 pass calling routine return address + INX ; +4 pass calling routine return address +LAB_11A6 + LDA LAB_STAK+1,X ; get token byte from stack + CMP #TK_FOR ; is it FOR token + BNE LAB_11CE ; exit if not FOR token + + ; was FOR token + LDA Frnxth ; get var pointer for FOR/NEXT high byte + BNE LAB_11BB ; branch if not null + + LDA LAB_STAK+2,X ; get FOR variable pointer low byte + STA Frnxtl ; save var pointer for FOR/NEXT low byte + LDA LAB_STAK+3,X ; get FOR variable pointer high byte + STA Frnxth ; save var pointer for FOR/NEXT high byte +LAB_11BB + CMP LAB_STAK+3,X ; compare var pointer with stacked var pointer (high byte) + BNE LAB_11C7 ; branch if no match + + LDA Frnxtl ; get var pointer for FOR/NEXT low byte + CMP LAB_STAK+2,X ; compare var pointer with stacked var pointer (low byte) + BEQ LAB_11CE ; exit if match found + +LAB_11C7 + TXA ; copy index + CLC ; clear carry for add + ADC #$10 ; add FOR stack use size + TAX ; copy back to index + BNE LAB_11A6 ; loop if not at start of stack + +LAB_11CE + RTS + +; perform NEXT + +LAB_NEXT + BNE LAB_1A46 ; branch if NEXT var + + LDY #$00 ; else clear Y + BEQ LAB_1A49 ; branch always (no variable to search for) + +; NEXT var + +LAB_1A46 + JSR LAB_GVAR ; get variable address +LAB_1A49 + STA Frnxtl ; store variable pointer low byte + STY Frnxth ; store variable pointer high byte + ; (both cleared if no variable defined) + JSR LAB_11A1 ; search the stack for FOR activity + BEQ LAB_1A56 ; branch if found + + LDX #$00 ; else set error $00 ("NEXT without FOR" error) +LAB_1A54 + BEQ LAB_1ABE ; do error #X, then warm start + +LAB_1A56 + TXS ; set stack pointer, X set by search, dumps return addresses + + TXA ; copy stack pointer + SEC ; set carry for subtract + SBC #$F7 ; point to TO var + STA ut2_pl ; save pointer to TO var for compare + ADC #$FB ; point to STEP var + + LDY #>LAB_STAK ; point to stack page high byte + JSR LAB_UFAC ; unpack memory (STEP value) into FAC1 + TSX ; get stack pointer back + LDA LAB_STAK+8,X ; get step sign + STA FAC1_s ; save FAC1 sign (b7) + LDA Frnxtl ; get FOR variable pointer low byte + LDY Frnxth ; get FOR variable pointer high byte + JSR LAB_246C ; add (FOR variable) to FAC1 + JSR LAB_PFAC ; pack FAC1 into (FOR variable) + LDY #>LAB_STAK ; point to stack page high byte + JSR LAB_27FA ; compare FAC1 with (Y,ut2_pl) (TO value) + TSX ; get stack pointer back + CMP LAB_STAK+8,X ; compare step sign + BEQ LAB_1A9B ; branch if = (loop complete) + + ; loop back and do it all again + LDA LAB_STAK+$0D,X ; get FOR line low byte + STA Clinel ; save current line low byte + LDA LAB_STAK+$0E,X ; get FOR line high byte + STA Clineh ; save current line high byte + LDA LAB_STAK+$10,X ; get BASIC execute pointer low byte + STA Bpntrl ; save BASIC execute pointer low byte + LDA LAB_STAK+$0F,X ; get BASIC execute pointer high byte + STA Bpntrh ; save BASIC execute pointer high byte +LAB_1A98 + JMP LAB_15C2 ; go do interpreter inner loop + + ; loop complete so carry on +LAB_1A9B + TXA ; stack copy to A + ADC #$0F ; add $10 ($0F+carry) to dump FOR structure + TAX ; copy back to index + TXS ; copy to stack pointer + JSR LAB_GBYT ; scan memory + CMP #',' ; compare with "," + BNE LAB_1A98 ; branch if not "," (go do interpreter inner loop) + + ; was "," so another NEXT variable to do + JSR LAB_IGBY ; else increment and scan memory + JSR LAB_1A46 ; do NEXT (var) + +; evaluate expression and check is numeric, else do type mismatch + +LAB_EVNM + JSR LAB_EVEX ; evaluate expression + +; check if source is numeric, else do type mismatch + +LAB_CTNM + CLC ; destination is numeric + .byte $24 ; makes next line BIT $38 + +; check if source is string, else do type mismatch + +LAB_CTST + SEC ; required type is string + +; type match check, set C for string, clear C for numeric + +LAB_CKTM + BIT Dtypef ; test data type flag, $FF=string, $00=numeric + BMI LAB_1ABA ; branch if data type is string + + ; else data type was numeric + BCS LAB_1ABC ; if required type is string do type mismatch error +LAB_1AB9 + RTS + + ; data type was string, now check required type +LAB_1ABA + BCS LAB_1AB9 ; exit if required type is string + + ; else do type mismatch error +LAB_1ABC + LDX #$18 ; error code $18 ("Type mismatch" error) +LAB_1ABE + JMP LAB_XERR ; do error #X, then warm start + +; evaluate expression + +LAB_EVEX + LDX Bpntrl ; get BASIC execute pointer low byte + BNE LAB_1AC7 ; skip next if not zero + + DEC Bpntrh ; else decrement BASIC execute pointer high byte +LAB_1AC7 + DEC Bpntrl ; decrement BASIC execute pointer low byte + +LAB_EVEZ + LDA #$00 ; set null precedence (flag done) +LAB_1ACC + PHA ; push precedence byte + LDA #$02 ; 2 bytes + JSR LAB_1212 ; check room on stack for A bytes + JSR LAB_GVAL ; get value from line + LDA #$00 ; clear A + STA comp_f ; clear compare function flag +LAB_1ADB + JSR LAB_GBYT ; scan memory +LAB_1ADE + SEC ; set carry for subtract + SBC #TK_GT ; subtract token for > (lowest comparison function) + BCC LAB_1AFA ; branch if < TK_GT + + CMP #$03 ; compare with ">" to "<" tokens + BCS LAB_1AFA ; branch if >= TK_SGN (highest evaluation function +1) + + ; was token for > = or < (A = 0, 1 or 2) + CMP #$01 ; compare with token for = + ROL ; *2, b0 = carry (=1 if token was = or <) + ; (A = 0, 3 or 5) + EOR #$01 ; toggle b0 + ; (A = 1, 2 or 4. 1 if >, 2 if =, 4 if <) + EOR comp_f ; EOR with compare function flag bits + CMP comp_f ; compare with compare function flag + BCC LAB_1B53 ; if <(comp_f) do syntax error then warm start + ; was more than one <, = or >) + + STA comp_f ; save new compare function flag + JSR LAB_IGBY ; increment and scan memory + JMP LAB_1ADE ; go do next character + + ; token is < ">" or > "<" tokens +LAB_1AFA + LDX comp_f ; get compare function flag + BNE LAB_1B2A ; branch if compare function + + BCS LAB_1B78 ; go do functions + + ; else was < TK_GT so is operator or lower + ADC #TK_GT-TK_PLUS ; add # of operators (+, -, *, /, ^, AND, OR or EOR) + BCC LAB_1B78 ; branch if < + operator + + ; carry was set so token was +, -, *, /, ^, AND, OR or EOR + BNE LAB_1B0B ; branch if not + token + + BIT Dtypef ; test data type flag, $FF=string, $00=numeric + BPL LAB_1B0B ; branch if not string + + ; will only be $00 if type is string and token was + + JMP LAB_224D ; add strings, string 1 is in descriptor des_pl, string 2 + ; is in line, and return + +LAB_1B0B + STA ut1_pl ; save it + ASL ; *2 + ADC ut1_pl ; *3 + TAY ; copy to index +LAB_1B13 + PLA ; pull previous precedence + CMP LAB_OPPT,Y ; compare with precedence byte + BCS LAB_1B7D ; branch if A >= + + JSR LAB_CTNM ; check if source is numeric, else do type mismatch +LAB_1B1C + PHA ; save precedence +LAB_1B1D + JSR LAB_1B43 ; get vector, execute function then continue evaluation + PLA ; restore precedence + LDY prstk ; get precedence stacked flag + BPL LAB_1B3C ; branch if stacked values + + TAX ; copy precedence (set flags) + BEQ LAB_1B9D ; exit if done + + BNE LAB_1B86 ; else pop FAC2 and return, branch always + +LAB_1B2A + ROL Dtypef ; shift data type flag into Cb + TXA ; copy compare function flag + STA Dtypef ; clear data type flag, X is 0xxx xxxx + ROL ; shift data type into compare function byte b0 + LDX Bpntrl ; get BASIC execute pointer low byte + BNE LAB_1B34 ; branch if no underflow + + DEC Bpntrh ; else decrement BASIC execute pointer high byte +LAB_1B34 + DEC Bpntrl ; decrement BASIC execute pointer low byte +TK_LT_PLUS = TK_LT-TK_PLUS + LDY #TK_LT_PLUS*3 ; set offset to last operator entry + STA comp_f ; save new compare function flag + BNE LAB_1B13 ; branch always + +LAB_1B3C + CMP LAB_OPPT,Y ;.compare with stacked function precedence + BCS LAB_1B86 ; branch if A >=, pop FAC2 and return + + BCC LAB_1B1C ; branch always + +;.get vector, execute function then continue evaluation + +LAB_1B43 + LDA LAB_OPPT+2,Y ; get function vector high byte + PHA ; onto stack + LDA LAB_OPPT+1,Y ; get function vector low byte + PHA ; onto stack + ; now push sign, round FAC1 and put on stack + JSR LAB_1B5B ; function will return here, then the next RTS will call + ; the function + LDA comp_f ; get compare function flag + PHA ; push compare evaluation byte + LDA LAB_OPPT,Y ; get precedence byte + JMP LAB_1ACC ; continue evaluating expression + +LAB_1B53 + JMP LAB_SNER ; do syntax error then warm start + +; push sign, round FAC1 and put on stack + +LAB_1B5B + PLA ; get return addr low byte + STA ut1_pl ; save it + INC ut1_pl ; increment it (was ret-1 pushed? yes!) + ; note! no check is made on the high byte! if the calling + ; routine assembles to a page edge then this all goes + ; horribly wrong !!! + PLA ; get return addr high byte + STA ut1_ph ; save it + LDA FAC1_s ; get FAC1 sign (b7) + PHA ; push sign + +; round FAC1 and put on stack + +LAB_1B66 + JSR LAB_27BA ; round FAC1 + LDA FAC1_3 ; get FAC1 mantissa3 + PHA ; push on stack + LDA FAC1_2 ; get FAC1 mantissa2 + PHA ; push on stack + LDA FAC1_1 ; get FAC1 mantissa1 + PHA ; push on stack + LDA FAC1_e ; get FAC1 exponent + PHA ; push on stack + JMP (ut1_pl) ; return, sort of + +; do functions + +LAB_1B78 + LDY #$FF ; flag function + PLA ; pull precedence byte +LAB_1B7B + BEQ LAB_1B9D ; exit if done + +LAB_1B7D + CMP #$64 ; compare previous precedence with $64 + BEQ LAB_1B84 ; branch if was $64 (< function) + + JSR LAB_CTNM ; check if source is numeric, else do type mismatch +LAB_1B84 + STY prstk ; save precedence stacked flag + + ; pop FAC2 and return +LAB_1B86 + PLA ; pop byte + LSR ; shift out comparison evaluation lowest bit + STA Cflag ; save comparison evaluation flag + PLA ; pop exponent + STA FAC2_e ; save FAC2 exponent + PLA ; pop mantissa1 + STA FAC2_1 ; save FAC2 mantissa1 + PLA ; pop mantissa2 + STA FAC2_2 ; save FAC2 mantissa2 + PLA ; pop mantissa3 + STA FAC2_3 ; save FAC2 mantissa3 + PLA ; pop sign + STA FAC2_s ; save FAC2 sign (b7) + EOR FAC1_s ; EOR FAC1 sign (b7) + STA FAC_sc ; save sign compare (FAC1 EOR FAC2) +LAB_1B9D + LDA FAC1_e ; get FAC1 exponent + RTS + +; print "..." string to string util area + +LAB_1BC1 + LDA Bpntrl ; get BASIC execute pointer low byte + LDY Bpntrh ; get BASIC execute pointer high byte + ADC #$00 ; add carry to low byte + BCC LAB_1BCA ; branch if no overflow + + INY ; increment high byte +LAB_1BCA + JSR LAB_20AE ; print " terminated string to Sutill/Sutilh + JMP LAB_23F3 ; restore BASIC execute pointer from temp and return + +; get value from line + +LAB_GVAL + JSR LAB_IGBY ; increment and scan memory + BCS LAB_1BAC ; branch if not numeric character + + ; else numeric string found (e.g. 123) +LAB_1BA9 + JMP LAB_2887 ; get FAC1 from string and return + +; get value from line .. continued + + ; wasn't a number so .. +LAB_1BAC + TAX ; set the flags + BMI LAB_1BD0 ; if -ve go test token values + + ; else it is either a string, number, variable or () + CMP #'$' ; compare with "$" + BEQ LAB_1BA9 ; branch if "$", hex number + + CMP #'%' ; else compare with "%" + BEQ LAB_1BA9 ; branch if "%", binary number + + CMP #'.' ; compare with "." + BEQ LAB_1BA9 ; if so get FAC1 from string and return (e.g. was .123) + + ; it wasn't any sort of number so .. + CMP #$22 ; compare with " + BEQ LAB_1BC1 ; branch if open quote + + ; wasn't any sort of number so .. + +; evaluate expression within parentheses + + CMP #'(' ; compare with "(" + BNE LAB_1C18 ; if not "(" get (var), return value in FAC1 and $ flag + +LAB_1BF7 + JSR LAB_EVEZ ; evaluate expression, no decrement + +; all the 'scan for' routines return the character after the sought character + +; scan for ")" , else do syntax error then warm start + +LAB_1BFB + LDA #$29 ; load A with ")" + +; scan for CHR$(A) , else do syntax error then warm start + +LAB_SCCA + LDY #$00 ; clear index + CMP (Bpntrl),Y ; check next byte is = A + BNE LAB_SNER ; if not do syntax error then warm start + + JMP LAB_IGBY ; increment and scan memory then return + +; scan for "(" , else do syntax error then warm start + +LAB_1BFE + LDA #$28 ; load A with "(" + BNE LAB_SCCA ; scan for CHR$(A), else do syntax error then warm start + ; (branch always) + +; scan for "," , else do syntax error then warm start + +LAB_1C01 + LDA #$2C ; load A with "," + BNE LAB_SCCA ; scan for CHR$(A), else do syntax error then warm start + ; (branch always) + +; syntax error then warm start + +LAB_SNER + LDX #$02 ; error code $02 ("Syntax" error) + JMP LAB_XERR ; do error #X, then warm start + +; get value from line .. continued +; do tokens + +LAB_1BD0 + CMP #TK_MINUS ; compare with token for - + BEQ LAB_1C11 ; branch if - token (do set-up for functions) + + ; wasn't -n so .. + CMP #TK_PLUS ; compare with token for + + BEQ LAB_GVAL ; branch if + token (+n = n so ignore leading +) + + CMP #TK_NOT ; compare with token for NOT + BNE LAB_1BE7 ; branch if not token for NOT + + ; was NOT token +TK_EQUAL_PLUS = TK_EQUAL-TK_PLUS + LDY #TK_EQUAL_PLUS*3 ; offset to NOT function + BNE LAB_1C13 ; do set-up for function then execute (branch always) + +; do = compare + +LAB_EQUAL + JSR LAB_EVIR ; evaluate integer expression (no sign check) + LDA FAC1_3 ; get FAC1 mantissa3 + EOR #$FF ; invert it + TAY ; copy it + LDA FAC1_2 ; get FAC1 mantissa2 + EOR #$FF ; invert it + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +; get value from line .. continued + + ; wasn't +, -, or NOT so .. +LAB_1BE7 + CMP #TK_FN ; compare with token for FN + BNE LAB_1BEE ; branch if not token for FN + + JMP LAB_201E ; go evaluate FNx + +; get value from line .. continued + + ; wasn't +, -, NOT or FN so .. +LAB_1BEE + SBC #TK_SGN ; subtract with token for SGN + BCS LAB_1C27 ; if a function token go do it + + JMP LAB_SNER ; else do syntax error + +; set-up for functions + +LAB_1C11 +TK_GT_PLUS = TK_GT-TK_PLUS + LDY #TK_GT_PLUS*3 ; set offset from base to > operator +LAB_1C13 + PLA ; dump return address low byte + PLA ; dump return address high byte + JMP LAB_1B1D ; execute function then continue evaluation + +; variable name set-up +; get (var), return value in FAC_1 and $ flag + +LAB_1C18 + JSR LAB_GVAR ; get (var) address + STA FAC1_2 ; save address low byte in FAC1 mantissa2 + STY FAC1_3 ; save address high byte in FAC1 mantissa3 + LDX Dtypef ; get data type flag, $FF=string, $00=numeric + BMI LAB_1C25 ; if string then return (does RTS) + +LAB_1C24 + JMP LAB_UFAC ; unpack memory (AY) into FAC1 + +LAB_1C25 + RTS + +; get value from line .. continued +; only functions left so .. + +; set up function references + +; new for V2.0+ this replaces a lot of IF .. THEN .. ELSEIF .. THEN .. that was needed +; to process function calls. now the function vector is computed and pushed on the stack +; and the preprocess offset is read. if the preprocess offset is non zero then the vector +; is calculated and the routine called, if not this routine just does RTS. whichever +; happens the RTS at the end of this routine, or the end of the preprocess routine, calls +; the function code + +; this also removes some less than elegant code that was used to bypass type checking +; for functions that returned strings + +LAB_1C27 + ASL ; *2 (2 bytes per function address) + TAY ; copy to index + + LDA LAB_FTBM,Y ; get function jump vector high byte + PHA ; push functions jump vector high byte + LDA LAB_FTBL,Y ; get function jump vector low byte + PHA ; push functions jump vector low byte + + LDA LAB_FTPM,Y ; get function pre process vector high byte + BEQ LAB_1C56 ; skip pre process if null vector + + PHA ; push functions pre process vector high byte + LDA LAB_FTPL,Y ; get function pre process vector low byte + PHA ; push functions pre process vector low byte + +LAB_1C56 + RTS ; do function, or pre process, call + +; process string expression in parenthesis + +LAB_PPFS + JSR LAB_1BF7 ; process expression in parenthesis + JMP LAB_CTST ; check if source is string then do function, + ; else do type mismatch + +; process numeric expression in parenthesis + +LAB_PPFN + JSR LAB_1BF7 ; process expression in parenthesis + JMP LAB_CTNM ; check if source is numeric then do function, + ; else do type mismatch + +; set numeric data type and increment BASIC execute pointer + +LAB_PPBI + LSR Dtypef ; clear data type flag, $FF=string, $00=numeric + JMP LAB_IGBY ; increment and scan memory then do function + +; process string for LEFT$, RIGHT$ or MID$ + +LAB_LRMS + JSR LAB_EVEZ ; evaluate (should be string) expression + JSR LAB_1C01 ; scan for ",", else do syntax error then warm start + JSR LAB_CTST ; check if source is string, else do type mismatch + + PLA ; get function jump vector low byte + TAX ; save functions jump vector low byte + PLA ; get function jump vector high byte + TAY ; save functions jump vector high byte + LDA des_ph ; get descriptor pointer high byte + PHA ; push string pointer high byte + LDA des_pl ; get descriptor pointer low byte + PHA ; push string pointer low byte + TYA ; get function jump vector high byte back + PHA ; save functions jump vector high byte + TXA ; get function jump vector low byte back + PHA ; save functions jump vector low byte + JSR LAB_GTBY ; get byte parameter + TXA ; copy byte parameter to A + RTS ; go do function + +; process numeric expression(s) for BIN$ or HEX$ + +LAB_BHSS + JSR LAB_EVEZ ; process expression + JSR LAB_CTNM ; check if source is numeric, else do type mismatch + LDA FAC1_e ; get FAC1 exponent + CMP #$98 ; compare with exponent = 2^24 + BCS LAB_BHER ; branch if n>=2^24 (is too big) + + JSR LAB_2831 ; convert FAC1 floating-to-fixed + LDX #$02 ; 3 bytes to do +LAB_CFAC + LDA FAC1_1,X ; get byte from FAC1 + STA nums_1,X ; save byte to temp + DEX ; decrement index + BPL LAB_CFAC ; copy FAC1 mantissa to temp + + JSR LAB_GBYT ; get next BASIC byte + LDX #$00 ; set default to no leading "0"s + CMP #')' ; compare with close bracket + BEQ LAB_1C54 ; if ")" go do rest of function + + JSR LAB_SCGB ; scan for "," and get byte + JSR LAB_GBYT ; get last byte back + CMP #')' ; is next character ) + BNE LAB_BHER ; if not ")" go do error + +LAB_1C54 + RTS ; else do function + +LAB_BHER + JMP LAB_FCER ; do function call error then warm start + +; perform EOR + +; added operator format is the same as AND or OR, precedence is the same as OR + +; this bit worked first time but it took a while to sort out the operator table +; pointers and offsets afterwards! + +LAB_EOR + JSR GetFirst ; get first integer expression (no sign check) + EOR XOAw_l ; EOR with expression 1 low byte + TAY ; save in Y + LDA FAC1_2 ; get FAC1 mantissa2 + EOR XOAw_h ; EOR with expression 1 high byte + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +; perform OR + +LAB_OR + JSR GetFirst ; get first integer expression (no sign check) + ORA XOAw_l ; OR with expression 1 low byte + TAY ; save in Y + LDA FAC1_2 ; get FAC1 mantissa2 + ORA XOAw_h ; OR with expression 1 high byte + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +; perform AND + +LAB_AND + JSR GetFirst ; get first integer expression (no sign check) + AND XOAw_l ; AND with expression 1 low byte + TAY ; save in Y + LDA FAC1_2 ; get FAC1 mantissa2 + AND XOAw_h ; AND with expression 1 high byte + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +; get first value for OR, AND or EOR + +GetFirst + JSR LAB_EVIR ; evaluate integer expression (no sign check) + LDA FAC1_2 ; get FAC1 mantissa2 + STA XOAw_h ; save it + LDA FAC1_3 ; get FAC1 mantissa3 + STA XOAw_l ; save it + JSR LAB_279B ; copy FAC2 to FAC1 (get 2nd value in expression) + JSR LAB_EVIR ; evaluate integer expression (no sign check) + LDA FAC1_3 ; get FAC1 mantissa3 +LAB_1C95 + RTS + +; perform comparisons + +; do < compare + +LAB_LTHAN + JSR LAB_CKTM ; type match check, set C for string + BCS LAB_1CAE ; branch if string + + ; do numeric < compare + LDA FAC2_s ; get FAC2 sign (b7) + ORA #$7F ; set all non sign bits + AND FAC2_1 ; and FAC2 mantissa1 (AND in sign bit) + STA FAC2_1 ; save FAC2 mantissa1 + LDA #FAC2_e ; set pointer high byte to FAC2 + JSR LAB_27F8 ; compare FAC1 with FAC2 (AY) + TAX ; copy result + JMP LAB_1CE1 ; go evaluate result + + ; do string < compare +LAB_1CAE + LSR Dtypef ; clear data type flag, $FF=string, $00=numeric + DEC comp_f ; clear < bit in compare function flag + JSR LAB_22B6 ; pop string off descriptor stack, or from top of string + ; space returns with A = length, X=pointer low byte, + ; Y=pointer high byte + STA str_ln ; save length + STX str_pl ; save string pointer low byte + STY str_ph ; save string pointer high byte + LDA FAC2_2 ; get descriptor pointer low byte + LDY FAC2_3 ; get descriptor pointer high byte + JSR LAB_22BA ; pop (YA) descriptor off stack or from top of string space + ; returns with A = length, X=pointer low byte, + ; Y=pointer high byte + STX FAC2_2 ; save string pointer low byte + STY FAC2_3 ; save string pointer high byte + TAX ; copy length + SEC ; set carry for subtract + SBC str_ln ; subtract string 1 length + BEQ LAB_1CD6 ; branch if str 1 length = string 2 length + + LDA #$01 ; set str 1 length > string 2 length + BCC LAB_1CD6 ; branch if so + + LDX str_ln ; get string 1 length + LDA #$FF ; set str 1 length < string 2 length +LAB_1CD6 + STA FAC1_s ; save length compare + LDY #$FF ; set index + INX ; adjust for loop +LAB_1CDB + INY ; increment index + DEX ; decrement count + BNE LAB_1CE6 ; branch if still bytes to do + + LDX FAC1_s ; get length compare back +LAB_1CE1 + BMI LAB_1CF2 ; branch if str 1 < str 2 + + CLC ; flag str 1 <= str 2 + BCC LAB_1CF2 ; go evaluate result + +LAB_1CE6 + LDA (FAC2_2),Y ; get string 2 byte + CMP (FAC1_1),Y ; compare with string 1 byte + BEQ LAB_1CDB ; loop if bytes = + + LDX #$FF ; set str 1 < string 2 + BCS LAB_1CF2 ; branch if so + + LDX #$01 ; set str 1 > string 2 +LAB_1CF2 + INX ; x = 0, 1 or 2 + TXA ; copy to A + ROL ; *2 (1, 2 or 4) + AND Cflag ; AND with comparison evaluation flag + BEQ LAB_1CFB ; branch if 0 (compare is false) + + LDA #$FF ; else set result true +LAB_1CFB + JMP LAB_27DB ; save A as integer byte and return + +LAB_1CFE + JSR LAB_1C01 ; scan for ",", else do syntax error then warm start + +; perform DIM + +LAB_DIM + TAX ; copy "DIM" flag to X + JSR LAB_1D10 ; search for variable + JSR LAB_GBYT ; scan memory + BNE LAB_1CFE ; scan for "," and loop if not null + + RTS + +; perform << (left shift) + +LAB_LSHIFT + JSR GetPair ; get integer expression and byte (no sign check) + LDA FAC1_2 ; get expression high byte + LDX TempB ; get shift count + BEQ NoShift ; branch if zero + + CPX #$10 ; compare bit count with 16d + BCS TooBig ; branch if >= + +Ls_loop + ASL FAC1_3 ; shift low byte + ROL ; shift high byte + DEX ; decrement bit count + BNE Ls_loop ; loop if shift not complete + + LDY FAC1_3 ; get expression low byte + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +; perform >> (right shift) + +LAB_RSHIFT + JSR GetPair ; get integer expression and byte (no sign check) + LDA FAC1_2 ; get expression high byte + LDX TempB ; get shift count + BEQ NoShift ; branch if zero + + CPX #$10 ; compare bit count with 16d + BCS TooBig ; branch if >= + +Rs_loop + LSR ; shift high byte + ROR FAC1_3 ; shift low byte + DEX ; decrement bit count + BNE Rs_loop ; loop if shift not complete + +NoShift + LDY FAC1_3 ; get expression low byte + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +TooBig + LDA #$00 ; clear high byte + TAY ; copy to low byte + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +GetPair + JSR LAB_EVBY ; evaluate byte expression, result in X + STX TempB ; save it + JSR LAB_279B ; copy FAC2 to FAC1 (get 2nd value in expression) + JMP LAB_EVIR ; evaluate integer expression (no sign check) + +; search for variable + +; return pointer to variable in Cvaral/Cvarah + +LAB_GVAR + LDX #$00 ; set DIM flag = $00 + JSR LAB_GBYT ; scan memory (1st character) +LAB_1D10 + STX Defdim ; save DIM flag +LAB_1D12 + STA Varnm1 ; save 1st character + AND #$7F ; clear FN flag bit + JSR LAB_CASC ; check byte, return C=0 if<"A" or >"Z" + BCS LAB_1D1F ; branch if ok + + JMP LAB_SNER ; else syntax error then warm start + + ; was variable name so .. +LAB_1D1F + LDX #$00 ; clear 2nd character temp + STX Dtypef ; clear data type flag, $FF=string, $00=numeric + JSR LAB_IGBY ; increment and scan memory (2nd character) + BCC LAB_1D2D ; branch if character = "0"-"9" (ok) + + ; 2nd character wasn't "0" to "9" so .. + JSR LAB_CASC ; check byte, return C=0 if<"A" or >"Z" + BCC LAB_1D38 ; branch if <"A" or >"Z" (go check if string) + +LAB_1D2D + TAX ; copy 2nd character + + ; ignore further (valid) characters in the variable name +LAB_1D2E + JSR LAB_IGBY ; increment and scan memory (3rd character) + BCC LAB_1D2E ; loop if character = "0"-"9" (ignore) + + JSR LAB_CASC ; check byte, return C=0 if<"A" or >"Z" + BCS LAB_1D2E ; loop if character = "A"-"Z" (ignore) + + ; check if string variable +LAB_1D38 + CMP #'$' ; compare with "$" + BNE LAB_1D47 ; branch if not string + +; to introduce a new variable type (% suffix for integers say) then this branch +; will need to go to that check and then that branch, if it fails, go to LAB_1D47 + + ; type is string + LDA #$FF ; set data type = string + STA Dtypef ; set data type flag, $FF=string, $00=numeric + TXA ; get 2nd character back + ORA #$80 ; set top bit (indicate string var) + TAX ; copy back to 2nd character temp + JSR LAB_IGBY ; increment and scan memory + +; after we have determined the variable type we need to come back here to determine +; if it's an array of type. this would plug in a%(b[,c[,d]])) integer arrays nicely + + +LAB_1D47 ; gets here with character after var name in A + STX Varnm2 ; save 2nd character + ORA Sufnxf ; or with subscript/FNX flag (or FN name) + CMP #'(' ; compare with "(" + BNE LAB_1D53 ; branch if not "(" + + JMP LAB_1E17 ; go find, or make, array + +; either find or create var +; var name (1st two characters only!) is in Varnm1,Varnm2 + + ; variable name wasn't var(... so look for plain var +LAB_1D53 + LDA #$00 ; clear A + STA Sufnxf ; clear subscript/FNX flag + LDA Svarl ; get start of vars low byte + LDX Svarh ; get start of vars high byte + LDY #$00 ; clear index +LAB_1D5D + STX Vrschh ; save search address high byte +LAB_1D5F + STA Vrschl ; save search address low byte + CPX Sarryh ; compare high address with var space end + BNE LAB_1D69 ; skip next compare if <> + + ; high addresses were = so compare low addresses + CMP Sarryl ; compare low address with var space end + BEQ LAB_1D8B ; if not found go make new var + +LAB_1D69 + LDA Varnm1 ; get 1st character of var to find + CMP (Vrschl),Y ; compare with variable name 1st character + BNE LAB_1D77 ; branch if no match + + ; 1st characters match so compare 2nd characters + LDA Varnm2 ; get 2nd character of var to find + INY ; index to point to variable name 2nd character + CMP (Vrschl),Y ; compare with variable name 2nd character + BEQ LAB_1DD7 ; branch if match (found var) + + DEY ; else decrement index (now = $00) +LAB_1D77 + CLC ; clear carry for add + LDA Vrschl ; get search address low byte + ADC #$06 ; +6 (offset to next var name) + BCC LAB_1D5F ; loop if no overflow to high byte + + INX ; else increment high byte + BNE LAB_1D5D ; loop always (RAM doesn't extend to $FFFF !) + +; check byte, return C=0 if<"A" or >"Z" or "a" to "z" + +LAB_CASC + CMP #'a' ; compare with "a" + BCS LAB_1D83 ; go check <"z"+1 + +; check byte, return C=0 if<"A" or >"Z" + +LAB_1D82 + CMP #'A' ; compare with "A" + BCC LAB_1D8A ; exit if less + + ; carry is set + SBC #$5B ; subtract "Z"+1 + SEC ; set carry + SBC #$A5 ; subtract $A5 (restore byte) + ; carry clear if byte>$5A +LAB_1D8A + RTS + +LAB_1D83 + SBC #$7B ; subtract "z"+1 + SEC ; set carry + SBC #$85 ; subtract $85 (restore byte) + ; carry clear if byte>$7A + RTS + + ; reached end of variable mem without match + ; .. so create new variable +LAB_1D8B + PLA ; pop return address low byte + PHA ; push return address low byte +LAB_1C18p2 = LAB_1C18+2 + CMP #LAB_1D96 ; high byte point to $00,$00 + RTS + + ; create new numeric variable +LAB_1D98 + LDA Sarryl ; get var mem end low byte + LDY Sarryh ; get var mem end high byte + STA Ostrtl ; save old block start low byte + STY Ostrth ; save old block start high byte + LDA Earryl ; get array mem end low byte + LDY Earryh ; get array mem end high byte + STA Obendl ; save old block end low byte + STY Obendh ; save old block end high byte + CLC ; clear carry for add + ADC #$06 ; +6 (space for one var) + BCC LAB_1DAE ; branch if no overflow to high byte + + INY ; else increment high byte +LAB_1DAE + STA Nbendl ; set new block end low byte + STY Nbendh ; set new block end high byte + JSR LAB_11CF ; open up space in memory + LDA Nbendl ; get new start low byte + LDY Nbendh ; get new start high byte (-$100) + INY ; correct high byte + STA Sarryl ; save new var mem end low byte + STY Sarryh ; save new var mem end high byte + LDY #$00 ; clear index + LDA Varnm1 ; get var name 1st character + STA (Vrschl),Y ; save var name 1st character + INY ; increment index + LDA Varnm2 ; get var name 2nd character + STA (Vrschl),Y ; save var name 2nd character + LDA #$00 ; clear A + INY ; increment index + STA (Vrschl),Y ; initialise var byte + INY ; increment index + STA (Vrschl),Y ; initialise var byte + INY ; increment index + STA (Vrschl),Y ; initialise var byte + INY ; increment index + STA (Vrschl),Y ; initialise var byte + + ; found a match for var ((Vrschl) = ptr) +LAB_1DD7 + LDA Vrschl ; get var address low byte + CLC ; clear carry for add + ADC #$02 ; +2 (offset past var name bytes) + LDY Vrschh ; get var address high byte + BCC LAB_1DE1 ; branch if no overflow from add + + INY ; else increment high byte +LAB_1DE1 + STA Cvaral ; save current var address low byte + STY Cvarah ; save current var address high byte + RTS + +; set-up array pointer (Adatal/h) to first element in array +; set Adatal,Adatah to Astrtl,Astrth+2*Dimcnt+#$05 + +LAB_1DE6 + LDA Dimcnt ; get # of dimensions (1, 2 or 3) + ASL ; *2 (also clears the carry !) + ADC #$05 ; +5 (result is 7, 9 or 11 here) + ADC Astrtl ; add array start pointer low byte + LDY Astrth ; get array pointer high byte + BCC LAB_1DF2 ; branch if no overflow + + INY ; else increment high byte +LAB_1DF2 + STA Adatal ; save array data pointer low byte + STY Adatah ; save array data pointer high byte + RTS + +; evaluate integer expression + +LAB_EVIN + JSR LAB_IGBY ; increment and scan memory + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch + +; evaluate integer expression (no check) + +LAB_EVPI + LDA FAC1_s ; get FAC1 sign (b7) + BMI LAB_1E12 ; do function call error if -ve + +; evaluate integer expression (no sign check) + +LAB_EVIR + LDA FAC1_e ; get FAC1 exponent + CMP #$90 ; compare with exponent = 2^16 (n>2^15) + BCC LAB_1E14 ; branch if n<2^16 (is ok) + + LDA #LAB_1DF7 ; set pointer high byte to -32768 + JSR LAB_27F8 ; compare FAC1 with (AY) +LAB_1E12 + BNE LAB_FCER ; if <> do function call error then warm start + +LAB_1E14 + JMP LAB_2831 ; convert FAC1 floating-to-fixed and return + +; find or make array + +LAB_1E17 + LDA Defdim ; get DIM flag + PHA ; push it + LDA Dtypef ; get data type flag, $FF=string, $00=numeric + PHA ; push it + LDY #$00 ; clear dimensions count + +; now get the array dimension(s) and stack it (them) before the data type and DIM flag + +LAB_1E1F + TYA ; copy dimensions count + PHA ; save it + LDA Varnm2 ; get array name 2nd byte + PHA ; save it + LDA Varnm1 ; get array name 1st byte + PHA ; save it + JSR LAB_EVIN ; evaluate integer expression + PLA ; pull array name 1st byte + STA Varnm1 ; restore array name 1st byte + PLA ; pull array name 2nd byte + STA Varnm2 ; restore array name 2nd byte + PLA ; pull dimensions count + TAY ; restore it + TSX ; copy stack pointer + LDA LAB_STAK+2,X ; get DIM flag + PHA ; push it + LDA LAB_STAK+1,X ; get data type flag + PHA ; push it + LDA FAC1_2 ; get this dimension size high byte + STA LAB_STAK+2,X ; stack before flag bytes + LDA FAC1_3 ; get this dimension size low byte + STA LAB_STAK+1,X ; stack before flag bytes + INY ; increment dimensions count + JSR LAB_GBYT ; scan memory + CMP #',' ; compare with "," + BEQ LAB_1E1F ; if found go do next dimension + + STY Dimcnt ; store dimensions count + JSR LAB_1BFB ; scan for ")" , else do syntax error then warm start + PLA ; pull data type flag + STA Dtypef ; restore data type flag, $FF=string, $00=numeric + PLA ; pull DIM flag + STA Defdim ; restore DIM flag + LDX Sarryl ; get array mem start low byte + LDA Sarryh ; get array mem start high byte + +; now check to see if we are at the end of array memory (we would be if there were +; no arrays). + +LAB_1E5C + STX Astrtl ; save as array start pointer low byte + STA Astrth ; save as array start pointer high byte + CMP Earryh ; compare with array mem end high byte + BNE LAB_1E68 ; branch if not reached array mem end + + CPX Earryl ; else compare with array mem end low byte + BEQ LAB_1EA1 ; go build array if not found + + ; search for array +LAB_1E68 + LDY #$00 ; clear index + LDA (Astrtl),Y ; get array name first byte + INY ; increment index to second name byte + CMP Varnm1 ; compare with this array name first byte + BNE LAB_1E77 ; branch if no match + + LDA Varnm2 ; else get this array name second byte + CMP (Astrtl),Y ; compare with array name second byte + BEQ LAB_1E8D ; array found so branch + + ; no match +LAB_1E77 + INY ; increment index + LDA (Astrtl),Y ; get array size low byte + CLC ; clear carry for add + ADC Astrtl ; add array start pointer low byte + TAX ; copy low byte to X + INY ; increment index + LDA (Astrtl),Y ; get array size high byte + ADC Astrth ; add array mem pointer high byte + BCC LAB_1E5C ; if no overflow go check next array + +; do array bounds error + +LAB_1E85 + LDX #$10 ; error code $10 ("Array bounds" error) + .byte $2C ; makes next bit BIT LAB_08A2 + +; do function call error + +LAB_FCER + LDX #$08 ; error code $08 ("Function call" error) +LAB_1E8A + JMP LAB_XERR ; do error #X, then warm start + + ; found array, are we trying to dimension it? +LAB_1E8D + LDX #$12 ; set error $12 ("Double dimension" error) + LDA Defdim ; get DIM flag + BNE LAB_1E8A ; if we are trying to dimension it do error #X, then warm + ; start + +; found the array and we're not dimensioning it so we must find an element in it + + JSR LAB_1DE6 ; set-up array pointer (Adatal/h) to first element in array + ; (Astrtl,Astrth points to start of array) + LDA Dimcnt ; get dimensions count + LDY #$04 ; set index to array's # of dimensions + CMP (Astrtl),Y ; compare with no of dimensions + BNE LAB_1E85 ; if wrong do array bounds error, could do "Wrong + ; dimensions" error here .. if we want a different + ; error message + + JMP LAB_1F28 ; found array so go get element + ; (could jump to LAB_1F28 as all LAB_1F24 does is take + ; Dimcnt and save it at (Astrtl),Y which is already the + ; same or we would have taken the BNE) + + ; array not found, so build it +LAB_1EA1 + JSR LAB_1DE6 ; set-up array pointer (Adatal/h) to first element in array + ; (Astrtl,Astrth points to start of array) + JSR LAB_121F ; check available memory, "Out of memory" error if no room + ; addr to check is in AY (low/high) + LDY #$00 ; clear Y (don't need to clear A) + STY Aspth ; clear array data size high byte + LDA Varnm1 ; get variable name 1st byte + STA (Astrtl),Y ; save array name 1st byte + INY ; increment index + LDA Varnm2 ; get variable name 2nd byte + STA (Astrtl),Y ; save array name 2nd byte + LDA Dimcnt ; get dimensions count + LDY #$04 ; index to dimension count + STY Asptl ; set array data size low byte (four bytes per element) + STA (Astrtl),Y ; set array's dimensions count + + ; now calculate the size of the data space for the array + CLC ; clear carry for add (clear on subsequent loops) +LAB_1EC0 + LDX #$0B ; set default dimension value low byte + LDA #$00 ; set default dimension value high byte + BIT Defdim ; test default DIM flag + BVC LAB_1ED0 ; branch if b6 of Defdim is clear + + PLA ; else pull dimension value low byte + ADC #$01 ; +1 (allow for zeroeth element) + TAX ; copy low byte to X + PLA ; pull dimension value high byte + ADC #$00 ; add carry from low byte + +LAB_1ED0 + INY ; index to dimension value high byte + STA (Astrtl),Y ; save dimension value high byte + INY ; index to dimension value high byte + TXA ; get dimension value low byte + STA (Astrtl),Y ; save dimension value low byte + JSR LAB_1F7C ; does XY = (Astrtl),Y * (Asptl) + STX Asptl ; save array data size low byte + STA Aspth ; save array data size high byte + LDY ut1_pl ; restore index (saved by subroutine) + DEC Dimcnt ; decrement dimensions count + BNE LAB_1EC0 ; loop while not = 0 + + ADC Adatah ; add size high byte to first element high byte + ; (carry is always clear here) + BCS LAB_1F45 ; if overflow go do "Out of memory" error + + STA Adatah ; save end of array high byte + TAY ; copy end high byte to Y + TXA ; get array size low byte + ADC Adatal ; add array start low byte + BCC LAB_1EF3 ; branch if no carry + + INY ; else increment end of array high byte + BEQ LAB_1F45 ; if overflow go do "Out of memory" error + + ; set-up mostly complete, now zero the array +LAB_1EF3 + JSR LAB_121F ; check available memory, "Out of memory" error if no room + ; addr to check is in AY (low/high) + STA Earryl ; save array mem end low byte + STY Earryh ; save array mem end high byte + LDA #$00 ; clear byte for array clear + INC Aspth ; increment array size high byte (now block count) + LDY Asptl ; get array size low byte (now index to block) + BEQ LAB_1F07 ; branch if low byte = $00 + +LAB_1F02 + DEY ; decrement index (do 0 to n-1) + STA (Adatal),Y ; zero byte + BNE LAB_1F02 ; loop until this block done + +LAB_1F07 + DEC Adatah ; decrement array pointer high byte + DEC Aspth ; decrement block count high byte + BNE LAB_1F02 ; loop until all blocks done + + INC Adatah ; correct for last loop + SEC ; set carry for subtract + LDY #$02 ; index to array size low byte + LDA Earryl ; get array mem end low byte + SBC Astrtl ; subtract array start low byte + STA (Astrtl),Y ; save array size low byte + INY ; index to array size high byte + LDA Earryh ; get array mem end high byte + SBC Astrth ; subtract array start high byte + STA (Astrtl),Y ; save array size high byte + LDA Defdim ; get default DIM flag + BNE LAB_1F7B ; exit (RET) if this was a DIM command + + ; else, find element + INY ; index to # of dimensions + +LAB_1F24 + LDA (Astrtl),Y ; get array's dimension count + STA Dimcnt ; save it + +; we have found, or built, the array. now we need to find the element + +LAB_1F28 + LDA #$00 ; clear byte + STA Asptl ; clear array data pointer low byte +LAB_1F2C + STA Aspth ; save array data pointer high byte + INY ; increment index (point to array bound high byte) + PLA ; pull array index low byte + TAX ; copy to X + STA FAC1_2 ; save index low byte to FAC1 mantissa2 + PLA ; pull array index high byte + STA FAC1_3 ; save index high byte to FAC1 mantissa3 + CMP (Astrtl),Y ; compare with array bound high byte + BCC LAB_1F48 ; branch if within bounds + + BNE LAB_1F42 ; if outside bounds do array bounds error + + ; else high byte was = so test low bytes + INY ; index to array bound low byte + TXA ; get array index low byte + CMP (Astrtl),Y ; compare with array bound low byte + BCC LAB_1F49 ; branch if within bounds + +LAB_1F42 + JMP LAB_1E85 ; else do array bounds error + +LAB_1F45 + JMP LAB_OMER ; do "Out of memory" error then warm start + +LAB_1F48 + INY ; index to array bound low byte +LAB_1F49 + LDA Aspth ; get array data pointer high byte + ORA Asptl ; OR with array data pointer low byte + BEQ LAB_1F5A ; branch if array data pointer = null (skip multiply) + + JSR LAB_1F7C ; does XY = (Astrtl),Y * (Asptl) + TXA ; get result low byte + ADC FAC1_2 ; add index low byte from FAC1 mantissa2 + TAX ; save result low byte + TYA ; get result high byte + LDY ut1_pl ; restore index +LAB_1F5A + ADC FAC1_3 ; add index high byte from FAC1 mantissa3 + STX Asptl ; save array data pointer low byte + DEC Dimcnt ; decrement dimensions count + BNE LAB_1F2C ; loop if dimensions still to do + + ASL Asptl ; array data pointer low byte * 2 + ROL ; array data pointer high byte * 2 + ASL Asptl ; array data pointer low byte * 4 + ROL ; array data pointer high byte * 4 + TAY ; copy high byte + LDA Asptl ; get low byte + ADC Adatal ; add array data start pointer low byte + STA Cvaral ; save as current var address low byte + TYA ; get high byte back + ADC Adatah ; add array data start pointer high byte + STA Cvarah ; save as current var address high byte + TAY ; copy high byte to Y + LDA Cvaral ; get current var address low byte +LAB_1F7B + RTS + +; does XY = (Astrtl),Y * (Asptl) + +LAB_1F7C + STY ut1_pl ; save index + LDA (Astrtl),Y ; get dimension size low byte + STA dims_l ; save dimension size low byte + DEY ; decrement index + LDA (Astrtl),Y ; get dimension size high byte + STA dims_h ; save dimension size high byte + + LDA #$10 ; count = $10 (16 bit multiply) + STA numbit ; save bit count + LDX #$00 ; clear result low byte + LDY #$00 ; clear result high byte +LAB_1F8F + TXA ; get result low byte + ASL ; *2 + TAX ; save result low byte + TYA ; get result high byte + ROL ; *2 + TAY ; save result high byte + BCS LAB_1F45 ; if overflow go do "Out of memory" error + + ASL Asptl ; shift multiplier low byte + ROL Aspth ; shift multiplier high byte + BCC LAB_1FA8 ; skip add if no carry + + CLC ; else clear carry for add + TXA ; get result low byte + ADC dims_l ; add dimension size low byte + TAX ; save result low byte + TYA ; get result high byte + ADC dims_h ; add dimension size high byte + TAY ; save result high byte + BCS LAB_1F45 ; if overflow go do "Out of memory" error + +LAB_1FA8 + DEC numbit ; decrement bit count + BNE LAB_1F8F ; loop until all done + + RTS + +; perform FRE() + +LAB_FRE + LDA Dtypef ; get data type flag, $FF=string, $00=numeric + BPL LAB_1FB4 ; branch if numeric + + JSR LAB_22B6 ; pop string off descriptor stack, or from top of string + ; space returns with A = length, X=$71=pointer low byte, + ; Y=$72=pointer high byte + + ; FRE(n) was numeric so do this +LAB_1FB4 + JSR LAB_GARB ; go do garbage collection + SEC ; set carry for subtract + LDA Sstorl ; get bottom of string space low byte + SBC Earryl ; subtract array mem end low byte + TAY ; copy result to Y + LDA Sstorh ; get bottom of string space high byte + SBC Earryh ; subtract array mem end high byte + +; save and convert integer AY to FAC1 + +LAB_AYFC + LSR Dtypef ; clear data type flag, $FF=string, $00=numeric + STA FAC1_1 ; save FAC1 mantissa1 + STY FAC1_2 ; save FAC1 mantissa2 + LDX #$90 ; set exponent=2^16 (integer) + JMP LAB_27E3 ; set exp=X, clear FAC1_3, normalise and return + +; perform POS() + +LAB_POS + LDY TPos ; get terminal position + +; convert Y to byte in FAC1 + +LAB_1FD0 + LDA #$00 ; clear high byte + BEQ LAB_AYFC ; always save and convert integer AY to FAC1 and return + +; check not Direct (used by DEF and INPUT) + +LAB_CKRN + LDX Clineh ; get current line high byte + INX ; increment it + BNE LAB_1F7B ; return if can continue not direct mode + + ; else do illegal direct error +LAB_1FD9 + LDX #$16 ; error code $16 ("Illegal direct" error) +LAB_1FDB + JMP LAB_XERR ; go do error #X, then warm start + +; perform DEF + +LAB_DEF + JSR LAB_200B ; check FNx syntax + STA func_l ; save function pointer low byte + STY func_h ; save function pointer high byte + JSR LAB_CKRN ; check not Direct (back here if ok) + JSR LAB_1BFE ; scan for "(" , else do syntax error then warm start + LDA #$80 ; set flag for FNx + STA Sufnxf ; save subscript/FNx flag + JSR LAB_GVAR ; get (var) address + JSR LAB_CTNM ; check if source is numeric, else do type mismatch + JSR LAB_1BFB ; scan for ")" , else do syntax error then warm start + LDA #TK_EQUAL ; get = token + JSR LAB_SCCA ; scan for CHR$(A), else do syntax error then warm start + LDA Cvarah ; get current var address high byte + PHA ; push it + LDA Cvaral ; get current var address low byte + PHA ; push it + LDA Bpntrh ; get BASIC execute pointer high byte + PHA ; push it + LDA Bpntrl ; get BASIC execute pointer low byte + PHA ; push it + JSR LAB_DATA ; go perform DATA + JMP LAB_207A ; put execute pointer and variable pointer into function + ; and return + +; check FNx syntax + +LAB_200B + LDA #TK_FN ; get FN" token + JSR LAB_SCCA ; scan for CHR$(A) , else do syntax error then warm start + ; return character after A + ORA #$80 ; set FN flag bit + STA Sufnxf ; save FN flag so array variable test fails + JSR LAB_1D12 ; search for FN variable + JMP LAB_CTNM ; check if source is numeric and return, else do type + ; mismatch + + ; Evaluate FNx +LAB_201E + JSR LAB_200B ; check FNx syntax + PHA ; push function pointer low byte + TYA ; copy function pointer high byte + PHA ; push function pointer high byte + JSR LAB_1BFE ; scan for "(", else do syntax error then warm start + JSR LAB_EVEX ; evaluate expression + JSR LAB_1BFB ; scan for ")", else do syntax error then warm start + JSR LAB_CTNM ; check if source is numeric, else do type mismatch + PLA ; pop function pointer high byte + STA func_h ; restore it + PLA ; pop function pointer low byte + STA func_l ; restore it + LDX #$20 ; error code $20 ("Undefined function" error) + LDY #$03 ; index to variable pointer high byte + LDA (func_l),Y ; get variable pointer high byte + BEQ LAB_1FDB ; if zero go do undefined function error + + STA Cvarah ; save variable address high byte + DEY ; index to variable address low byte + LDA (func_l),Y ; get variable address low byte + STA Cvaral ; save variable address low byte + TAX ; copy address low byte + + ; now stack the function variable value before use + INY ; index to mantissa_3 +LAB_2043 + LDA (Cvaral),Y ; get byte from variable + PHA ; stack it + DEY ; decrement index + BPL LAB_2043 ; loop until variable stacked + + LDY Cvarah ; get variable address high byte + JSR LAB_2778 ; pack FAC1 (function expression value) into (XY) + ; (function variable), return Y=0, always + LDA Bpntrh ; get BASIC execute pointer high byte + PHA ; push it + LDA Bpntrl ; get BASIC execute pointer low byte + PHA ; push it + LDA (func_l),Y ; get function execute pointer low byte + STA Bpntrl ; save as BASIC execute pointer low byte + INY ; index to high byte + LDA (func_l),Y ; get function execute pointer high byte + STA Bpntrh ; save as BASIC execute pointer high byte + LDA Cvarah ; get variable address high byte + PHA ; push it + LDA Cvaral ; get variable address low byte + PHA ; push it + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch + PLA ; pull variable address low byte + STA func_l ; save variable address low byte + PLA ; pull variable address high byte + STA func_h ; save variable address high byte + JSR LAB_GBYT ; scan memory + BEQ LAB_2074 ; branch if null (should be [EOL] marker) + + JMP LAB_SNER ; else syntax error then warm start + +; restore Bpntrl,Bpntrh and function variable from stack + +LAB_2074 + PLA ; pull BASIC execute pointer low byte + STA Bpntrl ; restore BASIC execute pointer low byte + PLA ; pull BASIC execute pointer high byte + STA Bpntrh ; restore BASIC execute pointer high byte + +; put execute pointer and variable pointer into function + +LAB_207A + LDY #$00 ; clear index + PLA ; pull BASIC execute pointer low byte + STA (func_l),Y ; save to function + INY ; increment index + PLA ; pull BASIC execute pointer high byte + STA (func_l),Y ; save to function + INY ; increment index + PLA ; pull current var address low byte + STA (func_l),Y ; save to function + INY ; increment index + PLA ; pull current var address high byte + STA (func_l),Y ; save to function + RTS + +; perform STR$() + +LAB_STRS + JSR LAB_CTNM ; check if source is numeric, else do type mismatch + JSR LAB_296E ; convert FAC1 to string + LDA #Decssp1 ; set result string high pointer + BEQ LAB_20AE ; print null terminated string to Sutill/Sutilh + +; Do string vector +; copy des_pl/h to des_2l/h and make string space A bytes long + +LAB_209C + LDX des_pl ; get descriptor pointer low byte + LDY des_ph ; get descriptor pointer high byte + STX des_2l ; save descriptor pointer low byte + STY des_2h ; save descriptor pointer high byte + +; make string space A bytes long +; A=length, X=Sutill=ptr low byte, Y=Sutilh=ptr high byte + +LAB_MSSP + JSR LAB_2115 ; make space in string memory for string A long + ; return X=Sutill=ptr low byte, Y=Sutilh=ptr high byte + STX str_pl ; save string pointer low byte + STY str_ph ; save string pointer high byte + STA str_ln ; save length + RTS + +; Scan, set up string +; print " terminated string to Sutill/Sutilh + +LAB_20AE + LDX #$22 ; set terminator to " + STX Srchc ; set search character (terminator 1) + STX Asrch ; set terminator 2 + +; print [Srchc] or [Asrch] terminated string to Sutill/Sutilh +; source is AY + +LAB_20B4 + STA ssptr_l ; store string start low byte + STY ssptr_h ; store string start high byte + STA str_pl ; save string pointer low byte + STY str_ph ; save string pointer high byte + LDY #$FF ; set length to -1 +LAB_20BE + INY ; increment length + LDA (ssptr_l),Y ; get byte from string + BEQ LAB_20CF ; exit loop if null byte [EOS] + + CMP Srchc ; compare with search character (terminator 1) + BEQ LAB_20CB ; branch if terminator + + CMP Asrch ; compare with terminator 2 + BNE LAB_20BE ; loop if not terminator 2 + +LAB_20CB + CMP #$22 ; compare with " + BEQ LAB_20D0 ; branch if " (carry set if = !) + +LAB_20CF + CLC ; clear carry for add (only if [EOL] terminated string) +LAB_20D0 + STY str_ln ; save length in FAC1 exponent + TYA ; copy length to A + ADC ssptr_l ; add string start low byte + STA Sendl ; save string end low byte + LDX ssptr_h ; get string start high byte + BCC LAB_20DC ; branch if no low byte overflow + + INX ; else increment high byte +LAB_20DC + STX Sendh ; save string end high byte + LDA ssptr_h ; get string start high byte + CMP #>Ram_base ; compare with start of program memory + BCS LAB_RTST ; branch if not in utility area + + ; string in utility area, move to string memory + TYA ; copy length to A + JSR LAB_209C ; copy des_pl/h to des_2l/h and make string space A bytes + ; long + LDX ssptr_l ; get string start low byte + LDY ssptr_h ; get string start high byte + JSR LAB_2298 ; store string A bytes long from XY to (Sutill) + +; check for space on descriptor stack then .. +; put string address and length on descriptor stack and update stack pointers + +LAB_RTST + LDX next_s ; get string stack pointer + CPX #des_sk+$09 ; compare with max+1 + BNE LAB_20F8 ; branch if space on string stack + + ; else do string too complex error + LDX #$1C ; error code $1C ("String too complex" error) +LAB_20F5 + JMP LAB_XERR ; do error #X, then warm start + +; put string address and length on descriptor stack and update stack pointers + +LAB_20F8 + LDA str_ln ; get string length + STA PLUS_0,X ; put on string stack + LDA str_pl ; get string pointer low byte + STA PLUS_1,X ; put on string stack + LDA str_ph ; get string pointer high byte + STA PLUS_2,X ; put on string stack + LDY #$00 ; clear Y + STX des_pl ; save string descriptor pointer low byte + STY des_ph ; save string descriptor pointer high byte (always $00) + DEY ; Y = $FF + STY Dtypef ; save data type flag, $FF=string + STX last_sl ; save old stack pointer (current top item) + INX ; update stack pointer + INX ; update stack pointer + INX ; update stack pointer + STX next_s ; save new top item value + RTS + +; Build descriptor +; make space in string memory for string A long +; return X=Sutill=ptr low byte, Y=Sutill=ptr high byte + +LAB_2115 + LSR Gclctd ; clear garbage collected flag (b7) + + ; make space for string A long +LAB_2117 + PHA ; save string length + EOR #$FF ; complement it + SEC ; set carry for subtract (twos comp add) + ADC Sstorl ; add bottom of string space low byte (subtract length) + LDY Sstorh ; get bottom of string space high byte + BCS LAB_2122 ; skip decrement if no underflow + + DEY ; decrement bottom of string space high byte +LAB_2122 + CPY Earryh ; compare with array mem end high byte + BCC LAB_2137 ; do out of memory error if less + + BNE LAB_212C ; if not = skip next test + + CMP Earryl ; compare with array mem end low byte + BCC LAB_2137 ; do out of memory error if less + +LAB_212C + STA Sstorl ; save bottom of string space low byte + STY Sstorh ; save bottom of string space high byte + STA Sutill ; save string utility ptr low byte + STY Sutilh ; save string utility ptr high byte + TAX ; copy low byte to X + PLA ; get string length back + RTS + +LAB_2137 + LDX #$0C ; error code $0C ("Out of memory" error) + LDA Gclctd ; get garbage collected flag + BMI LAB_20F5 ; if set then do error code X + + JSR LAB_GARB ; else go do garbage collection + LDA #$80 ; flag for garbage collected + STA Gclctd ; set garbage collected flag + PLA ; pull length + BNE LAB_2117 ; go try again (loop always, length should never be = $00) + +; garbage collection routine + +LAB_GARB + LDX Ememl ; get end of mem low byte + LDA Ememh ; get end of mem high byte + +; re-run routine from last ending + +LAB_214B + STX Sstorl ; set string storage low byte + STA Sstorh ; set string storage high byte + LDY #$00 ; clear index + STY garb_h ; clear working pointer high byte (flag no strings to move) + LDA Earryl ; get array mem end low byte + LDX Earryh ; get array mem end high byte + STA Histrl ; save as highest string low byte + STX Histrh ; save as highest string high byte + LDA #des_sk ; set descriptor stack pointer + STA ut1_pl ; save descriptor stack pointer low byte + STY ut1_ph ; save descriptor stack pointer high byte ($00) +LAB_2161 + CMP next_s ; compare with descriptor stack pointer + BEQ LAB_216A ; branch if = + + JSR LAB_21D7 ; go garbage collect descriptor stack + BEQ LAB_2161 ; loop always + + ; done stacked strings, now do string vars +LAB_216A + ASL g_step ; set step size = $06 + LDA Svarl ; get start of vars low byte + LDX Svarh ; get start of vars high byte + STA ut1_pl ; save as pointer low byte + STX ut1_ph ; save as pointer high byte +LAB_2176 + CPX Sarryh ; compare start of arrays high byte + BNE LAB_217E ; branch if no high byte match + + CMP Sarryl ; else compare start of arrays low byte + BEQ LAB_2183 ; branch if = var mem end + +LAB_217E + JSR LAB_21D1 ; go garbage collect strings + BEQ LAB_2176 ; loop always + + ; done string vars, now do string arrays +LAB_2183 + STA Nbendl ; save start of arrays low byte as working pointer + STX Nbendh ; save start of arrays high byte as working pointer + LDA #$04 ; set step size + STA g_step ; save step size +LAB_218B + LDA Nbendl ; get pointer low byte + LDX Nbendh ; get pointer high byte +LAB_218F + CPX Earryh ; compare with array mem end high byte + BNE LAB_219A ; branch if not at end + + CMP Earryl ; else compare with array mem end low byte + BEQ LAB_2216 ; tidy up and exit if at end + +LAB_219A + STA ut1_pl ; save pointer low byte + STX ut1_ph ; save pointer high byte + LDY #$02 ; set index + LDA (ut1_pl),Y ; get array size low byte + ADC Nbendl ; add start of this array low byte + STA Nbendl ; save start of next array low byte + INY ; increment index + LDA (ut1_pl),Y ; get array size high byte + ADC Nbendh ; add start of this array high byte + STA Nbendh ; save start of next array high byte + LDY #$01 ; set index + LDA (ut1_pl),Y ; get name second byte + BPL LAB_218B ; skip if not string array + +; was string array so .. + + LDY #$04 ; set index + LDA (ut1_pl),Y ; get # of dimensions + ASL ; *2 + ADC #$05 ; +5 (array header size) + JSR LAB_2208 ; go set up for first element +LAB_21C4 + CPX Nbendh ; compare with start of next array high byte + BNE LAB_21CC ; branch if <> (go do this array) + + CMP Nbendl ; else compare element pointer low byte with next array + ; low byte + BEQ LAB_218F ; if equal then go do next array + +LAB_21CC + JSR LAB_21D7 ; go defrag array strings + BEQ LAB_21C4 ; go do next array string (loop always) + +; defrag string variables +; enter with XA = variable pointer +; return with XA = next variable pointer + +LAB_21D1 + INY ; increment index (Y was $00) + LDA (ut1_pl),Y ; get var name byte 2 + BPL LAB_2206 ; if not string, step pointer to next var and return + + INY ; else increment index +LAB_21D7 + LDA (ut1_pl),Y ; get string length + BEQ LAB_2206 ; if null, step pointer to next string and return + + INY ; else increment index + LDA (ut1_pl),Y ; get string pointer low byte + TAX ; copy to X + INY ; increment index + LDA (ut1_pl),Y ; get string pointer high byte + CMP Sstorh ; compare bottom of string space high byte + BCC LAB_21EC ; branch if less + + BNE LAB_2206 ; if greater, step pointer to next string and return + + ; high bytes were = so compare low bytes + CPX Sstorl ; compare bottom of string space low byte + BCS LAB_2206 ; if >=, step pointer to next string and return + + ; string pointer is < string storage pointer (pos in mem) +LAB_21EC + CMP Histrh ; compare to highest string high byte + BCC LAB_2207 ; if <, step pointer to next string and return + + BNE LAB_21F6 ; if > update pointers, step to next and return + + ; high bytes were = so compare low bytes + CPX Histrl ; compare to highest string low byte + BCC LAB_2207 ; if <, step pointer to next string and return + + ; string is in string memory space +LAB_21F6 + STX Histrl ; save as new highest string low byte + STA Histrh ; save as new highest string high byte + LDA ut1_pl ; get start of vars(descriptors) low byte + LDX ut1_ph ; get start of vars(descriptors) high byte + STA garb_l ; save as working pointer low byte + STX garb_h ; save as working pointer high byte + DEY ; decrement index DIFFERS + DEY ; decrement index (should point to descriptor start) + STY g_indx ; save index pointer + + ; step pointer to next string +LAB_2206 + CLC ; clear carry for add +LAB_2207 + LDA g_step ; get step size +LAB_2208 + ADC ut1_pl ; add pointer low byte + STA ut1_pl ; save pointer low byte + BCC LAB_2211 ; branch if no overflow + + INC ut1_ph ; else increment high byte +LAB_2211 + LDX ut1_ph ; get pointer high byte + LDY #$00 ; clear Y + RTS + +; search complete, now either exit or set-up and move string + +LAB_2216 + DEC g_step ; decrement step size (now $03 for descriptor stack) + LDX garb_h ; get string to move high byte + BEQ LAB_2211 ; exit if nothing to move + + LDY g_indx ; get index byte back (points to descriptor) + CLC ; clear carry for add + LDA (garb_l),Y ; get string length + ADC Histrl ; add highest string low byte + STA Obendl ; save old block end low pointer + LDA Histrh ; get highest string high byte + ADC #$00 ; add any carry + STA Obendh ; save old block end high byte + LDA Sstorl ; get bottom of string space low byte + LDX Sstorh ; get bottom of string space high byte + STA Nbendl ; save new block end low byte + STX Nbendh ; save new block end high byte + JSR LAB_11D6 ; open up space in memory, don't set array end + LDY g_indx ; get index byte + INY ; point to descriptor low byte + LDA Nbendl ; get string pointer low byte + STA (garb_l),Y ; save new string pointer low byte + TAX ; copy string pointer low byte + INC Nbendh ; correct high byte (move sets high byte -1) + LDA Nbendh ; get new string pointer high byte + INY ; point to descriptor high byte + STA (garb_l),Y ; save new string pointer high byte + JMP LAB_214B ; re-run routine from last ending + ; (but don't collect this string) + +; concatenate +; add strings, string 1 is in descriptor des_pl, string 2 is in line + +LAB_224D + LDA des_ph ; get descriptor pointer high byte + PHA ; put on stack + LDA des_pl ; get descriptor pointer low byte + PHA ; put on stack + JSR LAB_GVAL ; get value from line + JSR LAB_CTST ; check if source is string, else do type mismatch + PLA ; get descriptor pointer low byte back + STA ssptr_l ; set pointer low byte + PLA ; get descriptor pointer high byte back + STA ssptr_h ; set pointer high byte + LDY #$00 ; clear index + LDA (ssptr_l),Y ; get length_1 from descriptor + CLC ; clear carry for add + ADC (des_pl),Y ; add length_2 + BCC LAB_226D ; branch if no overflow + + LDX #$1A ; else set error code $1A ("String too long" error) + JMP LAB_XERR ; do error #X, then warm start + +LAB_226D + JSR LAB_209C ; copy des_pl/h to des_2l/h and make string space A bytes + ; long + JSR LAB_228A ; copy string from descriptor (sdescr) to (Sutill) + LDA des_2l ; get descriptor pointer low byte + LDY des_2h ; get descriptor pointer high byte + JSR LAB_22BA ; pop (YA) descriptor off stack or from top of string space + ; returns with A = length, ut1_pl = pointer low byte, + ; ut1_ph = pointer high byte + JSR LAB_229C ; store string A bytes long from (ut1_pl) to (Sutill) + LDA ssptr_l ;.set descriptor pointer low byte + LDY ssptr_h ;.set descriptor pointer high byte + JSR LAB_22BA ; pop (YA) descriptor off stack or from top of string space + ; returns with A = length, X=ut1_pl=pointer low byte, + ; Y=ut1_ph=pointer high byte + JSR LAB_RTST ; check for space on descriptor stack then put string + ; address and length on descriptor stack and update stack + ; pointers + JMP LAB_1ADB ;.continue evaluation + +; copy string from descriptor (sdescr) to (Sutill) + +LAB_228A + LDY #$00 ; clear index + LDA (sdescr),Y ; get string length + PHA ; save on stack + INY ; increment index + LDA (sdescr),Y ; get source string pointer low byte + TAX ; copy to X + INY ; increment index + LDA (sdescr),Y ; get source string pointer high byte + TAY ; copy to Y + PLA ; get length back + +; store string A bytes long from YX to (Sutill) + +LAB_2298 + STX ut1_pl ; save source string pointer low byte + STY ut1_ph ; save source string pointer high byte + +; store string A bytes long from (ut1_pl) to (Sutill) + +LAB_229C + TAX ; copy length to index (don't count with Y) + BEQ LAB_22B2 ; branch if = $0 (null string) no need to add zero length + + LDY #$00 ; zero pointer (copy forward) +LAB_22A0 + LDA (ut1_pl),Y ; get source byte + STA (Sutill),Y ; save destination byte + + INY ; increment index + DEX ; decrement counter + BNE LAB_22A0 ; loop while <> 0 + + TYA ; restore length from Y +LAB_22A9 + CLC ; clear carry for add + ADC Sutill ; add string utility ptr low byte + STA Sutill ; save string utility ptr low byte + BCC LAB_22B2 ; branch if no carry + + INC Sutilh ; else increment string utility ptr high byte +LAB_22B2 + RTS + +; evaluate string + +LAB_EVST + JSR LAB_CTST ; check if source is string, else do type mismatch + +; pop string off descriptor stack, or from top of string space +; returns with A = length, X=pointer low byte, Y=pointer high byte + +LAB_22B6 + LDA des_pl ; get descriptor pointer low byte + LDY des_ph ; get descriptor pointer high byte + +; pop (YA) descriptor off stack or from top of string space +; returns with A = length, X=ut1_pl=pointer low byte, Y=ut1_ph=pointer high byte + +LAB_22BA + STA ut1_pl ; save descriptor pointer low byte + STY ut1_ph ; save descriptor pointer high byte + JSR LAB_22EB ; clean descriptor stack, YA = pointer + PHP ; save status flags + LDY #$00 ; clear index + LDA (ut1_pl),Y ; get length from string descriptor + PHA ; put on stack + INY ; increment index + LDA (ut1_pl),Y ; get string pointer low byte from descriptor + TAX ; copy to X + INY ; increment index + LDA (ut1_pl),Y ; get string pointer high byte from descriptor + TAY ; copy to Y + PLA ; get string length back + PLP ; restore status + BNE LAB_22E6 ; branch if pointer <> last_sl,last_sh + + CPY Sstorh ; compare bottom of string space high byte + BNE LAB_22E6 ; branch if <> + + CPX Sstorl ; else compare bottom of string space low byte + BNE LAB_22E6 ; branch if <> + + PHA ; save string length + CLC ; clear carry for add + ADC Sstorl ; add bottom of string space low byte + STA Sstorl ; save bottom of string space low byte + BCC LAB_22E5 ; skip increment if no overflow + + INC Sstorh ; increment bottom of string space high byte +LAB_22E5 + PLA ; restore string length +LAB_22E6 + STX ut1_pl ; save string pointer low byte + STY ut1_ph ; save string pointer high byte + RTS + +; clean descriptor stack, YA = pointer +; checks if AY is on the descriptor stack, if so does a stack discard + +LAB_22EB + CPY last_sh ; compare pointer high byte + BNE LAB_22FB ; exit if <> + + CMP last_sl ; compare pointer low byte + BNE LAB_22FB ; exit if <> + + STA next_s ; save descriptor stack pointer + SBC #$03 ; -3 + STA last_sl ; save low byte -3 + LDY #$00 ; clear high byte +LAB_22FB + RTS + +; perform CHR$() + +LAB_CHRS + JSR LAB_EVBY ; evaluate byte expression, result in X + TXA ; copy to A + PHA ; save character + LDA #$01 ; string is single byte + JSR LAB_MSSP ; make string space A bytes long A=$AC=length, + ; X=$AD=Sutill=ptr low byte, Y=$AE=Sutilh=ptr high byte + PLA ; get character back + LDY #$00 ; clear index + STA (str_pl),Y ; save byte in string (byte IS string!) + JMP LAB_RTST ; check for space on descriptor stack then put string + ; address and length on descriptor stack and update stack + ; pointers + +; perform LEFT$() + +LAB_LEFT + PHA ; push byte parameter + JSR LAB_236F ; pull string data and byte parameter from stack + ; return pointer in des_2l/h, byte in A (and X), Y=0 + CMP (des_2l),Y ; compare byte parameter with string length + TYA ; clear A + BEQ LAB_2316 ; go do string copy (branch always) + +; perform RIGHT$() + +LAB_RIGHT + PHA ; push byte parameter + JSR LAB_236F ; pull string data and byte parameter from stack + ; return pointer in des_2l/h, byte in A (and X), Y=0 + CLC ; clear carry for add-1 + SBC (des_2l),Y ; subtract string length + EOR #$FF ; invert it (A=LEN(expression$)-l) + +LAB_2316 + BCC LAB_231C ; branch if string length > byte parameter + + LDA (des_2l),Y ; else make parameter = length + TAX ; copy to byte parameter copy + TYA ; clear string start offset +LAB_231C + PHA ; save string start offset +LAB_231D + TXA ; copy byte parameter (or string length if <) +LAB_231E + PHA ; save string length + JSR LAB_MSSP ; make string space A bytes long A=$AC=length, + ; X=$AD=Sutill=ptr low byte, Y=$AE=Sutilh=ptr high byte + LDA des_2l ; get descriptor pointer low byte + LDY des_2h ; get descriptor pointer high byte + JSR LAB_22BA ; pop (YA) descriptor off stack or from top of string space + ; returns with A = length, X=ut1_pl=pointer low byte, + ; Y=ut1_ph=pointer high byte + PLA ; get string length back + TAY ; copy length to Y + PLA ; get string start offset back + CLC ; clear carry for add + ADC ut1_pl ; add start offset to string start pointer low byte + STA ut1_pl ; save string start pointer low byte + BCC LAB_2335 ; branch if no overflow + + INC ut1_ph ; else increment string start pointer high byte +LAB_2335 + TYA ; copy length to A + JSR LAB_229C ; store string A bytes long from (ut1_pl) to (Sutill) + JMP LAB_RTST ; check for space on descriptor stack then put string + ; address and length on descriptor stack and update stack + ; pointers + +; perform MID$() + +LAB_MIDS + PHA ; push byte parameter + LDA #$FF ; set default length = 255 + STA mids_l ; save default length + JSR LAB_GBYT ; scan memory + CMP #')' ; compare with ")" + BEQ LAB_2358 ; branch if = ")" (skip second byte get) + + JSR LAB_1C01 ; scan for "," , else do syntax error then warm start + JSR LAB_GTBY ; get byte parameter (use copy in mids_l) +LAB_2358 + JSR LAB_236F ; pull string data and byte parameter from stack + ; return pointer in des_2l/h, byte in A (and X), Y=0 + DEX ; decrement start index + TXA ; copy to A + PHA ; save string start offset + CLC ; clear carry for sub-1 + LDX #$00 ; clear output string length + SBC (des_2l),Y ; subtract string length + BCS LAB_231D ; if start>string length go do null string + + EOR #$FF ; complement -length + CMP mids_l ; compare byte parameter + BCC LAB_231E ; if length>remaining string go do RIGHT$ + + LDA mids_l ; get length byte + BCS LAB_231E ; go do string copy (branch always) + +; pull string data and byte parameter from stack +; return pointer in des_2l/h, byte in A (and X), Y=0 + +LAB_236F + JSR LAB_1BFB ; scan for ")" , else do syntax error then warm start + PLA ; pull return address low byte (return address) + STA Fnxjpl ; save functions jump vector low byte + PLA ; pull return address high byte (return address) + STA Fnxjph ; save functions jump vector high byte + PLA ; pull byte parameter + TAX ; copy byte parameter to X + PLA ; pull string pointer low byte + STA des_2l ; save it + PLA ; pull string pointer high byte + STA des_2h ; save it + LDY #$00 ; clear index + TXA ; copy byte parameter + BEQ LAB_23A8 ; if null do function call error then warm start + + INC Fnxjpl ; increment function jump vector low byte + ; (JSR pushes return addr-1. this is all very nice + ; but will go tits up if either call is on a page + ; boundary!) + JMP (Fnxjpl) ; in effect, RTS + +; perform LCASE$() + +LAB_LCASE + JSR LAB_EVST ; evaluate string + STA str_ln ; set string length + TAY ; copy length to Y + BEQ NoString ; branch if null string + + JSR LAB_MSSP ; make string space A bytes long A=length, + ; X=Sutill=ptr low byte, Y=Sutilh=ptr high byte + STX str_pl ; save string pointer low byte + STY str_ph ; save string pointer high byte + TAY ; get string length back + +LC_loop + DEY ; decrement index + LDA (ut1_pl),Y ; get byte from string + JSR LAB_1D82 ; is character "A" to "Z" + BCC NoUcase ; branch if not upper case alpha + + ORA #$20 ; convert upper to lower case +NoUcase + STA (Sutill),Y ; save byte back to string + TYA ; test index + BNE LC_loop ; loop if not all done + + BEQ NoString ; tidy up and exit, branch always + +; perform UCASE$() + +LAB_UCASE + JSR LAB_EVST ; evaluate string + STA str_ln ; set string length + TAY ; copy length to Y + BEQ NoString ; branch if null string + + JSR LAB_MSSP ; make string space A bytes long A=length, + ; X=Sutill=ptr low byte, Y=Sutilh=ptr high byte + STX str_pl ; save string pointer low byte + STY str_ph ; save string pointer high byte + TAY ; get string length back + +UC_loop + DEY ; decrement index + LDA (ut1_pl),Y ; get byte from string + JSR LAB_CASC ; is character "a" to "z" (or "A" to "Z") + BCC NoLcase ; branch if not alpha + + AND #$DF ; convert lower to upper case +NoLcase + STA (Sutill),Y ; save byte back to string + TYA ; test index + BNE UC_loop ; loop if not all done + +NoString + JMP LAB_RTST ; check for space on descriptor stack then put string + ; address and length on descriptor stack and update stack + ; pointers + +; perform SADD() + +LAB_SADD + JSR LAB_IGBY ; increment and scan memory + JSR LAB_GVAR ; get var address + + JSR LAB_1BFB ; scan for ")", else do syntax error then warm start + JSR LAB_CTST ; check if source is string, else do type mismatch + + LDY #$02 ; index to string pointer high byte + LDA (Cvaral),Y ; get string pointer high byte + TAX ; copy string pointer high byte to X + DEY ; index to string pointer low byte + LDA (Cvaral),Y ; get string pointer low byte + TAY ; copy string pointer low byte to Y + TXA ; copy string pointer high byte to A + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +; perform LEN() + +LAB_LENS + JSR LAB_ESGL ; evaluate string, get length in A (and Y) + JMP LAB_1FD0 ; convert Y to byte in FAC1 and return + +; evaluate string, get length in Y + +LAB_ESGL + JSR LAB_EVST ; evaluate string + TAY ; copy length to Y + RTS + +; perform ASC() + +LAB_ASC + JSR LAB_ESGL ; evaluate string, get length in A (and Y) + BEQ LAB_23A8 ; if null do function call error then warm start + + LDY #$00 ; set index to first character + LDA (ut1_pl),Y ; get byte + TAY ; copy to Y + JMP LAB_1FD0 ; convert Y to byte in FAC1 and return + +; do function call error then warm start + +LAB_23A8 + JMP LAB_FCER ; do function call error then warm start + +; scan and get byte parameter + +LAB_SGBY + JSR LAB_IGBY ; increment and scan memory + +; get byte parameter + +LAB_GTBY + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch + +; evaluate byte expression, result in X + +LAB_EVBY + JSR LAB_EVPI ; evaluate integer expression (no check) + + LDY FAC1_2 ; get FAC1 mantissa2 + BNE LAB_23A8 ; if top byte <> 0 do function call error then warm start + + LDX FAC1_3 ; get FAC1 mantissa3 + JMP LAB_GBYT ; scan memory and return + +; perform VAL() + +LAB_VAL + JSR LAB_ESGL ; evaluate string, get length in A (and Y) + BNE LAB_23C5 ; branch if not null string + + ; string was null so set result = $00 + JMP LAB_24F1 ; clear FAC1 exponent and sign and return + +LAB_23C5 + LDX Bpntrl ; get BASIC execute pointer low byte + LDY Bpntrh ; get BASIC execute pointer high byte + STX Btmpl ; save BASIC execute pointer low byte + STY Btmph ; save BASIC execute pointer high byte + LDX ut1_pl ; get string pointer low byte + STX Bpntrl ; save as BASIC execute pointer low byte + CLC ; clear carry + ADC ut1_pl ; add string length + STA ut2_pl ; save string end low byte + LDA ut1_ph ; get string pointer high byte + STA Bpntrh ; save as BASIC execute pointer high byte + ADC #$00 ; add carry to high byte + STA ut2_ph ; save string end high byte + LDY #$00 ; set index to $00 + LDA (ut2_pl),Y ; get string end +1 byte + PHA ; push it + TYA ; clear A + STA (ut2_pl),Y ; terminate string with $00 + JSR LAB_GBYT ; scan memory + JSR LAB_2887 ; get FAC1 from string + PLA ; restore string end +1 byte + LDY #$00 ; set index to zero + STA (ut2_pl),Y ; put string end byte back + +; restore BASIC execute pointer from temp (Btmpl/Btmph) + +LAB_23F3 + LDX Btmpl ; get BASIC execute pointer low byte back + LDY Btmph ; get BASIC execute pointer high byte back + STX Bpntrl ; save BASIC execute pointer low byte + STY Bpntrh ; save BASIC execute pointer high byte + RTS + +; get two parameters for POKE or WAIT + +LAB_GADB + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch + JSR LAB_F2FX ; save integer part of FAC1 in temporary integer + +; scan for "," and get byte, else do Syntax error then warm start + +LAB_SCGB + JSR LAB_1C01 ; scan for "," , else do syntax error then warm start + LDA Itemph ; save temporary integer high byte + PHA ; on stack + LDA Itempl ; save temporary integer low byte + PHA ; on stack + JSR LAB_GTBY ; get byte parameter + PLA ; pull low byte + STA Itempl ; restore temporary integer low byte + PLA ; pull high byte + STA Itemph ; restore temporary integer high byte + RTS + +; convert float to fixed routine. accepts any value that fits in 24 bits, +ve or +; -ve and converts it into a right truncated integer in Itempl and Itemph + +; save unsigned 16 bit integer part of FAC1 in temporary integer + +LAB_F2FX + LDA FAC1_e ; get FAC1 exponent + CMP #$98 ; compare with exponent = 2^24 + BCS LAB_23A8 ; if >= do function call error then warm start + +LAB_F2FU + JSR LAB_2831 ; convert FAC1 floating-to-fixed + LDA FAC1_2 ; get FAC1 mantissa2 + LDY FAC1_3 ; get FAC1 mantissa3 + STY Itempl ; save temporary integer low byte + STA Itemph ; save temporary integer high byte + RTS + +; perform PEEK() + +LAB_PEEK + JSR LAB_F2FX ; save integer part of FAC1 in temporary integer + LDX #$00 ; clear index + LDA (Itempl,X) ; get byte via temporary integer (addr) + TAY ; copy byte to Y + JMP LAB_1FD0 ; convert Y to byte in FAC1 and return + +; perform POKE + +LAB_POKE + JSR LAB_GADB ; get two parameters for POKE or WAIT + TXA ; copy byte argument to A + LDX #$00 ; clear index + STA (Itempl,X) ; save byte via temporary integer (addr) + RTS + +; perform DEEK() + +LAB_DEEK + JSR LAB_F2FX ; save integer part of FAC1 in temporary integer + LDX #$00 ; clear index + LDA (Itempl,X) ; PEEK low byte + TAY ; copy to Y + INC Itempl ; increment pointer low byte + BNE Deekh ; skip high increment if no rollover + + INC Itemph ; increment pointer high byte +Deekh + LDA (Itempl,X) ; PEEK high byte + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +; perform DOKE + +LAB_DOKE + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch + JSR LAB_F2FX ; convert floating-to-fixed + + STY Frnxtl ; save pointer low byte (float to fixed returns word in AY) + STA Frnxth ; save pointer high byte + + JSR LAB_1C01 ; scan for "," , else do syntax error then warm start + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch + JSR LAB_F2FX ; convert floating-to-fixed + + TYA ; copy value low byte (float to fixed returns word in AY) + LDX #$00 ; clear index + STA (Frnxtl,X) ; POKE low byte + INC Frnxtl ; increment pointer low byte + BNE Dokeh ; skip high increment if no rollover + + INC Frnxth ; increment pointer high byte +Dokeh + LDA Itemph ; get value high byte + STA (Frnxtl,X) ; POKE high byte + JMP LAB_GBYT ; scan memory and return + +; perform SWAP + +LAB_SWAP + JSR LAB_GVAR ; get var1 address + STA Lvarpl ; save var1 address low byte + STY Lvarph ; save var1 address high byte + LDA Dtypef ; get data type flag, $FF=string, $00=numeric + PHA ; save data type flag + + JSR LAB_1C01 ; scan for "," , else do syntax error then warm start + JSR LAB_GVAR ; get var2 address (pointer in Cvaral/h) + PLA ; pull var1 data type flag + EOR Dtypef ; compare with var2 data type + BPL SwapErr ; exit if not both the same type + + LDY #$03 ; four bytes to swap (either value or descriptor+1) +SwapLp + LDA (Lvarpl),Y ; get byte from var1 + TAX ; save var1 byte + LDA (Cvaral),Y ; get byte from var2 + STA (Lvarpl),Y ; save byte to var1 + TXA ; restore var1 byte + STA (Cvaral),Y ; save byte to var2 + DEY ; decrement index + BPL SwapLp ; loop until done + + RTS + +SwapErr + JMP LAB_1ABC ; do "Type mismatch" error then warm start + +; perform CALL + +LAB_CALL + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch + JSR LAB_F2FX ; convert floating-to-fixed + LDA #>CallExit ; set return address high byte + PHA ; put on stack + LDA #8 shifts) + BCC LAB_24A8 ;.go subtract mantissas + +; add 0.5 to FAC1 + +LAB_244E + LDA #LAB_2A96 ; set 0.5 pointer high byte + +; add (AY) to FAC1 + +LAB_246C + JSR LAB_264D ; unpack memory (AY) into FAC2 + +; add FAC2 to FAC1 + +LAB_ADD + BNE LAB_2474 ; branch if FAC1 was not zero + +; copy FAC2 to FAC1 + +LAB_279B + LDA FAC2_s ; get FAC2 sign (b7) + +; save FAC1 sign and copy ABS(FAC2) to FAC1 + +LAB_279D + STA FAC1_s ; save FAC1 sign (b7) + LDX #$04 ; 4 bytes to copy +LAB_27A1 + LDA FAC1_o,X ; get byte from FAC2,X + STA FAC1_e-1,X ; save byte at FAC1,X + DEX ; decrement count + BNE LAB_27A1 ; loop if not all done + + STX FAC1_r ; clear FAC1 rounding byte + RTS + + ; FAC1 is non zero +LAB_2474 + LDX FAC1_r ; get FAC1 rounding byte + STX FAC2_r ; save as FAC2 rounding byte + LDX #FAC2_e ; set index to FAC2 exponent addr + LDA FAC2_e ; get FAC2 exponent +LAB_247C + TAY ; copy exponent + BEQ LAB_244D ; exit if zero + + SEC ; set carry for subtract + SBC FAC1_e ; subtract FAC1 exponent + BEQ LAB_24A8 ; branch if = (go add mantissa) + + BCC LAB_2498 ; branch if < + + ; FAC2>FAC1 + STY FAC1_e ; save FAC1 exponent + LDY FAC2_s ; get FAC2 sign (b7) + STY FAC1_s ; save FAC1 sign (b7) + EOR #$FF ; complement A + ADC #$00 ; +1 (twos complement, carry is set) + LDY #$00 ; clear Y + STY FAC2_r ; clear FAC2 rounding byte + LDX #FAC1_e ; set index to FAC1 exponent addr + BNE LAB_249C ; branch always + +LAB_2498 + LDY #$00 ; clear Y + STY FAC1_r ; clear FAC1 rounding byte +LAB_249C + CMP #$F9 ; compare exponent diff with $F9 + BMI LAB_2467 ; branch if range $79-$F8 + + TAY ; copy exponent difference to Y + LDA FAC1_r ; get FAC1 rounding byte + LSR PLUS_1,X ; shift FAC? mantissa1 + JSR LAB_2592 ; shift FACX Y times right + + ; exponents are equal now do mantissa subtract +LAB_24A8 + BIT FAC_sc ; test sign compare (FAC1 EOR FAC2) + BPL LAB_24F8 ; if = add FAC2 mantissa to FAC1 mantissa and return + + LDY #FAC1_e ; set index to FAC1 exponent addr + CPX #FAC2_e ; compare X to FAC2 exponent addr + BEQ LAB_24B4 ; branch if = + + LDY #FAC2_e ; else set index to FAC2 exponent addr + + ; subtract smaller from bigger (take sign of bigger) +LAB_24B4 + SEC ; set carry for subtract + EOR #$FF ; ones complement A + ADC FAC2_r ; add FAC2 rounding byte + STA FAC1_r ; save FAC1 rounding byte + LDA PLUS_3,Y ; get FACY mantissa3 + SBC PLUS_3,X ; subtract FACX mantissa3 + STA FAC1_3 ; save FAC1 mantissa3 + LDA PLUS_2,Y ; get FACY mantissa2 + SBC PLUS_2,X ; subtract FACX mantissa2 + STA FAC1_2 ; save FAC1 mantissa2 + LDA PLUS_1,Y ; get FACY mantissa1 + SBC PLUS_1,X ; subtract FACX mantissa1 + STA FAC1_1 ; save FAC1 mantissa1 + +; do ABS and normalise FAC1 + +LAB_24D0 + BCS LAB_24D5 ; branch if number is +ve + + JSR LAB_2537 ; negate FAC1 + +; normalise FAC1 + +LAB_24D5 + LDY #$00 ; clear Y + TYA ; clear A + CLC ; clear carry for add +LAB_24D9 + LDX FAC1_1 ; get FAC1 mantissa1 + BNE LAB_251B ; if not zero normalise FAC1 + + LDX FAC1_2 ; get FAC1 mantissa2 + STX FAC1_1 ; save FAC1 mantissa1 + LDX FAC1_3 ; get FAC1 mantissa3 + STX FAC1_2 ; save FAC1 mantissa2 + LDX FAC1_r ; get FAC1 rounding byte + STX FAC1_3 ; save FAC1 mantissa3 + STY FAC1_r ; clear FAC1 rounding byte + ADC #$08 ; add x to exponent offset + CMP #$18 ; compare with $18 (max offset, all bits would be =0) + BNE LAB_24D9 ; loop if not max + +; clear FAC1 exponent and sign + +LAB_24F1 + LDA #$00 ; clear A +LAB_24F3 + STA FAC1_e ; set FAC1 exponent + +; save FAC1 sign + +LAB_24F5 + STA FAC1_s ; save FAC1 sign (b7) + RTS + +; add FAC2 mantissa to FAC1 mantissa + +LAB_24F8 + ADC FAC2_r ; add FAC2 rounding byte + STA FAC1_r ; save FAC1 rounding byte + LDA FAC1_3 ; get FAC1 mantissa3 + ADC FAC2_3 ; add FAC2 mantissa3 + STA FAC1_3 ; save FAC1 mantissa3 + LDA FAC1_2 ; get FAC1 mantissa2 + ADC FAC2_2 ; add FAC2 mantissa2 + STA FAC1_2 ; save FAC1 mantissa2 + LDA FAC1_1 ; get FAC1 mantissa1 + ADC FAC2_1 ; add FAC2 mantissa1 + STA FAC1_1 ; save FAC1 mantissa1 + BCS LAB_252A ; if carry then normalise FAC1 for C=1 + + RTS ; else just exit + +LAB_2511 + ADC #$01 ; add 1 to exponent offset + ASL FAC1_r ; shift FAC1 rounding byte + ROL FAC1_3 ; shift FAC1 mantissa3 + ROL FAC1_2 ; shift FAC1 mantissa2 + ROL FAC1_1 ; shift FAC1 mantissa1 + +; normalise FAC1 + +LAB_251B + BPL LAB_2511 ; loop if not normalised + + SEC ; set carry for subtract + SBC FAC1_e ; subtract FAC1 exponent + BCS LAB_24F1 ; branch if underflow (set result = $0) + + EOR #$FF ; complement exponent + ADC #$01 ; +1 (twos complement) + STA FAC1_e ; save FAC1 exponent + +; test and normalise FAC1 for C=0/1 + +LAB_2528 + BCC LAB_2536 ; exit if no overflow + +; normalise FAC1 for C=1 + +LAB_252A + INC FAC1_e ; increment FAC1 exponent + BEQ LAB_2564 ; if zero do overflow error and warm start + + ROR FAC1_1 ; shift FAC1 mantissa1 + ROR FAC1_2 ; shift FAC1 mantissa2 + ROR FAC1_3 ; shift FAC1 mantissa3 + ROR FAC1_r ; shift FAC1 rounding byte +LAB_2536 + RTS + +; negate FAC1 + +LAB_2537 + LDA FAC1_s ; get FAC1 sign (b7) + EOR #$FF ; complement it + STA FAC1_s ; save FAC1 sign (b7) + +; twos complement FAC1 mantissa + +LAB_253D + LDA FAC1_1 ; get FAC1 mantissa1 + EOR #$FF ; complement it + STA FAC1_1 ; save FAC1 mantissa1 + LDA FAC1_2 ; get FAC1 mantissa2 + EOR #$FF ; complement it + STA FAC1_2 ; save FAC1 mantissa2 + LDA FAC1_3 ; get FAC1 mantissa3 + EOR #$FF ; complement it + STA FAC1_3 ; save FAC1 mantissa3 + LDA FAC1_r ; get FAC1 rounding byte + EOR #$FF ; complement it + STA FAC1_r ; save FAC1 rounding byte + INC FAC1_r ; increment FAC1 rounding byte + BNE LAB_2563 ; exit if no overflow + +; increment FAC1 mantissa + +LAB_2559 + INC FAC1_3 ; increment FAC1 mantissa3 + BNE LAB_2563 ; finished if no rollover + + INC FAC1_2 ; increment FAC1 mantissa2 + BNE LAB_2563 ; finished if no rollover + + INC FAC1_1 ; increment FAC1 mantissa1 +LAB_2563 + RTS + +; do overflow error (overflow exit) + +LAB_2564 + LDX #$0A ; error code $0A ("Overflow" error) + JMP LAB_XERR ; do error #X, then warm start + +; shift FCAtemp << A+8 times + +LAB_2569 + LDX #FACt_1-1 ; set offset to FACtemp +LAB_256B + LDY PLUS_3,X ; get FACX mantissa3 + STY FAC1_r ; save as FAC1 rounding byte + LDY PLUS_2,X ; get FACX mantissa2 + STY PLUS_3,X ; save FACX mantissa3 + LDY PLUS_1,X ; get FACX mantissa1 + STY PLUS_2,X ; save FACX mantissa2 + LDY FAC1_o ; get FAC1 overflow byte + STY PLUS_1,X ; save FACX mantissa1 + +; shift FACX -A times right (> 8 shifts) + +LAB_257B + ADC #$08 ; add 8 to shift count + BMI LAB_256B ; go do 8 shift if still -ve + + BEQ LAB_256B ; go do 8 shift if zero + + SBC #$08 ; else subtract 8 again + TAY ; save count to Y + LDA FAC1_r ; get FAC1 rounding byte + BCS LAB_259A ;. + +LAB_2588 + ASL PLUS_1,X ; shift FACX mantissa1 + BCC LAB_258E ; branch if +ve + + INC PLUS_1,X ; this sets b7 eventually +LAB_258E + ROR PLUS_1,X ; shift FACX mantissa1 (correct for ASL) + ROR PLUS_1,X ; shift FACX mantissa1 (put carry in b7) + +; shift FACX Y times right + +LAB_2592 + ROR PLUS_2,X ; shift FACX mantissa2 + ROR PLUS_3,X ; shift FACX mantissa3 + ROR ; shift FACX rounding byte + INY ; increment exponent diff + BNE LAB_2588 ; branch if range adjust not complete + +LAB_259A + CLC ; just clear it + RTS + +; perform LOG() + +LAB_LOG + JSR LAB_27CA ; test sign and zero + BEQ LAB_25C4 ; if zero do function call error then warm start + + BPL LAB_25C7 ; skip error if +ve + +LAB_25C4 + JMP LAB_FCER ; do function call error then warm start (-ve) + +LAB_25C7 + LDA FAC1_e ; get FAC1 exponent + SBC #$7F ; normalise it + PHA ; save it + LDA #$80 ; set exponent to zero + STA FAC1_e ; save FAC1 exponent + LDA #LAB_25AD ; set 1/root2 pointer high byte + JSR LAB_246C ; add (AY) to FAC1 (1/root2) + LDA #LAB_25B1 ; set root2 pointer high byte + JSR LAB_26CA ; convert AY and do (AY)/FAC1 (root2/(x+(1/root2))) + LDA #LAB_259C ; set 1 pointer high byte + JSR LAB_2455 ; subtract (AY) from FAC1 ((root2/(x+(1/root2)))-1) + LDA #LAB_25A0 ; set pointer high byte to counter + JSR LAB_2B6E ; ^2 then series evaluation + LDA #LAB_25B5 ; set -0.5 pointer high byte + JSR LAB_246C ; add (AY) to FAC1 + PLA ; restore FAC1 exponent + JSR LAB_2912 ; evaluate new ASCII digit + LDA #LAB_25B9 ; set LOG(2) pointer high byte + +; do convert AY, FCA1*(AY) + +LAB_25FB + JSR LAB_264D ; unpack memory (AY) into FAC2 +LAB_MULTIPLY + BEQ LAB_264C ; exit if zero + + JSR LAB_2673 ; test and adjust accumulators + LDA #$00 ; clear A + STA FACt_1 ; clear temp mantissa1 + STA FACt_2 ; clear temp mantissa2 + STA FACt_3 ; clear temp mantissa3 + LDA FAC1_r ; get FAC1 rounding byte + JSR LAB_2622 ; go do shift/add FAC2 + LDA FAC1_3 ; get FAC1 mantissa3 + JSR LAB_2622 ; go do shift/add FAC2 + LDA FAC1_2 ; get FAC1 mantissa2 + JSR LAB_2622 ; go do shift/add FAC2 + LDA FAC1_1 ; get FAC1 mantissa1 + JSR LAB_2627 ; go do shift/add FAC2 + JMP LAB_273C ; copy temp to FAC1, normalise and return + +LAB_2622 + BNE LAB_2627 ; branch if byte <> zero + + JMP LAB_2569 ; shift FCAtemp << A+8 times + + ; else do shift and add +LAB_2627 + LSR ; shift byte + ORA #$80 ; set top bit (mark for 8 times) +LAB_262A + TAY ; copy result + BCC LAB_2640 ; skip next if bit was zero + + CLC ; clear carry for add + LDA FACt_3 ; get temp mantissa3 + ADC FAC2_3 ; add FAC2 mantissa3 + STA FACt_3 ; save temp mantissa3 + LDA FACt_2 ; get temp mantissa2 + ADC FAC2_2 ; add FAC2 mantissa2 + STA FACt_2 ; save temp mantissa2 + LDA FACt_1 ; get temp mantissa1 + ADC FAC2_1 ; add FAC2 mantissa1 + STA FACt_1 ; save temp mantissa1 +LAB_2640 + ROR FACt_1 ; shift temp mantissa1 + ROR FACt_2 ; shift temp mantissa2 + ROR FACt_3 ; shift temp mantissa3 + ROR FAC1_r ; shift temp rounding byte + TYA ; get byte back + LSR ; shift byte + BNE LAB_262A ; loop if all bits not done + +LAB_264C + RTS + +; unpack memory (AY) into FAC2 + +LAB_264D + STA ut1_pl ; save pointer low byte + STY ut1_ph ; save pointer high byte + LDY #$03 ; 4 bytes to get (0-3) + LDA (ut1_pl),Y ; get mantissa3 + STA FAC2_3 ; save FAC2 mantissa3 + DEY ; decrement index + LDA (ut1_pl),Y ; get mantissa2 + STA FAC2_2 ; save FAC2 mantissa2 + DEY ; decrement index + LDA (ut1_pl),Y ; get mantissa1+sign + STA FAC2_s ; save FAC2 sign (b7) + EOR FAC1_s ; EOR with FAC1 sign (b7) + STA FAC_sc ; save sign compare (FAC1 EOR FAC2) + LDA FAC2_s ; recover FAC2 sign (b7) + ORA #$80 ; set 1xxx xxx (set normal bit) + STA FAC2_1 ; save FAC2 mantissa1 + DEY ; decrement index + LDA (ut1_pl),Y ; get exponent byte + STA FAC2_e ; save FAC2 exponent + LDA FAC1_e ; get FAC1 exponent + RTS + +; test and adjust accumulators + +LAB_2673 + LDA FAC2_e ; get FAC2 exponent +LAB_2675 + BEQ LAB_2696 ; branch if FAC2 = $00 (handle underflow) + + CLC ; clear carry for add + ADC FAC1_e ; add FAC1 exponent + BCC LAB_2680 ; branch if sum of exponents <$0100 + + BMI LAB_269B ; do overflow error + + CLC ; clear carry for the add + .byte $2C ; makes next line BIT $1410 +LAB_2680 + BPL LAB_2696 ; if +ve go handle underflow + + ADC #$80 ; adjust exponent + STA FAC1_e ; save FAC1 exponent + BNE LAB_268B ; branch if not zero + + JMP LAB_24F5 ; save FAC1 sign and return + +LAB_268B + LDA FAC_sc ; get sign compare (FAC1 EOR FAC2) + STA FAC1_s ; save FAC1 sign (b7) +LAB_268F + RTS + +; handle overflow and underflow + +LAB_2690 + LDA FAC1_s ; get FAC1 sign (b7) + BPL LAB_269B ; do overflow error + + ; handle underflow +LAB_2696 + PLA ; pop return address low byte + PLA ; pop return address high byte + JMP LAB_24F1 ; clear FAC1 exponent and sign and return + +; multiply by 10 + +LAB_269E + JSR LAB_27AB ; round and copy FAC1 to FAC2 + TAX ; copy exponent (set the flags) + BEQ LAB_268F ; exit if zero + + CLC ; clear carry for add + ADC #$02 ; add two to exponent (*4) + BCS LAB_269B ; do overflow error if > $FF + + LDX #$00 ; clear byte + STX FAC_sc ; clear sign compare (FAC1 EOR FAC2) + JSR LAB_247C ; add FAC2 to FAC1 (*5) + INC FAC1_e ; increment FAC1 exponent (*10) + BNE LAB_268F ; if non zero just do RTS + +LAB_269B + JMP LAB_2564 ; do overflow error and warm start + +; divide by 10 + +LAB_26B9 + JSR LAB_27AB ; round and copy FAC1 to FAC2 + LDA #LAB_26B5 ; set pointer to 10d high addr + LDX #$00 ; clear sign + +; divide by (AY) (X=sign) + +LAB_26C2 + STX FAC_sc ; save sign compare (FAC1 EOR FAC2) + JSR LAB_UFAC ; unpack memory (AY) into FAC1 + JMP LAB_DIVIDE ; do FAC2/FAC1 + + ; Perform divide-by +; convert AY and do (AY)/FAC1 + +LAB_26CA + JSR LAB_264D ; unpack memory (AY) into FAC2 + + ; Perform divide-into +LAB_DIVIDE + BEQ LAB_2737 ; if zero go do /0 error + + JSR LAB_27BA ; round FAC1 + LDA #$00 ; clear A + SEC ; set carry for subtract + SBC FAC1_e ; subtract FAC1 exponent (2s complement) + STA FAC1_e ; save FAC1 exponent + JSR LAB_2673 ; test and adjust accumulators + INC FAC1_e ; increment FAC1 exponent + BEQ LAB_269B ; if zero do overflow error + + LDX #$FF ; set index for pre increment + LDA #$01 ; set bit to flag byte save +LAB_26E4 + LDY FAC2_1 ; get FAC2 mantissa1 + CPY FAC1_1 ; compare FAC1 mantissa1 + BNE LAB_26F4 ; branch if <> + + LDY FAC2_2 ; get FAC2 mantissa2 + CPY FAC1_2 ; compare FAC1 mantissa2 + BNE LAB_26F4 ; branch if <> + + LDY FAC2_3 ; get FAC2 mantissa3 + CPY FAC1_3 ; compare FAC1 mantissa3 +LAB_26F4 + PHP ; save FAC2-FAC1 compare status + ROL ; shift the result byte + BCC LAB_2702 ; if no carry skip the byte save + + LDY #$01 ; set bit to flag byte save + INX ; else increment the index to FACt + CPX #$02 ; compare with the index to FACt_3 + BMI LAB_2701 ; if not last byte just go save it + + BNE LAB_272B ; if all done go save FAC1 rounding byte, normalise and + ; return + + LDY #$40 ; set bit to flag byte save for the rounding byte +LAB_2701 + STA FACt_1,X ; write result byte to FACt_1 + index + TYA ; copy the next save byte flag +LAB_2702 + PLP ; restore FAC2-FAC1 compare status + BCC LAB_2704 ; if FAC2 < FAC1 then skip the subtract + + TAY ; save FAC2-FAC1 compare status + LDA FAC2_3 ; get FAC2 mantissa3 + SBC FAC1_3 ; subtract FAC1 mantissa3 + STA FAC2_3 ; save FAC2 mantissa3 + LDA FAC2_2 ; get FAC2 mantissa2 + SBC FAC1_2 ; subtract FAC1 mantissa2 + STA FAC2_2 ; save FAC2 mantissa2 + LDA FAC2_1 ; get FAC2 mantissa1 + SBC FAC1_1 ; subtract FAC1 mantissa1 + STA FAC2_1 ; save FAC2 mantissa1 + TYA ; restore FAC2-FAC1 compare status + + ; FAC2 = FAC2*2 +LAB_2704 + ASL FAC2_3 ; shift FAC2 mantissa3 + ROL FAC2_2 ; shift FAC2 mantissa2 + ROL FAC2_1 ; shift FAC2 mantissa1 + BCS LAB_26F4 ; loop with no compare + + BMI LAB_26E4 ; loop with compare + + BPL LAB_26F4 ; loop always with no compare + +; do A<<6, save as FAC1 rounding byte, normalise and return + +LAB_272B + LSR ; shift b1 - b0 .. + ROR ; .. + ROR ; .. to b7 - b6 + STA FAC1_r ; save FAC1 rounding byte + PLP ; dump FAC2-FAC1 compare status + JMP LAB_273C ; copy temp to FAC1, normalise and return + +; do "Divide by zero" error + +LAB_2737 + LDX #$14 ; error code $14 ("Divide by zero" error) + JMP LAB_XERR ; do error #X, then warm start + +; copy temp to FAC1 and normalise + +LAB_273C + LDA FACt_1 ; get temp mantissa1 + STA FAC1_1 ; save FAC1 mantissa1 + LDA FACt_2 ; get temp mantissa2 + STA FAC1_2 ; save FAC1 mantissa2 + LDA FACt_3 ; get temp mantissa3 + STA FAC1_3 ; save FAC1 mantissa3 + JMP LAB_24D5 ; normalise FAC1 and return + +; unpack memory (AY) into FAC1 + +LAB_UFAC + STA ut1_pl ; save pointer low byte + STY ut1_ph ; save pointer high byte + LDY #$03 ; 4 bytes to do + LDA (ut1_pl),Y ; get last byte + STA FAC1_3 ; save FAC1 mantissa3 + DEY ; decrement index + LDA (ut1_pl),Y ; get last-1 byte + STA FAC1_2 ; save FAC1 mantissa2 + DEY ; decrement index + LDA (ut1_pl),Y ; get second byte + STA FAC1_s ; save FAC1 sign (b7) + ORA #$80 ; set 1xxx xxxx (add normal bit) + STA FAC1_1 ; save FAC1 mantissa1 + DEY ; decrement index + LDA (ut1_pl),Y ; get first byte (exponent) + STA FAC1_e ; save FAC1 exponent + STY FAC1_r ; clear FAC1 rounding byte + RTS + +; pack FAC1 into Adatal + +LAB_276E + LDX #Adatal ; set pointer high byte + BEQ LAB_2778 ; pack FAC1 into (XY) and return + +; pack FAC1 into (Lvarpl) + +LAB_PFAC + LDX Lvarpl ; get destination pointer low byte + LDY Lvarph ; get destination pointer high byte + +; pack FAC1 into (XY) + +LAB_2778 + JSR LAB_27BA ; round FAC1 + STX ut1_pl ; save pointer low byte + STY ut1_ph ; save pointer high byte + LDY #$03 ; set index + LDA FAC1_3 ; get FAC1 mantissa3 + STA (ut1_pl),Y ; store in destination + DEY ; decrement index + LDA FAC1_2 ; get FAC1 mantissa2 + STA (ut1_pl),Y ; store in destination + DEY ; decrement index + LDA FAC1_s ; get FAC1 sign (b7) + ORA #$7F ; set bits x111 1111 + AND FAC1_1 ; AND in FAC1 mantissa1 + STA (ut1_pl),Y ; store in destination + DEY ; decrement index + LDA FAC1_e ; get FAC1 exponent + STA (ut1_pl),Y ; store in destination + STY FAC1_r ; clear FAC1 rounding byte + RTS + +; round and copy FAC1 to FAC2 + +LAB_27AB + JSR LAB_27BA ; round FAC1 + +; copy FAC1 to FAC2 + +LAB_27AE + LDX #$05 ; 5 bytes to copy +LAB_27B0 + LDA FAC1_e-1,X ; get byte from FAC1,X + STA FAC1_o,X ; save byte at FAC2,X + DEX ; decrement count + BNE LAB_27B0 ; loop if not all done + + STX FAC1_r ; clear FAC1 rounding byte +LAB_27B9 + RTS + +; round FAC1 + +LAB_27BA + LDA FAC1_e ; get FAC1 exponent + BEQ LAB_27B9 ; exit if zero + + ASL FAC1_r ; shift FAC1 rounding byte + BCC LAB_27B9 ; exit if no overflow + +; round FAC1 (no check) + +LAB_27C2 + JSR LAB_2559 ; increment FAC1 mantissa + BNE LAB_27B9 ; branch if no overflow + + JMP LAB_252A ; normalise FAC1 for C=1 and return + +; get FAC1 sign +; return A=FF,C=1/-ve A=01,C=0/+ve + +LAB_27CA + LDA FAC1_e ; get FAC1 exponent + BEQ LAB_27D7 ; exit if zero (already correct SGN(0)=0) + +; return A=FF,C=1/-ve A=01,C=0/+ve +; no = 0 check + +LAB_27CE + LDA FAC1_s ; else get FAC1 sign (b7) + +; return A=FF,C=1/-ve A=01,C=0/+ve +; no = 0 check, sign in A + +LAB_27D0 + ROL ; move sign bit to carry + LDA #$FF ; set byte for -ve result + BCS LAB_27D7 ; return if sign was set (-ve) + + LDA #$01 ; else set byte for +ve result +LAB_27D7 + RTS + +; perform SGN() + +LAB_SGN + JSR LAB_27CA ; get FAC1 sign + ; return A=$FF/-ve A=$01/+ve +; save A as integer byte + +LAB_27DB + STA FAC1_1 ; save FAC1 mantissa1 + LDA #$00 ; clear A + STA FAC1_2 ; clear FAC1 mantissa2 + LDX #$88 ; set exponent + +; set exp=X, clearFAC1 mantissa3 and normalise + +LAB_27E3 + LDA FAC1_1 ; get FAC1 mantissa1 + EOR #$FF ; complement it + ROL ; sign bit into carry + +; set exp=X, clearFAC1 mantissa3 and normalise + +LAB_STFA + LDA #$00 ; clear A + STA FAC1_3 ; clear FAC1 mantissa3 + STX FAC1_e ; set FAC1 exponent + STA FAC1_r ; clear FAC1 rounding byte + STA FAC1_s ; clear FAC1 sign (b7) + JMP LAB_24D0 ; do ABS and normalise FAC1 + +; perform ABS() + +LAB_ABS + LSR FAC1_s ; clear FAC1 sign (put zero in b7) + RTS + +; compare FAC1 with (AY) +; returns A=$00 if FAC1 = (AY) +; returns A=$01 if FAC1 > (AY) +; returns A=$FF if FAC1 < (AY) + +LAB_27F8 + STA ut2_pl ; save pointer low byte +LAB_27FA + STY ut2_ph ; save pointer high byte + LDY #$00 ; clear index + LDA (ut2_pl),Y ; get exponent + INY ; increment index + TAX ; copy (AY) exponent to X + BEQ LAB_27CA ; branch if (AY) exponent=0 and get FAC1 sign + ; A=FF,C=1/-ve A=01,C=0/+ve + + LDA (ut2_pl),Y ; get (AY) mantissa1 (with sign) + EOR FAC1_s ; EOR FAC1 sign (b7) + BMI LAB_27CE ; if signs <> do return A=FF,C=1/-ve + ; A=01,C=0/+ve and return + + CPX FAC1_e ; compare (AY) exponent with FAC1 exponent + BNE LAB_2828 ; branch if different + + LDA (ut2_pl),Y ; get (AY) mantissa1 (with sign) + ORA #$80 ; normalise top bit + CMP FAC1_1 ; compare with FAC1 mantissa1 + BNE LAB_2828 ; branch if different + + INY ; increment index + LDA (ut2_pl),Y ; get mantissa2 + CMP FAC1_2 ; compare with FAC1 mantissa2 + BNE LAB_2828 ; branch if different + + INY ; increment index + LDA #$7F ; set for 1/2 value rounding byte + CMP FAC1_r ; compare with FAC1 rounding byte (set carry) + LDA (ut2_pl),Y ; get mantissa3 + SBC FAC1_3 ; subtract FAC1 mantissa3 + BEQ LAB_2850 ; exit if mantissa3 equal + +; gets here if number <> FAC1 + +LAB_2828 + LDA FAC1_s ; get FAC1 sign (b7) + BCC LAB_282E ; branch if FAC1 > (AY) + + EOR #$FF ; else toggle FAC1 sign +LAB_282E + JMP LAB_27D0 ; return A=FF,C=1/-ve A=01,C=0/+ve + +; convert FAC1 floating-to-fixed + +LAB_2831 + LDA FAC1_e ; get FAC1 exponent + BEQ LAB_287F ; if zero go clear FAC1 and return + + SEC ; set carry for subtract + SBC #$98 ; subtract maximum integer range exponent + BIT FAC1_s ; test FAC1 sign (b7) + BPL LAB_2845 ; branch if FAC1 +ve + + ; FAC1 was -ve + TAX ; copy subtracted exponent + LDA #$FF ; overflow for -ve number + STA FAC1_o ; set FAC1 overflow byte + JSR LAB_253D ; twos complement FAC1 mantissa + TXA ; restore subtracted exponent +LAB_2845 + LDX #FAC1_e ; set index to FAC1 + CMP #$F9 ; compare exponent result + BPL LAB_2851 ; if < 8 shifts shift FAC1 A times right and return + + JSR LAB_257B ; shift FAC1 A times right (> 8 shifts) + STY FAC1_o ; clear FAC1 overflow byte +LAB_2850 + RTS + +; shift FAC1 A times right + +LAB_2851 + TAY ; copy shift count + LDA FAC1_s ; get FAC1 sign (b7) + AND #$80 ; mask sign bit only (x000 0000) + LSR FAC1_1 ; shift FAC1 mantissa1 + ORA FAC1_1 ; OR sign in b7 FAC1 mantissa1 + STA FAC1_1 ; save FAC1 mantissa1 + JSR LAB_2592 ; shift FAC1 Y times right + STY FAC1_o ; clear FAC1 overflow byte + RTS + +; perform INT() + +LAB_INT + LDA FAC1_e ; get FAC1 exponent + CMP #$98 ; compare with max int + BCS LAB_2886 ; exit if >= (already int, too big for fractional part!) + + JSR LAB_2831 ; convert FAC1 floating-to-fixed + STY FAC1_r ; save FAC1 rounding byte + LDA FAC1_s ; get FAC1 sign (b7) + STY FAC1_s ; save FAC1 sign (b7) + EOR #$80 ; toggle FAC1 sign + ROL ; shift into carry + LDA #$98 ; set new exponent + STA FAC1_e ; save FAC1 exponent + LDA FAC1_3 ; get FAC1 mantissa3 + STA Temp3 ; save for EXP() function + JMP LAB_24D0 ; do ABS and normalise FAC1 + +; clear FAC1 and return + +LAB_287F + STA FAC1_1 ; clear FAC1 mantissa1 + STA FAC1_2 ; clear FAC1 mantissa2 + STA FAC1_3 ; clear FAC1 mantissa3 + TAY ; clear Y +LAB_2886 + RTS + +; get FAC1 from string +; this routine now handles hex and binary values from strings +; starting with "$" and "%" respectively + +LAB_2887 + LDY #$00 ; clear Y + STY Dtypef ; clear data type flag, $FF=string, $00=numeric + LDX #$09 ; set index +LAB_288B + STY numexp,X ; clear byte + DEX ; decrement index + BPL LAB_288B ; loop until numexp to negnum (and FAC1) = $00 + + BCC LAB_28FE ; branch if 1st character numeric + +; get FAC1 from string .. first character wasn't numeric + + CMP #'-' ; else compare with "-" + BNE LAB_289A ; branch if not "-" + + STX negnum ; set flag for -ve number (X = $FF) + BEQ LAB_289C ; branch always (go scan and check for hex/bin) + +; get FAC1 from string .. first character wasn't numeric or - + +LAB_289A + CMP #'+' ; else compare with "+" + BNE LAB_289D ; branch if not "+" (go check for hex/bin) + +; was "+" or "-" to start, so get next character + +LAB_289C + JSR LAB_IGBY ; increment and scan memory + BCC LAB_28FE ; branch if numeric character + +; code here for hex and binary numbers + +LAB_289D + CMP #'$' ; else compare with "$" + BNE LAB_NHEX ; branch if not "$" + + JMP LAB_CHEX ; branch if "$" + +LAB_NHEX + CMP #'%' ; else compare with "%" + BNE LAB_28A3 ; branch if not "%" (continue original code) + + JMP LAB_CBIN ; branch if "%" + +LAB_289E + JSR LAB_IGBY ; increment and scan memory (ignore + or get next number) +LAB_28A1 + BCC LAB_28FE ; branch if numeric character + +; get FAC1 from string .. character wasn't numeric, -, +, hex or binary + +LAB_28A3 + CMP #'.' ; else compare with "." + BEQ LAB_28D5 ; branch if "." + +; get FAC1 from string .. character wasn't numeric, -, + or . + + CMP #'E' ; else compare with "E" + BNE LAB_28DB ; branch if not "E" + + ; was "E" so evaluate exponential part + JSR LAB_IGBY ; increment and scan memory + BCC LAB_28C7 ; branch if numeric character + + CMP #TK_MINUS ; else compare with token for - + BEQ LAB_28C2 ; branch if token for - + + CMP #'-' ; else compare with "-" + BEQ LAB_28C2 ; branch if "-" + + CMP #TK_PLUS ; else compare with token for + + BEQ LAB_28C4 ; branch if token for + + + CMP #'+' ; else compare with "+" + BEQ LAB_28C4 ; branch if "+" + + BNE LAB_28C9 ; branch always + +LAB_28C2 + ROR expneg ; set exponent -ve flag (C, which=1, into b7) +LAB_28C4 + JSR LAB_IGBY ; increment and scan memory +LAB_28C7 + BCC LAB_2925 ; branch if numeric character + +LAB_28C9 + BIT expneg ; test exponent -ve flag + BPL LAB_28DB ; if +ve go evaluate exponent + + ; else do exponent = -exponent + LDA #$00 ; clear result + SEC ; set carry for subtract + SBC expcnt ; subtract exponent byte + JMP LAB_28DD ; go evaluate exponent + +LAB_28D5 + ROR numdpf ; set decimal point flag + BIT numdpf ; test decimal point flag + BVC LAB_289E ; branch if only one decimal point so far + + ; evaluate exponent +LAB_28DB + LDA expcnt ; get exponent count byte +LAB_28DD + SEC ; set carry for subtract + SBC numexp ; subtract numerator exponent + STA expcnt ; save exponent count byte + BEQ LAB_28F6 ; branch if no adjustment + + BPL LAB_28EF ; else if +ve go do FAC1*10^expcnt + + ; else go do FAC1/10^(0-expcnt) +LAB_28E6 + JSR LAB_26B9 ; divide by 10 + INC expcnt ; increment exponent count byte + BNE LAB_28E6 ; loop until all done + + BEQ LAB_28F6 ; branch always + +LAB_28EF + JSR LAB_269E ; multiply by 10 + DEC expcnt ; decrement exponent count byte + BNE LAB_28EF ; loop until all done + +LAB_28F6 + LDA negnum ; get -ve flag + BMI LAB_28FB ; if -ve do - FAC1 and return + + RTS + +; do - FAC1 and return + +LAB_28FB + JMP LAB_GTHAN ; do - FAC1 and return + +; do unsigned FAC1*10+number + +LAB_28FE + PHA ; save character + BIT numdpf ; test decimal point flag + BPL LAB_2905 ; skip exponent increment if not set + + INC numexp ; else increment number exponent +LAB_2905 + JSR LAB_269E ; multiply FAC1 by 10 + PLA ; restore character + AND #$0F ; convert to binary + JSR LAB_2912 ; evaluate new ASCII digit + JMP LAB_289E ; go do next character + +; evaluate new ASCII digit + +LAB_2912 + PHA ; save digit + JSR LAB_27AB ; round and copy FAC1 to FAC2 + PLA ; restore digit + JSR LAB_27DB ; save A as integer byte + LDA FAC2_s ; get FAC2 sign (b7) + EOR FAC1_s ; toggle with FAC1 sign (b7) + STA FAC_sc ; save sign compare (FAC1 EOR FAC2) + LDX FAC1_e ; get FAC1 exponent + JMP LAB_ADD ; add FAC2 to FAC1 and return + +; evaluate next character of exponential part of number + +LAB_2925 + LDA expcnt ; get exponent count byte + CMP #$0A ; compare with 10 decimal + BCC LAB_2934 ; branch if less + + LDA #$64 ; make all -ve exponents = -100 decimal (causes underflow) + BIT expneg ; test exponent -ve flag + BMI LAB_2942 ; branch if -ve + + JMP LAB_2564 ; else do overflow error + +LAB_2934 + ASL ; * 2 + ASL ; * 4 + ADC expcnt ; * 5 + ASL ; * 10 + LDY #$00 ; set index + ADC (Bpntrl),Y ; add character (will be $30 too much!) + SBC #'0'-1 ; convert character to binary +LAB_2942 + STA expcnt ; save exponent count byte + JMP LAB_28C4 ; go get next character + +; print " in line [LINE #]" + +LAB_2953 + LDA #LAB_LMSG ; point to " in line " message high byte + JSR LAB_18C3 ; print null terminated string from memory + + ; print Basic line # + LDA Clineh ; get current line high byte + LDX Clinel ; get current line low byte + +; print XA as unsigned integer + +LAB_295E + STA FAC1_1 ; save low byte as FAC1 mantissa1 + STX FAC1_2 ; save high byte as FAC1 mantissa2 + LDX #$90 ; set exponent to 16d bits + SEC ; set integer is +ve flag + JSR LAB_STFA ; set exp=X, clearFAC1 mantissa3 and normalise + LDY #$00 ; clear index + TYA ; clear A + JSR LAB_297B ; convert FAC1 to string, skip sign character save + JMP LAB_18C3 ; print null terminated string from memory and return + +; convert FAC1 to ASCII string result in (AY) +; not any more, moved scratchpad to page 0 + +LAB_296E + LDY #$01 ; set index = 1 + LDA #$20 ; character = " " (assume +ve) + BIT FAC1_s ; test FAC1 sign (b7) + BPL LAB_2978 ; branch if +ve + + LDA #$2D ; else character = "-" +LAB_2978 + STA Decss,Y ; save leading character (" " or "-") +LAB_297B + STA FAC1_s ; clear FAC1 sign (b7) + STY Sendl ; save index + INY ; increment index + LDX FAC1_e ; get FAC1 exponent + BNE LAB_2989 ; branch if FAC1<>0 + + ; exponent was $00 so FAC1 is 0 + LDA #'0' ; set character = "0" + JMP LAB_2A89 ; save last character, [EOT] and exit + + ; FAC1 is some non zero value +LAB_2989 + LDA #$00 ; clear (number exponent count) + CPX #$81 ; compare FAC1 exponent with $81 (>1.00000) + + BCS LAB_299A ; branch if FAC1=>1 + + ; FAC1<1 + LDA #LAB_294F ; set pointer high byte to 1,000,000 + JSR LAB_25FB ; do convert AY, FCA1*(AY) + LDA #$FA ; set number exponent count (-6) +LAB_299A + STA numexp ; save number exponent count +LAB_299C + LDA #LAB_294B ; set pointer high byte to 999999.4375 + JSR LAB_27F8 ; compare FAC1 with (AY) + BEQ LAB_29C3 ; exit if FAC1 = (AY) + + BPL LAB_29B9 ; go do /10 if FAC1 > (AY) + + ; FAC1 < (AY) +LAB_29A7 + LDA #LAB_2947 ; set pointer high byte to 99999.9375 + JSR LAB_27F8 ; compare FAC1 with (AY) + BEQ LAB_29B2 ; branch if FAC1 = (AY) (allow decimal places) + + BPL LAB_29C0 ; branch if FAC1 > (AY) (no decimal places) + + ; FAC1 <= (AY) +LAB_29B2 + JSR LAB_269E ; multiply by 10 + DEC numexp ; decrement number exponent count + BNE LAB_29A7 ; go test again (branch always) + +LAB_29B9 + JSR LAB_26B9 ; divide by 10 + INC numexp ; increment number exponent count + BNE LAB_299C ; go test again (branch always) + +; now we have just the digits to do + +LAB_29C0 + JSR LAB_244E ; add 0.5 to FAC1 (round FAC1) +LAB_29C3 + JSR LAB_2831 ; convert FAC1 floating-to-fixed + LDX #$01 ; set default digits before dp = 1 + LDA numexp ; get number exponent count + CLC ; clear carry for add + ADC #$07 ; up to 6 digits before point + BMI LAB_29D8 ; if -ve then 1 digit before dp + + CMP #$08 ; A>=8 if n>=1E6 + BCS LAB_29D9 ; branch if >= $08 + + ; carry is clear + ADC #$FF ; take 1 from digit count + TAX ; copy to A + LDA #$02 ;.set exponent adjust +LAB_29D8 + SEC ; set carry for subtract +LAB_29D9 + SBC #$02 ; -2 + STA expcnt ;.save exponent adjust + STX numexp ; save digits before dp count + TXA ; copy to A + BEQ LAB_29E4 ; branch if no digits before dp + + BPL LAB_29F7 ; branch if digits before dp + +LAB_29E4 + LDY Sendl ; get output string index + LDA #$2E ; character "." + INY ; increment index + STA Decss,Y ; save to output string + TXA ;. + BEQ LAB_29F5 ;. + + LDA #'0' ; character "0" + INY ; increment index + STA Decss,Y ; save to output string +LAB_29F5 + STY Sendl ; save output string index +LAB_29F7 + LDY #$00 ; clear index (point to 100,000) + LDX #$80 ; +LAB_29FB + LDA FAC1_3 ; get FAC1 mantissa3 + CLC ; clear carry for add + ADC LAB_2A9C,Y ; add -ve LSB + STA FAC1_3 ; save FAC1 mantissa3 + LDA FAC1_2 ; get FAC1 mantissa2 + ADC LAB_2A9B,Y ; add -ve NMSB + STA FAC1_2 ; save FAC1 mantissa2 + LDA FAC1_1 ; get FAC1 mantissa1 + ADC LAB_2A9A,Y ; add -ve MSB + STA FAC1_1 ; save FAC1 mantissa1 + INX ; + BCS LAB_2A18 ; + + BPL LAB_29FB ; not -ve so try again + + BMI LAB_2A1A ; + +LAB_2A18 + BMI LAB_29FB ; + +LAB_2A1A + TXA ; + BCC LAB_2A21 ; + + EOR #$FF ; + ADC #$0A ; +LAB_2A21 + ADC #'0'-1 ; add "0"-1 to result + INY ; increment index .. + INY ; .. to next less .. + INY ; .. power of ten + STY Cvaral ; save as current var address low byte + LDY Sendl ; get output string index + INY ; increment output string index + TAX ; copy character to X + AND #$7F ; mask out top bit + STA Decss,Y ; save to output string + DEC numexp ; decrement # of characters before the dp + BNE LAB_2A3B ; branch if still characters to do + + ; else output the point + LDA #$2E ; character "." + INY ; increment output string index + STA Decss,Y ; save to output string +LAB_2A3B + STY Sendl ; save output string index + LDY Cvaral ; get current var address low byte + TXA ; get character back + EOR #$FF ; + AND #$80 ; + TAX ; + CPY #$12 ; compare index with max + BNE LAB_29FB ; loop if not max + + ; now remove trailing zeroes + LDY Sendl ; get output string index +LAB_2A4B + LDA Decss,Y ; get character from output string + DEY ; decrement output string index + CMP #'0' ; compare with "0" + BEQ LAB_2A4B ; loop until non "0" character found + + CMP #'.' ; compare with "." + BEQ LAB_2A58 ; branch if was dp + + ; restore last character + INY ; increment output string index +LAB_2A58 + LDA #$2B ; character "+" + LDX expcnt ; get exponent count + BEQ LAB_2A8C ; if zero go set null terminator and exit + + ; exponent isn't zero so write exponent + BPL LAB_2A68 ; branch if exponent count +ve + + LDA #$00 ; clear A + SEC ; set carry for subtract + SBC expcnt ; subtract exponent count adjust (convert -ve to +ve) + TAX ; copy exponent count to X + LDA #'-' ; character "-" +LAB_2A68 + STA Decss+2,Y ; save to output string + LDA #$45 ; character "E" + STA Decss+1,Y ; save exponent sign to output string + TXA ; get exponent count back + LDX #'0'-1 ; one less than "0" character + SEC ; set carry for subtract +LAB_2A74 + INX ; increment 10's character + SBC #$0A ;.subtract 10 from exponent count + BCS LAB_2A74 ; loop while still >= 0 + + ADC #':' ; add character ":" ($30+$0A, result is 10 less that value) + STA Decss+4,Y ; save to output string + TXA ; copy 10's character + STA Decss+3,Y ; save to output string + LDA #$00 ; set null terminator + STA Decss+5,Y ; save to output string + BEQ LAB_2A91 ; go set string pointer (AY) and exit (branch always) + + ; save last character, [EOT] and exit +LAB_2A89 + STA Decss,Y ; save last character to output string + + ; set null terminator and exit +LAB_2A8C + LDA #$00 ; set null terminator + STA Decss+1,Y ; save after last character + + ; set string pointer (AY) and exit +LAB_2A91 + LDA #Decssp1 ; set result string high pointer + RTS + +; perform power function + +LAB_POWER + BEQ LAB_EXP ; go do EXP() + + LDA FAC2_e ; get FAC2 exponent + BNE LAB_2ABF ; branch if FAC2<>0 + + JMP LAB_24F3 ; clear FAC1 exponent and sign and return + +LAB_2ABF + LDX #func_l ; set destination pointer high byte + JSR LAB_2778 ; pack FAC1 into (XY) + LDA FAC2_s ; get FAC2 sign (b7) + BPL LAB_2AD9 ; branch if FAC2>0 + + ; else FAC2 is -ve and can only be raised to an + ; integer power which gives an x +j0 result + JSR LAB_INT ; perform INT + LDA #func_l ; set source pointer high byte + JSR LAB_27F8 ; compare FAC1 with (AY) + BNE LAB_2AD9 ; branch if FAC1 <> (AY) to allow Function Call error + ; this will leave FAC1 -ve and cause a Function Call + ; error when LOG() is called + + TYA ; clear sign b7 + LDY Temp3 ; save mantissa 3 from INT() function as sign in Y + ; for possible later negation, b0 +LAB_2AD9 + JSR LAB_279D ; save FAC1 sign and copy ABS(FAC2) to FAC1 + TYA ; copy sign back .. + PHA ; .. and save it + JSR LAB_LOG ; do LOG(n) + LDA #garb_l ; set pointer high byte + JSR LAB_25FB ; do convert AY, FCA1*(AY) (square the value) + JSR LAB_EXP ; go do EXP(n) + PLA ; pull sign from stack + LSR ; b0 is to be tested, shift to Cb + BCC LAB_2AF9 ; if no bit then exit + + ; Perform negation +; do - FAC1 + +LAB_GTHAN + LDA FAC1_e ; get FAC1 exponent + BEQ LAB_2AF9 ; exit if FAC1_e = $00 + + LDA FAC1_s ; get FAC1 sign (b7) + EOR #$FF ; complement it + STA FAC1_s ; save FAC1 sign (b7) +LAB_2AF9 + RTS + +; perform EXP() (x^e) + +LAB_EXP + LDA #LAB_2AFA ; set 1.443 pointer high byte + JSR LAB_25FB ; do convert AY, FCA1*(AY) + LDA FAC1_r ; get FAC1 rounding byte + ADC #$50 ; +$50/$100 + BCC LAB_2B2B ; skip rounding if no carry + + JSR LAB_27C2 ; round FAC1 (no check) +LAB_2B2B + STA FAC2_r ; save FAC2 rounding byte + JSR LAB_27AE ; copy FAC1 to FAC2 + LDA FAC1_e ; get FAC1 exponent + CMP #$88 ; compare with EXP limit (256d) + BCC LAB_2B39 ; branch if less + +LAB_2B36 + JSR LAB_2690 ; handle overflow and underflow +LAB_2B39 + JSR LAB_INT ; perform INT + LDA Temp3 ; get mantissa 3 from INT() function + CLC ; clear carry for add + ADC #$81 ; normalise +1 + BEQ LAB_2B36 ; if $00 go handle overflow + + SEC ; set carry for subtract + SBC #$01 ; now correct for exponent + PHA ; save FAC2 exponent + + ; swap FAC1 and FAC2 + LDX #$04 ; 4 bytes to do +LAB_2B49 + LDA FAC2_e,X ; get FAC2,X + LDY FAC1_e,X ; get FAC1,X + STA FAC1_e,X ; save FAC1,X + STY FAC2_e,X ; save FAC2,X + DEX ; decrement count/index + BPL LAB_2B49 ; loop if not all done + + LDA FAC2_r ; get FAC2 rounding byte + STA FAC1_r ; save as FAC1 rounding byte + JSR LAB_SUBTRACT ; perform subtraction, FAC2 from FAC1 + JSR LAB_GTHAN ; do - FAC1 + LDA #LAB_2AFE ; set counter pointer high byte + JSR LAB_2B84 ; go do series evaluation + LDA #$00 ; clear A + STA FAC_sc ; clear sign compare (FAC1 EOR FAC2) + PLA ;.get saved FAC2 exponent + JMP LAB_2675 ; test and adjust accumulators and return + +; ^2 then series evaluation + +LAB_2B6E + STA Cptrl ; save count pointer low byte + STY Cptrh ; save count pointer high byte + JSR LAB_276E ; pack FAC1 into Adatal + LDA #Adatal ; pointer to original # high byte + JMP LAB_25FB ; do convert AY, FCA1*(AY) and return + +; series evaluation + +LAB_2B84 + STA Cptrl ; save count pointer low byte + STY Cptrh ; save count pointer high byte +LAB_2B88 + LDX #numexp ; set pointer high byte to partial @ numexp + DEC numcon ; decrement constants count + BNE LAB_2B9B ; loop until all done + + RTS + +; RND(n), 32 bit Galoise version. make n=0 for 19th next number in sequence or n<>0 +; to get 19th next number in sequence after seed n. This version of the PRNG uses +; the Galois method and a sample of 65536 bytes produced gives the following values. + +; Entropy = 7.997442 bits per byte +; Optimum compression would reduce these 65536 bytes by 0 percent + +; Chi square distribution for 65536 samples is 232.01, and +; randomly would exceed this value 75.00 percent of the time + +; Arithmetic mean value of data bytes is 127.6724, 127.5 would be random +; Monte Carlo value for Pi is 3.122871269, error 0.60 percent +; Serial correlation coefficient is -0.000370, totally uncorrelated would be 0.0 + +LAB_RND + LDA FAC1_e ; get FAC1 exponent + BEQ NextPRN ; do next random # if zero + + ; else get seed into random number store + LDX #Rbyte4 ; set PRNG pointer low byte + LDY #$00 ; set PRNG pointer high byte + JSR LAB_2778 ; pack FAC1 into (XY) +NextPRN + LDX #$AF ; set EOR byte + LDY #$13 ; do this nineteen times +LoopPRN + ASL Rbyte1 ; shift PRNG most significant byte + ROL Rbyte2 ; shift PRNG middle byte + ROL Rbyte3 ; shift PRNG least significant byte + ROL Rbyte4 ; shift PRNG extra byte + BCC Ninc1 ; branch if bit 32 clear + + TXA ; set EOR byte + EOR Rbyte1 ; EOR PRNG extra byte + STA Rbyte1 ; save new PRNG extra byte +Ninc1 + DEY ; decrement loop count + BNE LoopPRN ; loop if not all done + + LDX #$02 ; three bytes to copy +CopyPRNG + LDA Rbyte1,X ; get PRNG byte + STA FAC1_1,X ; save FAC1 byte + DEX + BPL CopyPRNG ; loop if not complete + + LDA #$80 ; set the exponent + STA FAC1_e ; save FAC1 exponent + + ASL ; clear A + STA FAC1_s ; save FAC1 sign + + JMP LAB_24D5 ; normalise FAC1 and return + +; perform COS() + +LAB_COS + LDA #LAB_2C78 ; set (pi/2) pointer high byte + JSR LAB_246C ; add (AY) to FAC1 + +; perform SIN() + +LAB_SIN + JSR LAB_27AB ; round and copy FAC1 to FAC2 + LDA #LAB_2C7C ; set (2*pi) pointer high byte + LDX FAC2_s ; get FAC2 sign (b7) + JSR LAB_26C2 ; divide by (AY) (X=sign) + JSR LAB_27AB ; round and copy FAC1 to FAC2 + JSR LAB_INT ; perform INT + LDA #$00 ; clear byte + STA FAC_sc ; clear sign compare (FAC1 EOR FAC2) + JSR LAB_SUBTRACT ; perform subtraction, FAC2 from FAC1 + LDA #LAB_2C80 ; set 0.25 pointer high byte + JSR LAB_2455 ; perform subtraction, (AY) from FAC1 + LDA FAC1_s ; get FAC1 sign (b7) + PHA ; save FAC1 sign + BPL LAB_2C35 ; branch if +ve + + ; FAC1 sign was -ve + JSR LAB_244E ; add 0.5 to FAC1 + LDA FAC1_s ; get FAC1 sign (b7) + BMI LAB_2C38 ; branch if -ve + + LDA Cflag ; get comparison evaluation flag + EOR #$FF ; toggle flag + STA Cflag ; save comparison evaluation flag +LAB_2C35 + JSR LAB_GTHAN ; do - FAC1 +LAB_2C38 + LDA #LAB_2C80 ; set 0.25 pointer high byte + JSR LAB_246C ; add (AY) to FAC1 + PLA ; restore FAC1 sign + BPL LAB_2C45 ; branch if was +ve + + ; else correct FAC1 + JSR LAB_GTHAN ; do - FAC1 +LAB_2C45 + LDA #LAB_2C84 ; set pointer high byte to counter + JMP LAB_2B6E ; ^2 then series evaluation and return + +; perform TAN() + +LAB_TAN + JSR LAB_276E ; pack FAC1 into Adatal + LDA #$00 ; clear byte + STA Cflag ; clear comparison evaluation flag + JSR LAB_SIN ; go do SIN(n) + LDX #func_l ; set sin(n) pointer high byte + JSR LAB_2778 ; pack FAC1 into (XY) + LDA #Adatal ; set n pointer high addr + JSR LAB_UFAC ; unpack memory (AY) into FAC1 + LDA #$00 ; clear byte + STA FAC1_s ; clear FAC1 sign (b7) + LDA Cflag ; get comparison evaluation flag + JSR LAB_2C74 ; save flag and go do series evaluation + + LDA #func_l ; set sin(n) pointer high byte + JMP LAB_26CA ; convert AY and do (AY)/FAC1 + +LAB_2C74 + PHA ; save comparison evaluation flag + JMP LAB_2C35 ; go do series evaluation + +; perform USR() + +LAB_USR + JSR Usrjmp ; call user code + JMP LAB_1BFB ; scan for ")", else do syntax error then warm start + +; perform ATN() + +LAB_ATN + LDA FAC1_s ; get FAC1 sign (b7) + PHA ; save sign + BPL LAB_2CA1 ; branch if +ve + + JSR LAB_GTHAN ; else do - FAC1 +LAB_2CA1 + LDA FAC1_e ; get FAC1 exponent + PHA ; push exponent + CMP #$81 ; compare with 1 + BCC LAB_2CAF ; branch if FAC1<1 + + LDA #LAB_259C ; set 1 pointer high byte + JSR LAB_26CA ; convert AY and do (AY)/FAC1 +LAB_2CAF + LDA #LAB_2CC9 ; set pointer high byte to counter + JSR LAB_2B6E ; ^2 then series evaluation + PLA ; restore old FAC1 exponent + CMP #$81 ; compare with 1 + BCC LAB_2CC2 ; branch if FAC1<1 + + LDA #LAB_2C78 ; set (pi/2) pointer high byte + JSR LAB_2455 ; perform subtraction, (AY) from FAC1 +LAB_2CC2 + PLA ; restore FAC1 sign + BPL LAB_2D04 ; exit if was +ve + + JMP LAB_GTHAN ; else do - FAC1 and return + +; perform BITSET + +LAB_BITSET + JSR LAB_GADB ; get two parameters for POKE or WAIT + CPX #$08 ; only 0 to 7 are allowed + BCS FCError ; branch if > 7 + + LDA #$00 ; clear A + SEC ; set the carry +S_Bits + ROL ; shift bit + DEX ; decrement bit number + BPL S_Bits ; loop if still +ve + + INX ; make X = $00 + ORA (Itempl,X) ; or with byte via temporary integer (addr) + STA (Itempl,X) ; save byte via temporary integer (addr) +LAB_2D04 + RTS + +; perform BITCLR + +LAB_BITCLR + JSR LAB_GADB ; get two parameters for POKE or WAIT + CPX #$08 ; only 0 to 7 are allowed + BCS FCError ; branch if > 7 + + LDA #$FF ; set A +S_Bitc + ROL ; shift bit + DEX ; decrement bit number + BPL S_Bitc ; loop if still +ve + + INX ; make X = $00 + AND (Itempl,X) ; and with byte via temporary integer (addr) + STA (Itempl,X) ; save byte via temporary integer (addr) + RTS + +FCError + JMP LAB_FCER ; do function call error then warm start + +; perform BITTST() + +LAB_BTST + JSR LAB_IGBY ; increment BASIC pointer + JSR LAB_GADB ; get two parameters for POKE or WAIT + CPX #$08 ; only 0 to 7 are allowed + BCS FCError ; branch if > 7 + + JSR LAB_GBYT ; get next BASIC byte + CMP #')' ; is next character ")" + BEQ TST_OK ; if ")" go do rest of function + + JMP LAB_SNER ; do syntax error then warm start + +TST_OK + JSR LAB_IGBY ; update BASIC execute pointer (to character past ")") + LDA #$00 ; clear A + SEC ; set the carry +T_Bits + ROL ; shift bit + DEX ; decrement bit number + BPL T_Bits ; loop if still +ve + + INX ; make X = $00 + AND (Itempl,X) ; AND with byte via temporary integer (addr) + BEQ LAB_NOTT ; branch if zero (already correct) + + LDA #$FF ; set for -1 result +LAB_NOTT + JMP LAB_27DB ; go do SGN tail + +; perform BIN$() + +LAB_BINS + CPX #$19 ; max + 1 + BCS BinFErr ; exit if too big ( > or = ) + + STX TempB ; save # of characters ($00 = leading zero remove) + LDA #$18 ; need A byte long space + JSR LAB_MSSP ; make string space A bytes long + LDY #$17 ; set index + LDX #$18 ; character count +NextB1 + LSR nums_1 ; shift highest byte + ROR nums_2 ; shift middle byte + ROR nums_3 ; shift lowest byte bit 0 to carry + TXA ; load with "0"/2 + ROL ; shift in carry + STA (str_pl),Y ; save to temp string + index + DEY ; decrement index + BPL NextB1 ; loop if not done + + LDA TempB ; get # of characters + BEQ EndBHS ; branch if truncate + + TAX ; copy length to X + SEC ; set carry for add ! + EOR #$FF ; 1's complement + ADC #$18 ; add 24d + BEQ GoPr2 ; if zero print whole string + + BNE GoPr1 ; else go make output string + +; this is the exit code and is also used by HEX$() +; truncate string to remove leading "0"s + +EndBHS + TAY ; clear index (A=0, X=length here) +NextB2 + LDA (str_pl),Y ; get character from string + CMP #'0' ; compare with "0" + BNE GoPr ; if not "0" then go print string from here + + DEX ; decrement character count + BEQ GoPr3 ; if zero then end of string so go print it + + INY ; else increment index + BPL NextB2 ; loop always + +; make fixed length output string - ignore overflows! + +GoPr3 + INX ; need at least 1 character +GoPr + TYA ; copy result +GoPr1 + CLC ; clear carry for add + ADC str_pl ; add low address + STA str_pl ; save low address + LDA #$00 ; do high byte + ADC str_ph ; add high address + STA str_ph ; save high address +GoPr2 + STX str_ln ; X holds string length + JSR LAB_IGBY ; update BASIC execute pointer (to character past ")") + JMP LAB_RTST ; check for space on descriptor stack then put address + ; and length on descriptor stack and update stack pointers + +BinFErr + JMP LAB_FCER ; do function call error then warm start + +; perform HEX$() + +LAB_HEXS + CPX #$07 ; max + 1 + BCS BinFErr ; exit if too big ( > or = ) + + STX TempB ; save # of characters + + LDA #$06 ; need 6 bytes for string + JSR LAB_MSSP ; make string space A bytes long + LDY #$05 ; set string index + + SED ; need decimal mode for nibble convert + LDA nums_3 ; get lowest byte + JSR LAB_A2HX ; convert A to ASCII hex byte and output + LDA nums_2 ; get middle byte + JSR LAB_A2HX ; convert A to ASCII hex byte and output + LDA nums_1 ; get highest byte + JSR LAB_A2HX ; convert A to ASCII hex byte and output + CLD ; back to binary + + LDX #$06 ; character count + LDA TempB ; get # of characters + BEQ EndBHS ; branch if truncate + + TAX ; copy length to X + SEC ; set carry for add ! + EOR #$FF ; 1's complement + ADC #$06 ; add 6d + BEQ GoPr2 ; if zero print whole string + + BNE GoPr1 ; else go make output string (branch always) + +; convert A to ASCII hex byte and output .. note set decimal mode before calling + +LAB_A2HX + TAX ; save byte + AND #$0F ; mask off top bits + JSR LAB_AL2X ; convert low nibble to ASCII and output + TXA ; get byte back + LSR ; /2 shift high nibble to low nibble + LSR ; /4 + LSR ; /8 + LSR ; /16 +LAB_AL2X + CMP #$0A ; set carry for +1 if >9 + ADC #'0' ; add ASCII "0" + STA (str_pl),Y ; save to temp string + DEY ; decrement counter + RTS + +LAB_NLTO + STA FAC1_e ; save FAC1 exponent + LDA #$00 ; clear sign compare +LAB_MLTE + STA FAC_sc ; save sign compare (FAC1 EOR FAC2) + TXA ; restore character + JSR LAB_2912 ; evaluate new ASCII digit + +; gets here if the first character was "$" for hex +; get hex number + +LAB_CHEX + JSR LAB_IGBY ; increment and scan memory + BCC LAB_ISHN ; branch if numeric character + + ORA #$20 ; case convert, allow "A" to "F" and "a" to "f" + SBC #'a' ; subtract "a" (carry set here) + CMP #$06 ; compare normalised with $06 (max+1) + BCS LAB_EXCH ; exit if >"f" or <"0" + + ADC #$0A ; convert to nibble +LAB_ISHN + AND #$0F ; convert to binary + TAX ; save nibble + LDA FAC1_e ; get FAC1 exponent + BEQ LAB_MLTE ; skip multiply if zero + + ADC #$04 ; add four to exponent (*16 - carry clear here) + BCC LAB_NLTO ; if no overflow do evaluate digit + +LAB_MLTO + JMP LAB_2564 ; do overflow error and warm start + +LAB_NXCH + TAX ; save bit + LDA FAC1_e ; get FAC1 exponent + BEQ LAB_MLBT ; skip multiply if zero + + INC FAC1_e ; increment FAC1 exponent (*2) + BEQ LAB_MLTO ; do overflow error if = $00 + + LDA #$00 ; clear sign compare +LAB_MLBT + STA FAC_sc ; save sign compare (FAC1 EOR FAC2) + TXA ; restore bit + JSR LAB_2912 ; evaluate new ASCII digit + +; gets here if the first character was "%" for binary +; get binary number + +LAB_CBIN + JSR LAB_IGBY ; increment and scan memory + EOR #'0' ; convert "0" to 0 etc. + CMP #$02 ; compare with max+1 + BCC LAB_NXCH ; branch exit if < 2 + +LAB_EXCH + JMP LAB_28F6 ; evaluate -ve flag and return + +; ctrl-c check routine. includes limited "life" byte save for INGET routine +; now also the code that checks to see if an interrupt has occurred + +CTRLC + LDA ccflag ; get [CTRL-C] check flag + BNE LAB_FBA2 ; exit if inhibited + + JSR V_INPT ; scan input device + BCC LAB_FBA0 ; exit if buffer empty + + STA ccbyte ; save received byte + LDX #$20 ; "life" timer for bytes + STX ccnull ; set countdown + JMP LAB_1636 ; return to BASIC + +LAB_FBA0 + LDX ccnull ; get countdown byte + BEQ LAB_FBA2 ; exit if finished + + DEC ccnull ; else decrement countdown +LAB_FBA2 + LDX #NmiBase ; set pointer to NMI values + JSR LAB_CKIN ; go check interrupt + LDX #IrqBase ; set pointer to IRQ values + JSR LAB_CKIN ; go check interrupt +LAB_CRTS + RTS + +; check whichever interrupt is indexed by X + +LAB_CKIN + LDA PLUS_0,X ; get interrupt flag byte + BPL LAB_CRTS ; branch if interrupt not enabled + +; we disable the interrupt here and make two new commands RETIRQ and RETNMI to +; automatically enable the interrupt when we exit + + ASL ; move happened bit to setup bit + AND #$40 ; mask happened bits + BEQ LAB_CRTS ; if no interrupt then exit + + STA PLUS_0,X ; save interrupt flag byte + + TXA ; copy index .. + TAY ; .. to Y + + PLA ; dump return address low byte, call from CTRL-C + PLA ; dump return address high byte + + LDA #$05 ; need 5 bytes for GOSUB + JSR LAB_1212 ; check room on stack for A bytes + LDA Bpntrh ; get BASIC execute pointer high byte + PHA ; push on stack + LDA Bpntrl ; get BASIC execute pointer low byte + PHA ; push on stack + LDA Clineh ; get current line high byte + PHA ; push on stack + LDA Clinel ; get current line low byte + PHA ; push on stack + LDA #TK_GOSUB ; token for GOSUB + PHA ; push on stack + + LDA PLUS_1,Y ; get interrupt code pointer low byte + STA Bpntrl ; save as BASIC execute pointer low byte + LDA PLUS_2,Y ; get interrupt code pointer high byte + STA Bpntrh ; save as BASIC execute pointer high byte + + JMP LAB_15C2 ; go do interpreter inner loop + ; can't RTS, we used the stack! the RTS from the ctrl-c + ; check will be taken when the RETIRQ/RETNMI/RETURN is + ; executed at the end of the subroutine + +; get byte from input device, no waiting +; returns with carry set if byte in A + +INGET + JSR V_INPT ; call scan input device + BCS LAB_FB95 ; if byte go reset timer + + LDA ccnull ; get countdown + BEQ LAB_FB96 ; exit if empty + + LDA ccbyte ; get last received byte + SEC ; flag we got a byte +LAB_FB95 + LDX #$00 ; clear X + STX ccnull ; clear timer because we got a byte +LAB_FB96 + RTS + +; these routines only enable the interrupts if the set-up flag is set +; if not they have no effect + +; perform IRQ {ON|OFF|CLEAR} + +LAB_IRQ + LDX #IrqBase ; set pointer to IRQ values + .byte $2C ; make next line BIT abs. + +; perform NMI {ON|OFF|CLEAR} + +LAB_NMI + LDX #NmiBase ; set pointer to NMI values + CMP #TK_ON ; compare with token for ON + BEQ LAB_INON ; go turn on interrupt + + CMP #TK_OFF ; compare with token for OFF + BEQ LAB_IOFF ; go turn off interrupt + + EOR #TK_CLEAR ; compare with token for CLEAR, A = $00 if = TK_CLEAR + BEQ LAB_INEX ; go clear interrupt flags and return + + JMP LAB_SNER ; do syntax error then warm start + +LAB_IOFF + LDA #$7F ; clear A + AND PLUS_0,X ; AND with interrupt setup flag + BPL LAB_INEX ; go clear interrupt enabled flag and return + +LAB_INON + LDA PLUS_0,X ; get interrupt setup flag + ASL ; Shift bit to enabled flag + ORA PLUS_0,X ; OR with flag byte +LAB_INEX + STA PLUS_0,X ; save interrupt flag byte + JMP LAB_IGBY ; update BASIC execute pointer and return + +; these routines set up the pointers and flags for the interrupt routines +; note that the interrupts are also enabled by these commands + +; perform ON IRQ + +LAB_SIRQ + CLI ; enable interrupts + LDX #IrqBase ; set pointer to IRQ values + .byte $2C ; make next line BIT abs. + +; perform ON NMI + +LAB_SNMI + LDX #NmiBase ; set pointer to NMI values + + STX TempB ; save interrupt pointer + JSR LAB_IGBY ; increment and scan memory (past token) + JSR LAB_GFPN ; get fixed-point number into temp integer + LDA Smeml ; get start of mem low byte + LDX Smemh ; get start of mem high byte + JSR LAB_SHLN ; search Basic for temp integer line number from AX + BCS LAB_LFND ; if carry set go set-up interrupt + + JMP LAB_16F7 ; else go do "Undefined statement" error and warm start + +LAB_LFND + LDX TempB ; get interrupt pointer + LDA Baslnl ; get pointer low byte + SBC #$01 ; -1 (carry already set for subtract) + STA PLUS_1,X ; save as interrupt pointer low byte + LDA Baslnh ; get pointer high byte + SBC #$00 ; subtract carry + STA PLUS_2,X ; save as interrupt pointer high byte + + LDA #$C0 ; set interrupt enabled/setup bits + STA PLUS_0,X ; set interrupt flags +LAB_IRTS + RTS + +; return from IRQ service, restores the enabled flag. + +; perform RETIRQ + +LAB_RETIRQ + BNE LAB_IRTS ; exit if following token (to allow syntax error) + + LDA IrqBase ; get interrupt flags + ASL ; copy setup to enabled (b7) + ORA IrqBase ; OR in setup flag + STA IrqBase ; save enabled flag + JMP LAB_16E8 ; go do rest of RETURN + +; return from NMI service, restores the enabled flag. + +; perform RETNMI + +LAB_RETNMI + BNE LAB_IRTS ; exit if following token (to allow syntax error) + + LDA NmiBase ; get set-up flag + ASL ; copy setup to enabled (b7) + ORA NmiBase ; OR in setup flag + STA NmiBase ; save enabled flag + JMP LAB_16E8 ; go do rest of RETURN + +; MAX() MIN() pre process + +LAB_MMPP + JSR LAB_EVEZ ; process expression + JMP LAB_CTNM ; check if source is numeric, else do type mismatch + +; perform MAX() + +LAB_MAX + JSR LAB_PHFA ; push FAC1, evaluate expression, + ; pull FAC2 and compare with FAC1 + BPL LAB_MAX ; branch if no swap to do + + LDA FAC2_1 ; get FAC2 mantissa1 + ORA #$80 ; set top bit (clear sign from compare) + STA FAC2_1 ; save FAC2 mantissa1 + JSR LAB_279B ; copy FAC2 to FAC1 + BEQ LAB_MAX ; go do next (branch always) + +; perform MIN() + +LAB_MIN + JSR LAB_PHFA ; push FAC1, evaluate expression, + ; pull FAC2 and compare with FAC1 + BMI LAB_MIN ; branch if no swap to do + + BEQ LAB_MIN ; branch if no swap to do + + LDA FAC2_1 ; get FAC2 mantissa1 + ORA #$80 ; set top bit (clear sign from compare) + STA FAC2_1 ; save FAC2 mantissa1 + JSR LAB_279B ; copy FAC2 to FAC1 + BEQ LAB_MIN ; go do next (branch always) + +; exit routine. don't bother returning to the loop code +; check for correct exit, else so syntax error + +LAB_MMEC + CMP #')' ; is it end of function? + BNE LAB_MMSE ; if not do MAX MIN syntax error + + PLA ; dump return address low byte + PLA ; dump return address high byte + JMP LAB_IGBY ; update BASIC execute pointer (to chr past ")") + +LAB_MMSE + JMP LAB_SNER ; do syntax error then warm start + +; check for next, evaluate and return or exit +; this is the routine that does most of the work + +LAB_PHFA + JSR LAB_GBYT ; get next BASIC byte + CMP #',' ; is there more ? + BNE LAB_MMEC ; if not go do end check + + ; push FAC1 + JSR LAB_27BA ; round FAC1 + LDA FAC1_s ; get FAC1 sign + ORA #$7F ; set all non sign bits + AND FAC1_1 ; AND FAC1 mantissa1 (AND in sign bit) + PHA ; push on stack + LDA FAC1_2 ; get FAC1 mantissa2 + PHA ; push on stack + LDA FAC1_3 ; get FAC1 mantissa3 + PHA ; push on stack + LDA FAC1_e ; get FAC1 exponent + PHA ; push on stack + + JSR LAB_IGBY ; scan and get next BASIC byte (after ",") + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch + + ; pop FAC2 (MAX/MIN expression so far) + PLA ; pop exponent + STA FAC2_e ; save FAC2 exponent + PLA ; pop mantissa3 + STA FAC2_3 ; save FAC2 mantissa3 + PLA ; pop mantissa1 + STA FAC2_2 ; save FAC2 mantissa2 + PLA ; pop sign/mantissa1 + STA FAC2_1 ; save FAC2 sign/mantissa1 + STA FAC2_s ; save FAC2 sign + + ; compare FAC1 with (packed) FAC2 + LDA #FAC2_e ; set pointer high byte to FAC2 + JMP LAB_27F8 ; compare FAC1 with FAC2 (AY) and return + ; returns A=$00 if FAC1 = (AY) + ; returns A=$01 if FAC1 > (AY) + ; returns A=$FF if FAC1 < (AY) + +; perform WIDTH + +LAB_WDTH + CMP #',' ; is next byte "," + BEQ LAB_TBSZ ; if so do tab size + + JSR LAB_GTBY ; get byte parameter + TXA ; copy width to A + BEQ LAB_NSTT ; branch if set for infinite line + + CPX #$10 ; else make min width = 16d + BCC TabErr ; if less do function call error and exit + +; this next compare ensures that we can't exit WIDTH via an error leaving the +; tab size greater than the line length. + + CPX TabSiz ; compare with tab size + BCS LAB_NSTT ; branch if >= tab size + + STX TabSiz ; else make tab size = terminal width +LAB_NSTT + STX TWidth ; set the terminal width + JSR LAB_GBYT ; get BASIC byte back + BEQ WExit ; exit if no following + + CMP #',' ; else is it "," + BNE LAB_MMSE ; if not do syntax error + +LAB_TBSZ + JSR LAB_SGBY ; scan and get byte parameter + TXA ; copy TAB size + BMI TabErr ; if >127 do function call error and exit + + CPX #$01 ; compare with min-1 + BCC TabErr ; if <=1 do function call error and exit + + LDA TWidth ; set flags for width + BEQ LAB_SVTB ; skip check if infinite line + + CPX TWidth ; compare TAB with width + BEQ LAB_SVTB ; ok if = + + BCS TabErr ; branch if too big + +LAB_SVTB + STX TabSiz ; save TAB size + +; calculate tab column limit from TAB size. The Iclim is set to the last tab +; position on a line that still has at least one whole tab width between it +; and the end of the line. + +WExit + LDA TWidth ; get width + BEQ LAB_SULP ; branch if infinite line + + CMP TabSiz ; compare with tab size + BCS LAB_WDLP ; branch if >= tab size + + STA TabSiz ; else make tab size = terminal width +LAB_SULP + SEC ; set carry for subtract +LAB_WDLP + SBC TabSiz ; subtract tab size + BCS LAB_WDLP ; loop while no borrow + + ADC TabSiz ; add tab size back + CLC ; clear carry for add + ADC TabSiz ; add tab size back again + STA Iclim ; save for now + LDA TWidth ; get width back + SEC ; set carry for subtract + SBC Iclim ; subtract remainder + STA Iclim ; save tab column limit +LAB_NOSQ + RTS + +TabErr + JMP LAB_FCER ; do function call error then warm start + +; perform SQR() + +LAB_SQR + LDA FAC1_s ; get FAC1 sign + BMI TabErr ; if -ve do function call error + + LDA FAC1_e ; get exponent + BEQ LAB_NOSQ ; if zero just return + + ; else do root + JSR LAB_27AB ; round and copy FAC1 to FAC2 + LDA #$00 ; clear A + + STA FACt_3 ; clear remainder + STA FACt_2 ; .. + STA FACt_1 ; .. + STA TempB ; .. + + STA FAC1_3 ; clear root + STA FAC1_2 ; .. + STA FAC1_1 ; .. + + LDX #$18 ; 24 pairs of bits to do + LDA FAC2_e ; get exponent + LSR ; check odd/even + BCS LAB_SQE2 ; if odd only 1 shift first time + +LAB_SQE1 + ASL FAC2_3 ; shift highest bit of number .. + ROL FAC2_2 ; .. + ROL FAC2_1 ; .. + ROL FACt_3 ; .. into remainder + ROL FACt_2 ; .. + ROL FACt_1 ; .. + ROL TempB ; .. never overflows +LAB_SQE2 + ASL FAC2_3 ; shift highest bit of number .. + ROL FAC2_2 ; .. + ROL FAC2_1 ; .. + ROL FACt_3 ; .. into remainder + ROL FACt_2 ; .. + ROL FACt_1 ; .. + ROL TempB ; .. never overflows + + ASL FAC1_3 ; root = root * 2 + ROL FAC1_2 ; .. + ROL FAC1_1 ; .. never overflows + + LDA FAC1_3 ; get root low byte + ROL ; *2 + STA Temp3 ; save partial low byte + LDA FAC1_2 ; get root low mid byte + ROL ; *2 + STA Temp3+1 ; save partial low mid byte + LDA FAC1_1 ; get root high mid byte + ROL ; *2 + STA Temp3+2 ; save partial high mid byte + LDA #$00 ; get root high byte (always $00) + ROL ; *2 + STA Temp3+3 ; save partial high byte + + ; carry clear for subtract +1 + LDA FACt_3 ; get remainder low byte + SBC Temp3 ; subtract partial low byte + STA Temp3 ; save partial low byte + + LDA FACt_2 ; get remainder low mid byte + SBC Temp3+1 ; subtract partial low mid byte + STA Temp3+1 ; save partial low mid byte + + LDA FACt_1 ; get remainder high mid byte + SBC Temp3+2 ; subtract partial high mid byte + TAY ; copy partial high mid byte + + LDA TempB ; get remainder high byte + SBC Temp3+3 ; subtract partial high byte + BCC LAB_SQNS ; skip sub if remainder smaller + + STA TempB ; save remainder high byte + + STY FACt_1 ; save remainder high mid byte + + LDA Temp3+1 ; get remainder low mid byte + STA FACt_2 ; save remainder low mid byte + + LDA Temp3 ; get partial low byte + STA FACt_3 ; save remainder low byte + + INC FAC1_3 ; increment root low byte (never any rollover) +LAB_SQNS + DEX ; decrement bit pair count + BNE LAB_SQE1 ; loop if not all done + + SEC ; set carry for subtract + LDA FAC2_e ; get exponent + SBC #$80 ; normalise + ROR ; /2 and re-bias to $80 + ADC #$00 ; add bit zero back in (allow for half shift) + STA FAC1_e ; save it + JMP LAB_24D5 ; normalise FAC1 and return + +; perform VARPTR() + +LAB_VARPTR + JSR LAB_IGBY ; increment and scan memory + JSR LAB_GVAR ; get var address + JSR LAB_1BFB ; scan for ")" , else do syntax error then warm start + LDY Cvaral ; get var address low byte + LDA Cvarah ; get var address high byte + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +; perform PI + +LAB_PI + LDA #LAB_2C7C ; set (2*pi) pointer high byte + JSR LAB_UFAC ; unpack memory (AY) into FAC1 + DEC FAC1_e ; make result = PI + RTS + +; perform TWOPI + +LAB_TWOPI + LDA #LAB_2C7C ; set (2*pi) pointer high byte + JMP LAB_UFAC ; unpack memory (AY) into FAC1 and return + +; system dependant i/o vectors +; these are in RAM and are set by the monitor at start-up + +V_INPT + JMP (VEC_IN) ; non halting scan input device +V_OUTP + JMP (VEC_OUT) ; send byte to output device +V_LOAD + JMP (VEC_LD) ; load BASIC program +V_SAVE + JMP (VEC_SV) ; save BASIC program + +; The rest are tables messages and code for RAM + +; the rest of the code is tables and BASIC start-up code + +PG2_TABS + .byte $FF ; ctrl-c flag - $00 = enabled + .byte $00 ; ctrl-c byte - GET needs this + .byte $00 ; ctrl-c byte timeout - GET needs this + .word CTRLC ; ctrl c check vector + .word CHRIN ; non halting key input - monitor to set this + .word CHROUT ; output vector - monitor to set this +; .word xxxx ; load vector - monitor to set this +; .word xxxx ; save vector - monitor to set this +PG2_TABE + +; character get subroutine for zero page + +; For a 1.8432MHz 6502 including the JSR and RTS +; fastest (>=":") = 29 cycles = 15.7uS +; slowest (<":") = 40 cycles = 21.7uS +; space skip = +21 cycles = +11.4uS +; inc across page = +4 cycles = +2.2uS + +; the target address for the LDA at LAB_2CF4 becomes the BASIC execute pointer once the +; block is copied to it's destination, any non zero page address will do at assembly +; time, to assemble a three byte instruction. + +; page 0 initialisation table from $BC +; increment and scan memory + +LAB_2CEE + INC Bpntrl ; increment BASIC execute pointer low byte + BNE LAB_2CF4 ; branch if no carry + ; else + INC Bpntrh ; increment BASIC execute pointer high byte + +; page 0 initialisation table from $C2 +; scan memory + +LAB_2CF4 + LDA $FFFF ; get byte to scan (addr set by call routine) + CMP #TK_ELSE ; compare with the token for ELSE + BEQ LAB_2D05 ; exit if ELSE, not numeric, carry set + + CMP #':' ; compare with ":" + BCS LAB_2D05 ; exit if >= ":", not numeric, carry set + + CMP #' ' ; compare with " " + BEQ LAB_2CEE ; if " " go do next + + SEC ; set carry for SBC + SBC #'0' ; subtract "0" + SEC ; set carry for SBC + SBC #$D0 ; subtract -"0" + ; clear carry if byte = "0"-"9" +LAB_2D05 + RTS + +; page zero initialisation table $00-$12 inclusive + +StrTab + .byte $4C ; JMP opcode + .word LAB_COLD ; initial warm start vector (cold start) + + .byte $00 ; these bytes are not used by BASIC + .word $0000 ; + .word $0000 ; + .word $0000 ; + + .byte $4C ; JMP opcode + .word LAB_FCER ; initial user function vector ("Function call" error) + .byte $00 ; default NULL count + .byte $00 ; clear terminal position + .byte $00 ; default terminal width byte + .byte $F2 ; default limit for TAB = 14 + .word Ram_base ; start of user RAM +EndTab + +LAB_MSZM + .byte $0D,$0A,"Memory size ",$00 + +LAB_SMSG + .byte " Bytes free",$0D,$0A,$0A + .byte "Enhanced BASIC 2.22",$0A,$00 + +; numeric constants and series + + ; constants and series for LOG(n) +LAB_25A0 + .byte $02 ; counter + .byte $80,$19,$56,$62 ; 0.59898 + .byte $80,$76,$22,$F3 ; 0.96147 +;## .byte $80,$76,$22,$F1 ; 0.96147 + .byte $82,$38,$AA,$40 ; 2.88539 +;## .byte $82,$38,$AA,$45 ; 2.88539 + +LAB_25AD + .byte $80,$35,$04,$F3 ; 0.70711 1/root 2 +LAB_25B1 + .byte $81,$35,$04,$F3 ; 1.41421 root 2 +LAB_25B5 + .byte $80,$80,$00,$00 ; -0.5 +LAB_25B9 + .byte $80,$31,$72,$18 ; 0.69315 LOG(2) + + ; numeric PRINT constants +LAB_2947 + .byte $91,$43,$4F,$F8 ; 99999.9375 (max value with at least one decimal) +LAB_294B + .byte $94,$74,$23,$F7 ; 999999.4375 (max value before scientific notation) +LAB_294F + .byte $94,$74,$24,$00 ; 1000000 + + ; EXP(n) constants and series +LAB_2AFA + .byte $81,$38,$AA,$3B ; 1.4427 (1/LOG base 2 e) +LAB_2AFE + .byte $06 ; counter + .byte $74,$63,$90,$8C ; 2.17023e-4 + .byte $77,$23,$0C,$AB ; 0.00124 + .byte $7A,$1E,$94,$00 ; 0.00968 + .byte $7C,$63,$42,$80 ; 0.05548 + .byte $7E,$75,$FE,$D0 ; 0.24023 + .byte $80,$31,$72,$15 ; 0.69315 + .byte $81,$00,$00,$00 ; 1.00000 + +;## .byte $07 ; counter +;## .byte $74,$94,$2E,$40 ; -1/7! (-1/5040) +;## .byte $77,$2E,$4F,$70 ; 1/6! ( 1/720) +;## .byte $7A,$88,$02,$6E ; -1/5! (-1/120) +;## .byte $7C,$2A,$A0,$E6 ; 1/4! ( 1/24) +;## .byte $7E,$AA,$AA,$50 ; -1/3! (-1/6) +;## .byte $7F,$7F,$FF,$FF ; 1/2! ( 1/2) +;## .byte $81,$80,$00,$00 ; -1/1! (-1/1) +;## .byte $81,$00,$00,$00 ; 1/0! ( 1/1) + + ; trigonometric constants and series +LAB_2C78 + .byte $81,$49,$0F,$DB ; 1.570796371 (pi/2) as floating # +LAB_2C84 + .byte $04 ; counter + .byte $86,$1E,$D7,$FB ; 39.7109 +;## .byte $86,$1E,$D7,$BA ; 39.7109 + .byte $87,$99,$26,$65 ;-76.575 +;## .byte $87,$99,$26,$64 ;-76.575 + .byte $87,$23,$34,$58 ; 81.6022 + .byte $86,$A5,$5D,$E1 ;-41.3417 +;## .byte $86,$A5,$5D,$E0 ;-41.3417 +LAB_2C7C + .byte $83,$49,$0F,$DB ; 6.28319 (2*pi) as floating # +;## .byte $83,$49,$0F,$DA ; 6.28319 (2*pi) as floating # + +LAB_2CC9 + .byte $08 ; counter + .byte $78,$3A,$C5,$37 ; 0.00285 + .byte $7B,$83,$A2,$5C ;-0.0160686 + .byte $7C,$2E,$DD,$4D ; 0.0426915 + .byte $7D,$99,$B0,$1E ;-0.0750429 + .byte $7D,$59,$ED,$24 ; 0.106409 + .byte $7E,$91,$72,$00 ;-0.142036 + .byte $7E,$4C,$B9,$73 ; 0.199926 + .byte $7F,$AA,$AA,$53 ;-0.333331 + +;## .byte $08 ; counter +;## .byte $78,$3B,$D7,$4A ; 1/17 +;## .byte $7B,$84,$6E,$02 ;-1/15 +;## .byte $7C,$2F,$C1,$FE ; 1/13 +;## .byte $7D,$9A,$31,$74 ;-1/11 +;## .byte $7D,$5A,$3D,$84 ; 1/9 +;## .byte $7E,$91,$7F,$C8 ;-1/7 +;## .byte $7E,$4C,$BB,$E4 ; 1/5 +;## .byte $7F,$AA,$AA,$6C ;-1/3 + +LAB_1D96 = *+1 ; $00,$00 used for undefined variables +LAB_259C + .byte $81,$00,$00,$00 ; 1.000000, used for INC +LAB_2AFD + .byte $81,$80,$00,$00 ; -1.00000, used for DEC. must be on the same page as +1.00 + + ; misc constants +LAB_1DF7 + .byte $90 ;-32768 (uses first three bytes from 0.5) +LAB_2A96 + .byte $80,$00,$00,$00 ; 0.5 +LAB_2C80 + .byte $7F,$00,$00,$00 ; 0.25 +LAB_26B5 + .byte $84,$20,$00,$00 ; 10.0000 divide by 10 constant + +; This table is used in converting numbers to ASCII. + +LAB_2A9A +LAB_2A9B = LAB_2A9A+1 +LAB_2A9C = LAB_2A9B+1 + .byte $FE,$79,$60 ; -100000 + .byte $00,$27,$10 ; 10000 + .byte $FF,$FC,$18 ; -1000 + .byte $00,$00,$64 ; 100 + .byte $FF,$FF,$F6 ; -10 + .byte $00,$00,$01 ; 1 + +LAB_CTBL + .word LAB_END-1 ; END + .word LAB_FOR-1 ; FOR + .word LAB_NEXT-1 ; NEXT + .word LAB_DATA-1 ; DATA + .word LAB_INPUT-1 ; INPUT + .word LAB_DIM-1 ; DIM + .word LAB_READ-1 ; READ + .word LAB_LET-1 ; LET + .word LAB_DEC-1 ; DEC new command + .word LAB_GOTO-1 ; GOTO + .word LAB_RUN-1 ; RUN + .word LAB_IF-1 ; IF + .word LAB_RESTORE-1 ; RESTORE modified command + .word LAB_GOSUB-1 ; GOSUB + .word LAB_RETIRQ-1 ; RETIRQ new command + .word LAB_RETNMI-1 ; RETNMI new command + .word LAB_RETURN-1 ; RETURN + .word LAB_REM-1 ; REM + .word LAB_STOP-1 ; STOP + .word LAB_ON-1 ; ON modified command + .word LAB_NULL-1 ; NULL modified command + .word LAB_INC-1 ; INC new command + .word LAB_WAIT-1 ; WAIT + .word V_LOAD-1 ; LOAD + .word V_SAVE-1 ; SAVE + .word LAB_DEF-1 ; DEF + .word LAB_POKE-1 ; POKE + .word LAB_DOKE-1 ; DOKE new command + .word LAB_CALL-1 ; CALL new command + .word LAB_DO-1 ; DO new command + .word LAB_LOOP-1 ; LOOP new command + .word LAB_PRINT-1 ; PRINT + .word LAB_CONT-1 ; CONT + .word LAB_LIST-1 ; LIST + .word LAB_CLEAR-1 ; CLEAR + .word LAB_NEW-1 ; NEW + .word LAB_WDTH-1 ; WIDTH new command + .word LAB_GET-1 ; GET new command + .word LAB_SWAP-1 ; SWAP new command + .word LAB_BITSET-1 ; BITSET new command + .word LAB_BITCLR-1 ; BITCLR new command + .word LAB_IRQ-1 ; IRQ new command + .word LAB_NMI-1 ; NMI new command + +; function pre process routine table + +LAB_FTPL +LAB_FTPM = LAB_FTPL+$01 + .word LAB_PPFN-1 ; SGN(n) process numeric expression in () + .word LAB_PPFN-1 ; INT(n) " + .word LAB_PPFN-1 ; ABS(n) " + .word LAB_EVEZ-1 ; USR(x) process any expression + .word LAB_1BF7-1 ; FRE(x) " + .word LAB_1BF7-1 ; POS(x) " + .word LAB_PPFN-1 ; SQR(n) process numeric expression in () + .word LAB_PPFN-1 ; RND(n) " + .word LAB_PPFN-1 ; LOG(n) " + .word LAB_PPFN-1 ; EXP(n) " + .word LAB_PPFN-1 ; COS(n) " + .word LAB_PPFN-1 ; SIN(n) " + .word LAB_PPFN-1 ; TAN(n) " + .word LAB_PPFN-1 ; ATN(n) " + .word LAB_PPFN-1 ; PEEK(n) " + .word LAB_PPFN-1 ; DEEK(n) " + .word $0000 ; SADD() none + .word LAB_PPFS-1 ; LEN($) process string expression in () + .word LAB_PPFN-1 ; STR$(n) process numeric expression in () + .word LAB_PPFS-1 ; VAL($) process string expression in () + .word LAB_PPFS-1 ; ASC($) " + .word LAB_PPFS-1 ; UCASE$($) " + .word LAB_PPFS-1 ; LCASE$($) " + .word LAB_PPFN-1 ; CHR$(n) process numeric expression in () + .word LAB_BHSS-1 ; HEX$(n) " + .word LAB_BHSS-1 ; BIN$(n) " + .word $0000 ; BITTST() none + .word LAB_MMPP-1 ; MAX() process numeric expression + .word LAB_MMPP-1 ; MIN() " + .word LAB_PPBI-1 ; PI advance pointer + .word LAB_PPBI-1 ; TWOPI " + .word $0000 ; VARPTR() none + .word LAB_LRMS-1 ; LEFT$() process string expression + .word LAB_LRMS-1 ; RIGHT$() " + .word LAB_LRMS-1 ; MID$() " + +; action addresses for functions + +LAB_FTBL +LAB_FTBM = LAB_FTBL+$01 + .word LAB_SGN-1 ; SGN() + .word LAB_INT-1 ; INT() + .word LAB_ABS-1 ; ABS() + .word LAB_USR-1 ; USR() + .word LAB_FRE-1 ; FRE() + .word LAB_POS-1 ; POS() + .word LAB_SQR-1 ; SQR() + .word LAB_RND-1 ; RND() modified function + .word LAB_LOG-1 ; LOG() + .word LAB_EXP-1 ; EXP() + .word LAB_COS-1 ; COS() + .word LAB_SIN-1 ; SIN() + .word LAB_TAN-1 ; TAN() + .word LAB_ATN-1 ; ATN() + .word LAB_PEEK-1 ; PEEK() + .word LAB_DEEK-1 ; DEEK() new function + .word LAB_SADD-1 ; SADD() new function + .word LAB_LENS-1 ; LEN() + .word LAB_STRS-1 ; STR$() + .word LAB_VAL-1 ; VAL() + .word LAB_ASC-1 ; ASC() + .word LAB_UCASE-1 ; UCASE$() new function + .word LAB_LCASE-1 ; LCASE$() new function + .word LAB_CHRS-1 ; CHR$() + .word LAB_HEXS-1 ; HEX$() new function + .word LAB_BINS-1 ; BIN$() new function + .word LAB_BTST-1 ; BITTST() new function + .word LAB_MAX-1 ; MAX() new function + .word LAB_MIN-1 ; MIN() new function + .word LAB_PI-1 ; PI new function + .word LAB_TWOPI-1 ; TWOPI new function + .word LAB_VARPTR-1 ; VARPTR() new function + .word LAB_LEFT-1 ; LEFT$() + .word LAB_RIGHT-1 ; RIGHT$() + .word LAB_MIDS-1 ; MID$() + +; hierarchy and action addresses for operator + +LAB_OPPT + .byte $79 ; + + .word LAB_ADD-1 + .byte $79 ; - + .word LAB_SUBTRACT-1 + .byte $7B ; * + .word LAB_MULTIPLY-1 + .byte $7B ; / + .word LAB_DIVIDE-1 + .byte $7F ; ^ + .word LAB_POWER-1 + .byte $50 ; AND + .word LAB_AND-1 + .byte $46 ; EOR new operator + .word LAB_EOR-1 + .byte $46 ; OR + .word LAB_OR-1 + .byte $56 ; >> new operator + .word LAB_RSHIFT-1 + .byte $56 ; << new operator + .word LAB_LSHIFT-1 + .byte $7D ; > + .word LAB_GTHAN-1 + .byte $5A ; = + .word LAB_EQUAL-1 + .byte $64 ; < + .word LAB_LTHAN-1 + +; keywords start with .. +; this is the first character table and must be in alphabetic order + +TAB_1STC + .byte "*" + .byte "+" + .byte "-" + .byte "/" + .byte "<" + .byte "=" + .byte ">" + .byte "?" + .byte "A" + .byte "B" + .byte "C" + .byte "D" + .byte "E" + .byte "F" + .byte "G" + .byte "H" + .byte "I" + .byte "L" + .byte "M" + .byte "N" + .byte "O" + .byte "P" + .byte "R" + .byte "S" + .byte "T" + .byte "U" + .byte "V" + .byte "W" + .byte "^" + .byte $00 ; table terminator + +; pointers to keyword tables + +TAB_CHRT + .word TAB_STAR ; table for "*" + .word TAB_PLUS ; table for "+" + .word TAB_MNUS ; table for "-" + .word TAB_SLAS ; table for "/" + .word TAB_LESS ; table for "<" + .word TAB_EQUL ; table for "=" + .word TAB_MORE ; table for ">" + .word TAB_QEST ; table for "?" + .word TAB_ASCA ; table for "A" + .word TAB_ASCB ; table for "B" + .word TAB_ASCC ; table for "C" + .word TAB_ASCD ; table for "D" + .word TAB_ASCE ; table for "E" + .word TAB_ASCF ; table for "F" + .word TAB_ASCG ; table for "G" + .word TAB_ASCH ; table for "H" + .word TAB_ASCI ; table for "I" + .word TAB_ASCL ; table for "L" + .word TAB_ASCM ; table for "M" + .word TAB_ASCN ; table for "N" + .word TAB_ASCO ; table for "O" + .word TAB_ASCP ; table for "P" + .word TAB_ASCR ; table for "R" + .word TAB_ASCS ; table for "S" + .word TAB_ASCT ; table for "T" + .word TAB_ASCU ; table for "U" + .word TAB_ASCV ; table for "V" + .word TAB_ASCW ; table for "W" + .word TAB_POWR ; table for "^" + +; tables for each start character, note if a longer keyword with the same start +; letters as a shorter one exists then it must come first, else the list is in +; alphabetical order as follows .. + +; [keyword,token +; [keyword,token]] +; end marker (#$00) + +TAB_STAR + .byte TK_MUL,$00 ; * +TAB_PLUS + .byte TK_PLUS,$00 ; + +TAB_MNUS + .byte TK_MINUS,$00 ; - +TAB_SLAS + .byte TK_DIV,$00 ; / +TAB_LESS +LBB_LSHIFT + .byte "<",TK_LSHIFT ; << note - "<<" must come before "<" + .byte TK_LT ; < + .byte $00 +TAB_EQUL + .byte TK_EQUAL,$00 ; = +TAB_MORE +LBB_RSHIFT + .byte ">",TK_RSHIFT ; >> note - ">>" must come before ">" + .byte TK_GT ; > + .byte $00 +TAB_QEST + .byte TK_PRINT,$00 ; ? +TAB_ASCA +LBB_ABS + .byte "BS(",TK_ABS ; ABS( +LBB_AND + .byte "ND",TK_AND ; AND +LBB_ASC + .byte "SC(",TK_ASC ; ASC( +LBB_ATN + .byte "TN(",TK_ATN ; ATN( + .byte $00 +TAB_ASCB +LBB_BINS + .byte "IN$(",TK_BINS ; BIN$( +LBB_BITCLR + .byte "ITCLR",TK_BITCLR ; BITCLR +LBB_BITSET + .byte "ITSET",TK_BITSET ; BITSET +LBB_BITTST + .byte "ITTST(",TK_BITTST + ; BITTST( + .byte $00 +TAB_ASCC +LBB_CALL + .byte "ALL",TK_CALL ; CALL +LBB_CHRS + .byte "HR$(",TK_CHRS ; CHR$( +LBB_CLEAR + .byte "LEAR",TK_CLEAR ; CLEAR +LBB_CONT + .byte "ONT",TK_CONT ; CONT +LBB_COS + .byte "OS(",TK_COS ; COS( + .byte $00 +TAB_ASCD +LBB_DATA + .byte "ATA",TK_DATA ; DATA +LBB_DEC + .byte "EC",TK_DEC ; DEC +LBB_DEEK + .byte "EEK(",TK_DEEK ; DEEK( +LBB_DEF + .byte "EF",TK_DEF ; DEF +LBB_DIM + .byte "IM",TK_DIM ; DIM +LBB_DOKE + .byte "OKE",TK_DOKE ; DOKE note - "DOKE" must come before "DO" +LBB_DO + .byte "O",TK_DO ; DO + .byte $00 +TAB_ASCE +LBB_ELSE + .byte "LSE",TK_ELSE ; ELSE +LBB_END + .byte "ND",TK_END ; END +LBB_EOR + .byte "OR",TK_EOR ; EOR +LBB_EXP + .byte "XP(",TK_EXP ; EXP( + .byte $00 +TAB_ASCF +LBB_FN + .byte "N",TK_FN ; FN +LBB_FOR + .byte "OR",TK_FOR ; FOR +LBB_FRE + .byte "RE(",TK_FRE ; FRE( + .byte $00 +TAB_ASCG +LBB_GET + .byte "ET",TK_GET ; GET +LBB_GOSUB + .byte "OSUB",TK_GOSUB ; GOSUB +LBB_GOTO + .byte "OTO",TK_GOTO ; GOTO + .byte $00 +TAB_ASCH +LBB_HEXS + .byte "EX$(",TK_HEXS ; HEX$( + .byte $00 +TAB_ASCI +LBB_IF + .byte "F",TK_IF ; IF +LBB_INC + .byte "NC",TK_INC ; INC +LBB_INPUT + .byte "NPUT",TK_INPUT ; INPUT +LBB_INT + .byte "NT(",TK_INT ; INT( +LBB_IRQ + .byte "RQ",TK_IRQ ; IRQ + .byte $00 +TAB_ASCL +LBB_LCASES + .byte "CASE$(",TK_LCASES + ; LCASE$( +LBB_LEFTS + .byte "EFT$(",TK_LEFTS ; LEFT$( +LBB_LEN + .byte "EN(",TK_LEN ; LEN( +LBB_LET + .byte "ET",TK_LET ; LET +LBB_LIST + .byte "IST",TK_LIST ; LIST +LBB_LOAD + .byte "OAD",TK_LOAD ; LOAD +LBB_LOG + .byte "OG(",TK_LOG ; LOG( +LBB_LOOP + .byte "OOP",TK_LOOP ; LOOP + .byte $00 +TAB_ASCM +LBB_MAX + .byte "AX(",TK_MAX ; MAX( +LBB_MIDS + .byte "ID$(",TK_MIDS ; MID$( +LBB_MIN + .byte "IN(",TK_MIN ; MIN( + .byte $00 +TAB_ASCN +LBB_NEW + .byte "EW",TK_NEW ; NEW +LBB_NEXT + .byte "EXT",TK_NEXT ; NEXT +LBB_NMI + .byte "MI",TK_NMI ; NMI +LBB_NOT + .byte "OT",TK_NOT ; NOT +LBB_NULL + .byte "ULL",TK_NULL ; NULL + .byte $00 +TAB_ASCO +LBB_OFF + .byte "FF",TK_OFF ; OFF +LBB_ON + .byte "N",TK_ON ; ON +LBB_OR + .byte "R",TK_OR ; OR + .byte $00 +TAB_ASCP +LBB_PEEK + .byte "EEK(",TK_PEEK ; PEEK( +LBB_PI + .byte "I",TK_PI ; PI +LBB_POKE + .byte "OKE",TK_POKE ; POKE +LBB_POS + .byte "OS(",TK_POS ; POS( +LBB_PRINT + .byte "RINT",TK_PRINT ; PRINT + .byte $00 +TAB_ASCR +LBB_READ + .byte "EAD",TK_READ ; READ +LBB_REM + .byte "EM",TK_REM ; REM +LBB_RESTORE + .byte "ESTORE",TK_RESTORE + ; RESTORE +LBB_RETIRQ + .byte "ETIRQ",TK_RETIRQ ; RETIRQ +LBB_RETNMI + .byte "ETNMI",TK_RETNMI ; RETNMI +LBB_RETURN + .byte "ETURN",TK_RETURN ; RETURN +LBB_RIGHTS + .byte "IGHT$(",TK_RIGHTS + ; RIGHT$( +LBB_RND + .byte "ND(",TK_RND ; RND( +LBB_RUN + .byte "UN",TK_RUN ; RUN + .byte $00 +TAB_ASCS +LBB_SADD + .byte "ADD(",TK_SADD ; SADD( +LBB_SAVE + .byte "AVE",TK_SAVE ; SAVE +LBB_SGN + .byte "GN(",TK_SGN ; SGN( +LBB_SIN + .byte "IN(",TK_SIN ; SIN( +LBB_SPC + .byte "PC(",TK_SPC ; SPC( +LBB_SQR + .byte "QR(",TK_SQR ; SQR( +LBB_STEP + .byte "TEP",TK_STEP ; STEP +LBB_STOP + .byte "TOP",TK_STOP ; STOP +LBB_STRS + .byte "TR$(",TK_STRS ; STR$( +LBB_SWAP + .byte "WAP",TK_SWAP ; SWAP + .byte $00 +TAB_ASCT +LBB_TAB + .byte "AB(",TK_TAB ; TAB( +LBB_TAN + .byte "AN(",TK_TAN ; TAN( +LBB_THEN + .byte "HEN",TK_THEN ; THEN +LBB_TO + .byte "O",TK_TO ; TO +LBB_TWOPI + .byte "WOPI",TK_TWOPI ; TWOPI + .byte $00 +TAB_ASCU +LBB_UCASES + .byte "CASE$(",TK_UCASES + ; UCASE$( +LBB_UNTIL + .byte "NTIL",TK_UNTIL ; UNTIL +LBB_USR + .byte "SR(",TK_USR ; USR( + .byte $00 +TAB_ASCV +LBB_VAL + .byte "AL(",TK_VAL ; VAL( +LBB_VPTR + .byte "ARPTR(",TK_VPTR ; VARPTR( + .byte $00 +TAB_ASCW +LBB_WAIT + .byte "AIT",TK_WAIT ; WAIT +LBB_WHILE + .byte "HILE",TK_WHILE ; WHILE +LBB_WIDTH + .byte "IDTH",TK_WIDTH ; WIDTH + .byte $00 +TAB_POWR + .byte TK_POWER,$00 ; ^ + +; new decode table for LIST +; Table is .. +; byte - keyword length, keyword first character +; word - pointer to rest of keyword from dictionary + +; note if length is 1 then the pointer is ignored + +LAB_KEYT + .byte 3,'E' + .word LBB_END ; END + .byte 3,'F' + .word LBB_FOR ; FOR + .byte 4,'N' + .word LBB_NEXT ; NEXT + .byte 4,'D' + .word LBB_DATA ; DATA + .byte 5,'I' + .word LBB_INPUT ; INPUT + .byte 3,'D' + .word LBB_DIM ; DIM + .byte 4,'R' + .word LBB_READ ; READ + .byte 3,'L' + .word LBB_LET ; LET + .byte 3,'D' + .word LBB_DEC ; DEC + .byte 4,'G' + .word LBB_GOTO ; GOTO + .byte 3,'R' + .word LBB_RUN ; RUN + .byte 2,'I' + .word LBB_IF ; IF + .byte 7,'R' + .word LBB_RESTORE ; RESTORE + .byte 5,'G' + .word LBB_GOSUB ; GOSUB + .byte 6,'R' + .word LBB_RETIRQ ; RETIRQ + .byte 6,'R' + .word LBB_RETNMI ; RETNMI + .byte 6,'R' + .word LBB_RETURN ; RETURN + .byte 3,'R' + .word LBB_REM ; REM + .byte 4,'S' + .word LBB_STOP ; STOP + .byte 2,'O' + .word LBB_ON ; ON + .byte 4,'N' + .word LBB_NULL ; NULL + .byte 3,'I' + .word LBB_INC ; INC + .byte 4,'W' + .word LBB_WAIT ; WAIT + .byte 4,'L' + .word LBB_LOAD ; LOAD + .byte 4,'S' + .word LBB_SAVE ; SAVE + .byte 3,'D' + .word LBB_DEF ; DEF + .byte 4,'P' + .word LBB_POKE ; POKE + .byte 4,'D' + .word LBB_DOKE ; DOKE + .byte 4,'C' + .word LBB_CALL ; CALL + .byte 2,'D' + .word LBB_DO ; DO + .byte 4,'L' + .word LBB_LOOP ; LOOP + .byte 5,'P' + .word LBB_PRINT ; PRINT + .byte 4,'C' + .word LBB_CONT ; CONT + .byte 4,'L' + .word LBB_LIST ; LIST + .byte 5,'C' + .word LBB_CLEAR ; CLEAR + .byte 3,'N' + .word LBB_NEW ; NEW + .byte 5,'W' + .word LBB_WIDTH ; WIDTH + .byte 3,'G' + .word LBB_GET ; GET + .byte 4,'S' + .word LBB_SWAP ; SWAP + .byte 6,'B' + .word LBB_BITSET ; BITSET + .byte 6,'B' + .word LBB_BITCLR ; BITCLR + .byte 3,'I' + .word LBB_IRQ ; IRQ + .byte 3,'N' + .word LBB_NMI ; NMI + +; secondary commands (can't start a statement) + + .byte 4,'T' + .word LBB_TAB ; TAB + .byte 4,'E' + .word LBB_ELSE ; ELSE + .byte 2,'T' + .word LBB_TO ; TO + .byte 2,'F' + .word LBB_FN ; FN + .byte 4,'S' + .word LBB_SPC ; SPC + .byte 4,'T' + .word LBB_THEN ; THEN + .byte 3,'N' + .word LBB_NOT ; NOT + .byte 4,'S' + .word LBB_STEP ; STEP + .byte 5,'U' + .word LBB_UNTIL ; UNTIL + .byte 5,'W' + .word LBB_WHILE ; WHILE + .byte 3,'O' + .word LBB_OFF ; OFF + +; opperators + + .byte 1,'+' + .word $0000 ; + + .byte 1,'-' + .word $0000 ; - + .byte 1,'*' + .word $0000 ; * + .byte 1,'/' + .word $0000 ; / + .byte 1,'^' + .word $0000 ; ^ + .byte 3,'A' + .word LBB_AND ; AND + .byte 3,'E' + .word LBB_EOR ; EOR + .byte 2,'O' + .word LBB_OR ; OR + .byte 2,'>' + .word LBB_RSHIFT ; >> + .byte 2,'<' + .word LBB_LSHIFT ; << + .byte 1,'>' + .word $0000 ; > + .byte 1,'=' + .word $0000 ; = + .byte 1,'<' + .word $0000 ; < + +; functions + + .byte 4,'S' ; + .word LBB_SGN ; SGN + .byte 4,'I' ; + .word LBB_INT ; INT + .byte 4,'A' ; + .word LBB_ABS ; ABS + .byte 4,'U' ; + .word LBB_USR ; USR + .byte 4,'F' ; + .word LBB_FRE ; FRE + .byte 4,'P' ; + .word LBB_POS ; POS + .byte 4,'S' ; + .word LBB_SQR ; SQR + .byte 4,'R' ; + .word LBB_RND ; RND + .byte 4,'L' ; + .word LBB_LOG ; LOG + .byte 4,'E' ; + .word LBB_EXP ; EXP + .byte 4,'C' ; + .word LBB_COS ; COS + .byte 4,'S' ; + .word LBB_SIN ; SIN + .byte 4,'T' ; + .word LBB_TAN ; TAN + .byte 4,'A' ; + .word LBB_ATN ; ATN + .byte 5,'P' ; + .word LBB_PEEK ; PEEK + .byte 5,'D' ; + .word LBB_DEEK ; DEEK + .byte 5,'S' ; + .word LBB_SADD ; SADD + .byte 4,'L' ; + .word LBB_LEN ; LEN + .byte 5,'S' ; + .word LBB_STRS ; STR$ + .byte 4,'V' ; + .word LBB_VAL ; VAL + .byte 4,'A' ; + .word LBB_ASC ; ASC + .byte 7,'U' ; + .word LBB_UCASES ; UCASE$ + .byte 7,'L' ; + .word LBB_LCASES ; LCASE$ + .byte 5,'C' ; + .word LBB_CHRS ; CHR$ + .byte 5,'H' ; + .word LBB_HEXS ; HEX$ + .byte 5,'B' ; + .word LBB_BINS ; BIN$ + .byte 7,'B' ; + .word LBB_BITTST ; BITTST + .byte 4,'M' ; + .word LBB_MAX ; MAX + .byte 4,'M' ; + .word LBB_MIN ; MIN + .byte 2,'P' ; + .word LBB_PI ; PI + .byte 5,'T' ; + .word LBB_TWOPI ; TWOPI + .byte 7,'V' ; + .word LBB_VPTR ; VARPTR + .byte 6,'L' ; + .word LBB_LEFTS ; LEFT$ + .byte 7,'R' ; + .word LBB_RIGHTS ; RIGHT$ + .byte 5,'M' ; + .word LBB_MIDS ; MID$ + +; BASIC messages, mostly error messages + +LAB_BAER + .word ERR_NF ;$00 NEXT without FOR + .word ERR_SN ;$02 syntax + .word ERR_RG ;$04 RETURN without GOSUB + .word ERR_OD ;$06 out of data + .word ERR_FC ;$08 function call + .word ERR_OV ;$0A overflow + .word ERR_OM ;$0C out of memory + .word ERR_US ;$0E undefined statement + .word ERR_BS ;$10 array bounds + .word ERR_DD ;$12 double dimension array + .word ERR_D0 ;$14 divide by 0 + .word ERR_ID ;$16 illegal direct + .word ERR_TM ;$18 type mismatch + .word ERR_LS ;$1A long string + .word ERR_ST ;$1C string too complex + .word ERR_CN ;$1E continue error + .word ERR_UF ;$20 undefined function + .word ERR_LD ;$22 LOOP without DO + +; I may implement these two errors to force definition of variables and +; dimensioning of arrays before use. + +; .word ERR_UV ;$24 undefined variable + +; the above error has been tested and works (see code and comments below LAB_1D8B) + +; .word ERR_UA ;$26 undimensioned array + +ERR_NF .byte "NEXT without FOR",$00 +ERR_SN .byte "Syntax",$00 +ERR_RG .byte "RETURN without GOSUB",$00 +ERR_OD .byte "Out of DATA",$00 +ERR_FC .byte "Function call",$00 +ERR_OV .byte "Overflow",$00 +ERR_OM .byte "Out of memory",$00 +ERR_US .byte "Undefined statement",$00 +ERR_BS .byte "Array bounds",$00 +ERR_DD .byte "Double dimension",$00 +ERR_D0 .byte "Divide by zero",$00 +ERR_ID .byte "Illegal direct",$00 +ERR_TM .byte "Type mismatch",$00 +ERR_LS .byte "String too long",$00 +ERR_ST .byte "String too complex",$00 +ERR_CN .byte "Can't continue",$00 +ERR_UF .byte "Undefined function",$00 +ERR_LD .byte "LOOP without DO",$00 + +;ERR_UV .byte "Undefined variable",$00 + +; the above error has been tested and works (see code and comments below LAB_1D8B) + +;ERR_UA .byte "Undimensioned array",$00 + +LAB_BMSG .byte $0D,$0A,"Break",$00 +LAB_EMSG .byte " Error",$00 +LAB_LMSG .byte " in line ",$00 +LAB_RMSG .byte $0D,$0A,"Ready",$0D,$0A,$00 + +LAB_IMSG .byte " Extra ignored",$0D,$0A,$00 +LAB_REDO .byte " Redo from start",$0D,$0A,$00 + +AA_end_basic diff --git a/ehbas_xx.dat b/ehbas_xx.dat new file mode 100644 index 0000000..08fa7d4 --- /dev/null +++ b/ehbas_xx.dat @@ -0,0 +1,1049 @@ +; Created with BIN2HEX (C) Marek Karcz 2016. All rights reserved. +; 09/11/16 18:02:19 +ADDR +$c000 +ORG +$c000 +; Char IO +IOADDR +$FFE0 +; ROM +ROMBEGIN +$FFC0 +ROMEND +$FFFF +;$FFDF +; Enable char IO and ROM +ENIO +ENROM +; Enable generic graphics display +; and set its base address. +ENGRAPH +GRAPHADDR +$FFE2 +$d8 $a0 $08 $b9 $fb $e0 $99 $00 $02 $88 $10 $f7 $a2 $ff $8e $21 +$02 $86 $88 $9a $a9 $4c $85 $a1 $a2 $1c $bd $03 $e1 $95 $bb $ca +$d0 $f8 $a2 $12 $bd $20 $e1 $95 $00 $ca $10 $f8 $a9 $00 $85 $dc +$85 $df $85 $b2 $85 $67 $a9 $0e $85 $64 $a9 $03 $85 $a0 $a2 $68 +$86 $65 $20 $97 $c8 $a9 $33 $a0 $e1 $20 $d8 $c8 $20 $45 $c2 $86 +$c3 $84 $c4 $20 $c2 $00 $d0 $1f $a0 $00 $e6 $11 $d0 $08 $e6 $12 +$a5 $12 $c9 $b0 $f0 $1d $a9 $55 $91 $11 $d1 $11 $d0 $15 $0a $91 +$11 $d1 $11 $f0 $e5 $d0 $0c $20 $ab $d9 $a5 $ac $c9 $98 $b0 $a2 +$20 $fc $d4 $a5 $11 $a4 $12 $c0 $01 $90 $97 $85 $85 $84 $86 $85 +$81 $84 $82 $a0 $00 $a2 $03 $84 $79 $86 $7a $98 $91 $79 $e6 $79 +$20 $97 $c8 $20 $55 $c3 $a5 $85 $38 $e5 $79 $aa $a5 $86 $e5 $7a +$20 $87 $da $a9 $42 $a0 $e1 $20 $d8 $c8 $a9 $5e $a0 $c1 $85 $01 +$84 $02 $6c $01 $00 $20 $0f $c1 $85 $7f $84 $80 $38 $a5 $a6 $e5 +$aa $a8 $a5 $a7 $e5 $ab $aa $e8 $98 $f0 $24 $38 $49 $ff $65 $a6 +$85 $a6 $b0 $03 $c6 $a7 $38 $98 $49 $ff $65 $a4 $85 $a4 $b0 $08 +$c6 $a5 $90 $04 $b1 $a6 $91 $a4 $88 $d0 $f9 $b1 $a6 $91 $a4 $c6 +$a7 $c6 $a5 $ca $d0 $f2 $60 $85 $78 $ba $e4 $78 $90 $30 $60 $c4 +$82 $90 $2a $d0 $04 $c5 $81 $90 $24 $48 $a2 $08 $98 $48 $b5 $a3 +$ca $10 $fa $20 $e4 $d1 $a2 $00 $68 $95 $a4 $e8 $e0 $08 $30 $f8 +$68 $a8 $68 $c4 $82 $90 $06 $d0 $05 $c5 $81 $b0 $01 $60 $a2 $0c +$20 $97 $c8 $bd $b2 $e6 $bc $b3 $e6 $20 $d8 $c8 $20 $8e $c3 $a9 +$ef $a0 $e7 $20 $d8 $c8 $a4 $88 $c8 $f0 $03 $20 $7c $da $a9 $00 +$85 $df $85 $dc $a9 $00 $a0 $e8 $20 $d8 $c8 $18 $20 $52 $c2 $86 +$c3 $84 $c4 $20 $c2 $00 $f0 $f4 $a2 $ff $86 $88 $90 $06 $20 $83 +$c2 $4c $f8 $c4 $20 $5a $c7 $20 $83 $c2 $84 $5d $20 $29 $c3 $90 +$44 $a0 $01 $b1 $aa $85 $72 $a5 $7b $85 $71 $a5 $ab $85 $74 $a5 +$aa $88 $f1 $aa $18 $65 $7b $85 $7b $85 $73 $a5 $7c $69 $ff $85 +$7c $e5 $ab $aa $38 $a5 $aa $e5 $7b $a8 $b0 $03 $e8 $c6 $74 $18 +$65 $71 $90 $03 $c6 $72 $18 $b1 $71 $91 $73 $c8 $d0 $f9 $e6 $72 +$e6 $74 $ca $d0 $f2 $ad $21 $02 $f0 $3f $a5 $85 $a4 $86 $85 $81 +$84 $82 $a5 $7b $85 $a6 $a4 $7c $84 $a7 $65 $5d $90 $01 $c8 $85 +$a4 $84 $a5 $20 $c5 $c0 $a5 $7f $a4 $80 $85 $7b $84 $7c $a4 $5d +$88 $b9 $1d $02 $91 $aa $88 $c0 $03 $d0 $f6 $a5 $12 $91 $aa $88 +$a5 $11 $91 $aa $88 $a9 $ff $91 $aa $20 $6a $c3 $a6 $79 $a5 $7a +$a0 $01 $86 $71 $85 $72 $b1 $71 $f0 $18 $a0 $04 $c8 $b1 $71 $d0 +$fb $38 $98 $65 $71 $aa $a0 $00 $91 $71 $98 $65 $72 $c8 $91 $71 +$90 $e0 $4c $6c $c1 $20 $f0 $c8 $20 $ed $c8 $d0 $05 $20 $f2 $c8 +$ca $2c $a2 $00 $20 $ef $e0 $90 $fb $f0 $f9 $c9 $07 $f0 $10 $c9 +$0d $f0 $19 $e0 $00 $d0 $04 $c9 $21 $90 $e9 $c9 $08 $f0 $de $e0 +$47 $b0 $0c $9d $21 $02 $e8 $20 $f2 $c8 $d0 $d8 $4c $8e $c8 $a9 +$07 $d0 $f4 $a0 $ff $38 $a5 $c3 $e9 $21 $aa $86 $60 $bd $21 $02 +$f0 $51 $c9 $5f $b0 $4d $c9 $3c $b0 $0e $c9 $30 $b0 $45 $85 $5c +$c9 $22 $f0 $61 $c9 $2a $90 $3b $24 $60 $70 $37 $86 $78 $84 $ba +$a0 $19 $84 $73 $a0 $e3 $84 $74 $a0 $00 $d1 $73 $f0 $05 $90 $21 +$c8 $d0 $f7 $98 $0a $aa $bd $37 $e3 $85 $73 $bd $38 $e3 $85 $74 +$a0 $ff $a6 $78 $c8 $b1 $73 $30 $08 $e8 $dd $21 $02 $f0 $f5 $d0 +$2b $a4 $ba $e8 $c8 $99 $21 $02 $c9 $00 $f0 $32 $e9 $3a $f0 $04 +$c9 $49 $d0 $02 $85 $60 $49 $57 $d0 $93 $85 $5c $bd $21 $02 $f0 +$e2 $c5 $5c $f0 $de $c8 $99 $21 $02 $e8 $d0 $f0 $a6 $78 $b1 $73 +$08 $c8 $28 $10 $f9 $b1 $73 $d0 $be $bd $21 $02 $10 $c3 $c8 $c8 +$99 $21 $02 $c8 $c8 $c8 $c6 $c3 $60 $a5 $79 $a6 $7a $a0 $01 $85 +$aa $86 $ab $b1 $aa $f0 $1a $a0 $03 $b1 $aa $88 $c5 $12 $d0 $04 +$b1 $aa $c5 $11 $b0 $09 $88 $b1 $aa $aa $88 $b1 $aa $90 $de $f0 +$01 $18 $60 $d0 $fd $a9 $00 $a8 $91 $79 $c8 $91 $79 $18 $a5 $79 +$69 $02 $85 $7b $a5 $7a $69 $00 $85 $7c $18 $a5 $79 $69 $ff $85 +$c3 $a5 $7a $69 $ff $85 $c4 $a5 $85 $a4 $86 $85 $81 $84 $82 $a5 +$7b $a4 $7c $85 $7d $84 $7e $85 $7f $84 $80 $20 $49 $c5 $a2 $68 +$86 $65 $68 $aa $68 $8e $fe $01 $8d $ff $01 $a2 $fd $9a $a9 $00 +$85 $8c $85 $61 $60 $f0 $d0 $60 $90 $06 $f0 $04 $c9 $b7 $d0 $f4 +$20 $5a $c7 $20 $29 $c3 $20 $c2 $00 $f0 $0c $c9 $b7 $d0 $93 $20 +$bc $00 $20 $5a $c7 $d0 $8b $a5 $11 $05 $12 $d0 $06 $a9 $ff $85 +$11 $85 $12 $a0 $01 $84 $60 $20 $97 $c8 $b1 $aa $f0 $3e $20 $19 +$c5 $c8 $b1 $aa $aa $c8 $b1 $aa $c5 $12 $d0 $04 $e4 $11 $f0 $02 +$b0 $2a $84 $97 $20 $87 $da $a9 $20 $a4 $97 $29 $7f $20 $f2 $c8 +$c9 $22 $d0 $06 $a5 $60 $49 $ff $85 $60 $c8 $b1 $aa $d0 $0e $a8 +$b1 $aa $aa $c8 $b1 $aa $86 $aa $85 $ab $d0 $b7 $60 $10 $de $24 +$60 $30 $da $a2 $e5 $0a $0a $90 $02 $e8 $18 $69 $1a $90 $01 $e8 +$85 $73 $86 $74 $84 $97 $a0 $00 $b1 $73 $aa $c8 $b1 $73 $ca $f0 +$b8 $20 $f2 $c8 $c8 $b1 $73 $48 $c8 $b1 $73 $a0 $00 $85 $74 $68 +$85 $73 $b1 $73 $ca $f0 $a2 $20 $f2 $c8 $c8 $d0 $f5 $a9 $80 $85 +$61 $20 $b9 $c7 $68 $68 $a9 $10 $20 $07 $c1 $20 $a2 $c6 $18 $98 +$65 $c3 $48 $a5 $c4 $69 $00 $48 $a5 $88 $48 $a5 $87 $48 $a9 $ad +$20 $f6 $cb $20 $d5 $ca $20 $d2 $ca $a5 $b0 $09 $7f $25 $ad $85 +$ad $a9 $9c $a0 $c4 $85 $71 $84 $72 $4c $89 $cb $a9 $e9 $a0 $e1 +$20 $82 $d8 $20 $c2 $00 $c9 $b2 $d0 $06 $20 $bc $00 $20 $d2 $ca +$20 $ee $d8 $85 $b0 $20 $7e $cb $a5 $98 $48 $a5 $97 $48 $a9 $81 +$48 $20 $19 $c5 $a5 $c3 $a4 $c4 $a6 $88 $e8 $f0 $04 $85 $8b $84 +$8c $a0 $00 $b1 $c3 $f0 $07 $c9 $3a $f0 $1d $4c $07 $cc $a0 $02 +$b1 $c3 $18 $f0 $56 $c8 $b1 $c3 $85 $87 $c8 $b1 $c3 $85 $88 $98 +$65 $c3 $85 $c3 $90 $02 $e6 $c4 $20 $bc $00 $20 $01 $c5 $4c $c1 +$c4 $f0 $54 $0a $b0 $03 $4c $b9 $c7 $c9 $56 $b0 $ce $a8 $b9 $11 +$e2 $48 $b9 $10 $e2 $48 $4c $bc $00 $6c $03 $02 $c9 $03 $b0 $01 +$18 $d0 $67 $a5 $c4 $49 $02 $f0 $10 $49 $02 $a4 $c3 $84 $8b $85 +$8c $a5 $87 $a4 $88 $85 $89 $84 $8a $68 $68 $90 $07 $a9 $e7 $a0 +$e7 $4c $53 $c1 $4c $5e $c1 $d0 $0f $38 $a5 $79 $e9 $01 $a4 $7a +$b0 $01 $88 $85 $8f $84 $90 $60 $20 $5a $c7 $20 $a5 $c6 $a5 $88 +$c5 $12 $b0 $0b $98 $38 $65 $c3 $a6 $c4 $90 $07 $e8 $b0 $04 $a5 +$79 $a6 $7a $20 $2d $c3 $b0 $03 $4c $77 $c6 $a5 $aa $e9 $01 $a4 +$ab $b0 $d0 $90 $cd $20 $91 $d4 $86 $0d $60 $d0 $fd $a4 $8c $d0 +$05 $a2 $1e $4c $40 $c1 $a9 $93 $20 $19 $df $a9 $93 $20 $1c $df +$84 $c4 $a5 $8b $85 $c3 $a5 $89 $a4 $8a $85 $87 $84 $88 $60 $d0 +$03 $4c $6a $c3 $20 $77 $c3 $f0 $2e $a9 $05 $20 $07 $c1 $a5 $c4 +$48 $a5 $c3 $48 $a5 $88 $48 $a5 $87 $48 $a9 $9d $48 $20 $c2 $00 +$4c $c1 $c4 $a9 $05 $20 $07 $c1 $a5 $c4 $48 $a5 $c3 $48 $a5 $88 +$48 $a5 $87 $48 $a9 $8d $48 $20 $c2 $00 $20 $f0 $c5 $4c $c1 $c4 +$20 $5a $c7 $20 $a5 $c6 $a5 $88 $c5 $12 $b0 $0b $98 $38 $65 $c3 +$a6 $c4 $90 $07 $e8 $b0 $04 $a5 $79 $a6 $7a $20 $2d $c3 $90 $67 +$a5 $aa $e9 $01 $85 $c3 $a5 $ab $e9 $00 $85 $c4 $60 $a2 $22 $4c +$40 $c1 $a8 $ba $bd $03 $01 $c9 $9d $d0 $f2 $e8 $e8 $9a $98 $f0 +$20 $c9 $3a $f0 $1c $e9 $b3 $aa $f0 $04 $ca $d0 $62 $ca $86 $98 +$20 $bc $00 $20 $e6 $ca $a5 $ac $f0 $02 $a9 $ff $ba $45 $98 $d0 +$1a $bd $02 $01 $85 $87 $bd $03 $01 $85 $88 $bd $04 $01 $85 $c3 +$bd $05 $01 $85 $c4 $20 $c2 $00 $4c $c1 $c4 $e8 $e8 $e8 $e8 $e8 +$9a $4c $91 $c6 $a2 $04 $2c $a2 $0e $4c $40 $c1 $d0 $9e $68 $68 +$68 $c9 $8d $d0 $ef $68 $85 $87 $68 $85 $88 $68 $85 $c3 $68 $85 +$c4 $20 $a2 $c6 $98 $18 $65 $c3 $85 $c3 $90 $02 $e6 $c4 $60 $4c +$07 $cc $a2 $3a $2c $a2 $00 $a0 $00 $84 $5c $8a $45 $5c $85 $5c +$b1 $c3 $f0 $ea $c5 $5c $f0 $e6 $c8 $c9 $22 $d0 $f3 $f0 $ec $20 +$e6 $ca $20 $c2 $00 $c9 $b0 $f0 $11 $c9 $89 $d0 $d2 $a6 $c3 $a4 +$c4 $20 $bc $00 $b0 $c9 $86 $c3 $84 $c4 $a5 $ac $f0 $1b $20 $bc +$00 $b0 $03 $4c $f0 $c5 $c9 $90 $d0 $03 $4c $03 $c5 $20 $01 $c5 +$a0 $00 $b1 $c3 $c9 $ac $f0 $99 $60 $a0 $00 $a2 $01 $c8 $b1 $c3 +$f0 $0f $c9 $8b $d0 $03 $e8 $d0 $f4 $c9 $ac $d0 $f0 $ca $d0 $ed +$c8 $98 $18 $65 $c3 $85 $c3 $90 $02 $e6 $c4 $20 $c2 $00 $90 $c3 +$4c $01 $c5 $20 $a5 $c6 $4c $94 $c6 $4c $07 $cc $c9 $a9 $d0 $03 +$4c $3d $df $c9 $aa $d0 $03 $4c $41 $df $20 $91 $d4 $48 $c9 $8d +$f0 $04 $c9 $89 $d0 $e3 $c6 $af $d0 $04 $68 $4c $03 $c5 $20 $bc +$00 $20 $5a $c7 $c9 $2c $f0 $ee $68 $60 $a2 $00 $86 $11 $86 $12 +$b0 $f7 $e0 $19 $a8 $b0 $dd $e9 $2f $a8 $a5 $11 $0a $26 $12 $0a +$26 $12 $65 $11 $85 $11 $8a $65 $12 $06 $11 $2a $aa $98 $65 $11 +$85 $11 $90 $01 $e8 $20 $bc $00 $4c $5e $c7 $a9 $ed $2c $a9 $e9 +$48 $20 $af $cd $a6 $5f $30 $1e $85 $97 $84 $98 $20 $82 $d8 $68 +$48 $a0 $e1 $20 $c3 $d5 $20 $a8 $d8 $20 $c2 $00 $c9 $2c $d0 $a8 +$20 $bc $00 $4c $91 $c7 $4c $e1 $ca $20 $af $cd $85 $97 $84 $98 +$a9 $c1 $20 $f6 $cb $a5 $5f $48 $20 $e6 $ca $68 $2a $20 $d8 $ca +$d0 $03 $4c $a8 $d8 $a0 $02 $b1 $ae $c5 $82 $90 $17 $d0 $07 $88 +$b1 $ae $c5 $81 $90 $0e $a4 $af $c4 $7c $90 $08 $d0 $0d $a5 $ae +$c5 $7b $b0 $07 $a5 $ae $a4 $af $4c $11 $c8 $a0 $00 $b1 $ae $20 +$37 $d1 $a5 $9e $a4 $9f $85 $b8 $84 $b9 $20 $16 $d3 $a9 $ac $a0 +$00 $85 $9e $84 $9f $20 $78 $d3 $a0 $00 $b1 $9e $91 $97 $c8 $b1 +$9e $91 $97 $c8 $b1 $9e $91 $97 $60 $20 $af $cd $85 $97 $84 $98 +$20 $05 $df $a6 $5f $30 $07 $a8 $20 $6b $d0 $4c $a8 $d8 $48 $a9 +$01 $b0 $01 $68 $20 $3f $d1 $f0 $05 $68 $a0 $00 $91 $ad $20 $8a +$d1 $4c $d5 $c7 $20 $db $c8 $20 $c2 $00 $f0 $3b $c9 $ab $f0 $56 +$c9 $af $f0 $52 $c9 $2c $f0 $38 $c9 $3b $f0 $66 $20 $e6 $ca $24 +$5f $30 $e1 $20 $9a $da $20 $49 $d1 $a0 $00 $a5 $0f $f0 $0a $38 +$e5 $0e $f1 $ae $b0 $03 $20 $97 $c8 $20 $db $c8 $f0 $c9 $a9 $00 +$9d $21 $02 $a2 $21 $a0 $02 $a9 $0d $20 $f2 $c8 $a9 $0a $d0 $52 +$a5 $0e $c5 $10 $90 $05 $20 $97 $c8 $d0 $27 $38 $e5 $64 $b0 $fc +$49 $ff $69 $01 $d0 $12 $48 $20 $8e $d4 $c9 $29 $d0 $7b $68 $c9 +$ab $d0 $06 $8a $e5 $0e $90 $0a $aa $8a $f0 $06 $20 $ed $c8 $ca +$d0 $fa $20 $bc $00 $d0 $85 $60 $20 $49 $d1 $20 $43 $d3 $a0 $00 +$aa $f0 $49 $b1 $71 $20 $f2 $c8 $c8 $ca $d0 $f7 $60 $a9 $20 $2c +$a9 $3f $c9 $20 $90 $19 $48 $a5 $0f $d0 $0a $a5 $0e $e5 $64 $d0 +$0b $85 $0e $f0 $07 $c5 $0e $d0 $03 $20 $97 $c8 $e6 $0e $68 $20 +$f2 $e0 $c9 $0d $d0 $14 $86 $78 $a6 $0d $f0 $0a $a9 $00 $20 $f2 +$c8 $ca $d0 $fa $a9 $0d $86 $0e $a6 $78 $29 $ff $60 $a5 $62 $10 +$0b $a5 $8d $a4 $8e $85 $87 $84 $88 $4c $07 $cc $a9 $1b $a0 $e8 +$20 $d8 $c8 $a5 $8b $a4 $8c $85 $c3 $84 $c4 $60 $c9 $22 $d0 $0b +$20 $c3 $cb $a9 $3b $20 $f6 $cb $20 $db $c8 $20 $6f $d0 $20 $45 +$c2 $a9 $00 $cd $21 $02 $d0 $0a $18 $4c $31 $c5 $a6 $8f $a4 $90 +$a9 $80 $85 $62 $86 $91 $84 $92 $20 $af $cd $85 $97 $84 $98 $a5 +$c3 $a4 $c4 $85 $11 $84 $12 $a6 $91 $a4 $92 $86 $c3 $84 $c4 $20 +$c2 $00 $d0 $11 $24 $62 $30 $65 $20 $f0 $c8 $20 $45 $c2 $86 $c3 +$84 $c4 $20 $c2 $00 $24 $5f $10 $24 $85 $5b $c9 $22 $f0 $07 $a9 +$3a $85 $5b $a9 $2c $18 $85 $5c $a5 $c3 $a4 $c4 $69 $00 $90 $01 +$c8 $20 $4f $d1 $20 $d4 $d4 $20 $d5 $c7 $4c $d3 $c9 $20 $ab $d9 +$20 $a8 $d8 $20 $c2 $00 $f0 $0a $c9 $2c $f0 $03 $4c $2d $c9 $20 +$bc $00 $a5 $c3 $a4 $c4 $85 $91 $84 $92 $a5 $11 $a4 $12 $85 $c3 +$84 $c4 $20 $c2 $00 $f0 $2c $20 $03 $cc $4c $78 $c9 $20 $a2 $c6 +$c8 $aa $d0 $12 $a2 $06 $c8 $b1 $c3 $f0 $73 $c8 $b1 $c3 $85 $8d +$c8 $b1 $c3 $c8 $85 $8e $b1 $c3 $c8 $aa $20 $94 $c6 $e0 $83 $f0 +$81 $d0 $da $a5 $91 $a4 $92 $a6 $62 $10 $03 $4c $53 $c5 $a0 $00 +$b1 $91 $d0 $01 $60 $a9 $0a $a0 $e8 $4c $d8 $c8 $ba $e8 $e8 $e8 +$e8 $bd $01 $01 $c9 $81 $d0 $21 $a5 $98 $d0 $0a $bd $02 $01 $85 +$97 $bd $03 $01 $85 $98 $dd $03 $01 $d0 $07 $a5 $97 $dd $02 $01 +$f0 $07 $8a $18 $69 $10 $aa $d0 $d8 $60 $d0 $04 $a0 $00 $f0 $03 +$20 $af $cd $85 $97 $84 $98 $20 $3c $ca $f0 $04 $a2 $00 $f0 $63 +$9a $8a $38 $e9 $f7 $85 $73 $69 $fb $a0 $01 $20 $82 $d8 $ba $bd +$08 $01 $85 $b0 $a5 $97 $a4 $98 $20 $c3 $d5 $20 $a8 $d8 $a0 $01 +$20 $1e $d9 $ba $dd $08 $01 $f0 $17 $bd $0d $01 $85 $87 $bd $0e +$01 $85 $88 $bd $10 $01 $85 $c3 $bd $0f $01 $85 $c4 $4c $c1 $c4 +$8a $69 $0f $aa $9a $20 $c2 $00 $c9 $2c $d0 $f1 $20 $bc $00 $20 +$70 $ca $20 $e6 $ca $18 $24 $38 $24 $5f $30 $03 $b0 $03 $60 $b0 +$fd $a2 $18 $4c $40 $c1 $a6 $c3 $d0 $02 $c6 $c4 $c6 $c3 $a9 $00 +$48 $a9 $02 $20 $07 $c1 $20 $d2 $cb $a9 $00 $85 $9b $20 $c2 $00 +$38 $e9 $c0 $90 $17 $c9 $03 $b0 $13 $c9 $01 $2a $49 $01 $45 $9b +$c5 $9b $90 $67 $85 $9b $20 $bc $00 $4c $00 $cb $a6 $9b $d0 $2c +$b0 $79 $69 $0a $90 $75 $d0 $07 $24 $5f $10 $03 $4c $d9 $d2 $85 +$71 $0a $65 $71 $a8 $68 $d9 $f2 $e2 $b0 $65 $20 $d5 $ca $48 $20 +$67 $cb $68 $a4 $99 $10 $19 $aa $f0 $76 $d0 $5d $26 $5f $8a $85 +$5f $2a $a6 $c3 $d0 $02 $c6 $c4 $c6 $c3 $a0 $24 $85 $9b $d0 $d5 +$d9 $f2 $e2 $b0 $44 $90 $d7 $b9 $f4 $e2 $48 $b9 $f3 $e2 $48 $20 +$7e $cb $a5 $9b $48 $b9 $f2 $e2 $4c $f0 $ca $4c $07 $cc $68 $85 +$71 $e6 $71 $68 $85 $72 $a5 $b0 $48 $20 $de $d8 $a5 $af $48 $a5 +$ae $48 $a5 $ad $48 $a5 $ac $48 $6c $71 $00 $a0 $ff $68 $f0 $20 +$c9 $64 $f0 $03 $20 $d5 $ca $84 $99 $68 $4a $85 $63 $68 $85 $b3 +$68 $85 $b4 $68 $85 $b5 $68 $85 $b6 $68 $85 $b7 $45 $b0 $85 $b8 +$a5 $ac $60 $a5 $c3 $a4 $c4 $69 $00 $90 $01 $c8 $20 $49 $d1 $4c +$d4 $d4 $20 $bc $00 $b0 $03 $4c $ab $d9 $aa $30 $2f $c9 $24 $f0 +$f6 $c9 $25 $f0 $f2 $c9 $2e $f0 $ee $c9 $22 $f0 $d6 $c9 $28 $d0 +$4f $20 $ee $ca $a9 $29 $a0 $00 $d1 $c3 $d0 $0b $4c $bc $00 $a9 +$28 $d0 $f3 $a9 $2c $d0 $ef $a2 $02 $4c $40 $c1 $c9 $b7 $f0 $29 +$c9 $b6 $f0 $be $c9 $b1 $d0 $13 $a0 $21 $d0 $1f $20 $ab $ce $a5 +$af $49 $ff $a8 $a5 $ae $49 $ff $4c $5e $d0 $c9 $ae $d0 $03 $4c +$b9 $d0 $e9 $c3 $b0 $19 $4c $07 $cc $a0 $1e $68 $68 $4c $3f $cb +$20 $af $cd $85 $ae $84 $af $a6 $5f $30 $03 $4c $82 $d8 $60 $0a +$a8 $b9 $ad $e2 $48 $b9 $ac $e2 $48 $b9 $67 $e2 $f0 $05 $48 $b9 +$66 $e2 $48 $60 $20 $f1 $cb $4c $d7 $ca $20 $f1 $cb $4c $d5 $ca +$46 $5f $4c $bc $00 $20 $ee $ca $20 $03 $cc $20 $d7 $ca $68 $aa +$68 $a8 $a5 $af $48 $a5 $ae $48 $98 $48 $8a $48 $20 $91 $d4 $8a +$60 $20 $ee $ca $20 $d5 $ca $a5 $ac $c9 $98 $b0 $20 $20 $55 $d9 +$a2 $02 $b5 $ad $95 $11 $ca $10 $f9 $20 $c2 $00 $a2 $00 $c9 $29 +$f0 $0a $20 $e3 $d4 $20 $c2 $00 $c9 $29 $d0 $01 $60 $4c $2e $cf +$20 $e7 $cc $45 $5b $a8 $a5 $ae $45 $5c $4c $5e $d0 $20 $e7 $cc +$05 $5b $a8 $a5 $ae $05 $5c $4c $5e $d0 $20 $e7 $cc $25 $5b $a8 +$a5 $ae $25 $5c $4c $5e $d0 $20 $ab $ce $a5 $ae $85 $5c $a5 $af +$85 $5b $20 $c8 $d5 $20 $ab $ce $a5 $af $60 $20 $d8 $ca $b0 $13 +$a5 $b7 $09 $7f $25 $b4 $85 $b4 $a9 $b3 $a0 $00 $20 $1c $d9 $aa +$4c $44 $cd $46 $5f $c6 $9b $20 $43 $d3 $85 $ac $86 $ad $84 $ae +$a5 $b5 $a4 $b6 $20 $47 $d3 $86 $b5 $84 $b6 $aa $38 $e5 $ac $f0 +$08 $a9 $01 $90 $04 $a6 $ac $a9 $ff $85 $b0 $a0 $ff $e8 $c8 $ca +$d0 $07 $a6 $b0 $30 $0f $18 $90 $0c $b1 $b5 $d1 $ad $f0 $ef $a2 +$ff $b0 $02 $a2 $01 $e8 $8a $2a $25 $63 $f0 $02 $a9 $ff $4c $ff +$d8 $20 $03 $cc $aa $20 $b4 $cd $20 $c2 $00 $d0 $f4 $60 $20 $a4 +$cd $a5 $ae $a6 $78 $f0 $22 $e0 $10 $b0 $23 $06 $af $2a $ca $d0 +$fa $a4 $af $4c $5e $d0 $20 $a4 $cd $a5 $ae $a6 $78 $f0 $0a $e0 +$10 $b0 $0b $4a $66 $af $ca $d0 $fa $a4 $af $4c $5e $d0 $a9 $00 +$a8 $4c $5e $d0 $20 $94 $d4 $86 $78 $20 $c8 $d5 $4c $ab $ce $a2 +$00 $20 $c2 $00 $86 $5e $85 $93 $29 $7f $20 $23 $ce $b0 $03 $4c +$07 $cc $a2 $00 $86 $5f $20 $bc $00 $90 $05 $20 $23 $ce $90 $0b +$aa $20 $bc $00 $90 $fb $20 $23 $ce $b0 $f6 $c9 $24 $d0 $0b $a9 +$ff $85 $5f $8a $09 $80 $aa $20 $bc $00 $86 $94 $05 $61 $c9 $28 +$d0 $03 $4c $bd $ce $a9 $00 $85 $61 $a5 $7b $a6 $7c $a0 $00 $86 +$ab $85 $aa $e4 $7e $d0 $04 $c5 $7d $f0 $2c $a5 $93 $d1 $aa $d0 +$08 $a5 $94 $c8 $d1 $aa $f0 $69 $88 $18 $a5 $aa $69 $06 $90 $e1 +$e8 $d0 $dc $c9 $61 $b0 $0a $c9 $41 $90 $05 $e9 $5b $38 $e9 $a5 +$60 $e9 $7b $38 $e9 $85 $60 $68 $48 $c9 $42 $d0 $05 $a9 $ea $a0 +$e1 $60 $a5 $7d $a4 $7e $85 $aa $84 $ab $a5 $7f $a4 $80 $85 $a6 +$84 $a7 $18 $69 $06 $90 $01 $c8 $85 $a4 $84 $a5 $20 $c5 $c0 $a5 +$a4 $a4 $a5 $c8 $85 $7d $84 $7e $a0 $00 $a5 $93 $91 $aa $c8 $a5 +$94 $91 $aa $a9 $00 $c8 $91 $aa $c8 $91 $aa $c8 $91 $aa $c8 $91 +$aa $a5 $aa $18 $69 $02 $a4 $ab $90 $01 $c8 $85 $95 $84 $96 $60 +$a5 $5d $0a $69 $05 $65 $aa $a4 $ab $90 $01 $c8 $85 $a4 $84 $a5 +$60 $20 $bc $00 $20 $d2 $ca $a5 $b0 $30 $0d $a5 $ac $c9 $90 $90 +$09 $a9 $f1 $a0 $e1 $20 $1c $d9 $d0 $74 $4c $55 $d9 $a5 $5e $48 +$a5 $5f $48 $a0 $00 $98 $48 $a5 $94 $48 $a5 $93 $48 $20 $a1 $ce +$68 $85 $93 $68 $85 $94 $68 $a8 $ba $bd $02 $01 $48 $bd $01 $01 +$48 $a5 $ae $9d $02 $01 $a5 $af $9d $01 $01 $c8 $20 $c2 $00 $c9 +$2c $f0 $d2 $84 $5d $20 $f4 $cb $68 $85 $5f $68 $85 $5e $a6 $7d +$a5 $7e $86 $aa $85 $ab $c5 $80 $d0 $04 $e4 $7f $f0 $39 $a0 $00 +$b1 $aa $c8 $c5 $93 $d0 $06 $a5 $94 $d1 $aa $f0 $16 $c8 $b1 $aa +$18 $65 $aa $aa $c8 $b1 $aa $65 $ab $90 $d7 $a2 $10 $2c $a2 $08 +$4c $40 $c1 $a2 $12 $a5 $5e $d0 $f7 $20 $90 $ce $a5 $5d $a0 $04 +$d1 $aa $d0 $e7 $4c $ca $cf $20 $90 $ce $20 $0f $c1 $a0 $00 $84 +$bb $a5 $93 $91 $aa $c8 $a5 $94 $91 $aa $a5 $5d $a0 $04 $84 $ba +$91 $aa $18 $a2 $0b $a9 $00 $24 $5e $50 $07 $68 $69 $01 $aa $68 +$69 $00 $c8 $91 $aa $c8 $8a $91 $aa $20 $19 $d0 $86 $ba $85 $bb +$a4 $71 $c6 $5d $d0 $dd $65 $a5 $b0 $5d $85 $a5 $a8 $8a $65 $a4 +$90 $03 $c8 $f0 $52 $20 $0f $c1 $85 $7f $84 $80 $a9 $00 $e6 $bb +$a4 $ba $f0 $05 $88 $91 $a4 $d0 $fb $c6 $a5 $c6 $bb $d0 $f5 $e6 +$a5 $38 $a0 $02 $a5 $7f $e5 $aa $91 $aa $c8 $a5 $80 $e5 $ab $91 +$aa $a5 $5e $d0 $53 $c8 $b1 $aa $85 $5d $a9 $00 $85 $ba $85 $bb +$c8 $68 $aa $85 $ae $68 $85 $af $d1 $aa $90 $0e $d0 $06 $c8 $8a +$d1 $aa $90 $07 $4c $2b $cf $4c $3e $c1 $c8 $a5 $bb $05 $ba $f0 +$0a $20 $19 $d0 $8a $65 $ae $aa $98 $a4 $71 $65 $af $86 $ba $c6 +$5d $d0 $cb $06 $ba $2a $06 $ba $2a $a8 $a5 $ba $65 $a4 $85 $95 +$98 $65 $a5 $85 $96 $a8 $a5 $95 $60 $84 $71 $b1 $aa $85 $76 $88 +$b1 $aa $85 $77 $a9 $10 $85 $a8 $a2 $00 $a0 $00 $8a $0a $aa $98 +$2a $a8 $b0 $b3 $06 $ba $26 $bb $90 $0b $18 $8a $65 $76 $aa $98 +$65 $77 $a8 $b0 $a2 $c6 $a8 $d0 $e3 $60 $a5 $5f $10 $03 $20 $43 +$d3 $20 $e4 $d1 $38 $a5 $81 $e5 $7f $a8 $a5 $82 $e5 $80 $46 $5f +$85 $ad $84 $ae $a2 $90 $4c $07 $d9 $a4 $0e $a9 $00 $f0 $ef $a6 +$88 $e8 $d0 $a4 $a2 $16 $4c $40 $c1 $20 $aa $d0 $85 $9c $84 $9d +$20 $6f $d0 $20 $ff $cb $a9 $80 $85 $61 $20 $af $cd $20 $d5 $ca +$20 $f4 $cb $a9 $c1 $20 $f6 $cb $a5 $96 $48 $a5 $95 $48 $a5 $c4 +$48 $a5 $c3 $48 $20 $91 $c6 $4c $19 $d1 $a9 $ae $20 $f6 $cb $09 +$80 $85 $61 $20 $b6 $cd $4c $d5 $ca $20 $aa $d0 $48 $98 $48 $20 +$ff $cb $20 $e6 $ca $20 $f4 $cb $20 $d5 $ca $68 $85 $9d $68 $85 +$9c $a2 $20 $a0 $03 $b1 $9c $f0 $9d $85 $96 $88 $b1 $9c $85 $95 +$aa $c8 $b1 $95 $48 $88 $10 $fa $a4 $96 $20 $ac $d8 $a5 $c4 $48 +$a5 $c3 $48 $b1 $9c $85 $c3 $c8 $b1 $9c $85 $c4 $a5 $96 $48 $a5 +$95 $48 $20 $d2 $ca $68 $85 $9c $68 $85 $9d $20 $c2 $00 $f0 $03 +$4c $07 $cc $68 $85 $c3 $68 $85 $c4 $a0 $00 $68 $91 $9c $c8 $68 +$91 $9c $c8 $68 $91 $9c $c8 $68 $91 $9c $60 $20 $d5 $ca $20 $9a +$da $a9 $f0 $a0 $00 $f0 $12 $a6 $ae $a4 $af $86 $9e $84 $9f $20 +$b2 $d1 $86 $ad $84 $ae $85 $ac $60 $a2 $22 $86 $5b $86 $5c $85 +$b8 $84 $b9 $85 $ad $84 $ae $a0 $ff $c8 $b1 $b8 $f0 $0c $c5 $5b +$f0 $04 $c5 $5c $d0 $f3 $c9 $22 $f0 $01 $18 $84 $ac $98 $65 $b8 +$85 $ba $a6 $b9 $90 $01 $e8 $86 $bb $a5 $b9 $c9 $03 $b0 $0b $98 +$20 $37 $d1 $a6 $b8 $a4 $b9 $20 $24 $d3 $a6 $65 $e0 $71 $d0 $05 +$a2 $1c $4c $40 $c1 $a5 $ac $95 $00 $a5 $ad $95 $01 $a5 $ae $95 +$02 $a0 $00 $86 $ae $84 $af $88 $84 $5f $86 $66 $e8 $e8 $e8 $86 +$65 $60 $46 $60 $48 $49 $ff $38 $65 $81 $a4 $82 $b0 $01 $88 $c4 +$80 $90 $11 $d0 $04 $c5 $7f $90 $0b $85 $81 $84 $82 $85 $83 $84 +$84 $aa $68 $60 $a2 $0c $a5 $60 $30 $b8 $20 $e4 $d1 $a9 $80 $85 +$60 $68 $d0 $d0 $a6 $85 $a5 $86 $86 $81 $85 $82 $a0 $00 $84 $9d +$a5 $7f $a6 $80 $85 $aa $86 $ab $a9 $68 $85 $71 $84 $72 $c5 $65 +$f0 $05 $20 $68 $d2 $f0 $f7 $06 $a0 $a5 $7b $a6 $7c $85 $71 $86 +$72 $e4 $7e $d0 $04 $c5 $7d $f0 $05 $20 $62 $d2 $f0 $f3 $85 $a4 +$86 $a5 $a9 $04 $85 $a0 $a5 $a4 $a6 $a5 $e4 $80 $d0 $04 $c5 $7f +$f0 $75 $85 $71 $86 $72 $a0 $02 $b1 $71 $65 $a4 $85 $a4 $c8 $b1 +$71 $65 $a5 $85 $a5 $a0 $01 $b1 $71 $10 $db $a0 $04 $b1 $71 $0a +$69 $05 $20 $9a $d2 $e4 $a5 $d0 $04 $c5 $a4 $f0 $cd $20 $68 $d2 +$f0 $f3 $c8 $b1 $71 $10 $30 $c8 $b1 $71 $f0 $2b $c8 $b1 $71 $aa +$c8 $b1 $71 $c5 $82 $90 $06 $d0 $1e $e4 $81 $b0 $1a $c5 $ab $90 +$17 $d0 $04 $e4 $aa $90 $11 $86 $aa $85 $ab $a5 $71 $a6 $72 $85 +$9c $86 $9d $88 $88 $84 $a2 $18 $a5 $a0 $65 $71 $85 $71 $90 $02 +$e6 $72 $a6 $72 $a0 $00 $60 $c6 $a0 $a6 $9d $f0 $f5 $a4 $a2 $18 +$b1 $9c $65 $aa $85 $a6 $a5 $ab $69 $00 $85 $a7 $a5 $81 $a6 $82 +$85 $a4 $86 $a5 $20 $cc $c0 $a4 $a2 $c8 $a5 $a4 $91 $9c $aa $e6 +$a5 $a5 $a5 $c8 $91 $9c $4c $e8 $d1 $a5 $af $48 $a5 $ae $48 $20 +$d2 $cb $20 $d7 $ca $68 $85 $b8 $68 $85 $b9 $a0 $00 $b1 $b8 $18 +$71 $ae $90 $05 $a2 $1a $4c $40 $c1 $20 $37 $d1 $20 $16 $d3 $a5 +$9e $a4 $9f $20 $47 $d3 $20 $28 $d3 $a5 $b8 $a4 $b9 $20 $47 $d3 +$20 $8a $d1 $4c $fd $ca $a0 $00 $b1 $b8 $48 $c8 $b1 $b8 $aa $c8 +$b1 $b8 $a8 $68 $86 $71 $84 $72 $aa $f0 $14 $a0 $00 $b1 $71 $91 +$83 $c8 $ca $d0 $f8 $98 $18 $65 $83 $85 $83 $90 $02 $e6 $84 $60 +$20 $d7 $ca $a5 $ae $a4 $af $85 $71 $84 $72 $20 $78 $d3 $08 $a0 +$00 $b1 $71 $48 $c8 $b1 $71 $aa $c8 $b1 $71 $a8 $68 $28 $d0 $13 +$c4 $82 $d0 $0f $e4 $81 $d0 $0b $48 $18 $65 $81 $85 $81 $90 $02 +$e6 $82 $68 $86 $71 $84 $72 $60 $c4 $67 $d0 $0c $c5 $66 $d0 $08 +$85 $65 $e9 $03 $85 $66 $a0 $00 $60 $20 $94 $d4 $8a $48 $a9 $01 +$20 $3f $d1 $68 $a0 $00 $91 $ad $4c $8a $d1 $48 $20 $fc $d3 $d1 +$9e $98 $f0 $09 $48 $20 $fc $d3 $18 $f1 $9e $49 $ff $90 $04 $b1 +$9e $aa $98 $48 $8a $48 $20 $3f $d1 $a5 $9e $a4 $9f $20 $47 $d3 +$68 $a8 $68 $18 $65 $71 $85 $71 $90 $02 $e6 $72 $98 $20 $28 $d3 +$4c $8a $d1 $48 $a9 $ff $85 $af $20 $c2 $00 $c9 $29 $f0 $06 $20 +$03 $cc $20 $91 $d4 $20 $fc $d3 $ca $8a $48 $18 $a2 $00 $f1 $9e +$b0 $c2 $49 $ff $c5 $af $90 $bd $a5 $af $b0 $b9 $20 $f4 $cb $68 +$85 $a2 $68 $85 $a3 $68 $aa $68 $85 $9e $68 $85 $9f $a0 $00 $8a +$f0 $79 $e6 $a2 $6c $a2 $00 $20 $40 $d3 $85 $ac $a8 $f0 $38 $20 +$3f $d1 $86 $ad $84 $ae $a8 $88 $b1 $71 $20 $27 $ce $90 $02 $09 +$20 $91 $83 $98 $d0 $f1 $f0 $1f $20 $40 $d3 $85 $ac $a8 $f0 $17 +$20 $3f $d1 $86 $ad $84 $ae $a8 $88 $b1 $71 $20 $23 $ce $90 $02 +$29 $df $91 $83 $98 $d0 $f1 $4c $8a $d1 $20 $bc $00 $20 $af $cd +$20 $f4 $cb $20 $d7 $ca $a0 $02 $b1 $95 $aa $88 $b1 $95 $a8 $8a +$4c $5e $d0 $20 $79 $d4 $4c $6b $d0 $20 $40 $d3 $a8 $60 $20 $79 +$d4 $f0 $08 $a0 $00 $b1 $71 $a8 $4c $6b $d0 $4c $2e $cf $20 $bc +$00 $20 $d2 $ca $20 $a7 $ce $a4 $ae $d0 $f0 $a6 $af $4c $c2 $00 +$20 $79 $d4 $d0 $03 $4c $55 $d6 $a6 $c3 $a4 $c4 $86 $ba $84 $bb +$a6 $71 $86 $c3 $18 $65 $71 $85 $73 $a5 $72 $85 $c4 $69 $00 $85 +$74 $a0 $00 $b1 $73 $48 $98 $91 $73 $20 $c2 $00 $20 $ab $d9 $68 +$a0 $00 $91 $73 $a6 $ba $a4 $bb $86 $c3 $84 $c4 $60 $20 $d2 $ca +$20 $f6 $d4 $20 $03 $cc $a5 $12 $48 $a5 $11 $48 $20 $91 $d4 $68 +$85 $11 $68 $85 $12 $60 $a5 $ac $c9 $98 $b0 $8f $20 $55 $d9 $a5 +$ae $a4 $af $84 $11 $85 $12 $60 $20 $f6 $d4 $a2 $00 $a1 $11 $a8 +$4c $6b $d0 $20 $dd $d4 $8a $a2 $00 $81 $11 $60 $20 $f6 $d4 $a2 +$00 $a1 $11 $a8 $e6 $11 $d0 $02 $e6 $12 $a1 $11 $4c $5e $d0 $20 +$d2 $ca $20 $f6 $d4 $84 $97 $85 $98 $20 $03 $cc $20 $d2 $ca $20 +$f6 $d4 $98 $a2 $00 $81 $97 $e6 $97 $d0 $02 $e6 $98 $a5 $12 $81 +$97 $4c $c2 $00 $20 $af $cd $85 $97 $84 $98 $a5 $5f $48 $20 $03 +$cc $20 $af $cd $68 $45 $5f $10 $10 $a0 $03 $b1 $97 $aa $b1 $95 +$91 $97 $8a $91 $95 $88 $10 $f3 $60 $4c $e1 $ca $20 $d2 $ca $20 +$f6 $d4 $a9 $d5 $48 $a9 $8a $48 $6c $11 $00 $4c $c2 $00 $20 $dd +$d4 $86 $97 $a2 $00 $20 $c2 $00 $f0 $03 $20 $e3 $d4 $86 $98 $b1 +$11 $45 $98 $25 $97 $f0 $f8 $60 $20 $90 $d7 $a5 $b0 $49 $ff $85 +$b0 $45 $b7 $85 $b8 $a5 $ac $4c $c6 $d5 $20 $df $d6 $90 $4d $a9 +$f2 $a0 $e1 $20 $90 $d7 $d0 $10 $a5 $b7 $85 $b0 $a2 $04 $b5 $b2 +$95 $ab $ca $d0 $f9 $86 $b9 $60 $a6 $b9 $86 $a3 $a2 $b3 $a5 $b3 +$a8 $f0 $c4 $38 $e5 $ac $f0 $24 $90 $12 $84 $ac $a4 $b7 $84 $b0 +$49 $ff $69 $00 $a0 $00 $84 $a3 $a2 $ac $d0 $04 $a0 $00 $84 $b9 +$c9 $f9 $30 $b6 $a8 $a5 $b9 $56 $01 $20 $f6 $d6 $24 $b8 $10 $4c +$a0 $ac $e0 $b3 $f0 $02 $a0 $b3 $38 $49 $ff $65 $a3 $85 $b9 $b9 +$03 $00 $f5 $03 $85 $af $b9 $02 $00 $f5 $02 $85 $ae $b9 $01 $00 +$f5 $01 $85 $ad $b0 $03 $20 $9b $d6 $a0 $00 $98 $18 $a6 $ad $d0 +$3e $a6 $ae $86 $ad $a6 $af $86 $ae $a6 $b9 $86 $af $84 $b9 $69 +$08 $c9 $18 $d0 $e8 $a9 $00 $85 $ac $85 $b0 $60 $65 $a3 $85 $b9 +$a5 $af $65 $b6 $85 $af $a5 $ae $65 $b5 $85 $ae $a5 $ad $65 $b4 +$85 $ad $b0 $1a $60 $69 $01 $06 $b9 $26 $af $26 $ae $26 $ad $10 +$f4 $38 $e5 $ac $b0 $cf $49 $ff $69 $01 $85 $ac $90 $0c $e6 $ac +$f0 $36 $66 $ad $66 $ae $66 $af $66 $b9 $60 $a5 $b0 $49 $ff $85 +$b0 $a5 $ad $49 $ff $85 $ad $a5 $ae $49 $ff $85 $ae $a5 $af $49 +$ff $85 $af $a5 $b9 $49 $ff $85 $b9 $e6 $b9 $d0 $0a $e6 $af $d0 +$06 $e6 $ae $d0 $02 $e6 $ad $60 $a2 $0a $4c $40 $c1 $a2 $74 $b4 +$03 $84 $b9 $b4 $02 $94 $03 $b4 $01 $94 $02 $a4 $b2 $94 $01 $69 +$08 $30 $ec $f0 $ea $e9 $08 $a8 $a5 $b9 $b0 $12 $16 $01 $90 $02 +$f6 $01 $76 $01 $76 $01 $76 $02 $76 $03 $6a $c8 $d0 $ee $18 $60 +$20 $ee $d8 $f0 $02 $10 $03 $4c $2e $cf $a5 $ac $e9 $7f $48 $a9 +$80 $85 $ac $a9 $72 $a0 $e1 $20 $c3 $d5 $a9 $76 $a0 $e1 $20 $06 +$d8 $a9 $e9 $a0 $e1 $20 $a8 $d5 $a9 $65 $a0 $e1 $20 $56 $dc $a9 +$7a $a0 $e1 $20 $c3 $d5 $68 $20 $4a $da $a9 $7e $a0 $e1 $20 $90 +$d7 $f0 $4c $20 $b6 $d7 $a9 $00 $85 $75 $85 $76 $85 $77 $a5 $b9 +$20 $65 $d7 $a5 $af $20 $65 $d7 $a5 $ae $20 $65 $d7 $a5 $ad $20 +$6a $d7 $4c $73 $d8 $d0 $03 $4c $cd $d6 $4a $09 $80 $a8 $90 $13 +$18 $a5 $77 $65 $b6 $85 $77 $a5 $76 $65 $b5 $85 $76 $a5 $75 $65 +$b4 $85 $75 $66 $75 $66 $76 $66 $77 $66 $b9 $98 $4a $d0 $de $60 +$85 $71 $84 $72 $a0 $03 $b1 $71 $85 $b6 $88 $b1 $71 $85 $b5 $88 +$b1 $71 $85 $b7 $45 $b0 $85 $b8 $a5 $b7 $09 $80 $85 $b4 $88 $b1 +$71 $85 $b3 $a5 $ac $60 $a5 $b3 $f0 $1d $18 $65 $ac $90 $04 $30 +$31 $18 $2c $10 $12 $69 $80 $85 $ac $d0 $03 $4c $59 $d6 $a5 $b8 +$85 $b0 $60 $a5 $b0 $10 $1b $68 $68 $4c $55 $d6 $20 $cf $d8 $aa +$f0 $f0 $18 $69 $02 $b0 $0b $a2 $00 $86 $b8 $20 $e0 $d5 $e6 $ac +$d0 $e0 $4c $c8 $d6 $20 $cf $d8 $a9 $fa $a0 $e1 $a2 $00 $86 $b8 +$20 $82 $d8 $4c $09 $d8 $20 $90 $d7 $f0 $63 $20 $de $d8 $a9 $00 +$38 $e5 $ac $85 $ac $20 $b6 $d7 $e6 $ac $f0 $d6 $a2 $ff $a9 $01 +$a4 $b4 $c4 $ad $d0 $0a $a4 $b5 $c4 $ae $d0 $04 $a4 $b6 $c4 $af +$08 $2a $90 $0e $a0 $01 $e8 $e0 $02 $30 $04 $d0 $28 $a0 $40 $95 +$75 $98 $28 $90 $14 $a8 $a5 $b6 $e5 $af $85 $b6 $a5 $b5 $e5 $ae +$85 $b5 $a5 $b4 $e5 $ad $85 $b4 $98 $06 $b6 $26 $b5 $26 $b4 $b0 +$cf $30 $bd $10 $cb $4a $6a $6a $85 $b9 $28 $4c $73 $d8 $a2 $14 +$4c $40 $c1 $a5 $75 $85 $ad $a5 $76 $85 $ae $a5 $77 $85 $af $4c +$39 $d6 $85 $71 $84 $72 $a0 $03 $b1 $71 $85 $af $88 $b1 $71 $85 +$ae $88 $b1 $71 $85 $b0 $09 $80 $85 $ad $88 $b1 $71 $85 $ac $84 +$b9 $60 $a2 $a4 $a0 $00 $f0 $04 $a6 $97 $a4 $98 $20 $de $d8 $86 +$71 $84 $72 $a0 $03 $a5 $af $91 $71 $88 $a5 $ae $91 $71 $88 $a5 +$b0 $09 $7f $25 $ad $91 $71 $88 $a5 $ac $91 $71 $84 $b9 $60 $20 +$de $d8 $a2 $05 $b5 $ab $95 $b2 $ca $d0 $f9 $86 $b9 $60 $a5 $ac +$f0 $fb $06 $b9 $90 $f7 $20 $bd $d6 $d0 $f2 $4c $8e $d6 $a5 $ac +$f0 $09 $a5 $b0 $2a $a9 $ff $b0 $02 $a9 $01 $60 $20 $ee $d8 $85 +$ad $a9 $00 $85 $ae $a2 $88 $a5 $ad $49 $ff $2a $a9 $00 $85 $af +$86 $ac $85 $b9 $85 $b0 $4c $34 $d6 $46 $b0 $60 $85 $73 $84 $74 +$a0 $00 $b1 $73 $c8 $aa $f0 $c6 $b1 $73 $45 $b0 $30 $c4 $e4 $ac +$d0 $1a $b1 $73 $09 $80 $c5 $ad $d0 $12 $c8 $b1 $73 $c5 $ae $d0 +$0b $c8 $a9 $7f $c5 $b9 $b1 $73 $e5 $af $f0 $28 $a5 $b0 $90 $02 +$49 $ff $4c $f4 $d8 $a5 $ac $f0 $4a $38 $e9 $98 $24 $b0 $10 $09 +$aa $a9 $ff $85 $b2 $20 $a1 $d6 $8a $a2 $ac $c9 $f9 $10 $06 $20 +$df $d6 $84 $b2 $60 $a8 $a5 $b0 $29 $80 $46 $ad $05 $ad $85 $ad +$20 $f6 $d6 $84 $b2 $60 $a5 $ac $c9 $98 $b0 $1e $20 $55 $d9 $84 +$b9 $a5 $b0 $84 $b0 $49 $80 $2a $a9 $98 $85 $ac $a5 $af $85 $5b +$4c $34 $d6 $85 $ad $85 $ae $85 $af $a8 $60 $a0 $00 $84 $5f $a2 +$09 $94 $a8 $ca $10 $fb $90 $7f $c9 $2d $d0 $04 $86 $b1 $f0 $04 +$c9 $2b $d0 $05 $20 $bc $00 $90 $6e $c9 $24 $d0 $03 $4c $73 $de +$c9 $25 $d0 $08 $4c $a1 $de $20 $bc $00 $90 $5b $c9 $2e $f0 $2e +$c9 $45 $d0 $30 $20 $bc $00 $90 $17 $c9 $b7 $f0 $0e $c9 $2d $f0 +$0a $c9 $b6 $f0 $08 $c9 $2b $f0 $04 $d0 $07 $66 $ab $20 $bc $00 +$90 $5b $24 $ab $10 $0e $a9 $00 $38 $e5 $a9 $4c $16 $da $66 $aa +$24 $aa $50 $c3 $a5 $a9 $38 $e5 $a8 $85 $a9 $f0 $12 $10 $09 $20 +$f5 $d7 $e6 $a9 $d0 $f9 $f0 $07 $20 $dc $d7 $c6 $a9 $d0 $f9 $a5 +$b1 $30 $01 $60 $4c $f9 $db $48 $24 $aa $10 $02 $e6 $a8 $20 $dc +$d7 $68 $29 $0f $20 $4a $da $4c $d7 $d9 $48 $20 $cf $d8 $68 $20 +$ff $d8 $a5 $b7 $45 $b0 $85 $b8 $a6 $ac $4c $c6 $d5 $a5 $a9 $c9 +$0a $90 $09 $a9 $64 $24 $ab $30 $0e $4c $c8 $d6 $0a $0a $65 $a9 +$0a $a0 $00 $71 $c3 $e9 $2f $85 $a9 $4c $fd $d9 $a9 $f6 $a0 $e7 +$20 $d8 $c8 $a5 $88 $a6 $87 $85 $ad $86 $ae $a2 $90 $38 $20 $0c +$d9 $a0 $00 $98 $20 $a7 $da $4c $d8 $c8 $a0 $01 $a9 $20 $24 $b0 +$10 $02 $a9 $2d $99 $ef $00 $85 $b0 $84 $ba $c8 $a6 $ac $d0 $05 +$a9 $30 $4c $b3 $db $a9 $00 $e0 $81 $b0 $09 $a9 $8a $a0 $e1 $20 +$3e $d7 $a9 $fa $85 $a8 $a9 $86 $a0 $e1 $20 $1c $d9 $f0 $1e $10 +$12 $a9 $82 $a0 $e1 $20 $1c $d9 $f0 $02 $10 $0e $20 $dc $d7 $c6 +$a8 $d0 $ee $20 $f5 $d7 $e6 $a8 $d0 $dc $20 $bf $d5 $20 $55 $d9 +$a2 $01 $a5 $a8 $18 $69 $07 $30 $09 $c9 $08 $b0 $06 $69 $ff $aa +$a9 $02 $38 $e9 $02 $85 $a9 $86 $a8 $8a $f0 $02 $10 $13 $a4 $ba +$a9 $2e $c8 $99 $ef $00 $8a $f0 $06 $a9 $30 $c8 $99 $ef $00 $84 +$ba $a0 $00 $a2 $80 $a5 $af $18 $79 $00 $e2 $85 $af $a5 $ae $79 +$ff $e1 $85 $ae $a5 $ad $79 $fe $e1 $85 $ad $e8 $b0 $04 $10 $e5 +$30 $02 $30 $e1 $8a $90 $04 $49 $ff $69 $0a $69 $2f $c8 $c8 $c8 +$84 $95 $a4 $ba $c8 $aa $29 $7f $99 $ef $00 $c6 $a8 $d0 $06 $a9 +$2e $c8 $99 $ef $00 $84 $ba $a4 $95 $8a $49 $ff $29 $80 $aa $c0 +$12 $d0 $b2 $a4 $ba $b9 $ef $00 $88 $c9 $30 $f0 $f8 $c9 $2e $f0 +$01 $c8 $a9 $2b $a6 $a9 $f0 $2e $10 $08 $a9 $00 $38 $e5 $a9 $aa +$a9 $2d $99 $f1 $00 $a9 $45 $99 $f0 $00 $8a $a2 $2f $38 $e8 $e9 +$0a $b0 $fb $69 $3a $99 $f3 $00 $8a $99 $f2 $00 $a9 $00 $99 $f4 +$00 $f0 $08 $99 $ef $00 $a9 $00 $99 $f0 $00 $a9 $f0 $a0 $00 $60 +$f0 $42 $a5 $b3 $d0 $03 $4c $57 $d6 $a2 $9c $a0 $00 $20 $ac $d8 +$a5 $b7 $10 $0f $20 $86 $d9 $a9 $9c $a0 $00 $20 $1c $d9 $d0 $03 +$98 $a4 $5b $20 $ca $d5 $98 $48 $20 $00 $d7 $a9 $9c $a0 $00 $20 +$3e $d7 $20 $04 $dc $68 $4a $90 $0a $a5 $ac $f0 $06 $a5 $b0 $49 +$ff $85 $b0 $60 $a9 $8e $a0 $e1 $20 $3e $d7 $a5 $b9 $69 $50 $90 +$03 $20 $e6 $d8 $85 $a3 $20 $d2 $d8 $a5 $ac $c9 $88 $90 $03 $20 +$d3 $d7 $20 $86 $d9 $a5 $5b $18 $69 $81 $f0 $f3 $38 $e9 $01 $48 +$a2 $04 $b5 $b3 $b4 $ac $95 $ac $94 $b3 $ca $10 $f5 $a5 $a3 $85 +$b9 $20 $ab $d5 $20 $f9 $db $a9 $92 $a0 $e1 $20 $6c $dc $a9 $00 +$85 $b8 $68 $4c $b8 $d7 $85 $ba $84 $bb $20 $a2 $d8 $a9 $a4 $20 +$3e $d7 $20 $70 $dc $a9 $a4 $a0 $00 $4c $3e $d7 $85 $ba $84 $bb +$a2 $a8 $20 $a4 $d8 $b1 $ba $85 $b1 $a4 $ba $c8 $98 $d0 $02 $e6 +$bb $85 $ba $a4 $bb $20 $3e $d7 $a5 $ba $a4 $bb $18 $69 $04 $90 +$01 $c8 $85 $ba $84 $bb $20 $c3 $d5 $a9 $a8 $a0 $00 $c6 $b1 $d0 +$e4 $60 $a5 $ac $f0 $07 $a2 $d8 $a0 $00 $20 $ac $d8 $a2 $af $a0 +$13 $06 $d9 $26 $da $26 $db $26 $d8 $90 $05 $8a $45 $d9 $85 $d9 +$88 $d0 $ee $a2 $02 $b5 $d9 $95 $ad $ca $10 $f9 $a9 $80 $85 $ac +$0a $85 $b0 $4c $39 $d6 $a9 $af $a0 $e1 $20 $c3 $d5 $20 $cf $d8 +$a9 $c4 $a0 $e1 $a6 $b7 $20 $fe $d7 $20 $cf $d8 $20 $86 $d9 $a9 +$00 $85 $b8 $20 $ab $d5 $a9 $f6 $a0 $e1 $20 $a8 $d5 $a5 $b0 $48 +$10 $0d $20 $bf $d5 $a5 $b0 $30 $09 $a5 $63 $49 $ff $85 $63 $20 +$f9 $db $a9 $f6 $a0 $e1 $20 $c3 $d5 $68 $10 $03 $20 $f9 $db $a9 +$b3 $a0 $e1 $4c $56 $dc $20 $a2 $d8 $a9 $00 $85 $63 $20 $dd $dc +$a2 $9c $a0 $00 $20 $ac $d8 $a9 $a4 $a0 $00 $20 $82 $d8 $a9 $00 +$85 $b0 $a5 $63 $20 $4e $dd $a9 $9c $a0 $00 $4c $06 $d8 $48 $4c +$0f $dd $20 $0a $00 $4c $f4 $cb $a5 $b0 $48 $10 $03 $20 $f9 $db +$a5 $ac $48 $c9 $81 $90 $07 $a9 $e9 $a0 $e1 $20 $06 $d8 $a9 $c8 +$a0 $e1 $20 $56 $dc $68 $c9 $81 $90 $07 $a9 $af $a0 $e1 $20 $a8 +$d5 $68 $10 $16 $4c $f9 $db $20 $dd $d4 $e0 $08 $b0 $20 $a9 $00 +$38 $2a $ca $10 $fc $e8 $01 $11 $81 $11 $60 $20 $dd $d4 $e0 $08 +$b0 $0c $a9 $ff $2a $ca $10 $fc $e8 $21 $11 $81 $11 $60 $4c $2e +$cf $20 $bc $00 $20 $dd $d4 $e0 $08 $b0 $f3 $20 $c2 $00 $c9 $29 +$f0 $03 $4c $07 $cc $20 $bc $00 $a9 $00 $38 $2a $ca $10 $fc $e8 +$21 $11 $f0 $02 $a9 $ff $4c $ff $d8 $e0 $19 $b0 $48 $86 $78 $a9 +$18 $20 $3f $d1 $a0 $17 $a2 $18 $46 $11 $66 $12 $66 $13 $8a $2a +$91 $ad $88 $10 $f3 $a5 $78 $f0 $0a $aa $38 $49 $ff $69 $18 $f0 +$1c $d0 $0f $a8 $b1 $ad $c9 $30 $d0 $07 $ca $f0 $03 $c8 $10 $f4 +$e8 $98 $18 $65 $ad $85 $ad $a9 $00 $65 $ae $85 $ae $86 $ac $20 +$bc $00 $4c $8a $d1 $4c $2e $cf $e0 $07 $b0 $f9 $86 $78 $a9 $06 +$20 $3f $d1 $a0 $05 $f8 $a5 $13 $20 $56 $de $a5 $12 $20 $56 $de +$a5 $11 $20 $56 $de $d8 $a2 $06 $a5 $78 $f0 $b7 $aa $38 $49 $ff +$69 $06 $f0 $c9 $d0 $bc $aa $29 $0f $20 $61 $de $8a $4a $4a $4a +$4a $c9 $0a $69 $30 $91 $ad $88 $60 $85 $ac $a9 $00 $85 $b8 $8a +$20 $4a $da $20 $bc $00 $90 $0a $09 $20 $e9 $61 $c9 $06 $b0 $2a +$69 $0a $29 $0f $aa $a5 $ac $f0 $e4 $69 $04 $90 $dc $4c $c8 $d6 +$aa $a5 $ac $f0 $06 $e6 $ac $f0 $f4 $a9 $00 $85 $b8 $8a $20 $4a +$da $20 $bc $00 $49 $30 $c9 $02 $90 $e6 $4c $2f $da $ad $00 $02 +$d0 $18 $20 $ef $e0 $90 $0b $8d $01 $02 $a2 $20 $8e $02 $02 $4c +$1c $c5 $ae $02 $02 $f0 $03 $ce $02 $02 $a2 $dc $20 $d5 $de $a2 +$df $20 $d5 $de $60 $b5 $00 $10 $fb $0a $29 $40 $f0 $f6 $95 $00 +$8a $a8 $68 $68 $a9 $05 $20 $07 $c1 $a5 $c4 $48 $a5 $c3 $48 $a5 +$88 $48 $a5 $87 $48 $a9 $8d $48 $b9 $01 $00 $85 $c3 $b9 $02 $00 +$85 $c4 $4c $c1 $c4 $20 $ef $e0 $b0 $09 $ad $02 $02 $f0 $09 $ad +$01 $02 $38 $a2 $00 $8e $02 $02 $60 $a2 $df $2c $a2 $dc $c9 $93 +$f0 $11 $c9 $b5 $f0 $07 $49 $a2 $f0 $0e $4c $07 $cc $a9 $7f $35 +$00 $10 $05 $b5 $00 $0a $15 $00 $95 $00 $4c $bc $00 $58 $a2 $df +$2c $a2 $dc $86 $78 $20 $bc $00 $20 $5a $c7 $a5 $79 $a6 $7a $20 +$2d $c3 $b0 $03 $4c $77 $c6 $a6 $78 $a5 $aa $e9 $01 $95 $01 $a5 +$ab $e9 $00 $95 $02 $a9 $c0 $95 $00 $60 $d0 $fd $a5 $df $0a $05 +$df $85 $df $4c $7e $c6 $d0 $f1 $a5 $dc $0a $05 $dc $85 $dc $4c +$7e $c6 $20 $ee $ca $4c $d5 $ca $20 $b6 $df $10 $fb $a5 $b4 $09 +$80 $85 $b4 $20 $c8 $d5 $f0 $f0 $20 $b6 $df $30 $fb $f0 $f9 $a5 +$b4 $09 $80 $85 $b4 $20 $c8 $d5 $f0 $ee $c9 $29 $d0 $05 $68 $68 +$4c $bc $00 $4c $07 $cc $20 $c2 $00 $c9 $2c $d0 $ed $20 $de $d8 +$a5 $b0 $09 $7f $25 $ad $48 $a5 $ae $48 $a5 $af $48 $a5 $ac $48 +$20 $bc $00 $20 $d2 $ca $68 $85 $b3 $68 $85 $b6 $68 $85 $b5 $68 +$85 $b4 $85 $b7 $a9 $b3 $a0 $00 $4c $1c $d9 $c9 $2c $f0 $1b $20 +$91 $d4 $8a $f0 $0a $e0 $10 $90 $45 $e4 $64 $b0 $02 $86 $64 $86 +$0f $20 $c2 $00 $f0 $1a $c9 $2c $d0 $a9 $20 $8e $d4 $8a $30 $2e +$e0 $01 $90 $2a $a5 $0f $f0 $06 $e4 $0f $f0 $02 $b0 $20 $86 $64 +$a5 $0f $f0 $06 $c5 $64 $b0 $03 $85 $64 $38 $e5 $64 $b0 $fc $65 +$64 $18 $65 $64 $85 $10 $a5 $0f $38 $e5 $10 $85 $10 $60 $4c $2e +$cf $a5 $b0 $30 $f9 $a5 $ac $f0 $f4 $20 $cf $d8 $a9 $00 $85 $77 +$85 $76 $85 $75 $85 $78 $85 $af $85 $ae $85 $ad $a2 $18 $a5 $b3 +$4a $b0 $0e $06 $b6 $26 $b5 $26 $b4 $26 $77 $26 $76 $26 $75 $26 +$78 $06 $b6 $26 $b5 $26 $b4 $26 $77 $26 $76 $26 $75 $26 $78 $06 +$af $26 $ae $26 $ad $a5 $af $2a $85 $5b $a5 $ae $2a $85 $5c $a5 +$ad $2a $85 $5d $a9 $00 $2a $85 $5e $a5 $77 $e5 $5b $85 $5b $a5 +$76 $e5 $5c $85 $5c $a5 $75 $e5 $5d $a8 $a5 $78 $e5 $5e $90 $0e +$85 $78 $84 $75 $a5 $5c $85 $76 $a5 $5b $85 $77 $e6 $af $ca $d0 +$a2 $38 $a5 $b3 $e9 $80 $6a $69 $00 $85 $ac $4c $39 $d6 $20 $bc +$00 $20 $af $cd $20 $f4 $cb $a4 $95 $a5 $96 $4c $5e $d0 $a9 $c4 +$a0 $e1 $20 $82 $d8 $c6 $ac $60 $a9 $c4 $a0 $e1 $4c $82 $d8 $6c +$05 $02 $6c $07 $02 $6c $09 $02 $6c $0b $02 $ff $00 $00 $ad $de +$c0 $ff $d3 $ff $e6 $c3 $d0 $02 $e6 $c4 $ad $ff $ff $c9 $ac $f0 +$0e $c9 $3a $b0 $0a $c9 $20 $f0 $eb $38 $e9 $30 $38 $e9 $d0 $60 +$4c $00 $c0 $00 $00 $00 $00 $00 $00 $00 $4c $2e $cf $00 $00 $00 +$f2 $00 $03 $0d $0a $4d $65 $6d $6f $72 $79 $20 $73 $69 $7a $65 +$20 $00 $20 $42 $79 $74 $65 $73 $20 $66 $72 $65 $65 $0d $0a $0a +$45 $6e $68 $61 $6e $63 $65 $64 $20 $42 $41 $53 $49 $43 $20 $32 +$2e $32 $32 $0a $00 $02 $80 $19 $56 $62 $80 $76 $22 $f3 $82 $38 +$aa $40 $80 $35 $04 $f3 $81 $35 $04 $f3 $80 $80 $00 $00 $80 $31 +$72 $18 $91 $43 $4f $f8 $94 $74 $23 $f7 $94 $74 $24 $00 $81 $38 +$aa $3b $06 $74 $63 $90 $8c $77 $23 $0c $ab $7a $1e $94 $00 $7c +$63 $42 $80 $7e $75 $fe $d0 $80 $31 $72 $15 $81 $00 $00 $00 $81 +$49 $0f $db $04 $86 $1e $d7 $fb $87 $99 $26 $65 $87 $23 $34 $58 +$86 $a5 $5d $e1 $83 $49 $0f $db $08 $78 $3a $c5 $37 $7b $83 $a2 +$5c $7c $2e $dd $4d $7d $99 $b0 $1e $7d $59 $ed $24 $7e $91 $72 +$00 $7e $4c $b9 $73 $7f $aa $aa $53 $81 $00 $00 $00 $81 $80 $00 +$00 $90 $80 $00 $00 $00 $7f $00 $00 $00 $84 $20 $00 $00 $fe $79 +$60 $00 $27 $10 $ff $fc $18 $00 $00 $64 $ff $ff $f6 $00 $00 $01 +$1f $c5 $5c $c4 $69 $ca $90 $c6 $4b $c9 $63 $cd $6b $c9 $b8 $c7 +$8a $c7 $ef $c5 $ae $c5 $be $c6 $46 $c5 $d2 $c5 $69 $df $75 $df +$7b $c6 $22 $c7 $1d $c5 $2b $c7 $84 $c5 $8d $c7 $8d $d5 $f4 $e0 +$f7 $e0 $78 $d0 $12 $d5 $2e $d5 $7b $d5 $b8 $c5 $21 $c6 $59 $c8 +$8a $c5 $a7 $c3 $a4 $c3 $52 $c3 $ea $df $28 $c8 $53 $d5 $86 $dd +$9a $dd $18 $df $1b $df $69 $cc $69 $cc $69 $cc $ed $ca $f0 $cb +$f0 $cb $69 $cc $69 $cc $69 $cc $69 $cc $69 $cc $69 $cc $69 $cc +$69 $cc $69 $cc $69 $cc $00 $00 $63 $cc $69 $cc $63 $cc $63 $cc +$63 $cc $63 $cc $69 $cc $90 $cc $90 $cc $00 $00 $81 $df $81 $df +$6f $cc $6f $cc $00 $00 $74 $cc $74 $cc $74 $cc $fb $d8 $85 $d9 +$18 $d9 $51 $dd $49 $d0 $68 $d0 $40 $e0 $a1 $dc $ff $d6 $03 $dc +$d5 $dc $dc $dc $25 $dd $57 $dd $07 $d5 $1b $d5 $59 $d4 $72 $d4 +$2a $d1 $9f $d4 $7d $d4 $37 $d4 $16 $d4 $88 $d3 $27 $de $d8 $dd +$b0 $dd $87 $df $97 $df $dd $e0 $e7 $e0 $cd $e0 $9a $d3 $a3 $d3 +$d2 $d3 $79 $c5 $d5 $79 $aa $d5 $7b $40 $d7 $7b $08 $d8 $7f $bf +$db $50 $d9 $cc $46 $bf $cc $46 $cc $cc $56 $85 $cd $56 $6d $cd +$7d $f8 $db $5a $1b $cc $64 $fa $cc $2a $2b $2d $2f $3c $3d $3e +$3f $41 $42 $43 $44 $45 $46 $47 $48 $49 $4c $4d $4e $4f $50 $52 +$53 $54 $55 $56 $57 $5e $00 $71 $e3 $73 $e3 $75 $e3 $77 $e3 $79 +$e3 $7d $e3 $7f $e3 $83 $e3 $85 $e3 $95 $e3 $ae $e3 $c5 $e3 $de +$e3 $ed $e3 $f7 $e3 $04 $e4 $0a $e4 $1c $e4 $41 $e4 $4f $e4 $61 +$e4 $69 $e4 $7e $e4 $ad $e4 $d8 $e4 $ec $e4 $fd $e4 $09 $e5 $18 +$e5 $b8 $00 $b6 $00 $b7 $00 $b9 $00 $3c $bf $c2 $00 $c1 $00 $3e +$be $c0 $00 $9f $00 $42 $53 $28 $c5 $4e $44 $bb $53 $43 $28 $d7 +$54 $4e $28 $d0 $00 $49 $4e $24 $28 $dc $49 $54 $43 $4c $52 $a8 +$49 $54 $53 $45 $54 $a7 $49 $54 $54 $53 $54 $28 $dd $00 $41 $4c +$4c $9c $48 $52 $24 $28 $da $4c $45 $41 $52 $a2 $4f $4e $54 $a0 +$4f $53 $28 $cd $00 $41 $54 $41 $83 $45 $43 $88 $45 $45 $4b $28 +$d2 $45 $46 $99 $49 $4d $85 $4f $4b $45 $9b $4f $9d $00 $4c $53 +$45 $ac $4e $44 $80 $4f $52 $bc $58 $50 $28 $cc $00 $4e $ae $4f +$52 $81 $52 $45 $28 $c7 $00 $45 $54 $a5 $4f $53 $55 $42 $8d $4f +$54 $4f $89 $00 $45 $58 $24 $28 $db $00 $46 $8b $4e $43 $95 $4e +$50 $55 $54 $84 $4e $54 $28 $c4 $52 $51 $a9 $00 $43 $41 $53 $45 +$24 $28 $d9 $45 $46 $54 $24 $28 $e3 $45 $4e $28 $d4 $45 $54 $87 +$49 $53 $54 $a1 $4f $41 $44 $97 $4f $47 $28 $cb $4f $4f $50 $9e +$00 $41 $58 $28 $de $49 $44 $24 $28 $e5 $49 $4e $28 $df $00 $45 +$57 $a3 $45 $58 $54 $82 $4d $49 $aa $4f $54 $b1 $55 $4c $4c $94 +$00 $46 $46 $b5 $4e $93 $52 $bd $00 $45 $45 $4b $28 $d1 $49 $e0 +$4f $4b $45 $9a $4f $53 $28 $c8 $52 $49 $4e $54 $9f $00 $45 $41 +$44 $86 $45 $4d $91 $45 $53 $54 $4f $52 $45 $8c $45 $54 $49 $52 +$51 $8e $45 $54 $4e $4d $49 $8f $45 $54 $55 $52 $4e $90 $49 $47 +$48 $54 $24 $28 $e4 $4e $44 $28 $ca $55 $4e $8a $00 $41 $44 $44 +$28 $d3 $41 $56 $45 $98 $47 $4e $28 $c3 $49 $4e $28 $ce $50 $43 +$28 $af $51 $52 $28 $c9 $54 $45 $50 $b2 $54 $4f $50 $92 $54 $52 +$24 $28 $d5 $57 $41 $50 $a6 $00 $41 $42 $28 $ab $41 $4e $28 $cf +$48 $45 $4e $b0 $4f $ad $57 $4f $50 $49 $e1 $00 $43 $41 $53 $45 +$24 $28 $d8 $4e $54 $49 $4c $b3 $53 $52 $28 $c6 $00 $41 $4c $28 +$d6 $41 $52 $50 $54 $52 $28 $e2 $00 $41 $49 $54 $96 $48 $49 $4c +$45 $b4 $49 $44 $54 $48 $a4 $00 $ba $00 $03 $45 $e2 $e3 $03 $46 +$ef $e3 $04 $4e $52 $e4 $04 $44 $c5 $e3 $05 $49 $0f $e4 $03 $44 +$d4 $e3 $04 $52 $7e $e4 $03 $4c $2d $e4 $03 $44 $c9 $e3 $04 $47 +$ff $e3 $03 $52 $a9 $e4 $02 $49 $0a $e4 $07 $52 $85 $e4 $05 $47 +$fa $e3 $06 $52 $8c $e4 $06 $52 $92 $e4 $06 $52 $98 $e4 $03 $52 +$82 $e4 $04 $53 $ca $e4 $02 $4f $64 $e4 $04 $4e $5c $e4 $03 $49 +$0c $e4 $04 $57 $09 $e5 $04 $4c $34 $e4 $04 $53 $b2 $e4 $03 $44 +$d1 $e3 $04 $50 $70 $e4 $04 $44 $d7 $e3 $04 $43 $ae $e3 $02 $44 +$db $e3 $04 $4c $3c $e4 $05 $50 $78 $e4 $04 $43 $bc $e3 $04 $4c +$30 $e4 $05 $43 $b7 $e3 $03 $4e $4f $e4 $05 $57 $12 $e5 $03 $47 +$f7 $e3 $04 $53 $d3 $e4 $06 $42 $a0 $e3 $06 $42 $9a $e3 $03 $49 +$18 $e4 $03 $4e $56 $e4 $04 $54 $d8 $e4 $04 $45 $de $e3 $02 $54 +$e4 $e4 $02 $46 $ed $e3 $04 $53 $be $e4 $04 $54 $e0 $e4 $03 $4e +$59 $e4 $04 $53 $c6 $e4 $05 $55 $f3 $e4 $05 $57 $0d $e5 $03 $4f +$61 $e4 $01 $2b $00 $00 $01 $2d $00 $00 $01 $2a $00 $00 $01 $2f +$00 $00 $01 $5e $00 $00 $03 $41 $89 $e3 $03 $45 $e5 $e3 $02 $4f +$66 $e4 $02 $3e $7f $e3 $02 $3c $79 $e3 $01 $3e $00 $00 $01 $3d +$00 $00 $01 $3c $00 $00 $04 $53 $b6 $e4 $04 $49 $14 $e4 $04 $41 +$85 $e3 $04 $55 $f8 $e4 $04 $46 $f2 $e3 $04 $50 $74 $e4 $04 $53 +$c2 $e4 $04 $52 $a5 $e4 $04 $4c $38 $e4 $04 $45 $e8 $e3 $04 $43 +$c0 $e3 $04 $53 $ba $e4 $04 $54 $dc $e4 $04 $41 $90 $e3 $05 $50 +$69 $e4 $05 $44 $cc $e3 $05 $53 $ad $e4 $04 $4c $29 $e4 $05 $53 +$ce $e4 $04 $56 $fd $e4 $04 $41 $8c $e3 $07 $55 $ec $e4 $07 $4c +$1c $e4 $05 $43 $b2 $e3 $05 $48 $04 $e4 $05 $42 $95 $e3 $07 $42 +$a6 $e3 $04 $4d $41 $e4 $04 $4d $4a $e4 $02 $50 $6e $e4 $05 $54 +$e6 $e4 $07 $56 $01 $e5 $06 $4c $23 $e4 $07 $52 $9e $e4 $05 $4d +$45 $e4 $d6 $e6 $e7 $e6 $ee $e6 $03 $e7 $0f $e7 $1d $e7 $26 $e7 +$34 $e7 $48 $e7 $55 $e7 $66 $e7 $75 $e7 $84 $e7 $92 $e7 $a2 $e7 +$b5 $e7 $c4 $e7 $d7 $e7 $4e $45 $58 $54 $20 $77 $69 $74 $68 $6f +$75 $74 $20 $46 $4f $52 $00 $53 $79 $6e $74 $61 $78 $00 $52 $45 +$54 $55 $52 $4e $20 $77 $69 $74 $68 $6f $75 $74 $20 $47 $4f $53 +$55 $42 $00 $4f $75 $74 $20 $6f $66 $20 $44 $41 $54 $41 $00 $46 +$75 $6e $63 $74 $69 $6f $6e $20 $63 $61 $6c $6c $00 $4f $76 $65 +$72 $66 $6c $6f $77 $00 $4f $75 $74 $20 $6f $66 $20 $6d $65 $6d +$6f $72 $79 $00 $55 $6e $64 $65 $66 $69 $6e $65 $64 $20 $73 $74 +$61 $74 $65 $6d $65 $6e $74 $00 $41 $72 $72 $61 $79 $20 $62 $6f +$75 $6e $64 $73 $00 $44 $6f $75 $62 $6c $65 $20 $64 $69 $6d $65 +$6e $73 $69 $6f $6e $00 $44 $69 $76 $69 $64 $65 $20 $62 $79 $20 +$7a $65 $72 $6f $00 $49 $6c $6c $65 $67 $61 $6c $20 $64 $69 $72 +$65 $63 $74 $00 $54 $79 $70 $65 $20 $6d $69 $73 $6d $61 $74 $63 +$68 $00 $53 $74 $72 $69 $6e $67 $20 $74 $6f $6f $20 $6c $6f $6e +$67 $00 $53 $74 $72 $69 $6e $67 $20 $74 $6f $6f $20 $63 $6f $6d +$70 $6c $65 $78 $00 $43 $61 $6e $27 $74 $20 $63 $6f $6e $74 $69 +$6e $75 $65 $00 $55 $6e $64 $65 $66 $69 $6e $65 $64 $20 $66 $75 +$6e $63 $74 $69 $6f $6e $00 $4c $4f $4f $50 $20 $77 $69 $74 $68 +$6f $75 $74 $20 $44 $4f $00 $0d $0a $42 $72 $65 $61 $6b $00 $20 +$45 $72 $72 $6f $72 $00 $20 $69 $6e $20 $6c $69 $6e $65 $20 $00 +$0d $0a $52 $65 $61 $64 $79 $0d $0a $00 $20 $45 $78 $74 $72 $61 +$20 $69 $67 $6e $6f $72 $65 $64 $0d $0a $00 $20 $52 $65 $64 $6f +$20 $66 $72 $6f $6d $20 $73 $74 $61 $72 $74 $0d $0a $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$ad $e1 $ff $f0 $0c $c9 $61 $90 $06 $c9 $7b $b0 $02 $29 $5f $38 +$60 $18 $60 $8d $e0 $ff $29 $ff $60 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +EXEC +$c000 diff --git a/main.cpp b/main.cpp index bc6ecb6..de802db 100644 --- a/main.cpp +++ b/main.cpp @@ -43,6 +43,7 @@ #include "VMachine.h" #include "GraphDisp.h" #include "MemMapDev.h" +#include "ConsoleIO.h" #include "MKGenException.h" using namespace std; @@ -60,6 +61,7 @@ char diss_buf[DISS_BUF_SIZE]; // last disassembled instruction buffer char curr_buf[DISS_BUF_SIZE]; // current disassembled instruction buffer VMachine *pvm = NULL; +ConsoleIO *pconio = NULL; Regs *preg = NULL; bool ioecho = false, opbrk = false, needhelp = false; bool loadbin = false, loadhex = false, reset = false, execvm = false; @@ -224,16 +226,34 @@ void trap_signal(int signum); */ void trap_signal(int signum) { - cout << "Signal caught: " << dec << signum << endl; - if (NULL != pvm && NULL != preg) { - pvm->SetOpInterrupt(true); - opbrk = true; - } + if (NULL != pconio) { + pconio->CloseCursesScr(); + } + if (NULL != pvm && NULL != preg) { + pvm->SetOpInterrupt(true); + opbrk = true; + } + cout << "Signal caught: " << dec << signum << endl; - return; + return; } -#endif +/* + *-------------------------------------------------------------------- + * Method: reset_terminal_mode() + * Purpose: Close curses window. + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +void reset_terminal_mode() +{ + if (NULL != pconio) pconio->CloseCursesScr(); + cout << "Thank you for using VM65." << endl; +} + + +#endif // #if defined(LINUX) #if defined(WINDOWS) #include @@ -842,10 +862,18 @@ int main(int argc, char *argv[]) { #if defined(LINUX) signal(SIGINT, trap_signal); signal(SIGTERM, trap_signal); + if (atexit(reset_terminal_mode)) { + cout << "WARNING: Can't set exit function." << endl; + PressEnter2Cont(""); + } #endif #if defined(WINDOWS) SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, TRUE ); #endif + pconio = new ConsoleIO(); + if (NULL == pconio) throw MKGenException("Out of memory - ConsoleIO"); + pconio->InitCursesScr(); + pconio->CloseCursesScr(); string romfile("dummy.rom"); LoadArgs(argc, argv); if (needhelp) { CmdArgHelp(argv[0]); exit(0); } @@ -871,7 +899,7 @@ int main(int argc, char *argv[]) { if (NULL != pvm && !reset) { reset = execvm = pvm->IsAutoReset(); } } if (NULL == pvm) { - throw MKGenException("Out of memory"); + throw MKGenException("Out of memory - VMachine"); } pvm->ClearScreen(); CopyrightBanner(); @@ -899,6 +927,8 @@ int main(int argc, char *argv[]) { preg = ((step) ? RunSingleCurrInstr() : pvm->Run()); RUNSTEPS(step,nsteps,brk,preg,stct,pvm,lrts,anim,delay); } + pconio->InitCursesScr(); + pconio->CloseCursesScr(); if (step) cout << "\rExecuted " << dec << stct << ((stct == 1) ? " step." : " steps.") << " " << endl; nsteps = 0; @@ -918,6 +948,8 @@ int main(int argc, char *argv[]) { lrts = preg->LastRTS; newaddr = 0x10000; } + pconio->InitCursesScr(); + pconio->CloseCursesScr(); if (brk || opbrk || stop || lrts) { pvm->ClearScreen(); pvm->ShowIO(); @@ -1008,6 +1040,7 @@ int main(int argc, char *argv[]) { anim = !anim; cout << "Registers status animation " << ((anim) ? "enabled." : "disabled.") << endl; } else if (c == 'b') { // clear screen + pconio->CloseCursesScr(); pvm->ClearScreen(); } else if (c == 'r') { // show registers stop = true; @@ -1082,11 +1115,14 @@ int main(int argc, char *argv[]) { cout << "ERROR: Unknown command." << endl; } } + if (NULL != pconio) pconio->CloseCursesScr(); } catch (MKGenException& ex) { + if (NULL != pconio) pconio->CloseCursesScr(); cout << ex.GetCause() << endl; } catch (...) { + if (NULL != pconio) pconio->CloseCursesScr(); cout << "ERROR: Fatal." << endl; } return 0; diff --git a/makefile b/makefile index 3f37b87..1d69d3a 100644 --- a/makefile +++ b/makefile @@ -1,11 +1,14 @@ # Project: MKBasic +SDLBASE = $(SDLDIR) +SDLINCS = -I"$(SDLBASE)/include" CPP = g++ -D__DEBUG__ -DLINUX CC = gcc -D__DEBUG__ -OBJ = main.o VMachine.o MKBasic.o MKCpu.o Memory.o Display.o MKGenException.o -LINKOBJ = main.o VMachine.o MKBasic.o MKCpu.o Memory.o Display.o MKGenException.o -BIN = mkbasic -LIBS = -static-libgcc -m32 -g3 -ltermcap +OBJ = main.o VMachine.o MKCpu.o Memory.o Display.o GraphDisp.o MemMapDev.o MKGenException.o ConsoleIO.o +LINKOBJ = main.o VMachine.o MKCpu.o Memory.o Display.o GraphDisp.o MemMapDev.o MKGenException.o ConsoleIO.o +BIN = vm65 +SDLLIBS = -L/usr/local/lib -lSDL2main -lSDL2 +LIBS = -static-libgcc -m32 -g3 -ltermcap -lncurses CLIBS = -static-libgcc -m32 -g3 INCS = CXXINCS = @@ -22,22 +25,22 @@ clean: clean-custom ${RM} $(OBJ) $(BIN) bin2hex $(BIN): $(OBJ) - $(CPP) $(LINKOBJ) -o $(BIN) $(LIBS) + $(CPP) $(LINKOBJ) -o $(BIN) $(LIBS) $(SDLLIBS) main.o: main.cpp - $(CPP) -c main.cpp -o main.o $(CXXFLAGS) + $(CPP) -c main.cpp -o main.o $(CXXFLAGS) $(SDLINCS) VMachine.o: VMachine.cpp - $(CPP) -c VMachine.cpp -o VMachine.o $(CXXFLAGS) + $(CPP) -c VMachine.cpp -o VMachine.o $(CXXFLAGS) $(SDLINCS) MKBasic.o: MKBasic.cpp $(CPP) -c MKBasic.cpp -o MKBasic.o $(CXXFLAGS) MKCpu.o: MKCpu.cpp - $(CPP) -c MKCpu.cpp -o MKCpu.o $(CXXFLAGS) + $(CPP) -c MKCpu.cpp -o MKCpu.o $(CXXFLAGS) $(SDLINCS) Memory.o: Memory.cpp - $(CPP) -c Memory.cpp -o Memory.o $(CXXFLAGS) + $(CPP) -c Memory.cpp -o Memory.o $(CXXFLAGS) $(SDLINCS) Display.o: Display.cpp $(CPP) -c Display.cpp -o Display.o $(CXXFLAGS) @@ -47,3 +50,12 @@ bin2hex: bin2hex.c MKGenException.o: MKGenException.cpp $(CPP) -c MKGenException.cpp -o MKGenException.o $(CXXFLAGS) + +GraphDisp.o: GraphDisp.cpp GraphDisp.h + $(CPP) -c GraphDisp.cpp -o GraphDisp.o $(CXXFLAGS) $(SDLINCS) + +MemMapDev.o: MemMapDev.cpp MemMapDev.h + $(CPP) -c MemMapDev.cpp -o MemMapDev.o $(CXXFLAGS) $(SDLINCS) + +ConsoleIO.o: ConsoleIO.cpp ConsoleIO.h + $(CPP) -c ConsoleIO.cpp -o ConsoleIO.o $(CXXFLAGS) diff --git a/test_grtxt.bas b/test_grtxt.bas new file mode 100644 index 0000000..d1822bf --- /dev/null +++ b/test_grtxt.bas @@ -0,0 +1,20 @@ +5 PRINT:PRINT "BITMAP TEXT DEMO. PRESS [SPACE] TO QUIT...":PRINT +10 C=0:M=0:N=22:B=65506:POKE B+9,0 +12 PRINT "NORMAL MODE, CHAR BANK ";N*2048 +15 POKE B+13,N:POKE B+17,0:POKE B+18,0 +20 FOR Y=0 TO 24 +30 FOR X=0 TO 39 +40 POKE B+14,X:POKE B+15,Y +50 POKE B+16,C +60 C=C+1:IF C<256 THEN 120 +70 IF N=22 THEN N=23:GOTO 100 +80 N=22:IF M=0 THEN M=1:GOTO 100 +90 M=0 +100 POKE B+13,N:POKE B+18,M +110 Y=Y+1:X=-1:C=0 +115 IF M=0 THEN PRINT "NORMAL"; ELSE PRINT "REVERSE"; +116 PRINT " MODE, CHAR BANK ";N*2048 +120 GET K$:IF K$=" " THEN END +130 NEXT X +140 NEXT Y +150 GOTO 5