diff --git a/include/oric.a02 b/include/oric.a02 index f371370..cdfe714 100644 --- a/include/oric.a02 +++ b/include/oric.a02 @@ -12,19 +12,18 @@ SRCHI EQU $01 DSTLO EQU $02 ;Destination String Pointer (string.asm) DSTHI EQU $03 -STKSAV EQU $04 ;Stack Pointer Storage -RDSEED EQU $05 ;Pseudo-RANDOM Seed -RANDOM EQU $06 ;Pseudo-RANDOM Number Storage +RDSEED EQU $04 ;Pseudo-RANDOM Seed +RANDOM EQU $05 ;Pseudo-RANDOM Number Storage -TEMP0 EQU $07 ;Temporary Storage -TEMP1 EQU $08 -TEMP2 EQU $09 -TEMP3 EQU $0A +TEMP0 EQU $06 ;Temporary Storage +TEMP1 EQU $07 +TEMP2 EQU $08 +TEMP3 EQU $09 -BLKSLO EQU $0B ;Block Start Address -BLKSHI EQU $0C -BLKELO EQU $0D ;Block End Address -BLKEHI EQU $0E +BLKSLO EQU $0A ;Block Start Address +BLKSHI EQU $0B +BLKELO EQU $0C ;Block End Address +BLKEHI EQU $0D ;Oric-1 Memory Locations CAPLCK EQU $020C ;Caps Lock: 127=Off, 255 = On @@ -53,22 +52,20 @@ VDU EQU $F409 ;Print character in X to screen ORG $0501 ;Basic Program Start Address -BASIC: .DB $0C,$05 ;Address of Next Line - .DB $00,$00 ;Basic Line Number (0) - .DB $BF ;Token for Basic Call Command - .DB $20 ;Space - .DS "1294" ;Address of START Label - .DB $00 ;End of Line - .DB $00,$00 ;End of Program Marker +BASIC: .DC $0C,$05 ;Address of Next Line + .DC $00,$00 ;Basic Line Number (0) + .DC $BF ;Token for Basic Call Command + .DC $20 ;Space + .DC "1294" ;Address of START Label + .DC $00 ;End of Line + .DC $00,$00 ;End of Program Marker -START: TXS ;Save Stack Pointer - STX STKSAV - LDA #127 ;Set Caps Lock Off +START: LDA #127 ;Set Caps Lock Off STA CAPLCK JMP MAIN ;Execute Program ;Poll Character from Keyboard -PLKEY: INC RDSEED ;Cycle the Random Seed (if not provided by system) +PLKEY: INC RDSEED ;Cycle the Random Seed JMP GTORKB ;Call ROM Key Reading function and return ;Read Character from Console @@ -80,23 +77,23 @@ RDKEY: JSR PLKEY ;Usually calls PLKEY RTS ;Delete Previous Character -DELCHR: LDA DELKEY ;Load Delete Character +DELCHR: LDA #DELKEY ;Load Delete Character BNE PRCHR ;and Print to Screem ;Advance Cursor to Next line -NEWLIN: LDA RTNKEY ;Load Carriage Return and fall through to PRCHR +NEWLIN: LDA #$0D ;Load Carriage Return + JSR PRCHR ;and Print It + LDA #$0A ;Load Line Feed and fall through to PRCHR ;Print Character to Screen PRCHR: TAX ;Transfer Character to X Register JMP VDU ;Call ROM Print Function and Return ;Exit Program and Return to Operating System or Monitor -EXIT: LDA #255 ;Set Caps Lock On +EXIT LDA #255 ;Set Caps Lock On STA CAPLCK - LDX STKSAV ;Restore Stack Pointer - TXS - RTS ;and Return to Basic - + JMP $C003 ;BASIC Warm Start +; ;Note: The following two functions replicate calls available ;in the Apple-1 monitor and are included for test purposes ;They will likely be removed before the final release @@ -118,18 +115,3 @@ PRHEX: AND #$0F ;Strip High Nybble ADC #$06 ; Convert ':' to 'A'... PRHEXC: ADC #$30 ;Convert to ASCII Character JMP PRCHR ;Print Hex Digit and Return - - -;Functions to set String Pointers -;Used by memory, stdio, stdlin, string, and stringx libraries - -;Initialize Destination String Pointer -SETDST: STX DSTLO ;Save Destination String Pointer - STY DSTHI - RTS - -;Initialize Source String Pointer and Index -SETSRC: STX SRCLO ;Save Source String Pointer - STY SRCHI - LDY #$00 ;Initialize Index Into String - RTS diff --git a/include/oric.h02 b/include/oric.h02 index 16f27c3..0dd362d 100644 --- a/include/oric.h02 +++ b/include/oric.h02 @@ -1,6 +1,5 @@ /* C02 Standard Header for Oric-1 */ - /* System Specific ASCII Key Codes */ #define DELKEY $7F //Delete/Backspace Key #define ESCKEY $1B //Escape/Stop Key diff --git a/test/echo.c02 b/test/echo.c02 new file mode 100644 index 0000000..b6ead48 --- /dev/null +++ b/test/echo.c02 @@ -0,0 +1,22 @@ +/**************************************************** + * ECHO - Test/Demo program for C02 Standard Header * + * Echos typed keys to screen * + * RETURN/ENTER key Moves to New Line * + * BACKSPACE/DELETE key Deletes to Left * + * ESCAPE/STOP key Ends Program * + ****************************************************/ + +//Specify System Header using -H option + +char key; //Key value + +main: + while() { + key = getkey(); + select (key) { + case #DELKEY: delchr(); + case #RTNKEY: newlin(); + case #ESCKEY: goto exit; + default: prchr(key); + } + } diff --git a/test/o1.bat b/test/o1.bat new file mode 100644 index 0000000..3238c1c --- /dev/null +++ b/test/o1.bat @@ -0,0 +1,22 @@ +@ECHO OFF +REM Compile and Assemble Program for ORIC-1 +IF EXIST %1.c02 GOTO COMPILE + ECHO File %1.c02 not found + EXIT /B + +:COMPILE +ECHO Compiling File %1.c02 +..\c02.exe -h oric %1 >%1.dbg +IF ERRORLEVEL 1 EXIT /B + +ECHO Assembling File %1.asm +dasm %1.asm -f1 -o%1.obj -l%1.lst -s%1.sym +IF ERRORLEVEL 1 EXIT /B + +ECHO Building Disk Image +python ..\util\orictap.py %1 +IF ERRORLEVEL 1 EXIT /B +DEL %1.obj + +REM ECHO Starting Emulator +REM START C:\Programs\Oricutron\oricutron.exe -m1 -t%1.tap diff --git a/util/orictap.py b/util/orictap.py new file mode 100644 index 0000000..5ec65ff --- /dev/null +++ b/util/orictap.py @@ -0,0 +1,71 @@ +#Oric .TAP Converter +#Builds Oric/Atmos .TAP file from DASM -F1 file + +#DASM -F1 File two byte load address in LSB, MSB order +#followed by binary object coda + +#Oric/Atmos .TAP file has the following structure: +# $16 $16 $16 $16 Tape Synchronization Bytes +# $24 $00 $00 Header Start Bytes +# $00/$80 Program Type (BASIC/Assembly) +# $00/$80/$C7 Autostart (None/BASIC/Assembly) +# $XX $XX End Address (MSB, LSB) +# $XX $XX Start Address (MSB, LSB) +# $00 Padding Byte +# 'XXX...' File Name (up to 16 characters) +# $00 File Name Terminator +# ... Program Data + +import os +import sys + +def getArgs(): + argCount = len(sys.argv) + if argCount != 2: + print("Usage:", sys.argv[0], "objfile") + exit(2) + return sys.argv[1] + +def splitFileSpec(filePath): + fileDir, fileSpec = os.path.split(filePath) + fileName, fileExt = os.path.splitext(fileSpec) + if fileExt == '': fileExt = '.obj' + return fileDir, fileName, fileExt + +def readPrgFile(fileSpec): + with open(fileSpec, "rb") as prgFile: + prgAddr = prgFile.read(2) + prgData = prgFile.read() + address = prgAddr[0] + prgAddr[1] * 256 + return address, prgData + +def writeTapFile(dir, name, addr, data): + tapName = os.path.join(dir, name + ".tap") + size = len(data)+1 #Program Size includes trailing 0 byte + type = b'\x00' if addr == 0x0501 else b'\x80' #Program Type BASIC/Assembly + auto = b'\x00' #Autostart (None) + #auto = b'\x80' if type == b'\x00' else b'\xC7' #Autostart Flag + start = addr.to_bytes(2, byteorder='big') #Program Start Address + end = (addr+size).to_bytes(2, byteorder='big') #Program End Address + ascName = name.upper().encode('ASCII') #Program Name as ASCII bytes object + with open(tapName, "wb") as tapFile: + tapFile.write(b'\x16\x16\x16\x16') #Tape Synchronization Bytes + tapFile.write(b'\x24\x00\x00') #Header Start Byte + tapFile.write(type) #Program Type + tapFile.write(auto) #Autostart Flag + tapFile.write(end) #Program End Address + tapFile.write(start) #Program Start Address MSB + tapFile.write(b'\x00') #Padding Byte + tapFile.write(ascName) #File Name + tapFile.write(b'\x00') #String Terminator + tapFile.write(data) #Binary Program Code + tapFile.write(b'\x00') #Final Dummy Byte + return tapName + +objFile = getArgs() +fileDir, fileName, fileExt = splitFileSpec(objFile) +inName = os.path.join(fileDir, fileName + fileExt) +print("Reading file", inName) +inAddr, inData = readPrgFile(inName) +outName = writeTapFile(fileDir, fileName, inAddr, inData) +print ("Wrote file", outName)