Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

LEN function, FONT statement - loading custom fonts! (see docs)

  • Loading branch information...
commit f111b8d68f5bb67d6da3f2ac238e677739955219 1 parent b3bb1a3
@M4v3R authored
View
28 README.md
@@ -9,10 +9,11 @@ Compiler structure and engine is heavily inspired by [Let's Build a Compiler, by
* Boolean operators: & ~ !
* Bit shifts: << >>
* Relational operators: == <> < > <= >=
+* Loading custom fonts
* Control structures: IF, LOOP
* Variables (both integer and string)
-* Statements: CLS, LOCATE, PRINT, COLOR, KEY, INPUT, POKE, GOTO, RND
-* Functions: STR, CHR, VAL, PEEK, SQR
+* Statements: CLS, LOCATE, PRINT, COLOR, KEY, INPUT, POKE, GOTO, RND, FONT
+* Functions: STR, CHR, VAL, LEN, PEEK, SQR
## How the language looks like
@@ -177,6 +178,17 @@ Number = VAL(expression)
Returns an integer representation of a number in string variable (e.g. input from user)
+### LEN
+
+Usage:
+
+```
+DIM Length
+Length = LEN(expression)
+```
+
+Returns length (how many letters) of a string.
+
### INPUT
Usage:
@@ -250,6 +262,18 @@ Result = SQR(expression)
Computes square root of _expression_.
+### FONT
+
+Usage:
+
+```
+FONT "file.txt"
+```
+
+Loads custom font from text file and replaces current terminal font with it. Font file can specify only selected characters.
+For a sample font file please refer to _fonts/box.txt_ file. Every letter in font file starts with letter ascii code, and then 8 lines 4 character each follow,
+where dot (.) is an empty space and capital o (O) is a solid "pixel".
+
### END
Program MUST end with an ```END``` statement.
View
59 asm.go
@@ -264,7 +264,7 @@ func Poke() {
func PutChar() {
SkipWhite()
- if (Look == '"') {
+ if Look == '"' {
GetChar()
EmitLine(fmt.Sprintf("SET [0x8000+X], %d", Look))
GetChar()
@@ -281,6 +281,16 @@ func PutChar() {
EmitLine("AND X, 0x1ff")
}
+func Font() {
+ SkipWhite()
+ if Look == '"' {
+ Next()
+ LoadFont(Value)
+ Token = '$'
+ Next()
+ }
+}
+
func Goto() {
Next()
Token = '$'
@@ -292,6 +302,53 @@ func Input() {
Call("input")
}
+func LoadFont(filename string) {
+ var error error
+ var file *os.File
+ var charCode = 0
+ var charLine uint8 = 0
+ var charWord1 uint32 = 0
+ var charWord2 uint32 = 0
+
+ EmitLine(fmt.Sprintf("; loading font: %s", filename))
+ file, error = os.Open(filename)
+ if error != nil {
+ Error(fmt.Sprintf("Couldn't open '%s' font file!", filename))
+ return
+ }
+ reader := bufio.NewReader(file)
+ for {
+ line, _, error := reader.ReadLine()
+ if error != nil {
+ break
+ }
+ if len(line) < 4 {
+ charCode, _ = strconv.Atoi(string(line))
+ charWord1 = 0
+ charWord2 = 0
+ charLine = 0
+ } else {
+ if line[0] == 'O' {
+ charWord1 = charWord1 | (1 << (charLine + 8))
+ }
+ if line[1] == 'O' {
+ charWord1 = charWord1 | (1 << charLine)
+ }
+ if line[2] == 'O' {
+ charWord2 = charWord2 | (1 << (charLine + 8))
+ }
+ if line[3] == 'O' {
+ charWord2 = charWord2 | (1 << charLine)
+ }
+ charLine++
+ if (charLine == 8) {
+ EmitLine(fmt.Sprintf("SET [%#x], %#x", 0x8180 + charCode * 2, charWord1))
+ EmitLine(fmt.Sprintf("SET [%#x], %#x", 0x8181 + charCode * 2, charWord2))
+ }
+ }
+ }
+}
+
func Lib() {
var error error
var file *os.File
View
BIN  binaries/font.bin
Binary file not shown
View
27 fonts/box.txt
@@ -0,0 +1,27 @@
+6
+O.O.
+O.O.
+O.O.
+..O.
+OOO.
+....
+....
+....
+7
+....
+....
+OOO.
+..O.
+O.O.
+O.O.
+O.O.
+O.O.
+15
+O.O.
+O.O.
+O.O.
+O.O.
+O.O.
+O.O.
+O.O.
+O.O.
View
6 functions.go
@@ -57,3 +57,9 @@ func FuncSqr() {
Call("sqrt")
}
+func FuncLen() {
+ Next()
+ MatchString("(")
+ BoolExpression()
+ Call("strlen")
+}
View
2  lib.dasm
@@ -23,7 +23,7 @@
SET B, A
SET A, 0
:strlen1
- IFN [B], 0 ; if character is 00 - end of string
+ IFE [B], 0 ; if character is 00 - end of string
SET PC, POP ; end function
ADD A, 1 ; increment char count
ADD B, 1 ; increment char address
View
416 output/font.s
@@ -0,0 +1,416 @@
+ ADD PC, 3
+ :rnd1
+ DAT 0x6769
+ :rnd2
+ DAT 0x1250
+ :timer
+ DAT 0
+ SET PUSH, X
+ SET PUSH, Y
+ SET PUSH, Z
+ SET PUSH, I
+ SET PUSH, J
+ SET A, SP
+ SET PUSH, A
+ SET Y, 0x7000
+ SET Z, 0x9000
+ SUB SP, 3 ; Alloc space on stack
+ ADD PC, 20
+ :c0 DAT "Hello from 0xBASIC!", 0
+ SET A, c0
+ BOR A, 0x8000
+ SET [0xfffe], A
+ SET A, 0x20
+ SET [0xfffd], A
+ SET A, 0x0
+ SET [0xffff], A
+ SET A, 0xe
+ SET Y, 0
+ SHL A, 12
+ BOR Y, A
+ SET A, 0x0
+ SHL A, 8
+ BOR Y, A
+ ; loading font: fonts/box.txt
+ SET [0x818c], 0x1710
+ SET [0x818d], 0x1f00
+ SET [0x818e], 0xf404
+ SET [0x818f], 0xfc00
+ SET [0x819e], 0xff00
+ SET [0x819f], 0xff00
+ SET A, 0x9
+ SET [0x8000+X], A
+ BOR [0x8000+X], Y
+ ADD X, 1
+ AND X, 0x1ff
+ :l0
+ SET A, [0xffff]
+ SET PUSH, A
+ SET A, 0x1e
+ SET B, POP
+ SET C, 1
+ IFG A, B
+ SET C, 0
+ IFN C, 0
+ SET PC, l1
+ SET A, 0xd
+ SET [0x8000+X], A
+ BOR [0x8000+X], Y
+ ADD X, 1
+ AND X, 0x1ff
+ SET A, [0xffff]
+ SET PUSH, A
+ SET A, 0x1
+ ADD A, POP
+ SET [0xffff], A
+ SET PC, l0
+ :l1
+ SET A, 0x7
+ SET [0x8000+X], A
+ BOR [0x8000+X], Y
+ ADD X, 1
+ AND X, 0x1ff
+ SET A, 0xf
+ SET [0x8000+X], A
+ BOR [0x8000+X], Y
+ ADD X, 1
+ AND X, 0x1ff
+ SET A, 0x2
+ SUB A, 1
+ SET PUSH, 0x20
+ MUL A, POP
+ SET X, A
+ SET A, 0x20
+ SUB A, 1
+ ADD X, A
+ SET A, 0xf
+ SET [0x8000+X], A
+ BOR [0x8000+X], Y
+ ADD X, 1
+ AND X, 0x1ff
+ SET A, 0x0
+ SET [0xffff], A
+ SET A, 0x8
+ SET [0x8000+X], A
+ BOR [0x8000+X], Y
+ ADD X, 1
+ AND X, 0x1ff
+ :l2
+ SET A, [0xffff]
+ SET PUSH, A
+ SET A, 0x1e
+ SET B, POP
+ SET C, 1
+ IFG A, B
+ SET C, 0
+ IFN C, 0
+ SET PC, l3
+ SET A, 0xd
+ SET [0x8000+X], A
+ BOR [0x8000+X], Y
+ ADD X, 1
+ AND X, 0x1ff
+ SET A, [0xffff]
+ SET PUSH, A
+ SET A, 0x1
+ ADD A, POP
+ SET [0xffff], A
+ SET PC, l2
+ :l3
+ SET A, 0x6
+ SET [0x8000+X], A
+ BOR [0x8000+X], Y
+ ADD X, 1
+ AND X, 0x1ff
+ SET A, 0x2
+ SUB A, 1
+ SET PUSH, 0x20
+ MUL A, POP
+ SET X, A
+ SET A, [0xfffd]
+ SET PUSH, A
+ SET A, 0x2
+ SET B, POP
+ DIV B, A
+ SET A, B
+ SET PUSH, A
+ SET A, [0xfffe]
+ JSR strlen
+ SET PUSH, A
+ SET A, 0x2
+ SET B, POP
+ DIV B, A
+ SET A, B
+ SUB A, POP
+ SET PUSH, A
+ SET A, 0
+ SUB A, POP
+ SUB A, 1
+ ADD X, A
+ SET A, 0xf
+ SET Y, 0
+ SHL A, 12
+ BOR Y, A
+ SET A, 0x0
+ SHL A, 8
+ BOR Y, A
+ SET A, [0xfffe]
+ JSR print
+ JSR printnl
+ SET J, POP
+ SET I, POP
+ SET Z, POP
+ SET Y, POP
+ SET X, POP
+ SET A, POP
+ SET SP, A
+ SET PC, end
+
+ ; lib.dasm - compiler library
+ ; get key press
+ ; also increments timer (for randomization)
+ ; uses Z register as pointer to keyboard buffer
+ ; returns the key code in A
+ :getkey
+ ADD [timer], 1
+ IFE [Z], 0
+ SET PC, POP
+ SET A, [Z]
+ SET [Z], 0
+ ADD Z, 1
+ AND Z, 0x900f ; the buffer is 16 words long
+ MUL [rnd1], [timer]
+ ADD [rnd2], O
+ SET PC, POP
+
+ ; get string length
+ ; A - string address in memory, with highest bit set
+ ; to signal string variable type
+ :strlen
+ IFG 0xF000, A ; get rid of highest bit, unless it's a stack address
+ AND A, 0x7fff
+ SET B, A
+ SET A, 0
+ :strlen1
+ IFE [B], 0 ; if character is 00 - end of string
+ SET PC, POP ; end function
+ ADD A, 1 ; increment char count
+ ADD B, 1 ; increment char address
+ SET PC, strlen1
+
+ ; prints a single character on the screen
+ ; A - character code
+ ; X - location on the terminal
+ ; Y - color/style mask
+ :printchar
+ SET [0x8000+X], A ; put character to video memory + current location
+ BOR [0x8000+X], Y ; apply color/style
+ ADD X, 1
+ IFG X, 0x1ff ; end of terminal - go back to first row and column
+ SET X, 0
+ SET PC, POP
+
+ ; prints an integer on the screen, converting it to string (itoa)
+ ; A - number to print
+ :printint
+ SET I, 0
+ :printint1
+ SET B, A
+ MOD A, 0xa
+ ADD A, 0x30
+ SET PUSH, A
+ SET A, B
+ DIV A, 0xa
+ ADD I, 1
+ IFN A, 0
+ SET PC, printint1
+ :printint2
+ SET A, POP
+ JSR printchar
+ SUB I, 1
+ IFN I, 0
+ SET PC, printint2
+ SET A, POP
+ SET PC, POP
+
+ ; prints a string on the screen
+ ; A - address of 0 terminated string
+ :printstr
+ IFG 0xF000, A ; see strlen function above
+ AND A, 0x7fff
+ SET I, A
+ :printstr1
+ IFE [I], 0
+ SET PC, POP
+ SET A, [I]
+ JSR printchar
+ ADD I, 1
+ SET PC, printstr1
+
+ ; sets location register X to point at new line
+ :printnl
+ SHR X, 5 ; shifting 5 bits to the right means divide by 32 - terminal width
+ ADD X, 1 ; next row
+ SHL X, 5 ; multiply by 32 to get address of next row
+ SET PC, POP
+
+ ; general purpose print function
+ ; determines which data type is being print and calls specific functions
+ ; A - address of data to be printed
+ :print
+ SET B, A
+ SHR B, 15 ; get the highest bit
+ IFE B, 0 ; if it's 0 - we have a integer
+ JSR printint
+ IFE B, 1 ; if it's 1 - we have a string
+ JSR printstr
+ SET PC, POP
+
+ ; wait for user input followed by Enter key, stores it on the stack
+ ; returns pointer to the string in A
+ :input
+ SET C, SP
+ SET PUSH, 0x0
+ SET I, SP
+ SUB I, 1
+ :input1
+ SET A, 0
+ JSR getkey
+ IFE A, 0
+ SET PC, input1
+ IFE A, 0xa
+ SET PC, input2
+ IFE A, 0x8
+ SET PC, inputbsp
+ SET PUSH, A
+ JSR printchar
+ SET PC, input1
+ :inputbsp
+ SET POP, 0
+ SUB X, 1
+ SET [0x8000+X], 0
+ BOR [0x8000+X], Y
+ SET PC, input1
+ :input2
+ SET B, SP
+ SET J, B
+ :input3
+ SET A, [B]
+ SET [B], [I]
+ SET [I], A
+ ADD B, 1
+ SUB I, 1
+ IFG B, I
+ SET PC, input4
+ SET PC, input3
+ :input4
+ SET A, J
+ BOR A, 0x8000
+ SET PC, [C]
+
+ ; compare two strings to see if they're equal
+ :comparestr
+ SET I, POP
+ ADD I, 2
+ SET PUSH, I
+ IFG 0xF000, A ; see strlen function
+ AND A, 0x7fff
+ IFG 0xF000, B
+ AND B, 0x7fff
+ SET I, 0
+ SET C, 0
+ :comparestr1
+ IFN [A], [B]
+ SET PC, comparestr2
+ IFN [A], 0
+ IFE [B], 0
+ SET PC, POP
+ ADD A, 1
+ ADD B, 1
+ SET PC, comparestr1
+ :comparestr2
+ SET C, 1
+ SET PC, POP
+
+ ; convert string representation of a number to an integer
+ ; A - address of the string
+ ; returns resulting integer in A
+ :atoi
+ SET C, 0
+ IFG 0xF000, A ; see strlen function
+ AND A, 0x7fff
+ IFE [A], 0
+ SET PC, atoi2
+ :atoi1
+ IFG [A], 47
+ IFG [A], 57
+ SET PC, atoi2
+ MUL C, 10
+ SET B, [A]
+ SUB B, 48
+ ADD C, B
+ ADD A, 1
+ IFE [A], 0
+ SET PC, atoi2
+ SET PC, atoi1
+ :atoi2
+ SET A, C
+ SET PC, POP
+
+ ; compute square root of a number
+ ; A - input number (16-bit integer)
+ ; returns the result (integer) in A
+ ; author: Mrrl (on the 0x10cforum.com)
+ :sqrt
+ SET B, 1
+ SET I, A
+ IFG 0x100, A
+ ADD PC, 2
+ SHR A, 8
+ SET B, 0x10
+ IFG 0x10, A
+ ADD PC, 2
+ SHR A, 4
+ SHL B, 2
+ ADD A, 4
+ MUL B, A
+ SHR B, 2
+ SET A, I
+ DIV A, B
+ ADD B, A
+ SHR B, 1
+ SET A, I
+ DIV A, B
+ ADD B, A
+ SHR B, 1
+ SET A, I
+ DIV A, B
+ ADD A, B
+ SHR A, 1
+ SET B, A
+ MUL B, A
+ IFG B, I
+ SUB A, 1
+ SET PC, POP
+
+ ; get a pseudo-random number
+ ; returns the number in A
+ ; author: Entroper (github.com/Entroper)
+ :rand
+ SET B, [rnd1]
+ SET A, [rnd2]
+ MUL [rnd1], 0x660D
+ SET C, O
+ MUL A, 0x660D
+ ADD A, C
+ MUL B, 0x0019
+ ADD A, B
+ ADD [rnd1], 1
+ ADD A, O
+ SET [rnd2], A
+ SET PC, POP
+
+ ; end of program
+ ; infinite loop
+ :end
+ SET PC, end
View
11 parse.go
@@ -16,8 +16,8 @@ import (
var data *os.File
var Look, Prev byte
-var Keywords = []string { "IF", "ELSE", "LOOP", "END", "DIM", "CLS", "PRINT", "LOCATE", "REM", "COLOR", "POKE", "PUTCHAR", "GOTO" }
-var Tokens = []byte { 'x', 'i', 'l', 'w', 'e', 'd', 'c', 'p', 'o', 'r', 'k', 'q', 'u', 'g', 'n' }
+var Keywords = []string { "IF", "ELSE", "LOOP", "END", "DIM", "CLS", "PRINT", "LOCATE", "REM", "COLOR", "POKE", "PUTCHAR", "GOTO", "FONT" }
+var Tokens = []byte { 'x', 'i', 'l', 'w', 'e', 'd', 'c', 'p', 'o', 'r', 'k', 'q', 'u', 'g', 'f' }
var Token byte
var Value string
var LabelCount = 0
@@ -458,6 +458,8 @@ func Factor() {
FuncChr()
} else if Value == "VAL" {
FuncVal()
+ } else if Value == "LEN" {
+ FuncLen()
} else if Value == "PEEK" {
FuncPeek()
} else if Value == "RND" {
@@ -668,11 +670,10 @@ func Block() {
Poke()
case 'u':
PutChar()
+ case 'f':
+ Font()
case 'g':
Goto()
- case 'n':
- Rnd()
-
default:
Assignment()
}
View
43 sample/font.bas
@@ -0,0 +1,43 @@
+DIM I, Hello, TermWidth
+
+REM This example requires an emulator that supports custom fonts!
+REM Check http://0x10co.de for one that does.
+
+REM Set up variables and colors
+Hello = "Hello from 0xBASIC!"
+TermWidth = 32
+I = 0
+COLOR 14, 0
+
+REM Load font from file
+FONT "fonts/box.txt"
+
+REM Top row
+PUTCHAR 9
+LOOP WHILE I < 30
+PUTCHAR 13
+I = I + 1
+END LOOP
+PUTCHAR 7
+
+REM Middle row
+PUTCHAR 15
+LOCATE 2, 32
+PUTCHAR 15
+
+REM bottom row
+I = 0
+PUTCHAR 8
+LOOP WHILE I < 30
+PUTCHAR 13
+I = I + 1
+END LOOP
+PUTCHAR 6
+
+REM Print text in the middle of the second line
+LOCATE 2, TermWidth / 2 - LEN(Hello) / 2
+COLOR 15, 0
+PRINT Hello
+
+END
+
Please sign in to comment.
Something went wrong with that request. Please try again.