mirror of
https://github.com/fumiama/c64-snake.git
synced 2026-06-05 00:32:39 +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