aboutsummaryrefslogtreecommitdiff
path: root/README.md
diff options
context:
space:
mode:
authorJuan J. Martinez <jjm@usebox.net>2023-05-01 13:50:52 +0100
committerJuan J. Martinez <jjm@usebox.net>2023-05-01 13:58:09 +0100
commit8998bd04c94da08dc49ab62007da5604d53895c3 (patch)
tree43a588f7a372ce17d035536a56fd71691fa6a73f /README.md
downloadtr8vm-8998bd04c94da08dc49ab62007da5604d53895c3.tar.gz
tr8vm-8998bd04c94da08dc49ab62007da5604d53895c3.zip
Initial import
Diffstat (limited to 'README.md')
-rw-r--r--README.md389
1 files changed, 389 insertions, 0 deletions
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..8c35301
--- /dev/null
+++ b/README.md
@@ -0,0 +1,389 @@
+# TR-8
+
+**Important**: this is a work in progress with pre-alpha quality. Not all the information in this document is final, complete or even accurate.
+
+8-bit fantasy console inspired by MIPS, Z80 and 6502 real world CPUs.
+
+## Specs
+
+```
+Display: 128 x 128 pixels 16 colors (from palette of 32)
+Memory: 64K
+CPU: TR-8, 8M VM instr/sec
+Sound: TBD
+```
+
+Other features:
+
+* programable in ASM
+* TR-8 CPU
+ - 16-bit registers: stack pointer (SP) and program counter (PC)
+ - 8-bit registers: 4 general purpose registers (a, b, x, y), flags refister (F)
+* frame interrupt (60Hz) and external IO interrupt
+* port based IO
+
+Memory map:
+
+```
+0x0000
+ program (48896 bytes)
+0xbf00
+ frame buffer (16K)
+0xff00
+ frame interrupt vector
+0xff02
+ IO interrupt vector
+0xff04
+ stack (251 bytes)
+0xffff
+```
+
+## How to build
+
+It requires SDL2 and SDL_Mixer.
+
+On Linux install a C compiler and the development packages for the requirements.
+
+Example on Debian/Ubuntu using `sudo`:
+
+ sudo apt install build-essential libsdl2-dev libsdl2-image-dev libsdl2-mixer-dev
+
+Then run `make`.
+
+This will result in two binaries:
+
+ - *tr8as*: the TR8 assembler
+ - *tr8vm*: the TR8 VM that can run `tr8` files
+
+You can then compile and run the example with `make example`.
+
+## Detailed specs
+
+### Ports
+
+| Port | Type | Result |
+| --- | --- | --- |
+| 0xe0 to 0xef | write | Color select |
+| 0xf0 | read | Status of the controller 1 |
+| 0xf1 | read | Status of the controller 2 |
+
+### Controller
+
+The controller support d-pad with 4 directions, 2 action buttons, select and start.
+
+Read the port `0xf0` for the 8 1-bit flags reporting the state of the controller 1, and `0xf1` for controller 2.
+
+```
+76543210
+|||||||\ a (fire 1)
+||||||\ b (fire 2)
+|||||\ d-pad up
+||||\ d-pad down
+|||\ d-pad left
+||\ d-pad right
+|\ select
+\ start
+```
+
+### Palette
+
+Ports from `0xe0` to `0xef` can be used to select the colors to use in the 16 color palette from the 32 available.
+
+TODO: palette colours
+
+### Instructions
+
+All the instructions are 16-bit, with the exception of `JMP addr` and `CALL
+addr` that use an extra 16-bit parameter for "addr". All the instructions take
+the same time to run, and being 8 MIPS it can fit `133333` instructions in a
+frame (at 60Hz).
+
+There are no 16-bit registers, but they can be implemented with 2 registers,
+and that is supported in some addressing modes with `[r1:r2]`.
+
+For example:
+
+```asm
+ ; fill with color 15
+ ld a, 15
+ push a
+ call fill
+ pop a
+
+ ; halt the CPU
+ sif
+ halt
+
+ ;
+ ; void fill(uint8_t color)
+ ;
+ ; fill frame-buffer with a color
+ ;
+fill:
+ ; grab the color from the stack
+ ld b, [sp + 2]
+ ; 64 * 256 is 16K
+ ld y, 64
+ ; a:x is our 16-bit register
+ ld a, 0xbf
+ ld x, 0
+fill_loop:
+ ld [a : x], b
+ inc x
+ bno
+ jmp fill_loop
+ ; x overfows, so we increment a
+ ; and decrement y (one 256 block done)
+ inc a
+ dec y
+ bnz
+ jmp fill_loop
+ ret
+```
+
+Arithmetic operations on the "16-bit" can be performed easily using branching
+instructions:
+
+```asm
+ ; inc a:x
+ inc x
+ ; if x overflows we need to increase a
+ bo
+ inc a
+```
+
+#### Directives
+
+.org addr
+Set the address to that value. By default the starting address is `0x0000`.
+
+.db imm [, imm]
+Literal byte. Label can be used with `<` prefix for the low byte of the address and `>`for the high byte.
+
+.dw imm [, imm]
+Literal word.
+
+#### Load and Store
+
+LD r1, r2
+Load the value of r2 in r1.
+
+LD r1, imm
+Load the immediate value in r1.
+
+LD [r1:r2], r3
+Load the value of r3 in the memory address provided by r1:r2.
+
+LD r3, [r1:r2]
+Load into r3 the value in the memory address provided by r1:r2.
+
+LD [SP + imm], r1
+Load r1 into the stack on top address plus the immediate value.
+
+LD r1, [SP + imm]
+Load into r1 the stack value on top address plus the immediate value.
+
+#### Stack
+
+PUSH r1
+Save the value of r1 on the top of the stack.
+
+POP r1
+Restore the value of r1 by popping it from the top of the stack.
+
+PUSH F
+Save the flags in the stack.
+
+POP F
+Restore the flags from the top of the stack.
+
+XSP r1
+Exchange the high byte of the stack pointer by the value in r1.
+
+#### Logical
+
+AND r1, r2
+Logical AND between r1 and r2, storing the result in r1.
+Affected flags: ZF, SF
+
+AND r1, imm
+Logical AND between r1 and immediate value, storing the result in r1.
+Affected flags: ZF, SF
+
+OR r1, r2
+Logical OR between r1 and r2, storing the result in r1.
+Affected flags: ZF, SF
+
+OR r1, imm
+Logical OR between r1 and immediate value, storing the result in r1.
+Affected flags: ZF, SF
+
+XOR r1, r2
+Logical exclusive OR between r1 and r2, storing the result in r1.
+Affected flags: ZF, SF
+
+XOR r1, imm
+Logical exclusive OR between r1 and immediate value, storing the result in r1.
+Affected flags: ZF, SF
+
+#### Arithmetic
+
+INC r1
+Incremet r1.
+Affected flags: ZF, CF, OF, SF
+
+DEC r1
+Decrement r1.
+Affected flags: ZF, CF, OF, SF
+
+ADD r1, r2
+Add r1 and r2, storing the result in r1.
+Affected flags: ZF, CF, OF, SF
+
+ADD r1, imm
+Add r1 and the immediate value, storing the result in r1.
+Affected flags: ZF, CF, OF, SF
+
+SUB r1, r2
+Subtract r2 to r1, storing the result in r1.
+Affected flags: ZF, CF, OF, SF
+
+SUB r1, imm
+Subtract the immediate value to r1, storing the result in r1.
+Affected flags: ZF, CF, OF, SF
+
+CMP r1, r2
+Perform a SUB of r1 minus r2, without storing the result and only updating the flags.
+Affected flags: ZF, CF, OF, SF
+
+CMP r1, imm
+Perform a SUB of r1 minus the immediate value without storing the result and only updating the flags.
+Affected flags: ZF, CF, OF, SF
+
+#### Bit Operations
+
+SHL r1, n
+Shift r1 n bits to the left (0 to 7), storing the result in r1.
+Affected flags: ZF, CF, SF
+
+SHR r1, n
+Shift r1 n bits to the right (0 to 7), storing the result in r1.
+Affected flags: ZF, CF, SF
+
+ROL r1, n
+Rotate r1 n bits to the left (0 to 7), storing the result in r1.
+Affected flags: ZF, CF, SF
+
+ROR r1, n
+Rotate r1 n bits to the right (0 to 7), storing the result in r1.
+Affected flags: ZF, CF, SF
+
+BIT r1, n
+Test bit n (0 to 7) or r1, setting ZF if it is set or clearing it otherwise.
+Affected flags: ZF
+
+#### Jump and Call
+
+JMP addr
+Set the PC to the 16-bit address.
+
+CALL addr
+Store the next PC in the stack (16-bit address) and sets te PC to the 16-bit address.
+
+CALL [r1:r2]
+Store the next PC in the stack (16-bit address) and sets te PC to the 16-bit address provided by r1:r2.
+
+RET
+Return from a call by setting PC to the top 16-bit value popped from the stack.
+
+#### Branching
+
+BZ inst
+Branch if Zero, will skip the next instruction if ZF is not set.
+Affected flags: BF
+
+BNZ inst
+Branch if not Zero, will skip the next instruction if ZF flag is set.
+Affected flags: BF
+
+BC inst
+Branch if Carry, will skip the next instruction if CF flag is not set.
+Affected flags: BF
+
+BNC inst
+Branch if not Carry, will skip the next instruction if CF flag is set.
+Affected flags: BF
+
+BO inst
+Branch if Overflow, will skip the next instruction if OF flag is not set.
+Affected flags: BF
+
+BNO inst
+Branch if not Overflow, will skip the next instruction if OF flag is set.
+Affected flags: BF
+
+BS inst
+Branch if Sign, will skip the next instruction if SF flag is not set.
+Affected flags: BF
+
+BNS inst
+Branch if not Sign, will skip the next instruction if SF flag is set.
+Affected flags: BF
+
+BI inst
+Branch if Interrupt, will skip the next instruction if IF flag is not set.
+Affected flags: BF
+
+BNI inst
+Branch if not Interrupt, will skip the next instruction if IF flag is set.
+Affected flags: BF
+
+#### IO, flags and Misc
+
+HALT
+Stop the execution until there is frame interrupt. If the interruption flag is set, this will hang the CPU.
+
+PORT r1, r2
+Write the value of r2 in the port number provided by r1. If there is an output, the value will be stored in r1.
+
+NOP
+No instruction has no effect.
+
+SIF
+Set IF, disabling the interrupt.
+Affected flags: IF
+
+CIF
+Clear IF, enabling the interrupt. If called in an interrupt handler, it won't have effect. Use IRET instead to return from the interrupt to unset IF.
+Affected flags: IF
+
+CCF
+Clear carry flag.
+Affected flags: CF
+
+SCF
+Set carry flag.
+Affected flags: CF
+
+COF
+Clear overflow flag.
+Affected flags: OF
+
+IRET
+Return from an interupt handler by setting PC to the top 16-bit value popped from the stack. It enables interrupts by clearing the interrupt flag.
+Affected flags: IF
+
+### TR8 file format
+
+It is a binary file to be run on the TR-8.
+
+It doesn't have a header and it will be loaded at `0x0000` address. The execution will start on that address with interruptions disabled (interruption flag set).
+
+See the memory map for further information.
+
+## Author and Licence
+
+This was made by [Juan J. Martinez](https://www.usebox.net/jjm/about/me/).
+
+The code is MIT licensed.
+