(notes) - Remove notes from this branch, since they moved to their own

This commit is contained in:
n loewen 2023-09-10 21:28:01 -07:00
parent b0996d30c3
commit 93f88560a2
13 changed files with 0 additions and 843 deletions

View File

@ -1,31 +0,0 @@
# Dev notes — 2023-08-05
- [ ] consider refactoring assembler to do something more like 'tokenize, then call helper functons'
- [ ] consider an extended system:
- add a byte in the ~zero-page to act as a flag for display mode
- 0 = 1 byte per pixel (default)
- 1 = 1 bit per pixel
- add another 16 ops (or fewer)
- rotate left / right (or shift?)
- AND
- OR
- more flags?
- another register?
- would require several new ops
- add binary input/output to assembler
- consider gamepad vs. hex keypad
- stick with hex
- but permit gamepad since that's a subset (NES layout = 8 bits/bytes, depending on mode)
- look at how uxn does it?
- [ ] rewrite to call things 'opcodes' and 'operands'
- add bank switching for higher 128 bytes
- add a flag in the ~zero-page
- try writing:
- a 'greater than' routine
- [x] make coding forms!

View File

@ -1,82 +0,0 @@
# Dev notes — 2023-08-07
## Carry vs overflow
[Understanding the difference between overflow and carry flags](https://stackoverflow.com/questions/69124873/understanding-the-difference-between-overflow-and-carry-flags)
> Carry indicates the result isn't mathematically correct when interpreted as unsigned, overflow indicates the result isn't mathematically correct when interpreted as signed.
> - 1111 + 0001 = 0000 should set carry (15 + 1 = 0 is false) and clear overflow (-1 + 1 = 0 is true).
> - 0111 + 0010 = 1001 should clear carry (7 + 2 = 9 is true) and set overflow (7 + 2 = -7 is false).
> - 1001 + 1001 = 0010 should set both (9 + 9 = 2 and -7 + -7 = 2 are both false).
so <mark>carry is unsigned</mark>
and <mark>overflow is signed</mark>
(which is what i've got, good)
## add more flags + change flag ops
### flags register
- [ ] Replace the current 'Carry Flag' with a Flags Register.
Here's a sketch for the bit pattern:
```
hi bit
0
0
0
0
0 ? negative
0 ? zero
0 overflow
0 carry
lo bit
```
cf. 6502:
- NV-BDIZC
- 7: Negative, 6: Overflow, 5: none, 4: Break, 3: Decimal, 2: Interrupt disable, 1: Zero, 0: Carry
### flag opcodes
- [ ] replace `CHP` and `CFC` with `FHP` and `FTG`
- `FHP n`: hop if flag _n_ is set
- eg: `FHP 0` = hop if carry flag set
- eg: `FHP 1` = hop if overflow flag set
- to keep it simple, we're just giving each flag a number, not fussing with bitmasking or anything
- `FTG n`: toggle flag _n_ on/off
- eg: if Carry is on, `FTG 0` turns it off
- eg: if Overflow is off, `FTG 1` turns it on
`FHP` and `FTG` can be combined to create `set flag` and `unset flag` routines:
```
@set_carry:
FHP 0
FTG 0
```
If Carry is on when this is called, then `FTG` is skipped and Carry remains set. Otherwise, `FTG` sets carry.
```
; call with a return address stored at $01
@unset_carry:
FHP 0 ; 1
FHP 0 ; 2
FTG 0 ; 3
JMP ($01) ; jump back to caller
```
If Carry is on when this is called, then the execution is: 1, 3, and Carry is turned off.
If Carry is off, then the execution is: 1, 2, (hop over 3; Carry is still off), jump back to caller.
## Think about a subroutine stack?
Maybe?

View File

@ -1,81 +0,0 @@
# Dev notes — 2023-08-07
## Keypad
An actual hexadecimal layout:
```
0 1 2 3
4 5 6 7
8 9 A B
C D E F
```
Another:
```
1 2 3 A
4 5 6 B
7 8 9 C
0 F E D
```
The conventional layout for cheap hardware:
```
1 2 3 A
4 5 6 B
7 8 9 C
* 0 # D
```
Kim-1:
```
GO ST RS
AD DA PC +
C D E F
8 9 A B
4 5 6 7
0 1 2 3
```
COSMAC VIP/CHIP-8:
```
1 2 3 C
4 5 6 D
7 8 9 E
A 0 B F
```
CHIP-8 to QWERTY mapping:
```
1 2 3 4
Q W E R
A S D F
Z X C V
```
## Turtle graphics
- yesterday Elizabeth had the great idea to create a turtle robot to go with the paper computer
- [ ] a minimal LOGO would be a fantastic (if challenging) program to write for the computer
- it could use the hex keypad:
- using CHIP-8 layout...
- A key: mode toggle
- mode 1: numeric
- mode 2: commands (tokens?)... something like this:
- `F` - mode toggle
- `2` - forward
- `4` - left
- `6` - right
- `0` - reverse
- `5` - turn
- `1` - pen up
- `C` - pen down
## Dot-matrix display
- [ ] Maybe try 5x5, like the micro:bit?

View File

@ -1,32 +0,0 @@
# Dev notes — 2023-08-10
- [x] Name it "Cardiograph"
- homage to CARDIAC
- (and cardboard)
- and the special feature is that unlike other paper computers, this one has a graphical display
- art note: "performing computation"
## Keypad (and memory map)
- [ ] Copy the CHIP-8 approach: one memory location that stores the current key pressed
- (Only one key can be pressed at a time)
- And then do a bitmask-y thing for the secret advanced mode, to add the ability to detect multiple simultaneous keypresses
## Display (and memory map)
- Move display to $10?
- Then $00 could contain a jump to the start of code, and we wouldn't have this strange "IP doesn't start at 0" situation
- But, this might feel more complicated, and it would make working with the display a little less elegant...
- C64 has random stuff at $0000
- How does the C64's PC get initialized ??
## (Moved from readme:) Nice features that didn't fit
- Hop `IF<` and hop `IF>`
- `MUL` and `DIV`
- Rotates and shifts
## (Moved from readme:) Possible features, maybe someday
- Timer (for a version in software/electronic-hardware)

View File

@ -1,60 +0,0 @@
# Dev notes — 2023-08-12
Brainstorming/sketching around subroutines with a return stack...
; need an instruction for IP → A i guess?
; ideally…
; but a jump table would work
; put that at beginning of the code
; then store numbers for subroutine labels in a designated memory slot
lda $1
sto $19 ; contains ID # for the next fn to jump to
@jump_table
hop $1
jmp @jt2
jmp @example_computation
@jt2
hop $2
; jmp @jt3
nop
; etc …
jmp @end
@example_computation
lda 5
sto $20
lda 3
sto $21
; $19 still has the # for this routine
; but lets pretend it doesnt and demonstrate updating it
lda $1
sto $19
jmp @greater?
; call with numbers to test in $20 and $21
; result is stored in acc
@greater?
; lda ($20)
; sub ($21)
; todo…
; wouldnt it be great to have a “hop if neg” op…
; do we have to just subtract numbers until we get 0?
; no!
; heres an approach thats at least better than that
lda ($21)
sto $22 ; stash
@loop
lda ($21)
sub $1
sto $22 ; stash
sub ($20)
hop $0
jmp @loop
sto $1
jmp $jmp_table
; ok this isnt quite it… we also need to chexk if we hit 0 by just deceementinf and if so retuen 0
jmp @jump_table

View File

@ -1,52 +0,0 @@
# Dev notes — 2023-08-15
## Goals for today
- [x] Review planned changes to simulator
- [x] 'opcodes' and 'operands'
- [x] fix $00 contains $20 bug
- [x] Review planned changes to the system
- [x] CHP, CFC -> FHP, FTG -- dev note 2023-08-07
- [/] bank-switching flag in 0 page
- added notes below, but decided to leave implementation for another day
- [x] ? 5x5 display
- [/] Implement any changes necessary for writing a program?
- [-] Write a program
- [-] LOGO turtle on 5x5?
## Overflow flag
Ken Shirriff, [The 6502 overflow flag explained mathematically](https://www.righto.com/2012/12/the-6502-overflow-flag-explained.html):
> A common definition of overflow is `V = C6 xor C7`. That is, overflow happens if the carry into bit 7 is different from the carry out.
## Bank switching
### Planned memory map
- `00-0F` - display (4x4)
- `10-1F` - keypad? (details TBD)
- `20 ` - pointer to display memory
- `21 ` - pointer to keypad memory
- `22 ` - pointer to memory bank
- `23-2F` - reserved for future use / variable storage
- `30 ` - initial value for IP
- `30-80` - free
- `80-FF` - free, can be bank-switched
## Looping using an interval timer
const loop = setInterval(async () => {
step = step + 1;
// Temporary limit as a lazy way to halt infinite loops:
if (CYCLE_LIMIT && (step > CYCLE_LIMIT)) {
console.log('SIMULATION HALTING - reached cycle limit');
clearInterval(loop);
}
if (!CPU.running) clearInterval(loop);
if (CPU.IP >= CPU.memory.length) clearInterval(loop);
stepCPU();
await logCPUState(debug);
}, frameRate);

View File

@ -1,24 +0,0 @@
# Dev notes — 2023-08-16
## Goals for today
- [x] Finish implementing *ADDR
- [x] Rename =constants to #constants
- [ ] ? Bank switching
- [>] Notes re: ROM and/or tape loader
- [x] CPU updates
- [x] Rename to CPU
- [x] Implement single-stepping
- [x] Implement keypad input
- [-] Look at KIM-1 and VIP buttons for memory editing
- [x] Rename to 'Cardiograph Mark I' (a 'Harvard Mark I' reference, plus a dumb drawing joke)
- Programming ideas:
- Draw dot at (x, y)
- Move dot around display using keypad
- simple LOGO
## Misc. earlier notes
- make sth that can run on phone!
- ? rename repository

View File

@ -1,16 +0,0 @@
# Dev notes — 2023-08-17
## Goals for today
- [ ] *ADDR - Add relative offsets - `*ADDR +1`, `$ADDR -2`
- [ ] ? Add keypad visualization to simulator
1. Display qwerty-to-VIP mapping for reference
2. Highlight the most recent keypress on there
- [ ] Notes re: ROM and/or tape loader
- Programming ideas:
- Keypad display
1. Light pixel corresponding to most recent keypress
2. Display character corresponging to most recent keypress
- Draw dot at (x, y)
- Move dot around display using keypad

View File

@ -1,77 +0,0 @@
# Dev notes - 2023-08-21
## Goals for today
- graphic design
- [x] graphics: 80 col card template
- see below
- printing
- [x] print: paper tape template
- [x] print: colour coding forms
- [x] print: 80 col card template
- [ ] see code/design commentary below...
- (consider python (microbit) version of simulator)
- maybe ask for e's input
## Memory map re-think
### CPU start-up
When starting up, the CPU executes a `JMP $FF`.
Put differently: it starts executing instructions at the address contained in `$FF`.
### Cardiograph memory map
```
00-19 - display (5x5)
1A - pointer to display memory
1B - keypad: value of latest key pressed
1C - reserved for future use (bank switching flag)
1D-FE - free
```
## References re: where do CPU instruction pointers start, and how are they set?
- ["Memory Map Requirements", in *6502 PRIMER: Building your own 6502 computer*](http://wilsonminesco.com/6502primer/MemMapReqs.html)
- "Reset (RST): When the 6502's RST input gets pulled low and then brought back high, the 6502 starts its reset process, and gets the address to start executing program instructions from $FFFC-FFFD. Notice it does not start executing at address $FFFC, but reads it to get the beginning address of the routine where it should start executing. That routine will normally have to be in ROM."
- [What address does the x86 begin executing at?](https://stackoverflow.com/questions/4004493/what-address-does-the-x86-begin-executing-at)
- "The `cs` (code selector) register is set to `0xffff` and `ip` (instruction pointer) is set to `0x0000`."
- [Why is the first BIOS instruction located at 0xFFFFFFF0 ("top" of RAM)?](https://superuser.com/questions/988473/why-is-the-first-bios-instruction-located-at-0xfffffff0-top-of-ram) (x86)
## Imported notes from earlier
### 2023-08-18 cardiograph loose thoughts
- use binary encoded punch cards for cardiog progs in machine code
- try making a microbit based emulator
- (microbit + hex keypad)
- (machine code monitor like VIP…)
- (+ tape input??)
- a4 template with full size 80 col card
- snake
- [/] add simulator todo: pass asm line thru to cpu to print when debugging
- asm: create a second array that stores every line with code (nor blank or comment only lines) + its line number
- cpu: accept an optional debugging array, print line # and statement
- readme:
- [x] readme: rename (or split up?) mem map / peripherals section
- [x] ? readme: put 2 keypad charts side by side (they would fit on my phone)
- [/] see paper notes on mem map
## 2023-08-19
[/] reconsider ISA order in light of supercat comment here
- [Why didn't the 6503 have increment/decrement opcodes for A?](https://retrocomputing.stackexchange.com/questions/13023/why-didnt-the-6502-have-increment-decrement-opcodes-for-a)
- [/] look at use of `*` or `.` in assembly
- [What does "jmp *" mean in 6502 assembly?](https://retrocomputing.stackexchange.com/questions/7998/what-does-jmp-mean-in-6502-assembly)
## 2023-07-17 - cardiograph - worksheet for hand-assembling code… + other docs
- [ ] docs/graphics: machine code quick ref (ops + short explanations + mnems)
- [ ] docs/graphics: assembly quick ref (as above, plus assembler-specific syntax like constants)
- [ ] docs/graphics: worksheet for hand-assembling

View File

@ -1,174 +0,0 @@
# Dev notes — 2023-08-23
## Problems to solve
The outline below / in the new README has some appeal, but it makes each instruction 8 bits long, which would require altering the simulator to support 8 bit addressing/storage...
Do I want to do this??
Or maybe go with the simpler "just swap NOP and FHP" plan...
**→ Ok i'm going to bail on this for now; the current set is easier to work with and nicer to teach. It was good to learn about and think about this, and maybe it will come back later, but for now it feels like adding this complexity would be contrary to my goals of maximum simplicity and rapid learnability.**
## Instruction set layout notes
### Reference: 6502
[The 6502 Instruction Set Decoded](https://llx.com/Neil/a2/opcodes.html)
> Most instructions that explicitly reference memory locations have bit patterns of the form aaabbbcc. The aaa and cc bits determine the opcode, and the bbb bits determine the addressing mode.
## CHUMP reference
from David Feinberg, "A Simple and Affordable TTL Processor for the Classroom":
> The CHUMP instruction set features seven key operations, each of which comes in two flavors: constant and memory. For example, there is an ADD command for adding a constant to the accumulator, and another ADD for adding a value from memory to the accumulator. The 4-bit constant portion of the instruction is ignored by the seven memory commands. Table 1 describes the seven constant commands. The corresponding memory commands operate similarly on a memory value, and have a 1 in the op-code's low-order bit.
>
> For example, the following program increments the value in RAM location 2 repeatedly. Used properly, every READ command should be followed by a memory command, and every memory command should be preceded by a READ command.
> ```0: 10000010 READ 2
> 1: 00010000 LOAD IT
> 2: 00100001 ADD 1
> 3: 01100010 STORETO 2
> 4: 10100000 GOTO 0
>```
Constant instructions:
dec bin
00 0000 Load
02 0010 Add
04 0100 Subtract
06 0110 Store To
08 1000 Read
10 1010 GOTO
12 1100 If Zero
Memory instructions (I think):
dec bin
01 0001 Load
03 0011 Add
05 0101 Subtract
07 0111 Store To
09 1001 Read
11 1011 GOTO
13 1101 If Zero
## Current Cardiograph
```
hex bin
00 0000 END *
01 0001 STO lit#
02 0010 STO addr
03 0011 LDA lit#
04 0100 LDA addr
05 0101 ADD lit#
06 0110 ADD addr
07 0111 SUB lit#
08 1000 SUB addr
09 1001 HOP lit#
0A 1010 HOP addr
0B 1011 JMP lit#
0C 1100 JMP addr
0D 1101 FTG lit#
0E 1110 FHP lit# *
0F 1111 NOP ———— *
```
so the least significant bit indicates the addressing mode (0 = direct, 1 = indirect)
except for three exceptions: END, FHP, and NOP
## Possible Cardiograph revisions
If NOP swaps with FHP, then a 1 in the least significant bit always indicates literal addressing:
```
0000 END
0001 STO lit#
0010 STO addr
0011 LDA lit#
0100 LDA addr
0101 ADD lit#
0110 ADD addr
0111 SUB lit#
1000 SUB addr
1001 HOP lit#
1010 HOP addr
1011 JMP lit#
1100 JMP addr
1101 FTG lit#
1110 NOP
1111 FHP lit#
```
Or we could use 8 bits, and use one of the upper 4 to group instructions:
```
00 0000 0000 END
01 0000 0001 NOP
... ... NOP
0F 0000 1111 NOP
10 0001 0000 STO lit#
11 0001 0001 STO addr
12 0001 0010 LDA lit#
13 0001 0011 LDA addr
14 0001 0100 ADD lit#
15 0001 0101 ADD addr
16 0001 0110 SUB lit#
17 0001 0111 SUB addr
18 0001 1000 HOP lit#
19 0001 1001 HOP addr
1A 0001 1010 JMP lit#
1B 0001 1011 JMP addr
1C 0001 1100 FTG lit#
1D 0001 1101 FTG addr
1E 0001 1110 FHP lit#
1F 0001 1111 FHP addr
```
```
gggg iii a
g: group
i: instruction
a: addressing mode (for group 0)
```
- makes the use of the LSB for direct/indirect addressing perfectly consistent for group `0001`
- makes room for indirect `FTG` and `FHP` (but those still don't seem very useful)
...
But if I want to be able to add more groups later, something like `gg aa iiii` might be better...
```
hex bin group mode op
00 0000 0000 0 -- END
01 0000 0001 0 -- NOP
50 0101 0000 1 direct STO
51 0101 0001 1 direct LDA
52 0101 0010 1 direct ADD
53 0101 0011 1 direct SUB
54 0101 0100 1 direct HOP
55 0101 0101 1 direct JMP
56 0101 0110 1 direct FTG
57 0101 0111 1 direct FHP
60 0110 0000 1 indirect STO
61 0110 0001 1 indirect LDA
62 0110 0010 1 indirect ADD
63 0110 0011 1 indirect SUB
64 0110 0100 1 indirect HOP
65 0110 0101 1 indirect JMP
66 0110 0110 1 indirect FTG
67 0110 0111 1 indirect FHP
```
~~**let's do that!**~~
(but for now i'm going to skip indirect FTG and FHP out of laziness)

View File

@ -1,81 +0,0 @@
# Dev notes — 2023-08-24
## CPU start-up
Thinking about booting up...
how would the "pointer to display memory" etc. get initialized?
They could be in ROM, but then they're not re-locatable.
Maybe there's a start-up routine in ROM that sets them up?
[cf. C64 bank switching](https://www.c64-wiki.com/wiki/Bank_Switching)
The C64 uses I/O lines on the CPU (+ others) to signal to the PLA that it's time to switch ROM banks in or out.
Maybe I need something like that?
~~A simplified approach might be to put the pointer-to-display and ...~~
Current memory map:
- `00-19` - display (5x5)
- `1A ` - pointer to display memory
- `1B ` - keypad: value of latest key pressed
- `1C ` - reserved for future use (bank switching flag)
- `1D ` - initial IP
- `1D-FF` - free
Thinking about changing it for better bank-switching:
- `00-19` - display (5x5)
- `20 ` - initial IP
- ` ` - free
- `FC ` - I/O controller - pointer to display memory
- `FD ` - I/O controller - reserved for future use (bank switching flag)
- `FE ` - I/O controller - keypad: value of latest key pressed
- `FF ` - ROM - pointer to initial IP
Ah so actually the issue is that the CPU needs to be paired with an I/O controller,
and that needs to know where to look to find these pointers/where to put the keypad info.
And I think that can just be hand-waved away for now?
### Here's the plan
**But I got started on this because I was trying to work out how FF gets loaded with the initial IP, and I think that's still a question.**
***(And maybe some way to switch ROM in and out would be good for the secret-advanced-mode, since it would be great to have a ROM pre-loaded with a set of convenient utility routines.)***
I think maybe we just leave the IP hardcoded for now; say that there's a 1-byte ROM at $FF.
- `00-19` - display (5x5)
- `1A ` - pointer to display memory
- `1B ` - keypad: value of latest key pressed
- `1C ` - reserved for future use (bank switching flag)
- `1D ` - initial IP
- `1D-FE` - free
- `FF ` - ROM (unwriteable) - pointer to initial IP
- [ ] store `$1D` at `$FF`
- [ ] make CPU execute `JMP $FF` on startup
- [ ] make ROM unwriteable
More step-by-step:
- Change memory from a Uint8Array to a regular array,
and make every entry { number | { type: 'ROM', value: number }}
- Store ROM as an object in machine.config.js
- Load ROM data into memory at CPU startup (`startCPU(RAM, ROM)`)
(And continue to handwave away how that RAM already contains data, for now...)
## TODO
- [ ] Check that we're starting execution at $1D now
- [ ] Programming
- [ ] Subroutine stack
- [ ] Conway's Life
- [ ] ? bank switching
- [ ] Keypad handling
- [ ] Start-up process described above

View File

@ -1,26 +0,0 @@
# Dev notes — 2023-08-28
Two current goals:
## 1. Implement a new CLI interface
- New arg-parser
- Allow setting clock speed with a command line flag
## 2. Re-architect
- Move the bulk of cpu.js to cpu.lib.js
- Add a way to register functions to be called each cycle
- Create a new 'cardiograph.js'
- imports cpu.lib.js
- registers functions for logging, updating display
- (split those apart)
- provides terminal interface
- get machine code input from stdin (or like, file stream?)
- `./assembler.js | ./cardiograph.js
- see below re: changes to assembler
- Assembler
- Move CLI interface into assembler.js and delete run-assembler.js
- Add a --json flag, which causes the assembler to print the json of {machineCode, debugInfo} on stdin
- Otherwise, print hex/bin to stdin

View File

@ -1,107 +0,0 @@
# Bibliography
Entries in bold are especially influential to my work on this project so far.
## To-read
- https://www.drdobbs.com/embedded-systems/paper-to-fpga/240155922
- LMC:
- http://elearning.algonquincollege.com/coursemat/dat2343/lectures.f03/12-LMC.htm
- http://www.povinelli.org/teaching/eece2710/lmc.html
- https://web.archive.org/web/20220628132003/https://thgie.ch/notes/Paper%20Computer.html
- https://wiki.osdev.org/Expanded_Main_Page
- (I haven't looked at this in this context at all yet)
- https://www.computerenhance.com/p/table-of-contents
- https://turingcomplete.game
### Games
- https://xscx.itch.io/110
- **https://jimhall.itch.io/toy-cpu**
- https://annwan.itch.io/a-cpu
- **https://nandgame.com**
- https://tobiasvl.itch.io/flip-8
- https://internet-janitor.itch.io/octo
### Machines
- https://en.wikipedia.org/wiki/CHIP-8
- https://en.wikipedia.org/wiki/KIM-1
- BBC Micro:bit
### 4-bits
- https://github.com/Subsystems-us/4-bit-Microprocessor-Trainer/blob/main/SubsySTEM2_Manual_rev01.pdf
- https://blog.lapinozz.com/learning/2016/11/19/calculator-with-caordboard-and-marbles.html
- https://jacobsweeten.github.io/4-Bit-Computer/
- **CHUMP**
- http://darcy.rsgc.on.ca/ACES/TEI4M/4BitComputer/index.html
- https://www.youtube.com/watch?app=desktop&v=b5qDwCN9Q2c
### Misc./To-sort
- https://retrocomputingforum.com/t/some-mechanical-and-optical-curiosities/1598/5
- "Coloring computers"
- **"NAND to Tetris" / Elements of Computing Systems**
- **Charles Petzold, _Code_.**
- **Mark Jones Lorenzo, _The Paper Computer Unfolded: A Twenty-First Century Guide to the Bell Labs CARDIAC (CARDboard Illustrative Aid to Computation), the LMC (Little Man Computer), and the IPC (Instructo Paper Computer)_ (self published, 2017).**
## Implementation reference
### Assembler design
- https://stackoverflow.com/questions/10244422/how-is-a-2-pass-assembler-different-from-a-one-pass-assembler-in-resolving-the-f
- https://gear.kku.ac.th/~watis/courses/188231/sp2-4.pdf
### Javascript
- https://devhints.io/jsdoc
- https://stackoverflow.com/questions/25354313/saving-a-uint8array-to-a-binary-file
## Temporary(?) references
- [Putting the “You” in CPU](https://cpu.land)
- on HN: https://news.ycombinator.com/item?id=36823605
- "These projects are really fun. On the other hand, you might want to learn in a way that lets you build hardware (esp for FPGA's). For that, I suggest a few types of books with examples:
..." https://news.ycombinator.com/item?id=36825693
- https://stackoverflow.com/questions/29193303/6502-emulation-proper-way-to-implement-adc-and-sbc
- http://6502.org/tutorials/6502opcodes.html
## Learning about CPUs
- http://skilldrick.github.io/easy6502/
- [Beagle Bros "6502 instruction reference"](https://raw.githubusercontent.com/camsaul/nesasm/master/beagle_bros_6502_reference.png)
## Instructional/toy computers
### Paper based
- **https://en.wikipedia.org/wiki/CARDboard_Illustrative_Aid_to_Computation**
- <3
- **https://en.wikipedia.org/wiki/Little_man_computer**
- **https://en.wikipedia.org/wiki/WDR_paper_computer**
### Mechanical
- Paperclip Computer
- https://hackaday.com/2020/02/08/a-modern-take-on-the-paperclip-computer/
- https://en.wikipedia.org/wiki/Digi-Comp_I
- https://en.wikipedia.org/wiki/Digi-Comp_II
- https://en.wikipedia.org/wiki/Turing_Tumble
- https://en.wikipedia.org/wiki/Dr._Nim
- https://en.wikipedia.org/wiki/Geniac
### Virtual machine
- https://wiki.xxiivv.com/site/uxn.html
- <3
### Computer games
- https://en.wikipedia.org/wiki/TIS-100
- https://en.wikipedia.org/wiki/Human_Resource_Machine
- I haven't played this one