7 ms·
Prince Of Persia Code Review (2013)
- CamperBob2 8y agoORG directives were really just hints. There was no operating system and no linker/loader on Apple II: The developer had to "somehow" manage to transfer the instructions from floppy disc to the intended location. Well, no. .ORG directives had nothing to do with any of that. They were (and are) used to tell the assembler how to fix up absolute references such as JMPs, JSRs, and loads/stores to variables defined in the code. As he points out, when building complex programs on the Apple II, you had to keep track of where to load modules yourself, precisely because there was no metadata in the object file. Nothing prevented you from loading a module compiled at one ORG at a different address... well, nothing except the fact that it would probably crash.
- joezydeco 8y agoYou could write 6502 code to be completely relocatable, but at a cost of space and a more complex assembler.
- tinus_hn 8y agoThe 6502 can only do small +128/-127 bytes relative jumps so that would be pretty complex indeed.
- pvg 8y agoSelf-modifying code was not that unusual and that's what Apple's own DOS did to relocate itself.
- boomlinde 8y agoTypically you'd patch the relocatable routine before inserting it at the desired memory location, simply overwriting the location-dependent instructions like jsr and absolute jmp with new operands. This isn't very complex, especially if the relocator doesn't need to be position independent itself. There are some factors that can simplify relocation: only allow relocation to page boundaries (i.e. $xx00 addresses) and possibly keeping the routines shorter than a page. For example, here's a single page, page boundary constrained relocator for a routine with two patch points: ; x = page relocate_routine stx rel_sta+2 ; patch stx patch1+2 stx patch2+2 ldy #0 copy lda routine_template,y rel_sta: sta $0000,y iny bne copy rts ; some routine assembled for any origin $xx00 routine_template bne continue patch1 jmp done continue ... patch2 jsr print ... done rts print ... rts
- tinus_hn 8y agoIf the relocator is not position independent then the solution is not completely relocateble. I don’t even know how you would get access to the program counter without trashing some memory.
- boomlinde 8y agoNot completely relocatable, but in practice this means that you have some memory reserved at a specific point in memory for the relocator and the template. The relocator can be made position independent by using indirect stores. You never need direct access to the program counter for this, but it gets a bit more complex. You don't need to read the program counter directly for this, but I think the simplest way of doing that is the jsr instruction, which puts the PC (plus some fixed offset) on the stack. The idea is that instead of using a "template" and referring directly to that, you load the relocatable code where you want it, load that location in some zero page vector and in the relocator you do indirect+relative stores based off of that vector: lda page ; the page that the routine was loaded to sta $ff lda #0 sta $fe jsr relocate ; wherever you've loaded the relocator ... ; vector $fe-$ff = routine location, $fe must be 0 relocate lda $ff ; load the lsbyte of the offset of the first patch in the routine into y ; in reality, would be calculated at the point of assembling the routine template ldy #<2+patch1-routine_start sta ($fe),y ldy #<2+patch2-routine_start sta ($fe),y rts As you can see, the relocate routine is now completely position independent. The relocated routine has the same constraints (has to be loaded to the beginning of a page). We use the y register to load the offset within a page and $ff as the page counter. It's also not much more complex to write the relocator for routines spanning multiple pages, but it comes with a bunch more considerations that I think would take much more code to demonstrate (e.g. cross page jumps and calls).
- tinus_hn 8y agoThe problem is that the only way to read the program counter is through jsr or an interrupt and these both can’t do relative jumps. If you start with that information and you allow patching you can of course relocate the code on the fly, but I wouldn’t really call that position independent code generation by a compiler. It’s more like you’re implementing your own linker.
- boomlinde 8y agoI think that you are misinterpreting that statement. The .ORG directive is indeed somewhat of a hint to the assembler (or rather, obviously, a directive) telling it which memory location it should assemble the code for. It is a hint in the sense that it doesn't necessarily reflect the actual location of the code at run-time, because it is separate from linking.
- snvzz 8y agoWhile nice, it doesn't go very far, yet. It'd have been more interesting to link it once more complete.
- Narishma 8y agoIt's been at this incomplete state for 6 years.
- fabiensanglard 8y agoI lost interest. I don't think i will ever finish it :P!
- snvzz 8y agoDamn. What a tease.
- bredren 8y ago(2013)
- fabiensanglard 8y agoBoy, this makes me feel old.
- Moru 8y agoYou were also expecting 1989 as the year? :)
- StacyC 8y agoI had so much fun playing this in college on a Mac Plus in our little computer room (closet)!
- pierrebai 8y agoAbout the disk format: the Amiga native disk format was just one huge sector per track. That is how the Amiga fitted 880K on the same disk MS-DOS filled with 720K and MacOS 800K. One of the custom chip on the Amiga had hardware for teh track decoding. So the Amiga could read the disk while performing other operations, the data would come in via DMA (direct memopry access) of the co-processor. (MacOS used variable-speed, that is how it fitted more sectors on outer tracks and achieved 800K.)
- zepearl 8y agoI owned an Amiga 500 and at a certain point I bought for it a HDD (20 MBs, if I remember correctly) => then later I switched to an IBM-compatible (386sx with a HDD) and, subjectively, I thought that the HDD of the IBM-compatible was slower than the one I previously used on the Amiga => any HW reason why the Amiga-HDD might be faster than the IBM-HDD, or did I just imagine it?
- bluedino 8y agoAmiga was very likely a SCSI drive vs IDE
- puzzle 8y agoIt might have been a SCSI drive/controller, but it might have also been that you used FastFileSystem, which was pretty efficient. One of the HD manufacturers of the time, either Conner or Maxtor, was known to use Amiga 3000 machines to test their SCSI disks, because of the CPU/chipset/OS/FS combination. Not many systems were able to extract 90%+ of theoretical throughput like the A3000 could.
- zepearl 8y agoThx - it was just some sort of standard HDD for Amiga 500 - cannot remember anything specific about it... . Can it be that the Amiga 500 had in its case a place for a HDD? (I don't remember using external cases, but maybe I have forgotten...)
- dang 8y agoDiscussed at the time: https://news.ycombinator.com/item?id=5917888 https://news.ycombinator.com/item?id=5917888
- antirez 8y ago> the 6502 is a simple 16 bits processor I don't think ability to address 64k means the CPU is 16 bit. The 6502 is a very 8 bit processor AFAIK. The main registers are 8 bit, most operations work on 8 bit registers.
- royjacobs 8y agoI presume he's referring to the address space? It's a bit confusing, indeed.
- antirez 8y agoSorry you read the comment one second before I updated it, I clarified how AFAIK addressing 16 bits of memory does not make it a 16 bit processor.
- Drakim 8y agoIndeed, the Nintendo Entertainment System (NES) can also address 16 bits of memory and is one of the most famous "8 bit systems" around.
- vidarh 8y agoIn fact the NES uses a 6502-derived core (the Ricoh 2A03/2A07 CPUs contain a licensed 6502 core with some minor tweaks)
- royjacobs 8y agoRight :) I think when the Atari Jaguar was released they used the same kind of logic to market it as a 64-bit system since technically some part of it was using 64-bit processing, but the CPUs were still 32-bit. It's just nitpicking though, I thoroughly enjoy Fabien's writing and I can highly recommend the couple of books he's written about reverse engineering Id Software games. On HN people seem to confuse "hacking" with "growth hacking" a lot of times, and Fabien's writing is thankfully on the right side of that fence.