6502.org Forum  Projects  Code  Resources  Tools  Forum
It is currently Wed Oct 01, 2014 10:11 am

All times are UTC




Post new topic Reply to topic  [ 36 posts ]  Go to page Previous  1, 2, 3  Next
Author Message
PostPosted: Fri Jul 13, 2012 5:21 pm 
Offline

Joined: Tue Jul 10, 2012 10:42 pm
Posts: 7
The amount of help and good will I am seeing here is beyond my wildest expectations.

@Miles: Thanks for this extensive post, I have a much better understanding of how the soft switches are working (this explains those "HIRESon " MACROs and this is probably the way the disk drive was piloted as well) and memory bank (I was unable to understand how Prince Of Persia could take 128KB runtime, as per the Prince Of Persia documentation: http://jordanmechner.com/wp-content/uploads/1989/10/popsource009.pdf page4) this is making much more sense now. I will have to find where in 0x00 page is the bank switching routine. I don't think POP is running in double high res, seems to be "normal" high resolution.

@teamtempest: Your explanation makes a lot of sense. In a time where there were no "include declaration.h" directive this dummy section is just a way to make the assembler award of the routines address in other .S via MACROs definition to inter-module communication can occur. The "DS" directive Merlin documentation (http://apple2.org.za/gswv/a2zine/Docs/MerlinManual.txt) did mention what your just re-explained but I was not familiar with "object code pointer" to fully understand it.

I have a much better understanding of the code right now. I think the cross-compilation track is the best one. To write a virtual machine is a lot of work and this wheel should not be re-invented. I tried cc65 assembler and it compiled fine on MacOS X, the Merlin 8/16 directive are not recognized (org, * comments), I also tried ATASM and the parsing did not go well either. I am going to try to sed all that into something and hopefully find equivalent to .org for those assembler. It is probably the safest road (and the least fun but whatever) to adapt the entry instead of writing an assembler myself...


Top
 Profile  
 
PostPosted: Fri Jul 13, 2012 11:01 pm 
Offline

Joined: Tue Jun 26, 2012 6:18 pm
Posts: 22
Hi Fabien!

fabiensanglard wrote:
I don't think POP is running in double high res, seems to be "normal" high resolution.
Yes, only the credits are shown in double hires (560x192 pixels, 16 colours). The game itself uses standard hires (280x192 pixels, 6 colours).

fabiensanglard wrote:
I will have to find where in 0x00 page is the bank switching routine.
Oops, sorry but that was meant to be an example of how one might do it. In fact there are many different ways how to accomplish this task. You could also place a routine at $400. Since the softswitches $c000 and $c001 (80 column store = window at $400..$7ff) override the other softswitches the processor can safely access $400..$7ff of the main ram while you flip around the rest of $200..$bfff at the same time. Now file 'MASTER.S' says at the beginning
Code:
org = $f880
 lst off
*-------------------------------
*
*  M  A  S  T  E  R
*
*  (3.5" version)
*
*  Sits in main l.c.
*
*-------------------------------

This means that this part of the program is put at the very end of the language card in the main memory on the motherboard. This is a safe place for switching $200..$bfff in and out, and this is exactly what POP does.

Well, for a better support it might be a good idea if you could tell us whether you are familiar with any 6502 based home computer system like the C64, Atari XL, BBC Micro etc. It might be easier to explain things if we can find some common ground. For example, if you are familiar with the Commodore 1541 floppy disk drive then explaining the AppleII disk drive is rather simple.

Well, here is a list of things I recommend to do (and which you have probably done already :) ):

- Download the game as disk images (*.dsk). I know of two versions, one working with two drives (my personal choice) and another which comes with an additional boot disk. Note: both versions need three disks to store the whole game. Page 4 you mentioned of popsource009.pdf states that the total disk space is about 252.5K. A single AppleII floppy disk will contain only 140K. So you will need at least 2 disks for your final program.

- Get yourself an AppleII emulator. Look for one that will allow you to save the current state of the VM as well as reloading it. This way you cannot only cheat during the game (naughty, naughty! :) ) but study your program again and again until you find out what's going wrong. Of course, the emulator should come with a debugger..

- Play the game. Just to get a feel for it. It's fun.

- Additional material about the AppleII you may find useful:
Watch out for the "AppleIIe Reference Manual" as well as "Inside the IIe". These books probably cover all you need to know about the AppleIIe. And, of course, you can always ask.

Now the tricky bit:
As teamtempest said: the source files of POP were not assembled in one go but separately. This was the usual approach in those days. I think I once read somewhere that it took Andrew Braybrook, author of the famous C64 game 'Uridium', about half an hour(!) to assemble the source file for his game. Then he would have to look for bugs, start the editor, load the source file, make some corrections, and start the whole process again. No wonder why a great amount of development then was done using a pencil and a sheet of paper...
What's more: since the whole game will take up as much as 252.5K you cannot just create one single executable program. As a matter of fact, there is not even something you could call an executable file. These things did/do not exist on the AppleII. All you have is a bootable floppy disk image. Of course, there were several disk operating systems like DOS3.3, the successor ProDOS and ApplePascal (= UCSD Pascal), but they all came with their own file system and all of them had to be loaded from disk first. There is no DOS stored in the ROM of the AppleII. The old DOS3.3 was loaded during the boot process into $9600..$bfff. ProDOS, more advanced, would load itself into the language card just like the ApplePascal system. Games, on the other hand, would use every single byte of the memory which usually meant to throw away the file system and load the sectors directly from disk bypassing the need for any directory or file allocation table etc. POP works the same way. There is no file system on the disk. Data and program are stored in specific sectors and loaded via the RWTS. Take a look at the following code:
Code:
   lda   #POPside1
   sta   BBundID

   lda   #2
   sta   track
   jsr   rw18
   db   RdGrp.Inc
   hex   e0,e1,e2,e3,e4,e5,e6,e7,e8
   hex   e9,ea,eb,ec,ed,00,00,00,00

First, the program will tell the RWTS from which disk to load (as there are two disks). Second, POP tells the RWTS that it wants to load from track #2. Then it calls the RWTS (named rw18 here which means 'read-write-18 sectors' indicating a special disk layout at GCR level). The following bytes are parameters. The routine rw18 will pop the return address and use this as a pointer to the parameter list. The first byte is the rwts command: read a group of sectors. In this case the command is followed by a list of addresses (high byte only) which correspond to the sectors on the disk: load the first sector to address $e000, load the second sector to address $e100 ... . The NULL-byte 00 means: don't load this sector. The list always contains 18 addresses since the (special) POP track also contains 18 sectors. This is a problem, as mentioned before, because standard disk images (*.dsk) will only allow 16 sectors per track.
After the routine rw18 has finished reading, it will push back the return address incremented by the total number of parameter list bytes (here: 19) and jump back to the program.
What does this mean for you?
1) You cannot just assemble the source files and expect them to run. Instead you must place the object code inside a disk image and load it from disk via your own RWTS.
2) Your assembler must support two important pseudo instructions: OBJ and SAVE (can be named differently)
While ORG will allow you to assemble a source file for a specific address, OBJ will actually write the generated object code to this address. Note: the addresses of ORG and OBJ can not only but must be different! SAVE will allow you to store some part of the virtual memory of the assembler in a file. For example:
SAVE "POP disk image 1.dsk", $0, $22fff
This will store the content of the virtual memory $0..$22fff into a file "POP disk image 1.dsk". You have to use this instruction at least twice to create two disk images. This is the easiest and fastest way to put your program onto the disk. If your assembler does not support instructions like these: throw it away and get another one. The following is an actual example:

Code:
;----------------------------------------
;   boot sector
;
;   this boot program will load
;   sectors 1..15 to addresses $900..$17ff
;
;----------------------------------------

;   look here: the code will be assembled to be used at address $800
;   but it will be written at the very beginning of the virtual memory
      org   $0800
      obj   $00000            ;   address on DOS-disk ==> track #0, sector #0

boot:
      hex   01            ;   load one sector


; reset 6502

      sei
      cld
      ldx   #$ff
      txs


; reset softswitches

      sta   $c000            ;   disable 80col store
      sta   $c002            ;   read main 47.5
      sta   $c004            ;   write main 47.5
      sta   $c006            ;   enable slot $c100
      sta   $c008            ;   read main ZP+LC
      sta   $c00c            ;   display 40col
      sta   $c00e            ;   disable altcharset
      bit   $c05f            ;   annunciator #3 on
      bit   $c051            ;   text
      bit   $c052            ;   no mixed
      bit   $c054            ;   page 1
      bit   $c056            ;   lores


; clear text screen

      lda   #32 + $80
      inx
?0:      sta   $400, x
      sta   $500, x
      sta   $600, x
      sta   $700, x
      inx
      bne   ?0


; load basic system

      lda   #$60            ;   patch RTS
      sta   boot + 1
      lda   $2b            ;   slot
      tax
      lsr
      lsr
      lsr
      lsr
      ora   #$c0
      sta   ?11 + 2            ;   patch JSR instruction
?10:      ldy   #14            ;   load 15 sectors
      lda   .boot_sector, y
      sta   $3d            ;   sector
      tya
      clc
      adc   #9
      sta   $27            ;   address high
?11:      jsr   $ff5c            ;   read sector

      dec   ?10 + 1            ;   dec number of sectors
      bpl   ?10



; clear memory

      ldx   #0
      txa
?20:      sta   $0, x
      sta   $100, x
      sta   $200, x
      sta   $300, x
      inx
      bne   ?20

      sta   $c050            ;   switch on lores


; fill screen with magenta pixels to show we are here..

      lda   #$11            ;   colour = magenta
?30:      sta   $400, x
      sta   $500, x
      sta   $600, x
      sta   $700, x
      inx
      bne   ?30

.endless:   jmp   .endless         ;   example ends here


;----------------------------------------

.boot_sector:   hex   0d0b09070503010e0c0a080604020f


      even   256            ;   fill rest of sector with 0


;----------------------------------------
;   RWTS
;----------------------------------------

; here you will usually find the RWTS

      hex   0101010101010101      ;   just to indicate first sector

      org   $0a00            ;   will be loaded at address $a00
      obj   $00200            ;   but is the second sector on the disk
      hex   0202020202020202      ;   just to indicate second sector

      org   $0b00            ;   ...
      obj   $00300
      hex   0303030303030303

      org   $0c00
      obj   $00400
      hex   0404040404040404

      org   $0d00
      obj   $00500
      hex   0505050505050505

      org   $0e00
      obj   $00600
      hex   0606060606060606

      org   $0f00
      obj   $00700
      hex   0707070707070707

      org   $1000
      obj   $00800
      hex   0808080808080808

      org   $1100
      obj   $00900
      hex   0909090909090909

      org   $1200
      obj   $00a00
      hex   0a0a0a0a0a0a0a0a

      org   $1300
      obj   $00b00
      hex   0b0b0b0b0b0b0b0b

      org   $1400
      obj   $00c00
      hex   0c0c0c0c0c0c0c0c

      org   $1500
      obj   $00d00
      hex   0d0d0d0d0d0d0d0d

      org   $1600
      obj   $00e00
      hex   0e0e0e0e0e0e0e0e

      org   $1700
      obj   $00f00
      hex   0f0f0f0f0f0f0f0f


; end of track #0


      sav   "test.dsk", 0, $22fff      ;   save the virtual memory as a disk image (140kb)

This example will load the whole track #0 at $800..$17ff with the first sector (boot sector) being loaded by the autostart ROM and the rest using the boot rom of the floppy disk drive. Note: this is just one way of doing it. There are lots. Unfortunately, the RWTS of POP is not included in the source files. And you cannot use the calls to rw18 since you do not have disk images that work with 18 sectors.
To sum up (again, sorry for being repetitive):
If you want to assemble an executable (= bootable) disk image, it's good to have an assembler that will offer pseudo instructions which will allow easy creation of a disk image. In addition, you definitely need a proper RWTS to load the program and the data from disk. Otherwise your program will not work. To achieve this, however, you must determine where to put the RWTS in memory (address and length) first. I'm afraid there are a few steps to go before you can even see the credits on the screen. But it's manageable. :)

Cheers
Miles


Top
 Profile  
 
PostPosted: Sat Jul 14, 2012 3:59 am 
Offline

Joined: Sat Dec 13, 2003 3:37 pm
Posts: 271
Well, one can say that development has changed a bit over the years, hasn't it. :)


Top
 Profile  
 
PostPosted: Thu Jul 19, 2012 10:05 pm 
Offline

Joined: Tue Jul 10, 2012 10:42 pm
Posts: 7
The two books recommended ("AppleIIe Reference Manual" as well as "Inside the IIe") were very useful. Since they were very old, I was unable to find them anywhere: I had to use pdf and fedex kinko:

Image

But I now have a much better understanding of the softswitches. The bank switching system is an horrible mess but whatever.

I also took the time to read the Making of Prince of Prince of Persia (http://jordanmechner.com/ebook/) :

Image

That gave me a good idea of the development machine (page 37: Pro-Dos, Merlin assembler and SCSI Hard-Drive).

In terms of build process I see no mention of OBJECT or SAVE in the source code so I wonder if this was really done this way. There are a few things that I cannot figure out because I never used Merlin:

1. The ".ORG" directive put the code at a certain location in object code. But there is not operating system, no loader and no filesystem: How does the code end up at the right memory location ?

2. Reading the code further (BOOT.S: https://github.com/jmechner/Prince-of-Persia-Apple-II/blob/master/01%20POP%20Source/Source/BOOT.S) I can see three booting stages that load each other. But I was unable to read in the documentation how the first stage gets into memory. Does the Apple ROM read the first 256 byte of track0,sector0 of the disk when it boots ? If so where does it place them ?

The source code of RTWS18 is actually provided (https://github.com/jmechner/Prince-of-Persia-Apple-II/tree/master/02%20POP%20Disk%20Routines/RW1835).

I am still wondering if an important piece of the build toolchain is missing in Github since the full binary was likely assembled on the SCSI disk and then a builder would chop things in 18 sectors. At this point the content of the floppy disc is essentially mashed potatoes that only the POP proprietary loader can load at the right location. It seems the GitHub source code features the runtime loader but not the "choper"....

Trivia: I also found the footage used for rotoscoping where you can see mechner's brother and the lady playing the princess: http://www.youtube.com/watch?v=gC3WEwSJoHs


Top
 Profile  
 
PostPosted: Fri Jul 20, 2012 1:19 am 
Offline

Joined: Sun Nov 08, 2009 1:56 am
Posts: 247
Location: Minnesota
Quote:
1. The ".ORG" directive put the code at a certain location in object code. But there is not operating system, no loader and no filesystem: How does the code end up at the right memory location ?


"ORG" sets the assembler's internal program counter to a specific value. It does not "put code" anywhere. The program counter is updated by assembling processor instructions (by the size of the instruction) and certain pseudo instructions. The value of the program counter is used for such things as assigning label addresses and calculating relative branch offsets.

What that means is that if the assembled code is then loaded to the same address specified by the "ORG", it will execute correctly at that address. How loading happens is in general not an assembler's direct concern or responsibility, but that of an operating system. However some assemblers will add "hidden" code or data not specified in the source file to the object file in order to assist the operating system. For that to work the assembler must have some knowledge of the target system, of course.


Top
 Profile  
 
PostPosted: Fri Jul 20, 2012 1:24 am 
Offline

Joined: Tue Jun 26, 2012 6:18 pm
Posts: 22
Hi Fabien!
fabiensanglard wrote:
But I now have a much better understanding of the softswitches. The bank switching system is an horrible mess but whatever.
Yes, indeed it is. :) But you get used to it after a while.
fabiensanglard wrote:
That gave me a good idea of the development machine (page 37: Pro-Dos, Merlin assembler and SCSI Hard-Drive).
It is as whartung said:
whartung wrote:
Well, one can say that development has changed a bit over the years, hasn't it.
My advice: Don't attempt to imitate that development.
fabiensanglard wrote:
In terms of build process I see no mention of OBJECT or SAVE in the source code so I wonder if this was really done this way.
No, it wasn't. In those days all source files were assembled separately which would give you several object code files you would have to store on the disk manually. There was an extra tool that would help you storing files (code or data) on a disk, but still this is a tedious task. Trust me, you don't want to do that. Everytime you change the code even so slightly you would have to assemble the corresponding part and then somehow write it back to the image. Of course, you would have to program your own tool first, since you can't use the original tool. Well, even if you could do that, it would mean much nerv-racking fiddling with an emulator.. Don't do it. That's why I've recommended a cross assembler. Only that will give you (just like this sentence) in one go two complete disk images as an output ready to be fed to an emulator directly for testing without much ado. (Got it :) ?) Don't waste your time with assembling all the code files independently. Just put them all into one big source file. As an example, when I assemble the code for the game 'Elite' (AppleII version) it will take just a few seconds on my PC to create a full bootable disk image. And this will also include a complete assembly listing for checking purposes.
fabiensanglard wrote:
There are a few things that I cannot figure out because I never used Merlin:
1. The ".ORG" directive put the code at a certain location in object code. But there is not operating system, no loader and no filesystem: How does the code end up at the right memory location ?
As I mentioned before, the loader is not included in the source file because it was written by another party (Roland Gustafsson). There are only calls to the loader ("jsr rw18"). I'm afraid, you will have to add your own loader (= RWTS).
fabiensanglard wrote:
2. Reading the code further (BOOT.S: https://github.com/jmechner/Prince-of-Persia-Apple-II/blob/master/01%20POP%20Source/Source/BOOT.S) I can see three booting stages that load each other. But I was unable to read in the documentation how the first stage gets into memory. Does the Apple ROM read the first 256 byte of track0,sector0 of the disk when it boots ? If so where does it place them ?
On reset the so-called autostart rom of the AppleII will scan the slot roms ($c100..$c7ff) for roms of a disk drive. There will normally be a disk drive slot rom located at addresses $c600..$c6ff (= slot #6). It will then jump directly to that rom. The rom will now move the head of the disk drive to a defined position (which is track 0) and attempt to load sector 0 of track 0 hoping that there is a disk in the drive. If there is none, the Apple//e will wait forever with the disk motor spinning in the drive. The Apple//c will stop the motor after a while and display an error message. If there is a disk in the drive, however, the rom will always load the first sector of the disk (track 0, sector 0) known as the 'boot sector' at addresses $800..$8ff. After it has done so, you find the number of sectors to be loaded from $800 on at address $800 (first byte). This number is usually 1 (= just load the boot sector). Then the slot rom will jump to address $801. At this address there is a little program that will continue loading the basic disk operating system (RWTS) with the help of the disk slot rom to wherever it wants to. The RWTS is needed since the little program inside the slot rom is only able to move the head in one direction (towards track 0) and also cannot write to a disk, not to mention things like formatting a disk etc. The code I added last time is just that: a boot sector code that will load the RWTS into memory. If you can assemble this little code, create a disk image out of it and successfully boot it in an emulator that would be a major step forward.
fabiensanglard wrote:
The source code of RTWS18 is actually provided.
Nope, the header says
Code:
* Unidisk 3.5 interface for
* 18 sector read/write routine
and that's what it is: an interface for making calls to the actual RWTS for 3.5" disks. Now most Apple//e emulators will not support 3.5" disk drive emulation, only 5.25". For this you will need to do all the reading from disk yourself, which means: switch on the disk motor, move the disk drive's head, read the GCR bytes, decode them, store them where you want them, and finally switch off the motor. Piece of cake. ;)
fabiensanglard wrote:
I am still wondering if an important piece of the build toolchain is missing in Github since the full binary was likely assembled on the SCSI disk and then a builder would chop things in 18 sectors. At this point the content of the floppy disc is essentially mashed potatoes that only the POP proprietary loader can load at the right location. It seems the GitHub source code features the runtime loader but not the "choper"....
I suggest to forget about the original tool chain. It won't help you anyway. You would have to use an Apple//gs with an old hard disk drive and Merlin to assemble the code and.. Please don't. Even with a fast Apple //gs emulator this would be a real PITA. And don't forget, please: if your aim is to make the source code available for other users as well you will have to establish a build process on a modern computer (Mac, Windows, Linux). Using ancient software in the tool chain will not help, I'm afraid.
fabiensanglard wrote:
Trivia: I also found the footage used for rotoscoping where you can see mechner's brother and the lady playing the princess:
:)

Cheers
Miles


Top
 Profile  
 
PostPosted: Fri Jul 20, 2012 3:31 am 
Offline

Joined: Sat Dec 13, 2003 3:37 pm
Posts: 271
Miles J. wrote:
No, it wasn't. In those days all source files were assembled separately which would give you several object code files you would have to store on the disk manually. There was an extra tool that would help you storing files (code or data) on a disk, but still this is a tedious task. Trust me, you don't want to do that. Everytime you change the code even so slightly you would have to assemble the corresponding part and then somehow write it back to the image. Of course, you would have to program your own tool first, since you can't use the original tool. Well, even if you could do that, it would mean much nerv-racking fiddling with an emulator.. Don't do it. That's why I've recommended a cross assembler. Only that will give you (just like this sentence) in one go two complete disk images as an output ready to be fed to an emulator directly for testing without much ado. (Got it :) ?) Don't waste your time with assembling all the code files independently. Just put them all into one big source file. As an example, when I assemble the code for the game 'Elite' (AppleII version) it will take just a few seconds on my PC to create a full bootable disk image. And this will also include a complete assembly listing for checking purposes.


I have not looked at the code in any detail.

But there was mention that the IIe had 128k of RAM, and that the RAM was banked in.

In PoP is the banked RAM solely for images and assets or is there code in them as well?

I mention this because of the talk of a custom tool to put the code on the disk. This is a classic example of where they might have several blocks of code, all .ORG to the same starting address, but meant to be overlaid in to the RAM banks. In this case, you may well not be able to assemble all of the code in one go, even with a cross assembler. It may complain about two sets of code overlapping (I know mine does, but mine is stupid :) ). If the cross assembler had a reasonably sophisticated linker tool chain, that is aware of overlays, then perhaps. Back In the Day, overlay linker and compiler tools were a big deal, especially on the PC. Whether those tools made their way to the Apple, and Merlin specifically, I can't say.

But it's a possible consideration to keep in mind while trying to resurrect PoP.


Top
 Profile  
 
PostPosted: Fri Jul 20, 2012 9:12 am 
Offline

Joined: Tue Jun 26, 2012 6:18 pm
Posts: 22
whartung wrote:
In PoP is the banked RAM solely for images and assets or is there code in them as well?
Code as well.
whartung wrote:
I mention this because of the talk of a custom tool to put the code on the disk. This is a classic example of where they might have several blocks of code, all .ORG to the same starting address, but meant to be overlaid in to the RAM banks. In this case, you may well not be able to assemble all of the code in one go, even with a cross assembler. It may complain about two sets of code overlapping (I know mine does, but mine is stupid :) ).
Well, IMHO it shouldn't complain about it. I would even consider it essential for an assembler to generate different parts of the code using the same ORG address. Imagine you want to write a set of drivers but only one of them will finally be loaded into ram after detecting the right hardware. How will you do that without the ability to write different versions of the code for the same address?
whartung wrote:
If the cross assembler had a reasonably sophisticated linker tool chain, that is aware of overlays, then perhaps. Back In the Day, overlay linker and compiler tools were a big deal, especially on the PC. Whether those tools made their way to the Apple, and Merlin specifically, I can't say.
I doubt it. Besides you don't need a linker etc to create a bootable disk image of PoP. What you need is an assembler which basically allows you to do the following:
1) All code/data generated first go into some virtual ram (inside the assembler) where they are buffered.
2) You can specify exactly where they are buffered by using the OBJ opcode.
3) You can use the ORG opcode to generate code suitable for any given address.
4) You can also load data (e.g. shapes or pictures) into this virtual memory with instructions like .incbin or .load.
5) Finally, one or more SAVE instructions will store specified areas of the virtual memory into a file(s).
For example: PoP needs two disk images. The first disk image will start at "address" $0000 inside the virtual buffer. The second disk image will start at address $30000. With OBJ you now tell the assembler where it will put your code/data into the disk image.
Another example (fast loader for the C64):
Code:
;----------------------------------------
;   track #18, sector #3
;
;   fast loader
;
;----------------------------------------

; >> assemble for address $300 inside the 1541 floppy disk drive <<
      org   $300
; >> put this code into track #18, sector #3 of the disk image <<
      obj   disk.objaddr + $16800

;----------------------------------------
;   main loop
;----------------------------------------

.main:

;   wait for command

      lda   $1c00            ;   LED off
      and   #$f7
      sta   $1c00
      lda   #$ee
      sta   $1c0c
      sta   .motor_flag         ;   motor flag (= on)

      lda   #$04
      sta   .value

      lda   #$08
      sta   $1800
      ...

So it's the assembler that will do the job of the tools and produce a complete disk image. No linker necessary. Straight forward, easy to use and fast. Well, at least it worked for me... :)
Cheers
Miles


Top
 Profile  
 
PostPosted: Mon Feb 11, 2013 5:46 pm 
Offline

Joined: Mon Dec 23, 2002 8:47 pm
Posts: 70
The Disk ][ firmware reads track 0 sector 0 off the disk at $0800, and jumps to $0801 with carry set. (Actually you can make it load up to 16 sectors by setting the first byte of the sector; in practice that's uncommon.)


Top
 Profile  
 
PostPosted: Tue Feb 26, 2013 3:07 pm 
Offline

Joined: Tue Feb 26, 2013 2:59 pm
Posts: 27
Just wanted to thank Miles in particular for posting up such great info!

There is some activity on this here: http://www.atariage.com/forums/topic/15 ... e__st__450


Top
 Profile  
 
PostPosted: Sat Mar 09, 2013 3:12 pm 
Offline

Joined: Tue Feb 26, 2013 2:59 pm
Posts: 27
Not sure Miles is still here, but maybe.

I've been working on this and really want to know which assembler was used with the examples above. Or, if they are conceptual, assemblers that have those features.

Anyone?

Thanks.


Top
 Profile  
 
PostPosted: Sat Mar 16, 2013 4:53 pm 
Offline

Joined: Tue Feb 26, 2013 2:59 pm
Posts: 27
Bump:

Does anyone here know of an assembler that contains the features Miles mentioned above?

In particular, I'm looking for the ability to assemble some code for say, $2000 and place it at a different memory address, say $30000.

Should I ask this somewhere else? I think I will start another thread, just to see whether or not this one is too long or convoluted.


Top
 Profile  
 
PostPosted: Sat Mar 16, 2013 7:09 pm 
Offline

Joined: Sun Nov 08, 2009 1:56 am
Posts: 247
Location: Minnesota
Quote:
In particular, I'm looking for the ability to assemble some code for say, $2000 and place it at a different memory address, say $30000.


Mmm, in general you can assemble code for any address you like, and you can also load it to any address you like. But if the two addresses don't match, the code won't run.

Perhaps you're asking about a two-part program? It's not uncommon to have a "stub header" attached to "the real program". The stub header has only one job: move the real program to its proper address after the pair has been loaded together. Stub headers are used to make things easier in some way - for example, to make the combined pair load as easily as any BASIC program, even though the real program is in assembly language and won't run in the BASIC program space.

If that's your goal then it's pretty easy with most assemblers. Skipping the code itself, the skeleton looks like this:

Code:
  .org BASIC_LOAD_ADDRESS
  ...
  (a "fake" BASIC line to transfer control via SYS or CALL)
  ...
   (code to transfer the following "real program" to its execution address)
  ...
  .org REAL_ADDRESS
  ...
  ("real" code)
  ...
  .end
 


It's also possible to have a portion of a program "resident", one of whose tasks is to manage non-resident "overlay" portions. The UCSD Pascal system for Apple worked like this. With modern cross-assemblers it's easy enough to do something like this:

Code:
  .org RESIDENT_ADDRESS
  ...(code)
  .org OVERLAY_ADDRESS
  ...(code)
  .org OVERLAY_ADDRESS
  ...(code)
  .org OVERLAY_ADDRESS
  ...(code)
  .end


The problem is that the whole shebang is probably larger than will fit in available target memory at once (if it does, why are you using overlays anyway?). It does all fit on mass storage, though (one or more floppy disks, perhaps). So somehow the resident code must be able to find and load on demand whatever piece of overlay code it's interested in at the moment.

One way to do that is if the code exists as one big file, there is a way to point to any byte of it, and the resident knows the offset and length of every overlay. Then it's just a matter of pointing to the start of any overlay and reading.

Another way would be to save each individual overlay as a separate file (if the total code size is too large for one floppy disk, say). That is easiest if the assembler has some way to do that. The Merlin assembler has one, IIRC. The HXA assembler can save individual segments as separate files, so for that one the resident and each overlay would be described to it as a separate segment.

Hmm, I seem to have forgotten the possibilty of loading the whole shebang into auxiliary memory of some sort and loading the overlays from there (speedier, once the whole shebang is loaded). But that's just the first variation, where the resident knows the offset and length in auxiliary memory of each overlay. The Wizardry games from Sir Tech often did this sort of thing.


Top
 Profile  
 
PostPosted: Sun Mar 17, 2013 1:17 am 
Offline

Joined: Tue Feb 26, 2013 2:59 pm
Posts: 27
Are the examples Miles provided fictional?


Top
 Profile  
 
PostPosted: Sun Mar 17, 2013 9:12 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 3162
Location: England
In Miles' example, the obj directive gives a disk address, not a memory address. The only way an object address could be outside 64k and a memory address is if you're running on a machine with more than 64k and the assembler knows about the banking arrangements. (Also note that it would be a native assembler, not a cross assembler)

See also your other thread: Big Memory Model assembler?

Cheers
Ed


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 36 posts ]  Go to page Previous  1, 2, 3  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron