mirror of
https://github.com/fumiama/c64-snake.git
synced 2026-06-12 22:40:25 +08:00
初步框架
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
.DS_Store
|
||||||
37
main.asm
Normal file
37
main.asm
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
.outfile "snake.prg"
|
||||||
|
.require "platform/c64_0.oph"
|
||||||
|
.require "platform/c64kernal.oph"
|
||||||
|
|
||||||
|
.alias go_u #1 ; 上
|
||||||
|
.alias go_d #2 ; 下
|
||||||
|
.alias go_l #4 ; 左
|
||||||
|
.alias go_r #8 ; 右
|
||||||
|
|
||||||
|
.data zp
|
||||||
|
.space d 1 ; 方向 值定义如上
|
||||||
|
.space c 1 ; 长度 最大255 最小0
|
||||||
|
.text
|
||||||
|
|
||||||
|
main:
|
||||||
|
.scope
|
||||||
|
lda #147 ;清屏
|
||||||
|
jsr chrout
|
||||||
|
|
||||||
|
rts
|
||||||
|
.scend
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
; getdir 返回一个方向到d
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
getdir:
|
||||||
|
.macro
|
||||||
|
jsr chrin
|
||||||
|
sta d
|
||||||
|
.macend
|
||||||
|
|
||||||
|
|
||||||
|
.checkpc $A000 ; text段边界
|
||||||
|
.data zp ; 零页段边界
|
||||||
|
.checkpc $80
|
||||||
|
.data
|
||||||
|
.checkpc $D000 ; data段边界
|
||||||
42
platform/README.txt
Executable file
42
platform/README.txt
Executable file
@@ -0,0 +1,42 @@
|
|||||||
|
This directory holds files likely to be of use to you in developing your own
|
||||||
|
programs. The contents of each file is summarized below.
|
||||||
|
|
||||||
|
|
||||||
|
c64_0.oph: A Commodore 64 equivalent to a modern compiler's "crt0.s" - it
|
||||||
|
contains a .PRG file header, a short BASIC program that launches
|
||||||
|
the machine language program, and a prologue and epilogue that
|
||||||
|
prepare memory for your use and then clean it up again when you
|
||||||
|
are done. Memory locations $02 through $8F on the zero page are
|
||||||
|
available for your use, and the program lives at the beginning
|
||||||
|
a contiguous block of RAM from $0800 through $CFFF. The BASIC
|
||||||
|
ROM is swapped out of memory (leaving $A000-$BFFF as RAM) for
|
||||||
|
the duration of your program. BASIC's working storage on the
|
||||||
|
zero page is backed up in the RAM underneath the KERNAL ROM
|
||||||
|
while your program runs.
|
||||||
|
|
||||||
|
c64kernal.oph: A collection of standard aliases for the KERNAL routines on the
|
||||||
|
Commodore 64. Names for these routines have been chosen to match
|
||||||
|
the Commodore 64 Programmer's Reference Guide. Additional useful
|
||||||
|
constants are defined for the character codes for color changes
|
||||||
|
and case-changing.
|
||||||
|
|
||||||
|
libbasic64.oph:A still-experimental set of macros and routines for exploiting
|
||||||
|
the software floating point routines in the Commodore 64
|
||||||
|
BASIC ROM.
|
||||||
|
|
||||||
|
c64header.oph: A much simpler Commodore 64 header that does nothing but jump
|
||||||
|
directly to your code. Useful for small programs or those that
|
||||||
|
intend to interface with BASIC.
|
||||||
|
|
||||||
|
vic20.oph: A simple header for the unexpanded VIC-20. Equivalent in
|
||||||
|
behavior to c64header.oph.
|
||||||
|
|
||||||
|
vic20x.oph: A simple header like the two above, but for expanded VIC-20.
|
||||||
|
|
||||||
|
nes.oph: A somewhat skeletal collection of aliases for the PPU registers
|
||||||
|
on the Nintendo Entertainment System. These names were chosen
|
||||||
|
to match the constant names given on the NESdev Wiki.
|
||||||
|
|
||||||
|
stella.oph: A collection of aliases for the registers of the Atari 2600.
|
||||||
|
These names were taken from the "Stella Programmer's Guide" and
|
||||||
|
are in wide use amongst developers and code analysts alike.
|
||||||
74
platform/c64_0.oph
Executable file
74
platform/c64_0.oph
Executable file
@@ -0,0 +1,74 @@
|
|||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;;
|
||||||
|
;; Commodore 64 Basic Runtime File
|
||||||
|
;;
|
||||||
|
;; Include this at the TOP of your C64 program, and it will handle
|
||||||
|
;; hiding away the BASIC ROM and data and restoring it at the end.
|
||||||
|
;;
|
||||||
|
;; You will have a contiguous block of RAM from $0800 to $CFFF, and
|
||||||
|
;; Zero Page access from $02 to $8F in the segment "zp".
|
||||||
|
|
||||||
|
.include "c64header.oph"
|
||||||
|
|
||||||
|
.data zp ; Zero Page memory segment.
|
||||||
|
.org $0002
|
||||||
|
|
||||||
|
.text
|
||||||
|
|
||||||
|
.scope
|
||||||
|
; Cache BASIC zero page underneath the KERNAL, while also
|
||||||
|
; making RAM copies of the NMI routines
|
||||||
|
ldx #$00
|
||||||
|
* lda $00, x
|
||||||
|
sta $e000, x
|
||||||
|
inx
|
||||||
|
bne -
|
||||||
|
|
||||||
|
; Swap out the BASIC ROM for RAM
|
||||||
|
lda $01
|
||||||
|
and #$fe
|
||||||
|
ora #$06
|
||||||
|
sta $01
|
||||||
|
|
||||||
|
; Run the real program
|
||||||
|
jsr _main
|
||||||
|
|
||||||
|
; Swap out KERNAL to expose cached BASIC ZP values
|
||||||
|
; Block IRQs during this period. NMIs cannot be blocked,
|
||||||
|
; but we copied enough of the processing code into the
|
||||||
|
; RAM under the KERNAL that we can disable NMI processing
|
||||||
|
; during this period
|
||||||
|
sei ; Disable IRQs
|
||||||
|
lda #$c1 ; Defang NMIs
|
||||||
|
sta $318
|
||||||
|
|
||||||
|
lda $01 ; Swap out KERNAL
|
||||||
|
and #$fd
|
||||||
|
sta $01
|
||||||
|
|
||||||
|
; Restore BASIC zero page
|
||||||
|
ldx #$8E
|
||||||
|
* lda $e001, x
|
||||||
|
sta $01, x
|
||||||
|
dex
|
||||||
|
bne -
|
||||||
|
|
||||||
|
; Restore BASIC ROM, KERNAL, and interrupts
|
||||||
|
lda $01
|
||||||
|
ora #$07
|
||||||
|
sta $01
|
||||||
|
lda #$47 ; Restore NMI vector
|
||||||
|
sta $318
|
||||||
|
cli ; Re-enable interrupts
|
||||||
|
|
||||||
|
; Back to BASIC. We do this by clearing the keyboard
|
||||||
|
; buffer and then jumping through the warm start
|
||||||
|
; vector. This will more cleanly handle case where
|
||||||
|
; the program has somehow modified BASIC's state,
|
||||||
|
; such as running through PUCRUNCH or a onefiler.
|
||||||
|
stx $c6 ; .X is zero from previous loop
|
||||||
|
jmp ($a002)
|
||||||
|
|
||||||
|
_main:
|
||||||
|
; Program follows...
|
||||||
|
.scend
|
||||||
10
platform/c64header.oph
Executable file
10
platform/c64header.oph
Executable file
@@ -0,0 +1,10 @@
|
|||||||
|
.word $0801
|
||||||
|
.org $0801
|
||||||
|
|
||||||
|
; BASIC program that just calls our machine language code
|
||||||
|
.scope
|
||||||
|
.word _next, 10 ; Next line and current line number
|
||||||
|
.byte $9e,"2061",0 ; SYS 2061
|
||||||
|
_next: .word 0 ; End of program
|
||||||
|
.scend
|
||||||
|
; Program follows...
|
||||||
67
platform/c64kernal.oph
Executable file
67
platform/c64kernal.oph
Executable file
@@ -0,0 +1,67 @@
|
|||||||
|
; KERNAL routine aliases (C64)
|
||||||
|
|
||||||
|
.alias acptr $ffa5
|
||||||
|
.alias chkin $ffc6
|
||||||
|
.alias chkout $ffc9
|
||||||
|
.alias chrin $ffcf
|
||||||
|
.alias chrout $ffd2
|
||||||
|
.alias ciout $ffa8
|
||||||
|
.alias cint $ff81
|
||||||
|
.alias clall $ffe7
|
||||||
|
.alias close $ffc3
|
||||||
|
.alias clrchn $ffcc
|
||||||
|
.alias getin $ffe4
|
||||||
|
.alias iobase $fff3
|
||||||
|
.alias ioinit $ff84
|
||||||
|
.alias listen $ffb1
|
||||||
|
.alias load $ffd5
|
||||||
|
.alias membot $ff9c
|
||||||
|
.alias memtop $ff99
|
||||||
|
.alias open $ffc0
|
||||||
|
.alias plot $fff0
|
||||||
|
.alias ramtas $ff87
|
||||||
|
.alias rdtim $ffde
|
||||||
|
.alias readst $ffb7
|
||||||
|
.alias restor $ff8a
|
||||||
|
.alias save $ffd8
|
||||||
|
.alias scnkey $ff9f
|
||||||
|
.alias screen $ffed
|
||||||
|
.alias second $ff93
|
||||||
|
.alias setlfs $ffba
|
||||||
|
.alias setmsg $ff90
|
||||||
|
.alias setnam $ffbd
|
||||||
|
.alias settim $ffdb
|
||||||
|
.alias settmo $ffa2
|
||||||
|
.alias stop $ffe1
|
||||||
|
.alias talk $ffb4
|
||||||
|
.alias tksa $ff96
|
||||||
|
.alias udtim $ffea
|
||||||
|
.alias unlsn $ffae
|
||||||
|
.alias untlk $ffab
|
||||||
|
.alias vector $ff8d
|
||||||
|
|
||||||
|
; Character codes for the colors.
|
||||||
|
.alias color'0 144
|
||||||
|
.alias color'1 5
|
||||||
|
.alias color'2 28
|
||||||
|
.alias color'3 159
|
||||||
|
.alias color'4 156
|
||||||
|
.alias color'5 30
|
||||||
|
.alias color'6 31
|
||||||
|
.alias color'7 158
|
||||||
|
.alias color'8 129
|
||||||
|
.alias color'9 149
|
||||||
|
.alias color'10 150
|
||||||
|
.alias color'11 151
|
||||||
|
.alias color'12 152
|
||||||
|
.alias color'13 153
|
||||||
|
.alias color'14 154
|
||||||
|
.alias color'15 155
|
||||||
|
|
||||||
|
; ...and reverse video
|
||||||
|
.alias reverse'on 18
|
||||||
|
.alias reverse'off 146
|
||||||
|
|
||||||
|
; ...and character set
|
||||||
|
.alias upper'case 142
|
||||||
|
.alias lower'case 14
|
||||||
287
platform/libbasic64.oph
Executable file
287
platform/libbasic64.oph
Executable file
@@ -0,0 +1,287 @@
|
|||||||
|
;;; LIBBASIC64.OPH
|
||||||
|
|
||||||
|
;;; This is a collection of routines inside the BASIC ROM that can
|
||||||
|
;;; be repurposed to do floating-point math inside your machine
|
||||||
|
;;; language programs. It is currently VERY EXPERIMENTAL. The documentation
|
||||||
|
;;; available for this is spotty at best and disassembly confirms that
|
||||||
|
;;; a lot of hidden invariants may lurk.
|
||||||
|
|
||||||
|
;;; BASIC function equivalents. These operate on FAC1 and are pretty
|
||||||
|
;;; clean overall. They take their input in FAC1 and put their output
|
||||||
|
;;; there too. While it is not *guaranteed* it is probably best to
|
||||||
|
;;; assume that these functions trash the value in FAC2.
|
||||||
|
.alias abs_fac1 $bc58
|
||||||
|
.alias atn_fac1 $e30e
|
||||||
|
.alias cos_fac1 $e264
|
||||||
|
.alias exp_fac1 $bfed
|
||||||
|
.alias int_fac1 $bccc
|
||||||
|
.alias log_fac1 $b9ea
|
||||||
|
.alias rnd_fac1 $e097
|
||||||
|
.alias sgn_fac1 $bc39
|
||||||
|
.alias sin_fac1 $e26b
|
||||||
|
.alias tan_fac1 $e2b4
|
||||||
|
|
||||||
|
;;; Getting useful information into the FACs
|
||||||
|
|
||||||
|
;; Treat the accumulator as a signed byte, load that value
|
||||||
|
;; into FAC1
|
||||||
|
.alias ld_fac1_a $bc3c
|
||||||
|
|
||||||
|
;; Load the signed 16-bit value with A as the *high* byte and
|
||||||
|
;; Y as the *low* byte into FAC1. This is backwards from pretty
|
||||||
|
;; much everything else.
|
||||||
|
.alias ld_fac1_s16 $b391
|
||||||
|
|
||||||
|
;; Load a 5-byte value from memory into FAC1.
|
||||||
|
.alias ld_fac1_mem $bba2
|
||||||
|
|
||||||
|
;; Copy FAC2 into FAC1.
|
||||||
|
.alias ld_fac1_fac2 $bbfc
|
||||||
|
|
||||||
|
;; Translate FAC1 into a string that is at $0100.
|
||||||
|
.alias fac1_to_string $bddd
|
||||||
|
|
||||||
|
;; Convert FAC1 into a 32-bit *big-endian* signed integer at
|
||||||
|
;; $62-$65 (where the mantissa usually goes in FAC1).
|
||||||
|
.alias fac1_to_s32 $bc9b
|
||||||
|
|
||||||
|
;; Store out FAC1 to $57-$5B, converting it back into the five-byte
|
||||||
|
;; floating-point format.
|
||||||
|
.alias fac1_to_57 $bbca
|
||||||
|
|
||||||
|
;; Do the same but at $5c-$60.
|
||||||
|
.alias fac1_to_5c $bbc7
|
||||||
|
|
||||||
|
;; Load a 5-byte value into FAC2.
|
||||||
|
.alias ld_fac2_mem $ba8c
|
||||||
|
|
||||||
|
;; Copy FAC1 to FAC2. FAC1 has some extra precision that is
|
||||||
|
;; rounded away when you do this.
|
||||||
|
.alias ld_fac2_fac1 $bc0c
|
||||||
|
|
||||||
|
;;; Comparison operator.
|
||||||
|
;; Like sgn_fac1, but returns the -1/0/1 in the accumulator as
|
||||||
|
;; an integer.
|
||||||
|
.alias fac1_sign $bc2b
|
||||||
|
|
||||||
|
;;; FP operators. These are all FAC2 OP FAC1 with the result in FAC1.
|
||||||
|
;;; PRECONDITIONS: All of these operations but AND and OR require you to
|
||||||
|
;;; have the contents of $61 in the accumulator. calling one of the ld_fac*
|
||||||
|
;;; routines will do that for you automatically. f_add_op also requires that
|
||||||
|
;;; $6F be set properly; only ld_fac2_mem does this.
|
||||||
|
.alias f_add_op $b86a
|
||||||
|
.alias f_subtract_op $b853
|
||||||
|
.alias f_multiply_op $ba2b
|
||||||
|
.alias f_divide_op $bb12
|
||||||
|
.alias f_pow_op $bf7b
|
||||||
|
.alias f_and_op $afe9
|
||||||
|
.alias f_or_op $afe6
|
||||||
|
|
||||||
|
;;; Memory-based FP operations. All are MEM OP FAC1. These are usually safer
|
||||||
|
;;; than the *_op routines.
|
||||||
|
.alias f_add_mem $b867
|
||||||
|
.alias f_subtract_mem $b850
|
||||||
|
.alias f_multiply_mem $ba28
|
||||||
|
.alias f_divide_mem $bb0f
|
||||||
|
|
||||||
|
;;; Useful FP constants that live in the ROM. It's plausible that ld_fac1_a
|
||||||
|
;;; or ld_fac1_s16 would be more convenient than ld_fac1_mem with f_1 or f_10,
|
||||||
|
;;; but when doing memory-based generic stuff, these will still be useful.
|
||||||
|
.alias f_0_5 $bf11 ; 0.5
|
||||||
|
.alias f_1 $b9bc ; 1.0
|
||||||
|
.alias f_pi $aea8 ; 3.1415926
|
||||||
|
.alias f_10 $baf9 ; 10.0
|
||||||
|
|
||||||
|
;;; Macros for using these routines more safely.
|
||||||
|
|
||||||
|
;; Copy 5-byte values around in memory without touching the FACs.
|
||||||
|
.macro f_move
|
||||||
|
ldx #$00
|
||||||
|
_fmvlp: lda _2,x
|
||||||
|
sta _1,x
|
||||||
|
inx
|
||||||
|
cpx #$05
|
||||||
|
bne _fmvlp
|
||||||
|
.macend
|
||||||
|
|
||||||
|
;;; These next few macros really exist just to save us the trouble of loading
|
||||||
|
;;; addresses into registers
|
||||||
|
.macro print_str
|
||||||
|
lda #<_1
|
||||||
|
ldy #>_1
|
||||||
|
jsr strout
|
||||||
|
.macend
|
||||||
|
|
||||||
|
.macro ld_fac1
|
||||||
|
lda #<_1
|
||||||
|
ldy #>_1
|
||||||
|
jsr ld_fac1_mem
|
||||||
|
.macend
|
||||||
|
|
||||||
|
.macro ld_fac2
|
||||||
|
lda #<_1
|
||||||
|
ldy #>_1
|
||||||
|
jsr ld_fac2_mem
|
||||||
|
.macend
|
||||||
|
|
||||||
|
.macro st_fac1
|
||||||
|
lda #<_1
|
||||||
|
ldy #>_1
|
||||||
|
jsr fac1_to_mem
|
||||||
|
.macend
|
||||||
|
|
||||||
|
.macro fp_load
|
||||||
|
`ld_fac1 _1
|
||||||
|
.macend
|
||||||
|
|
||||||
|
.macro fp_store
|
||||||
|
`st_fac1 _1
|
||||||
|
.macend
|
||||||
|
|
||||||
|
.macro fp_print
|
||||||
|
`ld_fac1 _1
|
||||||
|
jsr fac1out
|
||||||
|
.macend
|
||||||
|
|
||||||
|
.macro fp_read
|
||||||
|
lda #<_1
|
||||||
|
ldy #>_1
|
||||||
|
jsr ld_fac1_string
|
||||||
|
.macend
|
||||||
|
|
||||||
|
;;; Arithmetic macros. These serve mainly to make the operations work left-
|
||||||
|
;;; to-right as one generally would prefer. They also guarantee the obscure
|
||||||
|
;;; preconditions hold.
|
||||||
|
|
||||||
|
.macro fp_add
|
||||||
|
lda #<_1
|
||||||
|
ldy #>_1
|
||||||
|
jsr f_add_mem
|
||||||
|
.macend
|
||||||
|
|
||||||
|
.macro fp_subtract
|
||||||
|
jsr ld_fac2_fac1
|
||||||
|
`ld_fac1 _1
|
||||||
|
jsr f_subtract_op
|
||||||
|
.macend
|
||||||
|
|
||||||
|
.macro fp_multiply
|
||||||
|
lda #<_1
|
||||||
|
ldy #>_1
|
||||||
|
jsr f_multiply_mem
|
||||||
|
.macend
|
||||||
|
|
||||||
|
.macro fp_divide
|
||||||
|
jsr ld_fac2_fac1
|
||||||
|
`ld_fac1 _1
|
||||||
|
jsr f_divide_op
|
||||||
|
.macend
|
||||||
|
|
||||||
|
.macro fp_pow
|
||||||
|
jsr ld_fac2_fac1
|
||||||
|
`ld_fac1 _1
|
||||||
|
jsr f_pow_op
|
||||||
|
.macend
|
||||||
|
|
||||||
|
.macro fp_and
|
||||||
|
`ld_fac2 _1
|
||||||
|
jsr f_and_op
|
||||||
|
.macend
|
||||||
|
|
||||||
|
.macro fp_or
|
||||||
|
`ld_fac2 _1
|
||||||
|
jsr f_or_op
|
||||||
|
.macend
|
||||||
|
|
||||||
|
;;; Utility routine for converting the system clock to a floating point
|
||||||
|
;;; value.
|
||||||
|
ld_fac1_ti:
|
||||||
|
jsr $ffde ; RDTIM
|
||||||
|
sty $63
|
||||||
|
stx $64
|
||||||
|
sta $65
|
||||||
|
;; Once the requirements on .Y and $68 are better
|
||||||
|
;; understood, this might be exportable as
|
||||||
|
;; ld_fac1_s32, but there are still some dragons
|
||||||
|
;; lurking
|
||||||
|
ldy #$00 ; Clear out intermediary values
|
||||||
|
sta $62
|
||||||
|
sta $68
|
||||||
|
jmp $bcd5
|
||||||
|
|
||||||
|
;;; FAC1 can only be stored out to two locations. We'd prefer to be able
|
||||||
|
;;; to store anywhere. This routine is a support routine that allows that.
|
||||||
|
;;; It will normally only be called by the fp_store macro.
|
||||||
|
fac1_to_mem:
|
||||||
|
sta $fd
|
||||||
|
sty $fe
|
||||||
|
jsr fac1_to_5c
|
||||||
|
ldy #$00
|
||||||
|
* lda $5c,y
|
||||||
|
sta ($fd),y
|
||||||
|
iny
|
||||||
|
cpy #$05
|
||||||
|
bne -
|
||||||
|
rts
|
||||||
|
|
||||||
|
;;; The VAL function uses the CHRGET routine copied to the zero page to read
|
||||||
|
;;; strings in. That's a fragile operation if we don't want to confuse BASIC
|
||||||
|
;;; later, so this routine juggles the values we need to preserve. It will
|
||||||
|
;;; normally only be called by the fp_read macro.
|
||||||
|
ld_fac1_string:
|
||||||
|
ldx $7a
|
||||||
|
sta $7a
|
||||||
|
txa
|
||||||
|
pha
|
||||||
|
lda $7b
|
||||||
|
pha
|
||||||
|
sty $7b
|
||||||
|
jsr $79
|
||||||
|
jsr $bcf3
|
||||||
|
pla
|
||||||
|
sta $7b
|
||||||
|
pla
|
||||||
|
sta $7a
|
||||||
|
rts
|
||||||
|
|
||||||
|
;;; Print out the contents of FAC1.
|
||||||
|
fac1out:
|
||||||
|
ldy #$00 ; Clean out overflow
|
||||||
|
sty $68
|
||||||
|
sty $70
|
||||||
|
jsr fac1_to_string
|
||||||
|
ldy #$01
|
||||||
|
;; Skip the first character if it's not "-"
|
||||||
|
lda $100
|
||||||
|
sec
|
||||||
|
sbc #$2d
|
||||||
|
beq strout
|
||||||
|
lda #$01
|
||||||
|
;; Fall through to strout
|
||||||
|
|
||||||
|
;;; The BASIC ROM already has a STROUT routine - $ab1e - but
|
||||||
|
;;; it makes use of BASIC's own temporary string handling. We
|
||||||
|
;;; don't want it to ever touch its notion of temporary strings
|
||||||
|
;;; here, so we provide our own short routine to do this.
|
||||||
|
strout: sta $fd
|
||||||
|
sty $fe
|
||||||
|
ldy #$00
|
||||||
|
* lda ($fd),y
|
||||||
|
beq +
|
||||||
|
jsr $ffd2 ; CHROUT
|
||||||
|
iny
|
||||||
|
bne -
|
||||||
|
* rts
|
||||||
|
|
||||||
|
;;; Execute RND(-TI), seeding the random number generator the traditional way.
|
||||||
|
randomize:
|
||||||
|
jsr ld_fac1_ti
|
||||||
|
lda #$ff
|
||||||
|
sta $66 ; Force sign negative
|
||||||
|
jmp rnd_fac1 ; RND(-TI)
|
||||||
|
|
||||||
|
|
||||||
|
;;; Return RND(1), a fresh random number between 0 and 1.
|
||||||
|
rnd: lda #$01
|
||||||
|
jsr ld_fac1_a
|
||||||
|
jmp rnd_fac1
|
||||||
15
platform/nes.oph
Executable file
15
platform/nes.oph
Executable file
@@ -0,0 +1,15 @@
|
|||||||
|
; NES-related headers. Unlike the C64 and Stella developers, there is
|
||||||
|
; no standard nomenclature for these registers. It's not uncommon to
|
||||||
|
; see them hardcoded.
|
||||||
|
|
||||||
|
; PPU registers have reasonably standard names, at least.
|
||||||
|
|
||||||
|
.alias PPUCTRL $2000 ; PPU Control Register #1
|
||||||
|
.alias PPUMASK $2001 ; PPU Control Register #2
|
||||||
|
.alias PPUSTATUS $2002 ; PPU Status Register
|
||||||
|
.alias OAMADDR $2003 ; SPR-RAM Address Register
|
||||||
|
.alias OAMDATA $2004 ; SPR-RAM I/O Register
|
||||||
|
.alias PPUSCROLL $2005 ; VRAM Address Register #1 (Panning control)
|
||||||
|
.alias PPUADDR $2006 ; VRAM Address Register #2 (Direct Address control)
|
||||||
|
.alias PPUDATA $2007 ; VRAM I/O Register
|
||||||
|
.alias OAMDMA $4014 ; Sprite DMA Register
|
||||||
127
platform/stella.oph
Executable file
127
platform/stella.oph
Executable file
@@ -0,0 +1,127 @@
|
|||||||
|
; Register mnemonics for the Atari 2600 VCS
|
||||||
|
;
|
||||||
|
; Taken from the "Stella Programming Guide", at
|
||||||
|
; http://www.alienbill.com/2600/101/docs/stella.html
|
||||||
|
|
||||||
|
; Writable TIA addresses
|
||||||
|
|
||||||
|
.alias VSYNC $00 ; vertical sync set-clear
|
||||||
|
.alias VBLANK $01 ; vertical blank set-clear
|
||||||
|
.alias WSYNC $02 ; wait for leading edge of horizontal blank
|
||||||
|
.alias RSYNC $03 ; reset horizontal sync counter
|
||||||
|
.alias NUSIZ0 $04 ; number-size player-missile 0
|
||||||
|
.alias NUSIZ1 $05 ; number-size player-missile 1
|
||||||
|
.alias COLUP0 $06 ; color-lum player 0
|
||||||
|
.alias COLUP1 $07 ; color-lum player 1
|
||||||
|
.alias COLUPF $08 ; color-lum playfield
|
||||||
|
.alias COLUBK $09 ; color-lum background
|
||||||
|
.alias CTRLPF $0A ; control playfield ball size and collisions
|
||||||
|
.alias REFP0 $0B ; reflect player 0
|
||||||
|
.alias REFP1 $0C ; reflect player 1
|
||||||
|
.alias PF0 $0D ; playfield register byte 0
|
||||||
|
.alias PF1 $0E ; playfield register byte 1
|
||||||
|
.alias PF2 $0F ; playfield register byte 2
|
||||||
|
.alias RESP0 $10 ; reset player 0
|
||||||
|
.alias RESP1 $11 ; reset player 1
|
||||||
|
.alias RESM0 $12 ; reset missile 0
|
||||||
|
.alias RESM1 $13 ; reset missile 1
|
||||||
|
.alias RESBL $14 ; reset ball
|
||||||
|
.alias AUDC0 $15 ; audio control 0
|
||||||
|
.alias AUDC1 $16 ; audio control 1
|
||||||
|
.alias AUDF0 $17 ; audio frequency 0
|
||||||
|
.alias AUDF1 $18 ; audio frequency 1
|
||||||
|
.alias AUDV0 $19 ; audio volume 0
|
||||||
|
.alias AUDV1 $1A ; audio volume 1
|
||||||
|
.alias GRP0 $1B ; Graphics player 0
|
||||||
|
.alias GRP1 $1C ; Graphics player 1
|
||||||
|
.alias ENAM0 $1D ; Graphics enable missile 0
|
||||||
|
.alias ENAM1 $1E ; Graphics enable missile 1
|
||||||
|
.alias ENABL $1F ; Graphics enable ball
|
||||||
|
.alias HMP0 $20 ; horizontal motion player 0
|
||||||
|
.alias HMP1 $21 ; horizontal motion player 1
|
||||||
|
.alias HMM0 $22 ; horizontal motion missile 0
|
||||||
|
.alias HMM1 $23 ; horizontal motion missile 1
|
||||||
|
.alias HMBL $24 ; horizontal motion ball
|
||||||
|
.alias VDELP0 $25 ; vertical delay player 0
|
||||||
|
.alias VDELP1 $26 ; vertical delay player 1
|
||||||
|
.alias VDELBL $27 ; vertical delay ball
|
||||||
|
.alias RESMP0 $28 ; reset missile 0 to player 0
|
||||||
|
.alias RESMP1 $29 ; reset missile 1 to player 1
|
||||||
|
.alias HMOVE $2A ; apply horizontal motion
|
||||||
|
.alias HMCLR $2B ; clear horizontal motion registers
|
||||||
|
.alias CXCLR $2C ; clear collision latches
|
||||||
|
|
||||||
|
; Readable TIA addresses
|
||||||
|
|
||||||
|
.alias CXM0P $00 ; read collision missile 0 players
|
||||||
|
.alias CXM1P $01 ; read collision missile 1 players
|
||||||
|
.alias CXP0FB $02 ; read collision player 0 playfield/ball
|
||||||
|
.alias CXP1FB $03 ; read collision player 1 playfield/ball
|
||||||
|
.alias CXM0FB $04 ; read collision missile 0 playfield/ball
|
||||||
|
.alias CXM1FB $05 ; read collision missile 1 playfield/ball
|
||||||
|
.alias CXBLPF $06 ; read collision ball playfield
|
||||||
|
.alias CXPPMM $07 ; read collision player/player missile/missile
|
||||||
|
.alias INPT0 $08 ; read pot port
|
||||||
|
.alias INPT1 $09 ; read pot port
|
||||||
|
.alias INPT2 $0A ; read pot port
|
||||||
|
.alias INPT3 $0B ; read pot port
|
||||||
|
.alias INPT4 $0C ; read input
|
||||||
|
.alias INPT5 $0D ; read input
|
||||||
|
|
||||||
|
; PIA addresses
|
||||||
|
|
||||||
|
.alias SWCHA $280 ; Port A data register (read/write)
|
||||||
|
.alias SWACNT $281 ; Port A data direction register (0=input, 1=output)
|
||||||
|
.alias SWCHB $282 ; Port B - console switches (read-only)
|
||||||
|
.alias SWBCNT $283 ; Port B data direction register (hardwired to 0)
|
||||||
|
.alias INTIM $284 ; Timer output (read only)
|
||||||
|
.alias TIM1T $294 ; Set 1-clock interval (838 nsec/interval)
|
||||||
|
.alias TIM8T $295 ; Set 8-clock interval (6.7 usec/interval)
|
||||||
|
.alias TIM64T $296 ; Set 64-clock interval (53.6 usec/interval
|
||||||
|
.alias T1024T $297 ; Set 1025-clock interval (858.2 usec/interval)
|
||||||
|
|
||||||
|
; These macros are adapted from DASM's old macro.h. Credit and description are
|
||||||
|
; replicated from there.
|
||||||
|
|
||||||
|
;-------------------------------------------------------------------------------
|
||||||
|
; VERTICAL_SYNC
|
||||||
|
; Original author: Manuel Polik
|
||||||
|
; Inserts the code required for a proper 3 scanline
|
||||||
|
; vertical sync sequence
|
||||||
|
;
|
||||||
|
; Note: Alters the accumulator
|
||||||
|
;
|
||||||
|
; IN:
|
||||||
|
; OUT: A = 1
|
||||||
|
|
||||||
|
.macro vertical'sync
|
||||||
|
lda #$02
|
||||||
|
sta WSYNC
|
||||||
|
sta VSYNC
|
||||||
|
sta WSYNC
|
||||||
|
sta WSYNC
|
||||||
|
lsr
|
||||||
|
sta WSYNC
|
||||||
|
sta VSYNC
|
||||||
|
.macend
|
||||||
|
|
||||||
|
;-------------------------------------------------------------------------------
|
||||||
|
; CLEAN_START
|
||||||
|
; Original author: Andrew Davie
|
||||||
|
; Standardised start-up code, clears stack, all TIA registers and RAM to 0
|
||||||
|
; Sets stack pointer to $FF, and all registers to 0
|
||||||
|
; Sets decimal mode off, sets interrupt flag (kind of un-necessary)
|
||||||
|
; Use as very first section of code on boot (ie: at reset)
|
||||||
|
; Code written to minimise total ROM usage - uses weird 6502 knowledge :)
|
||||||
|
.macro clean'start
|
||||||
|
sei
|
||||||
|
cld
|
||||||
|
ldx #$00
|
||||||
|
txa
|
||||||
|
tay
|
||||||
|
_clear'stack:
|
||||||
|
dex
|
||||||
|
txs
|
||||||
|
pha
|
||||||
|
bne _clear'stack
|
||||||
|
.macend
|
||||||
5
platform/vic20.oph
Executable file
5
platform/vic20.oph
Executable file
@@ -0,0 +1,5 @@
|
|||||||
|
;;; Minimal header file for unexpanded VIC-20.
|
||||||
|
;;; It translates to 10 SYS4109.
|
||||||
|
.word $1001
|
||||||
|
.org $1001
|
||||||
|
.byte $0b,$10,$0a,$00,$9e,$34,$31,$30,$39,$00,$00,$00
|
||||||
5
platform/vic20x.oph
Executable file
5
platform/vic20x.oph
Executable file
@@ -0,0 +1,5 @@
|
|||||||
|
;;; Minimal header file for expanded VIC-20.
|
||||||
|
;;; It translates to 10 SYS4621.
|
||||||
|
.word $1201
|
||||||
|
.org $1201
|
||||||
|
.byte $0b,$12,$0a,$00,$9e,$34,$36,$32,$31,$00,$00,$00
|
||||||
33
printinput.asm
Normal file
33
printinput.asm
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
.outfile "printinput.prg"
|
||||||
|
.require "platform/c64header.oph"
|
||||||
|
.require "platform/c64kernal.oph"
|
||||||
|
|
||||||
|
.data
|
||||||
|
.org $C000
|
||||||
|
.space _na 1 ; a的临时存放处
|
||||||
|
|
||||||
|
.text
|
||||||
|
main:
|
||||||
|
* jsr getin
|
||||||
|
beq skip
|
||||||
|
jsr printbyte
|
||||||
|
lda #13 ; 换行
|
||||||
|
jsr chrout
|
||||||
|
skip:
|
||||||
|
jmp -
|
||||||
|
|
||||||
|
printbyte:
|
||||||
|
sta _na
|
||||||
|
txa
|
||||||
|
pha
|
||||||
|
ldx #7 ; 打印8bit
|
||||||
|
* lda #$30 ; a = '0'
|
||||||
|
asl _na ; 左移一位,溢出到c
|
||||||
|
bcc + ; if(c == 0) goto 下一个星号
|
||||||
|
adc #0 ; else a = a + c + 0
|
||||||
|
* jsr chrout ; putchar(a)
|
||||||
|
dex ; x--
|
||||||
|
bne -- ; if(x != 0) goto 上两个星号
|
||||||
|
pla
|
||||||
|
tax
|
||||||
|
rts
|
||||||
BIN
printinput.prg
Normal file
BIN
printinput.prg
Normal file
Binary file not shown.
Reference in New Issue
Block a user