]
# see ribbit.bas
+# hrcg is loaded at DOS addr - $801 = $9600 - $801 = $8dff
RBOOT_ENTRY = 0x208
-RLOAD_START = 0xb000 # for now
-RLOAD_ENTRY = 0xb003 # for now
+HRCG_START = 0x8dff # initialization with banner
+HRCG_ENTRY = HRCG_START + 3 # initialization without banner
# see lemonade_tone.lst
LEMONADE_TONE_PERIOD = 0x300
atexit.register(deinit)
tty.setraw(fd_in)
# auto wrap off, hide cursor, reset attributes
- write('\x1b[?7l\x1b[?25l\x1b[0m')
+ if not hrcg:
+ write('\x1b[?7l\x1b[?25l\x1b[0m')
def deinit():
global termios_attr
# reset to initial state, auto wrap on, show cursor, reset attributes
# note: reset to initial state clears the screen which I do not like,
# but it may be the only way to clear our change to the beep settings
- #write('\x1bc\x1b[?7h\x1b[?25h\x1b[0m')
- write('\x1b[?7h\x1b[?25h\x1b[0m')
+ if not hrcg:
+ #write('\x1bc\x1b[?7h\x1b[?25h\x1b[0m')
+ write('\x1b[?7h\x1b[?25h\x1b[0m')
termios.tcsetattr(fd_in, termios.TCSADRAIN, termios_attr)
atexit.unregister(deinit)
global flash_color0
addr &= 0xffff
- if addr == RBOOT_ENTRY:
- pass
- elif addr == RLOAD_ENTRY:
+ if addr == RBOOT_ENTRY or addr == HRCG_START or addr == HRCG_ENTRY:
pass
elif addr == LITTLE_BRICK_OUT_TONE_ENTRY:
# for little brick out, see test/little_brick_out_tone.py
def usr(n):
# for ribbit (HRCG)
- return RLOAD_START
+ return HRCG_START
def scrn(x, y):
i = y & 1
stop = False
poll = select.poll()
+flip_x = False
+flip_y = False
+swap_axes = False
+swap_buttons = False
+
def init():
global input_device, poll, stop, thread
assert input_device is None
if input_path is not None:
- # we will not update these until we get some movement,
- # so start with a reasonable value (not timeout value)
- apple_io.pdl_value[:3] = [128, 128, 128]
+ # with joystick present it is centred and has buttons not pressed
+ apple_io.pdl_value[:3] = [0x7f] * 3
+ apple_io.mem[apple_io.HW_PB0] = 0
+ apple_io.mem[apple_io.HW_PB1] = 0
+ apple_io.mem[apple_io.HW_PB2] = 0
input_device = evdev.InputDevice(input_path)
input_device.close()
input_device = None
- # the timeout value generally indicates no joystick present
- apple_io.pdl_value[:3] = [255, 255, 255]
+ # with no joystick present it has the timeout value and buttons pressed
+ apple_io.pdl_value[:3] = [0xff] * 3
+ apple_io.mem[apple_io.HW_PB0] = 0x80
+ apple_io.mem[apple_io.HW_PB1] = 0x80
+ apple_io.mem[apple_io.HW_PB2] = 0x80
def run():
while not stop:
if event.type == evdev.ecodes.EV_ABS:
#sys.stderr.write(f'abs code {event.code:d} value {event.value:d}\r\n')
if event.code == 0:
- apple_io.pdl_value[0] = event.value & 0xff
+ apple_io.pdl_value[0 + swap_axes] = \
+ (event.value & 0xff) ^ (flip_x * 0xff)
elif event.code == 1:
- apple_io.pdl_value[1] = event.value & 0xff
+ apple_io.pdl_value[1 - swap_axes] = \
+ (event.value & 0xff) ^ (flip_y * 0xff)
elif event.code == 5:
apple_io.pdl_value[2] = event.value & 0xff
elif event.type == evdev.ecodes.EV_KEY:
#sys.stderr.write(f'key code {event.code:d} value {event.value:d}\r\n')
if event.code == 288:
- apple_io.mem[apple_io.HW_PB0] = 0x80 if event.value else 0
+ apple_io.mem[apple_io.HW_PB0 + swap_buttons] = \
+ (event.value != 0) * 0x80
+ if event.code == 289:
+ apple_io.mem[apple_io.HW_PB1 - swap_buttons] = \
+ (event.value != 0) * 0x80
if event.code == 290:
- apple_io.mem[apple_io.HW_PB1] = 0x80 if event.value else 0
- if event.code == 291:
- apple_io.mem[apple_io.HW_PB2] = 0x80 if event.value else 0
+ apple_io.mem[apple_io.HW_PB2] = (event.value != 0) * 0x80
elif sys.argv[1][:24] == '--inter-statement-delay=':
t_def.inter_statement_delay = float(sys.argv[1][24:])
elif sys.argv[1][:11] == '--joystick=':
- apple_joystick.input_path = sys.argv[1][11:]
+ fields = sys.argv[1][11:].split(',')
+ apple_joystick.input_path = fields[0]
+ for i in fields[1:]:
+ if i == 'flip_x':
+ apple_joystick.flip_x = True
+ elif i == 'flip_y':
+ apple_joystick.flip_y = True
+ elif i == 'swap_axes':
+ apple_joystick.swap_axes = True
+ elif i == 'swap_buttons':
+ apple_joystick.swap_buttons = True
+ else:
+ assert False
else:
break
del sys.argv[1]
if len(sys.argv) < 2:
- print(f'usage: {sys.argv[0]:s} [--beep-style=alsa|vt100] [--inter-statement-delay=secs] [--joystick=/dev/input/eventNN] program.tok')
+ print(f'usage: {sys.argv[0]:s} [--beep-style=alsa|vt100] [--inter-statement-delay=secs] [--joystick=/dev/input/eventNN[,flip_x|flip_y|swap_axes|swap_buttons,...]] program.tok')
sys.exit(EXIT_FAILURE)
program_bas = sys.argv[1]
#define APPLE_WIDTH 560
#define APPLE_HEIGHT 192
#define APPLE_HIRES0 0x2000
+#define APPLE_HIRES1 0x4000
// includes cool down sequence
#define PADDED_WIDTH (APPLE_WIDTH + 3)
#define IO_KBDSTRB 0xc010
#define IO_SPKR 0xc030
#define IO_TXTCLR 0xc050
+#define IO_TXTSET 0xc051
#define IO_MIXCLR 0xc052
+#define IO_MIXSET 0xc053
#define IO_LOWSCR 0xc054
+#define IO_HISCR 0xc055
#define IO_HIRES 0xc057
#define IO_PB0 0xc061
#define IO_PB1 0xc062
#define USLEEP_LO 0xc0f6
#define USLEEP_HI 0xc0f7
#define SYS_EXIT 0xc0f8
+#define DOS_LO 0xc0f9
+#define DOS_HI 0xc0fa
#define RESET_VECTOR 0xfffc
#endif
uint8_t key_waiting;
uint8_t usleep_lo;
+uint8_t dos_lo;
+int hires = APPLE_HIRES0;
int exit_flag;
int bload(char *name) {
;
c = *q;
*q++ = 0;
- if (*p == 'A' || *p == 'a')
- load_address = atoi(p + 1);
+ if (*p == 'a') {
+ ++p;
+ int base = 10;
+ if (*p == '$') {
+ ++p;
+ base = 16;
+ }
+ load_address = (int)strtol(p, NULL, base);
+ }
else {
fprintf(stderr, "unknown BLOAD option: %s\n", p);
exit(EXIT_FAILURE);
return load_address;
}
+void dos(char *line) {
+ //fprintf(stderr, "dos: %s\n", line);
+ if (memcmp(line, "BLOAD", 5) == 0) {
+ char *p;
+ for (p = line + 5; *p == ' '; ++p)
+ ;
+ if (strcmp(p, "RBOOT") != 0) {
+ for (char *q = p; *q; ++q)
+ if (*q == ' ')
+ *q = '_';
+ else if (*q >= 'A' && *q <= 'Z')
+ *q += 'a' - 'A';
+ bload(p);
+ }
+ }
+ else {
+ fprintf(stderr, "unrecognized DOS command: %s\n", line);
+ exit(EXIT_FAILURE);
+ }
+}
+
uint8_t mem_read(uint16_t addr, bool isDbg) {
if ((addr & 0xff00) != IO_PAGE) {
#if 0 // breakpoint
switch (addr) {
case IO_KBD:
return key_waiting;
+ case IO_LOWSCR:
+ hires = APPLE_HIRES0;
+ break;
+ case IO_HISCR:
+ hires = APPLE_HIRES1;
break;
case STDIN_DATA:
{
}
case USLEEP_LO:
return usleep_lo;
+ case DOS_LO:
+ return dos_lo;
}
return 0xff;
}
case IO_KBDSTRB:
key_waiting &= 0x7f;
break;
+ case IO_LOWSCR:
+ hires = APPLE_HIRES0;
+ break;
+ case IO_HISCR:
+ hires = APPLE_HIRES1;
+ break;
case STDOUT_DATA:
if (write(STDOUT_FILENO, &val, 1) == -1) {
perror("write()");
exit_flag = val | 0x100;
vrEmu6502Jam(cpu);
break;
+ case DOS_LO:
+ dos_lo = val;
+ break;
+ case DOS_HI:
+ dos((char *)(mem + (dos_lo | (val << 8))));
+ break;
}
}
memset(frame, 0, WINDOW_HEIGHT * WINDOW_WIDTH * sizeof(uint32_t));
for (int i = 0; i < APPLE_HEIGHT; ++i) {
int line =
- APPLE_HIRES0 |
+ hires |
(i >> 6) * 40 |
((i & 0x38) << 4) |
((i & 7) << 10);
--- /dev/null
+#!/bin/sh
+../applesoft_basic.py --hrcg --joystick=/dev/input/event19,flip_y,swap_buttons ../ribbit/ribbit_patched.tok |\
+./emu_65c02 monitor_rom.obj hrcg.obj terminal.obj
wndbtm equ $23
ch equ $24
cv equ $25
-state equ $fe
-number equ $ff
+prevch equ $fc
+state equ $fd
+prevnum equ $fe
+num equ $ff
+linebuf equ $200
chario equ $3ea
hrcg equ $8dff
extfont equ hrcg+7
slp.lo equ $c0f6
slp.hi equ $c0f7
s.exit equ $c0f8
+dos.lo equ $c0f9
+dos.hi equ $c0fa
cout equ $fded
org $800
lda #0
lda #<font
sta extfont+1
jsr hrcg
+ lda #$d cr
+ sta prevch
ldx #0
newst stx state
loop lda sout.s
sta sout.d
jmp loop
nosout lda sin.s
- bpl nosin
- lda sin.d
+ bmi issin
+ lda >1000
+ sta slp.lo
+ lda <1000
+ sta slp.hi
+ jmp loop
+issin lda sin.d
ldx state
beq state0
dex
beq state1
dex
beq state2
- lda #1
+ dex
+ bne notst3
+ jmp state3
+notst3 lda #1
sta s.exit
-state0 cmp #$1b esc
+state0 cmp #4 ctrl-d
+ bne notctld
+ ldy prevch
+ cpy #$d but only after cr
+ bne notctld
+ stx num use num as linebuf index
+ ldx #3
+ jmp newst
+notctld cmp #$1b esc
bne notesc
inx
jmp newst
+notesc sta prevch
+ ora #$80
+ jsr cout
+ jmp loop
state1 cmp #$5b [
- bne aborte
- stx number
+ bne newst invalid escape sequence
+ stx prevnum
+ stx num
ldx #2
jmp newst
state2 cmp #$30 0
- bcc aborte
+ bcc newst invalid escape sequence
cmp #$3a
bcs notdig
sec
sbc #$30 digit value
- asl number
+ asl num
clc
- adc number + number * 2
- asl number
- asl number
+ adc num + num * 2
+ asl num
+ asl num
clc
- adc number + number * 8
- sta number to number
+ adc num + num * 8
+ sta num to num
+ jmp loop
+notdig cmp #$3b ;
+ bne notscln
+ lda num
+ sta prevnum
+ stx num
jmp loop
-notdig cmp #$47 G
+notscln cmp #$47 G
bne notch
- dec number
- lda number
+ dec num
+ lda num
sta ch
jmp newst
notch cmp #$64 d
- bne aborte
- dec number
- lda number
+ bne notcv
+ dec num
+ lda num
sta cv
jmp newst
-aborte stx state
-notesc ora #$80
- jsr cout
- jmp loop
-nosin lda >1000
- sta slp.lo
- lda <1000
- sta slp.hi
+notcv cmp #$72 r
+ bne notwnd
+ dec prevnum
+ lda prevnum
+ sta wndtop
+ lda num
+ sta wndbtm
+notwnd jmp newst invalid escape sequence
+state3 ldy num
+ cmp #$d
+ bne notcr
+ txa
+ sta linebuf,y
+ lda #>linebuf
+ sta dos.lo
+ lda #<linebuf
+ sta dos.hi
+ jmp newst
+notcr sta linebuf,y
+ iny
+ sty num
jmp loop
+--- ribbit.bas 2022-05-25 17:23:30.448202796 +1000
++++ ribbit_patched.bas 2022-05-25 17:29:46.852217967 +1000
+@@ -1,6 +1,7 @@
+ 10GOTO10000:REM INITIALIZE
+ 20GOSUB900:GOTO1000
+ 100REM FLUTTER BY
++105FORJ=1TO75:NEXT
+ 120BC=NOTBC:IFBCTHENVTABBY:HTABBX:PRINTBUG$((BD<0),2):RETURN
+ 130IFBX>1ANDBX<38THEN150
+ 140VTABBY:HTABBX:PRINTBUG$(0,0):BY=INT(RND(1)*8)*2+3:BX=(RND(1)<.5)*37+1:BD=1-(BX>20)*2:BS=BS+1:GOSUB2000
+@@ -37,7 +38,7 @@
+ 850PRINT" RIB*BIT ";:RETURN
+ 900REM TURN AROUND
+ 910VTABFY:HTABFX:PRINTFROG$(FD,1);:GOSUB100:RETURN
+-1000FORI=1TO100:NEXT:REM MAIN LOOP
++1000REM MAIN LOOP
+ 1010FORI=1TORND(1)*400+100:GOSUB100
+ 1020P0=PDL(0):IFP0<80ANDFDTHENFD=0:GOSUB900
+ 1030IFP0>160ANDNOTFDTHENFD=1:GOSUB900
+@@ -139,8 +140,8 @@
+ 20110VTAB10:PRINT"\13DO YOU KNOW HOW TO PLAY THIS GAME?\v"
+ 20120PRINTIA$;IT$;:VTAB1:HTAB1:PRINT" ";
+ 20200FY=1:FORFX=2TO32STEP2
+-20210VTABFY:HTABFX:PRINTFROG$(1,3):FORI=1TO20:NEXT
+-20220VTABFY:HTABFX+1:PRINTFROG$(1,4):FORI=1TO20:NEXT
++20210VTABFY:HTABFX:PRINTFROG$(1,3):FORI=1TO100:NEXT
++20220VTABFY:HTABFX+1:PRINTFROG$(1,4):FORI=1TO100:NEXT
+ 20230VTABFY:HTABFX+2:PRINTFROG$(1,1)
+ 20240FORI=1TO100:NEXT:NEXT
+ 20250FORI=1TO1000:NEXT:VTABFY:HTABFX:PRINTIP$;FROG$(0,1)
+5 SPEED=10
10 HOME
20 HTAB 10
30 INVERSE:PRINT "MY PROGRAM":NORMAL
+32 SPEED=255
35 FOR I=0 TO 31:POKE 1280+I,I*8:NEXT
40 VTAB 5
50 PRINT CHR$(7)"TYPE SOMETHING: ";