Curt Vendel Posted September 11, 2005 Share Posted September 11, 2005 .title VCS Skeleton Program .enable ama .asect ;absolute addressing .radix 16 ;default base .LIST MEB ;DISPLAY ALL OF ANY MACROS ; romstr = 0f000 ;rom start addr ; SKLTON.MAC ; copyright Atari, 1982 .nlist .sbttl Stella Hardware Regs .list .page ; * ; ** ;********** ********************************** ;*********** * TIA and PIA Register Addresses * ;********** ********************************** ; ** ; * ; ; TIA Addresses vsync = 00 ;bit 1 vertical sync set-clr 1=>start vblank = 01 ;bit 76 1 vblank set-clr, port ctl (inpt0-5) wsync = 02 ;strobe wait for horiz blank rsync = 03 ;strobe reset horiz sync counter nusiz0 = 04 ;bits 54 210 number-size player/missile 0 nusiz1 = 05 ;bits 54 210 number-size player/missile 1 colup0 = 06 ;bits 7654321 color(4)-lum(3) player 0 colup1 = 07 ;bits 7654321 color(4)-lum(3) player 1 colupf = 08 ;bits 7654321 color(4)-lum(3) playfield colubk = 09 ;bits 7654321 color(4)-lum(3) background ctrlpf = 0a ;bits 54 210 playfield control & ball refp0 = 0b ;bit 3 reflect player 0. 1=>reflect refp1 = 0c ;bit 3 reflect player 1 pf0 = 0d ;bits 7654 playfield reg byte 0 (reversed) pf1 = 0e ;bits all playfield reg byte 1 pf2 = 0f ;bits all playfield reg byte 2 (reversed) resp0 = 10 ;strobe reset player 0 resp1 = 11 ;strobe reset player 1 resm0 = 12 ;strobe reset missile 0 resm1 = 13 ;strobe reset missile 1 resbl = 14 ;strobe reset ball audc0 = 15 ;bits 3210 audio control 0 audc1 = 16 ;bits 3210 audio control 1 audf0 = 17 ;bits 3210 audio frequency 0 audf1 = 18 ;bits 3210 audio frequency 1 audv0 = 19 ;bits 3210 audio volume 0 audv1 = 1a ;bits 3210 audio volume 1 grp0 = 1b ;bits all graphics for player 0 grp1 = 1c ;bits all graphics for player 1 enam0 = 1d ;bit 1 enable missile 0. 1=> enable enam1 = 1e ;bit 1 enable missile 1 enabl = 1f ;bit 1 enable ball hmp0 = 20 ;bits 7654 horiz motion player 0. 0-7 => left hmp1 = 21 ;bits 7654 horiz motion player 1. f-8 => right hmm0 = 22 ;bits 7654 horiz motion missile 0 hmm1 = 23 ;bits 7654 horiz motion missile 1 hmbl = 24 ;bits 7654 horiz motion ball vdelp0 = 25 ;bit 0 vertical delay player 0. 1=> vdel on vdelp1 = 26 ;bit 0 vertical delay player 1 vdelbl = 27 ;bit 0 vertical delay ball resmp0 = 28 ;bit 1 reset missile to player 0 resmp1 = 29 ;bit 1 reset missile to player 1 hmove = 2a ;strobe act on horiz motion hmclr = 2b ;strobe clear all hm registers cxclr = 2c ;strobe clear collision latches ; ; Read Addresses - bits 7 & 6 only cxm0p = 30 ;m0*p1 m0*p0 cxm1p = 31 ;m1*p0 m1*p1 cxp0fb = 32 ;p0*pf p0*bl cxp1fb = 33 ;p1*pf p1*bl cxm0fb = 34 ;m0*pf m0*bl cxm1fb = 35 ;m1*pf m1*bl cxblpf = 36 ;bl*pf cxppmm = 37 ;p0*p1 m0*m1 inpt0 = 38 ;pot 0. bit7=1 => pot cap is charged inpt1 = 39 ;pot 1 inpt2 = 3a ;pot 2 inpt3 = 3b ;pot 3 inpt4 = 3c ;joystick 0 button. b7=0 => button pressed inpt5 = 3d ;joystick 1 button ; ; PIA and Timer (6532) Locations swcha = 280 ;p0,p1 sticks (rldu), pot triggers, kbd, driving ctl ctlswa = 281 ;swcha i/o control 1=output swchb = 282 ;console switches (read only) p1b,p0b,x,x,b/w,x,select, reset ctlswb = 283 ;unused intim = 284 ;interval timer input =>timer up tim1t = 294 ;timer output: 1 mc/tick (.838 microsec) tim8t = 295 ;8 machine cycles/tick tim64t = 296 ;64 mc's/tick t1024t = 297 ;1024 machine cycles/tick (858.2 microseconds) .nlist .sbttl Equates .list .page ; * ; ** ;********** ******************** ;*********** * Assorted Equates * ;********** ******************** ; ** ; * gscon = 45. ;game select timer initial value ovrcon = 25 ;overscan timer initial value vblcon = 2b ;vblank timer initial value gmax = 03 ;highest game # +1 .nlist .sbttl Ram Variables .list .page ; * ; ** ;********** ***************************** ;*********** * Variables (ram page zero) * ;********** ***************************** ; ** ; * .=80 tcol: .=.+1 ;top score color bcol: .=.+1 ;bottom score color gflg1: .=.+1 ;game status bits ;80 1= game is in play ;40 1= bonzo (easy) game ;20 1= one-player game ;10 1= select mode ;08 1= color-shifting attract mode ;04 not used yet ;02 not used yet ;01 not used yet gamno: .=.+1 ;game number (decimal) gstim: .=.+1 ;game select timer tscr: .=.+2 ;top player's score bscr: .=.+2 ;bottom player's score rand: .=.+1 ;"random" number seed/last number rndind: .=.+1 ;"random" number index frame: .=.+1 ;frame counter hfram: .=.+1 ;hi byte of frame counter atim: .=.+1 ;attract timer atmask: .=.+1 ;attract lum mask t0: .=.+1 ;temporary variables t1: .=.+1 .NLIST .SBTTL MACROS .LIST .PAGE ; * ; ** ;********** ****************** ;*********** * MACROS * ;********** ****************** ; ** ; * ; ; PALIGN WILL AUTOMATICALLY ALIGN FOLLOWING CODE WITH A PAGE VOUNDARY. ; IT WILL USUALLY BE USED AT THE TOP OF TABLES, SO THAT A TABLE WON'T ; CROSS A BOUNDARY AND FUCK UP A KERNEL. ; .MACRO PALIGN .=<.+0FF>&0FF00 .ENDM ; ; ; .INTSET ENABLES INTERRUPTS WHEN IN A RAM VERSION, BUT ALLOWS INTERRUPTS ; TO BE DISABLED IN THE ROMMED VERSION, BY THE USE OF THE TERM ZZZROM. ; AS LONG AS ZZZROM IS UNDEFINED, INTERRUPTS WILL BE ENABLED, AND A ; PROGRAM CAN BE HALTED BY CONTROL-C. BEFORE ROMMING THE PROGRAM, MERELY ; INSERT A DEFINITION FOR ZZZROM, SUCH AS ZZZROM = 1. ; .MACRO .INTSET .IF NDF,ZZZROM CLI .IFF SEI .ENDC .ENDM ; ; ; LINE WILL DECREMENT THE LINE COUNT, IF REQUESTED, WILL SET UP A ; PLAYER, IF REQUESTED, AND WILL SET UP A MISSILE OR BALL DURING A ; KERNEL LINE. THE LINE COUNT MAY BE DECREMENTED BY ANY VALUE, SET ; AS ARGUMENT A1. IF A1 IS ZERO, THAT PART OF THE CODE IS NOT ; ASSEMBLED. ARGUMENT A2 SPECIFIES THE VERTICAL POSITION OF THE ; PLAYER, BY NAME OF RAM POSITION WHERE THAT VALUE IS LOCATED. IF ; THAT ARGUMENT IS SET TO ZERO, THE CODE FOR HANDLING THE PLAYER ; IS LEFT OUT. ; ; THERE ARE EIGHT ARGUMENTS, BUT A8 MUST NOT BE SPECIFIED WHEN ; INVOKING THE MACRO. IT IS A DUMMY FOR CREATING A JUMP ADDRESS. ; THE OTHERS MUST BE USED, AT LEAST TO THE POINT OF PUTTING IN A ; COMMA AS A PLACE-HOLDER. THE ARGUMENTS AND THEIR MEANINGS ARE: ; ; A1 LINE COUNT DECREMENT AMOUNT (USUALLY 1 OR 2; IF 0, CODE IS ; SKIPPED) ; A2 NAME OF RAM LOCATION FOR VERT. POSITION OF A PLAYER. IF 0, ; CODE FOR PLAYER SETUP IS LEFT OUT ; A3 PLAYER'S HEIGHT ; A4 NAME OF PLAYER'S GRAPHICS TABLE ; A5 NAME OF A TEMPORARY STORAGE LOCATION FOR THAT PLAYER'S GRAPHICS ; A6 NAME OF LOCATION FOR MISSILE'S OR BALL'S VERTICAL POSITION ; A7 HEIGHT OF MISSILE OR BALL ; A8 DUMMY JUMP ADDRESS -- DON'T PUT A VALUE IN FOR THIS ARGUMENT!!! ; ; AN EXAMPLE FOR THE FIRST LINE OF A DOUBLE-LINE KERNEL MIGHT BE: ; ; LINE 2,VP0,8,P0TAB,GP0,VM0,14. ; ; THE SECOND LINE OF THE KERNEL MIGHT LOOK LIKE: ; ; LINE 0,VP1,10.,P1TAB,GP1,VBL,4 ; ; A LINE WITH NO PLAYER MIGHT BE CALLED AS FOLLOWS: ; ; LINE 1,0,,,,VM1,6 ; ; NOTE THAT ALL NUMERIC VALUES ARE IN HEX, AND DECIMAL VALUES MUST END ; WITH A DOT. THIS MACRO USES THE ACCUMULATOR AND Y REGISTER, BUT LEAVES ; THE X REGISTER FREE. ; ; THE RESULTS OF THIS MACRO MUST BE INVOKED AT THE START OF THE NEXT LINE, ; PROBABLY IMMEDIATELY AFTER AT STA WSYNC, OR AFTER STA WSYNC, STA HMOVE. ; IF THE PLAYER GRAPHICS HAS BEEN STORED IN GP1, FOR INSTANCE, AND YOU ; ARE ABOUT TO PUT UP THAT PLAYER AND THE BALL, AS IN THE SECOND EXAMPLE ; ABOVE, YOU WOULD PUT IN CODE: ; STY ENABL ; LDY GP1 ; STY GRP1 ; AND THEN CONTINUE WITH REST OF CODE FOR THAT LINE. THERE SHOULD BE ; ENOUGH TIME TO GET A PLAYFIELD STARTED, BUT DON'T DECREMENT LINE ; COUNTS WHERE THERE WILL BE NEW PLAYFIELD. THERE ISN'T ENOUGH TIME. ; PUT A 0 IN A1 FOR THOSE LINES, IN A TWO-LINE KERNEL, AND PUT A 2 IN ; A1 ON THE NEXT LINE, WHERE THERE WILL BE MORE TIME. ; ; THE ROUTINE WALKS DOWN THROUGH THE PLAYER GRAPHICS TABLE AS IT MOVES ; DOWN THE SCREEN, SO THE FIRST VALUE OF THE TABLE SHOULD BE 0, TO SET ; THAT VALUE INTO THE GRAPHICS STORE LOCATION WHEN THE PLAYER ISN'T TO ; APPEAR. ; .MACRO LINE A1,A2,A3,A4,A5,A6,A7,?A8 .IF NE,A2 LDA A2 SEC SBC LNCNT CMP #A3 BCS A8 TAY LDA A4(Y) STA A5 .ENDC A8: LDY #0 LDA LNCNT SEC .IF NE,A1 SBC #A1 STA LNCNT .ENDC SBC A6 CMP #-A7 BCC .+4 LDY #2 .ENDM ; ; .nlist .sbttl Initialization .list .page ; * ; ** ;********** ****************** ;*********** * Initialization * ;********** ****************** ; ** ; * .=romstr init: sei ;disable interrupts cld ;binary arithmetic ldx #0 txa sta ctlswa ;set porta for input 10$: sta 0(x) ;clear hardware registers and ram inx bne 10$ dex ;ff stx gflg1 ;set select mode flag txs ;init stack ptr ; ; Perform a Game Select, Game # 1 ; jsr initsl ;simulate select lever press ; ; End of Initialization ; jmp oversc ;go start with overscan .nlist .sbttl video kernel .list .page ; * ; ** ;********** **************** ;*********** * Video Kernel * ;********** **************** ; ** ; * kernel: sta wsync ;0 lda #82 ;2 load background color eor atim ;5 comp for attract mode and #0f7 ;7 sta colubk ;10 ldx #180. ;12 load number of lines 10$: sta wsync ;0 finish the line dex ;2 done? bne 10$ ;4,5 no, go lda gflg1 ;7 are we in select mode? and #10 ;9 bne copy ;11,12 yes, go do copyright notice ldx #11. ;13 load number of lines 20$: sta wsync ;0 end the line dex ;2 done? bne 20$ ;4,5 no, go jmp oversc ;7 yes, exit ; ; Display Copyright Notice ; copy: sta wsync ;0 sync up stx pf0 ;3 clear playfield regs stx pf1 ;6 stx pf2 ;9 nop ;11 waste some cycles sta t0 ;14 waste some more lda bcol ;17 set up player color eor atim ;20 adjust for attract colors and atmask ;23 ensure low lum if attract colors sta colup0 ;26 sta colup1 ;29 nop ;31 waste 2 cycles here lda #0f0 ;33 set up fine positioning in advance sta hmp0 ;36 ldx #0 ;38 stx hmp1 ;41 sta resp0 ;44 reset player zero... sta resp1 ;47 ...and player one sta wsync ;0 sta hmove ;3 execute fine adjustment lda #0cb ;5 set nusiz for small players sta nusiz0 ;8 and proper number of copies ldx #1 ;10 stx nusiz1 ;13 ; do display ldx #07 ;15 for 8 lines of the screen... 1$: stx t1 ;18,66 save index because x is used later sta wsync ;0 ldy #2 ;2 time out to center of screen dey ;4;9 bne .-1 ;7;11 sta t0 ;14 waste 3 cycles to get timing right lda col1-1(x) ;18 get graphics for first store sta grp0 ;21 store it lda col2-1(x) ;25 same for p1 sta grp1 ;28 ldy col3-1(x) ;32 now get tricky to save time... lda col4-1(x) ;36 use X and Y and A to their fullest sta t0 ;39 use temp 0 also for time savings lda col5-1(x) ;43 now load up all 3 regs ldx t0 ;46 sty grp0 ;49 and store 'em as fast as possible stx grp1 ;52 (timing is very crucial here) sta grp0 ;55 ldx t1 ;58 now restore index dex ;60 bne 1$ ;62,63 and branch back till done stx grp0 ;65 clear player graphics for neatness stx grp1 ;68 sta wsync ;0 display two blank lines sta wsync ;0 (bottom margin) jmp oversc ; ; End of Kernel ; .nlist .sbttl Overscan .list .page ; * ; ** ;********** *************************** ;*********** * Overscan: 30 Scan Lines * ;********** *************************** ; ** ; * ; ; Tie Up Screen Loose Ends ; oversc: ldx #0 stx colubk ;turn off background lda #ovrcon ;set up overscan timer sta tim64t lda #82 ;turn on vblank, ground the pots sta vblank ; ; Update Frame Counter ; inc frame bne 10$ ;go if no overflow inc hfram lda #30 ;time to go into attract? cmp hfram bne 10$ ;no, go lda gflg1 ;yes, set the flag ora #08 sta gflg1 10$: ; ; Check For Reset/Game Select ; jsr gsrst ;check levers... bcs 99$ ;if lever was pressed... jmp intst ;skip game play this frame 99$: ; ; ;******************************************** ; put overscan calcs here * ;******************************************** ; ; ; ; End of Overscan ; intst: ldx intim ;overscan done yet? bne intst ;no, go back vsnc: ldx #02 ;yes, do vsync stx vsync sta wsync ;send 4 lines of vsync sta wsync sta wsync sta wsync lda #0 sta vsync ;turn off vsync (a=0) .nlist .sbttl Vblank Calculations .list .page ; * ; ** ;********** ************************* ;*********** * Vblank: 37 Scan Lines * ;********** ************************* ; ** ; * ; ; Start Vblank Timer ; vblnk: lda #vblcon ;set up vblank timer sta tim64t ; ; ;******************************************** ; put vblank calcs here * ;******************************************** ; ; ; Color-Shift Attract Mode ; shft: ldy #0ff ;assume no attract mask lda gflg1 ;are we in color attract? and #08 bne 5$ ;yes, go sta atim ;no, reset attract shift key to zero beq 99$ ;always taken 5$: ldy #0f7 ;load attract mask lda frame ;is it time to shift? bne 99$ ;no, go inc atim ;set new color-shift mask 99$: sty atmask ;store current lum mask ; ; End of Vblank ; intst2: lda intim ;done with vblank yet? bne intst2 ;no, go back sta wsync ;yes, get ready for kernel sta vblank ;turn off vblank, and start charging pots sta hmclr ;reset horiz. motion regs to 0 sta cxclr ;clear collisions jmp kernel ;go for it .nlist .sbttl Game Reset/Select .list .page ; * ; ** ;********** ****************************** ;*********** * Game Select and Game Reset * ;********** ****************************** ; ** ; * ; Check to see if game select or game reset levers are being ; pressed. If yes, then check to see if time-out has occurred. If ; yes, then execute the function. Otherwise return with carry set, ; indicating that no action was taken. If game select or reset did ; take place, return with carry clear, so that the overscan calcs will ; be skipped (reset or select usually takes a long time to do). gsrst: lda swchb ;read console switches ror bcc grs ;go if reset lever pressed gs2: ror bcc gsel ;go if game select lever pressed ldx #1 stx gstim gsex: sec rts ;rts with carry set means no action ; ; Game Select gsel: dec gstim ;time to execute? bne gsex ;no, go initsl: lda #2d ;reset timer sta gstim lda gflg1 ;are we in select mode? and #10 beq 12$ ;no, don't inc game number sed ;new game number lda gamno clc adc #1 ;add 1 to old number cmp #gmax ;too high? bne 10$ ;no, skip reset lda #1 ;yes, reset to 1 10$: sta gamno cld ;restore binary functioning ;*************************************** ; put game select logic here * ;*************************************** 12$: ldx gamno ;set gflg1 from table lda gf1sel-1(x) sta gflg1 bne gsrs ;always taken ; ; Game Reset grs: dec gstim ;time to execute? bne gsex ;no, exit ldx #10 ;reset timer stx gstim ldx gamno ;set gflg1 from table lda gf1rst-1(x) sta gflg1 ;************************************** ; put game reset logic here * ;************************************** ldx #0 ;reset scores stx tscr stx tscr+1 stx bscr stx bscr+1 ; ; Both Functions gsrs: lda #05 ;set up hardware sta nusiz0 sta nusiz1 lda #21 sta ctrlpf lda #4 sta audc0 sta cxclr lda #0 sta hfram ;turn off color attract ldx #1 ;set up screen colors 20$: lda misc(x) sta tcol(x) dex bpl 20$ 99$: clc ;return with clear carry rts .nlist .sbttl Assorted Subroutines .list .page ; * ; ** ;********** ************************ ;*********** * Assorted Subroutines * ;********** ************************ ; ** ; * ; ; "Random" Number Routine ; ; Returns a "random" number in the accumulator. If it doesn't ; seem very random try playing around with the base address of the first ; two exclusive or's... find very varied pieces of your program to use, ; and it should return very unpredictable results. Another trick is to ; somehow do an eor with your game controllers... this is about ; as random as data can get, and usually makes a difference. rndno: lda rand ;get seed (last number) ldx rndind ;and index eor oversc(x) ;"randomize" eor kernel(x) asl ;rotate to avoid single-bit adc #0 ;state preferences inx stx rndind ;save new index eor hfram ;and use frame counter for eor frame ;long repeat time sta rand ;save new seed rts ;exit ; ; Score Addition Routine ; ; Adds value found in accumulator to the player whose offset is in ; y-reg. Keep in mind that player zero should be y-reg = 0 and player ; one should be y-reg = 2. Also, remember the amount to add (in the acc.) ; should be a decimal number. This routine allows four decimal digits ; of score for each player. adscr: sed ;add to score of a player clc adc tscr+1(y) sta tscr+1(y) txa adc tscr(y) sta tscr(y) cld rts .nlist .sbttl Tables .list .page ; * ; ** ;********** ********************** ;*********** * Relocatable Tables * ;********** ********************** ; ** ; * misc: .byte 7c,46 ;misc information for initialization ; ; Frcmov is a table used for smooth movement of objects at ; fractional speeds. To use it, assume speed byte is xxxx.xxxx ; (in pixels per frame) and do the following: ; lda #0 ;init number of pixels to move to 0 ; sta t0 ; lda frame ;get frame number ; and #0f ;use only low nybble ; tay ;index into frcmov ; lda frcmov(y) ;get table value ; and speed ;time to let fractional speed overflow ; ;into a pixel movement? ; beq 10$ ;no, skip it ; inc t0 ;yes, t0 is now 1 ;10$: lda speed ;get speed again ; lsr ;shift out fractional portion ; lsr ; lsr ; lsr ; clc ;add to overflow from fractional part ; adc t0 ; ; accumulator now contains the number of pixels to move this frame. frcmov: .byte 1,8,4,8,2,8,4,8,0,8,4,8,2,8,4,8 gf1rst: .byte 0a0,80 ;gflg1 values after game reset gf1sel: .byte 30,10 ;gflg1 values after game select ; ; copyright notice graphics tables col1: .byte 79,85,0b5,0a5,0b5,85,79 col2: .byte 17,15,15,77,55,55,77 col3: .byte 71,41,41,71,11,11,70 col4: .byte 49,49,49,0c9,49,49,0be col5: .byte 55,55,55,0d9,55,55,99 .page ; * ; ** ;********** ******************************* ;*********** * Fixed (Page-aligned) Tables * ;********** ******************************* ; ** ; * PALIGN ; ; Hmvtab contains reset counts and hmove values for objects on the ; screen. To use it, do the following (this example positions the ball): ; ; lda posn ;get horizontal position of ball ; sta wsync ;0 sync up for reset line ; tax ;2 index into hmvtab ; lda hmvtab(x) ;6 get table value ; sta hmbl ;9 set hmove value from high nybble ; and #0f ;11 keep low nybble for time loop ; tay ;13 tfr to y for loop ; nop ;15 waste 2 cycles ; dey ;17;22 etc. timing loop ; bpl .-1 ;20;25 etc. ; sta resbl ;set the ball's position right here ; sta wsync ;finish the line ; sta hmove ;execute the fine positioning hmove ; ; remember, hmvtab must not cross a page boundary, because if it does ; it could cause the instruction "lda hmvtab(x)" to take 5 cycles instead of ; 4, and that would throw off the timing of the reset line. hmvtab: .byte 60,50,40,30,20,10,00,0f0,0e0,0d0,0c0,0b0,0a0,90 .byte 71,61,51,41,31,21,11,01,0f1,0e1,0d1,0c1,0b1,0a1,91 .byte 72,62,52,42,32,22,12,02,0f2,0e2,0d2,0c2,0b2,0a2,92 .byte 73,63,53,43,33,23,13,03,0f3,0e3,0d3,0c3,0b3,0a3,93 .byte 74,64,54,44,34,24,14,04,0f4,0e4,0d4,0c4,0b4,0a4,94 .byte 75,65,55,45,35,25,15,05,0f5,0e5,0d5,0c5,0b5,0a5,95 .byte 76,66,56,46,36,26,16,06,0f6,0e6,0d6,0c6,0b6,0a6,96 .byte 77,67,57,47,37,27,17,07,0f7,0e7,0d7,0c7,0b7,0a7,97 .byte 78,68,58,48,38,28,18,08,0f8,0e8,0d8,0c8,0b8,0a8,98 .byte 79,69,59,49,39,29,19,09,0f9,0e9,0d9,0c9 ; ; End of Memory ; .=0fffc .word init ;start vector .word init .end Quote Link to comment Share on other sites More sharing options...
Cybergoth Posted September 11, 2005 Share Posted September 11, 2005 Hi there! ; .INTSET ENABLES INTERRUPTS WHEN IN A RAM VERSION, BUT ALLOWS INTERRUPTS; TO BE DISABLED IN THE ROMMED VERSION, BY THE USE OF THE TERM ZZZROM. ; AS LONG AS ZZZROM IS UNDEFINED, INTERRUPTS WILL BE ENABLED, AND A ; PROGRAM CAN BE HALTED BY CONTROL-C. BEFORE ROMMING THE PROGRAM, MERELY ; INSERT A DEFINITION FOR ZZZROM, SUCH AS ZZZROM = 1. :-o Greetings, Manuel Quote Link to comment Share on other sites More sharing options...
Cybergoth Posted September 11, 2005 Share Posted September 11, 2005 Hi there! Uihjah... Skeleton = 4K-Template Phew... and I thought this were some parts of an unfinished game... Anyway, DASM'd: ; VCS SKELETON PROGRAM ; COPYRIGHT ATARI, 1982 PROCESSOR 6502 INCLUDE VCS.H ; * ; ** ;********** ******************** ;*********** * ASSORTED EQUATES * ;********** ******************** ; ** ; * GSCON = 45;GAME SELECT TIMER INITIAL VALUE OVRCON = $25;OVERSCAN TIMER INITIAL VALUE VBLCON = $2B;VBLANK TIMER INITIAL VALUE GMAX = $03;HIGHEST GAME # +1 ; * ; ** ;********** ***************************** ;*********** * VARIABLES (RAM PAGE ZERO) * ;********** ***************************** ; ** ; * SEG.U VARS ORG $80 TCOL DS 1 ;TOP SCORE COLOR BCOL DS 1 ;BOTTOM SCORE COLOR GFLG1 DS 1 ;GAME STATUS BITS ;80 1= GAME IS IN PLAY ;40 1= BONZO (EASY) GAME ;20 1= ONE-PLAYER GAME ;10 1= SELECT MODE ;08 1= COLOR-SHIFTING ATTRACT MODE ;04 NOT USED YET ;02 NOT USED YET ;01 NOT USED YET GAMNO DS 1 ;GAME NUMBER (DECIMAL) GSTIM DS 1 ;GAME SELECT TIMER TSCR DS 2 ;TOP PLAYER'S SCORE BSCR DS 2 ;BOTTOM PLAYER'S SCORE RAND DS 1 ;"RANDOM" NUMBER SEED/LAST NUMBER RNDIND DS 1 ;"RANDOM" NUMBER INDEX FRAME DS 1 ;FRAME COUNTER HFRAM DS 1 ;HI BYTE OF FRAME COUNTER ATIM DS 1 ;ATTRACT TIMER ATMASK DS 1 ;ATTRACT LUM MASK T0 DS 1 ;TEMPORARY VARIABLES T1 DS 1 ;; * ;; ** ;;********** ****************** ;;*********** * MACROS * ;;********** ****************** ;; ** ;; * ;; ;; PALIGN WILL AUTOMATICALLY ALIGN FOLLOWING CODE WITH A PAGE VOUNDARY. ;; IT WILL USUALLY BE USED AT THE TOP OF TABLES, SO THAT A TABLE WON'T ;; CROSS A BOUNDARY AND FUCK UP A KERNEL. ;; ;.MACRO PALIGN ;.=<.+0FF>&0FF00 ;.ENDM ;; ;; ;; .INTSET ENABLES INTERRUPTS WHEN IN A RAM VERSION, BUT ALLOWS INTERRUPTS ;; TO BE DISABLED IN THE ROMMED VERSION, BY THE USE OF THE TERM ZZZROM. ;; AS LONG AS ZZZROM IS UNDEFINED, INTERRUPTS WILL BE ENABLED, AND A ;; PROGRAM CAN BE HALTED BY CONTROL-C. BEFORE ROMMING THE PROGRAM, MERELY ;; INSERT A DEFINITION FOR ZZZROM, SUCH AS ZZZROM = 1. ;; ;.MACRO .INTSET ;.IF NDF,ZZZROM ;CLI ;.IFF ;SEI ;.ENDC ;.ENDM ;; ;; ;; LINE WILL DECREMENT THE LINE COUNT, IF REQUESTED, WILL SET UP A ;; PLAYER, IF REQUESTED, AND WILL SET UP A MISSILE OR BALL DURING A ;; KERNEL LINE. THE LINE COUNT MAY BE DECREMENTED BY ANY VALUE, SET ;; AS ARGUMENT A1. IF A1 IS ZERO, THAT PART OF THE CODE IS NOT ;; ASSEMBLED. ARGUMENT A2 SPECIFIES THE VERTICAL POSITION OF THE ;; PLAYER, BY NAME OF RAM POSITION WHERE THAT VALUE IS LOCATED. IF ;; THAT ARGUMENT IS SET TO ZERO, THE CODE FOR HANDLING THE PLAYER ;; IS LEFT OUT. ;; ;; THERE ARE EIGHT ARGUMENTS, BUT A8 MUST NOT BE SPECIFIED WHEN ;; INVOKING THE MACRO. IT IS A DUMMY FOR CREATING A JUMP ADDRESS. ;; THE OTHERS MUST BE USED, AT LEAST TO THE POINT OF PUTTING IN A ;; COMMA AS A PLACE-HOLDER. THE ARGUMENTS AND THEIR MEANINGS ARE: ;; ;; A1 LINE COUNT DECREMENT AMOUNT (USUALLY 1 OR 2; IF 0, CODE IS ;; SKIPPED) ;; A2 NAME OF RAM LOCATION FOR VERT. POSITION OF A PLAYER. IF 0, ;; CODE FOR PLAYER SETUP IS LEFT OUT ;; A3 PLAYER'S HEIGHT ;; A4 NAME OF PLAYER'S GRAPHICS TABLE ;; A5 NAME OF A TEMPORARY STORAGE LOCATION FOR THAT PLAYER'S GRAPHICS ;; A6 NAME OF LOCATION FOR MISSILE'S OR BALL'S VERTICAL POSITION ;; A7 HEIGHT OF MISSILE OR BALL ;; A8 DUMMY JUMP ADDRESS -- DON'T PUT A VALUE IN FOR THIS ARGUMENT!!! ;; ;; AN EXAMPLE FOR THE FIRST LINE OF A DOUBLE-LINE KERNEL MIGHT BE: ;; ;; LINE 2,VP0,8,P0TAB,GP0,VM0,14. ;; ;; THE SECOND LINE OF THE KERNEL MIGHT LOOK LIKE: ;; ;; LINE 0,VP1,10.,P1TAB,GP1,VBL,4 ;; ;; A LINE WITH NO PLAYER MIGHT BE CALLED AS FOLLOWS: ;; ;; LINE 1,0,,,,VM1,6 ;; ;; NOTE THAT ALL NUMERIC VALUES ARE IN HEX, AND DECIMAL VALUES MUST END ;; WITH A DOT. THIS MACRO USES THE ACCUMULATOR AND Y REGISTER, BUT LEAVES ;; THE X REGISTER FREE. ;; ;; THE RESULTS OF THIS MACRO MUST BE INVOKED AT THE START OF THE NEXT LINE, ;; PROBABLY IMMEDIATELY AFTER AT STA WSYNC, OR AFTER STA WSYNC, STA HMOVE. ;; IF THE PLAYER GRAPHICS HAS BEEN STORED IN GP1, FOR INSTANCE, AND YOU ;; ARE ABOUT TO PUT UP THAT PLAYER AND THE BALL, AS IN THE SECOND EXAMPLE ;; ABOVE, YOU WOULD PUT IN CODE: ;; STY ENABL ;; LDY GP1 ;; STY GRP1 ;; AND THEN CONTINUE WITH REST OF CODE FOR THAT LINE. THERE SHOULD BE ;; ENOUGH TIME TO GET A PLAYFIELD STARTED, BUT DON'T DECREMENT LINE ;; COUNTS WHERE THERE WILL BE NEW PLAYFIELD. THERE ISN'T ENOUGH TIME. ;; PUT A 0 IN A1 FOR THOSE LINES, IN A TWO-LINE KERNEL, AND PUT A 2 IN ;; A1 ON THE NEXT LINE, WHERE THERE WILL BE MORE TIME. ;; ;; THE ROUTINE WALKS DOWN THROUGH THE PLAYER GRAPHICS TABLE AS IT MOVES ;; DOWN THE SCREEN, SO THE FIRST VALUE OF THE TABLE SHOULD BE 0, TO SET ;; THAT VALUE INTO THE GRAPHICS STORE LOCATION WHEN THE PLAYER ISN'T TO ;; APPEAR. ;; ;.MACRO LINE A1,A2,A3,A4,A5,A6,A7,?A8 ;.IF NE,A2 ;LDA A2 ;SEC ;SBC LNCNT ;CMP #A3 ;BCS A8 ;TAY ;LDA A4(Y) ;STA A5 ;.ENDC ;A8: LDY #0 ;LDA LNCNT ;SEC ;.IF NE,A1 ;SBC #A1 ;STA LNCNT ;.ENDC ;SBC A6 ;CMP #-A7 ;BCC .+4 ;LDY #2 ;.ENDM ;; ; * ; ** ;********** ****************** ;*********** * INITIALIZATION * ;********** ****************** ; ** ; * SEG Bank0 ORG $F000 START SEI;DISABLE INTERRUPTS CLD;BINARY ARITHMETIC LDX #0 TXA STA SWACNT;SET PORTA FOR INPUT 10$: STA 0,X;CLEAR HARDWARE REGISTERS AND RAM INX BNE 10$ DEX;FF STX GFLG1;SET SELECT MODE FLAG TXS;INIT STACK PTR ; ; PERFORM A GAME SELECT, GAME # 1 ; JSR INITSL;SIMULATE SELECT LEVER PRESS ; ; END OF INITIALIZATION ; JMP OVERSC;GO START WITH OVERSCAN ; * ; ** ;********** **************** ;*********** * VIDEO KERNEL * ;********** **************** ; ** ; * KERNEL: STA WSYNC;0 LDA #$82;2 LOAD BACKGROUND COLOR EOR ATIM;5 COMP FOR ATTRACT MODE AND #$F7;7 STA COLUBK;10 LDX #180;12 LOAD NUMBER OF LINES 10$: STA WSYNC;0 FINISH THE LINE DEX;2 DONE? BNE 10$;4,5 NO, GO LDA GFLG1;7 ARE WE IN SELECT MODE? AND #$10;9 BNE COPY;11,12 YES, GO DO COPYRIGHT NOTICE LDX #$11;13 LOAD NUMBER OF LINES 20$: STA WSYNC;0 END THE LINE DEX;2 DONE? BNE 20$;4,5 NO, GO JMP OVERSC;7 YES, EXIT ; ; DISPLAY COPYRIGHT NOTICE ; COPY: STA WSYNC;0 SYNC UP STX PF0;3 CLEAR PLAYFIELD REGS STX PF1;6 STX PF2;9 NOP;11 WASTE SOME CYCLES STA T0;14 WASTE SOME MORE LDA BCOL;17 SET UP PLAYER COLOR EOR ATIM;20 ADJUST FOR ATTRACT COLORS AND ATMASK;23 ENSURE LOW LUM IF ATTRACT COLORS STA COLUP0;26 STA COLUP1;29 NOP;31 WASTE 2 CYCLES HERE LDA #$F0;33 SET UP FINE POSITIONING IN ADVANCE STA HMP0;36 LDX #0;38 STX HMP1;41 STA RESP0;44 RESET PLAYER ZERO... STA RESP1;47 ...AND PLAYER ONE STA WSYNC;0 STA HMOVE;3 EXECUTE FINE ADJUSTMENT LDA #$CB;5 SET NUSIZ FOR SMALL PLAYERS STA NUSIZ0;8 AND PROPER NUMBER OF COPIES LDX #1;10 STX NUSIZ1;13 ; DO DISPLAY LDX #$07;15 FOR 8 LINES OF THE SCREEN... 1$: STX T1;18,66 SAVE INDEX BECAUSE X IS USED LATER STA WSYNC;0 LDY #2;2 TIME OUT TO CENTER OF SCREEN DEY;4;9 BNE .-1;7;11 STA T0;14 WASTE 3 CYCLES TO GET TIMING RIGHT LDA COL1-1,X;18 GET GRAPHICS FOR FIRST STORE STA GRP0;21 STORE IT LDA COL2-1,X;25 SAME FOR P1 STA GRP1;28 LDY COL3-1,X;32 NOW GET TRICKY TO SAVE TIME... LDA COL4-1,X;36 USE X AND Y AND A TO THEIR FULLEST STA T0;39 USE TEMP 0 ALSO FOR TIME SAVINGS LDA COL5-1,X;43 NOW LOAD UP ALL 3 REGS LDX T0;46 STY GRP0;49 AND STORE 'EM AS FAST AS POSSIBLE STX GRP1;52 (TIMING IS VERY CRUCIAL HERE) STA GRP0;55 LDX T1;58 NOW RESTORE INDEX DEX;60 BNE 1$;62,63 AND BRANCH BACK TILL DONE STX GRP0;65 CLEAR PLAYER GRAPHICS FOR NEATNESS STX GRP1;68 STA WSYNC;0 DISPLAY TWO BLANK LINES STA WSYNC;0 (BOTTOM MARGIN) JMP OVERSC ; ; END OF KERNEL ; ; * ; ** ;********** *************************** ;*********** * OVERSCAN: 30 SCAN LINES * ;********** *************************** ; ** ; * ; ; TIE UP SCREEN LOOSE ENDS ; OVERSC: LDX #0 STX COLUBK;TURN OFF BACKGROUND LDA #OVRCON;SET UP OVERSCAN TIMER STA TIM64T LDA #$82;TURN ON VBLANK, GROUND THE POTS STA VBLANK ; ; UPDATE FRAME COUNTER ; INC FRAME BNE 10$;GO IF NO OVERFLOW INC HFRAM LDA #$30;TIME TO GO INTO ATTRACT? CMP HFRAM BNE 10$;NO, GO LDA GFLG1;YES, SET THE FLAG ORA #$08 STA GFLG1 10$: ; ; CHECK FOR RESET/GAME SELECT ; JSR GSRST;CHECK LEVERS... BCS 99$;IF LEVER WAS PRESSED... JMP INTST;SKIP GAME PLAY THIS FRAME 99$: ; ; ;******************************************** ; PUT OVERSCAN CALCS HERE * ;******************************************** ; ; ; ; END OF OVERSCAN ; INTST: LDX INTIM;OVERSCAN DONE YET? BNE INTST;NO, GO BACK VSNC: LDX #$02;YES, DO VSYNC STX VSYNC STA WSYNC;SEND 4 LINES OF VSYNC STA WSYNC STA WSYNC STA WSYNC LDA #0 STA VSYNC;TURN OFF VSYNC (A=0) ; * ; ** ;********** ************************* ;*********** * VBLANK: 37 SCAN LINES * ;********** ************************* ; ** ; * ; ; START VBLANK TIMER ; VBLNK: LDA #VBLCON;SET UP VBLANK TIMER STA TIM64T ; ; ;******************************************** ; PUT VBLANK CALCS HERE * ;******************************************** ; ; ; COLOR-SHIFT ATTRACT MODE ; SHFT: LDY #$FF;ASSUME NO ATTRACT MASK LDA GFLG1;ARE WE IN COLOR ATTRACT? AND #$08 BNE 5$;YES, GO STA ATIM;NO, RESET ATTRACT SHIFT KEY TO ZERO BEQ 99$;ALWAYS TAKEN 5$: LDY #$F7;LOAD ATTRACT MASK LDA FRAME;IS IT TIME TO SHIFT? BNE 99$;NO, GO INC ATIM;SET NEW COLOR-SHIFT MASK 99$: STY ATMASK;STORE CURRENT LUM MASK ; ; END OF VBLANK ; INTST2: LDA INTIM;DONE WITH VBLANK YET? BNE INTST2;NO, GO BACK STA WSYNC;YES, GET READY FOR KERNEL STA VBLANK;TURN OFF VBLANK, AND START CHARGING POTS STA HMCLR;RESET HORIZ. MOTION REGS TO 0 STA CXCLR;CLEAR COLLISIONS JMP KERNEL;GO FOR IT ; * ; ** ;********** ****************************** ;*********** * GAME SELECT AND GAME RESET * ;********** ****************************** ; ** ; * ; CHECK TO SEE IF GAME SELECT OR GAME RESET LEVERS ARE BEING ; PRESSED. IF YES, THEN CHECK TO SEE IF TIME-OUT HAS OCCURRED. IF ; YES, THEN EXECUTE THE FUNCTION. OTHERWISE RETURN WITH CARRY SET, ; INDICATING THAT NO ACTION WAS TAKEN. IF GAME SELECT OR RESET DID ; TAKE PLACE, RETURN WITH CARRY CLEAR, SO THAT THE OVERSCAN CALCS WILL ; BE SKIPPED (RESET OR SELECT USUALLY TAKES A LONG TIME TO DO). GSRST: LDA SWCHB;READ CONSOLE SWITCHES ROR BCC GRS;GO IF RESET LEVER PRESSED GS2: ROR BCC GSEL;GO IF GAME SELECT LEVER PRESSED LDX #1 STX GSTIM GSEX: SEC RTS;RTS WITH CARRY SET MEANS NO ACTION ; ; GAME SELECT GSEL: DEC GSTIM;TIME TO EXECUTE? BNE GSEX;NO, GO INITSL: LDA #$2D;RESET TIMER STA GSTIM LDA GFLG1;ARE WE IN SELECT MODE? AND #$10 BEQ 12$;NO, DON'T INC GAME NUMBER SED;NEW GAME NUMBER LDA GAMNO CLC ADC #1;ADD 1 TO OLD NUMBER CMP #GMAX;TOO HIGH? BNE 10$;NO, SKIP RESET LDA #1;YES, RESET TO 1 10$: STA GAMNO CLD;RESTORE BINARY FUNCTIONING ;*************************************** ; PUT GAME SELECT LOGIC HERE * ;*************************************** 12$: LDX GAMNO;SET GFLG1 FROM TABLE LDA GF1SEL-1,X STA GFLG1 BNE GSRS;ALWAYS TAKEN ; ; GAME RESET GRS: DEC GSTIM;TIME TO EXECUTE? BNE GSEX;NO, EXIT LDX #$10;RESET TIMER STX GSTIM LDX GAMNO;SET GFLG1 FROM TABLE LDA GF1RST-1,X STA GFLG1 ;************************************** ; PUT GAME RESET LOGIC HERE * ;************************************** LDX #0;RESET SCORES STX TSCR STX TSCR+1 STX BSCR STX BSCR+1 ; ; BOTH FUNCTIONS GSRS: LDA #$05;SET UP HARDWARE STA NUSIZ0 STA NUSIZ1 LDA #$21 STA CTRLPF LDA #4 STA AUDC0 STA CXCLR LDA #0 STA HFRAM;TURN OFF COLOR ATTRACT LDX #1;SET UP SCREEN COLORS 20$: LDA MISC,X STA TCOL,X DEX BPL 20$ 99$: CLC;RETURN WITH CLEAR CARRY RTS ; * ; ** ;********** ************************ ;*********** * ASSORTED SUBROUTINES * ;********** ************************ ; ** ; * ; ; "RANDOM" NUMBER ROUTINE ; ; RETURNS A "RANDOM" NUMBER IN THE ACCUMULATOR. IF IT DOESN'T ; SEEM VERY RANDOM TRY PLAYING AROUND WITH THE BASE ADDRESS OF THE FIRST ; TWO EXCLUSIVE OR'S... FIND VERY VARIED PIECES OF YOUR PROGRAM TO USE, ; AND IT SHOULD RETURN VERY UNPREDICTABLE RESULTS. ANOTHER TRICK IS TO ; SOMEHOW DO AN EOR WITH YOUR GAME CONTROLLERS... THIS IS ABOUT ; AS RANDOM AS DATA CAN GET, AND USUALLY MAKES A DIFFERENCE. RNDNO: LDA RAND;GET SEED (LAST NUMBER) LDX RNDIND;AND INDEX EOR OVERSC,X;"RANDOMIZE" EOR KERNEL,X ASL;ROTATE TO AVOID SINGLE-BIT ADC #0;STATE PREFERENCES INX STX RNDIND;SAVE NEW INDEX EOR HFRAM;AND USE FRAME COUNTER FOR EOR FRAME;LONG REPEAT TIME STA RAND;SAVE NEW SEED RTS;EXIT ; ; SCORE ADDITION ROUTINE ; ; ADDS VALUE FOUND IN ACCUMULATOR TO THE PLAYER WHOSE OFFSET IS IN ; Y-REG. KEEP IN MIND THAT PLAYER ZERO SHOULD BE Y-REG = 0 AND PLAYER ; ONE SHOULD BE Y-REG = 2. ALSO, REMEMBER THE AMOUNT TO ADD (IN THE ACC.) ; SHOULD BE A DECIMAL NUMBER. THIS ROUTINE ALLOWS FOUR DECIMAL DIGITS ; OF SCORE FOR EACH PLAYER. ADSCR: SED;ADD TO SCORE OF A PLAYER CLC ADC TSCR+1,Y STA TSCR+1,Y TXA ADC TSCR,Y STA TSCR,Y CLD RTS ; * ; ** ;********** ********************** ;*********** * RELOCATABLE TABLES * ;********** ********************** ; ** ; * MISC: .BYTE $7C,$46;MISC INFORMATION FOR INITIALIZATION ; ; FRCMOV IS A TABLE USED FOR SMOOTH MOVEMENT OF OBJECTS AT ; FRACTIONAL SPEEDS. TO USE IT, ASSUME SPEED BYTE IS XXXX.XXXX ; (IN PIXELS PER FRAME) AND DO THE FOLLOWING: ; LDA #0;INIT NUMBER OF PIXELS TO MOVE TO 0 ; STA T0 ; LDA FRAME;GET FRAME NUMBER ; AND #$0F;USE ONLY LOW NYBBLE ; TAY;INDEX INTO FRCMOV ; LDA FRCMOV,Y;GET TABLE VALUE ; AND SPEED;TIME TO LET FRACTIONAL SPEED OVERFLOW ;;INTO A PIXEL MOVEMENT? ; BEQ 10$;NO, SKIP IT ; INC T0;YES, T0 IS NOW 1 ;10$: LDA SPEED;GET SPEED AGAIN ; LSR;SHIFT OUT FRACTIONAL PORTION ; LSR ; LSR ; LSR ; CLC;ADD TO OVERFLOW FROM FRACTIONAL PART ; ADC T0 ; ; ACCUMULATOR NOW CONTAINS THE NUMBER OF PIXELS TO MOVE THIS FRAME. FRCMOV: .BYTE 1,8,4,8,2,8,4,8,0,8,4,8,2,8,4,8 GF1RST: .BYTE $A0,$80;GFLG1 VALUES AFTER GAME RESET GF1SEL: .BYTE $30,$10;GFLG1 VALUES AFTER GAME SELECT ; ; COPYRIGHT NOTICE GRAPHICS TABLES COL1: .BYTE $79,$85,$B5,$A5,$B5,$85,$79 COL2: .BYTE $17,$15,$15,$77,$55,$55,$77 COL3: .BYTE $71,$41,$41,$71,$11,$11,$70 COL4: .BYTE $49,$49,$49,$C9,$49,$49,$BE COL5: .BYTE $55,$55,$55,$D9,$55,$55,$99 ; * ; ** ;********** ******************************* ;*********** * FIXED (PAGE-ALIGNED) TABLES * ;********** ******************************* ; ** ; * ALIGN 256 ; ; HMVTAB CONTAINS RESET COUNTS AND HMOVE VALUES FOR OBJECTS ON THE ; SCREEN. TO USE IT, DO THE FOLLOWING (THIS EXAMPLE POSITIONS THE BALL): ; ; LDA POSN;GET HORIZONTAL POSITION OF BALL ; STA WSYNC;0 SYNC UP FOR RESET LINE ; TAX;2 INDEX INTO HMVTAB ; LDA HMVTAB,X;6 GET TABLE VALUE ; STA HMBL;9 SET HMOVE VALUE FROM HIGH NYBBLE ; AND #$0F;11 KEEP LOW NYBBLE FOR TIME LOOP ; TAY;13 TFR TO Y FOR LOOP ; NOP;15 WASTE 2 CYCLES ; DEY;17;22 ETC. TIMING LOOP ; BPL .-1;20;25 ETC. ; STA RESBL;SET THE BALL'S POSITION RIGHT HERE ; STA WSYNC;FINISH THE LINE ; STA HMOVE;EXECUTE THE FINE POSITIONING HMOVE ; ; REMEMBER, HMVTAB MUST NOT CROSS A PAGE BOUNDARY, BECAUSE IF IT DOES ; IT COULD CAUSE THE INSTRUCTION "LDA HMVTAB,X" TO TAKE 5 CYCLES INSTEAD OF ; 4, AND THAT WOULD THROW OFF THE TIMING OF THE RESET LINE. HMVTAB: .BYTE $60,$50,$40,$30,$20,$10,$00,$F0,$E0,$D0,$C0,$B0,$A0,$90 .BYTE $71,$61,$51,$41,$31,$21,$11,$01,$F1,$E1,$D1,$C1,$B1,$A1,91 .BYTE $72,$62,$52,$42,$32,$22,$12,$02,$F2,$E2,$D2,$C2,$B2,$A2,92 .BYTE $73,$63,$53,$43,$33,$23,$13,$03,$F3,$E3,$D3,$C3,$B3,$A3,93 .BYTE $74,$64,$54,$44,$34,$24,$14,$04,$F4,$E4,$D4,$C4,$B4,$A4,94 .BYTE $75,$65,$55,$45,$35,$25,$15,$05,$F5,$E5,$D5,$C5,$B5,$A5,95 .BYTE $76,$66,$56,$46,$36,$26,$16,$06,$F6,$E6,$D6,$C6,$B6,$A6,96 .BYTE $77,$67,$57,$47,$37,$27,$17,$07,$F7,$E7,$D7,$C7,$B7,$A7,97 .BYTE $78,$68,$58,$48,$38,$28,$18,$08,$F8,$E8,$D8,$C8,$B8,$A8,98 .BYTE $79,$69,$59,$49,$39,$29,$19,$09,$F9,$E9,$D9,$C9 ; ; END OF MEMORY ; ORG $FFFC .WORD START .WORD START Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.