diff --git a/Dockerfile b/Dockerfile index e3a62c2..cda032e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,6 +12,7 @@ RUN apt-get update && \ nginx \ source-highlight \ supervisor \ + xa65 \ xvfb \ x11vnc \ && \ @@ -38,6 +39,7 @@ COPY Makefile.am ./ COPY src/ ./src/ COPY conf/ ./conf/ +COPY rom/ ./rom/ COPY installer/ ./installer/ COPY doc/ ./doc/ diff --git a/Makefile.am b/Makefile.am index ac61658..78e0fe9 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,2 +1,4 @@ -SUBDIRS = src conf installer doc +#@configure_input@ +ACLOCAL_AMFLAGS=-I m4 --install +SUBDIRS = src conf rom installer doc EXTRA_DIST = COPYING.sdl COPYING.other diff --git a/configure.ac b/configure.ac index 9939305..436429e 100644 --- a/configure.ac +++ b/configure.ac @@ -1,3 +1,4 @@ +# -*- Autoconf -*- # Process this file with autoconf to produce a configure script. AC_INIT(epple2, 1.2-SNAPSHOT) AC_PREREQ(2.68) @@ -17,6 +18,36 @@ AC_PROG_INSTALL AC_PROG_LN_S AC_PROG_MAKE_SET AC_PROG_RANLIB +AC_PATH_PROGS([XA65],[xa65 xa]) +if test "X$ac_cv_path_XA65" == X +then + AC_MSG_ERROR([Cannot find xa (xa65) 6502 cross assembler by Andre Fachat]) +fi +AC_ARG_VAR([XA65],[path to xa (xa65) 6502 cross assembler by Andre Fachat]) + +AC_PATH_PROG([LDO65],[ldo65]) +if test "X$ac_cv_path_LDO65" == X +then + AC_MSG_ERROR([Cannot find ldo65, from xa (xa65) 6502 cross assembler by Andre Fachat]) +fi +AC_ARG_VAR([LDO65],[path to ldo65, from xa (xa65) 6502 cross assembler by Andre Fachat]) + +AC_PATH_PROG([RELOC65],[reloc65]) +if test "X$ac_cv_path_RELOC65" == X +then + AC_MSG_ERROR([Cannot find reloc, from xa (xa65) 6502 cross assembler by Andre Fachat]) +fi +AC_ARG_VAR([RELOC65],[path to reloc65, from xa (xa65) 6502 cross assembler by Andre Fachat]) + +AC_PATH_PROG([M4],[m4]) +if test "X$ac_cv_path_M4" == X +then + AC_MSG_ERROR([Cannot find m4]) +fi +AC_ARG_VAR([M4],[path to m4]) + +AC_PATH_PROG([MD5SUM],[md5sum]) +AC_ARG_VAR([MD5SUM],[path to md5sum]) @@ -45,5 +76,5 @@ AC_CHECK_FUNCS([memset sqrt]) -AC_CONFIG_FILES([Makefile src/Makefile conf/Makefile installer/Makefile doc/Makefile]) +AC_CONFIG_FILES([Makefile src/Makefile conf/Makefile rom/Makefile installer/Makefile doc/Makefile]) AC_OUTPUT diff --git a/rom/Makefile.am b/rom/Makefile.am new file mode 100644 index 0000000..6424d7b --- /dev/null +++ b/rom/Makefile.am @@ -0,0 +1,58 @@ +#@configure_input@ +#!/usr/bin/make -f + +AUTOMAKE_OPTIONS=-Wno-override + +ZEROSEGS=-bd 0 -bb 0 -bz 0 + +.m4.s65: + $(M4) -I $(srcdir) $(M4FLAGS) $< >$@ + +.s65.o65: + $(XA65) -C -M -R -c -bt 0 $(ZERO_SEGS) -o $@ $(XA65FLAGS) $< + +.o65.r65: + $(LDO65) -bt $(CODE_SEG) $(ZERO_SEGS) -o $@ $(LD65FLAGS) $^ + +.r65.a65: + $(RELOC65) -xt -o $@ $(RELOC65FLAGS) $< + +libsysdir=$(prefix)/lib/epple2/system +libcrddir=$(prefix)/lib/epple2/cards + +libsys_DATA=epple2sys.a65 +libcrd_DATA=stdin.a65 stdout.a65 clock.a65 +noinst_DATA=epple2sys.md5 stdin.md5 stdout.md5 clock.md5 +EXTRA_DIST=epple2sys.m4 asm.m4h stdin.s65 stdout.s65 clock.s65 epple2sys.md5 stdin.md5 stdout.md5 clock.md5 + +epple2sys.r65: CODE_SEG=64512 +epple2sys.s65: epple2sys.m4 asm.m4h + +clock.r65: CODE_SEG=0 +stdin.r65: CODE_SEG=0 +stdout.r65: CODE_SEG=0 + +define_new_md5: all + $(MD5SUM) --binary epple2sys.a65 >$(srcdir)/epple2sys.md5 + +check_SCRIPTS=unit_test.sh +TESTS=$(check_SCRIPTS) + +unit_test.sh: + touch $@ + if test "X$(MD5SUM)" == X ; \ + then \ + echo "echo \"md5sum program not found, so cannot run this test\" >&2" >>$@ ; \ + echo "exit 1" >>$@ ; \ + else \ + echo "set -e" >>$@ ; \ + echo "$(MD5SUM) --check --status --warn $(srcdir)/epple2sys.md5" >>$@ ; \ + echo "$(MD5SUM) --check --status --warn $(srcdir)/stdin.md5" >>$@ ; \ + echo "$(MD5SUM) --check --status --warn $(srcdir)/stdout.md5" >>$@ ; \ + echo "$(MD5SUM) --check --status --warn $(srcdir)/clock.md5" >>$@ ; \ + fi + chmod +x $@ + + + +CLEANFILES=unit_test.sh *.a65 *.r65 epple2sys.s65 diff --git a/rom/asm.m4h b/rom/asm.m4h new file mode 100644 index 0000000..7e6a5bc --- /dev/null +++ b/rom/asm.m4h @@ -0,0 +1,43 @@ +define(`ASM_DATA',`.BYT $*') +define(`ASM_DATA_W',`.WORD $*') +define(`ASM_ADDR',`.WORD $*') +define(`ASM_RES',`.DSB $1,ifelse(`$2',`',0,$2)') + + + +define(`NL',` +') + +changecom(`;',NL()) + +dnl assumes no single-letter macros +define(`SAFESUB', + `ifelse( + $#,0,``$0'', + $#,2,`$0($@,eval(len(`$1')-($2)))', + eval(`$3-0'),0,`', + `substr(`$1',eval($2),1)`'$0(`$1',eval(($2)+1),eval(($3)-1))')') + +define(`STR_REVERSE', + `ifelse( + len(`$1'),0,`', + `$0(SAFESUB(`$1',1))`'SAFESUB(`$1',0,1)')') + +define(`STR_FORCHAR', + `ifelse( + `$2',`',`', + `pushdef(`$1',SAFESUB(`$2',0,1))$3`'popdef(`$1')`'$0($1,SAFESUB(`$2',1),`$3')')') + +define(`STR_FORCHAR_LAST', + `ifelse( + len(`$2'),1,`pushdef(`$1',`$2')$4`'popdef(`$1')', + `pushdef(`$1',SAFESUB(`$2',0,1))$3`'popdef(`$1')`'$0($1,SAFESUB(`$2',1),`$3',`$4')')') + +define(`HICHAR',`("`$1'"|%10000000)') +define(`LOCHAR',`("`$1'"&%01111111)') + +define(`HIASCII',`STR_FORCHAR(__,`$1',`ASM_DATA(HICHAR(__)) NL()')') +define(`LOASCII',`STR_FORCHAR(__,`$1',`ASM_DATA(LOCHAR(__)) NL()')') + +define(`HLASCII',`STR_FORCHAR_LAST(__,`$1',`ASM_DATA(HICHAR(__)) NL()',`ASM_DATA(LOCHAR(__)) NL()')') +define(`LHASCII',`STR_FORCHAR_LAST(__,`$1',`ASM_DATA(LOCHAR(__)) NL()',`ASM_DATA(HICHAR(__)) NL()')') diff --git a/rom/clock.md5 b/rom/clock.md5 new file mode 100644 index 0000000..6f76100 --- /dev/null +++ b/rom/clock.md5 @@ -0,0 +1 @@ +ef0159bc66a6f3b20e2fe6f634361a54 *clock.a65 diff --git a/rom/clock.s65 b/rom/clock.s65 new file mode 100644 index 0000000..9eebaf9 --- /dev/null +++ b/rom/clock.s65 @@ -0,0 +1,41 @@ +YSAV1 = $35 +CR = $8D +STKBAS = $0100 +BUF = $0200 +READC = $C080 +LATCHC = $C081 + +CLOCK PHP + NOP + PLP + CLV + CLI + SEC + BVS *+2+$18 + BVC READCL + NOP + +WRITECL ORA ($6F,X) + RTS + +READCL LDA #$60 + STA YSAV1 + JSR YSAV1 + TSX + LDA STKBAS,X + ASL + ASL + ASL + ASL + TAX + + LDY #0 +LOOP LDA LATCHC,X +REREAD LDA READC,X + BPL REREAD + STA BUF,Y + INY + CMP #CR + BNE LOOP + + RTS diff --git a/rom/epple2sys.m4 b/rom/epple2sys.m4 new file mode 100644 index 0000000..9ca2fa1 --- /dev/null +++ b/rom/epple2sys.m4 @@ -0,0 +1,658 @@ +; Epple ][ System Demo ROM +; Copyright (C) 2009 by Chris Mosher +; +; This program is free software: you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation, either version 3 of the License, or +; (at your option) any later version. +; +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY, without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program. If not, see . +; +; +; +include(asm.m4h) +; +; +; +; constants +SCREENWID = 40 ; width of text screen +SCREENHGT = 24 ; height of text screen +; +; +; +; ASCII values (high bit set) +BS = $88 +CR = $8D +SPACE = $A0 +; +; +; +; zero page addresses (our variables) +TMPW = $00 ; $01 +ADDR = $02 ; $03 +ADDR2 = $04 ; $05 +TEXTROW = $06 ; $07 +TMP = $08 +COL = $09 +ROW = $0A +INBUFC = $0B +; +; +; +; page 2 (input buffer) +INBUF = $0200 +; +; +; +; I/O addresses ($C0xx) +READKEY = $C000 +CLEARKEY = $C010 +TEXTON = $C051 +MIXEDOFF = $C052 +PAGE2OFF = $C054 +HIRESOFF = $C056 + + + + + + +; +; +; +;;RESET +; Handles power-on or reset-button-press. +; Initializes CPU, screen; displays welcome message; +; invokes the shell. +; +RESET NOP + SEI + CLD + LDX #$FF + TXS + + LDA TEXTON + LDA MIXEDOFF + LDA PAGE2OFF + LDA HIRESOFF + + NOP + + JSR ENDSCR + JSR ADVCUR + JSR WELCOME + JMP SHELL +; +; +; +;;LINEADDR +; Computes address of column 0 for text line +; (0-23) given in A, into TEXTROW. +; input: +; A 000edcba +; output: +; TEXTROW aeded000 000001cb +; scratch: +; X +; +LINEADDR TAX + LDA #$04 + STA TEXTROW+1 + TXA + LSR + AND #$03 + ORA TEXTROW+1 + STA TEXTROW+1 + + BCC ZERO + LDA #$80 + BNE STORELOW +ZERO LDA #$00 +STORELOW STA TEXTROW + TXA + AND #$18 + TAX + ORA TEXTROW + STA TEXTROW + TXA + ASL + ASL + ORA TEXTROW + STA TEXTROW + RTS +; +; +; +;;CHARADDR +; Computes address of character at ROW,COL +; for use as STA (TEXTROW),Y +; input: ROW, COL +; output: TEXTROW, Y +; scratch: A,X +; +CHARADDR LDA ROW + JSR LINEADDR + LDY COL + RTS +; +; +; +;;ENDSCR +; Moves cursor to bottom right. +; output: ROW, COL +; scratch: A +; +ENDSCR LDA #SCREENHGT-1 + STA ROW + LDA #SCREENWID-1 + STA COL + RTS +; +; +; +;;SCROLL +; Scrolls the entire screen up one line +; scratch: A. Y, X, TMP, TMPW, TEXTROW +; +SCROLL LDA #0 + STA TMP ; row + +LOOPROW LDA TMP + JSR LINEADDR + LDA TEXTROW + STA TMPW + LDA TEXTROW+1 + STA TMPW+1 + INC TMP + LDA TMP + JSR LINEADDR + + LDY #SCREENWID-1 +LOOPCOL LDA (TEXTROW),Y + STA (TMPW),Y + DEY + BPL LOOPCOL + + LDA TMP + CMP #SCREENHGT-1 + BNE LOOPROW + + RTS +; +; +; +;;CLEARLINE +; Clears line given by A +; input: A +; scratch: X, Y, TEXTROW +; +CLEARLINE JSR LINEADDR + LDA #SPACE + LDY #SCREENWID-1 +LOOPCLR STA (TEXTROW),Y + DEY + BPL LOOPCLR + RTS +; +; +; +;;PRCURS +; Prints the cursor (inverses char at ROL,COL) +; input: ROW, COL +; scratch: TEXTROW, Y, A, X +; +PRCURS JSR CHARADDR + LDA #$60 + STA (TEXTROW),Y + RTS +; +; +; +;;PRCHAR +; Prints a normal character in A at ROW, COL; +; advances cursor; scrolls if necessary +; input: A, ROW, COL +; scratch: TEXTROW, Y, X +; +PRCHAR PHA + JSR CHARADDR + PLA + + STA (TEXTROW),Y + + JSR ADVCUR + RTS +; +; +; +;;ADVCUR +; Advances cursor one position; scrolls if necessary. +; +ADVCUR INC COL + LDA COL + CMP #SCREENWID + BNE ADVOK + + JSR PRCR + JSR PRLF + +ADVOK RTS +; +; +; +;;PRCR +; Prints a carraige return (goes to start of same line) +; output: COL +; scratch: A +; +PRCR LDA #0 + STA COL + RTS +; +; +; +;;PRLF +; Prints a line feed (goes down one line); +; scrolls if necessary +; input: ROW +; output: ROW +; scratch: A. Y, X, TMP, TMPW, TEXTROW +; +PRLF INC ROW + LDA ROW + CMP #SCREENHGT + BNE LFOK + + DEC ROW + JSR SCROLL + LDA #SCREENHGT-1 + JSR CLEARLINE +LFOK RTS +; +; +; +;;PRBS +; Prints a back-space (goes left one char) +; input: COL, ROW +; output: COL, ROW +; scratch: A +; +PRBS DEC COL + BPL BSOK + LDA #SCREENWID-1 + STA COL + DEC ROW + BPL BSOK + INC ROW + LDA #0 + STA COL +BSOK RTS +; +; +; +;;PRPROMPT +; Prints the prompt character. +; input: ROW, COL +; scratch: A, TEXTROW, Y, X +; +PRPROMPT JSR PRSTR + HIASCII(`E2>') + ASM_DATA(0) + RTS +; +; +; +;;RDCHAR +; Reads a character (waits for one) into A +; (high bit will be set) +; +RDCHAR LDA CLEARKEY +NOKEY LDA READKEY + BPL NOKEY + RTS +; +; +; +;;WELCOME +; +WELCOME JSR PRSTR + HIASCII(`EPPLE ][ DEMO ROM [GPLV3] ? FOR HELP') + ASM_DATA(0) + JSR PRCR + JSR PRLF + RTS +; +; +; +;;PRSTR +; Prints a string (in code seg of caller) +; +PRSTR PLA + STA TMPW + PLA + STA TMPW+1 + INC TMPW + BNE NOC + INC TMPW+1 +NOC LDY #0 + LDA (TMPW),Y + TAY + LDA TMPW+1 + PHA + LDA TMPW + PHA + TYA + BEQ DONE + JSR PRCHAR + JMP PRSTR +DONE + + RTS +; +; +;;CVTHEX +; Parses hex character ('0'-'9' or 'A'-'F') in A +; and shifts into low-order nibble of TMPW. +; Undefined op if A contains something else. +; +CVTHEX CMP #HICHAR(`A') + BCC DIGIT + SBC #'A'-'9'-1 +DIGIT + AND #%00001111 + ASL + ASL + ASL + ASL + + ASL + ROL TMPW + ROL TMPW+1 + ASL + ROL TMPW + ROL TMPW+1 + ASL + ROL TMPW + ROL TMPW+1 + ASL + ROL TMPW + ROL TMPW+1 + RTS +; +; +;;PRBYTE +; Prints byte in A as hex +; +PRBYTE PHA + ; ABCDxxxx + ; 1011ABCD + LSR + LSR + LSR + LSR + ORA #%10110000 + CMP #HICHAR(`9')+1 + BCC PRDIGIT + ADC #'A'-'9'-2 +PRDIGIT JSR PRCHAR + PLA + AND #%00001111 + ORA #%10110000 + CMP #HICHAR(`9')+1 + BCC PRDIGIT2 + ADC #'A'-'9'-2 +PRDIGIT2 JSR PRCHAR + RTS +; +; +; +;;SHELL +; +SHELL LDA #0 + STA INBUFC + JSR PRPROMPT + + +K_LOOP JSR PRCURS + JSR RDCHAR + +K_CR CMP #CR + BNE K_BS + LDA #SPACE + JSR PRCHAR + JSR COMMAND + JMP SHELL + +K_BS CMP #BS + BNE K_CHAR + DEC INBUFC + BPL K_BS_OK + INC INBUFC + JMP K_LOOP +K_BS_OK JSR PRBS + LDA #SPACE + JSR PRCHAR + LDA #SPACE + JSR PRCHAR + JSR PRBS + JSR PRBS + JMP K_LOOP + +K_CHAR LDY INBUFC + STA INBUF,Y + INC INBUFC + BNE K_CHAR_OK + DEC INBUFC + JMP K_LOOP +K_CHAR_OK JSR PRCHAR + JMP K_LOOP +; +; +; +;;COMMAND +; +COMMAND JSR PRCR + JSR PRLF + + + + LDY #0 + CPY INBUFC + BNE PARS1 + RTS +PARS1 LDA INBUF,Y + +CMD_H CMP #HICHAR(`?') + BEQ CMD_H_IMP + JMP CMD_D +CMD_H_IMP + JSR PRCR + JSR PRLF + + JSR PRSTR + HIASCII(`COMMAND ACTION') + ASM_DATA(0) + JSR PRCR + JSR PRLF + + JSR PRSTR + HIASCII(`------------- ------------------------') + ASM_DATA(0) + JSR PRCR + JSR PRLF + + JSR PRSTR + HIASCII(`D XXXX [YYYY] DUMP MEMORY XXXX TO YYYY') + ASM_DATA(0) + JSR PRCR + JSR PRLF + + JSR PRSTR + HIASCII(`R XXXX RUN AT XXXX') + ASM_DATA(0) + JSR PRCR + JSR PRLF + + JSR PRSTR + HIASCII(`S XXXX YY SET MEMORY XXXX TO YY') + ASM_DATA(0) + JSR PRCR + JSR PRLF + + JSR PRSTR + HIASCII(`? SHOW HELP') + ASM_DATA(0) + JSR PRCR + JSR PRLF + + JSR PRSTR + HIASCII(`[ENTER ALL VALUES IN HEX]') + ASM_DATA(0) + JSR PRCR + JSR PRLF + + JSR PRCR + JSR PRLF + + RTS + +CMD_D CMP #HICHAR(`D') + BEQ CMD_D_IMP + JMP CMD_R + +CMD_D_IMP LDA #0 + STA TMP + +CMD_D_ARGS LDA #0 + STA TMPW + STA TMPW+1 + + LDX #4 +CMD_D_SP INY + CPY INBUFC + BNE CMD_D_1 + LDA TMP + BNE CMD_D_RUN + RTS +CMD_D_1 LDA INBUF,Y + CMP #SPACE + BEQ CMD_D_SP + JSR CVTHEX + DEX + BNE CMD_D_SP + LDA TMP + BNE CMD_D_RUN + INC TMP + LDA TMPW + STA ADDR + STA ADDR2 + LDA TMPW+1 + STA ADDR+1 + STA ADDR2+1 + JMP CMD_D_ARGS + +CMD_D_RUN LDA TMPW + STA ADDR2 + LDA TMPW+1 + STA ADDR2+1 + +CMD_D_ADR LDA ADDR+1 + JSR PRBYTE + LDA ADDR + JSR PRBYTE + LDA #HICHAR(`:') + JSR PRCHAR + +CMD_D_BYT LDA #SPACE + JSR PRCHAR + LDY #0 + LDA (ADDR),Y + JSR PRBYTE + INC ADDR + BNE CMD_D_NOOV + INC ADDR+1 +CMD_D_CKRO LDA ADDR + BNE CMD_D_NOOV + LDA ADDR+1 + BEQ CMD_D_END +CMD_D_NOOV LDA ADDR+1 + CMP ADDR2+1 + BNE CMD_D_NEXT + LDA ADDR + CMP ADDR2 +CMD_D_NEXT BCC CMD_D_CR + BEQ CMD_D_CR +CMD_D_END JSR PRCR + JSR PRLF + RTS +CMD_D_CR LDA ADDR + AND #%00000111 + BNE CMD_D_BYT + JSR PRCR + JSR PRLF + JMP CMD_D_ADR + +CMD_R CMP #HICHAR(`R') + BNE CMD_S + LDX #4 +CMD_R_SP INY + CPY INBUFC + BNE CMD_R_1 + RTS +CMD_R_1 LDA INBUF,Y + CMP #SPACE + BEQ CMD_R_SP + JSR CVTHEX + DEX + BNE CMD_R_SP + JMP (TMPW) + +CMD_S CMP #HICHAR(`S') + BEQ CMD_S_IMP + RTS +CMD_S_IMP LDX #4 +CMD_S_SP INY + CPY INBUFC + BNE CMD_S_1 + RTS +CMD_S_1 LDA INBUF,Y + CMP #SPACE + BEQ CMD_S_SP + JSR CVTHEX + DEX + BNE CMD_S_SP + LDA TMPW + STA ADDR + LDA TMPW+1 + STA ADDR+1 + + LDX #2 +CMD_S_SP2 INY + CPY INBUFC + BNE CMD_S_2 + RTS +CMD_S_2 LDA INBUF,Y + CMP #SPACE + BEQ CMD_S_SP2 + JSR CVTHEX + DEX + BNE CMD_S_SP2 + LDA TMPW + LDY #0 + STA (ADDR),Y + RTS +; +; +; +;;VECTORS +; +VECTORS RTS + JMP RESET + ASM_ADDR(RESET) + ASM_ADDR(RESET) diff --git a/rom/epple2sys.md5 b/rom/epple2sys.md5 new file mode 100644 index 0000000..d218293 --- /dev/null +++ b/rom/epple2sys.md5 @@ -0,0 +1 @@ +784b0b39ee03b593dc83bb7f989c7205 *epple2sys.a65 diff --git a/rom/stdin.md5 b/rom/stdin.md5 new file mode 100644 index 0000000..81e9cad --- /dev/null +++ b/rom/stdin.md5 @@ -0,0 +1 @@ +a09d60bfcbbb5cbdb3334e5ae57ddc8b *stdin.a65 diff --git a/rom/stdin.s65 b/rom/stdin.s65 new file mode 100644 index 0000000..443813d --- /dev/null +++ b/rom/stdin.s65 @@ -0,0 +1,31 @@ +YSAV1 = $35 +EOF = $FF +STKBAS = $0100 +READC = $C080 +LATCHC = $C081 +KEYIN = $FD1B +MONRTS = $FF58 + +STDIN TXA + PHA + JSR MONRTS + TSX + LDA STKBAS,X + ASL + ASL + ASL + ASL + TAX + + LDA LATCHC,X +REREAD LDA READC,X + BPL REREAD + STA YSAV1 + CMP #EOF + BNE EXIT + JSR KEYIN + STA YSAV1 +EXIT PLA + TAX + LDA YSAV1 + RTS diff --git a/rom/stdout.md5 b/rom/stdout.md5 new file mode 100644 index 0000000..902d71c --- /dev/null +++ b/rom/stdout.md5 @@ -0,0 +1 @@ +a414efb58aa5291e7888fb7a8b088c94 *stdout.a65 diff --git a/rom/stdout.s65 b/rom/stdout.s65 new file mode 100644 index 0000000..e0f661e --- /dev/null +++ b/rom/stdout.s65 @@ -0,0 +1,33 @@ +YSAV1 = $35 +STKBAS = $0100 +LATCHC = $C080 +COUT = $FDF0 +MONRTS = $FF58 + +STDOUT STY YSAV1 + PHA + TXA + PHA + + JSR MONRTS + TSX + LDA STKBAS,X + ASL + ASL + ASL + ASL + TAX + + PLA + TAY + PLA + + STA LATCHC,X + + PHA + TYA + TAX + PLA + LDY YSAV1 + + JMP COUT