GithubHelp home page GithubHelp logo

jefftranter / 6502 Goto Github PK

View Code? Open in Web Editor NEW
290.0 43.0 67.0 69.62 MB

Code for the 6502 microprocessor, mostly for the Replica 1 computer.

Assembly 77.63% Makefile 1.57% Shell 0.31% C 5.63% Python 2.55% C++ 4.04% BASIC 8.25% HTML 0.01%

6502's Introduction

These directories contain various software 6502 microprocessor
intended to run on various computers including the Apple 1 and
compatibles like the Briel Replica 1 computer, Ohio Scientific
Superboard II and compatibles like the Briel Superboard ///, and the
MOS Technology KIM-1.

Some code is entirely written by me and others are ports of existing
software.

Files written by me are released under the following license:

Copyright (C) 2012-2020 by Jeff Tranter <[email protected]>

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

6502's People

Contributors

cbmeeks avatar gabrielsroka avatar jefftranter avatar mrwheel avatar napobear avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

6502's Issues

Minor error in port of Apple ][ System Monitor

I believe there may be an error in this port of the Apple ][ System Monitor. Line 1999 reads:
IOPRT1: LDA COUT1/256
This attempts to load the accumator with the high byte of the address of subroutine COUT1. This is actually using a zero-page addressing mode since COUT1/256 evaluates to a byte and there is no hash to indicate to load immediate. I believe the correct line should read:
IOPRT1: LDA #>COUT1

This may result in the I/O vectors being loaded with the wrong address on an Apple II, if for some reason the monitor is relocated.

This correction also matches what appears in the original F8 ROM.

Out of curiosity, the IOPRT2 routine seems to require that LOC0 and LOC1 be initialized to 0 and 1, respectively. This does not seem to be set anywhere in the monitor. Was this done somewhere else on the Apple II computers?

JMON Copy incorrect branching

In the JMON memory copy routine, line 575 in jmon.s branches from the copy up portion of the code into the copy down portion of the code. The BNE @NotDone should be BNE @NotDone1.

HEXPAWN

; Formatted for the SB-Assembler-3 (sbasm v3)
; https://www.sbprojects.net/sbasm/index.php

.CR	6502
.TF   hexpawn_0100.BIN,BIN
.EF errors
.OR $0100

;KIMROM routines
PADD .EQ $1741
CONVD .EQ $1F4E-6
KEYIN .EQ $1F40
GETKEY .EQ $1F6A
SCANDS .EQ $1F1F
DIGCOD .EQ $1FE7
TIMER .EQ $1704

; Page 0 locations used by program HEXPAWN
FLSHR .EQ $0000 ;Timer for flashing KIM's men
DBD .EQ $0001 ;Current board in Display format
MASK .EQ $0004 ;Masks for flashing KIM's men
EBD .EQ $0007 ;Current bd - Easy-to-read format
WINDO .EQ $0010 ;Current 7-segment display
MOVTIM .EQ $0016
MOVTYP .EQ $0017 ;KIM's last move (TO;FROM)
TOG .EQ $0018 ;On/Off indicator for KIM's men
GAMNUM .EQ $0019 ;Game number
BDNDX .EQ $001A ;3*Bd # for model match/move select
MOVNO .EQ $001B ;KIM's last move # (0,1, or 2)
PTO .EQ $001C ;Person's last "to" move
FROM .EQ $001D ;If < 0, no "from" move yet
;If >= 0, is equal to the "from" move
TMP .EQ $001E
TMP1 .EQ $001F
POINTER .EQ $0020
POINT0 .EQ $0021 ;Page # (ADH) of MOVES
MPOINT .EQ $0022
MPOIN1 .EQ $0023 ;page # (ADH) of messages
BGEBD .EQ $0024 ;Beginning bd - Easy-format:
; 03 = KIM
; 00 = space
; 01 = Person
MOVES .EQ $002D ;Table of possible moves is placed
;here by startup routine and
;is modified as KIM "learns"
INH .EQ $00F9
TEMP .EQ $00FC

;HEXPAWN for KIM-1 Copyright May 1978 R.C. Leedom

HXPNST LDX #$6E ;transfer moves, beginning
INLP
LDA SP0IN0,X
STA POINT0,X
DEX
BPL INLP
STA GAMNUM
JMP INIT

;The following board positions that
;the HEXPAWN program will recognize after the
;human opponent has moved. The squares are numbered
;according to the scheme shown in the
;comment field for CAPSET (location 03F8)
;Here, the pieces and spaces (K=KIM, P=person,
;and =space) are packed by column -- that is,
;in gorups: 0,3,6; 1,4,7; 2,5,8, (For segment-
;lighting, actual data is ordered 360,471,582)
BDMDL
.DB $43, $0B, $0B ;KP
,K_P,K_P
.DB $0B, $0B, $43 ;K_P,K_P,KP_
.DB $0B, $43, $0B ;K_P,KP_,K_P
.DB $C3, $40, $0B ;KK_,P,K_P
.DB $40, $C3, $0B
.DB $43, $48, $03
.DB $43, $03, $48
.DB $08, $C3, $43
.DB $C8, $43, $43
.DB $C3, $08, $43
.DB $43, $43, $C8
.DB $48, $03, $43
.DB $40, $40, $43
.DB $08, $43, $03
.DB $43, $00, $0B
.DB $C0, $C0, $43
.DB $43, $40, $40
.DB $C0, $43, $40
.DB $40, $43, $C0
.DB $C3, $C0, $40
.DB $43, $08, $C3
.DB $00, $43, $0B
.DB $40, $C0, $C3
.DB $C0, $40, $03
.DB $40, $C3, $00
.DB $00, $C3, $40
.DB $0B, $00, $43
.DB $00, $40, $C3
.DB $0B, $40, $C3
.DB $03, $48, $43
.DB $43, $C8, $43
.DB $00, $43, $00
.DB $C3, $40, $00
;End-game messages
KWIN
.DB $3E, $00, $38, $3F, $6D, $79
PWIN
.DB $00, $54, $1C, $78, $6D, $00
KWAD .EQ KWIN-$100
PWAD .EQ PWIN-$100
;The following data is saved here for startup intitalization
SP0IN0 .DB $00
SMP0IN .DB $00
SMP0I1 .DB $01
SPGEBD
SPGEBD .DB $03, $03, $03
.DB $00, $00, $00
.DB $01, $01, $01

SMVTBL .DB $31, $41, $52
.DB $30, $41, $51
.DB $30, $40, $00
.DB $40, $42, $63
.DB $31, $52, $74
.DB $40, $42, $52
.DB $31, $41, $51
.DB $51, $64, $74
.DB $51, $42, $00
.DB $63, $73, $00
.DB $40, $31, $00
.DB $31, $41, $51
.DB $42, $00, $00
.DB $42, $52, $00
.DB $52, $00, $00
.DB $63, $74, $00
.DB $40, $00, $00
.DB $51, $63, $00
.DB $31, $85, $00
.DB $63, $74, $00
.DB $75, $85, $00
.DB $42, $52, $00
.DB $74, $85, $00
.DB $63, $42, $52
.DB $74, $31, $00
.DB $74, $51, $00
.DB $30, $00, $00
.DB $42, $85, $00
.DB $30, $40, $85
.DB $30, $40, $42
.DB $00, $00, $00
.DB $00, $00, $00
.DB $63, $40, $00

;BDNDX .DB $00, $03, $06, $09, $0C, $0F, $12, $15, $18, $1B, $1E, $21, $24, $27, $2A, $2D
; .DB $30, $33, $36, $39, $3C, $3F, $42, $45, $48, $4B, $4E, $51, $54, $57, $5A, $5D, $60

	.BS $13

INIT
LDX #$07 ;Initialize right
LDA #$00 ;side
INITLP
STA WINDO,X ;of display
DEX ;(plus MOVTIM, MOVTYP)
BPL INITLP ;to await
LDA #$C0 ;person's
STA WINDO+4 ;move
LDX #$08
BDINIT
LDA BGEBD,X ;Transfer beginning board (in
STA EBD,X ;Easy-format) to current
DEX ;board
BPL BDINIT
STX FROM ;Indicate no "from" move yet
DISPLT
LDX #$03 ;Clear the
DSPLP
LDA #$00 ;"Display-format"
STA FLSHR,X ;board and
DEX ;the flasher-timer
BPL DSPLP
LDY #$02 ;Start with 3rd char of board
CLC
NXDIG
STY TMP ;(*** was 'TEMP' in original listing )
LDA #$06 ;Set up X to start with
ADC TMP ;lower segment for
TAX ;this character
LDA #$00 ;Clear A so can OR segments
NXSEG
ROR ;In this loop, shift the
ROR ;segments into place
ROR
ORA EBD,X ;OR 3 for KIM, 1 for person
DEX ;point to next higher segment
DEX
DEX
BPL NXSEG ;Loop till character done
STA DBD,Y ;Save completed char;
DEY ;go do next ont to
BPL NXDIG ;the left
; Main loop begins here
DISPL0
DEC FLSHR ;Time to flip KIM bits?
BPL LITEST ;No, just show current pattern
LDA #$30 ;Yes, Reset
STA FLSHR ;timer
LDX #$02 ;From the
GETMSK
LDA DBD,X ;flasher-mask
LSR ;patterns
AND #$49 ;for
STA MASK,X ;the
DEX ;current
BPL GETMSK ;board
LDX #$02 ;Set X for next loop
LDA TOG ;Toggle to
EOR #$80 ;alternate l's and 0's
STA TOG ;for KIiM' s men
BMI WNDSET ;Go do 0's
LDA #$00
ZERMSK
STA MASK,X ;Clear inasks so
DEX ;can do
BPL ZERMSK ;1's
LDX #$02
WNDSET
LDA DBD,X ;Use the
AND #$49 ;masks
EOR MASK,X ;to flip
STA WINDO,X ;the bits
DEX
BPL WNDSET
;Output to KIM's 7-segment displays
LITEST
LDA #$7F ;Set directional
STA PADD ;registers
LDY #$00
LDX #$09 ;Start with leftmost char
LITE
LDA WINDO,Y ;Get character
STY TEMP
JSR CONVD+6 ;Output character
INY
CPY #$06 ;Done all six yet?
BCC LITE ;Not yet, continue
JSR $1F3D ;Turn off digits
;Keyboard input begins here
KEYGET
CLD
JSR KEYIN
JSR GETKEY
CMP #$13 ;GO key?
BNE DACHK
JMP INIT ;Yes, start new game
DACHK
CMP #$11 ;DA key?
BNE GIPROG
LDX #$02 ;Yes, display (for Data Analysis)
DALP
LDA GAMNUM,X ;from left to right
STA INH,X ;Move# (00,01, or 02)
DEX ;Board index (Bd # * 3)
BPL DALP ;Game #. (2 digits each)
JSR SCANDS ;Keep doing this till DA
BPL KEYGET ;released; then resume play
GIPROG
LDX WINDO+4 ;Is game still
CPX #$C0 ;in progress?
BNE LITEST ;No, Keep showing endgame msg
CMP #$14 ;PC key?
BEQ KWLINK ;Yes, Person Concedes
LDX MOVTIM ;Person's turn to move?
BNE TIMEDS ;No, go time display,
JSR LEGMOV ;Yes, Did he make legal move?
BPL PERLM ;Yes, Go execute it
LDA #$08 ;He didn't make a legal move
STA TMP ;does he have one? Try
LMCHK
JSR LEGMOV ;each po3ition to see
BPL TOMVCK
NXFMCK
DEC TMP ;Try
LDA TMP ;next
BPL LMCHK ;position
STA MOVTIM ;Tried all, no luck, no legal
STA MOVTYP ;moves possible, Set KIM
FNMVLP
JMP DISPL0 ;win display after delay
;Continue looking for valid move for person
TOMVCK
LDA FROM ;Was valid move a "to" move?
BPL FNMVLP ;Yes, he can therefore move
STX FROM ;No, Given this "from" move
LDA #$06 ;try all possible
STA TMP1 ;"to" moves
LTMCHK
JSR LEGMOV ;Find one?
BPL OKMOV ;Yes, He's got a move.
DEC TMP1 ;Try
LDA TMP1 ;next
BPL LTMCHK ;position
STX FROM ;Tried all "to" moves look
BMI NXFMCK ;for another "from" move.
;Have found a possible "from-to" move for person
OKMOV
LDA #$FF ;Has got a move he could make,
STA FROM ;so restore FROM and
BMI FNMVLP ;continue the game,
;Person has entered a legal move
PERLM
LDA #$00 ;Clear the "to" indication
STA WINDO+5 ;left from KIM's move.
LDA FROM ;Was this a "from" move?
BMI FRMDIS ;Yes, display it; save move
STX PTO ;No, save as person's "to".
LDY #$01 ;Set "person" indicator
TMINIT
LDA #$FF ;Set timer, not person's mov
MAKMOV
STA MOVTIM ;Save move-timer
STY EBD,X ;Place piece on board.
LDA DIGCOD,X ;Get ?-segment code for
STA WINDO+5 ;"to" indication on board
LDY #$00 ;Remove piece from
LDX FROM ;previous
STY EBD,X ;board position
LDA #$FF ;Prepare for next
STA FROM ;"from" move
BMI DISX ;Go show this "from" move
;This code displays "from" moves
FRMDIS
STX FROM ;Save "from" move
DISX
LDA DIGCOD,X ;Use "from" in X to get 7-seg
STA WINDO+3 ;indication
JMP DISPLT ;Return to main loop.
TIMEDS
LDA TOG ;Time to decrement move timer?
BMI FNMVLP ;Not yet
DEC MOVTIM ;Yes. Ready for next move?
BNE FNMVLP ;Not yet
KWCHK
LDA MOVTYP ;Has KIM moved
LSR ;to either
CMP #$30 ;6,7, or 8
KWLINK
BPL KIMWIN ;Yes. KIM won
LDA PTO ;Has person moved
CMP #$03 ;to 0,1,or 2?
BMI PERWIN ;Yes. Person won.
;Try to match current board with stored model
LDY #$60 ;(#models - 1)3 = 323 = 96
MDLCHK
LDX BDMDL,Y
CPX DBD ;First column match?
BNE NXBD ;No, try next board model
LDX BDMDL+1,Y ;Yes, does
CPX DBD+1 ;second column match?
BNE NXBD ;No, try next board mode
LDX BDMDL+2,Y ;Yes, does
CPX DBD+2 ;third columh match?
BEQ GOTMDL ;Yes, found model. Go get move,
NXBD
DEY ;Point to
DEY ;next board model
DEY
BPL MDLCHK ;and keep comparing,
BMI PWMSG ;No models found1 have KIM concede the game
;Pick one of the remaining moves for this position
GOTMDL
LDA TIMER ;Use the timer to
AND #$03 ;arbitrarily select
TAX ;move o, 1, or 2
BEQ POK ;(This code picks #2
DEX ;half the time.)
POK
LDA #$02 ;lnititialize the counter for
STA TMP ;how many moves to try (3)
MVSLLP
STX TMP1 ;Temporary move number
MVLP1
LDA #$2D ;(
was LDA ADMVTB in original listing )
CLC
ADC TMP1 ;Set ADL of pointer to pick
STA POINTER ;up this move.
LDA (POINTER),Y
BNE GOTMOV ;Got a valid move -- use it!
DEC TMP
BMI PERWIN ;No moves left; KIM resigns,
DEC TMP1 ;Try next move
BPL MVLP1 ;in the set, (May try
LDX #$02 ;in order 2,1,0; 1,0,2;
BPL MVSLLP ;or 0,2,1)
PERWIN
LDY BDNDX ;Person has won. ************
CLC ;Compute the ADL
LDA #$2D ;(
was LDA ADMVTB in original listing ***)
ADC MOVNO ;of KIM's
STA POINTER ;last move. (POINTER+1 = 0)
LDA #$00 ;Wipe out the last
STA (POINTER),Y ;move KIM made,
PWMSG
LDA #PWAD ;Get address of "person won"
BPL STAD ;message
KIMWIN
LDA #KWAD ;Get "KIM won" msg address.
STAD
STA MPOINT ;Point to message address (ADL)
;Display en-of-game-message
LDY #$05
FILWIN
LDA (MPOINT),Y ;Store the six-letter
STA WINDO,Y ;message in the window.
DEY
BPL FILWIN
INC GAMNUM ;Increment game number.
JMP LITEST ;Show msg and wait for GO
;Make KIM's chosen move
GOTMOV
STA MOVTYP ;Save move for later checks,
STY BDNDX ;save board pointer.
LDX TMP1 ;Pick up
STX MOVNO ;move# (=0,1, or 2)
PHA ;Save 2 copies of move type
PHA
LSR
LSR
LSR
LSR
TAX ;Place "to" move in X
PLA
AND #$0F ;Extract and save
STA FROM ;"from" move
LDY #$03 ;Indicate KIM move being made
PLA ;Is upper half-byte of...
LSR
CMP #$30 ;move a 6,7, or 8?
BMI NOKWIN ;No, KIM hasn't won
JMP TMINIT ;Yes. Show winning move
NOKWIN
LDA #$00 ;Indicate it's person's
JMP MAKMOV ;move, and make KIM's
;Subroutine to test for legal move
;Call with move in A
;Returns with X = $FF if illegal move
; X = move if legal
.DB $00, $00
LEGMOV
CMP #$09 ;Is move 0 to 8?
BCS MOVFNG ;No, illegal
TAX
LDA EBD,X ;Extract player indicator from
ROR ;board: 1 player, 3 KIM
ROR
BPL TOCHK ;Nobody here, but OK if "to"
LDA FROM ;Is this a "from• move?
BPL PTOMOV ;No. Go see if legal "to"
BCS MOVFNG ;Yes, but KIM's here! Bad
MOVOK
TXA ;Return, Legal move was made
RTS ;(or found possible)
PTOMOV
TXA ;Place "to• move in A
BCC MOVFNG ;Person here! Can't capture!
ASL ;KIM here. A capture. Can
ASL ;only be one of 8 possible
ASL
ASL
ORA FROM ;moves, Format "T0:FROM"
LDY #$07 ;and test against
CAPCHK
CMP CAPSET,Y ;each possibility.
BEQ MOVOK ;Found it! Move is OK,
DEY
BPL CAPCHK
MOVFNG
LDX #$FF ;Move illegal, Set indicator
RTS ;(Second of two return points
NOCAP
TXA ;If here, not capture, C=O,
ADC #$03 ;Is move + 3 = FROM?
CMP FROM
BNE MOVFNG ;No, Illegal move.
BEQ MOVOK
TOCHK
LDY FROM ;Space here. "To" move?
BMI MOVFNG ;No, Illegal move,
BPL NOCAP ;Yes, See if valid move.
;Set of all possible "capture" moves by person
;packed in "TO;FROM" format
CAPSET
.DB $13, $04, $24, $15, $46, $37, $57, $48

"Check that start address <= end address" is considering only the high bytes

Something is fishy with the "Check that start address <= end address" code, which appears 5 times in JMON. The trouble is that either the BEQ or the BNE must be taken (the Z flag has to be either 0 or 1!), leaving no way to reach the "LDA SL" and the 3 lines after it.

; Check that start address <= end address
    LDA SH
    CMP EH
    BCC @okay1
    BEQ @okay1
    BNE @invalid1
    LDA SL
    CMP EL
    BCC @okay1
    BEQ @okay1
@invalid1:
    LDX #<InvalidRange
    LDY #>InvalidRange
    JSR PrintString
    RTS

I believe the solution is to remove the (first) BEQ @okay1, because it's when the high bytes are equal that it must consider the low bytes.

If this were packaged into a subroutine for the 5 callers, it looks like it could save around 100 bytes. (For example, return CLC if everything is OK; otherwise print the error string and return with SEC, to allow JSR RequireStartNotAfterEnd + BCS BailOut.)

A1 BASIC relocation

The A1 BASIC as it is will not assemble and standalone if you try to relocate the code. There are hard coded references to the pages used in the code and in certain tables. It will work (and largely use the relocated code for things at times) if there is an still an image of A1B at $E000. To make it truly stand alone, the following changes are needed.

Line 96, change to the origination address (to be safe and keep thing easy, I keep this at a multiple of $2000).

Line 200, the LDX #$ED needs to load the second page of the token table is located. The code will check if you are looking for a token greater than $50, it will the page further down in the code. (The tokens are parsed downward from the highest memory address which contains information of the lowest number token.)

Line 761, the LDA #$76 is followed by an ROL (effectively doubling it), so this is actually a pointer to page $EC. This is why I believe that you need to stick to even pages as origins (and would, for extra safety, stick with multiples of $2000). If you want to relocate to $8000, you need to change line 761 to LDA #$46. For relocation to $A000, it become LDA #$56.

Lines 1520 through 1544 contain a table of the high-byte of the addresses of functions in the verb table. All of the addresses in the $E0 thru $EF would need to changed to reflect the address things are relocated to. (For example, the first $E8 would need to become $88 to move the code to $8000. The $FF values seem to be markers that don't actually point to an address, so they can remain unchanged.)

By sticking to multiples of $2000, you can just do a search and replace for something like find '$E' and replace with '$8' in the tables. If you move it to some other type of page boundary, there would, at a minimum, be a lot more math involved.

With these changes and patches to the I/O routines, I was able to get this running on a PAL-1/KIM-1 at $8000 (in RAM) and $A000 (in ROM).

I wrote two short Python program to help automate it (on my GitHub page in the A1B repository), but actually modifying the source to automatically calculate the values that need to be changed would be a better approach if someone is going to be doing much relocation.

Even with needing this tweak, I never would have gotten A1B running without your source code. Thanks!

Typo in the Cassette Load and Save section of KIM-1 Quick Reference

The 1st instructions in both the Save and Load sections specify to store value $00 in $00F1 which resets the Decimal mode flag. This is correct however it is to ensure that the CPU is in BINARY mode. The comments incorrectly state it is to ensure the CPU is in Decimal mode.

cc65 apple1 target ?

Hi,

I noticed that in one of your Makefiles you are using cc65 to build for apple1, specifically in https://github.com/jefftranter/6502/tree/master/c/adventure1 however cc65 on my system errors with:

cl65: No such target system: 'apple1'

Are you using a modified/patched cc65 or the Makefile is wrong ? (I checked the documentation of cc65 and it seems they do not have a backend for apple1)

Thanks,
Jean

JMON info.s can corrupt top of memory code

In the info.s module of JMON, the code tests memory byte by byte starting at an address stored and maintained at $0000.

The code doing the testing tries to protect itself from having the test walk through it by skipping over the page (or pages) where the top-of-memory search code are:

        LDA TOP+1           ; High byte of page
        CMP #>FindTopOfRAM  ; Same page as this code?
        BEQ @Skip
        CMP #>FindTopOfRAMEnd ; Same page as this code (code could cross two pages)
        BEQ @Skip
        BNE @NotUs
@Skip:
        INC TOP+1           ; Skip over this page when testing

@NotUs:

        LDA TOP+1           ; Did we reach LIMIT? (high byte)
        CMP #>LIMIT
        BNE @Loop           ; If not, keep looping
        LDA TOP             ; Did we reach LIMIT? (low byte)
        CMP #<LIMIT
        BNE @Loop           ; If not, keep looping

If this code actually crosses two pages, the test on the second page does not take place. For example, if the code is on Page X and Page Y, the first compare will determine it is on Page X, increment it (so it now points to Page Y), and then jump back to @Notus and continue testing.

If the code crosses two pages, it seems like it will always only skip only the first. (And if the code is all on one page, the test is redundant but that doesn't cause any issue.)

It is a bit of a bandaid, but what I did was change the code to this:

        LDA TOP+1           ; High byte of page
        CMP #>FindTopOfRAM  ; Same page as this code?
        BEQ @Skip
        BNE @NotUs
@Skip:
        INC TOP+1           ; Skip over this page when testing
        INC TOP+1

I only test for the first page (Page X in my example) and then I increment not once but twice, so I always skip both the page where the code begins and the page following that.

If this code were towards the top of memory, it might need a more elegant fix (maybe do the comparison to the page where the code ends minus 1 so you always skip the end of the code and the page that precedes it if needed).

I was encountering "hangs" of the test before the change, but it crosses two pages and runs fine now.

Constants errors in wozfp.s

I'm yet another developer implementing the Steve Wozniak FP routines printed in Dr Dobb's Journal 1976.

However, also as a mathematician, I was checking the FP constants in the code and I noticed some errors.

In the text file that I was basing my work on (http://www.6502.org/source/floats/wozfp1.txt) I tried to calculate by hand the constants and found that several of them are wrong.

I found a copy of the original print at https://archive.org/details/dr_dobbs_journal_vol_01/page/n209/mode/2up

It looks like the digits were read incorrectly, as they are close but not equal to the original print

image

Text: R22 = 80 5A 02 7A
Orig: R22 = 80 5A 82 7A

These are easily checked, the value is 2^(x80- high byte) * (lower 3 bytes) / 2^22
5A027A = 1.4064012
5A827A = 1.4142136

Similarly for A1:
Text: A1 = 80 52 80 40
Orig: A1 = 80 52 B0 40

Again, very similar, but the text 8 was actually a B
Changing the expected value of A1 from 1.2920074 down to 1.289077759

So a patch would be:

R22:   .byte $80, $5A, $82, $7A ; 1.4142136 SQRT(2)

LE2:   .byte $7F, $58, $B9, $0C ; 0.69314718 LOG BASE E OF 2

A1:    .byte $80, $52, $B0, 40 ; 1.2920074

iNfo command crash in FindTopOfRAM

JMON is great! I ran it for the first time tonight.

On my Replica 1, JMON 1.01 crashes in the iNfo command while trying to determine how much RAM I have. (It stored a $00 into the code that was running, and then it hit the BRK where a CMP should be, 6 lines below @loop.)

I see the problem -- in this code, LDA TOP is getting the low byte of the address...it wants to do LDA TOP+1 instead.

;  Are we testing in the range of this code (i.e. the same 256 byte
;  page)? If so, need to skip over it because otherwise the memory
;  test will collide with the code being executed when writing to it.
    LDA TOP             ; High byte of page
    CMP #>FindTopOfRAM  ; Same page as this code?

That still leaves a bit of fragility: If the code shifts around such that FindTopOfRAM straddles two 256-byte pages, the protection could still fail. It could use a 2nd label at the end of the critical section (just after the STA for "Write original data back"?), and skip the page if TOP+1 matches either one.

(I am tempted to suggest a few micro-optimizations, but that's really another topic. For example, just before the above code, it could save 7 bytes by doing INC TOP, BNE skip, INC TOP+1 instead of the more general-purpose 16-bit addition.)

Tiny Basic internal doc?

I found a 6502 version of Tiny Basic...it's in your repo! 😄
Anyway, I grabbed the code and modified it to assemble using ACME (not hard!), and modified it so it has both TOPMEM and BOTTOM memory range. then integrated it with my text mode screen manager (console style) plus a machine monitor derived from WozMon (of Apple I). I had to relocate the zero pages used by these programs to accommodate Tiny Basic interpreter. I originally had used $20-$3F zero pages, but I saw explicit uses of $23, etc (when modifying the code to use TOPMEM/BOTTOM boundaries), so I relocated them to $40-$5F range. But when running the interpreter, I noticed the text rendering got corrupted somehow, and I then looked more closely into the code. I don't see any $4x and $5x. I think the interpreter has an internal parameter stack located in zero page that somehow hit the memory range. But the source code is so incredibly cryptic to figure out!!!
I am thinking about reverse engineering it and adding the document to that...though it would be quite some work. And I'm willing to submit the updates to your copy if you like.
Let me know what you think or say about all that. Thanks in advance!
P.S. Having more (meaningful) symbols would be helpful, plus more info re: internal working would be helpful in porting that interpreter to other 6502 platforms.
P.S.S. I don't want to clone the entire 6502 repo just to push changes to one file...but I don't see how... ☹️

JMON srecord end address issue

JMON allows creation of Moto S record dumps. The current source will not do complete dumps for some specified ranges.

Specifying either $2000-$201F or $2000-$2020 will both dump up to $201F and stop.

Specifying $2000-$22FF will dump $2000-$21FF while specifying $2000-$2300 will dump $2000-$22FF.

Part of the issue seems to be that each record contains bytesPerLine number of bytes. This means that the count can increment past the specified end address prior to checking. Because of this, doing the comparison as a pair of 8-bit compares instead of a full 16-bit magnitude comparison can cause problems.

The pointer to the next address to be dumped is also incremented prior to checking if we are at the end, so the proper test is for 'less than or equal to' instead of just 'less than'.

The current code at line 1925 in jmon.s is:

        lda     ADDR+1          ; if address < endAddress, go back and continue
        cmp     EH
        bmi     writes1
        lda     ADDR
        cmp     EL
        bmi     writes1

I have replaced this with the following:

        lda     ADDR+1          ; if address <= endAddress, go back and continue
        cmp     EH
        bne     @tstaddr
        lda     ADDR
        cmp     EL
@tstaddr:
        bcc     writes1
        beq     writes1

This still dumps in blocks of bytesPerLine but does catch the equal comparison so that something like $2000-$2100 will end up dumping to $211F (which is 15 bytes long instead of ending 1 byte short at $20FF as previously happened).

It is possible to detect instruction fetch on 6809E

I'm planning to build a version of this analyzer to use with the 6809E, which has some differences from the 6809. Among them, it is possible to detect the beginning of instruction fetch by snooping the LIC (Last Instruction Cycle) signal (pin 38 of the 6809E).

Quoting "MC6809-MC6809E 8-Bit Microprocessor Programming Manual [M6809PM/AD]", section [1.11.4]:

1.11.4 LAST INSTRUCTION CYCLE (LIC) (MC6809E).

This output goes high during the last cycle of every instruction and its high-to-low transition indicates that the first byte of an opcode will be latched at the end of the present bus cycle.

I'm opening this issue just to make a note of it.

Copy routines to handle overwrite are reversed

In lines 554 through 562, there is logic that decides whether to call @Okup or @okayDown to handle a copy. This is designed to handle situations where the source and destination overlap.

The routine selected is actually backwards (@okayUp is called when @okayDown should be and visa versa). Pure speculation, but this may be because the intent of the routine names is easy to confuse.

@okayUp starts with the bottom of the Source address and copies to the Destination address by counting upward (by incrementing) the Source and Destination address as it goes. The confusing part (to me anyway, and it took me a while to figure out what was going on) is that this routine is appropriate when the Source address is above the Destination address (in other words, you are copying 'down' from a higher block of memory to a lower block).

In the current code, the call to @okayUp is made when the opposite is true--when the Source address is BELOW the Destination address. Or, put another way, when you are copying "up" in memory.

@okayDown calculates the size of the transfer and then starts copying from the top of the Source block to the top of the Destination block, counting downward (by decrementing). This will prevent overwriting the source when you are copying "up" from one block of memory to a block "higher" in memory.

I did copies such as C 0200 02FF 0280 and C 0300 03FF 0280 when testing and debugging. Unless you are copying a range that actually overlaps, either routine will work fine.

My code eventually was:

@okay1:
  LDA SH
  CMP DH
  BCC @okayDown             ; copy up
  BNE @okayUp               ; copy down
  LDA SL
  CMP DL
  BCC @okayDown
  BCS @okayUp

Possible issue in Apple ][ system monitor mini-assembler

In the Apple ][ system monitor port, there are numerous conditional assembly sections for porting to the Apple I, mostly to handle the different hardware. However, I noticed that some of these conditionals may not be working properly (at least, on the hardware I have running the port of the monitor) in the mini-assembler. The first is at at line 136. Here, L6 is called instead of INSDS2, and I am unsure why a different subroutine is needed on Apple I hardware vs. any other 6502 hardware with regards to processing the mnemonic entered from the console. L0 is also called in INSDS1 if APPLE is defined and it's unclear why. In fact, with APPLE1 defined, I'm unable to get the mini-assembler to function properly with some mnemonics compared to the unmodified (Apple II) mini-assembler code, which works fine on my hardware. For example, if APPLE1 is defined, LDA and STA do not get mapped correctly to opcodes by the mini-assembler:

* F666G
!300: LDA #8A
0300-   A7          ???
! STA 88
0301-   17          ???

A7 and 17 are not the correct opcodes for LDA immediate nor STA zero-page, and the mini-assembler is thus confused by the operands. Again the official code (without APPLE1 defined) correctly assembles these commands. Was there something special on the Apple I replica that needed different INSDS1 and INSDS2 routines?

Unless I am missing something, there is also some extraneous code in the mini-assembler conditionally assembled with APPLE1 defined on lines 266-261, which occur before MINIASM, which I do not think ever gets called.

I gather the Apple I port of the monitor was originally done by someone else, so I understand you may not have direct rationale for these changes. Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.