A machine monitor, or machine language monitor, is a tool to examine memory, assemble and disassemble program code, and debug programs a the machine language level.
I don't think a ton of keywords are needed. Here's the list I can think off off the top of my head:
M [start] [length] - dump memory.
W or > addr data [data] ... write memory. M prints the format that > uses as input, making modifying memory simple.
A or . [addr] operator - assemble starting at the specified address.
F addr [length] data [data] - fill memory with byte or bytes specified.
C start1 start2 length - compare memory
T addr1 addr2 length - transfer (copy) memory. If addr2 is inside of addr1+length range, then copy operates backward so no data is lost
S, L, V start len filename - save, load, verify.
R - display registers in format A=xx X=xx, etc.
; - Update registers. Like >, the R command prefaces the register dump with ; to make updates simple.
@ - get disk status or issue disk command. eg: @CD /GAMES changes to GAMES directory on root of hard drive.
I used JMON as the starting point for a monitor for my homebrew 6502 projects. I included the assembler and disassembler--I usually have 32K of ROM (minus a page or 1K for memory mapped I/O), so even with a BASIC interpreter space typically isn't an issue. I also like to have a fairly robust monitor. I ended up with the following command set:
A - Assemble <address>
B - BASIC C - Copy <start> <end> <destination>
D - Disassemble <start>
F - Fill <start> <end> <value>
G - Go <address>
H - HEX Dump <start> <end> (note: dumps in Intel .hex format)
K - Checksum <start> <end>
L - Load Memory L <address> <data>...
M - Dump Memory <start>
N - Info (note: provides info such as processor type, memory size, I/O options, etc.)
O - Options (all upper case, force processor type, etc.)
P - Breakpoint P <n or ?> <address>
R - Registers
S - Search <start> <end> <data>...
= - Math = <address> +/- <address>
. - Trace
^ - Clr Screen
; - HEX Load (note: load Intel .hex format which can be generated by using H command)
? - Help
This has worked well for systems with 64K of address space. I'd have to think some about what would feel intuitive when it came to the 65816's address space.
Another logical starting point would be the WDC W65C256's embedded monitor. I believe the source code is out there. The '256 is basically a '816 core with some I/O and the built in ROM. The manual has the monitor command summary on page 82:
http://www.westerndesigncenter.com/Wdc/documentation/265monrom.pdf
Obviously to use that code wholesale would require the okay from WDC.
I like the ability to dump and load either Intel hex (in my monitor) or Moto S (in the WDC monitors) files.
Just my two cents worth, but happy to help where I can. Looks like an exciting project.
Thanks,
Jim
ok.
Again, there's a kernel thread. That's the place to discuss kernel design. Yes, the monitor depends on the kernel, but they're still two different things, and if we don't keep the conversations in the right places, it'll get confusing later.
It's talked about because the ML Monitor would be calling these Jump tables in order to save to disk your ML program. What good is an ML Monitor if you can't save to storage? That is why I was talking about it. It isn't completely isolated silos. ML Monitor (such as JamMON) and Kernal will need to be in sync. Keep in mind C64 programs using kernal routines are going to be looking for a Jump table at bank $00 as they don't know anything about bank switching. They have to be modified before they can work.
They will normally JSR to the routine. We will have to then build short routines in the same bank that does the following:
JSL the kernal table where you located it and then we have to RTS so traditional C64 programs returns back to their location in the same memory bank. These programs must also reside in the same bank whether we are in bank $00 or even bank $01 or something. So when we emulate the C64 environment, we have to reside the C64 in a memory bank. However, things can still get mucky given how all these C64 demo coders, hackers, etc. did call kinds of sh-t that would likely break anyway because the 65c816 lacks the illegal opcodes and such.
I suppose we could somewhat break from tradition if we try not to really emulate the C64 because without the illegal opcodes, numerous C64 games, demos, etc. will break or fail to function properly. I can get JamMON to work regardless of where you have jump tables but it'll likely be called to using JSL instruction to invoke the kernal jump table that you set up.
Again, the 65816 does not support a vectored, Far JSR. You can vector a JSR in the same 64K bank as the program counter; that's it.
As such, there's no need for vector tables in Page 0, and so the jump tables will be at the end of the kernel ROM at the top of the system's address space. Each entry will be $22 (JSL) followed by the 3 byte long address of the ROM entry point for the routine.
If you want to discuss this any further, please take it to a new thread. This thread is about the machine monitor, not about kernel design.
Thanks.
Commodore was consistent with use of jump tables. Commodore may have still found ways to keep Kernal on the first 64KB memory zone and still be able to access their programs from the 64KB memory zone.
If anything, we should keep in mind what Commodore would have done and they have managed to do this consistently for all these models.
Basically, a double hop approach. A "short" hop prior to a "Long" hop. Of course, anyone making a C-256 specific program could technically directly jump to the routine for absolute most efficient per clock cycle. The second most efficient is using the 24-bit jump vector but for legacy programs.... they use the 16-bit jump vector to jump to the 24-bit vector.
For those reading, 16-bit refers to the address bus not the data bus for legacy software written for 6502. The 24 bit is referring to the full 65c816 memory addressing. This is for clarification for Stef and others. A rewrite of BASIC like a structured BASIC that Tom is looking for could use the 24-bit jump vector or directly addressing the routines of the kernal but Tom, you may still be advised to use the 24 bit Jump vector but some legacy stuff may still call the Kernal routines in the same locations as they were on PET/CBM, Vic-20, C64, Plus/4, C16,...
The C128 is where they got things more complicated in the C128 mode but NONETHELESS, they were able to still implement Standard Commodore Jump Table with additional C-128 Kernal jump routines preceding the standard Jump Table.
https://ia801002.us.archive.org/10/items/Compute_s_Mapping_the_Commodore_128/Compute_s_Mapping_the_Commodore_128.pdf
It's there.
Even the VERY LAST Commodore 8 bit machine that was being developed.... the C65 they still had the standard jump table in their standard location as with the previous models plus some new stuff.
http://www.zimmers.net/cbmpics/cbm/c65/c65manual.txt
As of 1991... of course. C65 had a memory addressing of up to 1 MEGABYTE as it had a 20 BIT ADDRESS BUS in the CSG4510.
Here's the beautiful thing about the 65186. Because you can switch the Program Bank Register to any 8-bit value you want, you can build your own jump table, or even a whole kernel, and place it at any 64K bank you want. There's no need to burn those values into ROM, since you can just include them with your program.
Indeed. However, the purpose for Jump Tables being fairly consistent is because if I was calling upon the kernal routine for "Command Serial Bus TALK" or other Kernal routines from the JUMP VECTOR table, the initial Jump Vector point to call either in BASIC or ML would be the same location from one computer model to the next. This is how several Commodore programs was able to function with no modifications in some cases. BASIC actually uses the JUMP VECTOR table.
https://ia801007.us.archive.org/20/items/Compute_s_Mapping_the_Commodore_64/Compute_s_Mapping_the_Commodore_64.pdf
page 257 of the pdf (printed page 243)
If I wanted to plot (read/set) position of cursor on screen, I have the same call point for the routine even though the routine itself maybe in different locations and of different sizes. As noted in this book (Mapping the Commodore 64), it says clearly:
"Kernal Jump Table
The following jump table is provided by Commodore in an effort to
maintain stable entry points for key I/O routines. Each three-byte
table entry consists of 6510 JMP instruction and the actual address
of the routine in the ROM. Although the actual address of the rou-
tine may vary from machine to machine, or change in later versions
of the Kernal, these addresses will stay where they are. By jumping
to the entry point provided by this table, rather than directly into the
ROM, you insure your programs against changes in the Operating
System. In addition, this jump table may help you write programs
that will function on more than one Commodore machine. The 15
table entries from 65472-65514 ($FFC0-$FFEA) are the same for all
Commodore machines, from the earliest PET on.
As an additional aid, some of these routines are also vectored
through the table which starts at 788 ($314). Since this table is in
RAM, you can change those vectors to point to your own routines
which support additional I/O devices. Programs that use the jump
table entry points to the I/O routines will be able to use these I/O
devices without problem.
The following table will give the entry point, routine name,
RAM vector if any, its current address, and brief summary of its
function."
This is why programs written using the table could jump to another jump table with 24 bit addressing to exact location of routines in the 24 bit memory space.
What I'm hoping is that someone will step up and write a compatibility toolkit that basically acts as a translation layer, allowing people to more easily port C64 programs over to the Foenix by basically adding a library to their existing code. The library could do the appropriate work of switching to 8-bit mode, copying data between the local 64K address space and the Foenix's 24-bit addresses, and mapping I/O between the KERNAL routines older programs expect and whatever we devise for the Foenix.
That will be challenging for a huge number of reasons I can enumerate but in cases some programs would work easier than others in the translation process. Programs using those jump tables (any program that used the BASIC's "DOS" commands and many C= 8 bit programs not using their own custom routines. Programs that will most easiest survive kernal changes are programs that don't use KERNAL at all or programs that used the jump vector table.
BASIC did not use the direct location of the routines. Jump vector table allowed something to be specified by Commodore because they had a team working on BASIC updates and a team that worked on the KERNAL and to maximize coordination, a jump vector table was employed so if Commodore developers changed the routines or reorganized the code in any way or form, it didn't cascade t to be modified in BASIC. It was an intelligent decision at the time. If KERNAL team modified the KERNAL, they didn't have to be change locations.
An option I propose is a double jump vector table approach. In which case, I point from one table to another table. Possibly, I could remove all Kernal stuff that can be relocated to another bank from the section $00E000 to $00FF80. Then insert the 24-bit (LONG) Jump Vector table(s) or (LONG) jump vectors where it would work. This an approach.
Of course, we could directly call the 24-bit Jump Vectors for C256 applications (and save a few cycles) but for legacy, we use the 16-bit jump vector table (traditional table) to jump to the 24 bit jump vectors which will then jump to the actual routines where they maybe located in memory.
Here's the beautiful thing about the 65186. Because you can switch the Program Bank Register to any 8-bit value you want, you can build your own jump table, or even a whole kernel, and place it at any 64K bank you want. There's no need to burn those values into ROM, since you can just include them with your program.
What I'm hoping is that someone will step up and write a compatibility toolkit that basically acts as a translation layer, allowing people to more easily port C64 programs over to the Foenix by basically adding a library to their existing code. The library could do the appropriate work of switching to 8-bit mode, copying data between the local 64K address space and the Foenix's 24-bit addresses, and mapping I/O between the KERNAL routines older programs expect and whatever we devise for the Foenix.
To be clear, there will be a 24-bit Foenix jump table, but it won't be in RAM. It will be in system ROM, at the very top of memory.
Yes, jump tables are in the works. I've been spending some time working on a list of routines and some general methodology for doing things. I wouldn't expect the Foenix's jump tables to match up with Commodore's, though. If nothing else, the 24-bit address space makes that impossible. Also, in looking at how Commodore handled certain APIs, I think we can do things better today - or at least simplify certain things. Part of that is because of the better CPU, part is due to having more RAM, but mostly I think we just understand computer science better today and would just not make some of the same choices.
If you like, since you'll need to get a Kernal together for Foenix, I'll work on getting Jammon initially ported with whatever modified Jump table but I would need a correlation between the one above listed from the C64 and that the Jump table you come up with. Once we have the functions lined up for the basic function and at least the ability to load and save to a 1541 disk drive and other similar Commodore serial bus devices made by third-party and hobbyist. From there we can evolve it.
I'll propose a JMP table in say bank $01xxxx because legacy hardware maybe hard mapped to $00D000 to $00DFFF. Modifying the table for full 24-bit addressing JMP tables would likely caused kernal to be over 8 KB and need 16KB ROM space at the least.
Actually, you should. Commodore jump tables should be $00FF81 to $00FFF3. Remember, the 65c816 operates in multiple addressing modes including 6502/65c02 style addressing modes. Put the extended features in bank $01.... say $01D000 to $01FFF3. Note the different addresses but there is no reason you can't put the basic routines to driving the Commodore serial bus, some of the traditional video modes and so forth as needed. You can use a table to jump to another table if you need to but these are for compatibility mode so you aren't throwing Jammon off too quickly and save time. With a 20 MHz or so CPU, double JMP won't be hard to do.
For example, you go to the Jump table at $00FF81 to $00FFF3 which are nothing but JMP $#### (16-bit addressing mode). That's okay. For example: The Jump Vector at $00FF81 [ $FF81 ], will do a JMP $FF5B in bank $00. That's okay. When calling these Jump table, bank register should be at $00. First instruction at $FF5B (or some other location in the first 64KB that you decide), should be a long JSR to the actual routines completed with an RTS if they are not going to be in the first 64KB bank.
You can most certainly make improvements but the basic Jump Vectors that I am talking about should not be messed with other than the actual JMP instructions they point to. Since they are only 64KB you can set aside a JSR jump vectors for 24-bit addressing that these JMP tables jump to as you may need.
JUMP (JMP) Vector Table
| $FF81/65409 Init Editor & Video Chips
| $FF84/65412 Init I/O Devices, Ports & Timers
| $FF87/65415 Init Ram & Buffers
| $FF8A/65418 Restore Vectors
| $FF8D/65421 Change Vectors For User
| $FF90/65424 Control OS Messages
| $FF93/65427 Send SA After Listen
| $FF96/65430 Send SA After Talk
| $FF99/65433 Set/Read System RAM Top
| $FF9C/65436 Set/Read System RAM Bottom
| $FF9F/65439 Scan Keyboard
| $FFA2/65442 Set Timeout In IEEE
| $FFA5/65445 Handshake Serial Byte In
| $FFA8/65448 Handshake Serial Byte Out
| $FFAB/65451 Command Serial Bus UNTALK
| $FFAE/65454 Command Serial Bus UNLISTEN
| $FFB1/65457 Command Serial Bus LISTEN
| $FFB4/65460 Command Serial Bus TALK
| $FFB7/65463 Read I/O Status Word
| $FFBA/65466 Set Logical File Parameters
| $FFBD/65469 Set Filename
| $FFC0/65472 Open Vector
| $FFC3/65475 Close Vector
| $FFC6/65478 Set Input
| $FFC9/65481 Set Output
| $FFCC/65484 Restore I/O Vector
| $FFCF/65487 Input Vector, chrin
| $FFD2/65490 Output Vector, chrout
| $FFD5/65493 Load RAM From Device
| $FFD8/65496 Save RAM To Device
| $FFDB/65499 Set Real-Time Clock
| $FFDE/65502 Read Real-Time Clock
| $FFE1/65505 Test-Stop Vector
| $FFE4/65508 Get From Keyboad
| $FFE7/65511 Close All Channels And Files
| $FFEA/65514 Increment Real-Time Clock
| $FFED/65517 Return Screen Organization
| $FFF0/65520 Read / Set Cursor X/Y Position
| $FFF3/65523 Return I/O Base Address
These JMP can point to say....
$C000-$CFFF or $A000-$BFFF because we can bank in BASIC on BANK $01 (on BANK $01A000-$01BFFF.... for example).
We can modify as needed.
Then replace:
$FE66/65126: Warm Start Basic
FE66: 20 15 FD JSR $FD15 ; Restore Kernal Vectors
FE69: 20 A3 FD JSR $FDA3 ; Initialise I/O
FE6C: 20 18 E5 JSR $E518 ; Initialize I/O
FE6F: 6C 02 A0 JMP ($A002) ; Restart Vectors
At some point, we replace this so we can point to BASIC on bank $01.
There is also using the other addressing modes to mask but any changes to the Jump vector MUST be documented and adjusted on Jammon but this should be exercised with care. These Jump Vectors are 3 BYTES. We can double vector if we must. We may modify zero page. Theoretically, we can move EVERYTHING to bank $01 and later and use 16 bit addressing for everything regarding the kernal and have the whole bank $00 as ZERO PAGE except legacy hardware that only maps to bank $00. But from our ML program using original JMP and JSR instruction addressing mode would be addressing in whatever is the current bank register value so we need to keep the bank register entact.
I'm not entirely opposed of changing the jump vectors but we need to document it and then employ the changes right away. I'll propose a set up and some modifications but we can bump up the KERNAL to say 16KB ROM instead of 8KB and BASIC can be tweaked.
I just really only need to add ONE byte to each JMP vector for a FULL 24-bit addressing. I would map the KERNAL $01D000 to $01FFFF.
Then we can use short addressing in Bank $01 to BASIC that could be located in $01A000-$01BFFF.
VIC-II and other I/O hardware for legacy hardware can be mapped to $00,D000-DFFF ($00D000-$00DFFF). Where as new hardware could be mapped to bank $02 and later banks.
These are some ideas.
Yes, jump tables are in the works. I've been spending some time working on a list of routines and some general methodology for doing things. I wouldn't expect the Foenix's jump tables to match up with Commodore's, though. If nothing else, the 24-bit address space makes that impossible. Also, in looking at how Commodore handled certain APIs, I think we can do things better today - or at least simplify certain things. Part of that is because of the better CPU, part is due to having more RAM, but mostly I think we just understand computer science better today and would just not make some of the same choices.
Jammon should be able to serve as a turnkey style monitor because at the basic level, it does all that as its basis built upon SuperMON which by the way influenced ML Monitors since its first release in 1980. Jim Butterfield was and still is one of if not the biggest name is Machine Language programming for the 6502 series even to the 65c816. Jammon would be a good turnkey because it is already updated to 65c816 instruction set and it is a decent code base to build from and a PD license is awesome. There will be some work involved but until we got a Kernel for Load and Saving to disk. In the meantime, like they did in the old days on minicomputers with a hex editor. You'll have to basically hard write the kernal accordingly. If we map a 6522 or borrow FPGA logic for a 6522 or 6526, we can get something going as long as it is mapped write so even your most stock kernals can mostly run. Remember that Commodore used jump table pointers so follow that model so you can point to those jump tables. These were helpful when Commodore made the different models. The Jump table were entry points that were fairly static and locations never changed between models. ( https://www.c64-wiki.com/wiki/Kernal ) Note the jump tables at $FF81-$FFF3. That were crucial for allowing changes in the Kernal subroutines between the Vic-20, C64, and other models without suddenly breaking everything. It started with the PET and every model kept them retained so they didn't move them so software that points to those jump tables will allow not break with changes in the actual subroutines and even the actual hardware location.
Don't F--- that part up and we can point to the jump tables to keep these in good order while the kernal is being modified. We can point to a second set on bank $01. So all we need to look to is bank $00 for the original jump table and place another set in $01 if we want to.
The wisdom of early Commodore programmers future proofed their kernal. Lets not screw that up and followed their wisdom. Commodore did that CONSISTENTLY (reasonably well) since the PET to the C65. Amiga was another platform altogether like the MS-DOS machines.
So Jammon looks promising (as discussed in the game development thread.)
http://www.ffd2.com/fridge/jammon/
I am not ready to start porting work on it yet, as we don't even have a basic set of kernel APIs defined yet, but I am going to take a closer look at this once we have basic I/O APIs defined. Initial development will probably happen on a PC, using the WDC assembler, so all we'll need at first is a simple Turnkey stile monitor (examine memory, alter memory, and Execute). As we flesh out the system APIs, then we can look at the monitor and a command interpreter.
Here are some resources found here: http://www.ffd2.com/fridge/
There are ML Monitors, assemblers, etc. Some of them for the SuperCPU (65c816 based CPU accelerator).
Just gonna drop this link here. Found a nice "Intro to 65816 for 6502 programmers" page here:
http://softpixel.com/~cwright/sianse/docs/65816NFO.HTM
That should be enough to get started on a basic machine monitor going, once some hardware specifications are nailed down.
Please note this monitor/disassembler/debugger: http://siz.hu/en/content/sizmon3