Skip to content

Commit 50322f7

Browse files
Add keyboard command to restart and toggle quirks
1 parent e0d0f07 commit 50322f7

File tree

2 files changed

+80
-55
lines changed

2 files changed

+80
-55
lines changed

README.md

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,19 @@
22

33
[CHIP-8](https://en.wikipedia.org/wiki/CHIP-8) is a fantasy video game console definition from the 1970s by Joseph Weisbecker.
44

5-
This version runs on Apple II models that support Double Low Resolution graphics (DGR):
5+
This is an interpreter for running CHIP-8 programs on Apple II models that support Double Low Resolution graphics (DGR):
66

7-
* Apple IIe (original)
8-
* Apple IIe Enhanced
7+
* Apple IIe* (original), with 80 column card
8+
* Apple IIe Enhanced*, with 80 column card
99
* Apple IIc
1010
* Apple IIc Plus
1111
* Apple IIgs
1212
* Macintosh IIe Option Card (_untested_)
1313
* Clones such as the Laser 128, Franklin ACE 2200, Franklin ACE 500
1414
* Emulators such as MAME, Virtual ][, AppleWin, etc.
1515

16+
_* The rare Apple IIe Revision A motherboard does not support double-resolution graphics._
17+
1618
It runs in ProDOS-8 and follows the "interpreter protocol" so that launchers such as [Bitsy Bye](https://prodos8.com/bitsy-bye/) and [Apple II DeskTop](https://a2desktop.com) can automatically launch CHIP-8 programs with it.
1719

1820
# For Users
@@ -25,9 +27,9 @@ https://github.com/a2stuff/chip8.system/releases/latest/download/chip8.po
2527

2628
## CHIP-8 Programs
2729

28-
To run a CHIP-8 program, copy the file to a [ProDOS-8 2.4](https://prodos8.com/) with the `CHIP8.SYSTEM` renamed to (or copied as) `BASIS.SYSTEM` in the root directory, then boot the disk. [Bitsy Bye](https://prodos8.com/bitsy-bye/) will run and show a list of files and directories. Pick the CHIP-8 file and it will launch automatically.
30+
To run a CHIP-8 program, copy the file to a [ProDOS-8 2.4](https://prodos8.com/) disk with the `CHIP8.SYSTEM` renamed to (or duplicated as) `BASIS.SYSTEM` in the root directory, then boot the disk. [Bitsy Bye](https://prodos8.com/bitsy-bye/) will run and show a list of files and directories. Pick the CHIP-8 file and it will launch automatically.
2931

30-
> TIP: [Apple II DeskTop](https://a2desktop.com) will use a copy of `BASIS.SYSTEM` in the same directory to launch unknown file types.
32+
> TIP: [Apple II DeskTop](https://a2desktop.com) will also use a copy of `BASIS.SYSTEM` in the same directory to launch unknown file types.
3133
3234
There are many online archives of CHIP-8 programs:
3335

@@ -36,13 +38,15 @@ There are many online archives of CHIP-8 programs:
3638
* https://github.com/kripod/chip8-roms
3739
* https://www.zophar.net/pdroms/chip8/chip-8-games-pack.html
3840

39-
> NOTE: Only CHIP-8 games are supported, not SUPER-CHIP or XO-CHIP.
41+
> NOTE: Only CHIP-8 programs are supported, not SUPER-CHIP or XO-CHIP.
4042
4143
## Controls
4244

4345
Press <kbd>Esc</kbd> at any time to quit to ProDOS.
4446

45-
The CHIP-8 assumes a 16-key keypad:
47+
Press <kbd>Del</kbd> at any time to restart the program.
48+
49+
The CHIP-8 assumes a 16-key keypad like the [COSMAC VIP](https://en.wikipedia.org/wiki/COSMAC_VIP):
4650
| | | | |
4751
|-|-|-|-|
4852
|<kbd>1</kbd>|<kbd>2</kbd>|<kbd>3</kbd>|<kbd>C</kbd>|
@@ -59,7 +63,9 @@ Use these keys on a QWERTY keyboard instead:
5963
|<kbd>A</kbd>|<kbd>S</kbd>|<kbd>D</kbd>|<kbd>F</kbd>|
6064
|<kbd>Z</kbd>|<kbd>X</kbd>|<kbd>C</kbd>|<kbd>V</kbd>|
6165

62-
> TIP: CHIP-8 programs use a variety of key combinations. Look for documentation where you found the program, or mash the keys to figure out the controls. Have fun!
66+
For example, the `BLINKY` game (a Pac-Man clone) uses keypad keys <kbd>7</kbd> and <kbd>8</kbd> for left and right, and <kbd>3</kbd> and <kbd>6</kbd> for up and down, so on the Apple II keyboard you would use <kbd>A</kbd> and <kbd>S</kbd> for left and right, and <kbd>3</kbd> and <kbd>E</kbd> for up and down.
67+
68+
> TIP: CHIP-8 programs use a variety of key combinations, often very strange ones. Look for documentation where you found the program, or mash the keys to figure out the controls. Good luck!
6369
6470

6571
Other controls:
@@ -70,26 +76,30 @@ Other controls:
7076

7177
## Compatibility & Quirks
7278

73-
Some CHIP-8 programs require different compatibility settings. This can be enabled by changing the ProDOS file type of the program to `$5D` (`ENT` or Entertainment), and setting the aux type to `$C800` (for "CHIP-8") with the lower byte used as "quirks" flags as follows:
79+
Some CHIP-8 programs require different compatibility settings, called "quirks".
7480

75-
| Bit | Name | ID | Default |
76-
|-----|--------------|--------------------------|-------------|
77-
| 0 | VF Reset | `logic` | on / true |
78-
| 1 | Memory | `memoryLeaveIUnchanged`* | on / false |
79-
| 2 | Display Wait | `vblank` | on / true |
80-
| 3 | Clipping | `wrap`* | on / false |
81-
| 4 | Shifting | `shift` | off / false |
82-
| 5 | Jumping | `jump` | off / false |
81+
| Quirk Name | ID | Default | Key | Bit |
82+
|--------------|--------------------------|-------------|--------------|-----|
83+
| VF Reset | `logic` | on / true | <kbd>!</kbd> | 0 |
84+
| Memory | `memoryLeaveIUnchanged`* | on / false | <kbd>@</kbd> | 1 |
85+
| Display Wait | `vblank` | on / true | <kbd>#</kbd> | 2 |
86+
| Clipping | `wrap`* | on / false | <kbd>$</kbd> | 3 |
87+
| Shifting | `shift` | off / false | <kbd>%</kbd> | 4 |
88+
| Jumping | `jump` | off / false | <kbd>^</kbd> | 5 |
8389

84-
Names are per [Timendus's CHIP-8 quirks test](https://github.com/Timendus/chip8-test-suite?tab=readme-ov-file#quirks-test). The defaults match the passing expectations in these tests.
90+
**Quirk names** are per [Timendus's CHIP-8 quirks test](https://github.com/Timendus/chip8-test-suite?tab=readme-ov-file#quirks-test). The defaults for `CHIP8.SYSTEM` match the passing expectations in these tests.
8591

86-
IDs are per the [CHIP-8 database](https://github.com/chip-8/chip-8-database/blob/master/database/quirks.json), which lists the same quirks but with slightly different expectations. A * signifies that sense is inverted, i.e. _setting_ the bit is the same as turning _off_ the quirk, per the database definition.
92+
**IDs** are per the [CHIP-8 database](https://github.com/chip-8/chip-8-database/blob/master/database/quirks.json), which lists the same quirks but with slightly different expectations. A * signifies that sense is inverted, i.e. turning the quirk *on*, per the test definition, is the same as the *false* setting in the database definition.
8793

8894
Defaults "on" and "off" reference Timendus' tests, "true" and "false" reference the CHIP-8 database.
8995

90-
Otherwise, all quirks are set to the defaults. This is equivalent to file type `$5D` and aux type `$C80F`.
96+
To toggle a quirk on or off at runtime, press the **Key**. The CHIP-8 program will restart with the new setting.
97+
98+
It is possible to persistently configure the quirks for a CHIP-8 program. This is done by changing the ProDOS file type of the program to `$5D` (a.k.a. `ENT` or Entertainment), and setting the aux type to `$C800` (for "CHIP-8") with the lower byte used as "quirks" flags, per the **Bit** column.
99+
100+
For example, the `BLINKY` game (a Pac-Man clone) requires the "Memory" quirk disabled (bit 1) and the "Shifting" quirk enabled (bit 4), so is packaged with file type `$5D` and aux type `$C81D`, since `$1D` is binary `00011101` meaning bit 0 is on, bit 1 is off, bit 2 is on, bit 3 is on, bit 4 is on, and bit 5 is off.
91101

92-
For exmple, the `BLINKY` game (a Pac-Man clone) requires the "Memory" quirk disabled and the "Shifting" quirk enabled, so is packaged with file type `$5D` and aux type `$C81D`.
102+
If the file type is not `$5D` or the aux type does not start with `$C8` then programs start with all quirks set to the defaults. This is equivalent to file type `$5D` and aux type `$C80F`, since `$0F` is binary `00001111` meaning bits 0-3 are on and bits 4-5 are off.
93103

94104
For detailed "quirks" definitions, see https://github.com/Timendus/chip8-test-suite?tab=readme-ov-file#the-test
95105

chip8.system.s

Lines changed: 49 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -18,23 +18,6 @@
1818

1919
;;; ============================================================
2020

21-
;;; If file has ProDOS-8 file type $5D "Entertainment" and the
22-
;;; high byte of the auxtype is $C8 (for "CHIP-8") then the low
23-
;;; bytes of the auxtype define "quirks" behavior:
24-
;;;
25-
;;; Bit 0 = VF Reset (default: on)
26-
;;; Bit 1 = Memory (default: on)
27-
;;; Bit 2 = Display Wait (default: on)
28-
;;; Bit 3 = Clipping (default: on)
29-
;;; Bit 4 = Shifting (default: off)
30-
;;; Bit 5 = Jumping (default: off)
31-
;;;
32-
;;; Otherwise, all quirks are set to the defaults.
33-
;;;
34-
;;; https://github.com/Timendus/chip8-test-suite?tab=readme-ov-file#the-test
35-
36-
;;; ============================================================
37-
3821
;;; Equates
3922
SPKR := $C030
4023
CLR80VID := $C00C
@@ -113,16 +96,14 @@ ADDR_MASK_HI := %00001111 ; mask high address byte to 12 bits
11396
LOAD_ADDR := $200
11497
FONT_ADDR := $050
11598

116-
;;; ============================================================
117-
;;; Graphics
99+
CHIP8_SCREEN_WIDTH = 64
100+
CHIP8_SCREEN_HEIGHT = 32
118101

102+
;;; Defaults
119103
COLOR_BORDER = 2 ; dark blue
120104
COLOR_BG = 0 ; black
121105
COLOR_FG = 15 ; white
122106

123-
CHIP8_SCREEN_WIDTH = 64
124-
CHIP8_SCREEN_HEIGHT = 32
125-
126107
;;; ============================================================
127108
;;; Start of Binary
128109
;;; ============================================================
@@ -185,6 +166,9 @@ reserved3: .word 0
185166
;;; ============================================================
186167
;;; Quirks flags
187168

169+
;;; See the associated `README.md` for more details.
170+
171+
188172
;;; Should `8XY1`, `8XY2` and `8XY3` reset `VF`?
189173
;;; https://tobiasvl.github.io/blog/write-a-chip-8-emulator/#logical-and-arithmetic-instructions
190174
;;; https://github.com/Timendus/chip8-test-suite?tab=readme-ov-file#the-test
@@ -296,11 +280,13 @@ get_info:
296280
MLI_CALL GET_FILE_INFO, get_file_info_params
297281
bcs fail
298282

283+
;; See the associated `README.md` for more details.
284+
299285
lda get_file_info_params::file_type
300-
cmp #$5D ; $5D = ENT "Entertainment"
286+
cmp #$5D ; `$5D` = `ENT` "Entertainment"
301287
bne :+
302288
lda get_file_info_params::aux_type+1
303-
cmp #$C8 ; Chip-8 signature
289+
cmp #$C8 ; CHIP-8 signature
304290
bne :+
305291
lda get_file_info_params::aux_type
306292

@@ -386,7 +372,7 @@ collision .byte
386372
_ZP_END_ .byte
387373
.endstruct
388374

389-
;;; NOTES: Avoid $40-$4E (used by ProDOS)
375+
;;; NOTES: Avoid `$40`-`$4E` (used by ProDOS)
390376
.assert _ZP_END_ <= $40, error, "ZP collision"
391377

392378
;;; NOTE: `pc_ptr` and `addr_ptr` are stored as real memory addresses,
@@ -475,7 +461,7 @@ InterpreterLoop:
475461
lda dispatch_hi,x
476462
sta dispatch+1
477463

478-
;; Not every instruction is of the form _XY_ but most are so
464+
;; Not every instruction is of the form `_XY_` but most are so
479465
;; load nibbles into X and Y
480466

481467
lda instr
@@ -490,7 +476,7 @@ InterpreterLoop:
490476
and #%00001111
491477
tax ; X = X
492478

493-
;; And using __NN is common so load low byte into A
479+
;; And using `__NN` is common so load low byte into A
494480

495481
lda instr ; commonly needed
496482

@@ -517,9 +503,9 @@ dispatch_hi:
517503
;;; ============================================================
518504

519505
;;; All of the following are called with:
520-
;;; X register = X (assuming _X__)
521-
;;; Y register = Y (assuming __Y_)
522-
;;; A register = low byte (i.e. __NN)
506+
;;; X register = X (assuming `_X__`)
507+
;;; Y register = Y (assuming `__Y_`)
508+
;;; A register = low byte (i.e. `__NN`)
523509

524510
;;; ============================================================
525511

@@ -1283,8 +1269,10 @@ VBL_XOR := ServiceTimers::vbl_xor
12831269
;;; Initialization
12841270

12851271
.proc InitMemory
1286-
12871272
;; Zero CHIP-8 memory
1273+
lda #.hibyte(CHIP8_MEMORY)
1274+
sta addr+1
1275+
12881276
lda #$00
12891277
ldy #.hibyte(CHIP8_SIZE) ; number of pages
12901278
ploop: ldx #$00 ; clear a whole page
@@ -1452,13 +1440,19 @@ found:
14521440

14531441

14541442
dispatch_key:
1455-
.byte $1B, '9', '0', '[', ']', ',', '.'
1443+
.byte $1B, $7F, \
1444+
'9', '0', '[', ']', ',', '.', \
1445+
'!', '@', '#', '$', '%', '^'
14561446
NUM_KEYS = * - dispatch_key
14571447
dispatch_lo:
1458-
.lobytes quit, PrevBorder, NextBorder, PrevBG, NextBG, PrevFG, NextFG
1448+
.lobytes quit, Restart, \
1449+
PrevBorder, NextBorder, PrevBG, NextBG, PrevFG, NextFG, \
1450+
ToggleQ1, ToggleQ2, ToggleQ3, ToggleQ4, ToggleQ5, ToggleQ6
14591451
.assert * - dispatch_lo = NUM_KEYS, error, "table size"
14601452
dispatch_hi:
1461-
.hibytes quit, PrevBorder, NextBorder, PrevBG, NextBG, PrevFG, NextFG
1453+
.hibytes quit, Restart, \
1454+
PrevBorder, NextBorder, PrevBG, NextBG, PrevFG, NextFG, \
1455+
ToggleQ1, ToggleQ2, ToggleQ3, ToggleQ4, ToggleQ5, ToggleQ6
14621456
.assert * - dispatch_hi = NUM_KEYS, error, "table size"
14631457

14641458
key_table:
@@ -1474,6 +1468,27 @@ key_table:
14741468
.byte '4', 'R', 'F', 'V'
14751469
.endproc
14761470

1471+
;;; ============================================================
1472+
;;; Runtime Quirk Configuration
1473+
1474+
.macro TQ_PROC n, flag
1475+
.proc .ident(.sprintf("ToggleQ%d", n))
1476+
lda flag
1477+
eor #$80
1478+
sta flag
1479+
jmp Restart
1480+
.endproc
1481+
.endmacro
1482+
1483+
TQ_PROC 1, quirks_vf_reset
1484+
TQ_PROC 2, quirks_memory
1485+
TQ_PROC 3, quirks_disp_wait
1486+
TQ_PROC 4, quirks_clipping
1487+
TQ_PROC 5, quirks_shifting
1488+
TQ_PROC 6, quirks_jumping
1489+
1490+
Restart := load_file
1491+
14771492
;;; ============================================================
14781493
;;; Graphics
14791494

0 commit comments

Comments
 (0)